From 008cd7ae86dee6812c6e456863d94bb270e91fa8 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 8 May 2026 08:54:17 +0200 Subject: [PATCH] feat(Navigation, UserRights, Localization): add worker schedules feature and enhance access control - Updated navigation structure to include a new section for worker schedules, accessible to specific user roles. - Introduced a new user right type for 'worker_schedule_read' to manage access permissions effectively. - Added localization entries for worker schedules in multiple languages, ensuring consistent user experience across the application. - Created a new route and component for managing worker schedules in the admin panel. --- backend/controllers/navigationController.js | 6 +- .../sql/add_worker_schedule_read_right.sql | 9 + backend/utils/initializeUserRights.js | 4 + frontend/src/components/AppSectionBar.vue | 1 + frontend/src/i18n/locales/ceb/admin.json | 19 ++ frontend/src/i18n/locales/ceb/general.json | 3 +- frontend/src/i18n/locales/ceb/navigation.json | 3 +- frontend/src/i18n/locales/de/admin.json | 19 ++ frontend/src/i18n/locales/de/general.json | 3 +- frontend/src/i18n/locales/de/navigation.json | 3 +- frontend/src/i18n/locales/en/admin.json | 19 ++ frontend/src/i18n/locales/en/general.json | 3 +- frontend/src/i18n/locales/en/navigation.json | 3 +- frontend/src/i18n/locales/es/admin.json | 19 ++ frontend/src/i18n/locales/es/general.json | 3 +- frontend/src/i18n/locales/es/navigation.json | 3 +- frontend/src/i18n/locales/fr/admin.json | 19 ++ frontend/src/i18n/locales/fr/general.json | 3 +- frontend/src/i18n/locales/fr/navigation.json | 3 +- frontend/src/router/adminRoutes.js | 7 + .../admin/falukant/WorkerSchedulesView.vue | 213 ++++++++++++++++++ 21 files changed, 354 insertions(+), 11 deletions(-) create mode 100644 backend/sql/add_worker_schedule_read_right.sql create mode 100644 frontend/src/views/admin/falukant/WorkerSchedulesView.vue diff --git a/backend/controllers/navigationController.js b/backend/controllers/navigationController.js index fc9a6ce..126abb6 100644 --- a/backend/controllers/navigationController.js +++ b/backend/controllers/navigationController.js @@ -295,7 +295,7 @@ const menuStructure = { path: "/admin/interests" }, falukant: { - visible: ["mainadmin", "falukant"], + visible: ["mainadmin", "falukant", "worker_schedule_read"], children: { logentries: { visible: ["mainadmin", "falukant"], @@ -317,6 +317,10 @@ const menuStructure = { visible: ["mainadmin", "falukant"], path: "/admin/falukant/create-npc" }, + workerSchedules: { + visible: ["mainadmin", "worker_schedule_read"], + path: "/admin/falukant/worker-schedules" + }, } }, minigames: { diff --git a/backend/sql/add_worker_schedule_read_right.sql b/backend/sql/add_worker_schedule_read_right.sql new file mode 100644 index 0000000..7b2aaa2 --- /dev/null +++ b/backend/sql/add_worker_schedule_read_right.sql @@ -0,0 +1,9 @@ +-- Adds user right required for Falukant worker schedule read access. + +INSERT INTO "type".user_right (title) +SELECT 'worker_schedule_read' +WHERE NOT EXISTS ( + SELECT 1 + FROM "type".user_right + WHERE title = 'worker_schedule_read' +); diff --git a/backend/utils/initializeUserRights.js b/backend/utils/initializeUserRights.js index 9e4de08..06f3eda 100644 --- a/backend/utils/initializeUserRights.js +++ b/backend/utils/initializeUserRights.js @@ -38,6 +38,10 @@ const initializeUserRights = async() => { where: { title: "match3"}, defaults: { title: "match3"} }); + await UserRightType.findOrCreate({ + where: { title: "worker_schedule_read"}, + defaults: { title: "worker_schedule_read"} + }); }; export default initializeUserRights; diff --git a/frontend/src/components/AppSectionBar.vue b/frontend/src/components/AppSectionBar.vue index 0fc9bcf..1fc6aa9 100644 --- a/frontend/src/components/AppSectionBar.vue +++ b/frontend/src/components/AppSectionBar.vue @@ -80,6 +80,7 @@ const TITLE_MAP = { AdminFalukantEditUserView: 'sectionBar.titles.adminFalukantUsers', AdminFalukantMapRegionsView: 'sectionBar.titles.adminFalukantMap', AdminFalukantCreateNPCView: 'sectionBar.titles.adminCreateNpc', + AdminFalukantWorkerSchedulesView: 'sectionBar.titles.adminWorkerSchedules', AdminMinigames: 'sectionBar.titles.adminMinigames', AdminTaxiTools: 'sectionBar.titles.adminTaxiTools', AdminServicesStatus: 'sectionBar.titles.adminServicesStatus' diff --git a/frontend/src/i18n/locales/ceb/admin.json b/frontend/src/i18n/locales/ceb/admin.json index b7cd465..b8346b6 100644 --- a/frontend/src/i18n/locales/ceb/admin.json +++ b/frontend/src/i18n/locales/ceb/admin.json @@ -329,6 +329,25 @@ "timeRemainingMinutes": "Nahibilin nga oras: {minutes} ka minuto {seconds} ka segundo", "almostDone": "Hapit na …", "jobNotFound": "Wala makit-i ang trabaho o na-expire na." + }, + "workerSchedules": { + "title": "Mga dagan sa daemon", + "description": "Kinatibuk-ang tan-aw sa naka-iskedyul nga dagan sa worker gikan sa daemon registry.", + "accessDenied": "Walay access ani nga view.", + "detailed": "Detalyadong tan-aw", + "autoRefresh": "Auto-refresh", + "refresh": "I-refresh", + "generatedAt": "Nabuhat sa", + "empty": "Walay schedules nga anaa.", + "notConnected": "Walay daemon connection.", + "sendError": "Napakyas ang request sa daemon.", + "responseError": "Dili maproseso ang tubag sa daemon.", + "currentStep": "Karon nga lakang", + "task": "Task", + "cadence": "Interbal", + "nextRun": "Pinakataas nga sunod nga dagan", + "remaining": "Nahibilin", + "noTasks": "Walay tasks para ani nga worker." } }, "chatrooms": { diff --git a/frontend/src/i18n/locales/ceb/general.json b/frontend/src/i18n/locales/ceb/general.json index e0a5a91..7498bc4 100644 --- a/frontend/src/i18n/locales/ceb/general.json +++ b/frontend/src/i18n/locales/ceb/general.json @@ -187,7 +187,8 @@ "adminCreateNpc": "Paghimo og NPC", "adminMinigames": "Pagdumala sa Match3", "adminTaxiTools": "Mga himan sa taxi", - "adminServicesStatus": "Status sa serbisyo" + "adminServicesStatus": "Status sa serbisyo", + "adminWorkerSchedules": "Mga dagan sa daemon" } } } diff --git a/frontend/src/i18n/locales/ceb/navigation.json b/frontend/src/i18n/locales/ceb/navigation.json index 7a0f7a3..16a4a0c 100644 --- a/frontend/src/i18n/locales/ceb/navigation.json +++ b/frontend/src/i18n/locales/ceb/navigation.json @@ -85,7 +85,8 @@ "edituser": "Usba ang user", "database": "Database", "mapEditor": "Editor sa mapa", - "createNPC": "Paghimo og NPC" + "createNPC": "Paghimo og NPC", + "workerSchedules": "Mga dagan sa daemon" }, "minigames": "Mga minidula", "m-minigames": { diff --git a/frontend/src/i18n/locales/de/admin.json b/frontend/src/i18n/locales/de/admin.json index 82961b3..747a2ae 100644 --- a/frontend/src/i18n/locales/de/admin.json +++ b/frontend/src/i18n/locales/de/admin.json @@ -322,6 +322,25 @@ "timeRemainingMinutes": "Verbleibende Zeit: {minutes} Minuten {seconds} Sekunden", "almostDone": "Fast fertig...", "jobNotFound": "Job nicht gefunden oder abgelaufen." + }, + "workerSchedules": { + "title": "Daemon-Läufe", + "description": "Übersicht geplanter Worker-Läufe aus der Daemon-Registry.", + "accessDenied": "Kein Zugriff auf diese Ansicht.", + "detailed": "Detaillierte Ansicht", + "autoRefresh": "Auto-Refresh", + "refresh": "Aktualisieren", + "generatedAt": "Erzeugt am", + "empty": "Keine Schedules vorhanden.", + "notConnected": "Keine Daemon-Verbindung verfügbar.", + "sendError": "Anfrage an den Daemon fehlgeschlagen.", + "responseError": "Antwort konnte nicht verarbeitet werden.", + "currentStep": "Aktueller Schritt", + "task": "Task", + "cadence": "Intervall", + "nextRun": "Spätester nächster Lauf", + "remaining": "Verbleibend", + "noTasks": "Keine Tasks für diesen Worker." } }, "chatrooms": { diff --git a/frontend/src/i18n/locales/de/general.json b/frontend/src/i18n/locales/de/general.json index 723245c..a127bf9 100644 --- a/frontend/src/i18n/locales/de/general.json +++ b/frontend/src/i18n/locales/de/general.json @@ -187,7 +187,8 @@ "adminCreateNpc": "NPC erstellen", "adminMinigames": "Match3-Verwaltung", "adminTaxiTools": "Taxi-Tools", - "adminServicesStatus": "Service-Status" + "adminServicesStatus": "Service-Status", + "adminWorkerSchedules": "Daemon-Laeufe" } } } diff --git a/frontend/src/i18n/locales/de/navigation.json b/frontend/src/i18n/locales/de/navigation.json index 08a52df..5aaeefa 100644 --- a/frontend/src/i18n/locales/de/navigation.json +++ b/frontend/src/i18n/locales/de/navigation.json @@ -85,7 +85,8 @@ "edituser": "Benutzer bearbeiten", "database": "Datenbank", "mapEditor": "Karteneditor", - "createNPC": "NPCs erstellen" + "createNPC": "NPCs erstellen", + "workerSchedules": "Daemon-Läufe" }, "minigames": "Minispiele", "m-minigames": { diff --git a/frontend/src/i18n/locales/en/admin.json b/frontend/src/i18n/locales/en/admin.json index 7e9f666..1a071f1 100644 --- a/frontend/src/i18n/locales/en/admin.json +++ b/frontend/src/i18n/locales/en/admin.json @@ -377,6 +377,25 @@ "timeRemainingMinutes": "Time remaining: {minutes} minutes {seconds} seconds", "almostDone": "Almost done...", "jobNotFound": "Job not found or expired." + }, + "workerSchedules": { + "title": "Daemon runs", + "description": "Overview of scheduled worker runs from the daemon registry.", + "accessDenied": "No access to this view.", + "detailed": "Detailed view", + "autoRefresh": "Auto refresh", + "refresh": "Refresh", + "generatedAt": "Generated at", + "empty": "No schedules available.", + "notConnected": "No daemon connection available.", + "sendError": "Request to daemon failed.", + "responseError": "Could not process daemon response.", + "currentStep": "Current step", + "task": "Task", + "cadence": "Cadence", + "nextRun": "Latest next run", + "remaining": "Remaining", + "noTasks": "No tasks for this worker." } }, "chatrooms": { diff --git a/frontend/src/i18n/locales/en/general.json b/frontend/src/i18n/locales/en/general.json index eaf620b..181a94d 100644 --- a/frontend/src/i18n/locales/en/general.json +++ b/frontend/src/i18n/locales/en/general.json @@ -187,7 +187,8 @@ "adminCreateNpc": "Create NPC", "adminMinigames": "Match3 administration", "adminTaxiTools": "Taxi tools", - "adminServicesStatus": "Service status" + "adminServicesStatus": "Service status", + "adminWorkerSchedules": "Daemon runs" } } } diff --git a/frontend/src/i18n/locales/en/navigation.json b/frontend/src/i18n/locales/en/navigation.json index 01ae899..116bf75 100644 --- a/frontend/src/i18n/locales/en/navigation.json +++ b/frontend/src/i18n/locales/en/navigation.json @@ -85,7 +85,8 @@ "edituser": "Edit user", "database": "Database", "mapEditor": "Map editor", - "createNPC": "Create NPCs" + "createNPC": "Create NPCs", + "workerSchedules": "Daemon runs" }, "minigames": "Mini games", "m-minigames": { diff --git a/frontend/src/i18n/locales/es/admin.json b/frontend/src/i18n/locales/es/admin.json index ec24f39..098b9ae 100644 --- a/frontend/src/i18n/locales/es/admin.json +++ b/frontend/src/i18n/locales/es/admin.json @@ -302,6 +302,25 @@ "timeRemainingMinutes": "Tiempo restante: {minutes} minutos {seconds} segundos", "almostDone": "Casi listo...", "jobNotFound": "Trabajo no encontrado o caducado." + }, + "workerSchedules": { + "title": "Ejecuciones del daemon", + "description": "Resumen de ejecuciones planificadas de workers desde el registro del daemon.", + "accessDenied": "No tienes acceso a esta vista.", + "detailed": "Vista detallada", + "autoRefresh": "Actualización automática", + "refresh": "Actualizar", + "generatedAt": "Generado el", + "empty": "No hay schedules disponibles.", + "notConnected": "No hay conexión con el daemon.", + "sendError": "Falló la solicitud al daemon.", + "responseError": "No se pudo procesar la respuesta del daemon.", + "currentStep": "Paso actual", + "task": "Tarea", + "cadence": "Intervalo", + "nextRun": "Próxima ejecución máxima", + "remaining": "Restante", + "noTasks": "No hay tareas para este worker." } }, "chatrooms": { diff --git a/frontend/src/i18n/locales/es/general.json b/frontend/src/i18n/locales/es/general.json index a5dfc15..b0b78fe 100644 --- a/frontend/src/i18n/locales/es/general.json +++ b/frontend/src/i18n/locales/es/general.json @@ -187,7 +187,8 @@ "adminCreateNpc": "Crear NPC", "adminMinigames": "Administración de Match3", "adminTaxiTools": "Herramientas de taxi", - "adminServicesStatus": "Estado del servicio" + "adminServicesStatus": "Estado del servicio", + "adminWorkerSchedules": "Ejecuciones del daemon" } } } diff --git a/frontend/src/i18n/locales/es/navigation.json b/frontend/src/i18n/locales/es/navigation.json index ee23713..8fedb87 100644 --- a/frontend/src/i18n/locales/es/navigation.json +++ b/frontend/src/i18n/locales/es/navigation.json @@ -85,7 +85,8 @@ "edituser": "Editar usuario", "database": "Datenbank", "mapEditor": "Editor de mapas", - "createNPC": "Crear NPCs" + "createNPC": "Crear NPCs", + "workerSchedules": "Ejecuciones del daemon" }, "minigames": "Minispiele", "m-minigames": { diff --git a/frontend/src/i18n/locales/fr/admin.json b/frontend/src/i18n/locales/fr/admin.json index 788af2b..bf27d6a 100644 --- a/frontend/src/i18n/locales/fr/admin.json +++ b/frontend/src/i18n/locales/fr/admin.json @@ -302,6 +302,25 @@ "timeRemainingMinutes": "Temps restant : {minutes} minutes {secondes} secondes", "almostDone": "Presque fini...", "jobNotFound": "Emploi introuvable ou expiré." + }, + "workerSchedules": { + "title": "Exécutions du daemon", + "description": "Vue d'ensemble des exécutions planifiées des workers depuis le registre du daemon.", + "accessDenied": "Aucun accès à cette vue.", + "detailed": "Vue détaillée", + "autoRefresh": "Rafraîchissement automatique", + "refresh": "Rafraîchir", + "generatedAt": "Généré à", + "empty": "Aucun schedule disponible.", + "notConnected": "Aucune connexion daemon disponible.", + "sendError": "Échec de la requête vers le daemon.", + "responseError": "Impossible de traiter la réponse du daemon.", + "currentStep": "Étape actuelle", + "task": "Tâche", + "cadence": "Intervalle", + "nextRun": "Prochaine exécution au plus tard", + "remaining": "Restant", + "noTasks": "Aucune tâche pour ce worker." } }, "chatrooms": { diff --git a/frontend/src/i18n/locales/fr/general.json b/frontend/src/i18n/locales/fr/general.json index 7892bc3..c9cd8ea 100644 --- a/frontend/src/i18n/locales/fr/general.json +++ b/frontend/src/i18n/locales/fr/general.json @@ -187,7 +187,8 @@ "adminCreateNpc": "Créer un PNJ", "adminMinigames": "Gestion des Match3", "adminTaxiTools": "Outils de taxi", - "adminServicesStatus": "Statut des services" + "adminServicesStatus": "Statut des services", + "adminWorkerSchedules": "Executions du daemon" } } } diff --git a/frontend/src/i18n/locales/fr/navigation.json b/frontend/src/i18n/locales/fr/navigation.json index e71f7b5..75d97f6 100644 --- a/frontend/src/i18n/locales/fr/navigation.json +++ b/frontend/src/i18n/locales/fr/navigation.json @@ -85,7 +85,8 @@ "edituser": "Modifier l'utilisateur", "database": "base de données", "mapEditor": "Editeur de cartes", - "createNPC": "NPCs erstellen" + "createNPC": "NPCs erstellen", + "workerSchedules": "Exécutions du daemon" }, "minigames": "Minispiele", "m-minigames": { diff --git a/frontend/src/router/adminRoutes.js b/frontend/src/router/adminRoutes.js index 77cc803..3f046cc 100644 --- a/frontend/src/router/adminRoutes.js +++ b/frontend/src/router/adminRoutes.js @@ -6,6 +6,7 @@ const ForumAdminView = () => import('../dialogues/admin/ForumAdminView.vue'); const AdminFalukantEditUserView = () => import('../views/admin/falukant/EditUserView.vue'); const AdminFalukantMapRegionsView = () => import('../views/admin/falukant/MapRegionsView.vue'); const AdminFalukantCreateNPCView = () => import('../views/admin/falukant/CreateNPCView.vue'); +const AdminFalukantWorkerSchedulesView = () => import('../views/admin/falukant/WorkerSchedulesView.vue'); const AdminMinigamesView = () => import('../views/admin/MinigamesView.vue'); const AdminTaxiToolsView = () => import('../views/admin/TaxiToolsView.vue'); const AdminUsersView = () => import('../views/admin/UsersView.vue'); @@ -94,6 +95,12 @@ const adminRoutes = [ component: AdminFalukantCreateNPCView, meta: { requiresAuth: true } }, + { + path: '/admin/falukant/worker-schedules', + name: 'AdminFalukantWorkerSchedulesView', + component: AdminFalukantWorkerSchedulesView, + meta: { requiresAuth: true } + }, { path: '/admin/minigames/match3', name: 'AdminMinigames', diff --git a/frontend/src/views/admin/falukant/WorkerSchedulesView.vue b/frontend/src/views/admin/falukant/WorkerSchedulesView.vue new file mode 100644 index 0000000..cab959b --- /dev/null +++ b/frontend/src/views/admin/falukant/WorkerSchedulesView.vue @@ -0,0 +1,213 @@ + + + + +