From 2df6111bd152f345eaf33c9c4160f2c5ec465d1d Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 11:02:31 +0100 Subject: [PATCH 1/8] Moved unflatten to site.js, implemented Admin.cshtml view --- src/Controllers/SettingsController.cs | 2 +- src/Views/Home/Users.cshtml | 27 --- src/Views/Settings/Admin.cshtml | 290 +++++++++++++++++++++++++- src/wwwroot/js/site.js | 28 ++- 4 files changed, 317 insertions(+), 30 deletions(-) diff --git a/src/Controllers/SettingsController.cs b/src/Controllers/SettingsController.cs index fa01430..5aab3d7 100644 --- a/src/Controllers/SettingsController.cs +++ b/src/Controllers/SettingsController.cs @@ -33,7 +33,7 @@ public class SettingsController : Controller public async Task AdminAsync() { AdminSettingsModel adminSettingsModel = await _ldap.GetAdminSettingsModelAsync(); - return View(); + return View(adminSettingsModel); } [Authorize(Roles = "CanManageSettings")] diff --git a/src/Views/Home/Users.cshtml b/src/Views/Home/Users.cshtml index 4e6d35e..47770e8 100644 --- a/src/Views/Home/Users.cshtml +++ b/src/Views/Home/Users.cshtml @@ -235,33 +235,6 @@ diff --git a/src/wwwroot/js/site.js b/src/wwwroot/js/site.js index bfdde28..5ba6601 100644 --- a/src/wwwroot/js/site.js +++ b/src/wwwroot/js/site.js @@ -239,4 +239,30 @@ function validatePassword(password) { const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_\-+=\[{\]};:'",<.>/?\\|`~]).{8,}$/; return strongPasswordRegex.test(password); -} \ No newline at end of file +} + +function unflatten(obj) { + const result = {}; + for (const [key, value] of Object.entries(obj)) { + const parts = key.split("."); + let current = result; + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + if (i === parts.length - 1) { + if (typeof value === "string" && /^[\[{]/.test(value.trim())) { + try { + current[part] = JSON.parse(value); + } catch { + current[part] = value; + } + } else { + current[part] = value; + } + } else { + current[part] = current[part] || {}; + current = current[part]; + } + } + } + return result; +} From bb1e4c197a55102bfae60dd62311933a5364a4f4 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 11:54:06 +0100 Subject: [PATCH 2/8] Made presets collapsible --- src/Views/Settings/Admin.cshtml | 60 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/Views/Settings/Admin.cshtml b/src/Views/Settings/Admin.cshtml index 3a1fe68..5980139 100644 --- a/src/Views/Settings/Admin.cshtml +++ b/src/Views/Settings/Admin.cshtml @@ -12,7 +12,7 @@ ViewData["Title"] = T["Users"]; } -
+

@T["General settings"]

@@ -44,11 +44,20 @@
-
-

@T["Presets"]

- - @foreach (var preset in Model.Presets) - { +
+

@T["Presets"]

+ +
+ @foreach (var preset in Model.Presets) + { +
@@ -80,15 +89,13 @@
- } -
-
+ } +
+
- - -
+ + + \ No newline at end of file From 770706883a7d6f8b11522dc1e73d2cc0fbf08eb3 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 12:44:52 +0100 Subject: [PATCH 4/8] Added localization for Admin.cshtml, added url-based collapse state --- src/Resources/Views.Settings.Admin.resx | 91 +++++++++++++++++++++++++ src/Views/Settings/Admin.cshtml | 32 ++++++++- src/wwwroot/js/site.js | 4 ++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/Resources/Views.Settings.Admin.resx diff --git a/src/Resources/Views.Settings.Admin.resx b/src/Resources/Views.Settings.Admin.resx new file mode 100644 index 0000000..0f6561c --- /dev/null +++ b/src/Resources/Views.Settings.Admin.resx @@ -0,0 +1,91 @@ + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, ... + + + System.Resources.ResXResourceWriter, System.Windows.Forms, ... + + + + Benutzer + + + + Allgemeine Einstellungen + + + + Standard-Hashalgorithmus + + + + Barcode-Typ + + + + Barcode-Text + + + + Maximale Download-Größe für Benutzerbilder + + + + Voreinstellungen + + + + Name der Voreinstellung + + + + Attribute + + + + Name + + + + Wert + + + + Attribut löschen + + + + Attribut hinzufügen + + + + Voreinstellung löschen + + + + Voreinstellung hinzufügen + + + + Einstellungen übernehmen und Voreinstellungen aktualisieren + + + + Einstellungen erfolgreich aktualisiert + + + + Unbekannter Fehler + + + + Fehler bei der Kommunikation mit dem Server + + diff --git a/src/Views/Settings/Admin.cshtml b/src/Views/Settings/Admin.cshtml index c6d42d4..44fd484 100644 --- a/src/Views/Settings/Admin.cshtml +++ b/src/Views/Settings/Admin.cshtml @@ -84,7 +84,7 @@ }
-
+
@@ -179,10 +179,38 @@ } document.querySelectorAll('[data-bs-toggle="collapse"]').forEach(toggler => { - toggler.addEventListener('click', () => { + toggler.addEventListener('click', async () => { const icon = toggler.querySelector('.chevron-svg'); icon.classList.toggle('rotate'); + var target = document.querySelector(toggler.dataset.bsTarget); + while (target.classList.contains('collapsing')) { + await sleep(10); + } icon.parentElement.classList.toggle("no-bottom-border"); + const collapseId = toggler.dataset.bsTarget.replace('#', ''); + const isCollapsed = target.classList.contains('show'); + // Update URL parameter + const url = new URL(window.location); + url.searchParams.set(collapseId, isCollapsed); // true = open, false = collapsed + window.history.replaceState({}, '', url); + }); + }); + + document.addEventListener('DOMContentLoaded', () => { + const collapseElements = document.querySelectorAll('.collapse'); + + collapseElements.forEach(el => { + const paramValue = new URL(window.location).searchParams.get(el.id); + if (paramValue === 'true') { + el.classList.add('show'); + const toggler = document.querySelector(`[data-bs-target="#${el.id}"]`); + if (toggler) { + toggler.querySelector('.chevron-svg')?.classList.add('rotate'); + toggler.classList.add('no-bottom-border'); + } + } else { + el.classList.remove('show'); + } }); }); diff --git a/src/wwwroot/js/site.js b/src/wwwroot/js/site.js index 5ba6601..5347028 100644 --- a/src/wwwroot/js/site.js +++ b/src/wwwroot/js/site.js @@ -266,3 +266,7 @@ function unflatten(obj) { } return result; } + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file From c8cb61f7666f960fcc746927e5935685a1b9b4f6 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 12:52:29 +0100 Subject: [PATCH 5/8] Updated German Admin.cshtml localization --- src/Resources/Views.Settings.Admin.resx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Resources/Views.Settings.Admin.resx b/src/Resources/Views.Settings.Admin.resx index 0f6561c..1915c86 100644 --- a/src/Resources/Views.Settings.Admin.resx +++ b/src/Resources/Views.Settings.Admin.resx @@ -38,11 +38,11 @@ - Voreinstellungen + Vorlagen - Name der Voreinstellung + Name der Vorlage @@ -66,15 +66,15 @@ - Voreinstellung löschen + Vorlage löschen - Voreinstellung hinzufügen + Vorlage hinzufügen - Einstellungen übernehmen und Voreinstellungen aktualisieren + Einstellungen übernehmen und Vorlagen aktualisieren From fb272ee63c0e76afab337aee51a5389a937fb85d Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 14:50:20 +0100 Subject: [PATCH 6/8] Added presets --- src/Controllers/SettingsController.cs | 8 ++ src/Resources/Views.Shared._Layout.de.resx | 6 ++ src/Views/Home/Assets.cshtml | 102 ++++++++++++++++++++- src/Views/Settings/Admin.cshtml | 2 +- src/Views/Shared/_Layout.cshtml | 4 +- src/wwwroot/js/site.js | 32 +++++++ 6 files changed, 151 insertions(+), 3 deletions(-) diff --git a/src/Controllers/SettingsController.cs b/src/Controllers/SettingsController.cs index 5aab3d7..2bf2d9b 100644 --- a/src/Controllers/SettingsController.cs +++ b/src/Controllers/SettingsController.cs @@ -36,6 +36,14 @@ public class SettingsController : Controller return View(adminSettingsModel); } + [Authorize] + [HttpGet("Presets")] + public async Task> PresetsAsync() + { + AdminSettingsModel adminSettingsModel = await _ldap.GetAdminSettingsModelAsync(); + return adminSettingsModel.Presets; + } + [Authorize(Roles = "CanManageSettings")] [HttpPut("Admin")] public async Task UpdateAdminAsync([FromBody]AdminUpdateRequestModel adminSettingsRequestModel) diff --git a/src/Resources/Views.Shared._Layout.de.resx b/src/Resources/Views.Shared._Layout.de.resx index 54a4121..174cddd 100644 --- a/src/Resources/Views.Shared._Layout.de.resx +++ b/src/Resources/Views.Shared._Layout.de.resx @@ -43,7 +43,13 @@ Fehler beim Laden der Orte + + Fehler beim Laden der Vorlagen + Benutzer auswählen + + Vorlage auswählen + diff --git a/src/Views/Home/Assets.cshtml b/src/Views/Home/Assets.cshtml index 5aca7a3..660a5f8 100644 --- a/src/Views/Home/Assets.cshtml +++ b/src/Views/Home/Assets.cshtml @@ -192,6 +192,18 @@
+

@T["Preset"]

+
+ +
+
+ +
+ +
+

@T["Description"]

@@ -254,7 +266,7 @@
- diff --git a/src/Views/Settings/Admin.cshtml b/src/Views/Settings/Admin.cshtml index 44fd484..eef077f 100644 --- a/src/Views/Settings/Admin.cshtml +++ b/src/Views/Settings/Admin.cshtml @@ -101,7 +101,7 @@ - diff --git a/src/wwwroot/js/site.js b/src/wwwroot/js/site.js index 5347028..c1bd0c8 100644 --- a/src/wwwroot/js/site.js +++ b/src/wwwroot/js/site.js @@ -269,4 +269,36 @@ function unflatten(obj) { function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); +} + +async function loadPresetsIntoSelect(selectElement, selectedValue = null) { + try { + const response = await fetch('/Settings/Presets'); + const responseJson = await response.json(); + var presets = []; + for (var key in responseJson) { + presets.push(key); + } + console.log(presets); + const ts = selectElement.tomselect; + if (!ts) { + selectElement.innerHTML = ``; + presets.forEach(u => { + const opt = document.createElement('option'); + opt.value = u; + opt.textContent = u; + selectElement.appendChild(opt); + }); + return; + } + + ts.clearOptions(); + ts.addOption(presets.map(u => ({ value: u, text: u }))); + ts.refreshOptions(false); + + if (selectedValue) ts.setValue(selectedValue); + } catch (err) { + console.error('Error loading presets:', err); + showToast(appTranslations.errorLoadingPresets, 'danger'); + } } \ No newline at end of file From 888223b31b1f78430abbd1b4ad8bc20494069bb8 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 14:55:00 +0100 Subject: [PATCH 7/8] Fixed missing localization in Assets.cshtml --- src/Resources/Views.Home.Assets.de.resx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Resources/Views.Home.Assets.de.resx b/src/Resources/Views.Home.Assets.de.resx index ee05dec..8a80ddd 100644 --- a/src/Resources/Views.Home.Assets.de.resx +++ b/src/Resources/Views.Home.Assets.de.resx @@ -178,4 +178,13 @@ Datum + + Vorlage + + + Vorlage auswählen + + + Vorlage anwenden + From 89ac080f0a4591c2664f60d2dbfa55b454acf9a8 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 15 Nov 2025 15:28:04 +0100 Subject: [PATCH 8/8] Fixed barcode settings not applying for Assets.cshtml --- src/Views/Home/Assets.cshtml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Views/Home/Assets.cshtml b/src/Views/Home/Assets.cshtml index 660a5f8..a477187 100644 --- a/src/Views/Home/Assets.cshtml +++ b/src/Views/Home/Assets.cshtml @@ -1,11 +1,14 @@ +@using Berufsschule_HAM.Services @using Microsoft.AspNetCore.Mvc.Localization @using Berufsschule_HAM.Models @model HomeIndexViewModel @inject IViewLocalizer T -@inject IConfiguration Configuration +@inject LdapService ldap @{ ViewData["Title"] = T["Assets"]; - string barcodeType = Configuration["BarcodeType"] ?? "EAN13"; + var adminSettingsModel = await ldap.GetAdminSettingsModelAsync(); + string barcodeType = adminSettingsModel.BarcodeType ?? "EAN13"; + string barcodeText = adminSettingsModel.BarcodeText ?? "HAM"; }