lanna_lalala;- commited on
Commit
9d421af
Β·
1 Parent(s): 2f3fcdf

lesson css try

Browse files
Files changed (1) hide show
  1. phase/Student_view/lesson.py +131 -71
phase/Student_view/lesson.py CHANGED
@@ -18,6 +18,72 @@ USE_LOCAL_DB = os.getenv("DISABLE_DB", "1") != "1"
18
 
19
  FALLBACK_TAG = "<!--fallback-->"
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  # --- Load external CSS (optional) ---
22
  def load_css(file_name: str):
23
  try:
@@ -38,7 +104,6 @@ _SS_DEFAULTS = {
38
  }
39
 
40
 
41
-
42
  def _ensure_state():
43
  for k, v in _SS_DEFAULTS.items():
44
  if k not in st.session_state:
@@ -418,6 +483,9 @@ def _get_topics(level: str, module_id: int) -> List[Tuple[str, str]]:
418
 
419
 
420
  def _render_lesson():
 
 
 
421
  """Render the lesson interface"""
422
  level = st.session_state.get("level", "beginner")
423
  module_id = st.session_state.get("module_id")
@@ -570,7 +638,27 @@ def _render_lesson():
570
  with col_main:
571
  t_title, t_text = topics[topic_idx]
572
 
573
- st.markdown(f"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
  <div class="lesson-card">
575
  <div class="unit-header">
576
  <span class="unit-info">Unit {topic_idx + 1} of {len(topics)}</span>
@@ -580,44 +668,20 @@ def _render_lesson():
580
  </div>
581
  </div>
582
  <div class="lesson-content">
583
- """, unsafe_allow_html=True)
584
-
585
- if t_text:
586
- st.markdown(t_text.strip(), unsafe_allow_html=True)
587
- else:
588
- st.info("Content coming soon.")
589
-
590
- if t_text:
591
- takeaways = _extract_takeaways(t_text)
592
- if takeaways:
593
- st.markdown("""
594
- <div class="takeaways-section" style="min-height: 150px;">
595
- <div class="takeaways-header">
596
- <span style="color: #10b981;">●</span>
597
- <span>Key Takeaways</span>
598
- </div>
599
- """, unsafe_allow_html=True)
600
-
601
- for takeaway in takeaways:
602
- st.markdown(f"""
603
- <div class="takeaway-item">
604
- <span class="takeaway-check">βœ“</span>
605
- <span>{takeaway}</span>
606
- </div>
607
- """, unsafe_allow_html=True)
608
-
609
- st.markdown("</div>", unsafe_allow_html=True)
610
-
611
- st.markdown("</div></div>", unsafe_allow_html=True)
612
 
 
613
  st.markdown('<div class="nav-buttons">', unsafe_allow_html=True)
614
-
615
  col1, col2, col3 = st.columns([1, 1, 1])
616
  with col1:
617
  if st.button("← Previous", disabled=topic_idx == 0, key="prev_btn"):
618
  st.session_state.topic_idx -= 1
619
  st.rerun()
620
-
621
  with col3:
622
  is_last = topic_idx >= len(topics) - 1
623
  if is_last:
@@ -631,57 +695,53 @@ def _render_lesson():
631
  if st.button("Next Unit β†’", key="next_btn"):
632
  st.session_state.topic_idx += 1
633
  st.rerun()
634
-
635
  st.markdown('</div>', unsafe_allow_html=True)
636
 
637
  with col_sidebar:
638
- # Module Progress Card
639
- st.markdown("""
 
 
 
640
  <div class="sidebar-card" style="min-height: 120px;">
641
  <h4>Module Progress</h4>
642
- """, unsafe_allow_html=True)
643
-
644
- progress = (topic_idx + 1) / max(1, len(topics))
645
- st.progress(progress)
646
- st.markdown(f"<p style='color: #6b7280; font-size: 0.875rem; margin-top: 0.5rem;'>Unit {topic_idx + 1} of {len(topics)}</p>", unsafe_allow_html=True)
647
-
648
- st.markdown("</div>", unsafe_allow_html=True)
649
-
650
- # Module Units Card
651
- st.markdown("""
652
- <div class="sidebar-card" style="min-height: 300px;">
653
- <h4>Module Units</h4>
654
- """, unsafe_allow_html=True)
655
-
656
  for i, (tt, _) in enumerate(topics):
657
- is_current = i == topic_idx
658
- is_completed = i < topic_idx
659
-
660
- if is_current:
661
- st.markdown(f"""
662
  <div class="unit-item">
663
- <span style="background: #10b981; color: white; width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.75rem;">●</span>
 
664
  <span class="unit-active">{tt}</span>
665
- </div>
666
- """, unsafe_allow_html=True)
667
- elif is_completed:
668
- st.markdown(f"""
669
  <div class="unit-item">
670
- <span style="color: #10b981; font-size: 1.1rem;">βœ“</span>
671
- <span style="color: #374151;">{tt}</span>
672
- </div>
673
- """, unsafe_allow_html=True)
674
  else:
675
- st.markdown(f"""
676
  <div class="unit-item">
677
- <span style="background: #e5e7eb; color: #9ca3af; width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.75rem;">β—‹</span>
 
678
  <span class="unit-inactive">{tt}</span>
679
- </div>
680
- """, unsafe_allow_html=True)
681
-
682
- st.markdown("</div>", unsafe_allow_html=True)
683
 
684
- # Back to modules button
685
  if st.button("← Back to Modules", key="back_modules"):
686
  st.session_state.mode = "catalog"
687
  st.session_state.module_id = None
 
18
 
19
  FALLBACK_TAG = "<!--fallback-->"
20
 
21
+
22
+ # ---- NEW: minimal Markdown -> HTML helper (keeps cards as single HTML blocks)
23
+ def _md_to_html(text: str) -> str:
24
+ """
25
+ Best-effort conversion so markdown-like lesson text can live *inside* a single HTML block.
26
+ Uses python-markdown if available; otherwise a tiny fallback that handles paragraphs + bullets.
27
+ """
28
+ if not text:
29
+ return ""
30
+ try:
31
+ # If python-markdown is available, use it for better fidelity.
32
+ from markdown import markdown as _mk
33
+ return _mk(text, extensions=["extra", "sane_lists"])
34
+ except Exception:
35
+ # Fallback: paragraphs + simple lists
36
+ lines = text.strip().splitlines()
37
+ html_parts = []
38
+ in_ul = False
39
+
40
+ def close_ul():
41
+ nonlocal in_ul
42
+ if in_ul:
43
+ html_parts.append("</ul>")
44
+ in_ul = False
45
+
46
+ for ln in lines:
47
+ s = ln.rstrip()
48
+ if not s:
49
+ close_ul()
50
+ html_parts.append("<p></p>")
51
+ continue
52
+
53
+ # Headings (#, ##, ###) basic support
54
+ if s.startswith("### "):
55
+ close_ul()
56
+ html_parts.append(f"<h3>{s[4:].strip()}</h3>")
57
+ continue
58
+ if s.startswith("## "):
59
+ close_ul()
60
+ html_parts.append(f"<h2>{s[3:].strip()}</h2>")
61
+ continue
62
+ if s.startswith("# "):
63
+ close_ul()
64
+ html_parts.append(f"<h1>{s[2:].strip()}</h1>")
65
+ continue
66
+
67
+ # Bullet lines
68
+ bullet_prefixes = ("- ", "* ", "β€’ ", "– ")
69
+ if s.startswith(bullet_prefixes):
70
+ if not in_ul:
71
+ html_parts.append("<ul>")
72
+ in_ul = True
73
+ html_parts.append(f"<li>{s[2:].strip()}</li>")
74
+ continue
75
+
76
+ # Regular paragraph
77
+ close_ul()
78
+ # light bold/italic
79
+ p = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", s)
80
+ p = re.sub(r"\*(.+?)\*", r"<em>\1</em>", p)
81
+ html_parts.append(f"<p>{p}</p>")
82
+
83
+ close_ul()
84
+ return "\n".join(html_parts)
85
+
86
+
87
  # --- Load external CSS (optional) ---
88
  def load_css(file_name: str):
89
  try:
 
104
  }
105
 
106
 
 
107
  def _ensure_state():
108
  for k, v in _SS_DEFAULTS.items():
109
  if k not in st.session_state:
 
483
 
484
 
485
  def _render_lesson():
486
+ ensure_quiz_state()
487
+ # make sure quiz keys exist
488
+
489
  """Render the lesson interface"""
490
  level = st.session_state.get("level", "beginner")
491
  module_id = st.session_state.get("module_id")
 
638
  with col_main:
639
  t_title, t_text = topics[topic_idx]
640
 
641
+ # ---- CHANGED: Build the entire lesson card in ONE HTML render
642
+ lesson_html_text = _md_to_html((t_text or "").strip())
643
+
644
+ takeaways_html = ""
645
+ if t_text:
646
+ takeaways = _extract_takeaways(t_text)
647
+ if takeaways:
648
+ takeaways_html = (
649
+ '<div class="takeaways-section" style="min-height: 150px;">'
650
+ ' <div class="takeaways-header">'
651
+ ' <span style="color: #10b981;">●</span>'
652
+ ' <span>Key Takeaways</span>'
653
+ ' </div>'
654
+ + "".join(
655
+ f'<div class="takeaway-item"><span class="takeaway-check">βœ“</span><span>{st.escape_markdown(x)}</span></div>'
656
+ for x in takeaways
657
+ )
658
+ + "</div>"
659
+ )
660
+
661
+ card_html = f"""
662
  <div class="lesson-card">
663
  <div class="unit-header">
664
  <span class="unit-info">Unit {topic_idx + 1} of {len(topics)}</span>
 
668
  </div>
669
  </div>
670
  <div class="lesson-content">
671
+ {lesson_html_text}
672
+ </div>
673
+ {takeaways_html}
674
+ </div>
675
+ """
676
+ st.markdown(card_html, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
 
678
+ # Navigation buttons (stay as Streamlit widgets)
679
  st.markdown('<div class="nav-buttons">', unsafe_allow_html=True)
 
680
  col1, col2, col3 = st.columns([1, 1, 1])
681
  with col1:
682
  if st.button("← Previous", disabled=topic_idx == 0, key="prev_btn"):
683
  st.session_state.topic_idx -= 1
684
  st.rerun()
 
685
  with col3:
686
  is_last = topic_idx >= len(topics) - 1
687
  if is_last:
 
695
  if st.button("Next Unit β†’", key="next_btn"):
696
  st.session_state.topic_idx += 1
697
  st.rerun()
 
698
  st.markdown('</div>', unsafe_allow_html=True)
699
 
700
  with col_sidebar:
701
+ # ---- CHANGED: Render sidebar progress as a single HTML block (so it's inside the card)
702
+ progress = (topic_idx + 1) / max(1, len(topics))
703
+ progress_pct = int(progress * 100)
704
+
705
+ progress_html = f"""
706
  <div class="sidebar-card" style="min-height: 120px;">
707
  <h4>Module Progress</h4>
708
+ <div style="width:100%;height:10px;background:#e5e7eb;border-radius:8px;overflow:hidden;">
709
+ <div style="height:10px;width:{progress_pct}%;background:#10b981;"></div>
710
+ </div>
711
+ <p style="color:#6b7280;font-size:0.875rem;margin-top:0.5rem;">
712
+ Unit {topic_idx + 1} of {len(topics)}
713
+ </p>
714
+ </div>
715
+ """
716
+ st.markdown(progress_html, unsafe_allow_html=True)
717
+
718
+ # ---- CHANGED: Render the "Module Units" list as one HTML block too
719
+ units_html = '<div class="sidebar-card" style="min-height: 300px;"><h4>Module Units</h4>'
 
 
720
  for i, (tt, _) in enumerate(topics):
721
+ if i == topic_idx:
722
+ units_html += f"""
 
 
 
723
  <div class="unit-item">
724
+ <span style="background:#10b981;color:white;width:20px;height:20px;border-radius:50%;
725
+ display:flex;align-items:center;justify-content:center;font-size:0.75rem;">●</span>
726
  <span class="unit-active">{tt}</span>
727
+ </div>"""
728
+ elif i < topic_idx:
729
+ units_html += f"""
 
730
  <div class="unit-item">
731
+ <span style="color:#10b981;font-size:1.1rem;">βœ“</span>
732
+ <span style="color:#374151;">{tt}</span>
733
+ </div>"""
 
734
  else:
735
+ units_html += f"""
736
  <div class="unit-item">
737
+ <span style="background:#e5e7eb;color:#9ca3af;width:20px;height:20px;border-radius:50%;
738
+ display:flex;align-items:center;justify-content:center;font-size:0.75rem;">β—‹</span>
739
  <span class="unit-inactive">{tt}</span>
740
+ </div>"""
741
+ units_html += "</div>"
742
+ st.markdown(units_html, unsafe_allow_html=True)
 
743
 
744
+ # Back to modules button (Streamlit widget outside HTML block)
745
  if st.button("← Back to Modules", key="back_modules"):
746
  st.session_state.mode = "catalog"
747
  st.session_state.module_id = None