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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -33
app.py CHANGED
@@ -11,7 +11,7 @@ def create_reranking_interface(task_data):
11
 
12
  # Define helper functions before UI elements are created
13
  def generate_sortable_html(candidates, existing_ranks=None):
14
- """Generate the HTML for the sortable list."""
15
  if existing_ranks and len(existing_ranks) == len(candidates):
16
  order = sorted(range(len(candidates)), key=lambda i: existing_ranks[i])
17
  else:
@@ -24,9 +24,18 @@ def create_reranking_interface(task_data):
24
  rank = rank_minus_1 + 1
25
  import html as html_escaper
26
  escaped_doc = html_escaper.escape(doc)
 
 
 
 
 
27
  html += f'''\
28
- <div class="sortable-item rank-bg-{rank}" data-doc-id="{idx}">
29
- <div class="rank-badge">{rank}</div>
 
 
 
 
30
  <div class="doc-content">{escaped_doc}</div>
31
  </div>
32
  '''
@@ -143,8 +152,115 @@ def create_reranking_interface(task_data):
143
  js_code = """
144
  <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
145
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  document.addEventListener('DOMContentLoaded', function() {
147
  function initializeSortable() {
 
 
 
 
148
  const container = document.getElementById('sortable-container');
149
  if (!container) {
150
  console.log('Container not found, retrying...');
@@ -166,37 +282,9 @@ def create_reranking_interface(task_data):
166
  animation: 150,
167
  ghostClass: "sortable-ghost",
168
  onEnd: function() {
169
- updateRanksAndSyncState();
170
  }
171
  });
172
-
173
- updateRanksAndSyncState();
174
- }
175
-
176
- function updateRanksAndSyncState() {
177
- const container = document.getElementById('sortable-container');
178
- if (!container) return;
179
-
180
- const items = container.querySelectorAll('.sortable-item');
181
- const orderInput = document.querySelector('#current-order textarea');
182
- if (!orderInput) return;
183
-
184
- const order = [];
185
- items.forEach((item, index) => {
186
- const rankBadge = item.querySelector('.rank-badge');
187
- if (rankBadge) rankBadge.textContent = (index + 1);
188
- item.className = item.className.replace(/rank-bg-\d+/g, '').trim();
189
- item.classList.add(`rank-bg-${index + 1}`);
190
- const docId = parseInt(item.getAttribute('data-doc-id'));
191
- order.push(docId);
192
- });
193
-
194
- const newOrderValue = JSON.stringify(order);
195
- if (orderInput.value !== newOrderValue) {
196
- orderInput.value = newOrderValue;
197
- const event = new Event('input', { bubbles: true });
198
- orderInput.dispatchEvent(event);
199
- }
200
  }
201
 
202
  // Initialize immediately and also set up a mutation observer
@@ -252,6 +340,12 @@ def create_reranking_interface(task_data):
252
  cursor: grabbing;
253
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
254
  }
 
 
 
 
 
 
255
  .rank-badge {
256
  display: flex;
257
  align-items: center;
@@ -262,9 +356,30 @@ def create_reranking_interface(task_data):
262
  background-color: #6c757d;
263
  color: white;
264
  font-weight: bold;
265
- margin-right: 15px;
266
  flex-shrink: 0;
267
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  .doc-content {
269
  flex: 1;
270
  line-height: 1.4;
 
11
 
12
  # Define helper functions before UI elements are created
13
  def generate_sortable_html(candidates, existing_ranks=None):
14
+ """Generate the HTML for the sortable list with up/down buttons."""
15
  if existing_ranks and len(existing_ranks) == len(candidates):
16
  order = sorted(range(len(candidates)), key=lambda i: existing_ranks[i])
17
  else:
 
24
  rank = rank_minus_1 + 1
25
  import html as html_escaper
26
  escaped_doc = html_escaper.escape(doc)
27
+
28
+ # Add navigation buttons (up/down arrows)
29
+ up_disabled = "disabled" if rank == 1 else ""
30
+ down_disabled = "disabled" if rank == len(candidates) else ""
31
+
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>
41
  '''
 
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) => {
212
+ const rank = index + 1;
213
+ const docId = parseInt(item.getAttribute('data-doc-id'));
214
+
215
+ // Update rank display
216
+ const rankBadge = item.querySelector('.rank-badge');
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
224
+ item.setAttribute('data-rank', rank);
225
+
226
+ // Update button states
227
+ const upBtn = item.querySelector('.up-btn');
228
+ const downBtn = item.querySelector('.down-btn');
229
+
230
+ if (upBtn) {
231
+ if (rank == 1) {
232
+ upBtn.setAttribute('disabled', 'disabled');
233
+ } else {
234
+ upBtn.removeAttribute('disabled');
235
+ }
236
+ }
237
+
238
+ if (downBtn) {
239
+ if (rank == items.length) {
240
+ downBtn.setAttribute('disabled', 'disabled');
241
+ } else {
242
+ downBtn.removeAttribute('disabled');
243
+ }
244
+ }
245
+
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...');
 
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
 
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;
351
  align-items: center;
 
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;
381
+ cursor: not-allowed;
382
+ }
383
  .doc-content {
384
  flex: 1;
385
  line-height: 1.4;