From 7225cbe89c2d9fac9eff6733a3ce66e5abd6c719 Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Fri, 9 May 2025 12:00:29 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Notizfunktion=20f=C3=BCr=20Administrator=20?= =?UTF-8?q?hinzugef=C3=BCgt=20Anzeige=20f=C3=BCr=20Benutzernotizen=20im=20?= =?UTF-8?q?Administrationsbereich?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin.py | 81 +++++++++++++++++++++++++++++++++---- users.py | 21 ++++++++-- users/testuser1/2025-5.json | 11 +++++ 3 files changed, 103 insertions(+), 10 deletions(-) diff --git a/admin.py b/admin.py index 704d313..dc9f2f7 100644 --- a/admin.py +++ b/admin.py @@ -131,7 +131,7 @@ def page_admin(): current_user = user(time_user.value) # Archivstatus - with ui.grid(columns='auto auto 1fr 1fr 1fr 1fr') as table_grid: + with ui.grid(columns='auto 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)) @@ -169,6 +169,7 @@ def page_admin(): # Überschriften ui.markdown("**Datum**") ui.markdown("**Buchungen**") + ui.space() ui.markdown("**Ist**") ui.markdown("**Soll**") ui.markdown("**Saldo**") @@ -304,6 +305,22 @@ Dies kann nicht rückgängig gemacht werden!''') if archive_status: timestamp_button.disable() + # Notizen anzeigen + days_notes = current_user.get_day_notes(select_year.value, select_month.value, day) + if days_notes != { }: + with ui.icon('o_description').classes('text-2xl'): + with ui.tooltip(): + with ui.grid(columns='auto auto'): + for username, text in days_notes.items(): + admins_name = load_adminsettings()["admin_user"] + if username == admins_name: + ui.markdown('Administrator:') + else: + ui.markdown(user(username).fullname) + ui.markdown(text) + else: + ui.space() + # Arbeitszeit Ist bestimmen timestamps_of_this_day = [] @@ -477,12 +494,60 @@ Dies kann nicht rückgängig gemacht werden!''') dialog.open() dialog.move(calendar_card) + def edit_notes(day): + notes = current_user.get_day_notes(select_year.value, select_month.value, day) + def del_note_entry(user): + del(notes[user]) + username_labels[user].delete() + note_labels[user].delete() + del_buttons[user].delete() + + def save_notes(): + if not note_labels[admin_settings["admin_user"]].is_deleted: + notes[admin_settings["admin_user"]] = note_labels[admin_settings["admin_user"]].value + current_user.write_notes(select_year.value, select_month.value, day, notes) + timetable.refresh() + dialog.close() + + with ui.dialog() as dialog, ui.card(): + # Notizen + username_labels = { } + note_labels = { } + del_buttons = { } + + ui.markdown(f'**Notizen für {day}.{current_month}.{current_year}**') + with ui.grid(columns='auto auto auto'): + admin_settings = load_adminsettings() + # Beschreibungsfeld für Admin + username_labels[admin_settings["admin_user"]] = ui.markdown("Administrator:") + # Textarea für Admin + note_labels[admin_settings["admin_user"]] = ui.textarea() + + for name, text in notes.items(): + if name != admin_settings["admin_user"]: + user_obj = user(name) + noteuser = user_obj.username + username_labels[noteuser] = ui.markdown(user_obj.fullname) + note_labels[noteuser] = ui.markdown(text) + else: + noteuser = admin_settings["admin_user"] + note_labels[noteuser].set_value(text) + del_buttons[noteuser] = ui.button(icon='remove', on_click=lambda user=noteuser: del_note_entry(user)) + + with ui.row(): + ui.button("OK", on_click=save_notes) + ui.button("Abbrechen", on_click=dialog.close) + dialog.open() + dialog.move(calendar_card) + 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() + menu_item = ui.menu_item("Notizen bearbeiten", lambda day=day: edit_notes(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 archive_status: @@ -493,12 +558,12 @@ Dies kann nicht rückgängig gemacht werden!''') #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.space().classes('col-span-5') ui.markdown(f"{convert_seconds_to_hours(general_saldo)}").classes('text-right') - ui.markdown("Stunden aus Vormonat").classes('col-span-4 text-right') + ui.markdown("Stunden aus Vormonat").classes('col-span-5 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("Gesamtsaldo").classes('col-span-5 text-right') ui.markdown(f"**{convert_seconds_to_hours(general_saldo + last_months_overtime)}**").classes('text-right') table_grid.move(calendar_card) @@ -507,13 +572,14 @@ Dies kann nicht rückgängig gemacht werden!''') def clear_card(): calendar_card.clear() + button_update.delete() 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() + button_update = ui.button("Aktualisieren", on_click=timetable.refresh) + button_update.move(timetable_header) with ui.tab_panel(settings): with ui.card(): @@ -540,6 +606,7 @@ Dies kann nicht rückgängig gemacht werden!''') ui.notify("Einstellungen gespeichert") timetable.refresh() + ui.markdown("Benutzername des Adminstrators") admin_user = ui.input() admin_user.value = data["admin_user"] @@ -933,7 +1000,7 @@ Dies kann nicht rückgängig gemacht werden!''') def dialog_new_user(): def create_new_user(): if user_name_input.validate(): - print(user_name_input.value) + new_user(user_name_input.value) update_userlist() time_user.set_options(userlist) diff --git a/users.py b/users.py index d9800dd..fc93b72 100644 --- a/users.py +++ b/users.py @@ -262,6 +262,24 @@ class user: except: return { } + def get_day_notes(self, year, month, day): + try: + with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "r") as json_file: + json_data = json.load(json_file) + day_note = json_data["notes"][str(day)] + return day_note + except: + return { } + + def write_notes(self, year, month, day, note_dict): + with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "r") as json_file: + json_data = json.load(json_file) + json_data["notes"][str(day)] = note_dict + json_output = json.dumps(json_data, indent=4) + with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "w") as json_file: + json_file.write(json_output) + + def update_absence(self, year, month, day, absence_type): try: with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "r") as json_file: @@ -375,9 +393,6 @@ class user: time_worked = todays_timestamps[i + 1] - todays_timestamps[i] total_time += time_worked - print(total_time) - print(in_time_stamp) - return [total_time, in_time_stamp] # Benutzer auflisten diff --git a/users/testuser1/2025-5.json b/users/testuser1/2025-5.json index c970b2a..74494a0 100644 --- a/users/testuser1/2025-5.json +++ b/users/testuser1/2025-5.json @@ -4,5 +4,16 @@ "absence": { "14": "U", "2": "SO" + }, + "notes": { + "5": { + "testuser1": "Jo, das ging echt ab.", + "admin": "Streik\n\nUnd anderes" + }, + "4": { + "admin": "Testeintrag" + }, + "2": {}, + "1": {} } } \ No newline at end of file From 363b30b0a8ee1b6a49cb7385357198163bec9f4c Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Fri, 9 May 2025 14:06:58 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Ansichtsfeld=20f=C3=BCr=20User?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homepage.py | 27 +++++++++++++++++++++++++++ users/testuser1/2025-5.json | 6 +++++- users/testuser1/settings.json | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/homepage.py b/homepage.py index 6002eb6..da91d5d 100644 --- a/homepage.py +++ b/homepage.py @@ -92,6 +92,33 @@ def homepage(): month_month_select.set_options(month_dict) month_month_select.enable() + with ui.grid(columns='1fr auto 1fr').classes('w-full justify-center'): + + ui.space() + with ui.expansion("Tagesnotiz", icon='o_description'): + with ui.grid(columns=2): + def button_enabler(): + if daynote.value == "": + save_button.disable() + delete_button.disable() + else: + save_button.enable() + delete_button.enable() + daynote = ui.textarea(on_change=button_enabler).classes('col-span-2') + + save_button = ui.button("Speichern") + save_button.disable() + def del_text(): + daynote.value = "" + delete_button = ui.button("Löschen", on_click=del_text) + delete_button.disable() + + notes = current_user.get_day_notes(today.year, today.month, today.day) + try: + daynote.value = notes[current_user.username] + except: + pass + ui.separator() with ui.grid(columns='1fr auto 1fr').classes('w-full justify-center'): diff --git a/users/testuser1/2025-5.json b/users/testuser1/2025-5.json index 74494a0..9ac3423 100644 --- a/users/testuser1/2025-5.json +++ b/users/testuser1/2025-5.json @@ -14,6 +14,10 @@ "admin": "Testeintrag" }, "2": {}, - "1": {} + "1": {}, + "9": { + "testuser1": "Dieses ist ein Testeintrag.", + "admin": "Das sollte der Testuser nicht sehen" + } } } \ No newline at end of file diff --git a/users/testuser1/settings.json b/users/testuser1/settings.json index 7f31cc1..f4cb50d 100644 --- a/users/testuser1/settings.json +++ b/users/testuser1/settings.json @@ -1,7 +1,7 @@ { "username": "testuser1", "fullname": "Pia Paulina", - "password": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "password": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "workhours": { "2025-05-13": { "1": "4", From ad959e0fea10362f9e76a7f58e3ee14746951e31 Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Tue, 13 May 2025 14:12:14 +0200 Subject: [PATCH 3/3] Vereinfachung Zuordnung Notizen Benutzer oder Admin --- admin.py | 19 +++++++++---------- homepage.py | 26 ++++++++++++++++++-------- users.py | 7 ++++++- users/testuser1/2025-5.json | 9 ++++++--- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/admin.py b/admin.py index dc9f2f7..8853de8 100644 --- a/admin.py +++ b/admin.py @@ -316,7 +316,7 @@ Dies kann nicht rückgängig gemacht werden!''') if username == admins_name: ui.markdown('Administrator:') else: - ui.markdown(user(username).fullname) + ui.markdown(current_user.fullname) ui.markdown(text) else: ui.space() @@ -503,8 +503,8 @@ Dies kann nicht rückgängig gemacht werden!''') del_buttons[user].delete() def save_notes(): - if not note_labels[admin_settings["admin_user"]].is_deleted: - notes[admin_settings["admin_user"]] = note_labels[admin_settings["admin_user"]].value + if not note_labels["admin"].is_deleted: + notes["admin"] = note_labels["admin"].value current_user.write_notes(select_year.value, select_month.value, day, notes) timetable.refresh() dialog.close() @@ -519,18 +519,17 @@ Dies kann nicht rückgängig gemacht werden!''') with ui.grid(columns='auto auto auto'): admin_settings = load_adminsettings() # Beschreibungsfeld für Admin - username_labels[admin_settings["admin_user"]] = ui.markdown("Administrator:") + username_labels["admin"] = ui.markdown("Administrator:") # Textarea für Admin - note_labels[admin_settings["admin_user"]] = ui.textarea() + note_labels["admin"] = ui.textarea() for name, text in notes.items(): - if name != admin_settings["admin_user"]: - user_obj = user(name) - noteuser = user_obj.username - username_labels[noteuser] = ui.markdown(user_obj.fullname) + if name != "admin": + noteuser = "user" + username_labels[noteuser] = ui.markdown(current_user.fullname) note_labels[noteuser] = ui.markdown(text) else: - noteuser = admin_settings["admin_user"] + noteuser = "admin" note_labels[noteuser].set_value(text) del_buttons[noteuser] = ui.button(icon='remove', on_click=lambda user=noteuser: del_note_entry(user)) diff --git a/homepage.py b/homepage.py index da91d5d..a26ca77 100644 --- a/homepage.py +++ b/homepage.py @@ -97,21 +97,31 @@ def homepage(): ui.space() with ui.expansion("Tagesnotiz", icon='o_description'): with ui.grid(columns=2): + status_binder = ValueBinder() + def button_enabler(): if daynote.value == "": - save_button.disable() - delete_button.disable() + status_binder.value = False else: - save_button.enable() - delete_button.enable() + status_binder.value = True daynote = ui.textarea(on_change=button_enabler).classes('col-span-2') + try: + daynote.value = current_user.get_day_notes(today.year, today.month, today.day)["user"] + except: + daynote.value = "" - save_button = ui.button("Speichern") - save_button.disable() + def save_note(): + note_dict = { } + note_dict["user"] = daynote.value + current_user.write_notes(today.year, today.month, today.day, note_dict) + + save_button = ui.button("Speichern", on_click=save_note) + #save_button.disable() def del_text(): daynote.value = "" - delete_button = ui.button("Löschen", on_click=del_text) - delete_button.disable() + delete_button = ui.button("Löschen", on_click=del_text).bind_enabled_from(status_binder, 'value') + #delete_button.disable() + status_binder.value = False notes = current_user.get_day_notes(today.year, today.month, today.day) try: diff --git a/users.py b/users.py index fc93b72..fe9fce5 100644 --- a/users.py +++ b/users.py @@ -274,7 +274,12 @@ class user: def write_notes(self, year, month, day, note_dict): with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "r") as json_file: json_data = json.load(json_file) - json_data["notes"][str(day)] = note_dict + if len(note_dict) == 1: + json_data["notes"][str(day)] = { } + json_data["notes"][str(day)]["user"] = note_dict["user"] + else: + json_data["notes"][str(day)] = note_dict + json_output = json.dumps(json_data, indent=4) with open(f"{self.userfolder}/{int(year)}-{int(month)}.json", "w") as json_file: json_file.write(json_output) diff --git a/users/testuser1/2025-5.json b/users/testuser1/2025-5.json index 9ac3423..d3b1f01 100644 --- a/users/testuser1/2025-5.json +++ b/users/testuser1/2025-5.json @@ -7,17 +7,20 @@ }, "notes": { "5": { - "testuser1": "Jo, das ging echt ab.", + "user": "Jo, das ging echt ab.", "admin": "Streik\n\nUnd anderes" }, "4": { - "admin": "Testeintrag" + "admin": "Testeintrag\n\nZusatzeintrag" }, "2": {}, "1": {}, "9": { - "testuser1": "Dieses ist ein Testeintrag.", + "user": "Dieses ist ein Testeintrag.", "admin": "Das sollte der Testuser nicht sehen" + }, + "12": { + "user": "Testtext" } } } \ No newline at end of file