"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,13 +5,13 @@ 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":
userfolder = input("Pfad für Benutzerdaten /users:")
backupfolder = input("Pfad für Backupdaten /backup:")
settingsfolder = input("Pfad für Einstellungen /settings:")
docker_compose_content = f'''
#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:")
docker_compose_content = f'''
services:
zeiterfassung:
image: {server}/{server_user}/{app_title.lower()}:{app_version.lower()}
@ -25,7 +25,7 @@ services:
- {backupfolder}:/backup
- {settingsfolder}:/settings'''
with open('docker-compose.yml', 'w') as docker_compose:
docker_compose.write(docker_compose_content)
else:
print("Es werden Root-Rechte benötigt.")
with open('docker-compose.yml', 'w') as docker_compose:
docker_compose.write(docker_compose_content)
#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,11 +1372,12 @@ 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.column().classes('gap-0') as api_link_column:
global stamp_link
stamp_link = [ ]
for i in app.urls:
stamp_link.append(ui.link(f'{i}/api/stamp/"API-Schüssel"'))
with ui.expansion("").classes('w-full'):
with ui.column().classes('gap-0') as api_link_column:
global stamp_link
stamp_link = [ ]
for i in app.urls:
stamp_link.append(ui.link(f'{i}/api/stamp/"API-Schüssel"'))
ui.label("Administratoren können nicht gelöscht werden. Um das Konto zu löschen, müssen Sie ihm zuerst die Administrationsrechte entziehen.").bind_visibility_from(delete_info, 'value').classes('font-bold text-red')
with ui.grid(columns=2):

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,76 +71,77 @@ 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'):
with current_button:
with ui.grid(columns='1fr 1fr').classes('w-full h-full py-5 items-start'):
if admin_settings["photos_on_touchscreen"]:
image_size = int(admin_settings["picture_height"])
try:
with open(current_user.photofile, 'r') as file:
pass
ui.image(current_user.photofile).classes(f'max-h-[{image_size}px]').props('fit=scale-down')
except:
no_photo_svg = f'''<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="{image_size/2}px" width="{image_size/2}px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 496.158 496.158" xml:space="preserve">
<path style="fill:#D61E1E;" d="M248.082,0.003C111.07,0.003,0,111.063,0,248.085c0,137.001,111.07,248.07,248.082,248.07
c137.006,0,248.076-111.069,248.076-248.07C496.158,111.062,385.088,0.003,248.082,0.003z"/>
<path style="fill:#F4EDED;" d="M248.082,39.002C132.609,39.002,39,132.602,39,248.084c0,115.463,93.609,209.072,209.082,209.072
c115.467,0,209.076-93.609,209.076-209.072C457.158,132.602,363.549,39.002,248.082,39.002z"/>
<g>
<path style="fill:#5B5147;" d="M145.23,144.237h-24.44c-3.21,0-5.819,4.741-5.819,10.605s2.609,10.611,5.819,10.611h24.44
c3.217,0,5.826-4.747,5.826-10.611C151.057,148.978,148.447,144.237,145.23,144.237z"/>
<path style="fill:#5B5147;" d="M380.289,172.06H226.545c-2.025-9.851-9.416-17.176-18.244-17.176h-92.199
c-10.403,0-18.818,10.125-18.818,22.592V328.9c0,10.254,8.314,18.581,18.58,18.581h264.425c10.262,0,18.586-8.327,18.586-18.581
V190.655C398.875,180.38,390.551,172.06,380.289,172.06z"/>
</g>
<path style="fill:#F4EDED;" d="M248.076,166.711c-51.133,0-92.604,41.462-92.604,92.602c0,51.146,41.471,92.608,92.604,92.608
c51.139,0,92.6-41.462,92.6-92.608C340.676,208.174,299.215,166.711,248.076,166.711z"/>
<path style="fill:#5B5147;" d="M248.086,171.416c-48.547,0-87.909,39.355-87.909,87.909c0,48.537,39.362,87.898,87.909,87.898
c48.543,0,87.896-39.361,87.896-87.898C335.981,210.771,296.629,171.416,248.086,171.416z"/>
<path style="fill:#F4EDED;" d="M248.611,205.005c-29.992,0-54.312,24.31-54.312,54.308c0,29.991,24.319,54.321,54.312,54.321
s54.318-24.33,54.318-54.321C302.93,229.315,278.603,205.005,248.611,205.005z"/>
<path style="fill:#5B5147;" d="M248.611,209.528c-27.494,0-49.789,22.286-49.789,49.786c0,27.494,22.295,49.798,49.789,49.798
c27.496,0,49.795-22.304,49.795-49.798C298.406,231.814,276.107,209.528,248.611,209.528z"/>
<g>
<path style="fill:#F4EDED;" d="M230.224,215.002c-14.401,0-26.065,11.674-26.065,26.067c0,14.399,11.664,26.073,26.065,26.073
c14.391,0,26.065-11.674,26.065-26.073C256.289,226.676,244.614,215.002,230.224,215.002z"/>
<path style="fill:#F4EDED;" d="M159.698,165.453h-45.712c-3.756,0-6.805,3.045-6.805,6.792v25.594c0,3.04,2.004,5.575,4.756,6.448
c0.65,0.209,1.328,0.35,2.049,0.35h45.712c3.76,0,6.793-3.04,6.793-6.798v-25.594C166.491,168.498,163.458,165.453,159.698,165.453
z"/>
</g>
<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)
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"]:
todays_timestamps = current_user.get_day_timestamps()
# Wenn wir Einträge haben
if len(todays_timestamps) > 0 and admin_settings["times_on_touchscreen"]:
table_string = ""
for i in range(0, len(todays_timestamps), 2):
try:
table_string += f"{datetime.datetime.fromtimestamp(todays_timestamps[i]).strftime('%H:%M')} - {datetime.datetime.fromtimestamp(todays_timestamps[i+1]).strftime('%H:%M')}"
except IndexError:
table_string += f"{datetime.datetime.fromtimestamp(todays_timestamps[i]).strftime('%H:%M')} -"
if i < len(todays_timestamps) - 2:
table_string += "\n"
ui.label(table_string).style('white-space: pre-wrap').classes('text-left')
if current_user.stamp_status() == status_in:
current_button.props('color=green')
else:
current_button.props('color=red')
buttons[name] = current_button
if admin_settings["photos_on_touchscreen"]:
image_size = int(admin_settings["picture_height"])
try:
with open(current_user.photofile, 'r') as file:
pass
ui.image(current_user.photofile).classes(f'max-h-[{image_size}px]').props('fit=scale-down')
except:
no_photo_svg = f'''<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="{image_size/2}px" width="{image_size/2}px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 496.158 496.158" xml:space="preserve">
<path style="fill:#D61E1E;" d="M248.082,0.003C111.07,0.003,0,111.063,0,248.085c0,137.001,111.07,248.07,248.082,248.07
c137.006,0,248.076-111.069,248.076-248.07C496.158,111.062,385.088,0.003,248.082,0.003z"/>
<path style="fill:#F4EDED;" d="M248.082,39.002C132.609,39.002,39,132.602,39,248.084c0,115.463,93.609,209.072,209.082,209.072
c115.467,0,209.076-93.609,209.076-209.072C457.158,132.602,363.549,39.002,248.082,39.002z"/>
<g>
<path style="fill:#5B5147;" d="M145.23,144.237h-24.44c-3.21,0-5.819,4.741-5.819,10.605s2.609,10.611,5.819,10.611h24.44
c3.217,0,5.826-4.747,5.826-10.611C151.057,148.978,148.447,144.237,145.23,144.237z"/>
<path style="fill:#5B5147;" d="M380.289,172.06H226.545c-2.025-9.851-9.416-17.176-18.244-17.176h-92.199
c-10.403,0-18.818,10.125-18.818,22.592V328.9c0,10.254,8.314,18.581,18.58,18.581h264.425c10.262,0,18.586-8.327,18.586-18.581
V190.655C398.875,180.38,390.551,172.06,380.289,172.06z"/>
</g>
<path style="fill:#F4EDED;" d="M248.076,166.711c-51.133,0-92.604,41.462-92.604,92.602c0,51.146,41.471,92.608,92.604,92.608
c51.139,0,92.6-41.462,92.6-92.608C340.676,208.174,299.215,166.711,248.076,166.711z"/>
<path style="fill:#5B5147;" d="M248.086,171.416c-48.547,0-87.909,39.355-87.909,87.909c0,48.537,39.362,87.898,87.909,87.898
c48.543,0,87.896-39.361,87.896-87.898C335.981,210.771,296.629,171.416,248.086,171.416z"/>
<path style="fill:#F4EDED;" d="M248.611,205.005c-29.992,0-54.312,24.31-54.312,54.308c0,29.991,24.319,54.321,54.312,54.321
s54.318-24.33,54.318-54.321C302.93,229.315,278.603,205.005,248.611,205.005z"/>
<path style="fill:#5B5147;" d="M248.611,209.528c-27.494,0-49.789,22.286-49.789,49.786c0,27.494,22.295,49.798,49.789,49.798
c27.496,0,49.795-22.304,49.795-49.798C298.406,231.814,276.107,209.528,248.611,209.528z"/>
<g>
<path style="fill:#F4EDED;" d="M230.224,215.002c-14.401,0-26.065,11.674-26.065,26.067c0,14.399,11.664,26.073,26.065,26.073
c14.391,0,26.065-11.674,26.065-26.073C256.289,226.676,244.614,215.002,230.224,215.002z"/>
<path style="fill:#F4EDED;" d="M159.698,165.453h-45.712c-3.756,0-6.805,3.045-6.805,6.792v25.594c0,3.04,2.004,5.575,4.756,6.448
c0.65,0.209,1.328,0.35,2.049,0.35h45.712c3.76,0,6.793-3.04,6.793-6.798v-25.594C166.491,168.498,163.458,165.453,159.698,165.453
z"/>
</g>
<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, 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"]:
todays_timestamps = current_user.get_day_timestamps()
# Wenn wir Einträge haben
if len(todays_timestamps) > 0 and admin_settings["times_on_touchscreen"]:
table_string = ""
for i in range(0, len(todays_timestamps), 2):
try:
table_string += f"{datetime.datetime.fromtimestamp(todays_timestamps[i]).strftime('%H:%M')} - {datetime.datetime.fromtimestamp(todays_timestamps[i+1]).strftime('%H:%M')}"
except IndexError:
table_string += f"{datetime.datetime.fromtimestamp(todays_timestamps[i]).strftime('%H:%M')} -"
if i < len(todays_timestamps) - 2:
table_string += "\n"
ui.label(table_string).style('white-space: pre-wrap').classes('text-left')
if current_user.stamp_status() == status_in:
current_button.props('color=green')
else:
current_button.props('color=red')
buttons[name] = current_button
user_buttons()
else:

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,20 +41,23 @@ class login_mask:
if username.value in get_admin_list():
current_user = user(username.value)
if hash_password(password.value) == current_user.password:
with ui.dialog() as forward_dialog, ui.card():
ui.label("Wollen Sie den Administrationsbereich oder den Datenbereich aufrufen?")
def admin_area():
app.storage.user['admin_authenticated'] = True
ui.navigate.to('/admin')
def time_area():
app.storage.user['active_user'] = current_user.username
ui.navigate.to(self.target)
with ui.grid(columns=2):
ui.button("Administrationsbereich", on_click=admin_area)
ui.button("Datenbereich", on_click=time_area)
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():
app.storage.user['admin_authenticated'] = True
ui.navigate.to('/admin')
def time_area():
app.storage.user['active_user'] = current_user.username
ui.navigate.to(self.target)
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")
forward_dialog.open()
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": {}
}