SarahXia0405 commited on
Commit
92b95bb
·
verified ·
1 Parent(s): 471bb76

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -46
app.py CHANGED
@@ -186,18 +186,49 @@ Currently: English & 简体中文.
186
  CUSTOM_CSS = """
187
  /* --- Login Page --- */
188
  .login-container {
189
- max-width: 500px !important; margin: 100px auto !important; padding: 40px !important;
190
- background: #ffffff; border: 1px solid #e5e7eb; border-radius: 12px;
191
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); text-align: center;
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
- .login-btn { background-color: #8B1A1A !important; color: white !important; font-weight: bold !important; margin-top: 20px !important; }
194
 
195
  /* --- Main Header --- */
196
- .header-container { padding: 10px 20px; background-color: #ffffff; border-bottom: 2px solid #f3f4f6; margin-bottom: 15px; display: flex; align-items: center; }
197
- .link-btn { background: transparent !important; border: none !important; box-shadow: none !important; color: #000 !important; text-decoration: underline; font-weight: bold !important; font-size: 12px !important; padding: 0 5px !important; min-width: auto !important; }
198
- .link-btn:hover { color: #cc0000 !important; }
 
 
 
 
 
199
 
200
- /* User Guide */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  .main-user-guide { border: none !important; background: transparent !important; box-shadow: none !important; }
202
  .main-user-guide > .label-wrap { border: none !important; background: transparent !important; padding: 10px 0 !important; }
203
  .main-user-guide > .label-wrap span { font-size: 1.3rem !important; font-weight: 800 !important; color: #111827 !important; }
@@ -207,25 +238,16 @@ CUSTOM_CSS = """
207
  .clean-accordion > .label-wrap span { font-size: 0.9rem !important; font-weight: 500 !important; color: #374151 !important; }
208
  .clean-accordion > .label-wrap:hover { background-color: #f9fafb !important; }
209
 
210
- /* Action Buttons */
211
  .action-btn { font-weight: bold !important; font-size: 0.9rem !important; position: relative; overflow: visible !important; }
212
  .action-btn:hover::before { content: "See User Guide for details"; position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background-color: #333; color: #fff; padding: 5px 10px; border-radius: 5px; font-size: 12px; white-space: nowrap; z-index: 1000; pointer-events: none; opacity: 0; animation: fadeIn 0.2s forwards; }
213
  .action-btn:hover::after { content: ""; position: absolute; bottom: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: #333 transparent transparent transparent; opacity: 0; animation: fadeIn 0.2s forwards; }
214
 
215
- /* Tooltips & Memory Line */
216
  .html-tooltip { border-bottom: 1px dashed #999; cursor: help; position: relative; }
217
  .html-tooltip:hover::before { content: attr(data-tooltip); position: absolute; bottom: 120%; left: 0; background-color: #333; color: #fff; padding: 5px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 100; pointer-events: none; }
218
- .memory-line-box { border: 1px solid #e5e7eb; padding: 12px; border-radius: 8px; background-color: #f9fafb; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
219
 
220
- /* Results Box Style (For Markdown) */
221
- .result-box {
222
- border: 1px solid #e5e7eb;
223
- background: #ffffff;
224
- padding: 10px;
225
- border-radius: 8px;
226
- height: 100%;
227
- }
228
- .result-box .prose { font-size: 0.9rem; }
229
 
230
  @keyframes fadeIn { to { opacity: 1; } }
231
  """
@@ -247,6 +269,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
247
  # ================== Layer 1: Login View ==================
248
  with gr.Group(visible=True) as login_view:
249
  with gr.Column(elem_classes="login-container"):
 
250
  gr.HTML(
251
  f"""
252
  <div style="display:flex; justify-content:center; gap:20px; margin-bottom:20px;">
@@ -257,16 +280,20 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
257
  <p style="color: #666; margin-bottom: 30px;">Your Personalized AI Tutor</p>
258
  """
259
  )
 
260
  login_name = gr.Textbox(label="Student Name", placeholder="Enter your full name", autofocus=True)
261
  login_id = gr.Textbox(label="Student ID / Email", placeholder="Enter your student ID or email")
 
262
  login_btn = gr.Button("Enter Class", elem_classes="login-btn", size="lg")
263
- login_msg = gr.Markdown(visible=False)
 
264
 
265
  # ================== Layer 2: Main App View ==================
266
  with gr.Group(visible=False) as main_view:
267
 
268
- # --- Custom Header ---
269
  with gr.Row(elem_classes="header-container"):
 
270
  with gr.Column(scale=1):
271
  gr.HTML(
272
  f"""
@@ -285,7 +312,9 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
285
  """
286
  )
287
 
 
288
  with gr.Column(scale=1):
 
289
  gr.HTML(
290
  f"""
291
  <div style="display:flex; justify-content:flex-end; margin-bottom: 5px;">
@@ -293,14 +322,18 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
293
  </div>
294
  """
295
  )
 
296
  with gr.Row():
 
297
  with gr.Column(scale=1): pass
 
 
298
  with gr.Column(scale=0, min_width=300):
299
  with gr.Row(elem_classes="no-gap"):
300
  student_info_disp = gr.Markdown(value="", elem_id="student-info")
301
  logout_btn = gr.Button("Log Out", elem_classes="link-btn")
302
 
303
- # --- Main Layout ---
304
  with gr.Row():
305
 
306
  # === Left Sidebar ===
@@ -345,28 +378,25 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
345
  # === Center Main ===
346
  with gr.Column(scale=3):
347
 
348
- # --- Top Control Row: Upload | Controls | Memory Line ---
349
  with gr.Row():
350
-
351
- # Col 1: Upload File (最左)
352
- with gr.Column(scale=2):
353
- syllabus_file = gr.File(
354
- file_types=[".docx", ".pdf", ".pptx"],
355
- file_count="single",
356
- height=160,
357
- label="Upload file (.docx/.pdf/.pptx)"
358
- )
359
-
360
- # Col 2: Controls (中间 - Dropdown & Docs Button)
361
- with gr.Column(scale=1):
362
- # 垂直排列
363
- doc_type = gr.Dropdown(choices=DOC_TYPES, value="Syllabus", label="File type", container=True)
364
- # 增加一点间距
365
- gr.HTML("<div style='height:5px'></div>")
366
- docs_btn = gr.Button("📂 Loaded Docs", size="sm", variant="secondary")
367
-
368
- # Col 3: Memory Line (最右)
369
  with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  with gr.Group(elem_classes="memory-line-box"):
371
  gr.HTML(
372
  f"""
@@ -409,9 +439,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
409
  summary_btn = gr.Button("Summarization", size="sm", elem_classes="action-btn")
410
 
411
  gr.Markdown("### Results")
412
- # 【修改点】:改用 Markdown 组件来显示格式化文本,外面包裹一个 Group 模拟 Box 样式
413
- with gr.Group(elem_classes="result-box"):
414
- result_display = gr.Markdown(value="Results will appear here...", label="Generated Content")
415
 
416
  # ================== Logic & Events ==================
417
 
@@ -419,6 +447,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
419
  if not name.strip() or not id_val.strip():
420
  return {login_msg: gr.update(value="❌ Please enter both Name and ID", visible=True)}
421
 
 
422
  welcome_text = f"🎓 **{name}** ({id_val})"
423
  return {
424
  login_view: gr.update(visible=False),
@@ -430,6 +459,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
430
  }
431
 
432
  def perform_logout():
 
433
  return {
434
  login_view: gr.update(visible=True),
435
  main_view: gr.update(visible=False),
@@ -449,6 +479,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
449
  outputs=[login_view, main_view, login_name, login_id, student_info_disp]
450
  )
451
 
 
452
  def update_course_and_rag(file, doc_type_val):
453
  topics = extract_course_topics_from_file(file, doc_type_val)
454
  rag_chunks = build_rag_chunks_from_file(file, doc_type_val)
 
186
  CUSTOM_CSS = """
187
  /* --- Login Page --- */
188
  .login-container {
189
+ max-width: 500px !important;
190
+ margin: 100px auto !important;
191
+ padding: 40px !important;
192
+ background: #ffffff;
193
+ border: 1px solid #e5e7eb;
194
+ border-radius: 12px;
195
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
196
+ text-align: center;
197
+ }
198
+ .login-btn {
199
+ background-color: #8B1A1A !important;
200
+ color: white !important;
201
+ font-weight: bold !important;
202
+ margin-top: 20px !important;
203
  }
 
204
 
205
  /* --- Main Header --- */
206
+ .header-container {
207
+ padding: 10px 20px;
208
+ background-color: #ffffff;
209
+ border-bottom: 2px solid #f3f4f6;
210
+ margin-bottom: 15px;
211
+ display: flex;
212
+ align-items: center;
213
+ }
214
 
215
+ /* 伪装成 Link 的 Button (Log Out) */
216
+ .link-btn {
217
+ background: transparent !important;
218
+ border: none !important;
219
+ box-shadow: none !important;
220
+ color: #000 !important;
221
+ text-decoration: underline;
222
+ font-weight: bold !important;
223
+ font-size: 12px !important;
224
+ padding: 0 5px !important;
225
+ min-width: auto !important;
226
+ }
227
+ .link-btn:hover {
228
+ color: #cc0000 !important;
229
+ }
230
+
231
+ /* User Guide 样式 */
232
  .main-user-guide { border: none !important; background: transparent !important; box-shadow: none !important; }
233
  .main-user-guide > .label-wrap { border: none !important; background: transparent !important; padding: 10px 0 !important; }
234
  .main-user-guide > .label-wrap span { font-size: 1.3rem !important; font-weight: 800 !important; color: #111827 !important; }
 
238
  .clean-accordion > .label-wrap span { font-size: 0.9rem !important; font-weight: 500 !important; color: #374151 !important; }
239
  .clean-accordion > .label-wrap:hover { background-color: #f9fafb !important; }
240
 
241
+ /* Action 按钮 & Tooltip */
242
  .action-btn { font-weight: bold !important; font-size: 0.9rem !important; position: relative; overflow: visible !important; }
243
  .action-btn:hover::before { content: "See User Guide for details"; position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background-color: #333; color: #fff; padding: 5px 10px; border-radius: 5px; font-size: 12px; white-space: nowrap; z-index: 1000; pointer-events: none; opacity: 0; animation: fadeIn 0.2s forwards; }
244
  .action-btn:hover::after { content: ""; position: absolute; bottom: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: #333 transparent transparent transparent; opacity: 0; animation: fadeIn 0.2s forwards; }
245
 
 
246
  .html-tooltip { border-bottom: 1px dashed #999; cursor: help; position: relative; }
247
  .html-tooltip:hover::before { content: attr(data-tooltip); position: absolute; bottom: 120%; left: 0; background-color: #333; color: #fff; padding: 5px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 100; pointer-events: none; }
 
248
 
249
+ /* Memory Line Box */
250
+ .memory-line-box { border: 1px solid #e5e7eb; padding: 12px; border-radius: 8px; background-color: #f9fafb; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
 
 
 
 
 
 
 
251
 
252
  @keyframes fadeIn { to { opacity: 1; } }
253
  """
 
269
  # ================== Layer 1: Login View ==================
270
  with gr.Group(visible=True) as login_view:
271
  with gr.Column(elem_classes="login-container"):
272
+ # Logo Area
273
  gr.HTML(
274
  f"""
275
  <div style="display:flex; justify-content:center; gap:20px; margin-bottom:20px;">
 
280
  <p style="color: #666; margin-bottom: 30px;">Your Personalized AI Tutor</p>
281
  """
282
  )
283
+
284
  login_name = gr.Textbox(label="Student Name", placeholder="Enter your full name", autofocus=True)
285
  login_id = gr.Textbox(label="Student ID / Email", placeholder="Enter your student ID or email")
286
+
287
  login_btn = gr.Button("Enter Class", elem_classes="login-btn", size="lg")
288
+
289
+ login_msg = gr.Markdown(visible=False) # 错误提示占位
290
 
291
  # ================== Layer 2: Main App View ==================
292
  with gr.Group(visible=False) as main_view:
293
 
294
+ # --- Custom Header (Using Row for Alignment) ---
295
  with gr.Row(elem_classes="header-container"):
296
+ # Left: Mascot & Title
297
  with gr.Column(scale=1):
298
  gr.HTML(
299
  f"""
 
312
  """
313
  )
314
 
315
+ # Right: Hanbridge Logo + Student Info + Logout
316
  with gr.Column(scale=1):
317
+ # 顶部放 Logo,居右
318
  gr.HTML(
319
  f"""
320
  <div style="display:flex; justify-content:flex-end; margin-bottom: 5px;">
 
322
  </div>
323
  """
324
  )
325
+ # 下面放 Info 和 Logout 按钮,使用 Row 紧凑排列
326
  with gr.Row():
327
+ # 这里放一个空的 Column 把内容挤到右边
328
  with gr.Column(scale=1): pass
329
+
330
+ # 真正的内容在右边
331
  with gr.Column(scale=0, min_width=300):
332
  with gr.Row(elem_classes="no-gap"):
333
  student_info_disp = gr.Markdown(value="", elem_id="student-info")
334
  logout_btn = gr.Button("Log Out", elem_classes="link-btn")
335
 
336
+ # --- Main Layout (Sidebar + Center + Right) ---
337
  with gr.Row():
338
 
339
  # === Left Sidebar ===
 
378
  # === Center Main ===
379
  with gr.Column(scale=3):
380
 
381
+ # Upload & Memory Line
382
  with gr.Row():
383
+ # [Left] Upload
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  with gr.Column(scale=2):
385
+ with gr.Row():
386
+ with gr.Column(scale=3):
387
+ # 调大高度 height=160
388
+ syllabus_file = gr.File(
389
+ file_types=[".docx", ".pdf", ".pptx"],
390
+ file_count="single",
391
+ height=160,
392
+ label="Upload file (.docx/.pdf/.pptx)"
393
+ )
394
+ with gr.Column(scale=1):
395
+ doc_type = gr.Dropdown(choices=DOC_TYPES, value="Syllabus", label="", container=False)
396
+ docs_btn = gr.Button("📂 Loaded Docs", size="sm", variant="secondary")
397
+
398
+ # [Right] Memory Line
399
+ with gr.Column(scale=1):
400
  with gr.Group(elem_classes="memory-line-box"):
401
  gr.HTML(
402
  f"""
 
439
  summary_btn = gr.Button("Summarization", size="sm", elem_classes="action-btn")
440
 
441
  gr.Markdown("### Results")
442
+ result_display = gr.Textbox(label="Generated Content", lines=15, placeholder="Results...", show_label=False)
 
 
443
 
444
  # ================== Logic & Events ==================
445
 
 
447
  if not name.strip() or not id_val.strip():
448
  return {login_msg: gr.update(value="❌ Please enter both Name and ID", visible=True)}
449
 
450
+ # 登录成功:更新Header信息,隐藏登录页,显示主页
451
  welcome_text = f"🎓 **{name}** ({id_val})"
452
  return {
453
  login_view: gr.update(visible=False),
 
459
  }
460
 
461
  def perform_logout():
462
+ # 登出:清空输入,隐藏主页,显示登录页
463
  return {
464
  login_view: gr.update(visible=True),
465
  main_view: gr.update(visible=False),
 
479
  outputs=[login_view, main_view, login_name, login_id, student_info_disp]
480
  )
481
 
482
+ # Existing Main App Logic
483
  def update_course_and_rag(file, doc_type_val):
484
  topics = extract_course_topics_from_file(file, doc_type_val)
485
  rag_chunks = build_rag_chunks_from_file(file, doc_type_val)