diff --git a/application/controllers/api/frontend/v1/dashboard/DashboardAdmin.php b/application/controllers/api/frontend/v1/dashboard/DashboardAdmin.php
index 31e73b6ba..af844b29e 100644
--- a/application/controllers/api/frontend/v1/dashboard/DashboardAdmin.php
+++ b/application/controllers/api/frontend/v1/dashboard/DashboardAdmin.php
@@ -32,15 +32,9 @@ class DashboardAdmin extends FHCAPI_Controller
'createDashboard' => 'dashboard/admin:rw',
'updateDashboard' => 'dashboard/admin:rw',
'deleteDashboard' => 'dashboard/admin:rw',
- 'index' => 'dashboard/benutzer:r',
- 'dummy' => 'dashboard/benutzer:r',
- 'genWidgetId' => 'dashboard/benutzer:rw',
'addWidgetsToPreset' => 'dashboard/admin:rw',
'removeWidgetFromPreset' => 'dashboard/admin:rw',
- 'addWidgetsToUserOverride' => 'dashboard/benutzer:rw',
- 'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw',
'funktionen' => 'dashboard/admin:r',
- 'preset' => 'dashboard/admin:r',
'presetBatch' => 'dashboard/admin:r'
]);
diff --git a/application/controllers/api/frontend/v1/dashboard/User.php b/application/controllers/api/frontend/v1/dashboard/User.php
new file mode 100644
index 000000000..1242232a2
--- /dev/null
+++ b/application/controllers/api/frontend/v1/dashboard/User.php
@@ -0,0 +1,152 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about the users dashboard
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class User extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'get' => 'dashboard/benutzer:r',
+ 'addWidget' => 'dashboard/benutzer:rw',
+ 'removeWidget' => 'dashboard/benutzer:rw'
+ ]);
+
+ // Libraries
+ $this->load->library('dashboard/DashboardLib');
+
+ // Models
+ $this->load->model('ressource/Funktion_model', 'FunktionModel');
+ }
+
+ public function get($dashboard_kurzbz)
+ {
+ $dashboard = $this->dashboardlib->getDashboardByKurzbz($dashboard_kurzbz);
+ if (!$dashboard)
+ show_404();
+
+ $uid = $this->authlib->getAuthObj()->username;
+
+ /*$mergedconfig = $this->dashboardlib->getMergedConfig($dashboard->dashboard_id, $uid);
+
+ $this->terminateWithSuccess([
+ 'general' => call_user_func_array(
+ 'array_merge_recursive',
+ $mergedconfig
+ )
+ ]);*/
+ $defaultconfig = $this->dashboardlib->getDefaultConfig($dashboard->dashboard_id, $uid);
+ $userconfig = $this->dashboardlib->getUserConfig($dashboard->dashboard_id, $uid);
+
+ $defaultconfig_squashed = $defaultconfig ? call_user_func_array('array_merge_recursive', $defaultconfig) : [];
+ $userconfig_squashed = $userconfig ? call_user_func_array('array_merge_recursive', $userconfig) : [];
+
+ $mergedconfig = array_replace_recursive($defaultconfig_squashed, $userconfig_squashed);
+
+ $this->terminateWithSuccess([
+ DashboardLib::SECTION_IF_FUNKTION_KURZBZ_IS_NULL => $mergedconfig
+ ]);
+ }
+
+ public function addWidget()
+ {
+ $this->terminateWithValidationErrors(['test' => 'Test']);
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
+ $this->form_validation->set_rules('widget[widget]', 'Widget', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $widget = $this->input->post('widget');
+ $dashboard_kurzbz = $this->input->post('dashboard');
+ $uid = $this->authlib->getAuthObj()->username;
+
+ if (!isset($widget['widgetid']))
+ $widget['widgetid'] = $this->dashboardlib->generateWidgetId($dashboard_kurzbz);
+
+ $override = $this->dashboardlib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
+
+ $override_decoded = json_decode($override->override, true);
+
+ if (!isset($override_decoded['general']) || !is_array($override_decoded['general']))
+ $override_decoded['general'] = [];
+
+ if (!isset($override_decoded['general']['widgets']))
+ $override_decoded['general']['widgets'] = [];
+
+ $override_decoded['general']['widgets'][$widget['widgetid']] = $widget;
+
+ $override->override = json_encode($override_decoded);
+
+ $result = $this->dashboardlib->insertOrUpdateOverride($override);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($widget['widgetid']);
+ }
+
+ public function removeWidget()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
+ $this->form_validation->set_rules('widget', 'Widget', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $widget_id = $this->input->post('widget');
+ $dashboard_kurzbz = $this->input->post('dashboard');
+ $uid = $this->authlib->getAuthObj()->username;
+
+ $override = $this->dashboardlib->getOverride($dashboard_kurzbz, $uid);
+ if (empty($override))
+ show_404();
+
+ $override_decoded = json_decode($override->override, true);
+
+ foreach (array_keys($override_decoded) as $k) {
+ if (!isset($override_decoded[$k]["widgets"])) {
+ unset($override_decoded[$k]);
+ continue;
+ }
+ if (isset($override_decoded[$k]["widgets"][$widget_id])) {
+ unset($override_decoded[$k]["widgets"][$widget_id]);
+ }
+ if (!$override_decoded[$k]["widgets"]) {
+ unset($override_decoded[$k]);
+ }
+ }
+
+ $override->override = json_encode($override_decoded);
+
+ $result = $this->dashboardlib->insertOrUpdateOverride($override);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess();
+ }
+}
diff --git a/application/controllers/dashboard/Config.php b/application/controllers/dashboard/Config.php
deleted file mode 100644
index f6db9509f..000000000
--- a/application/controllers/dashboard/Config.php
+++ /dev/null
@@ -1,216 +0,0 @@
- 'dashboard/benutzer:r',
- 'dummy' => 'dashboard/benutzer:r',
- 'genWidgetId' => 'dashboard/benutzer:rw',
- 'addWidgetsToPreset' => 'dashboard/admin:rw',
- 'removeWidgetFromPreset' => 'dashboard/admin:rw',
- 'addWidgetsToUserOverride' => 'dashboard/benutzer:rw',
- 'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw',
- 'funktionen' => 'dashboard/admin:r',
- 'preset' => 'dashboard/admin:r',
- 'presetBatch' => 'dashboard/admin:r'
- )
- );
-
- $this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
- $this->load->library('AuthLib', null, 'AuthLib');
- $this->load->model('ressource/Funktion_model', 'FunktionModel');
- }
-
- public function index()
- {
- $dashboard_kurzbz = $this->input->get('db');
- $uid = $this->AuthLib->getAuthObj()->username;
-
- $dashboard = $this->DashboardLib->getDashboardByKurzbz($dashboard_kurzbz);
- if(!$dashboard) {
- http_response_code(404);
- $this->terminateWithJsonError(array(
- 'error' => 'Dashboard ' . $dashboard_kurzbz . ' not found.'
- ));
- }
-
- $mergedconfig = $this->DashboardLib->getMergedConfig($dashboard->dashboard_id, $uid);
- $this->outputJsonSuccess($mergedconfig);
- }
-
- public function genWidgetId()
- {
- $dashboard_kurzbz = $this->input->get('db');
- $widgetid = $this->DashboardLib->generateWidgetId($dashboard_kurzbz);
- $this->outputJsonSuccess(array(
- 'widgetid' => $widgetid
- ));
- }
-
- public function addWidgetsToPreset()
- {
- $input = json_decode($this->input->raw_input_stream);
- $dashboard_kurzbz = $input->db;
- $funktion_kurzbz = $input->funktion_kurzbz;
-
- $preset = $this->DashboardLib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
-
- $preset_decoded = json_decode($preset->preset, true);
-
- $this->DashboardLib->addWidgetsToWidgets($preset_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
-
- $preset->preset = json_encode($preset_decoded);
-
- $result = $this->DashboardLib->insertOrUpdatePreset($preset);
- if (isError($result)) {
- http_response_code(500);
- $this->terminateWithJsonError('preset could not be saved');
- }
-
- $this->outputJsonSuccess(array('msg' => 'preset successfully stored.', 'data' => $preset_decoded));
- }
-
- public function removeWidgetFromPreset()
- {
- $input = json_decode($this->input->raw_input_stream);
- $dashboard_kurzbz = $input->db;
- $funktion_kurzbz = $input->funktion_kurzbz;
- $widgetid = $input->widgetid;
-
- $preset = $this->DashboardLib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
- if ($preset === null) {
- http_response_code(404);
- $this->terminateWithJsonError('preset for dashboard ' . $dashboard_kurzbz . ' and funktion ' . $funktion_kurzbz . ' not found.');
- }
-
- $preset_decoded = json_decode($preset->preset, true);
- if (!$this->DashboardLib->removeWidgetFromWidgets($preset_decoded, $funktion_kurzbz, $widgetid))
- {
- http_response_code(404);
- $this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
- }
-
- $preset->preset = json_encode($preset_decoded);
- $result = $this->DashboardLib->insertOrUpdatePreset($preset);
- if (isError($result))
- {
- http_response_code(500);
- $this->terminateWithJsonError('failed to remove widget');
- }
- $this->outputJsonSuccess(array('msg' => 'preset successfully updated.'));
- }
-
- public function addWidgetsToUserOverride()
- {
- $input = json_decode($this->input->raw_input_stream);
- $dashboard_kurzbz = $input->db;
- $funktion_kurzbz = $input->funktion_kurzbz;
- $uid = $this->AuthLib->getAuthObj()->username;
-
- $override = $this->DashboardLib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
-
- $override_decoded = json_decode($override->override, true);
-
- $this->DashboardLib->addWidgetsToWidgets($override_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
-
- $override->override = json_encode($override_decoded);
-
- $result = $this->DashboardLib->insertOrUpdateOverride($override);
- if (isError($result)) {
- http_response_code(500);
- $this->terminateWithJsonError('override could not be saved');
- }
-
- $this->outputJsonSuccess(array('msg' => 'override successfully stored.', 'data' => $override_decoded));
- }
-
- public function removeWidgetFromUserOverride()
- {
- $input = json_decode($this->input->raw_input_stream);
- $dashboard_kurzbz = $input->db;
- $funktion_kurzbz = $input->funktion_kurzbz;
- $uid = $this->AuthLib->getAuthObj()->username;
- $widgetid = $input->widgetid;
-
- $override = $this->DashboardLib->getOverride($dashboard_kurzbz, $uid);
- if (empty($override)) {
- http_response_code(404);
- $this->terminateWithJsonError('userconfig for dashboard ' . $dashboard_kurzbz . ' not found.');
- }
-
- $override_decoded = json_decode($override->override, true);
-
- if (!$this->DashboardLib->removeWidgetFromWidgets($override_decoded, $funktion_kurzbz, $widgetid))
- {
- http_response_code(404);
- $this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
- }
-
- $override->override = json_encode($override_decoded);
- $result = $this->DashboardLib->insertOrUpdateOverride($override, $uid);
- if (isError($result))
- {
- http_response_code(500);
- $this->terminateWithJsonError('failed to remove widget');
- }
- $this->outputJsonSuccess(array('msg' => 'override successfully updated.'));
- }
-
- public function funktionen()
- {
- $funktionen = $this->FunktionModel->load();
-
- if (isError($funktionen)) {
- http_response_code(404);
- $this->terminateWithJsonError([
- 'error' => getError($funktionen)
- ]);
- }
-
- return $this->outputJsonSuccess(getData($funktionen) ?: []);
- }
-
- public function preset()
- {
- $db = $this->input->get('db');
- $funktion = $this->input->get('funktion');
-
- $conf = $this->DashboardLib->getPreset($db, $funktion);
-
- if (!$conf)
- return $this->outputJsonSuccess(['widgets' => [$funktion => []]]);
-
- return $this->outputJsonSuccess(json_decode($conf->preset, true));
- }
-
- public function presetBatch()
- {
- $db = $this->input->get('db');
- $funktionen = $this->input->get('funktionen');
- $result = [];
-
- foreach ($funktionen as $funktion) {
- $conf = $this->DashboardLib->getPreset($db, $funktion);
- if ($conf)
- {
- $preset = json_decode($conf->preset, true);
- if (!isset($preset[$funktion]) || !isset($preset[$funktion]['widgets']))
- $result[$funktion] = [];
- else
- $result[$funktion] = $preset[$funktion]['widgets'];
- }
- else
- $result[$funktion] = [];
- }
-
- return $this->outputJsonSuccess($result);
- }
-}
diff --git a/public/js/api/factory/dashboard/user.js b/public/js/api/factory/dashboard/user.js
new file mode 100644
index 000000000..e660d077e
--- /dev/null
+++ b/public/js/api/factory/dashboard/user.js
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2026 fhcomplete.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see