Spaces:
Runtime error
Runtime error
Updated markdown text about generating schedules
Browse files
main.py
CHANGED
@@ -41,8 +41,11 @@ theme = gr.themes.Soft(
|
|
41 |
)
|
42 |
|
43 |
### Connect to Supabase ###
|
44 |
-
URL = os.environ['URL']
|
45 |
-
API_KEY = os.environ['API_KEY']
|
|
|
|
|
|
|
46 |
client = supabase.create_client(URL, API_KEY)
|
47 |
|
48 |
|
@@ -82,7 +85,7 @@ def make_form(email: str, schedule_name: str, password_1: str, password_2: str,
|
|
82 |
return gr.Warning('', ALERT_TIME, title=f"The capacity (number of people who can teach per timeslot) must be greater than zero.")
|
83 |
|
84 |
if len(slots) == 0:
|
85 |
-
return gr.Warning('', ALERT_TIME, title="Please enter at least one timeslot. Make sure to press \"Enter\" after each one!")
|
86 |
|
87 |
|
88 |
# Check if schedule name already exists
|
@@ -178,7 +181,7 @@ def submit_preferences(schedule_name: str, curr_juggler_name: str, curr_email: s
|
|
178 |
return gr.Warning('', ALERT_TIME, title=f"You only selected {len(curr_availability)} timeslots. However, you said you wanted to teach {curr_num_workshops} workshops. Please make sure that you are available to teach during at least {curr_num_workshops} timeslots.")
|
179 |
|
180 |
if len(curr_descriptions) == 0:
|
181 |
-
return gr.Warning('', ALERT_TIME, title=f"Please describe at least one workshop that you want to teach. You must hit \"Enter\" after each one!")
|
182 |
|
183 |
response = client.table('Forms').select('responses', 'slots').eq('form_name', standardize(schedule_name)).execute()
|
184 |
data = response.data
|
@@ -252,7 +255,7 @@ Returns:
|
|
252 |
gr.Button: corresponds to open_close_btn
|
253 |
'''
|
254 |
def make_visible(schedule_name:str, password: str):
|
255 |
-
skip_output = gr.Button(), gr.Column(), gr.Column(), gr.Row(), gr.Column(), gr.Button()
|
256 |
|
257 |
if len(schedule_name) == 0:
|
258 |
gr.Warning('Please enter the form name.', ALERT_TIME)
|
@@ -273,11 +276,11 @@ def make_visible(schedule_name:str, password: str):
|
|
273 |
else:
|
274 |
if my_dict['status'] == 'open':
|
275 |
gr.Info('', ALERT_TIME, title='Btw, the form is currently OPEN.')
|
276 |
-
return gr.Button(variant='secondary'), gr.Column(visible=True), gr.Column(visible=True), gr.Row(visible=True), gr.Column(visible=True), gr.Button("Close Form", visible=True)
|
277 |
|
278 |
elif my_dict['status'] == 'closed':
|
279 |
gr.Info('', ALERT_TIME, title='Btw, the form is currently CLOSED.')
|
280 |
-
return gr.Button(variant='secondary'), gr.Column(visible=True), gr.Column(visible=True), gr.Row(visible=True),gr.Column(visible=True), gr.Button("Open Form", visible=True)
|
281 |
|
282 |
else:
|
283 |
gr.Warning(f"There is no form called \"{schedule_name}\". Please check the spelling and try again.", ALERT_TIME)
|
@@ -417,10 +420,60 @@ def toggle_btn(schedule_name:str, password:str):
|
|
417 |
return gr.Button()
|
418 |
|
419 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
### MARKDOWN TEXT ###
|
421 |
generate_markdown = f"""
|
422 |
-
The app will attempt to create schedules where everyone is teaching their
|
423 |
If that is impossible, then the app will create schedules that maximize the number of timeslots that are filled.\n
|
|
|
424 |
You can either get a random selection of the best schedules (recommended), or ALL of the best schedules.\n
|
425 |
WARNING: It can sometimes take a LONG time to get all the best schedules!
|
426 |
"""
|
@@ -461,7 +514,7 @@ with gr.Blocks() as demo:
|
|
461 |
|
462 |
# Let the user dynamically describe their workshops
|
463 |
descriptions = gr.State([])
|
464 |
-
new_description = gr.Textbox(label='Workshop Descriptions', info='Describe the workshop(s) you want to teach. Include the title, prereqs, and difficulty level for each workshop. Hit "Enter" after each one.', visible=False)
|
465 |
|
466 |
def add_descrip(descriptions, new_description):
|
467 |
return descriptions + [{"name": new_description}], ""
|
@@ -496,7 +549,7 @@ with gr.Blocks() as demo:
|
|
496 |
# Dynamically render timeslots
|
497 |
# Based on: https://www.gradio.app/guides/dynamic-apps-with-render-decorator
|
498 |
slots = gr.State([])
|
499 |
-
new_slot = gr.Textbox(label='Enter Timeslots People Can Teach', info='Ex: Friday 7 pm, Saturday 11 am. Hit "Enter" after each one. Make sure to put them in CHRONOLOGICAL ORDER!')
|
500 |
|
501 |
def add_slot(slots, new_slot_name):
|
502 |
return slots + [{"name": new_slot_name}], ""
|
@@ -568,7 +621,16 @@ with gr.Blocks() as demo:
|
|
568 |
open_close_btn.click(fn=toggle_btn, inputs=[schedule_name, password], outputs=[open_close_btn])
|
569 |
|
570 |
|
571 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
572 |
|
573 |
|
574 |
### INFO ###
|
|
|
41 |
)
|
42 |
|
43 |
### Connect to Supabase ###
|
44 |
+
#URL = os.environ['URL']
|
45 |
+
#API_KEY = os.environ['API_KEY']
|
46 |
+
# TODO
|
47 |
+
URL = 'https://ubngctgvhjgxkvimdmri.supabase.co'
|
48 |
+
API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVibmdjdGd2aGpneGt2aW1kbXJpIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzQ5MjAwOTQsImV4cCI6MjA1MDQ5NjA5NH0.NtGdfP8GYNuYdPdsaLW5GjgfB0_7Q1kNBIDJtPhO8nY'
|
49 |
client = supabase.create_client(URL, API_KEY)
|
50 |
|
51 |
|
|
|
85 |
return gr.Warning('', ALERT_TIME, title=f"The capacity (number of people who can teach per timeslot) must be greater than zero.")
|
86 |
|
87 |
if len(slots) == 0:
|
88 |
+
return gr.Warning('', ALERT_TIME, title="Please enter at least one timeslot. Make sure to press \"Enter\" after each one (\"Return\" if you're on mobile)!")
|
89 |
|
90 |
|
91 |
# Check if schedule name already exists
|
|
|
181 |
return gr.Warning('', ALERT_TIME, title=f"You only selected {len(curr_availability)} timeslots. However, you said you wanted to teach {curr_num_workshops} workshops. Please make sure that you are available to teach during at least {curr_num_workshops} timeslots.")
|
182 |
|
183 |
if len(curr_descriptions) == 0:
|
184 |
+
return gr.Warning('', ALERT_TIME, title=f"Please describe at least one workshop that you want to teach. You must hit \"Enter\" after each one (\"Return\" if you're on mobile)!")
|
185 |
|
186 |
response = client.table('Forms').select('responses', 'slots').eq('form_name', standardize(schedule_name)).execute()
|
187 |
data = response.data
|
|
|
255 |
gr.Button: corresponds to open_close_btn
|
256 |
'''
|
257 |
def make_visible(schedule_name:str, password: str):
|
258 |
+
skip_output = gr.Button(), gr.Column(), gr.Column(), gr.Row(), gr.Column(), gr.Button(), gr.Column
|
259 |
|
260 |
if len(schedule_name) == 0:
|
261 |
gr.Warning('Please enter the form name.', ALERT_TIME)
|
|
|
276 |
else:
|
277 |
if my_dict['status'] == 'open':
|
278 |
gr.Info('', ALERT_TIME, title='Btw, the form is currently OPEN.')
|
279 |
+
return gr.Button(variant='secondary'), gr.Column(visible=True), gr.Column(visible=True), gr.Row(visible=True), gr.Column(visible=True), gr.Button("Close Form", visible=True), gr.Column(visible=True)
|
280 |
|
281 |
elif my_dict['status'] == 'closed':
|
282 |
gr.Info('', ALERT_TIME, title='Btw, the form is currently CLOSED.')
|
283 |
+
return gr.Button(variant='secondary'), gr.Column(visible=True), gr.Column(visible=True), gr.Row(visible=True),gr.Column(visible=True), gr.Button("Open Form", visible=True), gr.Column(visible=True)
|
284 |
|
285 |
else:
|
286 |
gr.Warning(f"There is no form called \"{schedule_name}\". Please check the spelling and try again.", ALERT_TIME)
|
|
|
420 |
return gr.Button()
|
421 |
|
422 |
|
423 |
+
'''
|
424 |
+
Delete a response
|
425 |
+
Returns: None
|
426 |
+
'''
|
427 |
+
def my_delete(schedule_name: str, curr_juggler_name: str):
|
428 |
+
response = client.table('Forms').select('responses', 'slots').eq('form_name', standardize(schedule_name)).execute()
|
429 |
+
data = response.data
|
430 |
+
|
431 |
+
if len(data) > 0:
|
432 |
+
form = json.loads(data[0]['responses'])
|
433 |
+
|
434 |
+
# Get current lists
|
435 |
+
curr_juggler_name = curr_juggler_name.strip()
|
436 |
+
names = form[NAME_COL]
|
437 |
+
emails = form[EMAIL_COL]
|
438 |
+
bandwidths = form[NUM_WORKSHOPS_COL]
|
439 |
+
availabilities = form[AVAIL_COL]
|
440 |
+
descriptions = form[DESCRIP_COL]
|
441 |
+
|
442 |
+
# Get index of the juggler's name
|
443 |
+
try:
|
444 |
+
index = names.index(curr_juggler_name)
|
445 |
+
except:
|
446 |
+
return gr.Warning('', ALERT_TIME, title=f"\"{curr_juggler_name}\" is not in the form responses. Please check the spelling and try again.")
|
447 |
+
|
448 |
+
# Remove juggler's responses from the lists
|
449 |
+
del names[index]
|
450 |
+
del emails[index]
|
451 |
+
del bandwidths[index]
|
452 |
+
del availabilities[index]
|
453 |
+
del descriptions[index]
|
454 |
+
|
455 |
+
# Update Supabase
|
456 |
+
my_obj = json.dumps({
|
457 |
+
NAME_COL: names,
|
458 |
+
EMAIL_COL: emails,
|
459 |
+
NUM_WORKSHOPS_COL: bandwidths,
|
460 |
+
AVAIL_COL: availabilities,
|
461 |
+
DESCRIP_COL: descriptions
|
462 |
+
})
|
463 |
+
client.table('Forms').update({'responses': my_obj}).eq('form_name', standardize(schedule_name)).execute()
|
464 |
+
return gr.Info('', ALERT_TIME, title='Response deleted successfully!')
|
465 |
+
|
466 |
+
# I don't think it's possible to get here because I checked the schedule name earlier
|
467 |
+
else:
|
468 |
+
return gr.Warning('', ALERT_TIME, title=f"There was no form called \"{schedule_name}\". Please check the spelling and try again.")
|
469 |
+
|
470 |
+
|
471 |
+
|
472 |
### MARKDOWN TEXT ###
|
473 |
generate_markdown = f"""
|
474 |
+
The app will attempt to create schedules where everyone is teaching their desired number of workshops AND all timeslots are filled.\n
|
475 |
If that is impossible, then the app will create schedules that maximize the number of timeslots that are filled.\n
|
476 |
+
If someone can teach at every possible timeslot, then they willl NOT be in any of the schedules (this helps the code run faster).\n
|
477 |
You can either get a random selection of the best schedules (recommended), or ALL of the best schedules.\n
|
478 |
WARNING: It can sometimes take a LONG time to get all the best schedules!
|
479 |
"""
|
|
|
514 |
|
515 |
# Let the user dynamically describe their workshops
|
516 |
descriptions = gr.State([])
|
517 |
+
new_description = gr.Textbox(label='Workshop Descriptions', info='Describe the workshop(s) you want to teach. Include the title, prereqs, and difficulty level for each workshop. Hit "Enter" after each one ("Return" if you\'re on mobile).', visible=False)
|
518 |
|
519 |
def add_descrip(descriptions, new_description):
|
520 |
return descriptions + [{"name": new_description}], ""
|
|
|
549 |
# Dynamically render timeslots
|
550 |
# Based on: https://www.gradio.app/guides/dynamic-apps-with-render-decorator
|
551 |
slots = gr.State([])
|
552 |
+
new_slot = gr.Textbox(label='Enter Timeslots People Can Teach', info='Ex: Friday 7 pm, Saturday 11 am. Hit "Enter" after each one ("Return" if you\'re on mobile). Make sure to put them in CHRONOLOGICAL ORDER!')
|
553 |
|
554 |
def add_slot(slots, new_slot_name):
|
555 |
return slots + [{"name": new_slot_name}], ""
|
|
|
621 |
open_close_btn.click(fn=toggle_btn, inputs=[schedule_name, password], outputs=[open_close_btn])
|
622 |
|
623 |
|
624 |
+
# 4. Delete response
|
625 |
+
with gr.Column(visible=False) as delete_btn_col:
|
626 |
+
gr.Markdown('# Delete a Response')
|
627 |
+
gr.Markdown('Pressing this button will delete the juggler\'s response entirely. Warning: this CANNOT be undone!!')
|
628 |
+
juggler_name = gr.Textbox(label="Juggler's Name: Enter the name of the juggler's response that you want to delete")
|
629 |
+
delete_btn = gr.Button('Delete Response')
|
630 |
+
delete_btn.click(fn=my_delete, inputs=[schedule_name, juggler_name])
|
631 |
+
|
632 |
+
|
633 |
+
find_form_btn.click(fn=make_visible, inputs=[schedule_name, password], outputs=[find_form_btn, all_responses_col, generate_schedules_explanation_col, generate_btns_row, open_close_btn_col, open_close_btn, delete_btn_col])
|
634 |
|
635 |
|
636 |
### INFO ###
|