import data import dashboard from nicegui import app, ui import re import requests import theme from utils import Utils # DB columns tasks(person, verse, verse_passage, status, awana_completed, awana_bonus) db = data.CON cur = db.cursor() APIKEY = "Token f562cf2d890151d682065696dacdc0f86938a18e" HEADERS = {"Authorization": APIKEY} @ui.page("/") def index_page() -> None: with theme.frame("Homepage"): firstload = Utils.get_unique_people() if firstload is None: with ui.dialog() as first_dialog, ui.card().classes("items-center"): first_dialog.open() ui.label( "Looks like this is your first time! \n\n Please click the button below to add your first Awana club member." ).classes("text-center font-bold text-xl") ui.button().props("push glossy icon=person_add color=secondary").on( "click", lambda: addchild.open() ) else: pass with ui.dialog().props("persistent") as addverse: pass with ui.dialog().props("persistent") as editverse: pass with ui.dialog() as addchild, ui.card().classes("items-center"): result = ui.input(label="Clubber's Name") ui.button().props("push glossy icon=add_circle color=secondary").on( "click", lambda: add_child(result) ) with ui.grid(columns=1).classes( "self-center justify-items-center content-center p-2 m-2 rounded-xl" ): users = Utils.get_unique_people() for ppl in users: pers = str(ppl)[2:-3].title() users = [pers if x == ppl else x for x in users] toggle = ui.toggle(users, clearable=True, on_change=lambda: show_person(toggle)) with ui.row().classes("fixed bottom-0 left-0 p-2 m-2"): with ui.element("q-fab").props("icon=navigation color=accent"): ui.element("q-fab-action").props("icon=add color=secondary").on( "click", lambda: add_verse(toggle) ) ui.element("q-fab-action").props("icon=remove color=negative").on( "click", lambda: remove_verse(toggle) ) ui.element("q-fab-action").props("icon=person_add color=positive").on( "click", lambda: addchild.open() ) ui.element("q-fab-action").props("icon=person_remove color=accent").on( "click", lambda: ui.notify("Removing person is not set up yet") ) with ui.row().style("justify-content: center") as showperson: pass showperson.set_visibility(False) # FEAT: Allow editing of the verse. Awana will sometimes only give the student part of a verse (i.e 1 John 4:14 is actually 14b). @ui.refreshable def show_person(person): showperson.clear() showperson.set_visibility(False) if person.value is not None: dbinfo = Utils.get_specific_person(person) if dbinfo == []: showperson.clear() ui.notify( f"{person.value} doesn't have any verses saved under their name! Start adding some by clicking the arrow in the bottom left." ) elif dbinfo[0][1] == None: pass else: showperson.set_visibility(True) if person.value == "Hannah": setcolor = "rgba(0, 255, 0, .5)" elif person.value == "Fiona": setcolor = "rgba(255, 0, 0, .5)" else: setcolor = "rgba(0, 0, 255, .5)" with showperson.classes(f"border-8").style( f"border: {setcolor} 1px solid;" ): with ui.grid(columns=5).classes( "items-center w-full" ) as persontoggle: ui.separator().classes("col-span-5 h-2") for item in dbinfo: label_verse = ui.label(text=item[0]).classes("hidden") label_passage = ui.label(text=item[1]).classes("hidden") label_status = ui.label(text=item[2]).classes("hidden") ui.label(label_verse.text).classes("font-bold text-center") with ui.row(): ui.label(label_passage.text).classes("text-wrap") # ui.chip("Edit Verse", selectable=True, icon="edit", color="white", on_selection_change=lambda label_verse=label_verse: edit_verse(label_verse.text, person, label_passage.text)) if label_status.text == "1": ui.chip( "Complete", selectable=True, icon="add", color="tnt", on_selection_change=lambda label_verse=label_verse: Utils.toggle_completion( label_verse.text, person, status=0 ), on_click=lambda: show_person(person), ).classes("text-white") else: ui.chip( "Incomplete", selectable=True, icon="add", color="sparks", on_selection_change=lambda label_verse=label_verse: Utils.toggle_completion( label_verse.text, person, status=1 ), on_click=lambda: show_person(person), ).classes("text-white") ui.chip( "Edit Verse", selectable=True, icon="edit", color="cubbies", on_selection_change=lambda label_passage=label_passage: edit_verse( label_verse.text, person, label_passage.text ), ).classes("text-white") ui.chip( "Delete Verse", selectable=True, color="red", icon="delete", on_selection_change=lambda label_verse=label_verse: Utils.delete_verse( label_verse.text, person ), on_click=lambda: show_person(person), ).classes("text-white").style('color: white;') ui.separator().classes("col-span-5 h-2") else: showperson.clear() addverse.close() def edit_verse(verse, person, passage): editverse.open() with editverse: with ui.card().classes("flex-wrap items-center"): ui.label("Here's the verse for easier copy & paste:") ui.label(passage) editing = ui.textarea(label="Edit below") with ui.row().classes("justify-content-center"): ui.button().props("push glossy icon=add_circle color=secondary").on( "click", lambda: edit_submit_verse(person, editing, verse) ) def add_verse(person): if person.value is None: ui.notify("Oops! You haven't selected a person") else: addverse.open() with addverse: with ui.card().classes("flex-wrap items-center"): result = ui.input(label="Add Verse Here") with ui.row().classes("justify-content-center"): ui.button().props( "push glossy icon=add_circle color=secondary" ).on("click", lambda: submit_verse(result, person)) ui.button().props("push glossy icon=cancel color=negative").on( "click", lambda: addverse.close() ) def edit_submit_verse(person, passage, verse): print(passage) print(passage.value) Utils.edit_verse(person, verse, passage) editverse.close() show_person(person) def submit_verse(result, person): # Check if Verse is already in db dbcheck = cur.execute( f"select * from tasks where person = '{person.value}' and verse = '{result.value}';" ) check_for_verse = dbcheck.fetchone() if check_for_verse is not None: ui.notify( f"{result.value} already exists for {person.value}! You can't have duplicates" ) else: # Verify the format of a Bible Verse if not re.match( r"((^\d\s\w{1,}\s|^\w{1,}\s)(\d{1,2}:)(\d{1,2}-\d{1,2}|\d{1,2}))", result.value, ): ui.notify("Verse was input incorrectly.") addverse.close() else: # Split up the string for later colon = result.value.split(":") precolon = colon[0].split(" ")[1].strip() postcolon = colon[1].strip() if "-" in postcolon: start = postcolon.split("-")[0] end = postcolon.split("-")[1] else: start = postcolon # Get Verse Endpoint url = f"https://api.esv.org/v3/passage/text/?q={result.value}" response = requests.get(url, headers=HEADERS) if response.status_code == 200 or response.status_code == 202: vpass = response.json() passage = str(vpass["passages"]) # npassage gets rid of any carriage return characters npassage = passage.replace("\\n", "").strip() # xpassage removes Footnotes section, if it exists if "Footnotes" in npassage: xpassage = re.sub(r"Footnotes.*", "", npassage) else: xpassage = npassage.replace("(ESV)']", "") # vpassage grabs the actual verses, dropping the title (starting from first verse in result) vpassage = re.search(rf"\[{start}\].*", xpassage).group(0) # zpassage - remove any parenthesis or brackets references zpassage = re.sub(r"\[\d+\]|\(\d+\)|\s{2,}", "", vpassage).strip() if re.match(r"^\“", zpassage): zpassage = f"{zpassage}”" else: pass else: ui.notify("Uh oh. Something went wrong.") ins = cur.execute( f"replace into tasks values('{person.value.lower()}', '{result.value}', '{zpassage}', 0, 0, 'none');" ) db.commit() show_person(person) def add_child(person): check_person = Utils.get_specific_person(person) print(check_person) if check_person == []: Utils.add_person(person) # persontoggle.set_visibility(False) show_person(person) addchild.close() else: ui.notify( f"The name {person.value} already exists. Please add someone else" ) ui.run(storage_secret="b601785a-855c-41d1-adeb-68f0330d8186")