AdnanElAssadi commited on
Commit
255d500
·
verified ·
1 Parent(s): c24aa0c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -91
app.py CHANGED
@@ -32,9 +32,9 @@ def create_reranking_interface(task_data):
32
  html += f'''\
33
  <div class="sortable-item rank-bg-{rank}" data-doc-id="{idx}" data-rank="{rank}">
34
  <div class="rank-controls">
35
- <button class="rank-btn up-btn" {up_disabled} onclick="moveItemUp({rank})">▲</button>
36
  <div class="rank-badge">{rank}</div>
37
- <button class="rank-btn down-btn" {down_disabled} onclick="moveItemDown({rank})">▼</button>
38
  </div>
39
  <div class="doc-content">{escaped_doc}</div>
40
  </div>
@@ -152,60 +152,88 @@ def create_reranking_interface(task_data):
152
  js_code = """
153
  <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
154
  <script>
155
- // Function to move an item up in the ranking
156
- function moveItemUp(currentRank) {
 
157
  if (currentRank <= 1) return; // Already at the top
158
 
159
  const container = document.getElementById('sortable-container');
160
- if (!container) return;
 
 
 
161
 
162
- const items = container.querySelectorAll('.sortable-item');
163
- const itemsArray = Array.from(items);
164
 
165
- // Find the items to swap
166
- const currentItem = itemsArray.find(item => item.getAttribute('data-rank') == currentRank);
167
- const aboveItem = itemsArray.find(item => item.getAttribute('data-rank') == currentRank - 1);
168
 
169
- if (!currentItem || !aboveItem) return;
 
 
 
170
 
171
- // Swap the items
172
- aboveItem.parentNode.insertBefore(currentItem, aboveItem);
 
 
 
 
 
 
173
 
174
  // Update ranks
175
- updateRanksAfterMove();
176
- }
177
 
178
- // Function to move an item down in the ranking
179
- function moveItemDown(currentRank) {
 
180
  const container = document.getElementById('sortable-container');
181
- if (!container) return;
 
 
 
 
 
 
182
 
183
- const items = container.querySelectorAll('.sortable-item');
184
  if (currentRank >= items.length) return; // Already at the bottom
185
 
186
- const itemsArray = Array.from(items);
 
 
187
 
188
- // Find the items to swap
189
- const currentItem = itemsArray.find(item => item.getAttribute('data-rank') == currentRank);
190
- const belowItem = itemsArray.find(item => item.getAttribute('data-rank') == currentRank + 1);
 
191
 
192
- if (!currentItem || !belowItem) return;
193
 
194
- // Swap the items
195
- belowItem.parentNode.insertBefore(belowItem, currentItem);
196
 
197
  // Update ranks
198
- updateRanksAfterMove();
199
- }
200
 
201
- // Update rank numbers and classes after moving
202
- function updateRanksAfterMove() {
203
  const container = document.getElementById('sortable-container');
204
- if (!container) return;
 
 
 
205
 
206
- const items = container.querySelectorAll('.sortable-item');
207
  const orderInput = document.querySelector('#current-order textarea');
208
- if (!orderInput) return;
 
 
 
209
 
210
  const order = [];
211
  items.forEach((item, index) => {
@@ -217,7 +245,7 @@ def create_reranking_interface(task_data):
217
  if (rankBadge) rankBadge.textContent = rank;
218
 
219
  // Update item classes
220
- item.className = item.className.replace(/rank-bg-\d+/g, '').trim();
221
  item.classList.add(`rank-bg-${rank}`);
222
 
223
  // Update data attribute
@@ -246,50 +274,73 @@ def create_reranking_interface(task_data):
246
  order.push(docId);
247
  });
248
 
249
- // Update hidden input
 
250
  const newOrderValue = JSON.stringify(order);
251
- if (orderInput.value !== newOrderValue) {
252
- orderInput.value = newOrderValue;
253
- const event = new Event('input', { bubbles: true });
254
- orderInput.dispatchEvent(event);
255
- }
256
- }
257
 
258
  document.addEventListener('DOMContentLoaded', function() {
259
- function initializeSortable() {
260
- // Initialize event handlers for buttons
261
- updateRanksAfterMove();
262
-
263
- // Keep drag-and-drop as a fallback
264
  const container = document.getElementById('sortable-container');
265
  if (!container) {
266
- console.log('Container not found, retrying...');
267
- setTimeout(initializeSortable, 200);
268
  return;
269
  }
270
 
271
- if (typeof Sortable === 'undefined') {
272
- console.log('Sortable not loaded, retrying...');
273
- setTimeout(initializeSortable, 200);
274
- return;
275
- }
276
 
277
- if (container.sortableInstance) {
278
- return;
279
- }
280
 
281
- container.sortableInstance = new Sortable(container, {
282
- animation: 150,
283
- ghostClass: "sortable-ghost",
284
- onEnd: function() {
285
- updateRanksAfterMove();
286
- }
287
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
289
 
290
- // Initialize immediately and also set up a mutation observer
291
- initializeSortable();
292
 
 
293
  const targetNode = document.getElementById('sortable-list-container');
294
  if (targetNode) {
295
  const config = { childList: true, subtree: true };
@@ -297,7 +348,8 @@ def create_reranking_interface(task_data):
297
  for(const mutation of mutationsList) {
298
  if (mutation.type === 'childList') {
299
  if (document.getElementById('sortable-container')) {
300
- initializeSortable();
 
301
  }
302
  }
303
  }
@@ -310,41 +362,30 @@ def create_reranking_interface(task_data):
310
  .sortable-container {
311
  display: flex;
312
  flex-direction: column;
313
- gap: 8px;
314
  min-height: 200px;
315
- padding: 10px;
316
  background-color: #f8f9fa;
317
  border-radius: 8px;
318
  }
319
  .sortable-item {
320
- padding: 12px 15px;
321
  background-color: #fff;
322
  border: 1px solid #e0e0e0;
323
  border-radius: 6px;
324
- cursor: grab;
325
  display: flex;
326
  align-items: center;
327
  transition: all 0.2s ease;
328
- user-select: none;
329
  }
330
  .sortable-item:hover {
331
  background-color: #f8f9fa;
332
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
333
  }
334
- .sortable-ghost {
335
- background-color: #e3f2fd !important;
336
- border-style: dashed !important;
337
- opacity: 0.8;
338
- }
339
- .sortable-chosen {
340
- cursor: grabbing;
341
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
342
- }
343
  .rank-controls {
344
- display: flex;
345
  flex-direction: column;
346
  align-items: center;
347
- margin-right: 15px;
348
  }
349
  .rank-badge {
350
  display: flex;
@@ -356,25 +397,27 @@ def create_reranking_interface(task_data):
356
  background-color: #6c757d;
357
  color: white;
358
  font-weight: bold;
359
- margin: 4px 0;
360
  flex-shrink: 0;
361
  }
362
  .rank-btn {
 
 
363
  border: none;
364
- background: #f0f0f0;
365
  border-radius: 4px;
366
- width: 24px;
367
- height: 24px;
368
- font-size: 12px;
369
- line-height: 1;
370
  display: flex;
371
  align-items: center;
372
  justify-content: center;
373
- cursor: pointer;
374
- color: #333;
375
  }
376
  .rank-btn:hover:not([disabled]) {
377
- background: #e0e0e0;
 
 
 
378
  }
379
  .rank-btn:disabled {
380
  opacity: 0.5;
@@ -382,7 +425,7 @@ def create_reranking_interface(task_data):
382
  }
383
  .doc-content {
384
  flex: 1;
385
- line-height: 1.4;
386
  word-break: break-word;
387
  }
388
  .rank-bg-1 .rank-badge { background-color: #198754; }
 
32
  html += f'''\
33
  <div class="sortable-item rank-bg-{rank}" data-doc-id="{idx}" data-rank="{rank}">
34
  <div class="rank-controls">
35
+ <button type="button" class="rank-btn up-btn" {up_disabled} onclick="window.moveItemUp({rank})">▲</button>
36
  <div class="rank-badge">{rank}</div>
37
+ <button type="button" class="rank-btn down-btn" {down_disabled} onclick="window.moveItemDown({rank})">▼</button>
38
  </div>
39
  <div class="doc-content">{escaped_doc}</div>
40
  </div>
 
152
  js_code = """
153
  <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
154
  <script>
155
+ // Make the functions globally available
156
+ window.moveItemUp = function(currentRank) {
157
+ console.log('Moving item up:', currentRank);
158
  if (currentRank <= 1) return; // Already at the top
159
 
160
  const container = document.getElementById('sortable-container');
161
+ if (!container) {
162
+ console.error('Container not found');
163
+ return;
164
+ }
165
 
166
+ const items = Array.from(container.querySelectorAll('.sortable-item'));
167
+ console.log('Found items:', items.length);
168
 
169
+ // Find the items to swap by their data-rank attribute
170
+ const currentItem = items.find(item => parseInt(item.getAttribute('data-rank')) === currentRank);
171
+ const aboveItem = items.find(item => parseInt(item.getAttribute('data-rank')) === currentRank - 1);
172
 
173
+ if (!currentItem || !aboveItem) {
174
+ console.error('Items not found:', currentItem, aboveItem);
175
+ return;
176
+ }
177
 
178
+ console.log('Swapping items:', currentItem, aboveItem);
179
+
180
+ // Swap the items in the DOM
181
+ if (aboveItem.previousElementSibling) {
182
+ container.insertBefore(currentItem, aboveItem);
183
+ } else {
184
+ container.insertBefore(currentItem, container.firstChild);
185
+ }
186
 
187
  // Update ranks
188
+ window.updateRanksAfterMove();
189
+ };
190
 
191
+ window.moveItemDown = function(currentRank) {
192
+ console.log('Moving item down:', currentRank);
193
+
194
  const container = document.getElementById('sortable-container');
195
+ if (!container) {
196
+ console.error('Container not found');
197
+ return;
198
+ }
199
+
200
+ const items = Array.from(container.querySelectorAll('.sortable-item'));
201
+ console.log('Found items:', items.length);
202
 
 
203
  if (currentRank >= items.length) return; // Already at the bottom
204
 
205
+ // Find the items to swap by their data-rank attribute
206
+ const currentItem = items.find(item => parseInt(item.getAttribute('data-rank')) === currentRank);
207
+ const belowItem = items.find(item => parseInt(item.getAttribute('data-rank')) === currentRank + 1);
208
 
209
+ if (!currentItem || !belowItem) {
210
+ console.error('Items not found for moving down');
211
+ return;
212
+ }
213
 
214
+ console.log('Swapping items down:', currentItem, belowItem);
215
 
216
+ // Swap the items in the DOM - insert the current item after the below item
217
+ container.insertBefore(currentItem, belowItem.nextElementSibling);
218
 
219
  // Update ranks
220
+ window.updateRanksAfterMove();
221
+ };
222
 
223
+ window.updateRanksAfterMove = function() {
224
+ console.log('Updating ranks');
225
  const container = document.getElementById('sortable-container');
226
+ if (!container) {
227
+ console.error('Container not found for rank update');
228
+ return;
229
+ }
230
 
231
+ const items = Array.from(container.querySelectorAll('.sortable-item'));
232
  const orderInput = document.querySelector('#current-order textarea');
233
+ if (!orderInput) {
234
+ console.error('Order input not found');
235
+ return;
236
+ }
237
 
238
  const order = [];
239
  items.forEach((item, index) => {
 
245
  if (rankBadge) rankBadge.textContent = rank;
246
 
247
  // Update item classes
248
+ item.className = item.className.replace(/rank-bg-\\d+/g, '').trim();
249
  item.classList.add(`rank-bg-${rank}`);
250
 
251
  // Update data attribute
 
274
  order.push(docId);
275
  });
276
 
277
+ // Update hidden input with JSON
278
+ console.log('New order:', order);
279
  const newOrderValue = JSON.stringify(order);
280
+ orderInput.value = newOrderValue;
281
+
282
+ // Trigger input event
283
+ const event = new Event('input', { bubbles: true });
284
+ orderInput.dispatchEvent(event);
285
+ };
286
 
287
  document.addEventListener('DOMContentLoaded', function() {
288
+ console.log('DOM loaded, initializing ranking interface');
289
+
290
+ // Function to initialize the interface
291
+ function initializeRankingInterface() {
 
292
  const container = document.getElementById('sortable-container');
293
  if (!container) {
294
+ console.log('Container not found, retrying in 200ms');
295
+ setTimeout(initializeRankingInterface, 200);
296
  return;
297
  }
298
 
299
+ console.log('Sortable container found, setting up');
 
 
 
 
300
 
301
+ // Add click events directly to buttons as a backup
302
+ const upButtons = container.querySelectorAll('.up-btn');
303
+ const downButtons = container.querySelectorAll('.down-btn');
304
 
305
+ upButtons.forEach(btn => {
306
+ btn.addEventListener('click', function() {
307
+ const item = this.closest('.sortable-item');
308
+ const rank = parseInt(item.getAttribute('data-rank'));
309
+ window.moveItemUp(rank);
310
+ });
311
  });
312
+
313
+ downButtons.forEach(btn => {
314
+ btn.addEventListener('click', function() {
315
+ const item = this.closest('.sortable-item');
316
+ const rank = parseInt(item.getAttribute('data-rank'));
317
+ window.moveItemDown(rank);
318
+ });
319
+ });
320
+
321
+ // Initialize drag-and-drop as fallback
322
+ if (typeof Sortable !== 'undefined') {
323
+ if (!container.sortableInstance) {
324
+ container.sortableInstance = new Sortable(container, {
325
+ animation: 150,
326
+ ghostClass: "sortable-ghost",
327
+ onEnd: function() {
328
+ window.updateRanksAfterMove();
329
+ }
330
+ });
331
+ }
332
+ } else {
333
+ console.log('Sortable library not available');
334
+ }
335
+
336
+ // Initialize the ranking
337
+ window.updateRanksAfterMove();
338
  }
339
 
340
+ // Initialize immediately
341
+ initializeRankingInterface();
342
 
343
+ // Also observe DOM changes to reinitialize when needed
344
  const targetNode = document.getElementById('sortable-list-container');
345
  if (targetNode) {
346
  const config = { childList: true, subtree: true };
 
348
  for(const mutation of mutationsList) {
349
  if (mutation.type === 'childList') {
350
  if (document.getElementById('sortable-container')) {
351
+ console.log('DOM changed, reinitializing');
352
+ initializeRankingInterface();
353
  }
354
  }
355
  }
 
362
  .sortable-container {
363
  display: flex;
364
  flex-direction: column;
365
+ gap: 12px;
366
  min-height: 200px;
367
+ padding: 16px;
368
  background-color: #f8f9fa;
369
  border-radius: 8px;
370
  }
371
  .sortable-item {
372
+ padding: 14px;
373
  background-color: #fff;
374
  border: 1px solid #e0e0e0;
375
  border-radius: 6px;
 
376
  display: flex;
377
  align-items: center;
378
  transition: all 0.2s ease;
 
379
  }
380
  .sortable-item:hover {
381
  background-color: #f8f9fa;
382
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
383
  }
 
 
 
 
 
 
 
 
 
384
  .rank-controls {
385
+ display: flex;
386
  flex-direction: column;
387
  align-items: center;
388
+ margin-right: 16px;
389
  }
390
  .rank-badge {
391
  display: flex;
 
397
  background-color: #6c757d;
398
  color: white;
399
  font-weight: bold;
400
+ margin: 6px 0;
401
  flex-shrink: 0;
402
  }
403
  .rank-btn {
404
+ width: 28px;
405
+ height: 28px;
406
  border: none;
407
+ background-color: #f0f0f0;
408
  border-radius: 4px;
409
+ margin: 2px 0;
410
+ cursor: pointer;
 
 
411
  display: flex;
412
  align-items: center;
413
  justify-content: center;
414
+ font-size: 14px;
 
415
  }
416
  .rank-btn:hover:not([disabled]) {
417
+ background-color: #e0e0e0;
418
+ }
419
+ .rank-btn:active:not([disabled]) {
420
+ background-color: #d0d0d0;
421
  }
422
  .rank-btn:disabled {
423
  opacity: 0.5;
 
425
  }
426
  .doc-content {
427
  flex: 1;
428
+ line-height: 1.5;
429
  word-break: break-word;
430
  }
431
  .rank-bg-1 .rank-badge { background-color: #198754; }