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

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")