diff --git a/admin.py b/admin.py
index 2de4ffc..b3dc822 100644
--- a/admin.py
+++ b/admin.py
@@ -112,344 +112,392 @@ def page_admin():
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()
-
-
+ @ui.refreshable
+ def timetable():
+ with ui.card() as calendar_card:
+ def update_month_and_year():
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] = [ ]
+ # Archivstatus
- # 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')
+ with ui.grid(columns='auto auto 1fr 1fr 1fr 1fr') as table_grid:
+ if int(select_month.value) > 1:
+ archive_status = current_user.get_archive_status(int(select_year.value),
+ int(select_month.value))
else:
- ui.markdown("Kein")
+ archive_status = current_user.get_archive_status(int(select_year.value) - 1, 12)
- # Arbeitszeitsoll bestimmen
+ def revoke_archive_status():
+ def revoke_status():
+ filename = f"{current_user.userfolder}/{int(select_year.value)}-{int(select_month.value)}.json"
+ with open(filename, 'r') as json_file:
+ data = json.load(json_file)
+ data["archived"] = 0
- 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)
+ json_dict = json.dumps(data)
- if day_in_list.strftime("%Y-%m-%d") in data["holidays"]:
- day_type.content = f'**{data["holidays"][day_in_list.strftime("%Y-%m-%d")]}**'
+ with open(filename, "w") as outputfile:
+ outputfile.write(json_dict)
+ timetable.refresh()
+ dialog.close()
- # Saldo für den Tag berechnen
+ with ui.dialog() as dialog, ui.card():
+ ui.label("Soll der Archivstatus für den aktuellen Monat aufgehoben werden, damit Änderungen vorgenommen werden können?")
+ with ui.grid(columns=2):
+ ui.button("Ja", on_click=revoke_status)
+ ui.button("Nein", on_click=dialog.close)
+ dialog.open()
- if time.time() > day_in_list.timestamp():
+ if archive_status:
+ with ui.row().classes('text-right col-span-6 justify-center'):
+ ui.button("Archiviert", on_click=revoke_archive_status).classes('bg-transparent text-black')
+ ui.separator()
+ calendar_card.classes('bg-yellow')
+ # Überschriften
+ ui.markdown("**Datum**")
+ ui.markdown("**Buchungen**")
+ ui.markdown("**Ist**")
+ ui.markdown("**Soll**")
+ ui.markdown("**Saldo**")
+ ui.space()
+
+ 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()
- 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
+ if int(i) == day:
+ absence_button = 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"]}')
+ if archive_status:
+ absence_button.disable()
except:
pass
- general_saldo = general_saldo + saldo
- ui.markdown(convert_seconds_to_hours(saldo)).classes('text-right')
- else:
- ui.markdown("-").classes('text-center')
+ day_type = ui.markdown("Kein Arbeitstag")
+ day_type.set_visibility(False)
- 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')
+ # Hier werden nur die Tage mit Timestamps behandelt
+ if len(timestamps_dict[day]) > 0:
+ timestamps_dict[day].sort()
- def add_entry_save():
- if input_time.value == None:
- ui.notify("Bitte eine Uhrzeit auswählen.")
- return
+ def edit_entry(t_stamp, day):
- 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)
+ 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().classes('bg-inherit'):
+ with ui.row():
+ for j in temp_pair:
+ timestamp_button = ui.button(datetime.datetime.fromtimestamp(int(j)).strftime('%H:%M'), on_click=lambda t_stamp=j, day=day: edit_entry(t_stamp, day))
+ if archive_status:
+ timestamp_button.disable()
+ except:
+ if len(timestamps_dict[day]) % 2 != 0:
+ with ui.card().classes('bg-inherit'):
+ timestamp_button = 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))
+ if archive_status:
+ timestamp_button.disable()
+
+ # 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()
- 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}"
+ 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
- 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
+ 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)
- # 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("-")
+ 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
- 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])
+ 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}"
- start_date = datetime.datetime(start_year, start_month, start_day)
- end_date = datetime.datetime(end_year, end_month, end_day)
- actual_date = start_date
+ 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()
- while actual_date <= end_date:
- absences = current_user.get_absence(actual_date.year, actual_date.month)
+ # 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("-")
- 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)
+ 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])
- actual_date = actual_date + datetime.timedelta(days=1)
- clear_card()
- ui.notify("Einträge vorgenomomen")
- dialog.close()
+ 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)
+ 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)
+ 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):
+ with ui.button(icon='menu'):
+ with ui.menu() as menu:
+ menu_item = ui.menu_item("Zeiteintrag hinzufügen", lambda day=day: add_entry(day))
+ if archive_status:
menu_item.disable()
+ 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 archive_status:
+ menu_item.disable()
+ if str(day) in list(user_absent):
+ menu_item.disable()
- #ui.button("Eintrag hinzufügen", on_click=lambda day=day: add_entry(day))
+ #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()
+ #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)
- 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)
+ 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)
+ timetable()
with ui.tab_panel(settings):
with ui.card():
diff --git a/api.py b/api.py
index 60634f9..a9d3020 100644
--- a/api.py
+++ b/api.py
@@ -22,8 +22,14 @@ def page_overview_month(username: str, year: int, month: int):
try:
current_user = user(username)
ui.page_title(f"Bericht für {current_user.fullname} für {calendar.month_name[month]} {year}")
- ui.label(datetime.now().strftime('%d.%m.%Y')).classes('absolute top-5 right-5')
- ui.space()
+ if current_user.get_archive_status(year, month):
+ with ui.column().classes('w-full items-end gap-0'):
+ ui.label(f"Bericht erstellt am {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}")
+ ui.label('Archiviert').classes('italic').classes('text-red text-bold text-xl')
+ #ui.add_head_html('')
+ else:
+ with ui.column().classes('w-full items-end gap-0'):
+ ui.label(f"Bericht erstellt am {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}")
ui.markdown(f'#Bericht für {current_user.fullname} für {calendar.month_name[month]} {year}')
pad_x = 4
@@ -55,7 +61,11 @@ def page_overview_month(username: str, year: int, month: int):
general_saldo = 0
- with ui.grid(columns='auto auto 1fr 1fr 1fr').classes(f'gap-0 border px-0 py-0'):
+ bg_color = ''
+ if current_user.get_archive_status(year, month):
+ bg_color = ' bg-yellow-100'
+
+ with ui.grid(columns='auto auto 1fr 1fr 1fr').classes(f'gap-0 border px-0 py-0{bg_color}'):
ui.markdown("**Datum**").classes(f'border px-{pad_x} py-{pad_y}')
ui.markdown("**Buchungen**").classes(f'border px-{pad_x} py-{pad_y}')
ui.markdown("**Ist**").classes(f'border px-{pad_x} py-{pad_y}')
diff --git a/favicon.svg b/favicon.svg
new file mode 100644
index 0000000..ecbb5e4
--- /dev/null
+++ b/favicon.svg
@@ -0,0 +1,118 @@
+
+
diff --git a/main.py b/main.py
index 3da3f94..1b73ccf 100644
--- a/main.py
+++ b/main.py
@@ -22,7 +22,23 @@ def main():
homepage()
- ui.run(port=port, storage_secret=secret, language='de-DE')
+ def startup_message():
+
+ message_string = f"{app_title} {app_version}"
+ underline = ""
+ for i in range(len(message_string)):
+ underline += "-"
+ print(message_string)
+ print(underline)
+
+ url_string = ""
+ for i in list(app.urls):
+ url_string += f"{i}, "
+ url_string = url_string[0:-2]
+ print("Weboberfläche erreichbar unter: " + url_string)
+
+ app.on_startup(startup_message)
+ ui.run(favicon="favicon.svg", port=port, storage_secret=secret, language='de-DE', show_welcome_message=False)
if __name__ in ("__main__", "__mp_main__"):
main()
diff --git a/users/testuser1/2025-5.txt b/users/testuser1/2025-5.txt
index ac88801..eb3add4 100644
--- a/users/testuser1/2025-5.txt
+++ b/users/testuser1/2025-5.txt
@@ -1,2 +1,2 @@
1746385124
-1746385127
+1746388680
diff --git a/web_ui.py b/web_ui.py
index c4b76e6..c1f4048 100644
--- a/web_ui.py
+++ b/web_ui.py
@@ -85,6 +85,9 @@ def convert_seconds_to_hours(seconds):
remaining_seconds = remaining_seconds - minutes * 60
if remaining_seconds > 0 and sign != "-":
minutes = minutes + 1
+ if minutes == 60:
+ hours = hours + 1
+ minutes = 0
if hours < 10:
hours = "0" + str(hours)
else: