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'): with ui.dialog().props('persistent') as addverse: pass with ui.dialog().props('persistent') as editverse: pass 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)) 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). # FEAT: Find how to pin/bind a verse to a second page @ui.refreshable def show_person(person): showperson.clear() 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 her name! Start adding some by clicking the green arrow in the bottom left.") 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'): 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="positive", on_selection_change=lambda label_verse=label_verse: Utils.toggle_completion(label_verse.text, person, status=0), on_click=lambda: show_person(person)) else: ui.chip('Incomplete', selectable=True, icon="add", color="negative", on_selection_change=lambda label_verse=label_verse: Utils.toggle_completion(label_verse.text, person, status=1), on_click=lambda: show_person(person)) ui.checkbox('Pin Verse')#.bind_visibility_from(card, 'value') ui.checkbox('Mark as Completed')#.bind_value(item[2]) 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'): editing = ui.textarea(label="Edit Below", placeholder=passage) with ui.row().classes('justify-content-center'): ui.button().props('push glossy icon=add_circle color=secondary').on('click', lambda: submit_verse(result, 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)) 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.lower()}' 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) print(xpassage) vpassage = re.search(fr'\[{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 print(zpassage) else: print(response.text) 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 checked_data() -> None: datavals = [] ui.run(storage_secret='b601785a-855c-41d1-adeb-68f0330d8186')