diff --git a/__pycache__/dashboard.cpython-312.pyc b/__pycache__/dashboard.cpython-312.pyc new file mode 100644 index 0000000..d315b2b Binary files /dev/null and b/__pycache__/dashboard.cpython-312.pyc differ diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..9c9f0c6 Binary files /dev/null and b/__pycache__/main.cpython-312.pyc differ diff --git a/__pycache__/theme.cpython-312.pyc b/__pycache__/theme.cpython-312.pyc index f17a4ad..d7a1975 100644 Binary files a/__pycache__/theme.cpython-312.pyc and b/__pycache__/theme.cpython-312.pyc differ diff --git a/dashboard.py b/dashboard.py new file mode 100644 index 0000000..98cf907 --- /dev/null +++ b/dashboard.py @@ -0,0 +1,13 @@ +import theme +from nicegui import ui +from main import checked_data + +@ui.page('/dashboard') +def dashboard(): + with theme.frame('Dashboard'): + pass + + with ui.grid(columns='auto 150px'): + with ui.card().classes('border-purple-200 grid justify-items-center').style('border: 2px solid rgba(0, 255, 0, .25)'): + ui.label('John 3:16').classes('text-center') + ui.label('For God Sent his son etc etc').classes('font-bold') diff --git a/homepage_sandbox.py b/homepage.py similarity index 100% rename from homepage_sandbox.py rename to homepage.py diff --git a/main.py b/main.py index a350a08..bf61d4b 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ import data -import homepage +import dashboard from nicegui import app, ui import re import requests @@ -20,15 +20,17 @@ def index_page() -> None: with ui.grid(columns=1).classes('self-center justify-items-center content-center p-2 m-2 rounded-xl'): toggle = ui.toggle(["Hannah", "Fiona", "Liam"], clearable=True, on_change=lambda: show_person(toggle)) - with ui.row().classes('absolute bottom-0 left-0 p-2 m-2'): - with ui.element('q-fab').props('icon=navigation color=green'): - ui.element('q-fab-action').props('icon=add color=blue-5').on('click', lambda: add_verse(toggle)) - ui.element('q-fab-action').props('icon=remove color=red-3').on('click', lambda: remove_verse(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): @@ -42,20 +44,29 @@ def index_page() -> None: else: showperson.set_visibility(True) #False if showperson.visible else True) # showoptions.set_visibility(True) - with showperson.classes('border-8'): - with ui.grid(columns=5).classes('rounded-md items-center border-8'): + 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.chip(label_verse.text, icon='ads_click', on_click=lambda: ui.notify(label_passage.text)) + ui.label(label_verse.text).classes('font-bold') + # ui.chip(label_verse.text, icon='ads_click', on_click=lambda: ui.notify(label_passage.text)).classes('border p-1') ui.label(label_passage.text).classes('text-wrap') if label_status.text == '0': - ui.chip("Incomplete", selectable=True, icon="add", color="orange", on_selection_change=lambda: toggle_completion(label_verse.text, person, status=1)) + ui.chip("Incomplete", selectable=True, icon="add", color="negative", on_selection_change=lambda: toggle_completion(label_verse.text, person, status=1)) else: - ui.chip("Complete", selectable=True, icon="add", color="green", on_selection_change=lambda: toggle_completion(label_verse.text, person, status=0)) + ui.chip("Complete", selectable=True, icon="add", color="accent", on_selection_change=lambda: toggle_completion(label_verse.text, person, status=0)) 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() @@ -68,6 +79,7 @@ def index_page() -> None: def add_verse(person): + # TODO: Add check of existing verses so that a user can't add duplicates. if person.value is None: ui.notify("Oops! You haven't selected a person") else: @@ -76,55 +88,63 @@ def index_page() -> None: 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=indigo-5').on('click', lambda: submit_verse(result, person)) - ui.button().props('push glossy icon=cancel color=orange-3').on('click', lambda: addverse.close()) + 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): - # 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.clear() + # 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: - # 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] + # 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.clear() 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) + # 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: - 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}”' + 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: - pass - print(zpassage) - else: - print(response.text) - ui.notify("Uh oh. Something went wrong.") + print(response.text) + ui.notify("Uh oh. Something went wrong.") - ins = cur.execute(f"insert into tasks values('{person.value.lower()}', '{result.value}', '{zpassage}', 0, 0, 'none');") - db.commit() - show_person(person) + 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') diff --git a/memorization_tasks.db b/memorization_tasks.db index 9f484f4..f6738a9 100644 Binary files a/memorization_tasks.db and b/memorization_tasks.db differ diff --git a/theme.py b/theme.py index c6ca66d..ed2d119 100644 --- a/theme.py +++ b/theme.py @@ -5,13 +5,15 @@ from nicegui import ui @contextmanager def frame(navigation_title: str): """Custom page frame to share the same styling and behavior across all pages""" - ui.colors(primary='#6E93D6', secondary='#53B689', accent='#111B1E', positive='#53B689') + ui.colors(primary='#023047', secondary='#219ebc', accent='#8ecae6', positive='#ffb703', negative='#fb8500') with ui.header(): - ui.label('Awana Verse Practice').classes('font-bold') + ui.label('Awana Verse Practice').classes('font-bold font-16') ui.space() ui.space() ui.space() ui.space() - ui.label(navigation_title) + with ui.row(): + ui.link('Admin', '/').classes(replace='text-white') + ui.link('Dashboard', '/dashboard').classes(replace='text-white') with ui.column().classes('absolute-center items-center'): yield