Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -30,6 +30,7 @@ def process_data(file: gr.File, progress=gr.Progress()) -> Tuple[str, str, pd.Da
|
|
30 |
raise ValueError(f"Error reading Excel file: {str(e)}")
|
31 |
|
32 |
base_path = tempfile.mkdtemp()
|
|
|
33 |
final_file_path = os.path.join(base_path, 'final_output.xlsx')
|
34 |
|
35 |
# Step 1: Extract User Information
|
@@ -56,7 +57,7 @@ def process_data(file: gr.File, progress=gr.Progress()) -> Tuple[str, str, pd.Da
|
|
56 |
|
57 |
# Step 4: Generate Filenames and Paths
|
58 |
user_info['File'] = 'User_' + user_info['Username'] + '_data.csv'
|
59 |
-
user_info['Path'] = user_info['File'].apply(lambda x: os.path.join(
|
60 |
|
61 |
# Remove extra columns and summary rows
|
62 |
user_info = user_info[['Username', 'Name', 'Courses', 'Grand Total', 'Email', 'File', 'Path']]
|
@@ -72,13 +73,13 @@ def process_data(file: gr.File, progress=gr.Progress()) -> Tuple[str, str, pd.Da
|
|
72 |
|
73 |
# Generate individual CSV files for each user
|
74 |
required_columns = ['course_id', 'course_pk1', 'data', 'event_type', 'internal_handle', 'lastname', 'session_id', 'timestamp', 'user_id', 'system_role']
|
75 |
-
|
76 |
-
if not os.path.exists(
|
77 |
-
os.makedirs(
|
78 |
|
79 |
for user_id in user_info['Username'].unique():
|
80 |
user_data = raw_data[raw_data['user_id'] == user_id][required_columns]
|
81 |
-
user_file_path = os.path.join(
|
82 |
user_data.to_csv(user_file_path, index=False)
|
83 |
|
84 |
# Save the final dataframe to the output Excel file
|
@@ -98,10 +99,11 @@ def process_data(file: gr.File, progress=gr.Progress()) -> Tuple[str, str, pd.Da
|
|
98 |
# Create a zip file containing all user CSV files and the final Excel file
|
99 |
zip_buffer = io.BytesIO()
|
100 |
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
|
101 |
-
for root, _, files in os.walk(
|
102 |
for file in files:
|
103 |
file_path = os.path.join(root, file)
|
104 |
-
|
|
|
105 |
|
106 |
zip_file.write(final_file_path, os.path.basename(final_file_path))
|
107 |
|
@@ -139,6 +141,7 @@ def create_bar_chart(df: pd.DataFrame, x: str, y: str, title: str) -> Union[px.b
|
|
139 |
paper_bgcolor='white',
|
140 |
font_color=NTU_BLUE
|
141 |
)
|
|
|
142 |
fig.update_traces(marker_color=NTU_BLUE)
|
143 |
return fig
|
144 |
except Exception as e:
|
@@ -156,6 +159,7 @@ def create_scatter_plot(df: pd.DataFrame) -> Union[px.scatter, None]:
|
|
156 |
paper_bgcolor='white',
|
157 |
font_color=NTU_BLUE
|
158 |
)
|
|
|
159 |
fig.update_traces(marker_color=NTU_RED)
|
160 |
return fig
|
161 |
except Exception as e:
|
@@ -214,7 +218,40 @@ custom_theme = gr.themes.Base().set(
|
|
214 |
input_border_color_focus="#C11E38",
|
215 |
)
|
216 |
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
gr.Markdown("# Gradebook Data Processor", elem_classes=["app-title"])
|
219 |
|
220 |
with gr.Tabs():
|
@@ -224,11 +261,12 @@ with gr.Blocks(theme=custom_theme, css="custom.css") as iface:
|
|
224 |
process_btn = gr.Button("Process Data", variant="primary")
|
225 |
output_msg = gr.Textbox(label="Processing Result")
|
226 |
csv_location = gr.Textbox(label="Output Information")
|
|
|
227 |
download_button = gr.File(visible=False, label="Download Results")
|
228 |
-
gr.Markdown("After processing, switch to the 'Data Insights' tab to view results and
|
229 |
|
230 |
with gr.TabItem("2. Data Insights Dashboard"):
|
231 |
-
gr.Markdown("##
|
232 |
summary_stats = gr.Markdown("Upload and process a file to see summary statistics.")
|
233 |
|
234 |
with gr.Row():
|
|
|
30 |
raise ValueError(f"Error reading Excel file: {str(e)}")
|
31 |
|
32 |
base_path = tempfile.mkdtemp()
|
33 |
+
mailmerge_path = os.path.join('mailmerge')
|
34 |
final_file_path = os.path.join(base_path, 'final_output.xlsx')
|
35 |
|
36 |
# Step 1: Extract User Information
|
|
|
57 |
|
58 |
# Step 4: Generate Filenames and Paths
|
59 |
user_info['File'] = 'User_' + user_info['Username'] + '_data.csv'
|
60 |
+
user_info['Path'] = user_info['File'].apply(lambda x: os.path.join(mailmerge_path, x))
|
61 |
|
62 |
# Remove extra columns and summary rows
|
63 |
user_info = user_info[['Username', 'Name', 'Courses', 'Grand Total', 'Email', 'File', 'Path']]
|
|
|
73 |
|
74 |
# Generate individual CSV files for each user
|
75 |
required_columns = ['course_id', 'course_pk1', 'data', 'event_type', 'internal_handle', 'lastname', 'session_id', 'timestamp', 'user_id', 'system_role']
|
76 |
+
full_mailmerge_path = os.path.join(base_path, mailmerge_path)
|
77 |
+
if not os.path.exists(full_mailmerge_path):
|
78 |
+
os.makedirs(full_mailmerge_path)
|
79 |
|
80 |
for user_id in user_info['Username'].unique():
|
81 |
user_data = raw_data[raw_data['user_id'] == user_id][required_columns]
|
82 |
+
user_file_path = os.path.join(full_mailmerge_path, f'User_{user_id}_data.csv')
|
83 |
user_data.to_csv(user_file_path, index=False)
|
84 |
|
85 |
# Save the final dataframe to the output Excel file
|
|
|
99 |
# Create a zip file containing all user CSV files and the final Excel file
|
100 |
zip_buffer = io.BytesIO()
|
101 |
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
|
102 |
+
for root, _, files in os.walk(full_mailmerge_path):
|
103 |
for file in files:
|
104 |
file_path = os.path.join(root, file)
|
105 |
+
arcname = os.path.relpath(file_path, base_path)
|
106 |
+
zip_file.write(file_path, arcname)
|
107 |
|
108 |
zip_file.write(final_file_path, os.path.basename(final_file_path))
|
109 |
|
|
|
141 |
paper_bgcolor='white',
|
142 |
font_color=NTU_BLUE
|
143 |
)
|
144 |
+
fig.update_xaxes(tickmode='linear') # Ensure all x-axis labels are shown
|
145 |
fig.update_traces(marker_color=NTU_BLUE)
|
146 |
return fig
|
147 |
except Exception as e:
|
|
|
159 |
paper_bgcolor='white',
|
160 |
font_color=NTU_BLUE
|
161 |
)
|
162 |
+
fig.update_xaxes(tickmode='linear') # Ensure all x-axis labels are shown
|
163 |
fig.update_traces(marker_color=NTU_RED)
|
164 |
return fig
|
165 |
except Exception as e:
|
|
|
218 |
input_border_color_focus="#C11E38",
|
219 |
)
|
220 |
|
221 |
+
# Custom CSS
|
222 |
+
custom_css = """
|
223 |
+
.gr-button-secondary {
|
224 |
+
background-color: #F0F0F0;
|
225 |
+
color: #003D7C;
|
226 |
+
border: 1px solid #003D7C;
|
227 |
+
border-radius: 12px;
|
228 |
+
padding: 8px 16px;
|
229 |
+
font-size: 16px;
|
230 |
+
font-weight: bold;
|
231 |
+
cursor: pointer;
|
232 |
+
transition: background-color 0.3s, color 0.3s, border-color 0.3s;
|
233 |
+
}
|
234 |
+
|
235 |
+
.gr-button-secondary:hover {
|
236 |
+
background-color: #003D7C;
|
237 |
+
color: white;
|
238 |
+
border-color: #003D7C;
|
239 |
+
}
|
240 |
+
|
241 |
+
.gr-button-secondary:active {
|
242 |
+
transform: translateY(1px);
|
243 |
+
}
|
244 |
+
|
245 |
+
.app-title {
|
246 |
+
color: #003D7C;
|
247 |
+
font-size: 24px;
|
248 |
+
font-weight: bold;
|
249 |
+
text-align: center;
|
250 |
+
margin-bottom: 20px;
|
251 |
+
}
|
252 |
+
"""
|
253 |
+
|
254 |
+
with gr.Blocks(theme=custom_theme, css=custom_css) as iface:
|
255 |
gr.Markdown("# Gradebook Data Processor", elem_classes=["app-title"])
|
256 |
|
257 |
with gr.Tabs():
|
|
|
261 |
process_btn = gr.Button("Process Data", variant="primary")
|
262 |
output_msg = gr.Textbox(label="Processing Result")
|
263 |
csv_location = gr.Textbox(label="Output Information")
|
264 |
+
gr.Markdown("## Step 2: Download Mail merge package")
|
265 |
download_button = gr.File(visible=False, label="Download Results")
|
266 |
+
gr.Markdown("Tip: 😎 After processing, switch to the 'Data Insights' tab at the top to view results and analytics.")
|
267 |
|
268 |
with gr.TabItem("2. Data Insights Dashboard"):
|
269 |
+
gr.Markdown("## Data Insights")
|
270 |
summary_stats = gr.Markdown("Upload and process a file to see summary statistics.")
|
271 |
|
272 |
with gr.Row():
|