import datetime from datetime import datetime from nicegui import ui, app from users import * from definitions import * from calendar import monthrange import hashlib import calendar import locale locale.setlocale(locale.LC_ALL, '') class pageheader: def __init__(self, heading): self.heading = heading ui.markdown(f"##{app_title} {app_version}") ui.markdown(f"###{self.heading}") def cookie_hash(user, password): return hashlib.sha256(b"{user}{app.storage.user['id']}{password}").hexdigest() def load_adminsettings(): # Settingsdatei einlesen try: with open(f"{scriptpath}/{usersettingsfilename}") as json_file: data = json.load(json_file) json_file.close() return(data) except: return(-1) def convert_seconds_to_hours(seconds): if seconds < 0: sign = "-" seconds = seconds * (-1) else: sign = "" hours = seconds // 3600 remaining_seconds = seconds - hours * 3600 minutes = remaining_seconds // 60 remaining_seconds = remaining_seconds - minutes * 60 if remaining_seconds > 0 and sign != "-": minutes = minutes + 1 if hours < 10: hours = "0" + str(hours) else: hours = str(hours) if minutes < 10: minutes = "0" + str(minutes) else: minutes = str(minutes) if sign == "-": return(f"-{hours}:{minutes}") else: return(f"{hours}:{minutes}") @ui.page('/login') def page_login(): # Settingsdatei einlesen data = load_adminsettings() def login(): nonlocal data if username.value == data["admin_user"]: if password.value == data["admin_password"]: active_login = cookie_hash(data["admin_user"], data["admin_password"]) app.storage.user['secret'] = active_login ui.navigate.to("/admin") else: ui.notify("Login fehlgeschlagen") #ui.markdown(f"## {app_title} {app_version}") #ui.markdown("Bitte einloggen") pageheader("Bitte einloggen:") with ui.grid(columns=2): ui.markdown("Benutzer:") username = ui.input('Benutzername') ui.markdown("Passwort:") password = ui.input('Passwort', password=True) ui.button(text="Login", on_click=lambda: login()) @ui.page('/admin') def page_admin(): data = load_adminsettings() active_login = cookie_hash(data["admin_user"], data["admin_password"]) try: browser_cookie = app.storage.user['secret'] except: browser_cookie = "" # Adminseite if browser_cookie == active_login: pageheader("Administration") def admin_logout(): app.storage.user['secret'] = "" ui.navigate.to("/login") ui.button("Logout", on_click=admin_logout) with ui.tabs() as tabs: time_overview = ui.tab('Zeitübersichten') admin_user = ui.tab('Admin Benutzer') users = ui.tab('Benutzer') settings = ui.tab('Einstellungen') 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: def update_months(): current_user = user(time_user.value) available_months = current_user.get_months(select_year.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] userlist = list_users() ui.markdown("Benutzer:") time_user = ui.select(options=userlist) time_user.value = userlist[0] current_year = datetime.datetime.now().year current_month = datetime.datetime.now().month current_user = user(time_user.value) 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)] select_month = ui.select(options=available_months_dict) select_year = ui.select(options=available_years, on_change=update_months) try: select_year.value = str(current_year) except: pass try: select_month.value = str(current_month) except: select_month.value = str(available_months[0]) month_header = ui.markdown(f"###Buchungen 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=6) as table_grid: ui.markdown("**Datum**") ui.markdown("**Buchungen**") ui.markdown("**Soll**") ui.markdown("**Ist**") ui.markdown("**Saldo**") ui.space() current_user = user(time_user.value) timestamps = current_user.get_timestamps(year=select_year.value, month=select_month.value) general_saldo = 0 for day in range(1, monthrange(int(select_year.value), int(select_month.value))[1] + 1): day_in_list = datetime.datetime(int(select_year.value), int(select_month.value), day) ui.markdown(f"{day_in_list.strftime('%a')}., {day}. {calendar.month_name[int(select_month.value)]}") # ---> Hier die Schleife für die Buchungen with ui.row(): counter = 0 for i in timestamps: actual_timestamp = datetime.datetime.fromtimestamp(int(i)) timestamp_day = actual_timestamp.strftime('%-d') if int(timestamp_day) == int(day): 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().classes('w-full justify-center') input_time.value = timestamp.strftime('%H:%M') def save_entry(day): 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" # print(timestamps) 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(): 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() counter += 1 ui.button(actual_timestamp.strftime('%H:%M'), on_click=lambda t_stamp=i, day=day: edit_entry(t_stamp, day)) #if counter % 2 == 0: # current_button.props('color=red') #else: # current_button.props('color=green') # Arbeitszeitsoll bestimmen workhour_entries = list(current_user.workhours) workhour_entries.sort() found_match = False for entry in reversed(workhour_entries): if datetime.datetime.strptime(entry, '%Y-%m-%d').timestamp() < day_in_list.timestamp() and found_match == False: if int(day_in_list.strftime('%w')) == 0: weekday_index = 7 else: weekday_index = int(day_in_list.strftime('%w')) ui.markdown(f"{current_user.workhours[entry][str(weekday_index)]} h") found_match = True # 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)) else: ui.markdown("Kein") # Plus und Minuszeit für den Tag berechnen if time.time() > day_in_list.timestamp(): time_duty = int(current_user.workhours[entry][str(weekday_index)]) * 3600 saldo = int(time_sum) - int(time_duty) general_saldo = general_saldo + saldo ui.markdown(convert_seconds_to_hours(saldo)) else: ui.markdown("-") 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(select_year.value), int(select_month.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") ui.button("Speichern", on_click=add_entry_save) ui.button("Abbrechen", on_click=add_dialog.close) add_dialog.open() ui.button("Eintrag hinzufügen", on_click=lambda day=day: add_entry(day)) #4x leer und dann Gesamtsald for i in range(4): ui.space() ui.markdown(f"{convert_seconds_to_hours(general_saldo)}") table_grid.move(calendar_card) update_month_and_year() def clear_card(): 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}") button_update = ui.button("Aktualisieren", on_click=clear_card) button_update.move(timetable_header) with ui.tab_panel(admin_user): with ui.grid(columns=2): def save_admin_settings(): output_dict = { } output_dict["admin_user"] = admin_user.value output_dict["adnin_password"] = admin_password.value json_dict = json.dumps(output_dict, indent=4) with open(f"{scriptpath}/{usersettingsfilename}", "w") as outputfile: outputfile.write(json_dict) ui.notify("Einstellungen gespeichert") ui.label("Benutzername des Adminstrators") admin_user = ui.input() admin_user.value = data["admin_user"] ui.label("Passwort des Adminsistrators") admin_password = ui.input(password=True) admin_password.value = data["admin_password"] 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 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 = password_input.value current_user.write_settings() 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: conctruct_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.label("Benutzername:") username_input = ui.input() ui.label("Voller Name:") fullname_input = ui.input() ui.label("Passwort") password_input = ui.input(password=True) 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 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: ui.navigate.to("/login") @ui.page('/stamping') def page_stamping(): ui.label('Stempelsteite') @ui.page('/touchscreen') def page_touchscreen(): def button_click(name): nonlocal buttons current_user = user(name) current_user.timestamp() if current_user.stamp_status() == status_in: buttons[name].props('color=green') ui.notify(status_in) else: buttons[name].props('color=red') ui.notify(status_out) pageheader("Bitte User auswählen:") userlist = list_users() number_of_users = len(userlist) buttons = { } if number_of_users > 5: number_of_columns = 5 else: number_of_columns = number_of_users with ui.grid(columns=number_of_columns): for name in userlist: current_user = user(name) current_button = ui.button(on_click=lambda name=name: button_click(name)) with current_button: try: with open(current_user.photofile, 'r') as file: pass file.close() ui.image(current_user.photofile) except: pass ui.label(current_user.fullname) if current_user.stamp_status() == status_in: current_button.props('color=green') else: current_button.props('color=red') buttons[name] = current_button @ui.page('/userlist') def page_userlist(): def click_button(button): ui.notify(button) ui.markdown(f"#{app_title} {app_version}") userlist = list_users() buttons = { } for name in userlist: button = ui.button(text=name, on_click=lambda name=name:click_button(name) ) buttons[name] = button ui.run(port=8090, storage_secret="test")