You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
7.3 KiB
205 lines
7.3 KiB
from nicegui import ui, app |
|
from datetime import datetime, timedelta |
|
from montydb import MontyClient |
|
from montydb.types.objectid import ObjectId |
|
import locale |
|
from pages import manager, user, useredit, index |
|
import signal |
|
import os |
|
import shutil |
|
|
|
from fastapi.responses import RedirectResponse |
|
from fastapi.responses import FileResponse |
|
|
|
class CallbackHandler: |
|
def __init__(self): |
|
self.callbacks = {} |
|
|
|
def register_callback(self, event_name, func): |
|
if event_name not in self.callbacks: |
|
self.callbacks[event_name] = [] |
|
self.callbacks[event_name].append(func) |
|
|
|
def execute_callbacks(self, event_name, *args, **kwargs): |
|
if event_name in self.callbacks: |
|
for callback in self.callbacks[event_name][:]: |
|
try: |
|
callback(*args, **kwargs) |
|
except Exception as e: |
|
print(f"Error executing callback {callback}: {e}") |
|
self.callbacks[event_name].remove(callback) |
|
|
|
|
|
handler = CallbackHandler() |
|
|
|
passwords = {'admin': [0,'sw1ng3rs',0, "Matteo Benedetto"], 'user': [1,'pass',1, "Pippo"]} |
|
# Set the locale to Italian |
|
locale.setlocale(locale.LC_ALL, 'it_IT.utf8') |
|
|
|
def styling(): |
|
ui.colors(primary='black', secondary="lightgray") |
|
ui.query('body').style(f'font-family: sans-serif') |
|
ui.add_head_html('<meta name="theme-color" content="#000000"/>') |
|
|
|
def login_check(): |
|
if not app.storage.user.get('authenticated', False): |
|
return False |
|
else: |
|
return True |
|
|
|
# Create a connection |
|
conn = MontyClient("db") |
|
# Access your database |
|
db = conn.letsswing |
|
|
|
|
|
# Routes |
|
@ui.page('/manager/{sede}/{livello}', title="Let's Swing Admin", favicon="assets/favicon.ico") |
|
def manager_page(sede:int, livello:int) -> None: |
|
if not login_check(): |
|
return RedirectResponse('/login') |
|
styling() |
|
|
|
manage = manager.Manager(handler) |
|
manage.main(db, sede, livello) |
|
|
|
# Routes |
|
app.add_static_files('/static', 'static') |
|
|
|
@ui.page('/', title="Let's Swing Admin", favicon="assets/favicon.ico") |
|
def index_page() -> None: |
|
|
|
if not login_check(): |
|
return RedirectResponse('/login') |
|
styling() |
|
index.main(db) |
|
|
|
|
|
@ui.page('/user/{userid}', title="Let's Swing Admin", favicon="assets/favicon.ico") |
|
def user_page(userid: str) -> None: |
|
if not login_check(): |
|
return RedirectResponse('/login') |
|
styling() |
|
user.main(userid, db, handler) |
|
|
|
@ui.page('/edit/{userid}/{sede}/{livello}', title="Let's Swing Admin", favicon="assets/favicon.ico") |
|
def useredit_page(userid: str, sede: int, livello: int) -> None: |
|
if not login_check(): |
|
return RedirectResponse('/login') |
|
styling() |
|
useredit.main(userid, sede, livello, db, handler) |
|
|
|
@ui.page('/backup/{password}') |
|
def api_backup(password: str) -> None: |
|
if password != "1337swing": |
|
return {'msg':'password errata'} |
|
|
|
# Percorso completo del file zip |
|
filename = "backup_db_" +datetime.now().strftime('%Y%m%d%H%M%S') |
|
zip_path = os.path.join('backup', filename) |
|
|
|
# Crea il file zip |
|
shutil.make_archive(zip_path, 'zip', "db") |
|
|
|
return FileResponse(path=zip_path + '.zip', media_type='application/octet-stream', filename=filename+".zip") |
|
|
|
|
|
|
|
@ui.page('/login',title="Let's Swing Admin", favicon="assets/favicon.ico") |
|
def page_login() -> None: |
|
styling() |
|
def try_login() -> None: # local function to avoid passing username and password as arguments |
|
if passwords.get(username.value)[1] == password.value: |
|
app.storage.user.update({'username': username.value, 'authenticated': True, 'id' : passwords.get(username.value)[0], "level": passwords.get(username.value)[2], "name": passwords.get(username.value)[3]}) |
|
ui.open('/') |
|
else: |
|
ui.notify('username o password errata', color='negative') |
|
|
|
if app.storage.user.get('authenticated', False): |
|
return RedirectResponse('/') |
|
ui.add_head_html(''' |
|
<link rel="manifest" href="/manifest.json"> |
|
<meta name="description" content="managing application for "let's swing" association of Matera, Italy"> |
|
<style> |
|
.hbtn { |
|
opacity: 0; |
|
visibility: hidden; |
|
transition: visibility 0s linear 0.5s, opacity 0.5s linear; |
|
} |
|
|
|
.hbtn.visible { |
|
opacity: 1; |
|
visibility: visible; |
|
transition-delay: 0s; |
|
} |
|
</style> |
|
''') |
|
ui.add_body_html(''' |
|
<script> |
|
let deferredPrompt; |
|
|
|
window.addEventListener('beforeinstallprompt', (e) => { |
|
// Prevent Chrome 67 and earlier from automatically showing the prompt |
|
e.preventDefault(); |
|
// Stash the event so it can be triggered later. |
|
deferredPrompt = e; |
|
// Update UI notify the user they can add to home screen |
|
btnAdd.style.display = 'block'; |
|
}); |
|
|
|
</script>''') |
|
async def install(): |
|
await ui.run_javascript(''' |
|
// Show the prompt |
|
if(!deferredPrompt) |
|
alert("Browser non compatibile"); |
|
deferredPrompt.prompt(); |
|
// Wait for the user to respond to the prompt |
|
deferredPrompt.userChoice.then((choiceResult) => { |
|
if (choiceResult.outcome === 'accepted') { |
|
console.log('User accepted the A2HS prompt'); |
|
} else { |
|
console.log('User dismissed the A2HS prompt'); |
|
} |
|
deferredPrompt = null; |
|
|
|
});''', respond=False) |
|
async def installable(btn): |
|
response = await ui.run_javascript(''' |
|
return (deferredPrompt ? true : false); |
|
''') |
|
if response: |
|
btn.classes("hbtn visible") |
|
|
|
with ui.card().classes('absolute-center items-center'): |
|
install_btn =ui.button('Installa App', on_click=install,icon="install_mobile").classes("hbtn").props("outline") |
|
ui.timer(1, lambda: installable(install_btn), once=True) |
|
|
|
ui.image('assets/logo.svg') |
|
ui.label('Let\'s Swing Admin').classes('text-2xl').style("text-align:center") |
|
username = ui.input('Username').on('keydown.enter', try_login).classes('w-full') |
|
password = ui.input('Password', password=True, password_toggle_button=True).on('keydown.enter', try_login) |
|
ui.button('Log in', on_click=try_login) |
|
|
|
ui.add_body_html('''<script>if ('serviceWorker' in navigator) { |
|
window.addEventListener('load', function() { |
|
navigator.serviceWorker.register('/static/service-worker.js').then(function(registration) { |
|
// Registration was successful |
|
console.log('ServiceWorker registration successful with scope: ', registration.scope); |
|
}, function(err) { |
|
// registration failed :( |
|
console.log('ServiceWorker registration failed: ', err); |
|
}); |
|
}); |
|
}</script>''') |
|
|
|
|
|
# PWA conversion |
|
@ui.page('/manifest.json') |
|
def manifest_json() -> None: |
|
|
|
return FileResponse(path='assets/site.webmanifest', filename="site.webmanifest") |
|
|
|
|
|
# Run main loop |
|
ui.run(host="0.0.0.0", port=9999, storage_secret='5w1ng4ndn0th1ngm0r3',language="it")
|
|
|