Tesneem commited on
Commit
eac0422
Β·
verified Β·
1 Parent(s): ad03416

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -76
app.py CHANGED
@@ -323,6 +323,7 @@ st.plotly_chart(fig, use_container_width=True)
323
 
324
  st.caption(f"{len(df_final)} line(s) aggregated." if not df_final.empty else "No data.")
325
 
 
326
  # ================== Dynamic Stage Summaries (only if student answered that week) ==================
327
  import re
328
  import unicodedata
@@ -554,82 +555,72 @@ if mongo_uri and student_choice != "(All)" and source_choice != "(All)":
554
  for q in (summary.get("notable_quotes") or [])[:3]:
555
  st.markdown(f"> {q}")
556
  # # ------------------- Output (Tabs) -------------------
557
- # tab_radar, tab_analyses = st.tabs(["πŸ“ˆ Radar", "πŸ“ Analyses"])
558
-
559
- # with tab_radar:
560
- # # plot the radar (uses df_plot, avg_label already computed above)
561
- # fig = plot_radar(df_plot, grouped, chart_title, avg_label=avg_label)
562
- # st.plotly_chart(fig, use_container_width=True)
563
- # st.caption(f"{len(df_final)} line(s) aggregated." if not df_final.empty else "No data.")
564
-
565
- # # Dynamic stage summary panel (only if a specific student + source selected,
566
- # # and only if they actually answered that week)
567
- # if mongo_uri and student_choice != "(All)" and source_choice != "(All)":
568
- # # Map the selected source (e.g., 'onboarding_responses') to stage (e.g., 'onboarding')
569
- # stage = SOURCE_TO_STAGE.get(source_choice.strip())
570
- # if stage:
571
- # # summaries collection name (adjust if needed)
572
- # summaries_coll_name = "summaries_IFE_2025"
573
-
574
- # summary = fetch_student_stage_summary(
575
- # mongo_uri, db_name, summaries_coll_name, coll_name,
576
- # student=student_choice, stage=stage
577
- # )
578
- # if summary:
579
- # st.markdown("---")
580
- # st.subheader(f"Summary β€” {student_choice} ({stage.replace('_', ' ').title()})")
581
-
582
- # c1, c2 = st.columns(2)
583
- # with c1:
584
- # st.markdown(f"**Most Consistent:** {summary.get('most_consistent') or 'β€”'}")
585
- # st.markdown(f"**Most Developed:** {summary.get('most_developed') or 'β€”'}")
586
- # with c2:
587
- # strengths = summary.get("top_strengths") or []
588
- # st.markdown("**Top Strengths:** " + (", ".join(strengths) if strengths else "β€”"))
589
-
590
- # st.markdown("**Notable Quotes:**")
591
- # for q in (summary.get("notable_quotes") or [])[:3]:
592
- # st.markdown(f"> {q}")
593
-
594
- # with tab_analyses:
595
- # st.subheader("Student Analysis (Markdown)")
596
-
597
- # # Use the folder you defined at top (ANALYSES_DIR), or expose it in the sidebar if you prefer.
598
- # idx = _build_analysis_index(ANALYSES_DIR)
599
-
600
- # if student_choice == "(All)":
601
- # st.info("Pick a specific student on the left to view their analysis.")
602
- # # (Optional) show what's available so you can browse:
603
- # if idx:
604
- # st.caption("Available analyses:")
605
- # st.write(", ".join(sorted({name.title() for name in idx.keys()})))
606
- # else:
607
- # # Normalize the selected student name to match filenames
608
- # norm = _normalize_name(student_choice)
609
- # path = idx.get(norm)
610
-
611
- # # If exact match not found, try simple underscore variant
612
- # if not path:
613
- # alt = student_choice.replace(" ", "_")
614
- # path = idx.get(_normalize_name(alt))
615
-
616
- # if path:
617
- # md = _load_markdown(path)
618
- # if md.strip():
619
- # st.markdown(md, unsafe_allow_html=False)
620
- # # Optional download button
621
- # with open(path, "rb") as f:
622
- # st.download_button(
623
- # "Download analysis (.md)", f,
624
- # file_name=os.path.basename(path), mime="text/markdown"
625
- # )
626
- # else:
627
- # st.warning("Analysis file found but empty.")
628
- # else:
629
- # st.warning(f"No analysis found for **{student_choice}** in `{ANALYSES_DIR}` yet.")
630
- # if idx:
631
- # st.caption("Available analyses:")
632
- # st.write(", ".join(sorted({name.title() for name in idx.keys()})))
633
 
634
 
635
 
 
323
 
324
  st.caption(f"{len(df_final)} line(s) aggregated." if not df_final.empty else "No data.")
325
 
326
+
327
  # ================== Dynamic Stage Summaries (only if student answered that week) ==================
328
  import re
329
  import unicodedata
 
555
  for q in (summary.get("notable_quotes") or [])[:3]:
556
  st.markdown(f"> {q}")
557
  # # ------------------- Output (Tabs) -------------------
558
+ tab_radar, tab_analyses = st.tabs(["πŸ“ˆ Radar", "πŸ“ Analyses"])
559
+
560
+ with tab_radar:
561
+ # Recompute a local copy for the tab (prevents reusing the same figure object)
562
+ df_plot_local = df_final.copy()
563
+ avg_label_local = None
564
+
565
+ if not df_plot_local.empty:
566
+ cols = list(SKILL_GROUPS.keys()) if grouped else SKILLS
567
+ show_cohort_avg = st.toggle("Show cohort average (all students)", value=True, key="toggle_avg_radar")
568
+ if show_cohort_avg:
569
+ avg_vals = df_plot_local[cols].mean()
570
+ avg_row = {"label": "Average (All Students)"}
571
+ avg_row.update({k: float(avg_vals[k]) for k in cols})
572
+ df_plot_local = pd.concat([df_plot_local, pd.DataFrame([avg_row])], ignore_index=True)
573
+ avg_label_local = "Average (All Students)"
574
+
575
+ # Build a fresh figure for the tab or copy if you already built one above:
576
+ fig_tab = plot_radar(df_plot_local, grouped, chart_title, avg_label=avg_label_local)
577
+ # fig_tab = go.Figure(fig) # <- alternative if you already computed `fig` above
578
+
579
+ # Unique key to avoid Plotly id collisions on reruns/tab switches
580
+ key_suffix = f"{student_choice}|{source_choice}|{int(grouped)}|{int(overlay_sources)}"
581
+ st.plotly_chart(fig_tab, use_container_width=True, key=f"radar_tab_{key_suffix}")
582
+
583
+ st.caption(f"{len(df_final)} line(s) aggregated." if not df_final.empty else "No data.")
584
+
585
+ with tab_analyses:
586
+ st.subheader("Student Analysis (Markdown)")
587
+
588
+ # Use the folder you defined at top (ANALYSES_DIR), or expose it in the sidebar if you prefer.
589
+ idx = _build_analysis_index(ANALYSES_DIR)
590
+
591
+ if student_choice == "(All)":
592
+ st.info("Pick a specific student on the left to view their analysis.")
593
+ # (Optional) show what's available so you can browse:
594
+ if idx:
595
+ st.caption("Available analyses:")
596
+ st.write(", ".join(sorted({name.title() for name in idx.keys()})))
597
+ else:
598
+ # Normalize the selected student name to match filenames
599
+ norm = _normalize_name(student_choice)
600
+ path = idx.get(norm)
601
+
602
+ # If exact match not found, try simple underscore variant
603
+ if not path:
604
+ alt = student_choice.replace(" ", "_")
605
+ path = idx.get(_normalize_name(alt))
606
+
607
+ if path:
608
+ md = _load_markdown(path)
609
+ if md.strip():
610
+ st.markdown(md, unsafe_allow_html=False)
611
+ # Optional download button
612
+ with open(path, "rb") as f:
613
+ st.download_button(
614
+ "Download analysis (.md)", f,
615
+ file_name=os.path.basename(path), mime="text/markdown"
616
+ )
617
+ else:
618
+ st.warning("Analysis file found but empty.")
619
+ else:
620
+ st.warning(f"No analysis found for **{student_choice}** in `{ANALYSES_DIR}` yet.")
621
+ if idx:
622
+ st.caption("Available analyses:")
623
+ st.write(", ".join(sorted({name.title() for name in idx.keys()})))
 
 
 
 
 
 
 
 
 
 
624
 
625
 
626