clementBE commited on
Commit
15632e6
·
verified ·
1 Parent(s): f88fbc7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -27
app.py CHANGED
@@ -74,6 +74,39 @@ def process_file(file_obj):
74
  text = f.read()
75
  return text, name, get_empty_df()
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  # ------------------------------
78
  # APPLY CODE
79
  # ------------------------------
@@ -119,16 +152,6 @@ def export_excel(df):
119
  df.to_excel(path, index=False)
120
  return path, "Excel ready."
121
 
122
- # ------------------------------
123
- # UPDATE HIGHLIGHTED TEXT
124
- # ------------------------------
125
- def get_highlighted_text(text, coded_df):
126
- highlights = []
127
- if coded_df is not None and not coded_df.empty:
128
- for _, row in coded_df.iterrows():
129
- highlights.append({"text": row["Coded Segment"], "label": row["Code"]})
130
- return {"text": text, "entities": highlights}
131
-
132
  # ------------------------------
133
  # GRADIO UI
134
  # ------------------------------
@@ -151,11 +174,7 @@ with gr.Blocks(title="Interactive Qualitative Coding") as demo:
151
  with gr.Row():
152
  # LEFT: transcript
153
  with gr.Column(scale=3):
154
- transcript_display = gr.HighlightedText(
155
- value={"text": "", "entities": []},
156
- label="Transcript",
157
- interactive=True,
158
- )
159
 
160
  # RIGHT: coding panel
161
  with gr.Column(scale=2):
@@ -177,23 +196,17 @@ with gr.Blocks(title="Interactive Qualitative Coding") as demo:
177
  # ---------------- CALLBACKS ----------------
178
  file_input.change(fn=process_file, inputs=file_input, outputs=[full_text, file_id, coded_df_state])
179
 
180
- # Update transcript display when text or coded_df changes
181
  def update_transcript(text, df):
182
- return get_highlighted_text(text, df)
183
-
184
- full_text.change(update_transcript, inputs=[full_text, coded_df_state], outputs=transcript_display)
185
- coded_df_state.change(update_transcript, inputs=[full_text, coded_df_state], outputs=transcript_display)
186
-
187
- # Selecting text in transcript auto-fills segment box
188
- def fill_segment(selected):
189
- return selected["text"] if selected else ""
190
 
191
- transcript_display.select(fill_segment, inputs=transcript_display, outputs=segment_box)
 
192
 
193
  # Fill code input when selecting dropdown
194
  code_dropdown.change(lambda x: x, inputs=code_dropdown, outputs=code_input)
195
 
196
- # Apply code (updates coded data and code list)
197
  code_btn.click(
198
  fn=apply_code,
199
  inputs=[coded_df_state, file_id, full_text, segment_box, code_input, code_categories_state] + metadata_inputs,
@@ -203,7 +216,7 @@ with gr.Blocks(title="Interactive Qualitative Coding") as demo:
203
  # Update dropdown when code list changes
204
  code_categories_state.change(lambda codes: gr.update(choices=codes), inputs=code_categories_state, outputs=code_dropdown)
205
 
206
- # Update table when coded_df changes
207
  coded_df_state.change(lambda x: x, inputs=coded_df_state, outputs=table)
208
 
209
  # Export
 
74
  text = f.read()
75
  return text, name, get_empty_df()
76
 
77
+ # ------------------------------
78
+ # BUILD HTML TRANSCRIPT
79
+ # ------------------------------
80
+ def build_html_transcript(text, coded_df):
81
+ display_text = text
82
+ if coded_df is not None and not coded_df.empty:
83
+ for _, row in coded_df.iterrows():
84
+ seg = row["Coded Segment"]
85
+ color = COLOR_MAP.get(row["Code"], "yellow")
86
+ display_text = display_text.replace(seg, f"<span style='background-color:{color}'>{seg}</span>", 1)
87
+
88
+ safe_text = display_text.replace("\n", "<br>")
89
+
90
+ html = f"""
91
+ <div style='white-space: pre-wrap; font-size:16px; line-height:1.5; max-height:600px; overflow:auto; border:1px solid #ccc; padding:5px;' id='transcript'>
92
+ {safe_text}
93
+ </div>
94
+ <script>
95
+ const transcript = document.getElementById('transcript');
96
+ transcript.addEventListener('mouseup', function() {{
97
+ const selection = window.getSelection().toString();
98
+ if(selection.length>0){{
99
+ const tb = document.querySelector('textarea[placeholder="Selected segment"]');
100
+ if(tb) {{
101
+ tb.value = selection;
102
+ tb.dispatchEvent(new Event("input", {{bubbles:true}}));
103
+ }}
104
+ }}
105
+ }});
106
+ </script>
107
+ """
108
+ return html
109
+
110
  # ------------------------------
111
  # APPLY CODE
112
  # ------------------------------
 
152
  df.to_excel(path, index=False)
153
  return path, "Excel ready."
154
 
 
 
 
 
 
 
 
 
 
 
155
  # ------------------------------
156
  # GRADIO UI
157
  # ------------------------------
 
174
  with gr.Row():
175
  # LEFT: transcript
176
  with gr.Column(scale=3):
177
+ transcript_html = gr.HTML()
 
 
 
 
178
 
179
  # RIGHT: coding panel
180
  with gr.Column(scale=2):
 
196
  # ---------------- CALLBACKS ----------------
197
  file_input.change(fn=process_file, inputs=file_input, outputs=[full_text, file_id, coded_df_state])
198
 
199
+ # Update transcript when text or coded_df changes
200
  def update_transcript(text, df):
201
+ return build_html_transcript(text, df)
 
 
 
 
 
 
 
202
 
203
+ full_text.change(update_transcript, inputs=[full_text, coded_df_state], outputs=transcript_html)
204
+ coded_df_state.change(update_transcript, inputs=[full_text, coded_df_state], outputs=transcript_html)
205
 
206
  # Fill code input when selecting dropdown
207
  code_dropdown.change(lambda x: x, inputs=code_dropdown, outputs=code_input)
208
 
209
+ # Apply code
210
  code_btn.click(
211
  fn=apply_code,
212
  inputs=[coded_df_state, file_id, full_text, segment_box, code_input, code_categories_state] + metadata_inputs,
 
216
  # Update dropdown when code list changes
217
  code_categories_state.change(lambda codes: gr.update(choices=codes), inputs=code_categories_state, outputs=code_dropdown)
218
 
219
+ # Update table
220
  coded_df_state.change(lambda x: x, inputs=coded_df_state, outputs=table)
221
 
222
  # Export