from datetime import datetime import dateutil.easter from dateutil.easter import * from nicegui import ui, app, events from users import * from definitions import * from calendar import monthrange from web_ui import * import os.path import hashlib import calendar import locale @ui.page('/admin') def page_admin(): ui.page_title(f"{app_title} {app_version}") data = load_adminsettings() try: browser_cookie = app.storage.user['admin_authenticated'] except: browser_cookie = False # Adminseite if browser_cookie: pageheader("Administration") def admin_logout(): app.storage.user.pop("admin_authenticated", None) ui.navigate.to("/") ui.button("Logout", on_click=admin_logout) with ui.tabs() as tabs: time_overview = ui.tab('Zeitübersichten') settings = ui.tab('Einstellungen') users = ui.tab('Benutzer') with (((ui.tab_panels(tabs, value=time_overview)))): with ui.tab_panel(time_overview): ui.markdown("##Übersichten") # Tabelle konstruieren with ui.card(): with ui.row() as timetable_header: year_binder = ValueBinder() month_binder = ValueBinder() def update_months(): current_user = user(time_user.value) available_months = current_user.get_months(year_binder.value) available_months_dict = { } for element in available_months: available_months_dict[element] = calendar.month_name[int(element)] select_month.clear() select_month.set_options(available_months_dict) select_month.value = list(available_months)[0] def update_user(): current_user = user(time_user.value) available_years = current_user.get_years() select_year.clear() select_year.set_options(available_years) try: select_year.value = str(datetime.datetime.now().year) except: select_year.value = list(available_years)[0] try: select_month.value = datetime.datetime.now().month except: select_month.value = list(available_months)[0] userlist = list_users() ui.markdown("Benutzer:") time_user = ui.select(options=userlist, value=userlist[0], on_change=update_user) user_to_select_for_start = userlist[0] current_year = datetime.datetime.now().year current_month = datetime.datetime.now().month current_user = user(user_to_select_for_start) available_years = current_user.get_years() available_months = current_user.get_months(current_year) available_months_dict = { } for element in available_months: available_months_dict[element] = calendar.month_name[int(element)] if current_month in available_months: set_month = current_month else: set_month = available_months[0] if str(current_year) in available_years: set_year = str(current_year) else: set_year = (available_years[0]) select_month = ui.select(options=available_months_dict, value=set_month).bind_value_to(month_binder, 'value') select_year = ui.select(options=available_years, value=set_year, on_change=update_months).bind_value_to(year_binder, 'value') month_header = ui.markdown(f"###Buchungen für **{current_user.fullname}** für **{calendar.month_name[int(select_month.value)]} {select_year.value}**") # Tabelle aufbauen with ui.card() as calendar_card: def update_month_and_year(): with ui.grid(columns='auto auto 1fr 1fr 1fr 1fr') as table_grid: ui.markdown("**Datum**") ui.markdown("**Buchungen**") ui.markdown("**Ist**") ui.markdown("**Soll**") ui.markdown("**Saldo**") ui.space() current_user = user(time_user.value) timestamps = current_user.get_timestamps(year=select_year.value, month=select_month.value) user_absent = current_user.get_absence(year=select_year.value, month=select_month.value) # Dictionary für sortierte Timestamps timestamps_dict = { } # Dictionary mit zunächst leeren Tageinträgen befüllen for day in range(1, monthrange(int(select_year.value), int(select_month.value))[1] + 1): # Jeder Tag bekommt eine leere Liste timestamps_dict[day] = [ ] # Alle Timestamps durchgehen und sie den Dictionaryeinträgen zuordnen: for stamp in timestamps: day_of_month_of_timestamp = int(datetime.datetime.fromtimestamp(int(stamp)).strftime("%-d")) timestamps_dict[day_of_month_of_timestamp].append(int(stamp)) general_saldo = 0 for day in list(timestamps_dict): # Datum für Tabelle konstruieren day_in_list = datetime.datetime(int(select_year.value), int(select_month.value), day) class_content = "" if day_in_list.date() == datetime.datetime.now().date(): class_content = 'font-bold text-red-700 uppercase' ui.markdown(f"{day_in_list.strftime('%a')}., {day}. {calendar.month_name[int(select_month.value)]}").classes(class_content) # Buchungen with ui.row(): def delete_absence(day, absence_type): def execute_deletion(): current_user.del_absence(select_year.value, select_month.value, day) calendar_card.clear() update_month_and_year() dialog.close() ui.notify("Abwesenheitseintrag gelöscht") with ui.dialog() as dialog, ui.card(): ui.markdown(f'''Soll der Eintrag **{absence_type}** für den **{day}. {calendar.month_name[int(select_month.value)]} {select_year.value}** gelöscht werden? Dies kann nicht rückgägig gemacht werden!''') with ui.grid(columns=3): ui.button("Ja", on_click=execute_deletion) ui.space() ui.button("Nein", on_click=dialog.close) dialog.open() try: for i in list(user_absent): if int(i) == day: ui.button(absence_entries[user_absent[i]]["name"], on_click=lambda i=i, day=day: delete_absence(day, absence_entries[user_absent[i]]["name"])).props(f'color={absence_entries[user_absent[i]]["color"]}') except: pass day_type = ui.markdown("Kein Arbeitstag") day_type.set_visibility(False) # Hier werden nur die Tage mit Timestamps behandelt if len(timestamps_dict[day]) > 0: timestamps_dict[day].sort() def edit_entry(t_stamp, day): with ui.dialog() as edit_dialog, ui.card(): ui.markdown("**Eintrag bearbeiten**") timestamp = datetime.datetime.fromtimestamp(int(t_stamp)) input_time = ui.time().props('format24h now-btn').classes('w-full justify-center') input_time.value = timestamp.strftime('%H:%M') def save_entry(day): nonlocal t_stamp t_stamp = f"{t_stamp}\n" position = timestamps.index(t_stamp) new_time_stamp = datetime.datetime(int(select_year.value), int(select_month.value), day, int(input_time.value[:2]), int(input_time.value[-2:])) timestamps[position] = str( int(new_time_stamp.timestamp())) + "\n" current_user = user(time_user.value) current_user.write_edited_timestamps(timestamps, select_year.value, select_month.value) edit_dialog.close() calendar_card.clear() update_month_and_year() month_header.set_content( f"###Buchungen für {calendar.month_name[int(select_month.value)]} {select_year.value}") ui.notify("Eintrag gespeichert") def del_entry(): nonlocal t_stamp t_stamp = f"{t_stamp}\n" timestamps.remove(t_stamp) timestamps.sort() current_user = user(time_user.value) current_user.write_edited_timestamps(timestamps, select_year.value, select_month.value) edit_dialog.close() calendar_card.clear() update_month_and_year() month_header.set_content( f"###Buchungen für {calendar.month_name[int(select_month.value)]} {select_year.value}") ui.notify("Eintrag gelöscht") with ui.row(): ui.button("Speichern", on_click=lambda day=day: save_entry(day)) ui.button("Löschen", on_click=del_entry) ui.button("Abbrechen", on_click=edit_dialog.close) edit_dialog.open() for i in range(len(timestamps_dict[day])): try: temp_pair = [ timestamps_dict[day][i] , timestamps_dict[day][i+1] ] with ui.card(): with ui.row(): for j in temp_pair: ui.button(datetime.datetime.fromtimestamp(int(j)).strftime('%H:%M'), on_click=lambda t_stamp=j, day=day: edit_entry(t_stamp, day)) except: if len(timestamps_dict[day]) % 2 != 0: with ui.card(): ui.button(datetime.datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M'), on_click=lambda t_stamp=timestamps_dict[day][i], day=day: edit_entry(t_stamp, day)) # Arbeitszeit Ist bestimmen timestamps_of_this_day = [] # Suche mir alle timestamps für diesen Tag for i in timestamps: actual_timestamp = datetime.datetime.fromtimestamp(int(i)) timestamp_day = actual_timestamp.strftime('%-d') if int(timestamp_day) == int(day): timestamps_of_this_day.append(i) timestamps_of_this_day.sort() time_sum = 0 if len(timestamps_of_this_day) > 1: if len(timestamps_of_this_day) % 2 == 0: for i in range(0, len(timestamps_of_this_day), 2): time_delta = int( timestamps_of_this_day[i + 1]) - int( timestamps_of_this_day[i]) time_sum = time_sum + time_delta else: for i in range(0, len(timestamps_of_this_day) - 1, 2): time_delta = int( timestamps_of_this_day[i + 1]) - int( timestamps_of_this_day[i]) time_sum = time_sum + time_delta ui.markdown(convert_seconds_to_hours(time_sum)).classes('text-right') else: ui.markdown("Kein") # Arbeitszeitsoll bestimmen hours_to_work = int(current_user.get_day_workhours(select_year.value, select_month.value, day)) if hours_to_work < 0: ui.space() else: ui.markdown(f"{convert_seconds_to_hours(int(hours_to_work) * 3600)}").classes('text-right') if int(hours_to_work) == 0: day_type.content = "**Kein Arbeitstag**" day_type.set_visibility(True) if day_in_list.strftime("%Y-%m-%d") in data["holidays"]: day_type.content = f'**{data["holidays"][day_in_list.strftime("%Y-%m-%d")]}**' # Saldo für den Tag berechnen if time.time() > day_in_list.timestamp(): time_duty = int(current_user.get_day_workhours(select_year.value, select_month.value, day)) * 3600 if time_duty < 0: ui.space() else: saldo = int(time_sum) - int(time_duty) # Nach Abwesenheitseinträgen suchen try: for i in list(user_absent): if int(i) == day and user_absent[i] != "UU": saldo = 0 except: pass general_saldo = general_saldo + saldo ui.markdown(convert_seconds_to_hours(saldo)).classes('text-right') else: ui.markdown("-").classes('text-center') def add_entry(day): with ui.dialog() as add_dialog, ui.card(): ui.markdown("###Eintrag hinzufügen") input_time = ui.time().classes('w-full justify-center') def add_entry_save(): if input_time.value == None: ui.notify("Bitte eine Uhrzeit auswählen.") return new_time_stamp = datetime.datetime(int(year_binder.value), int(month_binder.value), day, int(input_time.value[:2]), int(input_time.value[-2:])).timestamp() current_user = user(time_user.value) current_user.timestamp(stamptime=int(new_time_stamp)) calendar_card.clear() update_month_and_year() add_dialog.close() ui.notify("Eintrag hinzugefügt") with ui.grid(columns=3): ui.button("Speichern", on_click=add_entry_save) ui.space() ui.button("Abbrechen", on_click=add_dialog.close) add_dialog.open() add_dialog.move(calendar_card) def add_absence(absence_type, day): with ui.dialog() as dialog, ui.card().classes('w-[350px]'): ui.markdown(f'Für welchen Zeitraum soll *{absence_entries[absence_type]["name"]}* eingetragen werden?').classes('w-full') absence_dates = ui.date().props('range today-btn').classes('w-full justify-center') absence_dates._props['locale'] = {'daysShort': ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'], 'months': ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 'monthsShort': ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']} absence_dates._props['title'] = absence_entries[absence_type]["name"] absence_dates._props['minimal'] = True if day < 10: day = f"0{str(day)}" else: day = str(day) if int(select_month.value) < 10: month = f"0{select_month.value}" else: month = select_month.value absence_dates.value = f"{select_year.value}-{month}-{day}" def add_absence_save(): # Bei nur einem Datum, direkt schreiben if isinstance(absence_dates.value, str): absence_date = absence_dates.value.split("-") current_user.update_absence(absence_date[0], absence_date[1], absence_date[2], absence_type) current_sel_month = select_month.value current_sel_year = select_year.value update_user() update_months() select_year.value = current_sel_year select_month.value = current_sel_month calendar_card.clear() update_month_and_year() # Bei Zeitbereich, aufteilen elif isinstance(absence_dates.value, dict): start_date = absence_dates.value["from"] end_date = absence_dates.value["to"] start_date = start_date.split("-") end_date = end_date.split("-") start_year = int(start_date[0]) end_year = int(end_date[0]) start_month = int(start_date[1]) end_month = int(end_date[1]) start_day = int(start_date[2]) end_day = int(end_date[2]) start_date = datetime.datetime(start_year, start_month, start_day) end_date = datetime.datetime(end_year, end_month, end_day) actual_date = start_date while actual_date <= end_date: absences = current_user.get_absence(actual_date.year, actual_date.month) if str(actual_date.day) in list(absences): current_user.del_absence(actual_date.year, actual_date.month, actual_date.day) ui.notify(f"Eintrag {absence_entries[absences[str(actual_date.day)]]['name']} am {actual_date.day}.{actual_date.month}.{actual_date.year} überschrieben.") current_user.update_absence(actual_date.year, actual_date.month, actual_date.day, absence_type) actual_date = actual_date + datetime.timedelta(days=1) clear_card() ui.notify("Einträge vorgenomomen") dialog.close() with ui.grid(columns=3).classes('w-full justify-center'): ui.button("Speichern", on_click=add_absence_save) ui.space() ui.button("Abbrechen", on_click=dialog.close) dialog.open() dialog.move(calendar_card) with ui.button(icon='menu'): with ui.menu() as menu: ui.menu_item("Zeiteintrag hinzufügen", lambda day=day: add_entry(day)) ui.separator() for i in list(absence_entries): menu_item = ui.menu_item(f"{absence_entries[i]['name']} eintragen", lambda absence_type=i, day=day: add_absence(absence_type, day)) if str(day) in list(user_absent): menu_item.disable() #ui.button("Eintrag hinzufügen", on_click=lambda day=day: add_entry(day)) #4x leer und dann Gesamtsaldo ui.space().classes('col-span-4') ui.markdown(f"{convert_seconds_to_hours(general_saldo)}").classes('text-right') ui.markdown("Stunden aus Vormonat").classes('col-span-4 text-right') last_months_overtime = current_user.get_last_months_overtime(select_year.value, select_month.value) ui.markdown(f"{convert_seconds_to_hours(last_months_overtime)}").classes('text-right') ui.markdown("Gesamtsaldo").classes('col-span-4 text-right') ui.markdown(f"**{convert_seconds_to_hours(general_saldo + last_months_overtime)}**").classes('text-right') table_grid.move(calendar_card) update_month_and_year() def clear_card(): calendar_card.clear() update_month_and_year() current_user = user(time_user.value) month_header.set_content(f"###Buchungen für **{current_user.fullname}** für **{calendar.month_name[int(select_month.value)]} {select_year.value}**") button_update = ui.button("Aktualisieren", on_click=clear_card) button_update.move(timetable_header) with ui.tab_panel(settings): with ui.card(): ui.markdown("**Administrationsbenutzer:**") with ui.grid(columns=2): def save_admin_settings(): output_dict = { } output_dict["admin_user"] = admin_user.value if admin_password.value != "": output_dict["admin_password"] = hash_password(admin_password.value) else: output_dict["admin_password"] = data["admin_password"] output_dict["port"] = port.value output_dict["secret"] = secret output_dict["holidays"] = data["holidays"] json_dict = json.dumps(output_dict, indent=4) with open(f"{scriptpath}/{usersettingsfilename}", "w") as outputfile: outputfile.write(json_dict) if int(old_port) != int(port.value): with ui.dialog() as dialog, ui.card(): ui.markdown("Damit die Porteinstellungen wirksam werden, muss der Server neu gestartet werden.") ui.button("OK", on_click=lambda: dialog.close()) dialog.open() ui.notify("Einstellungen gespeichert") ui.markdown("Benutzername des Adminstrators") admin_user = ui.input() admin_user.value = data["admin_user"] ui.markdown("Passwort des Administrators") admin_password = ui.input(password=True) secret = data["secret"] with ui.card(): ui.markdown("**Systemeinstellungen:**") with ui.grid(columns=2): ui.markdown("Port:") port = ui.input() old_port = data["port"] port.value = old_port def holiday_section(): with ui.card(): ui.markdown('**Feiertage:**') def new_holiday_entry(): def add_holiday_to_dict(): year_from_picker = int(datepicker.value.split("-")[0]) month_from_picker = int(datepicker.value.split("-")[1]) day_from_picker = int(datepicker.value.split("-")[2]) for i in range(0, int(repetition.value)): repetition_date_dt = datetime.datetime(year_from_picker + i, month_from_picker, day_from_picker) date_entry = repetition_date_dt.strftime('%Y-%m-%d') data["holidays"][date_entry] = description.value print(data['holidays']) holiday_buttons_grid.refresh() dialog.close() with ui.dialog() as dialog, ui.card(): with ui.grid(columns='auto auto'): ui.markdown('Geben Sie den neuen Feiertag ein:').classes('col-span-2') datepicker = ui.date(value=datetime.datetime.now().strftime('%Y-%m-%d')).classes('col-span-2') description = ui.input('Beschreibung').classes('col-span-2') repetition = ui.number('Für Jahre wiederholen', value=1, min=1, precision=0).classes('col-span-2') ui.button("OK", on_click=add_holiday_to_dict) ui.button('Abbrechen', on_click=dialog.close) dialog.open() @ui.refreshable def holiday_buttons_grid(): holidays = list(data["holidays"]) holidays.sort() year_list = [] # Jahresliste erzeugen for i in holidays: i_split = i.split("-") year = int(i_split[0]) year_list.append(year) year_list = list(set(year_list)) year_dict = {} # Jahresdictionary konstruieren for i in year_list: year_dict[i] = [] for i in holidays: i_split = i.split("-") year = int(i_split[0]) month = int(i_split[1]) day = int(i_split[2]) date_dt = datetime.datetime(year, month, day) year_dict[year].append(date_dt) def del_holiday_entry(entry): del(data['holidays'][entry.strftime('%Y-%m-%d')]) holiday_buttons_grid.refresh() def defined_holidays(): with ui.dialog() as dialog, ui.card(): ui.markdown("Bitte wählen Sie aus, welche Feiertage eingetragen werden sollen. Vom Osterdatum abhängige Feiertage werden für die verschiedenen Jahre berechnet.:") with ui.grid(columns='auto auto'): with ui.column().classes('gap-0'): # Auswahlen für Feiertage checkbox_classes = 'py-0' new_year = ui.checkbox("Neujahr (1. Januar)").classes(checkbox_classes) heilige_drei_koenige = ui.checkbox("Heilige Drei Könige (6. Januar)").classes(checkbox_classes) womens_day = ui.checkbox("Internationaler Frauentag (8. März)").classes(checkbox_classes) gruendonnerstag = ui.checkbox("Gründonnerstag (berechnet").classes(checkbox_classes) karfreitag = ui.checkbox("Karfreitag (berechnet").classes(checkbox_classes) easter_sunday = ui.checkbox("Ostersonntag (berechnet)").classes(checkbox_classes) easter_monday = ui.checkbox("Ostermontag (berechnet)").classes(checkbox_classes) first_of_may = ui.checkbox("Tag der Arbeit (1. Mai)").classes(checkbox_classes) liberation_day = ui.checkbox("Tag der Befreiung (8. Mai)").classes(checkbox_classes) ascension_day = ui.checkbox("Christi Himmelfahrt (berechnet)").classes(checkbox_classes) whitsun_sunday = ui.checkbox("Pfingssonntag (berechnet)").classes(checkbox_classes) whitsun_monday = ui.checkbox("Pfingsmontag (berechnet)").classes(checkbox_classes) fronleichnam = ui.checkbox("Fronleichnam (berechnet)").classes(checkbox_classes) peace_party = ui.checkbox("Friedensfest (Augsburg - 8. August)").classes(checkbox_classes) mary_ascension = ui.checkbox("Mariä Himmelfahrt (15. August)").classes(checkbox_classes) childrens_day = ui.checkbox("Weltkindertag (20. September)").classes(checkbox_classes) unity_day = ui.checkbox("Tag der deutschen Einheit (3. Oktober)").classes(checkbox_classes) reformation_day = ui.checkbox("Reformationstag (30. Oktober)").classes(checkbox_classes) all_hallows = ui.checkbox("Allerheiligen (1. November)").classes(checkbox_classes) praying_day = ui.checkbox("Buß- und Bettag (berechnet)").classes(checkbox_classes) christmas_day = ui.checkbox("1. Weihnachtsfeiertag (25. Dezember)").classes(checkbox_classes) boxing_day = ui.checkbox("2. Weihnachtsfeiertag (26. Dezember)").classes(checkbox_classes) def enter_holidays(): for year in range (int(starting_year.value), int(end_year.value) + 1): ostersonntag = dateutil.easter.easter(year) if new_year.value: data["holidays"][f"{year}-01-01"] = f"Neujahr" if heilige_drei_koenige.value: data["holidays"][f"{year}-01-06"] = f"Hl. Drei Könige" if womens_day.value: data["holidays"][f"{year}-03-08"] = f"Intern. Frauentag" if gruendonnerstag.value: datum_dt = ostersonntag - datetime.timedelta(days=3) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Gründonnerstag" if karfreitag.value: datum_dt = ostersonntag - datetime.timedelta(days=2) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Karfreitag" if easter_sunday.value: datum_dt = ostersonntag datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = "Ostersonntag" if easter_monday.value: datum_dt = ostersonntag + datetime.timedelta(days=1) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = "Ostermontag" if first_of_may.value: data["holidays"][f"{year}-05-01"] = f"Tage der Arbeit" if liberation_day.value: data["holidays"][f"{year}-05-08"] = f"Tag der Befreiung" if ascension_day.value: datum_dt = ostersonntag + datetime.timedelta(days=39) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Christi Himmelfahrt" if whitsun_sunday.value: datum_dt = ostersonntag + datetime.timedelta(days=49) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Pfingssonntag" if whitsun_monday.value: datum_dt = ostersonntag + datetime.timedelta(days=49) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Pfingstmontag" if fronleichnam.value: datum_dt = ostersonntag + datetime.timedelta(days=60) datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Fronleichnam" if peace_party.value: data["holidays"][f"{year}-08-08"] = f"Friedensfest" if mary_ascension.value: data["holidays"][f"{year}-08-15"] = f"Mariä Himmelfahrt" if childrens_day.value: data["holidays"][f"{year}-09-20"] = f"Intern. Kindertag" if unity_day.value: data["holidays"][f"{year}-10-03"] = f"Tag der deutschen Einheit" if reformation_day.value: data["holidays"][f"{year}-10-30"] = f"Reformationstag" if all_hallows.value: data["holidays"][f"{year}-11-01"] = f"Allerheiligen" if praying_day.value: starting_day = datetime.datetime(year, 11 ,23) for i in range(1, 8): test_day = starting_day - datetime.timedelta(days=-i) if test_day.weekday() == 2: datum_dt = test_day break datum = datum_dt.strftime("%Y-%m-%d") data["holidays"][f"{datum}"] = f"Bu0- und Bettag" if christmas_day.value: data["holidays"][f"{year}-12-25"] = f"1. Weihnachtsfeiertag" if boxing_day.value: data["holidays"][f"{year}-12-26"] = f"2. Weihnachtsfeiertag" dialog.close() holiday_buttons_grid.refresh() with ui.column(): starting_year = ui.number(value=datetime.datetime.now().year, label="Startjahr") end_year = ui.number(value=starting_year.value, label="Endjahr") with ui.row(): ui.button("Anwenden", on_click=enter_holidays) ui.button("Abbrechen", on_click=dialog.close) dialog.open() with ui.grid(columns='auto auto'): ui.space() with ui.row(): ui.button("Gesetzliche Feiertage eintragen", on_click=defined_holidays) ui.button("Eigener Eintrag", on_click=new_holiday_entry) ui.separator().classes('col-span-2') for year_entry in year_list: ui.markdown(f"{str(year_entry)}:") with ui.row(): for entry in year_dict[year_entry]: date_label = entry.strftime("%d.%m.") ui.button(f"{data['holidays'][entry.strftime('%Y-%m-%d')]} ({date_label})", on_click=lambda entry=entry: del_holiday_entry(entry)).classes('text-sm') holiday_buttons_grid() holiday_section() ui.button("Speichern", on_click=save_admin_settings) with ui.tab_panel(users): ui.markdown("###Benutzerverwaltung") userlist = list_users() userlist.sort() workhours = [ ] with ui.row(): def user_selection_changed(): try: if user_selection.value != None: current_user = user(user_selection.value) username_input.value = current_user.username fullname_input.value = current_user.fullname #password_input.value = current_user.password usersettingscard.visible = True workhours_select.clear() workhour_list = list(current_user.workhours) workhour_list.sort() workhours_select.set_options(workhour_list) workhours_select.value = workhour_list[0] workinghourscard.visible = True user_photo.set_source(current_user.photofile) user_photo.force_reload() user_photo.set_visibility(os.path.exists(current_user.photofile)) delete_button.set_visibility(os.path.exists(current_user.photofile)) except: pass # workhours_selection_changed(list(current_user.workhours)[0]) def workhours_selection_changed(): if workhours_select.value != None: current_user = user(user_selection.value) selected_workhours = current_user.workhours[workhours_select.value] for key, hours in selected_workhours.items(): try: days[int(key)-1].value = hours except: if key == 0: days[6].value = hours elif key == "vacation": vacation_input.value = hours def save_user_settings(): def save_settings(): current_user = user(user_selection.value) current_user.username = username_input.value current_user.fullname = fullname_input.value current_user.password = hash_password(password_input.value) current_user.write_settings() password_input.value = "" userlist = list_users() userlist.sort() user_selection.clear() user_selection.set_options(userlist) user_selection.value = current_user.username dialog.close() ui.notify("Einstellungen gespeichert") with ui.dialog() as dialog, ui.card(): if user_selection.value != username_input.value: ui.markdown("**Benutzername wurde geändert.**") ui.markdown(f"Benutzerdaten werden in den neuen Ordner {username_input.value}") ui.markdown("Sollen die Einstellungen gespeichert werden?") with ui.row(): ui.button("Speichern", on_click=save_settings) ui.button("Abbrechen", on_click=dialog.close) dialog.open() def del_user(): current_user = user(user_selection.value) def del_definitely(): current_user.del_user() userlist = list_users() userlist.sort() user_selection.clear() user_selection.set_options(userlist) user_selection.value = userlist[0] dialog.close() ui.notify("Benutzer gelöscht") with ui.dialog() as dialog, ui.card(): ui.markdown(f"Soll der Benutzer *{current_user.username}* gelöscht werden?") ui.markdown("**Dies kann nicht rückgängig gemacht werden?**") with ui.row(): ui.button("Löschen", on_click=del_definitely) ui.button("Abbrechen", on_click=dialog.close) dialog.open() def save_workhours(): def save_settings(): current_user = user(user_selection.value) construct_dict = { } for i in range(7): if i < 7: construct_dict[i+1] = days[i].value elif i == 7: construct_dict[0] = days[i].value construct_dict["vacation"] = vacation_input.value current_user.workhours[workhours_select.value] = construct_dict current_user.write_settings() dialog.close() ui.notify("Einstellungen gespeichert") with ui.dialog() as dialog, ui.card(): ui.markdown("Sollen die Änderungen an den Arbeitsstunden und/oder Urlaubstagen gespeichert werden?") with ui.row(): ui.button("Speichern", on_click=save_settings) ui.button("Abrrechen", on_click=dialog.close) dialog.open() def delete_workhour_entry(): def delete_entry(): current_user = user(user_selection.value) del current_user.workhours[workhours_select.value] current_user.write_settings() workhour_list = list(current_user.workhours) workhours_select.clear() workhours_select.set_options(workhour_list) workhours_select.set_value(workhour_list[-1]) #workhours_selection_changed(current_user.workhours[0]) dialog.close() ui.notify("Eintrag gelöscht" "") with ui.dialog() as dialog, ui.card(): current_user = user(user_selection.value) if len(current_user.workhours) > 1: ui.markdown(f"Soll der Eintrag *{workhours_select.value}* wirklich gelöscht werden?") ui.markdown("**Dies kann nicht rückgängig gemacht werden.**") with ui.row(): ui.button("Löschen", on_click=delete_entry) ui.button("Abbrechen", on_click=dialog.close) else: ui.markdown("Es gibt nur einen Eintrag. Dieser kann nicht gelöscht werden.") ui.button("OK", on_click=dialog.close) dialog.open() with ui.column(): user_selection = ui.select(options=userlist, with_input=True, on_change=user_selection_changed) user_selection.value = userlist[0] ui.button("Neu") with ui.column(): with ui.card() as usersettingscard: ui.markdown("**Benutzereinstellungen**") with ui.grid(columns=2): ui.markdown("Benutzername:") username_input = ui.input() ui.markdown("Voller Name:") fullname_input = ui.input() ui.markdown("Passwort") password_input = ui.input(password=True) password_input.value = "" with ui.grid(columns=2): ui.button("Speichern", on_click=save_user_settings) ui.button("Löschen", on_click=del_user) with ui.card() as photocard: ui.markdown('**Foto**') current_user = user(user_selection.value) user_photo = ui.image(current_user.photofile) def handle_upload(e: events.UploadEventArguments): picture = e.content.read() current_user = user(user_selection.value) with open(current_user.photofile, 'wb') as outoutfile: outoutfile.write(picture) uploader.reset() user_selection_changed() def del_photo(): current_user = user(user_selection.value) current_user.delete_photo() user_selection_changed() uploader = ui.upload(label="Foto hochladen", on_upload=handle_upload).props('accept=.jpg|.jpeg').classes('max-w-full') delete_button = ui.button("Löschen", on_click=del_photo) with ui.card() as workinghourscard: workhours = [] ui.markdown("**Arbeitszeiten**") with ui.card(): def calculate_weekhours(): sum = 0 for i in range(7): try: sum = float(days[i].value) + sum except: pass workhours_sum.set_content(str(sum)) with ui.grid(columns=2): ui.markdown("gültig ab:") workhours_select = ui.select(options=workhours, on_change=workhours_selection_changed) days = [ ] weekdays = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"] counter = 0 for day in weekdays: ui.markdown(f"{day}:") days.append(ui.input(on_change=calculate_weekhours)) counter = counter + 1 ui.separator().classes('col-span-full') ui.markdown("**Summe:**") workhours_sum = ui.markdown() with ui.card(): with ui.grid(columns=2): ui.markdown("Urlaubstage") vacation_input = ui.input() with ui.row(): ui.button("Speichern", on_click=save_workhours) ui.button("Löschen", on_click=delete_workhour_entry) def new_workhours_entry(): current_user = user(user_selection.value) def add_workhours_entry(): workhours_dict = { } for i in range(7): workhours_dict[i] = 0 workhours_dict["vacation"] = 0 current_user.workhours[date_picker.value] = workhours_dict current_user.write_settings() workhours_select.clear() workhours_list = list(current_user.workhours) workhours_list.sort() workhours_select.set_options(workhours_list) workhours_select.value = date_picker.value dialog.close() ui.notify("Eintrag angelegt") with ui.dialog() as dialog, ui.card(): ui.markdown("Geben Sie das Gültigkeitsdatum an, ab wann die Einträge gültig sein sollen.") date_picker = ui.date() with ui.row(): ui.button("OK", on_click=add_workhours_entry) ui.button("Abbrechen", on_click=dialog.close) dialog.open() ui.button("Neu", on_click=new_workhours_entry) user_selection_changed() # Alternativ zur Loginseite navigieren else: login = login_mask() #ui.navigate.to("/login")