taesiri commited on
Commit
b4fe8a8
·
1 Parent(s): 28c1a75
Files changed (2) hide show
  1. templates/game_selection.html +25 -0
  2. templates/index.html +322 -0
templates/game_selection.html ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Select a Game</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ </head>
10
+
11
+ <body class="bg-gray-100">
12
+ <div class="container mx-auto px-4 py-8">
13
+ <h1 class="text-4xl font-bold mb-8">Select a Game</h1>
14
+ <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
15
+ {% for game in games %}
16
+ <a href="?game={{ game | urlencode }}"
17
+ class="bg-white shadow-md rounded-lg p-4 hover:shadow-lg transition-shadow duration-300">
18
+ <h2 class="text-xl font-semibold">{{ game }}</h2>
19
+ </a>
20
+ {% endfor %}
21
+ </div>
22
+ </div>
23
+ </body>
24
+
25
+ </html>
templates/index.html ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>{{ game }} - Glitch Image Preview</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <style>
10
+ .markdown-content p {
11
+ margin-bottom: 1em;
12
+ }
13
+
14
+ .markdown-content br {
15
+ display: block;
16
+ content: "";
17
+ margin-top: 0.5em;
18
+ }
19
+
20
+ .markdown-content pre {
21
+ background-color: #f4f4f4;
22
+ border: 1px solid #ddd;
23
+ border-left: 3px solid #f36d33;
24
+ color: #666;
25
+ page-break-inside: avoid;
26
+ font-family: monospace;
27
+ font-size: 15px;
28
+ line-height: 1.6;
29
+ margin-bottom: 1.6em;
30
+ max-width: 100%;
31
+ overflow: auto;
32
+ padding: 1em 1.5em;
33
+ display: block;
34
+ word-wrap: break-word;
35
+ }
36
+
37
+ .markdown-content code {
38
+ background-color: #f4f4f4;
39
+ border-radius: 3px;
40
+ color: #666;
41
+ font-family: monospace;
42
+ padding: 0.2em 0.4em;
43
+ }
44
+
45
+ .custom-tag-btn {
46
+ padding: 0.25rem 0.75rem;
47
+ border-radius: 9999px;
48
+ font-size: 0.875rem;
49
+ font-weight: 600;
50
+ color: white;
51
+ transition: all 0.2s;
52
+ }
53
+
54
+ .custom-tag-btn.active {
55
+ opacity: 1;
56
+ }
57
+
58
+ .custom-tag-btn.inactive {
59
+ opacity: 0.5;
60
+ }
61
+
62
+ .custom-tag-bug {
63
+ background-color: #EF4444;
64
+ }
65
+
66
+ .custom-tag-bug[data-tag="Does not contain a bug"] {
67
+ background-color: #10B981;
68
+ }
69
+
70
+ .custom-tag-analysis {
71
+ background-color: #3B82F6;
72
+ }
73
+
74
+ .custom-tag-issue {
75
+ background-color: #F59E0B;
76
+ }
77
+ </style>
78
+ </head>
79
+
80
+ <body class="bg-gray-100">
81
+ <div class="container mx-auto px-4 py-8">
82
+ <h1 class="text-4xl font-bold mb-8">{{ game }} - Glitch Image Preview</h1>
83
+
84
+ <div class="mb-8">
85
+ <a href="/" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mr-4">Back to Game
86
+ Selection</a>
87
+ <a href="?game={{ game | urlencode }}&view=list&page={{ page }}"
88
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mr-4">List View</a>
89
+ <a href="?game={{ game | urlencode }}&view=gallery&page=1"
90
+ class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">Gallery View</a>
91
+ </div>
92
+
93
+ {% if view == "list" %}
94
+ {% for result in results %}
95
+ <div
96
+ class="bg-white shadow-md rounded-lg p-6 mb-8 {% if result.highlight %}highlight border-4 border-blue-500{% endif %}">
97
+ <h2 class="text-2xl font-semibold mb-4">{{ result.title }}</h2>
98
+ <img src="/{{ result.local_image_file }}" alt="{{ result.title }}" class="w-full mb-4 rounded-lg">
99
+
100
+ <div class="mb-4">
101
+ <h3 class="font-semibold mb-2">Tags:</h3>
102
+ <div class="flex flex-col space-y-2" data-image-path="{{ result.local_image_file }}">
103
+ <div>
104
+ <h4 class="font-medium">Bug Tags:</h4>
105
+ <div class="flex flex-wrap gap-2">
106
+ {% for tag in BUG_TAGS %}
107
+ <button
108
+ class="custom-tag-btn custom-tag-bug {% if tag in result.tags.bug %}active{% else %}inactive{% endif %}"
109
+ data-tag="{{ tag }}" data-type="bug">{{ tag }}</button>
110
+ {% endfor %}
111
+ </div>
112
+ </div>
113
+ <div>
114
+ <h4 class="font-medium">Analysis Tags:</h4>
115
+ <div class="flex flex-wrap gap-2">
116
+ {% for tag in ANALYSIS_TAGS %}
117
+ <button
118
+ class="custom-tag-btn custom-tag-analysis {% if tag in result.tags.analysis %}active{% else %}inactive{% endif %}"
119
+ data-tag="{{ tag }}" data-type="analysis">{{ tag }}</button>
120
+ {% endfor %}
121
+ </div>
122
+ </div>
123
+ <div>
124
+ <h4 class="font-medium">Issue Tags:</h4>
125
+ <div class="flex flex-wrap gap-2">
126
+ {% for tag in ISSUE_TAGS %}
127
+ <button
128
+ class="custom-tag-btn custom-tag-issue {% if tag in result.tags.issue %}active{% else %}inactive{% endif %}"
129
+ data-tag="{{ tag }}" data-type="issue">{{ tag }}</button>
130
+ {% endfor %}
131
+ {% for tag in result.tags.issue %}
132
+ {% if tag not in ISSUE_TAGS %}
133
+ <button class="custom-tag-btn custom-tag-issue active" data-tag="{{ tag }}"
134
+ data-type="issue">{{ tag }}</button>
135
+ {% endif %}
136
+ {% endfor %}
137
+ </div>
138
+ <input type="text" class="new-tag-input mt-2 px-2 py-1 border rounded"
139
+ placeholder="Add new issue tag">
140
+ <button
141
+ class="add-tag-btn bg-purple-500 hover:bg-purple-700 text-white font-bold py-1 px-2 rounded ml-2">Add
142
+ Tag</button>
143
+ </div>
144
+ </div>
145
+ </div>
146
+
147
+ <h3 class="text-xl font-semibold mb-2">Extracted Content:</h3>
148
+ <div class="prose markdown-content" data-raw-content="{{ result.extracted_content_raw | escape }}">
149
+ {{ result.extracted_content_html | safe }}
150
+ </div>
151
+ </div>
152
+ {% endfor %}
153
+
154
+ <div class="flex justify-center items-center space-x-2 mt-8">
155
+ {% if page > 1 %}
156
+ <a href="?game={{ game | urlencode }}&page={{ page - 1 }}&view={{ view }}"
157
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Previous</a>
158
+ {% endif %}
159
+
160
+ {% for p in range(1, total_pages + 1) %}
161
+ {% if p == page %}
162
+ <span class="bg-gray-300 text-gray-700 font-bold py-2 px-4 rounded">{{ p }}</span>
163
+ {% else %}
164
+ <a href="?game={{ game | urlencode }}&page={{ p }}&view={{ view }}"
165
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">{{ p }}</a>
166
+ {% endif %}
167
+ {% endfor %}
168
+
169
+ {% if page < total_pages %} <a href="?game={{ game | urlencode }}&page={{ page + 1 }}&view={{ view }}"
170
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Next</a>
171
+ {% endif %}
172
+ </div>
173
+ {% else %}
174
+ <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
175
+ {% for result in all_results %}
176
+ <div class="relative">
177
+ <a href="?game={{ game | urlencode }}&view=list&page={{ ((loop.index0 // ITEMS_PER_PAGE) + 1) }}&highlight={{ result.local_image_file }}"
178
+ class="block">
179
+ <img src="/{{ result.local_image_file }}" alt="{{ result.title }}"
180
+ class="w-full h-40 object-cover rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300">
181
+ </a>
182
+ <div class="absolute bottom-0 left-0 right-0 p-2 bg-black bg-opacity-50 rounded-b-lg">
183
+ <div class="flex flex-wrap gap-1">
184
+ {% for tag_type in ['bug', 'analysis', 'issue'] %}
185
+ {% for tag in result.tags.get(tag_type, []) %}
186
+ <span class="text-xs px-1 py-0.5 rounded-full tag-{{ tag_type }}" data-tag="{{ tag }}">{{ tag
187
+ }}</span>
188
+ {% endfor %}
189
+ {% endfor %}
190
+ </div>
191
+ </div>
192
+ </div>
193
+ {% endfor %}
194
+ </div>
195
+ {% endif %}
196
+ </div>
197
+
198
+ <script>
199
+ document.addEventListener('DOMContentLoaded', function () {
200
+ const markdownContents = document.querySelectorAll('.markdown-content');
201
+ markdownContents.forEach(content => {
202
+ const rawContent = content.getAttribute('data-raw-content');
203
+ if (rawContent) {
204
+ const formattedContent = rawContent
205
+ .replace(/```(\w+)?\n([\s\S]*?)```/g, function (match, lang, code) {
206
+ return `<pre><code class="language-${lang || ''}">${code.trim()}</code></pre>`;
207
+ })
208
+ .replace(/\n\n/g, '</p><p>')
209
+ .replace(/\n/g, '<br>')
210
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
211
+ .replace(/\*(.*?)\*/g, '<em>$1</em>');
212
+ content.innerHTML = `<p>${formattedContent}</p>`;
213
+ }
214
+ });
215
+
216
+ // Update the tag functionality
217
+ document.querySelectorAll('.custom-tag-btn').forEach(btn => {
218
+ btn.addEventListener('click', function (event) {
219
+ event.preventDefault();
220
+ const imagePath = this.closest('[data-image-path]').dataset.imagePath;
221
+ const tag = this.dataset.tag;
222
+ const tagType = this.dataset.type;
223
+ const isActive = this.classList.contains('inactive');
224
+
225
+ fetch('/tag', {
226
+ method: 'POST',
227
+ headers: {
228
+ 'Content-Type': 'application/x-www-form-urlencoded',
229
+ },
230
+ body: `image_path=${encodeURIComponent(imagePath)}&tag=${encodeURIComponent(tag)}&active=${isActive}&tag_type=${tagType}`
231
+ }).then(response => response.json())
232
+ .then(data => {
233
+ if (data.status === 'success') {
234
+ updateTagsUI(this.closest('[data-image-path]'), data.tags);
235
+ } else {
236
+ console.error('Error updating tag:', data.message);
237
+ }
238
+ })
239
+ .catch(error => {
240
+ console.error('Error:', error);
241
+ });
242
+ });
243
+ });
244
+
245
+ function updateTagsUI(container, tags) {
246
+ Object.entries(tags).forEach(([tagType, tagList]) => {
247
+ container.querySelectorAll(`.custom-tag-btn.custom-tag-${tagType}`).forEach(btn => {
248
+ const shouldBeActive = tagList.includes(btn.dataset.tag);
249
+ if (shouldBeActive) {
250
+ btn.classList.remove('inactive');
251
+ btn.classList.add('active');
252
+ } else {
253
+ btn.classList.remove('active');
254
+ btn.classList.add('inactive');
255
+ }
256
+ });
257
+ });
258
+ }
259
+
260
+ // Update the add new tag functionality
261
+ document.querySelectorAll('.add-tag-btn').forEach(btn => {
262
+ btn.addEventListener('click', function () {
263
+ const newTagInput = this.previousElementSibling;
264
+ const newTag = newTagInput.value.trim();
265
+ const imagePath = this.closest('[data-image-path]').dataset.imagePath;
266
+ if (newTag) {
267
+ fetch('/add_tag', {
268
+ method: 'POST',
269
+ headers: {
270
+ 'Content-Type': 'application/x-www-form-urlencoded',
271
+ },
272
+ body: `tag=${encodeURIComponent(newTag)}&image_path=${encodeURIComponent(imagePath)}`
273
+ })
274
+ .then(response => response.json())
275
+ .then(data => {
276
+ if (data.status === 'success') {
277
+ const issueTagsContainer = this.closest('div').querySelector('.flex.flex-wrap.gap-2');
278
+ const newButton = document.createElement('button');
279
+ newButton.className = 'custom-tag-btn custom-tag-issue active';
280
+ newButton.dataset.tag = newTag;
281
+ newButton.dataset.type = 'issue';
282
+ newButton.textContent = newTag;
283
+ issueTagsContainer.appendChild(newButton);
284
+ newTagInput.value = '';
285
+
286
+ // Add click event listener to the new button
287
+ newButton.addEventListener('click', function () {
288
+ const imagePath = this.closest('[data-image-path]').dataset.imagePath;
289
+ const tag = this.dataset.tag;
290
+ const tagType = this.dataset.type;
291
+ const isActive = this.classList.contains('active');
292
+
293
+ fetch('/tag', {
294
+ method: 'POST',
295
+ headers: {
296
+ 'Content-Type': 'application/x-www-form-urlencoded',
297
+ },
298
+ body: `image_path=${encodeURIComponent(imagePath)}&tag=${encodeURIComponent(tag)}&active=${!isActive}&tag_type=${tagType}`
299
+ }).then(response => response.json())
300
+ .then(data => {
301
+ if (data.status === 'success') {
302
+ this.classList.toggle('active');
303
+ this.classList.toggle('inactive');
304
+ }
305
+ });
306
+ });
307
+ }
308
+ });
309
+ }
310
+ });
311
+ });
312
+
313
+ // Scroll to highlighted image
314
+ const highlightedImage = document.querySelector('.highlight');
315
+ if (highlightedImage) {
316
+ highlightedImage.scrollIntoView({ behavior: 'smooth', block: 'start' });
317
+ }
318
+ });
319
+ </script>
320
+ </body>
321
+
322
+ </html>