youngtsai commited on
Commit
96c172b
·
1 Parent(s): 25cbf06

def update_submission_data_html(submission_json):

Browse files
Files changed (4) hide show
  1. README.md +1 -1
  2. assignment_service.py +27 -3
  3. assignment_ui.py +122 -49
  4. requirements.txt +1 -1
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 📚
4
  colorFrom: red
5
  colorTo: blue
6
  sdk: gradio
7
- sdk_version: 4.37.2
8
  app_file: app.py
9
  pinned: false
10
  ---
 
4
  colorFrom: red
5
  colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 4.41.0
8
  app_file: app.py
9
  pinned: false
10
  ---
assignment_service.py CHANGED
@@ -16,7 +16,7 @@ class AssignmentService:
16
  if not self.gcs_service.check_file_exists(self.bucket_name, file_name):
17
  return assignment_id
18
 
19
- def create_assignment_metadata(self, assignment_type, grade, topic, introduction, description, url, attach_materials, submission_deadline):
20
  if assignment_type == "中文寫作 AI 批改":
21
  metadata = {
22
  "assignment_type": assignment_type,
@@ -24,7 +24,6 @@ class AssignmentService:
24
  "topic": topic,
25
  "introduction": introduction,
26
  "description": description,
27
- "url": url,
28
  "attach_materials": attach_materials,
29
  "submission_deadline": submission_deadline
30
  }
@@ -34,17 +33,42 @@ class AssignmentService:
34
  def create_assignment(self, user_data, assignment_type, metadata):
35
  assignment_id = self.create_assignment_id()
36
  timestamp_now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 
 
 
 
 
 
 
 
37
  new_assignment = {
38
  "assignment_id": assignment_id,
39
  "assigner_data": user_data,
40
  "assignment_type": assignment_type,
41
  "metadata": metadata,
 
42
  "submission_ids": [],
43
  "timestamp": timestamp_now
44
  }
45
  self.save_assignment_to_gcs(new_assignment)
46
  self.save_user_assignment_to_gcs(user_data, assignment_id)
47
- return assignment_id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  def save_assignment_to_gcs(self, assignment):
50
  file_name = f"assignments/{assignment['assignment_id']}.json"
 
16
  if not self.gcs_service.check_file_exists(self.bucket_name, file_name):
17
  return assignment_id
18
 
19
+ def create_assignment_metadata(self, assignment_type, grade, topic, introduction, description, attach_materials, submission_deadline):
20
  if assignment_type == "中文寫作 AI 批改":
21
  metadata = {
22
  "assignment_type": assignment_type,
 
24
  "topic": topic,
25
  "introduction": introduction,
26
  "description": description,
 
27
  "attach_materials": attach_materials,
28
  "submission_deadline": submission_deadline
29
  }
 
33
  def create_assignment(self, user_data, assignment_type, metadata):
34
  assignment_id = self.create_assignment_id()
35
  timestamp_now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
36
+ host_url = "https://www.junyiacademy.org/event/jutor_write_2024/?__theme=light"
37
+ language_mapping = {
38
+ "寫作 AI 批改": "chinese",
39
+ "英文寫作 AI 批改": "english"
40
+ }
41
+ language = language_mapping.get(assignment_type, "")
42
+
43
+ assignment_url = f"{host_url}&language={language}&assignment={assignment_id}"
44
  new_assignment = {
45
  "assignment_id": assignment_id,
46
  "assigner_data": user_data,
47
  "assignment_type": assignment_type,
48
  "metadata": metadata,
49
+ "assignment_url": assignment_url,
50
  "submission_ids": [],
51
  "timestamp": timestamp_now
52
  }
53
  self.save_assignment_to_gcs(new_assignment)
54
  self.save_user_assignment_to_gcs(user_data, assignment_id)
55
+ return new_assignment
56
+
57
+ def get_assignment_url(self, assignment_id):
58
+ assignment_data = self.get_assignment(assignment_id)
59
+ if isinstance(assignment_data, str):
60
+ print(f"错误:无法获取作业数据。返回的数据:{assignment_data}")
61
+ return None
62
+
63
+ assignment_url = assignment_data.get("assignment_url")
64
+ if not assignment_url:
65
+ print(f"警告:作业 {assignment_id} 没有 URL")
66
+ return None
67
+
68
+ return assignment_url
69
+
70
+ def update_assignment(self, assignment_id, assignment_data):
71
+ self.gcs_service.upload_json_string(self.bucket_name, f"assignments/{assignment_id}.json", json.dumps(assignment_data))
72
 
73
  def save_assignment_to_gcs(self, assignment):
74
  file_name = f"assignments/{assignment['assignment_id']}.json"
assignment_ui.py CHANGED
@@ -5,29 +5,63 @@ def create_assignment_ui(user_data, assignment_service, submission_service):
5
  with gr.Tab("老師|建立作業"):
6
  with gr.Row():
7
  with gr.Column():
8
- assignment_type_list = [
9
- "中文寫作 AI 批改",
10
- "英文寫作 AI 批改"
11
- ]
12
- assignment_type = gr.Radio(choices=assignment_type_list, label="選擇類型")
13
- grade = gr.Radio(["一年級", "二年級", "三年級", "四年級", "五年級", "六年級"], label="選擇年級")
14
- topic = gr.Textbox(label="題目")
15
- introduction = gr.Textbox(label="寫作引文(非必填)")
16
- description = gr.Textbox(label="作業說明")
17
- url = gr.Textbox(label="作業链接")
18
- attach_materials = gr.Textbox(label="附加材料 (JSON 格式)", placeholder='[{"type": "video", "url": "link1", "description": "描述"}]')
19
- submission_deadline = gr.Textbox(label="提交截止日期", placeholder="2024-09-01T23:59:59Z")
20
- create_button = gr.Button("建立作業")
21
- assignment_id_display_teacher = gr.Textbox(label="作業 ID", interactive=False)
22
- assignment_metadata = gr.JSON(label="作業元數據")
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- create_button.click(
 
 
 
 
 
 
25
  assignment_service.create_assignment_metadata,
26
- inputs=[assignment_type, grade, topic, introduction, description, url, attach_materials, submission_deadline],
 
 
 
 
 
 
 
 
27
  outputs=[assignment_metadata]
28
  ).then(
29
  assignment_service.create_assignment,
30
  inputs=[user_data, assignment_type, assignment_metadata],
 
 
 
 
 
 
 
 
31
  outputs=[assignment_id_display_teacher]
32
  )
33
 
@@ -38,40 +72,66 @@ def create_assignment_ui(user_data, assignment_service, submission_service):
38
  assignment_list = gr.Radio([], label="作業列表", interactive=True)
39
  with gr.Column(scale=2):
40
  assignment_data = gr.JSON(label="作業內容", visible=False)
41
- assignment_data_markdown = gr.Markdown(label="作業內容", show_label=True)
42
  with gr.Row():
43
  with gr.Column(scale=1):
44
  submissions_list_json = gr.JSON(visible=False)
45
  submissions_list_radio = gr.Radio([], label="已提交的作業學生", interactive=True)
46
  with gr.Column(scale=2):
47
  submission_data_json = gr.JSON(label="提交內容", visible=False)
48
- submission_data_markdown = gr.Markdown(label="提交內容")
49
 
50
  def init_assignment_list_data(assignment_list_value=None):
51
  assignment_list = gr.update(value=assignment_list_value)
52
  assignment_data = gr.update(value=None)
53
- assignment_data_markdown = gr.update(value=None)
54
  submissions_list_json = gr.update(value=None)
55
  submissions_list_radio = gr.update(choices=[], value=None)
56
  submission_data_json = gr.update(value=None)
57
- submission_data_markdown = gr.update(value=None)
58
- return assignment_list, assignment_data, assignment_data_markdown, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_markdown
59
 
60
- def update_assignment_data_markdown(assignment_data):
61
- markdown_value = f"""
62
- ### 作業類型: {assignment_data['assignment_type']}
63
- ### 作業年級: {assignment_data['metadata']['grade']}
64
- ### 作業題目: {assignment_data['metadata']['topic']}
65
- ### 日期: {assignment_data['timestamp']}
66
- ### 作業引文
67
- {assignment_data['metadata']['introduction']}
68
- ### 作業說明:
69
- {assignment_data['metadata']['description']}
70
- ### 作業連結: {assignment_data['metadata']['url']}
71
- ### 附加材料:
72
- {assignment_data['metadata']['attach_materials']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  """
74
- return gr.update(value=markdown_value)
75
 
76
  def update_submissions_list_radio(submission_ids):
77
  choices = []
@@ -82,14 +142,27 @@ def create_assignment_ui(user_data, assignment_service, submission_service):
82
  choices.append(choice)
83
  return gr.update(choices=choices)
84
 
85
- def update_submission_data_markdown(submission_json):
86
- markdown_value = f"""
87
- ### 提交內容
88
- {submission_json['submission_data']['content']}
89
- ### 提交日期
90
- {submission_json['timestamp']}
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  """
92
- return gr.update(value=markdown_value)
93
 
94
  get_all_assignments_button.click(
95
  assignment_service.update_assignment_list,
@@ -98,21 +171,21 @@ def create_assignment_ui(user_data, assignment_service, submission_service):
98
  ).then(
99
  fn=init_assignment_list_data,
100
  inputs=[],
101
- outputs=[assignment_list, assignment_data, assignment_data_markdown, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_markdown]
102
  )
103
 
104
  assignment_list.select(
105
  fn=init_assignment_list_data,
106
  inputs=[assignment_list],
107
- outputs=[assignment_list, assignment_data, assignment_data_markdown, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_markdown]
108
  ).then(
109
  assignment_service.get_assignment,
110
  inputs=[assignment_list],
111
  outputs=[assignment_data]
112
  ).then(
113
- fn=update_assignment_data_markdown,
114
  inputs=[assignment_data],
115
- outputs=[assignment_data_markdown]
116
  ).then(
117
  assignment_service.get_assignment_submissions,
118
  inputs=[assignment_list],
@@ -128,9 +201,9 @@ def create_assignment_ui(user_data, assignment_service, submission_service):
128
  inputs=[submissions_list_radio],
129
  outputs=submission_data_json
130
  ).then(
131
- fn=update_submission_data_markdown,
132
  inputs=[submission_data_json],
133
- outputs=[submission_data_markdown]
134
  )
135
 
136
  with gr.Tab("學生"):
 
5
  with gr.Tab("老師|建立作業"):
6
  with gr.Row():
7
  with gr.Column():
8
+ with gr.Row():
9
+ gr.Markdown("### 作業資訊")
10
+ with gr.Row():
11
+ assignment_topic = gr.Textbox(label="題目(必填)")
12
+ assignment_type_list = [
13
+ "中文寫作 AI 批改",
14
+ "英文寫作 AI 批改"
15
+ ]
16
+ assignment_type = gr.Radio(choices=assignment_type_list, label="選擇類型")
17
+ assignment_grade = gr.Radio(["一年級", "二年級", "三年級", "四年級", "五年級", "六年級"], label="選擇年級", visible=False)
18
+ with gr.Row():
19
+ gr.Markdown("### 內容規範")
20
+ with gr.Row():
21
+ assignment_introduction = gr.TextArea(label="寫作引文��填)")
22
+ assignment_description = gr.TextArea(label="作業說明")
23
+ with gr.Row():
24
+ gr.Markdown("### 繳交規範")
25
+ with gr.Row():
26
+ assignment_submission_deadline = gr.DateTime(label="提交截止日期")
27
+ assignment_attach_materials = gr.Textbox(label="附件參考", placeholder='[{"type": "video", "url": "link1", "description": "描述"}]')
28
+ with gr.Row():
29
+ assignment_create_button = gr.Button("建立作業")
30
+ assignment_metadata = gr.JSON(label="作業元數據", visible=False)
31
+ assignment_data = gr.JSON(label="作業數據", visible=False)
32
+ assignment_url = gr.Textbox(label="作業指派連結", interactive=False, show_copy_button=True)
33
+ assignment_id_display_teacher = gr.Textbox(label="作業 ID", interactive=False, visible=False)
34
+
35
 
36
+ def update_gr_assignment_url(assignment_data):
37
+ return assignment_data['assignment_url']
38
+
39
+ def update_gr_assignment_id(assignment_data):
40
+ return assignment_data['assignment_id']
41
+
42
+ assignment_create_button.click(
43
  assignment_service.create_assignment_metadata,
44
+ inputs=[
45
+ assignment_type,
46
+ assignment_grade,
47
+ assignment_topic,
48
+ assignment_introduction,
49
+ assignment_description,
50
+ assignment_attach_materials,
51
+ assignment_submission_deadline
52
+ ],
53
  outputs=[assignment_metadata]
54
  ).then(
55
  assignment_service.create_assignment,
56
  inputs=[user_data, assignment_type, assignment_metadata],
57
+ outputs=[assignment_data]
58
+ ).then(
59
+ update_gr_assignment_url,
60
+ inputs=[assignment_data],
61
+ outputs=[assignment_url]
62
+ ).then(
63
+ update_gr_assignment_id,
64
+ inputs=[assignment_data],
65
  outputs=[assignment_id_display_teacher]
66
  )
67
 
 
72
  assignment_list = gr.Radio([], label="作業列表", interactive=True)
73
  with gr.Column(scale=2):
74
  assignment_data = gr.JSON(label="作業內容", visible=False)
75
+ assignment_data_html = gr.HTML()
76
  with gr.Row():
77
  with gr.Column(scale=1):
78
  submissions_list_json = gr.JSON(visible=False)
79
  submissions_list_radio = gr.Radio([], label="已提交的作業學生", interactive=True)
80
  with gr.Column(scale=2):
81
  submission_data_json = gr.JSON(label="提交內容", visible=False)
82
+ submission_data_html = gr.HTML()
83
 
84
  def init_assignment_list_data(assignment_list_value=None):
85
  assignment_list = gr.update(value=assignment_list_value)
86
  assignment_data = gr.update(value=None)
87
+ assignment_data_html = gr.update(value=None)
88
  submissions_list_json = gr.update(value=None)
89
  submissions_list_radio = gr.update(choices=[], value=None)
90
  submission_data_json = gr.update(value=None)
91
+ submission_data_html = gr.update(value=None)
92
+ return assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html
93
 
94
+ def update_assignment_data_html(assignment_data):
95
+ html = f"""
96
+ <div style="background-color: #f8f9fa; padding: 30px; border-radius: 15px; font-family: 'Helvetica', sans-serif;">
97
+ <h2 style="color: #007bff; font-size: 28px; margin-bottom: 20px;">✨ 作業詳情</h2>
98
+ <div style="background-color: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
99
+ <div style="margin-bottom: 20px;">
100
+ <div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">🏷️ 作業類型</div>
101
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['assignment_type']}</div>
102
+ </div>
103
+ <div style="margin-bottom: 20px;">
104
+ <div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">📝 作業題目</div>
105
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['topic']}</div>
106
+ </div>
107
+ <div style="margin-bottom: 20px;">
108
+ <div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">🗓️ 日期</div>
109
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['timestamp']}</div>
110
+ </div>
111
+
112
+ <div style="margin-bottom: 20px;">
113
+ <div style="font-weight: bold; color: #28a745; margin-bottom: 5px;">📖 寫作引文</div>
114
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['introduction']}</div>
115
+ </div>
116
+
117
+ <div style="margin-bottom: 20px;">
118
+ <div style="font-weight: bold; color: #ffc107; margin-bottom: 5px;">ℹ️ 作業說明</div>
119
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['description']}</div>
120
+ </div>
121
+
122
+ <div style="margin-bottom: 20px;">
123
+ <div style="font-weight: bold; color: #17a2b8; margin-bottom: 5px;">🔗 作業連結</div>
124
+ <a href="{assignment_data['assignment_url']}" 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>
125
+ </div>
126
+
127
+ <div>
128
+ <div style="font-weight: bold; color: #dc3545; margin-bottom: 5px;">📎 附加材料</div>
129
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{assignment_data['metadata']['attach_materials']}</div>
130
+ </div>
131
+ </div>
132
+ </div>
133
  """
134
+ return gr.update(value=html)
135
 
136
  def update_submissions_list_radio(submission_ids):
137
  choices = []
 
142
  choices.append(choice)
143
  return gr.update(choices=choices)
144
 
145
+ def update_submission_data_html(submission_json):
146
+ html = f"""
147
+ <div style="background-color: #f8f9fa; padding: 30px; border-radius: 15px; font-family: 'Helvetica', sans-serif;">
148
+ <h2 style="color: #007bff; font-size: 28px; margin-bottom: 20px;">📝 學生回傳作業</h2>
149
+ <div style="background-color: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
150
+ <div style="margin-bottom: 20px;">
151
+ <div style="font-weight: bold; color: #6c757d; margin-bottom: 5px;">👤 學生姓名</div>
152
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{submission_json['student_name']}</div>
153
+ </div>
154
+ <div style="margin-bottom: 20px;">
155
+ <div style="font-weight: bold; color: #28a745; margin-bottom: 5px;">📄 回傳内容</div>
156
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px; white-space: pre-wrap;">{submission_json['submission_data']['content']}</div>
157
+ </div>
158
+ <div>
159
+ <div style="font-weight: bold; color: #17a2b8; margin-bottom: 5px;">🕒 回傳日期</div>
160
+ <div style="background-color: #f8f9fa; padding: 10px 15px; border-radius: 5px;">{submission_json['timestamp']}</div>
161
+ </div>
162
+ </div>
163
+ </div>
164
  """
165
+ return gr.update(value=html)
166
 
167
  get_all_assignments_button.click(
168
  assignment_service.update_assignment_list,
 
171
  ).then(
172
  fn=init_assignment_list_data,
173
  inputs=[],
174
+ outputs=[assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html]
175
  )
176
 
177
  assignment_list.select(
178
  fn=init_assignment_list_data,
179
  inputs=[assignment_list],
180
+ outputs=[assignment_list, assignment_data, assignment_data_html, submissions_list_json, submissions_list_radio, submission_data_json, submission_data_html]
181
  ).then(
182
  assignment_service.get_assignment,
183
  inputs=[assignment_list],
184
  outputs=[assignment_data]
185
  ).then(
186
+ fn=update_assignment_data_html,
187
  inputs=[assignment_data],
188
+ outputs=[assignment_data_html]
189
  ).then(
190
  assignment_service.get_assignment_submissions,
191
  inputs=[assignment_list],
 
201
  inputs=[submissions_list_radio],
202
  outputs=submission_data_json
203
  ).then(
204
+ fn=update_submission_data_html,
205
  inputs=[submission_data_json],
206
+ outputs=[submission_data_html]
207
  )
208
 
209
  with gr.Tab("學生"):
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- gradio==4.37.2
2
  openai>=1.16.2
3
  python-docx
4
  google-api-python-client
 
1
+ gradio==4.41.0
2
  openai>=1.16.2
3
  python-docx
4
  google-api-python-client