import data import dashboard from nicegui import ui import re import requests import theme from utils import Utils # DB columns tasks(person, verse, verse_passage, status, awana_completed, awana_bonus, spark ) db = data.CON cur = db.cursor() APIKEY = "Token f562cf2d890151d682065696dacdc0f86938a18e" HEADERS = {"Authorization": APIKEY} @ui.page("/", dark=False) 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"): result1 = ui.input(label="Clubber's Name") result2 = ui.input(label="Awana Club") ui.button().props("push glossy icon=add_circle color=secondary").on( "click", lambda: add_person(result1, result2) ) with ui.grid(columns=1).classes( "self-center justify-items-center content-center p-2 m-2 rounded-xl" ) as pplrow: 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) @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("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") verssage = ui.label(text=f"{label_verse.text} - {label_passage.text}").classes("hidden") ui.label(label_verse.text).classes("font-bold text-center") with ui.row(): ui.label(label_passage.text).classes("text-wrap") 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 verssage=verssage: edit_verse( verssage, person ), ).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 remove_verse(): pass def edit_verse(verssage, person): editverse.clear() editverse.open() verse = verssage.text.split('-')[0].strip() passage = verssage.text.split('-')[1] with editverse: with ui.card().classes("flex-wrap items-center"): ui.label("Here's the verse for easier copy & paste:") ui.label(passage).classes('text-center') ui.label(verse) editing = ui.textarea(label="Edit below").classes('center') 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) ) ui.button().props("push glossy icon=cancel color=sparks").on('click', lambda: editverse.close()) def edit_submit_verse(person, passage, verse): Utils.edit_verse(person, verse, passage) editverse.close() show_person(person) 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), addverse.close())) ui.button().props("push glossy icon=cancel color=negative").on( "click", lambda: addverse.close() ) 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.") Utils.add_verse(person, result, zpassage) show_person(person) def add_person(person, club): check_person = Utils.get_specific_person(person) if check_person == []: Utils.add_person(person, club) addchild.close() else: ui.notify( f"The name {person.value} already exists. Please add someone else" ) show_person(person) ui.run(storage_secret="b601785a-855c-41d1-adeb-68f0330d8186")