"No Time Users" hinzugefügt.

This commit is contained in:
Alexander Malzkuhn 2025-10-27 13:47:57 +01:00
parent 47a71ebf44
commit 0b517f2b30
9 changed files with 170 additions and 240 deletions

View File

@ -5,9 +5,9 @@ import os
server = 'gitea.am-td.de'
server_user = 'alexander'
if os.getuid() == 0:
subprocess.run(["docker", "build", "--force-rm", "-t", f"{server}/{server_user}/{app_title.lower()}:{app_version}", "."])
if input("docker-compose erstellen j=JA ") == "j":
#if os.getuid() == 0:
subprocess.run(["docker", "build", "--force-rm", "-t", f"{server}/{server_user}/{app_title.lower()}:{app_version}", "."])
if input("docker-compose erstellen j=JA ") == "j":
userfolder = input("Pfad für Benutzerdaten /users:")
backupfolder = input("Pfad für Backupdaten /backup:")
settingsfolder = input("Pfad für Einstellungen /settings:")
@ -27,5 +27,5 @@ services:
with open('docker-compose.yml', 'w') as docker_compose:
docker_compose.write(docker_compose_content)
else:
print("Es werden Root-Rechte benötigt.")
#else:
# print("Es werden Root-Rechte benötigt.")

View File

@ -4,6 +4,7 @@ import dateutil.easter
from dateutil.easter import *
from nicegui import ui, app, events
from nicegui.functions.navigate import navigate
from nicegui.html import button
from nicegui.events import KeyEventArguments
@ -69,6 +70,13 @@ def page_admin():
def update_userlist():
nonlocal userlist
userlist = list_users()
# Benutzerliste um No Time Users bereinigen
users_to_remove = [ ]
for entry in userlist:
if entry in get_no_time_users_list():
users_to_remove.append(entry)
for i in users_to_remove:
userlist.remove(i)
update_userlist()
@ -763,19 +771,27 @@ def page_admin():
with ui.tab_panel(settings):
with ui.grid(columns='auto auto'):
with ui.card():
ui.label("Administrationsbenutzer:").classes('text-bold')
with ui.grid(columns=2).classes('items-baseline'):
ui.label("Benutzereinstellungen:").classes('text-bold')
with ui.grid(columns=2).classes('items-center'):
ui.label("Benutzer mit Administrationsrechten:")
user_switch_list = []
with ui.element():
with ui.grid(columns=2).classes('gap-y-0'):
for i in list_users():
user_switch_list.append(ui.switch(i))
for i in user_switch_list:
if i.text in get_admin_list():
i.value = True
secret = data["secret"]
ui.separator().classes('col-span-2')
ui.label("Benutzer ohne Zeiterfassung:")
no_time_user_switch_list = [ ]
with ui.grid(columns=2).classes('gap-y-0'):
for i in list_users():
no_time_user_switch_list.append(ui.switch(i))
for item in no_time_user_switch_list:
if item.text in get_no_time_users_list():
item.value = True
with ui.card():
ui.label("Systemeinstellungen:").classes('text-bold')
with ui.grid(columns=2).classes('items-baseline'):
@ -1064,7 +1080,17 @@ def page_admin():
dialog.open()
else:
no_time_users = { }
no_time_users_counter = -1
for i in no_time_user_switch_list:
if i.value == True:
no_time_users_counter += 1
no_time_users[str(no_time_users_counter)] = i.text
old_no_time_users_list = get_no_time_users_list()
write_adminsetting("admin_user", admin_users)
write_adminsetting("no_time_users", no_time_users)
write_adminsetting("port", port.value)
write_adminsetting("secret", secret)
write_adminsetting("touchscreen", touchscreen_switch.value)
@ -1086,6 +1112,12 @@ def page_admin():
reset_visibility.value = False
timetable.refresh()
if not set(old_no_time_users_list) == set(get_no_time_users_list()):
with ui.dialog() as infobox, ui.card():
ui.label("Benutzer ohne Zeiterfassung wurden geändert. Die Seite wird neu geladen.")
ui.button("OK", on_click=ui.navigate.reload)
infobox.open()
with ui.button("Speichern", on_click=save_admin_settings):
with ui.tooltip():
ui.label("Hiermit werden sämtliche oben gemachten Einstellungen gespeichert.\nGgf. müssen Sie die Seite neu laden um die Auswirkungen sichtbar zu machen.").style('white-space: pre-wrap')
@ -1109,8 +1141,6 @@ def page_admin():
else:
delete_info.value = False
delete_binder.value = True
print(delete_info.value)
print(delete_binder.value)
api_key_input.value = current_user.api_key
api_link_column.clear()
@ -1183,7 +1213,7 @@ def page_admin():
ui.label("Benutzername wurde geändert.").classes('text-bold')
ui.label(f"Benutzerdaten werden in den neuen Ordner {username_input.value} verschoben.")
ui.label("Sollen die Einstellungen gespeichert werden?")
with ui.row():
with ui.row().classes('w-full justify-center'):
ui.button("Speichern", on_click=save_settings)
ui.button("Abbrechen", on_click=dialog.close)
dialog.open()
@ -1236,9 +1266,9 @@ def page_admin():
with ui.dialog() as dialog, ui.card():
ui.label("Sollen die Änderungen an den Arbeitsstunden und/oder Urlaubstagen gespeichert werden?")
with ui.row():
with ui.row().classes('justify-center w-full'):
ui.button("Speichern", on_click=save_settings)
ui.button("Abrrechen", on_click=dialog.close)
ui.button("Abbrechen", on_click=dialog.close)
dialog.open()
def delete_workhour_entry():
@ -1342,6 +1372,7 @@ def page_admin():
ui.button("Neu", on_click=new_api_key).tooltip("Neuen API-Schlüssel erzeugen. Wird erst beim Klick auf Speichern übernommen und entsprechende Links und QR-Codes aktualisiert")
ui.label('Aufruf zum Stempeln:')
global api_link_column
with ui.expansion("").classes('w-full'):
with ui.column().classes('gap-0') as api_link_column:
global stamp_link
stamp_link = [ ]

View File

@ -38,6 +38,7 @@ status_out = "ausgestempelt"
standard_adminsettings = { "admin_user": {
0: "admin"},
"no_time_users": { },
"port": "8090",
"secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise",
"times_on_touchscreen": True,

View File

@ -41,15 +41,15 @@ def page_touchscreen():
def set_columns(width):
nonlocal number_of_columns
if width > 1400:
number_of_columns = 6
elif width > 1200:
number_of_columns = 5
elif width > 900:
elif width > 1200:
number_of_columns = 4
elif width > 750:
elif width > 900:
number_of_columns = 3
else:
elif width > 750:
number_of_columns = 2
else:
number_of_columns = 1
user_buttons.refresh()
ui.on('resize', lambda e: set_columns(e.args['width']))
@ -71,11 +71,12 @@ def page_touchscreen():
</script>
''')
with ui.grid(columns=number_of_columns).classes('w-full center'):
with ui.grid(columns=number_of_columns).classes('w-full'):
for name in userlist:
current_user = user(name)
current_button = ui.button(on_click=lambda name=name: button_click(name)).classes(f'w-md h-full min-h-[{admin_settings["button_height"]}px]')
if not current_user.username in get_no_time_users_list():
current_button = ui.button(on_click=lambda name=name: button_click(name)).classes(f'h-full min-h-[{admin_settings["button_height"]}px]')
with current_button:
with ui.grid(columns='1fr 1fr').classes('w-full h-full py-5 items-start'):
@ -120,7 +121,7 @@ def page_touchscreen():
<path style="fill:#D61E1E;" d="M85.85,60.394c-9.086,7.86-17.596,16.37-25.456,25.456l349.914,349.914
c9.086-7.861,17.596-16.37,25.456-25.456L85.85,60.394z"/>
</svg>'''
ui.html(no_photo_svg)
ui.html(no_photo_svg, sanitize=False)
with ui.column().classes('' if admin_settings["photos_on_touchscreen"] else 'col-span-2'):
ui.label(current_user.fullname).classes('text-left text-xl text.bold')
if admin_settings["times_on_touchscreen"]:

View File

@ -583,3 +583,8 @@ def get_admin_list():
admin_list = load_adminsettings()["admin_user"]
return admin_list.values()
def get_no_time_users_list():
adnin_settings = load_adminsettings()
admin_list = load_adminsettings()["no_time_users"]
return admin_list.values()

View File

@ -41,6 +41,7 @@ class login_mask:
if username.value in get_admin_list():
current_user = user(username.value)
if hash_password(password.value) == current_user.password:
if not username.value in get_no_time_users_list():
with ui.dialog() as forward_dialog, ui.card():
ui.label("Wollen Sie den Administrationsbereich oder den Datenbereich aufrufen?")
def admin_area():
@ -49,12 +50,14 @@ class login_mask:
def time_area():
app.storage.user['active_user'] = current_user.username
ui.navigate.to(self.target)
with ui.grid(columns=2):
with ui.grid(columns=2).classes('justify-center w-full'):
ui.button("Administrationsbereich", on_click=admin_area)
ui.button("Datenbereich", on_click=time_area)
forward_dialog.open()
#ui.navigate.to("/admin")
else:
app.storage.user['admin_authenticated'] = True
ui.navigate.to("/admin")
else:
ui.notify("Login fehlgeschlagen")
else:

View File

@ -1,131 +0,0 @@
aiofiles==24.1.0
aiohappyeyeballs==2.6.1
aiohttp==3.11.16
aiosignal==1.3.2
altgraph==0.17.4
annotated-types==0.7.0
anyio==4.9.0
attrs==25.3.0
Babel==2.10.3
beautifulsoup4==4.11.2
bidict==0.23.1
blinker==1.5
Brlapi==0.8.4
certifi==2025.1.31
chardet==5.1.0
charset-normalizer==3.0.1
click==8.1.8
crit==3.17.1
cryptography==38.0.4
cupshelpers==1.0
dbus-python==1.3.2
distro==1.8.0
distro-info==1.5+deb12u1
docker==5.0.3
docker-compose==1.29.2
dockerpty==0.4.1
docopt==0.6.2
docutils==0.21.2
easygui==0.98.1
fastapi==0.115.12
feedgenerator==2.0.0
frozenlist==1.5.0
gitdb==4.0.9
GitPython==3.1.30
gpg==1.18.0
h11==0.14.0
html5lib==1.1
httpcore==1.0.8
httplib2==0.20.4
httptools==0.6.4
httpx==0.28.1
idna==3.3
ifaddr==0.2.0
imaplib2==3.5
invoke==2.0.0
itsdangerous==2.2.0
Jinja2==3.1.6
jsonpointer==2.3
jsonschema==4.10.3
lazr.restfulclient==0.14.5
lazr.uri==1.0.6
louis==3.24.0
lxml==4.9.2
Mako==1.2.4.dev0
Markdown==3.4.1
markdown-it-py==2.1.0
markdown2==2.5.3
MarkupSafe==2.1.2
mdurl==0.1.2
menulibre==2.2.2
multidict==6.4.3
nicegui==2.15.0
ntpsec==1.2.2
numpy==2.2.5
oauthlib==3.2.2
olefile==0.46
opencv-python==4.11.0.86
orjson==3.10.16
packaging==25.0
pelican==4.8.0
photocollage==1.4.5
Pillow==9.4.0
playsound3==3.2.3
propcache==0.3.1
protobuf==4.21.12
pscript==0.7.7
psutil==5.9.4
pycairo==1.20.1
pycups==2.0.1
pydantic==2.11.3
pydantic_core==2.33.1
pyenchant==3.2.2
Pygments==2.19.1
PyGObject==3.42.2
pygtkspellcheck==4.0.5
pyinstaller==6.13.0
pyinstaller-hooks-contrib==2025.4
PyJWT==2.6.0
pyparsing==3.0.9
pyrsistent==0.18.1
pysmbc==1.0.23
python-apt==2.6.0
python-dateutil==2.8.2
python-dotenv==1.1.0
python-engineio==4.12.0
python-multipart==0.0.20
python-socketio==5.13.0
pytz==2022.7.1
pyxdg==0.28
PyYAML==6.0.2
requests==2.32.3
rfc3987==1.3.8
rich==13.3.1
roman==3.3
segno==1.6.6
simple-websocket==1.1.0
six==1.16.0
smmap==5.0.0
sniffio==1.3.1
soupsieve==2.3.2
starlette==0.46.2
texttable==1.6.7
typing-inspection==0.4.0
typing_extensions==4.13.2
Unidecode==1.3.6
uritemplate==4.1.1
urllib3==2.4.0
uvicorn==0.34.1
uvloop==0.21.0
vboxapi==1.0
vbuild==0.8.2
wadllib==1.3.6
watchfiles==1.0.5
webcolors==1.11.1
webencodings==0.5.1
websocket-client==1.2.3
websockets==15.0.1
wsproto==1.2.0
wxPython==4.2.0
xdg==5
yarl==1.19.0

View File

@ -3,13 +3,16 @@
"0": "admin",
"1": "admin2"
},
"no_time_users": {
"0": "admin"
},
"port": "8090",
"secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise",
"times_on_touchscreen": true,
"photos_on_touchscreen": true,
"touchscreen": true,
"picture_height": 200,
"button_height": 300,
"button_height": "300",
"user_notes": true,
"vacation_application": true,
"backup_folder": "/home/alexander/Dokumente/Python/Zeiterfassung/backup",

17
settings/settings.json Normal file
View File

@ -0,0 +1,17 @@
{
"admin_user": {
"0": "admin"
},
"port": "8090",
"secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise",
"times_on_touchscreen": true,
"photos_on_touchscreen": true,
"touchscreen": true,
"picture_height": 200,
"button_height": 300,
"user_notes": true,
"vacation_application": true,
"backup_folder": "/backup",
"backup_api_key": "0b3b1d883b915bd2f05ee4d256d97a404df67a93",
"holidays": {}
}