emvecchi commited on
Commit
ce8b1cd
·
verified ·
1 Parent(s): 7340a7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -45
app.py CHANGED
@@ -646,33 +646,40 @@ def show_fields(fields: List[Field]):
646
  st.session_state.form_displayed = st.session_state.current_index
647
  '''
648
  def show_field(f: Field, index: int, data_collected):
649
- """Render a Field tree. No form logic; everything runs outside forms."""
650
- # Non-input widgets (custom structural types)
 
651
  if f.type not in INPUT_FIELD_DEFAULT_VALUES.keys():
652
  match f.type:
653
  case 'input_col':
654
- # Safely read a column from the current CSV row (or None if missing)
655
- value = st.session_state.data.iloc[index][f.name] if (
656
- f.name and f.name in st.session_state.data.columns
657
- ) else None
658
-
659
- # Render based on field name
 
 
660
  if f.name == 'image_name' and value:
661
  display_image(os.path.join(input_repo_path, 'images', value))
 
662
  elif f.name == 'dialogue_name' and value:
663
  render_dialogue(
664
  os.path.join(input_repo_path, 'dialogues', value),
665
  width_chars=115, height_px=520, show_border=False
666
  )
 
667
  elif f.name == 'patient' and value:
668
  st.markdown(f"## Patient:  {value}")
 
669
  elif value not in (None, np.nan, ""):
670
  # generic fallback
671
- st.write(f.title)
 
672
  st.write(value)
673
 
674
  case 'markdown':
675
- # If a file path is provided, load & render it; otherwise render the title string
676
  path = f.other_params.get("path") if f.other_params else None
677
  if path:
678
  content = load_text(os.path.join(input_repo_path, path))
@@ -681,7 +688,7 @@ def show_field(f: Field, index: int, data_collected):
681
  st.markdown(f.title)
682
 
683
  case 'expander':
684
- # Markdown header above; expander label is plain text
685
  st.markdown(f.title)
686
  with st.expander(""):
687
  for child in (f.children or []):
@@ -694,20 +701,25 @@ def show_field(f: Field, index: int, data_collected):
694
  show_field(child, index, data_collected)
695
 
696
  case 'skip_checkbox':
697
- # outside forms this is fine
698
  st.checkbox(f.title, key=f.name, value=False)
699
 
700
  case 'rupture_markers':
701
- # dynamic widget (outside forms)
702
  render_rupture_markers_widget(index, rupture_choices)
703
 
704
- return # done with non-input types
705
 
706
- # Input widgets (saved via data_inputs_keys)
707
  key = f.name + str(index)
 
708
  st.session_state.data_inputs_keys.append(f.name)
709
 
710
- # Initial value: session_state > saved JSON > default
 
 
 
 
711
  if key in st.session_state:
712
  value = st.session_state[key]
713
  elif data_collected and f.name in data_collected:
@@ -715,54 +727,91 @@ def show_field(f: Field, index: int, data_collected):
715
  else:
716
  value = INPUT_FIELD_DEFAULT_VALUES[f.type]
717
 
718
- # Render inputs
719
  match f.type:
720
  case 'checkbox':
721
  st.checkbox(f.title, key=key, value=value, help=f.help)
722
 
723
  case 'radio':
724
- labels = f.other_params.get('labels') if f.other_params and f.other_params.get('labels') else default_labels
725
- st.radio(f.title,
726
- options=range(len(labels)),
727
- format_func=lambda x: labels[x],
728
- key=key,
729
- index=value if value is not None else 0,
730
- help=f.help, horizontal=False)
 
 
 
 
 
731
 
732
  case 'slider':
733
- st.slider(f.title, min_value=0, max_value=6, step=1, key=key, value=value, help=f.help)
 
734
 
735
  case 'select_slider':
736
- labels = f.other_params.get('labels') if f.other_params and f.other_params.get('labels') else default_labels
737
- st.select_slider(f.title,
738
- options=[0, 20, 40, 60, 80, 100],
739
- format_func=lambda x: labels[x // 20],
740
- key=key, value=value, help=f.help)
 
 
 
 
 
 
741
 
742
  case 'multiselect':
743
- choices = f.other_params.get('choices') if f.other_params and f.other_params.get('choices') else default_choices
744
- st.multiselect(f.title, options=choices, format_func=lambda x: x,
745
- key=key, max_selections=3, default=value, help=f.help)
 
 
 
 
 
 
 
 
 
746
 
747
  case 'likert_radio':
748
- labels = f.other_params.get('labels') if f.other_params and f.other_params.get('labels') else default_labels
749
- st.radio(f.title, options=[0, 1, 2, 3, 4],
750
- format_func=lambda x: labels[x],
751
- key=key, index=value if value is not None else 0,
752
- help=f.help, horizontal=True)
 
 
 
 
 
 
 
753
 
754
  case 'y_n_radio':
755
- labels = f.other_params.get('labels') if f.other_params and f.other_params.get('labels') else yes_no_labels
756
- st.radio(f.title, options=[0, 1],
757
- format_func=lambda x: labels[x],
758
- key=key, index=value if value is not None else 0,
759
- help=f.help, horizontal=True)
 
 
 
 
 
 
 
760
 
761
  case 'text':
762
- st.text_input(f.title, key=key, value=value if value is not None else "", max_chars=None)
 
763
 
764
  case 'textarea':
765
- st.text_area(f.title, key=key, value=value if value is not None else "", max_chars=None)
 
 
766
 
767
 
768
  def show_fields(fields: List[Field]):
 
646
  st.session_state.form_displayed = st.session_state.current_index
647
  '''
648
  def show_field(f: Field, index: int, data_collected):
649
+ """Render a Field tree. Pure rendering (no form submit logic here)."""
650
+
651
+ # ---------- Non-input / structural types ----------
652
  if f.type not in INPUT_FIELD_DEFAULT_VALUES.keys():
653
  match f.type:
654
  case 'input_col':
655
+ # Safely read CSV value if the column exists
656
+ value = (
657
+ st.session_state.data.iloc[index][f.name]
658
+ if f.name and f.name in st.session_state.data.columns
659
+ else None
660
+ )
661
+
662
+ # Render by name
663
  if f.name == 'image_name' and value:
664
  display_image(os.path.join(input_repo_path, 'images', value))
665
+
666
  elif f.name == 'dialogue_name' and value:
667
  render_dialogue(
668
  os.path.join(input_repo_path, 'dialogues', value),
669
  width_chars=115, height_px=520, show_border=False
670
  )
671
+
672
  elif f.name == 'patient' and value:
673
  st.markdown(f"## Patient:  {value}")
674
+
675
  elif value not in (None, np.nan, ""):
676
  # generic fallback
677
+ if f.title:
678
+ st.write(f.title)
679
  st.write(value)
680
 
681
  case 'markdown':
682
+ # Either render file contents, or the literal title as markdown
683
  path = f.other_params.get("path") if f.other_params else None
684
  if path:
685
  content = load_text(os.path.join(input_repo_path, path))
 
688
  st.markdown(f.title)
689
 
690
  case 'expander':
691
+ # Markdown header above; expander label is plain text (blank)
692
  st.markdown(f.title)
693
  with st.expander(""):
694
  for child in (f.children or []):
 
701
  show_field(child, index, data_collected)
702
 
703
  case 'skip_checkbox':
704
+ # Lives fine outside forms
705
  st.checkbox(f.title, key=f.name, value=False)
706
 
707
  case 'rupture_markers':
708
+ # Dynamic add/remove rows (outside forms so buttons rerun)
709
  render_rupture_markers_widget(index, rupture_choices)
710
 
711
+ return # done with structural types
712
 
713
+ # ---------- Input types (saved to session & later to JSON) ----------
714
  key = f.name + str(index)
715
+ # track the logical field name once per page; prep_and_save_data relies on this
716
  st.session_state.data_inputs_keys.append(f.name)
717
 
718
+ # Compose title with inline help (no stray/bare expression)
719
+ if not SHOW_HELP_ICON:
720
+ f.title = f'**{f.title}**\n\n{f.help}' if f.help else f.title
721
+
722
+ # Resolve initial value: session_state > saved JSON > default
723
  if key in st.session_state:
724
  value = st.session_state[key]
725
  elif data_collected and f.name in data_collected:
 
727
  else:
728
  value = INPUT_FIELD_DEFAULT_VALUES[f.type]
729
 
 
730
  match f.type:
731
  case 'checkbox':
732
  st.checkbox(f.title, key=key, value=value, help=f.help)
733
 
734
  case 'radio':
735
+ labels = (f.other_params.get('labels')
736
+ if f.other_params and f.other_params.get('labels')
737
+ else default_labels)
738
+ st.radio(
739
+ f.title,
740
+ options=range(len(labels)),
741
+ format_func=lambda x: labels[x],
742
+ key=key,
743
+ index=(value if value is not None else 0),
744
+ help=f.help,
745
+ horizontal=False
746
+ )
747
 
748
  case 'slider':
749
+ st.slider(f.title, min_value=0, max_value=6, step=1, key=key,
750
+ value=value, help=f.help)
751
 
752
  case 'select_slider':
753
+ labels = (f.other_params.get('labels')
754
+ if f.other_params and f.other_params.get('labels')
755
+ else default_labels)
756
+ st.select_slider(
757
+ f.title,
758
+ options=[0, 20, 40, 60, 80, 100],
759
+ format_func=lambda x: labels[x // 20],
760
+ key=key,
761
+ value=value,
762
+ help=f.help
763
+ )
764
 
765
  case 'multiselect':
766
+ choices = (f.other_params.get('choices')
767
+ if f.other_params and f.other_params.get('choices')
768
+ else default_choices)
769
+ st.multiselect(
770
+ f.title,
771
+ options=choices,
772
+ format_func=lambda x: x,
773
+ key=key,
774
+ default=value,
775
+ max_selections=3,
776
+ help=f.help
777
+ )
778
 
779
  case 'likert_radio':
780
+ labels = (f.other_params.get('labels')
781
+ if f.other_params and f.other_params.get('labels')
782
+ else default_labels)
783
+ st.radio(
784
+ f.title,
785
+ options=[0, 1, 2, 3, 4],
786
+ format_func=lambda x: labels[x],
787
+ key=key,
788
+ index=(value if value is not None else 0),
789
+ help=f.help,
790
+ horizontal=True
791
+ )
792
 
793
  case 'y_n_radio':
794
+ labels = (f.other_params.get('labels')
795
+ if f.other_params and f.other_params.get('labels')
796
+ else yes_no_labels)
797
+ st.radio(
798
+ f.title,
799
+ options=[0, 1],
800
+ format_func=lambda x: labels[x],
801
+ key=key,
802
+ index=(value if value is not None else 0),
803
+ help=f.help,
804
+ horizontal=True
805
+ )
806
 
807
  case 'text':
808
+ st.text_input(f.title, key=key, value=(value if value is not None else ""),
809
+ max_chars=None, help=f.help)
810
 
811
  case 'textarea':
812
+ st.text_area(f.title, key=key, value=(value if value is not None else ""),
813
+ max_chars=None, help=f.help)
814
+
815
 
816
 
817
  def show_fields(fields: List[Field]):