arthrod commited on
Commit
d254c7b
·
verified ·
1 Parent(s): 1eeb044

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +238 -161
app.py CHANGED
@@ -3,7 +3,6 @@ import json
3
  import uuid
4
  from datetime import datetime
5
  import os
6
- import pandas as pd
7
 
8
  class LegalTechEvaluator:
9
  def __init__(self):
@@ -45,6 +44,7 @@ class LegalTechEvaluator:
45
  "responses": {},
46
  "completed": False
47
  }
 
48
  return user_id
49
 
50
  def record_choice(self, sample_choice):
@@ -134,8 +134,8 @@ Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
134
  """
135
 
136
  for idx in range(len(self.data)):
137
- if str(idx) in question_stats:
138
- stats = question_stats[str(idx)]
139
  total_responses = sum(stats.values())
140
  if total_responses > 0:
141
  question = self.data[idx]
@@ -169,6 +169,13 @@ custom_css = """
169
  max-width: 1200px !important;
170
  margin: 0 auto !important;
171
  padding: 0 !important;
 
 
 
 
 
 
 
172
  }
173
 
174
  #main-container {
@@ -201,26 +208,28 @@ custom_css = """
201
  line-height: 1.6;
202
  }
203
 
204
- #name-input {
205
  max-width: 400px;
206
  margin: 0 auto 24px;
207
  }
208
 
209
- #name-input input {
210
  font-size: 16px;
211
  padding: 12px 20px;
212
  border: 2px solid #e0e0e0;
213
  border-radius: 8px;
214
  width: 100%;
215
  transition: all 0.3s ease;
 
 
216
  }
217
 
218
- #name-input input:focus {
219
  border-color: #4a90e2;
220
  outline: none;
221
  }
222
 
223
- #start-button {
224
  background: #2563eb;
225
  color: white;
226
  border: none;
@@ -232,7 +241,7 @@ custom_css = """
232
  transition: all 0.3s ease;
233
  }
234
 
235
- #start-button:hover {
236
  background: #1d4ed8;
237
  transform: translateY(-1px);
238
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
@@ -391,7 +400,7 @@ custom_css = """
391
  border-top: 2px solid #e5e7eb;
392
  }
393
 
394
- #export-button {
395
  background: #6366f1;
396
  color: white;
397
  padding: 14px 40px;
@@ -403,7 +412,7 @@ custom_css = """
403
  transition: all 0.3s ease;
404
  }
405
 
406
- #export-button:hover {
407
  background: #4f46e5;
408
  transform: translateY(-1px);
409
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
@@ -428,6 +437,10 @@ custom_css = """
428
  display: none !important;
429
  }
430
 
 
 
 
 
431
  .success-message {
432
  background: #d1fae5;
433
  color: #065f46;
@@ -450,19 +463,163 @@ custom_css = """
450
  }
451
  """
452
 
453
- # HTML Template
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  html_template = """
455
  <div id="main-container">
456
  <div id="welcome-screen">
457
  <h1>Legal Tech Tool Evaluation</h1>
458
  <p>Compare and evaluate outputs from different legal technology tools to help us understand user preferences.</p>
459
- <div id="name-input">
460
- <input type="text" id="user-name" placeholder="Enter your name" />
461
  </div>
462
- <button id="start-button" onclick="startEvaluation()">Start Evaluation</button>
463
  </div>
464
 
465
- <div id="evaluation-container" class="hide">
466
  <div class="user-info" id="user-info"></div>
467
 
468
  <div id="question-header">
@@ -497,136 +654,22 @@ html_template = """
497
 
498
  <div id="action-buttons">
499
  <button class="nav-button" id="prev-button" onclick="previousQuestion()">← Previous</button>
500
- <button class="nav-button" id="confirm-button" onclick="confirmSelection()">Confirm Selection</button>
501
  <button class="nav-button" id="next-button" onclick="nextQuestion()">Next →</button>
502
  </div>
503
 
504
  <div id="export-section">
505
- <button id="export-button" onclick="exportResults()">Export Results</button>
506
  <div id="export-status"></div>
507
  </div>
508
  </div>
509
 
510
- <div id="file-upload-section" class="hide">
511
  <h3>No data file found</h3>
512
  <p>Please upload a JSONL file to begin the evaluation</p>
513
- <input type="file" id="file-input" accept=".jsonl" onchange="uploadFile()" />
514
  </div>
515
  </div>
516
-
517
- <script>
518
- let currentSelection = null;
519
- let evaluationStarted = false;
520
-
521
- function startEvaluation() {
522
- const name = document.getElementById('user-name').value.trim();
523
- if (!name) {
524
- alert('Please enter your name');
525
- return;
526
- }
527
-
528
- // Call Gradio function to start session
529
- window.gradioApp().querySelector('#start-session-btn').click();
530
- }
531
-
532
- function selectSample(sampleIndex) {
533
- // Clear previous selections
534
- document.querySelectorAll('.sample-card').forEach(card => {
535
- card.classList.remove('selected');
536
- });
537
-
538
- // Add selection to clicked sample
539
- document.getElementById(`sample-${sampleIndex}`).classList.add('selected');
540
- currentSelection = sampleIndex;
541
-
542
- // Enable confirm button
543
- document.getElementById('confirm-button').disabled = false;
544
- }
545
-
546
- function updateDisplay(data) {
547
- if (!data) return;
548
-
549
- // Parse the data
550
- const questionData = JSON.parse(data);
551
-
552
- if (questionData.showWelcome) {
553
- document.getElementById('welcome-screen').classList.remove('hide');
554
- document.getElementById('evaluation-container').classList.add('hide');
555
- document.getElementById('file-upload-section').classList.add('hide');
556
- } else if (questionData.showFileUpload) {
557
- document.getElementById('welcome-screen').classList.add('hide');
558
- document.getElementById('evaluation-container').classList.add('hide');
559
- document.getElementById('file-upload-section').classList.remove('hide');
560
- } else {
561
- document.getElementById('welcome-screen').classList.add('hide');
562
- document.getElementById('evaluation-container').classList.remove('hide');
563
- document.getElementById('file-upload-section').classList.add('hide');
564
-
565
- // Update user info
566
- if (questionData.userName) {
567
- document.getElementById('user-info').textContent = `Evaluator: ${questionData.userName}`;
568
- }
569
-
570
- // Update question info
571
- document.getElementById('current-question').textContent = questionData.currentIndex + 1;
572
- document.getElementById('total-questions').textContent = questionData.totalQuestions;
573
-
574
- // Update example and samples
575
- document.getElementById('example-text').textContent = questionData.introductoryExample;
576
- document.getElementById('sample-0-text').textContent = questionData.sampleZero;
577
- document.getElementById('sample-1-text').textContent = questionData.sampleOne;
578
- document.getElementById('sample-2-text').textContent = questionData.sampleTwo;
579
-
580
- // Update button states
581
- document.getElementById('prev-button').disabled = questionData.currentIndex === 0;
582
- document.getElementById('next-button').disabled = questionData.currentIndex >= questionData.totalQuestions - 1;
583
- document.getElementById('confirm-button').disabled = true;
584
-
585
- // Clear selection
586
- document.querySelectorAll('.sample-card').forEach(card => {
587
- card.classList.remove('selected');
588
- });
589
- currentSelection = null;
590
- }
591
- }
592
-
593
- function confirmSelection() {
594
- if (currentSelection === null) return;
595
-
596
- const sampleMap = ['sample_zero', 'sample_one', 'sample_two'];
597
- // Trigger Gradio function with selection
598
- window.gradioApp().querySelector('#hidden-selection').value = sampleMap[currentSelection];
599
- window.gradioApp().querySelector('#confirm-btn').click();
600
- }
601
-
602
- function previousQuestion() {
603
- window.gradioApp().querySelector('#prev-btn').click();
604
- }
605
-
606
- function nextQuestion() {
607
- window.gradioApp().querySelector('#next-btn').click();
608
- }
609
-
610
- function exportResults() {
611
- window.gradioApp().querySelector('#export-btn').click();
612
- }
613
-
614
- function uploadFile() {
615
- const fileInput = document.getElementById('file-input');
616
- if (fileInput.files.length > 0) {
617
- // Trigger Gradio file upload
618
- window.gradioApp().querySelector('#file-upload-btn').click();
619
- }
620
- }
621
-
622
- // Listen for Gradio updates
623
- setInterval(() => {
624
- const stateElement = window.gradioApp().querySelector('#current-state');
625
- if (stateElement && stateElement.value) {
626
- updateDisplay(stateElement.value);
627
- }
628
- }, 100);
629
- </script>
630
  """
631
 
632
  def start_session(name):
@@ -644,9 +687,12 @@ def get_current_state():
644
  """Get current state as JSON"""
645
  question = evaluator.get_current_question()
646
 
647
- if not question:
648
  return json.dumps({"showWelcome": True})
649
 
 
 
 
650
  return json.dumps({
651
  "showWelcome": False,
652
  "showFileUpload": False,
@@ -683,26 +729,19 @@ def export_results_handler():
683
  """Export results and return status"""
684
  try:
685
  jsonl_file, md_file, json_file, md_content = evaluator.export_results()
686
-
687
- # Read files for download
688
- with open(jsonl_file, 'r') as f:
689
- jsonl_content = f.read()
690
- with open(md_file, 'r') as f:
691
- md_download = f.read()
692
-
693
  return (
694
  get_current_state(),
695
- gr.update(value="✅ Results exported successfully!"),
696
- gr.File.update(value=jsonl_file, visible=True),
697
- gr.File.update(value=md_file, visible=True),
698
  md_content
699
  )
700
  except Exception as e:
701
  return (
702
  get_current_state(),
703
- gr.update(value=f"❌ Export failed: {str(e)}"),
704
- gr.File.update(visible=False),
705
- gr.File.update(visible=False),
706
  ""
707
  )
708
 
@@ -713,19 +752,29 @@ def load_file(file):
713
  return get_current_state()
714
 
715
  # Create Gradio interface
716
- with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo:
 
 
 
 
 
 
 
 
 
 
 
717
  # Hidden components for JavaScript interaction
718
  with gr.Column(visible=False):
719
- name_input = gr.Textbox(elem_id="hidden-name")
720
  start_btn = gr.Button("Start", elem_id="start-session-btn")
721
- current_state = gr.Textbox(elem_id="current-state")
722
  selection_input = gr.Textbox(elem_id="hidden-selection")
723
  confirm_btn = gr.Button("Confirm", elem_id="confirm-btn")
724
  prev_btn = gr.Button("Previous", elem_id="prev-btn")
725
  next_btn = gr.Button("Next", elem_id="next-btn")
726
  export_btn = gr.Button("Export", elem_id="export-btn")
727
- file_upload = gr.File(elem_id="file-upload-input")
728
- file_upload_btn = gr.Button("Upload", elem_id="file-upload-btn")
729
 
730
  # Output components (hidden)
731
  with gr.Column(visible=False):
@@ -734,13 +783,16 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo:
734
  download_md = gr.File(label="Download Summary")
735
  summary_display = gr.Markdown()
736
 
737
- # Main HTML interface
738
- gr.HTML(html_template)
739
-
740
  # Event handlers
 
 
 
 
 
 
741
  start_btn.click(
742
- fn=lambda name: start_session(name),
743
- inputs=[name_input],
744
  outputs=[current_state]
745
  )
746
 
@@ -765,16 +817,41 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo:
765
  outputs=[current_state, export_status, download_jsonl, download_md, summary_display]
766
  )
767
 
768
- file_upload_btn.click(
769
  fn=load_file,
770
  inputs=[file_upload],
771
  outputs=[current_state]
772
  )
773
 
774
- # Initial state
775
  demo.load(
776
- fn=lambda: json.dumps({"showWelcome": True}) if not evaluator.data else get_current_state(),
777
- outputs=[current_state]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  )
779
 
780
  # Create sample data if no file exists
 
3
  import uuid
4
  from datetime import datetime
5
  import os
 
6
 
7
  class LegalTechEvaluator:
8
  def __init__(self):
 
44
  "responses": {},
45
  "completed": False
46
  }
47
+ self.current_index = 0
48
  return user_id
49
 
50
  def record_choice(self, sample_choice):
 
134
  """
135
 
136
  for idx in range(len(self.data)):
137
+ if idx in question_stats:
138
+ stats = question_stats[idx]
139
  total_responses = sum(stats.values())
140
  if total_responses > 0:
141
  question = self.data[idx]
 
169
  max-width: 1200px !important;
170
  margin: 0 auto !important;
171
  padding: 0 !important;
172
+ background: transparent !important;
173
+ }
174
+
175
+ /* Fix for input text visibility */
176
+ input[type="text"] {
177
+ color: #1f2937 !important;
178
+ background-color: white !important;
179
  }
180
 
181
  #main-container {
 
208
  line-height: 1.6;
209
  }
210
 
211
+ #name-input-container {
212
  max-width: 400px;
213
  margin: 0 auto 24px;
214
  }
215
 
216
+ #name-input-container input {
217
  font-size: 16px;
218
  padding: 12px 20px;
219
  border: 2px solid #e0e0e0;
220
  border-radius: 8px;
221
  width: 100%;
222
  transition: all 0.3s ease;
223
+ color: #1f2937 !important;
224
+ background-color: white !important;
225
  }
226
 
227
+ #name-input-container input:focus {
228
  border-color: #4a90e2;
229
  outline: none;
230
  }
231
 
232
+ .start-button {
233
  background: #2563eb;
234
  color: white;
235
  border: none;
 
241
  transition: all 0.3s ease;
242
  }
243
 
244
+ .start-button:hover {
245
  background: #1d4ed8;
246
  transform: translateY(-1px);
247
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
 
400
  border-top: 2px solid #e5e7eb;
401
  }
402
 
403
+ .export-button {
404
  background: #6366f1;
405
  color: white;
406
  padding: 14px 40px;
 
412
  transition: all 0.3s ease;
413
  }
414
 
415
+ .export-button:hover {
416
  background: #4f46e5;
417
  transform: translateY(-1px);
418
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
 
437
  display: none !important;
438
  }
439
 
440
+ .show {
441
+ display: block !important;
442
+ }
443
+
444
  .success-message {
445
  background: #d1fae5;
446
  color: #065f46;
 
463
  }
464
  """
465
 
466
+ # JavaScript code to handle interactions
467
+ js_code = """
468
+ function startEvaluation() {
469
+ const nameInput = document.querySelector('textarea[data-testid="textbox"]');
470
+ if (nameInput && nameInput.value.trim()) {
471
+ const hiddenNameInput = document.querySelector('#hidden-name textarea');
472
+ if (hiddenNameInput) {
473
+ hiddenNameInput.value = nameInput.value.trim();
474
+ hiddenNameInput.dispatchEvent(new Event('input', { bubbles: true }));
475
+
476
+ setTimeout(() => {
477
+ const startBtn = document.querySelector('#start-session-btn button');
478
+ if (startBtn) {
479
+ startBtn.click();
480
+ }
481
+ }, 100);
482
+ }
483
+ } else {
484
+ alert('Please enter your name');
485
+ }
486
+ }
487
+
488
+ function selectSample(sampleIndex) {
489
+ // Update hidden selection input
490
+ const selectionInput = document.querySelector('#hidden-selection textarea');
491
+ if (selectionInput) {
492
+ const sampleMap = ['sample_zero', 'sample_one', 'sample_two'];
493
+ selectionInput.value = sampleMap[sampleIndex];
494
+ selectionInput.dispatchEvent(new Event('input', { bubbles: true }));
495
+
496
+ // Update visual selection
497
+ document.querySelectorAll('.sample-card').forEach(card => {
498
+ card.classList.remove('selected');
499
+ });
500
+ document.getElementById(`sample-${sampleIndex}`).classList.add('selected');
501
+
502
+ // Enable confirm button
503
+ const confirmBtn = document.getElementById('confirm-button');
504
+ if (confirmBtn) {
505
+ confirmBtn.disabled = false;
506
+ }
507
+ }
508
+ }
509
+
510
+ function confirmSelection() {
511
+ const confirmBtn = document.querySelector('#confirm-btn button');
512
+ if (confirmBtn) {
513
+ confirmBtn.click();
514
+ }
515
+ }
516
+
517
+ function previousQuestion() {
518
+ const prevBtn = document.querySelector('#prev-btn button');
519
+ if (prevBtn) {
520
+ prevBtn.click();
521
+ }
522
+ }
523
+
524
+ function nextQuestion() {
525
+ const nextBtn = document.querySelector('#next-btn button');
526
+ if (nextBtn) {
527
+ nextBtn.click();
528
+ }
529
+ }
530
+
531
+ function exportResults() {
532
+ const exportBtn = document.querySelector('#export-btn button');
533
+ if (exportBtn) {
534
+ exportBtn.click();
535
+ }
536
+ }
537
+
538
+ // Update display based on state changes
539
+ function updateDisplay() {
540
+ const stateElement = document.querySelector('#current-state textarea');
541
+ if (stateElement && stateElement.value) {
542
+ try {
543
+ const data = JSON.parse(stateElement.value);
544
+
545
+ const welcomeScreen = document.getElementById('welcome-screen');
546
+ const evaluationContainer = document.getElementById('evaluation-container');
547
+ const fileUploadSection = document.getElementById('file-upload-section');
548
+
549
+ if (data.showWelcome) {
550
+ welcomeScreen.style.display = 'block';
551
+ evaluationContainer.style.display = 'none';
552
+ fileUploadSection.style.display = 'none';
553
+ } else if (data.showFileUpload) {
554
+ welcomeScreen.style.display = 'none';
555
+ evaluationContainer.style.display = 'none';
556
+ fileUploadSection.style.display = 'block';
557
+ } else {
558
+ welcomeScreen.style.display = 'none';
559
+ evaluationContainer.style.display = 'block';
560
+ fileUploadSection.style.display = 'none';
561
+
562
+ // Update content
563
+ if (data.userName) {
564
+ const userInfo = document.getElementById('user-info');
565
+ if (userInfo) userInfo.textContent = `Evaluator: ${data.userName}`;
566
+ }
567
+
568
+ document.getElementById('current-question').textContent = data.currentIndex + 1;
569
+ document.getElementById('total-questions').textContent = data.totalQuestions;
570
+ document.getElementById('example-text').textContent = data.introductoryExample;
571
+ document.getElementById('sample-0-text').textContent = data.sampleZero;
572
+ document.getElementById('sample-1-text').textContent = data.sampleOne;
573
+ document.getElementById('sample-2-text').textContent = data.sampleTwo;
574
+
575
+ // Update button states
576
+ document.getElementById('prev-button').disabled = data.currentIndex === 0;
577
+ document.getElementById('next-button').disabled = data.currentIndex >= data.totalQuestions - 1;
578
+ document.getElementById('confirm-button').disabled = true;
579
+
580
+ // Clear selection
581
+ document.querySelectorAll('.sample-card').forEach(card => {
582
+ card.classList.remove('selected');
583
+ });
584
+ }
585
+ } catch (e) {
586
+ console.error('Error parsing state:', e);
587
+ }
588
+ }
589
+ }
590
+
591
+ // Set up observer for state changes
592
+ const observer = new MutationObserver(() => {
593
+ updateDisplay();
594
+ });
595
+
596
+ // Start observing when DOM is ready
597
+ document.addEventListener('DOMContentLoaded', () => {
598
+ const stateElement = document.querySelector('#current-state textarea');
599
+ if (stateElement) {
600
+ observer.observe(stateElement, {
601
+ attributes: true,
602
+ childList: true,
603
+ characterData: true,
604
+ subtree: true
605
+ });
606
+ updateDisplay();
607
+ }
608
+ });
609
+ """
610
+
611
+ # HTML Template with onclick handlers
612
  html_template = """
613
  <div id="main-container">
614
  <div id="welcome-screen">
615
  <h1>Legal Tech Tool Evaluation</h1>
616
  <p>Compare and evaluate outputs from different legal technology tools to help us understand user preferences.</p>
617
+ <div id="name-input-container">
618
+ <!-- Gradio will inject the textbox here -->
619
  </div>
 
620
  </div>
621
 
622
+ <div id="evaluation-container">
623
  <div class="user-info" id="user-info"></div>
624
 
625
  <div id="question-header">
 
654
 
655
  <div id="action-buttons">
656
  <button class="nav-button" id="prev-button" onclick="previousQuestion()">← Previous</button>
657
+ <button class="nav-button" id="confirm-button" onclick="confirmSelection()" disabled>Confirm Selection</button>
658
  <button class="nav-button" id="next-button" onclick="nextQuestion()">Next →</button>
659
  </div>
660
 
661
  <div id="export-section">
662
+ <button class="export-button" onclick="exportResults()">Export Results</button>
663
  <div id="export-status"></div>
664
  </div>
665
  </div>
666
 
667
+ <div id="file-upload-section">
668
  <h3>No data file found</h3>
669
  <p>Please upload a JSONL file to begin the evaluation</p>
670
+ <!-- File upload will be handled by Gradio -->
671
  </div>
672
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  """
674
 
675
  def start_session(name):
 
687
  """Get current state as JSON"""
688
  question = evaluator.get_current_question()
689
 
690
+ if not evaluator.current_user_name:
691
  return json.dumps({"showWelcome": True})
692
 
693
+ if not question:
694
+ return json.dumps({"showFileUpload": True})
695
+
696
  return json.dumps({
697
  "showWelcome": False,
698
  "showFileUpload": False,
 
729
  """Export results and return status"""
730
  try:
731
  jsonl_file, md_file, json_file, md_content = evaluator.export_results()
 
 
 
 
 
 
 
732
  return (
733
  get_current_state(),
734
+ "✅ Results exported successfully!",
735
+ jsonl_file,
736
+ md_file,
737
  md_content
738
  )
739
  except Exception as e:
740
  return (
741
  get_current_state(),
742
+ f"❌ Export failed: {str(e)}",
743
+ None,
744
+ None,
745
  ""
746
  )
747
 
 
752
  return get_current_state()
753
 
754
  # Create Gradio interface
755
+ with gr.Blocks(css=custom_css, js=js_code, theme=gr.themes.Base()) as demo:
756
+ gr.HTML(html_template)
757
+
758
+ # Visible name input in welcome screen
759
+ with gr.Column(elem_id="name-input-wrapper", visible=True):
760
+ user_name_input = gr.Textbox(
761
+ label="",
762
+ placeholder="Enter your name",
763
+ elem_id="user-name-field"
764
+ )
765
+ start_button = gr.Button("Start Evaluation", elem_classes=["start-button"])
766
+
767
  # Hidden components for JavaScript interaction
768
  with gr.Column(visible=False):
769
+ hidden_name = gr.Textbox(elem_id="hidden-name")
770
  start_btn = gr.Button("Start", elem_id="start-session-btn")
771
+ current_state = gr.Textbox(value=json.dumps({"showWelcome": True}), elem_id="current-state")
772
  selection_input = gr.Textbox(elem_id="hidden-selection")
773
  confirm_btn = gr.Button("Confirm", elem_id="confirm-btn")
774
  prev_btn = gr.Button("Previous", elem_id="prev-btn")
775
  next_btn = gr.Button("Next", elem_id="next-btn")
776
  export_btn = gr.Button("Export", elem_id="export-btn")
777
+ file_upload = gr.File(elem_id="file-upload-input", file_types=[".jsonl"])
 
778
 
779
  # Output components (hidden)
780
  with gr.Column(visible=False):
 
783
  download_md = gr.File(label="Download Summary")
784
  summary_display = gr.Markdown()
785
 
 
 
 
786
  # Event handlers
787
+ start_button.click(
788
+ fn=start_session,
789
+ inputs=[user_name_input],
790
+ outputs=[current_state]
791
+ )
792
+
793
  start_btn.click(
794
+ fn=start_session,
795
+ inputs=[hidden_name],
796
  outputs=[current_state]
797
  )
798
 
 
817
  outputs=[current_state, export_status, download_jsonl, download_md, summary_display]
818
  )
819
 
820
+ file_upload.change(
821
  fn=load_file,
822
  inputs=[file_upload],
823
  outputs=[current_state]
824
  )
825
 
826
+ # Move name input to welcome screen on load
827
  demo.load(
828
+ fn=None,
829
+ js="""
830
+ () => {
831
+ // Move the name input to the welcome screen
832
+ const nameWrapper = document.querySelector('#name-input-wrapper');
833
+ const nameContainer = document.querySelector('#name-input-container');
834
+ if (nameWrapper && nameContainer) {
835
+ const nameField = nameWrapper.querySelector('.wrap');
836
+ if (nameField) {
837
+ nameContainer.appendChild(nameField);
838
+ }
839
+ nameWrapper.style.display = 'none';
840
+ }
841
+
842
+ // Style the start button
843
+ const startBtn = document.querySelector('#name-input-wrapper').nextElementSibling;
844
+ if (startBtn) {
845
+ const btn = startBtn.querySelector('button');
846
+ if (btn) {
847
+ btn.className = 'start-button';
848
+ btn.onclick = () => startEvaluation();
849
+ }
850
+ document.querySelector('#welcome-screen').appendChild(btn);
851
+ startBtn.style.display = 'none';
852
+ }
853
+ }
854
+ """
855
  )
856
 
857
  # Create sample data if no file exists