Spaces:
Sleeping
Sleeping
import gradio as gr | |
def create_assignment_ui(user_data, assignment_service, submission_service): | |
with gr.Blocks() as assignment_interface: | |
with gr.Tab("老師|建立作業"): | |
with gr.Row(): | |
with gr.Column(): | |
with gr.Row(): | |
gr.Markdown("### 作業資訊") | |
with gr.Row(): | |
assignment_topic = gr.Textbox(label="題目(必填)") | |
assignment_type_list = [ | |
"中文寫作 AI 批改", | |
"英文寫作 AI 批改" | |
] | |
assignment_type = gr.Radio(choices=assignment_type_list, label="選擇類型") | |
assignment_grade = gr.Radio(["一年級", "二年級", "三年級", "四年級", "五年級", "六年級"], label="選擇年級", visible=False) | |
with gr.Row(): | |
gr.Markdown("### 內容規範") | |
with gr.Row(): | |
assignment_introduction = gr.TextArea(label="寫作引文") | |
assignment_description = gr.TextArea(label="作業說明") | |
with gr.Row(): | |
gr.Markdown("### 繳交規範") | |
with gr.Row(): | |
assignment_submission_deadline = gr.DateTime(label="提交截止日期") | |
assignment_attach_materials = gr.Textbox(label="附件參考", placeholder='[{"type": "video", "url": "link1", "description": "描述"}]') | |
with gr.Row(): | |
assignment_create_button = gr.Button("建立作業") | |
assignment_metadata = gr.JSON(label="作業元數據", visible=False) | |
assignment_data = gr.JSON(label="作業數據", visible=False) | |
assignment_url = gr.Textbox(label="作業指派連結", interactive=False, show_copy_button=True) | |
assignment_id_display_teacher = gr.Textbox(label="作業 ID", interactive=False, visible=False) | |
def update_gr_assignment_url(assignment_data): | |
return assignment_data['assignment_url'] | |
def update_gr_assignment_id(assignment_data): | |
return assignment_data['assignment_id'] | |
assignment_create_button.click( | |
assignment_service.create_assignment_metadata, | |
inputs=[ | |
assignment_type, | |
assignment_grade, | |
assignment_topic, | |
assignment_introduction, | |
assignment_description, | |
assignment_attach_materials, | |
assignment_submission_deadline | |
], | |
outputs=[assignment_metadata] | |
).then( | |
assignment_service.create_assignment, | |
inputs=[user_data, assignment_type, assignment_metadata], | |
outputs=[assignment_data] | |
).then( | |
update_gr_assignment_url, | |
inputs=[assignment_data], | |
outputs=[assignment_url] | |
).then( | |
update_gr_assignment_id, | |
inputs=[assignment_data], | |
outputs=[assignment_id_display_teacher] | |
) | |
with gr.Tab("老師|作業列表") as assignment_list_tab: | |
with gr.Row(): | |
with gr.Column(scale=1): | |
get_all_assignments_button = gr.Button("獲取所有作業") | |
assignment_list = gr.Radio([], label="作業列表", interactive=True) | |
with gr.Column(scale=2): | |
assignment_data = gr.JSON(label="作業內容", visible=False) | |
assignment_data_html = gr.HTML() | |
with gr.Row(): | |
with gr.Column(scale=1): | |
submissions_list_json = gr.JSON(visible=False) | |
submissions_list_radio = gr.Radio([], label="已提交的作業學生", interactive=True) | |
with gr.Column(scale=2): | |
submission_data_json = gr.JSON(label="提交內容", visible=False) | |
submission_data_html = gr.HTML() | |
def init_assignment_list_data(assignment_list_value=None): | |
assignment_list = gr.update(value=assignment_list_value) | |
assignment_data = gr.update(value=None) | |
assignment_data_html = gr.update(value=None) | |
submissions_list_json = gr.update(value=None) | |
submissions_list_radio = gr.update(choices=[], value=None) | |
submission_data_json = gr.update(value=None) | |
submission_data_html = gr.update(value=None) | |
return assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html | |
def update_assignment_data_html(assignment_data): | |
html = f""" | |
<div style="background-color: #f8f9fa; padding: 30px; border-radius: 15px; font-family: 'Helvetica', sans-serif;"> | |
<h2 style="color: #007bff; font-size: 28px; margin-bottom: 20px;">✨ 作業詳情</h2> | |
<div style="background-color: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);"> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">🏷️ 作業類型</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['assignment_type']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">📝 作業題目</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['topic']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">🗓️ 日期</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['timestamp']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #28a745; margin-bottom: 5px;">📖 寫作引文</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['introduction']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #ffc107; margin-bottom: 5px;">ℹ️ 作業說明</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['description']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #17a2b8; margin-bottom: 5px;">🔗 作業連結</div> | |
<a href="{assignment_data['assignment_url']}" target="_blank" style="display: inline-block; padding: 10px 15px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px; transition: background-color 0.3s;" onmouseover="this.style.backgroundColor='#0056b3'" onmouseout="this.style.backgroundColor='#007bff'">點擊前往作業</a> | |
</div> | |
<div> | |
<div style="font-weight: bold; color: #dc3545; margin-bottom: 5px;">📎 附加材料</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['attach_materials']}</div> | |
</div> | |
</div> | |
</div> | |
""" | |
return gr.update(value=html) | |
def update_submissions_list_radio(submission_ids): | |
choices = [] | |
for submission_id in submission_ids: | |
submission_data = submission_service.get_submission_from_gcs(submission_id) | |
choice_text = f"{submission_data['student_name']}" | |
choice = (choice_text, submission_id) | |
choices.append(choice) | |
return gr.update(choices=choices) | |
def update_submission_data_html(submission_json): | |
html = f""" | |
<div style="background-color: #f8f9fa; padding: 30px; border-radius: 15px; font-family: 'Helvetica', sans-serif;"> | |
<h2 style="color: #007bff; font-size: 28px; margin-bottom: 20px;">📝 學生回傳作業</h2> | |
<div style="background-color: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);"> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">👤 學生姓名</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{submission_json['student_name']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">🆔 學生帳號</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{submission_json['student_id']}</div> | |
</div> | |
<div style="margin-bottom: 20px;"> | |
<div style="font-weight: bold; color: #28a745; margin-bottom: 5px;">📄 回傳内容</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px; white-space: pre-wrap;">{submission_json['submission_data']['content']}</div> | |
</div> | |
<div> | |
<div style="font-weight: bold; color: #17a2b8; margin-bottom: 5px;">🕒 回傳日期</div> | |
<div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{submission_json['timestamp']}</div> | |
</div> | |
</div> | |
</div> | |
""" | |
return gr.update(value=html) | |
get_all_assignments_button.click( | |
assignment_service.update_assignment_list, | |
inputs=[user_data], | |
outputs=assignment_list | |
).then( | |
fn=init_assignment_list_data, | |
inputs=[], | |
outputs=[assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html] | |
) | |
assignment_list.select( | |
fn=init_assignment_list_data, | |
inputs=[assignment_list], | |
outputs=[assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html] | |
).then( | |
assignment_service.get_assignment, | |
inputs=[assignment_list], | |
outputs=[assignment_data] | |
).then( | |
fn=update_assignment_data_html, | |
inputs=[assignment_data], | |
outputs=[assignment_data_html] | |
).then( | |
assignment_service.get_assignment_submissions, | |
inputs=[assignment_list], | |
outputs=[submissions_list_json] | |
).then( | |
fn=update_submissions_list_radio, | |
inputs=[submissions_list_json], | |
outputs=[submissions_list_radio] | |
) | |
submissions_list_radio.select( | |
submission_service.get_submission_from_gcs, | |
inputs=[submissions_list_radio], | |
outputs=submission_data_json | |
).then( | |
fn=update_submission_data_html, | |
inputs=[submission_data_json], | |
outputs=[submission_data_html] | |
) | |
with gr.Tab("學生|模擬繳交"): | |
with gr.Row(): | |
with gr.Column(): | |
assignment_id_input_student = gr.Textbox(label="作業 ID") | |
get_assignment_button = gr.Button("獲取作業") | |
assignment_display = gr.JSON(label="作業內容") | |
get_assignment_button.click( | |
assignment_service.get_assignment, | |
inputs=[assignment_id_input_student], | |
outputs=assignment_display | |
) | |
with gr.Row(): | |
with gr.Column(): | |
student_name_input = gr.Textbox(label="學生姓名") | |
submission_input = gr.Textbox(label="文字輸入") | |
submit_button = gr.Button("繳交作業") | |
submission_status = gr.Textbox(label="繳交狀態", interactive=False) | |
submit_button.click( | |
submission_service.submit_assignment, | |
inputs=[assignment_id_input_student, user_data, student_name_input, submission_input], | |
outputs=submission_status | |
) | |
with gr.Row(): | |
with gr.Column(): | |
load_submissions_button = gr.Button("獲取提交的作業") | |
submissions_radio = gr.Radio([], label="提交的作業", interactive=True) | |
submission_display = gr.JSON(label="作業內容") | |
load_submissions_button.click( | |
submission_service.update_submission_list, | |
inputs=[user_data], | |
outputs=submissions_radio | |
) | |
submissions_radio.select( | |
submission_service.get_submission_from_gcs, | |
inputs=[submissions_radio], | |
outputs=submission_display | |
) | |
return assignment_interface |