Compare commits

..

6 Commits

Author SHA1 Message Date
50d6166067 1.2.4 release 2026-06-21 13:26:17 +02:00
ebf44f5152 fix table column sizing issue 2026-06-21 12:32:26 +02:00
6682b974a3 Made the user groups table sortable and searchable. 2026-06-21 12:32:12 +02:00
433ed86f7e minor css and js improvements 2026-06-20 23:30:20 +02:00
55cc1be52f css warning fixes 2026-06-20 23:22:04 +02:00
229d2b4a15 Content Security Policy (CSP) Improvements. 2026-06-20 22:52:21 +02:00
47 changed files with 8378 additions and 6058 deletions

View File

@@ -27,7 +27,7 @@ if ($API_devices->request_method === 'POST') {
} }
$filename = basename($_FILES['file']['name']); $filename = basename($_FILES['file']['name']);
$filename = preg_replace('/[^a-zA-Z0-9_\.\-]/', '_', $filename); $filename = preg_replace('/[^a-zA-Z0-9_.-]/', '_', $filename);
$file_extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $file_extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$expectedExtension = $allowedFiletypes[$filetype]; $expectedExtension = $allowedFiletypes[$filetype];

View File

@@ -26,11 +26,11 @@ if (!$API->checkPermissions('admin-devices', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['datepicker'] = true; $jsScriptLoadData['datepicker'] = true;
$jsScriptLoadData['multiple_select'] = true; $jsScriptLoadData['/src/js/sentri/multiple_select.js'] = true;
$jsScriptLoadData['validateJson'] = true; $jsScriptLoadData['/src/js/sentri/validateJson.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,9 +27,9 @@ if (!$API->checkPermissions('admin-devices', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'][] = true; $jsScriptLoadData['form'][] = true;
$jsScriptLoadData['datepicker'] = true; $jsScriptLoadData['datepicker'] = true;
$jsScriptLoadData['multiple_select'] = true; $jsScriptLoadData['/src/js/sentri/multiple_select.js'] = true;
$jsScriptLoadData['validateJson'] = true; $jsScriptLoadData['/src/js/sentri/validateJson.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -23,10 +23,10 @@ if (!$API->checkPermissions('admin-devices', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['multiFilterSelect'] = true; $jsScriptLoadData['/src/js/sentri/multiFilterSelect.js'] = true;
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(false, '<i class="fas fa-fax"></i> ' . __('devices')); $pageNavbar = new pageNavbar(false, '<i class="fas fa-fax"></i> ' . __('devices'));

View File

@@ -102,10 +102,10 @@ function render_template_controls($template_uuid, $device_uuid, $default_templat
} }
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'][] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['load_dropzone'] = true; $jsScriptLoadData['/src/js/sentri/load_dropzone.js'] = true;
$jsScriptLoadData['form'][] = true; $jsScriptLoadData['form'][] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -25,8 +25,8 @@ if (!$API->checkPermissions('admin-access-control-permissions', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,7 +27,7 @@ if (!$API->checkPermissions('admin-platforms', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -24,8 +24,8 @@ if (!$API->checkPermissions('admin-vendors', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,7 +27,7 @@ if (!$API->checkPermissions('admin-vendors', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -30,10 +30,10 @@ if (!$API_servers->checkPermissions('customer-companies', 'RO', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['datepicker'] = true; $jsScriptLoadData['datepicker'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['multiFilterSelectServers'] = true; $jsScriptLoadData['/src/js/sentri/multiFilterSelectServers.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -25,11 +25,11 @@ if (!$API->checkPermissions('customer-companies', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['multiFilterSelect'] = true; $jsScriptLoadData['/src/js/sentri/multiFilterSelect.js'] = true;
$jsScriptLoadData['datepicker'] = true; $jsScriptLoadData['datepicker'] = true;
$jsScriptLoadData['activateCompany'] = true; $jsScriptLoadData['/src/js/sentri/activateCompany.js'] = true;
# PageClasses Setup # PageClasses Setup

View File

@@ -26,10 +26,11 @@ if (!$API->checkPermissions('office-stompjes', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['stompjes'] = true; $jsScriptLoadData['/src/js/plugin/chart.js/chart.min.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/sentri/stompjes.js'] = true;
$jsScriptLoadData['multiFilterSelect'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['/src/js/sentri/multiFilterSelect.js'] = true;
$jsScriptLoadData['datepicker'] = true; $jsScriptLoadData['datepicker'] = true;
# PageClasses Setup # PageClasses Setup

View File

@@ -2,7 +2,7 @@
<div class="card-body py-0 border"> <div class="card-body py-0 border">
<h5> <h5>
Sentri<br> Made by: Sentri<br> Made by:
<a class="text-decoration-none" href="https://marcomooij.net" target="_blank">Marco Mooij</a><br> Version 1.2.3 <a class="text-decoration-none" href="https://marcomooij.net" target="_blank">Marco Mooij</a><br> Version 1.2.4
</h5> </h5>
</div> </div>
</div> </div>

View File

@@ -14,11 +14,11 @@ require_once "{$_SERVER['DOCUMENT_ROOT']}/bin/php/Classes/formBuilder.php";
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['Generatepassword'] = true; $jsScriptLoadData['/src/js/sentri/Generatepassword.js'] = true;
$jsScriptLoadData['passwordShowHide'] = true; $jsScriptLoadData['/src/js/sentri/passwordShowHide.js'] = true;
$jsScriptLoadData['passwordRegen'] = true; $jsScriptLoadData['/src/js/sentri/passwordRegen.js'] = true;
$jsScriptLoadData['enableButtonOnImageUpload'] = true; $jsScriptLoadData['/src/js/sentri/enableButtonOnImageUpload.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -18,10 +18,10 @@ require_once "{$_SERVER['DOCUMENT_ROOT']}/api/classes/API_apitoken.php";
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['enableButtonOnImageUpload'] = true; $jsScriptLoadData['/src/js/sentri/enableButtonOnImageUpload.js'] = true;
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['CopyTargetData'] = true; $jsScriptLoadData['/src/js/sentri/CopyTargetData.js'] = true;
$jsScriptLoadData['updateToggle'] = true; $jsScriptLoadData['/src/js/sentri/updateToggle.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(false, '<i class="fa-solid fa-address-card"></i> ' . $_SESSION['user']['user_full_name'] . ' ' . strtolower(__('user_profile'))); $pageNavbar = new pageNavbar(false, '<i class="fa-solid fa-address-card"></i> ' . $_SESSION['user']['user_full_name'] . ' ' . strtolower(__('user_profile')));
@@ -207,19 +207,19 @@ if ($user_data) { ?>
<h4><?php echo __('user_management') ?></h4> <h4><?php echo __('user_management') ?></h4>
</div> </div>
<div class="card-body"> <div class="card-body">
<div id="mfa-enabled-row" class="row" style="display: <?php echo(($_SESSION['user']['user_two_factor_enabled'] == 1) ? '' : 'none') ?>"> <div id="mfa-enabled-row" class="row <?= ($_SESSION['user']['user_two_factor_enabled'] ? '' : 'd-none') ?>">
<div class="col-auto"> <div class="col-auto">
<a href="#" class="btn btn-danger delete-btn" data-item-uuid="<?php echo $user_uuid ?>" data-api-url="/api/v1/user/mfa/" data-delete-action='{"mfa-enabled-row":"hide", "mfa-disabled-row":"show"}' data-item-name='user_uuid'> <a href="#" class="btn btn-danger delete-btn" data-item-uuid="<?= $user_uuid ?>" data-api-url="/api/v1/user/mfa/" data-item-name="user_uuid" data-delete-action='{"mfa-enabled-row":"hide", "mfa-disabled-row":"show"}'>
<i class="fa-solid fa-lock"></i> <?php echo __('reset_mfa') ?> <i class="fa-solid fa-lock"></i> <?= __('reset_mfa') ?>
</a> </a>
</div> </div>
</div> </div>
<div id="mfa-disabled-row" class="row" style="display: <?php echo(($_SESSION['user']['user_two_factor_enabled'] == 1) ? 'none' : '') ?>"> <div id="mfa-disabled-row" class="row <?= ($_SESSION['user']['user_two_factor_enabled'] ? 'd-none' : '') ?>">
<div class="col-auto"> <div class="col-auto">
<a class="btn btn-primary" href="/login/mfaSetup.php"> <button class="btn btn-danger delete-btn" disabled>
<i class="fa-solid fa-lock"></i> <?php echo __('set_mfa') ?> <i class="fa-solid fa-lock"></i> <?= __('reset_mfa') ?>
</a> </button>
</div> </div>
</div> </div>
@@ -299,9 +299,9 @@ if ($user_data) { ?>
<tbody> <tbody>
<?php foreach ($apitokens as $token_data) { ?> <?php foreach ($apitokens as $token_data) { ?>
<tr> <tr>
<td class="text-nowrap" style="max-width: 100%;"> <td class="text-nowrap w-100">
<div class="d-flex align-items-center gap-2" style="max-width: 100%;"> <div class="d-flex align-items-center gap-2 w-100">
<div class="text-truncate" style="max-width: 200px;" id="<?php echo $token_data['api_token_uuid'] ?>" data-copy-data="<?php echo $token_data['api_token_uuid']; ?>"> <div class="text-truncate" id="<?php echo $token_data['api_token_uuid'] ?>" data-copy-data="<?php echo $token_data['api_token_uuid']; ?>">
<?php echo $token_data['api_token_uuid']; ?> <?php echo $token_data['api_token_uuid']; ?>
</div> </div>
<button type="button" class="btn btn-sm btn-outline-secondary" data-copy-target="<?php echo $token_data['api_token_uuid'] ?>" title="Copy ID"> <button type="button" class="btn btn-sm btn-outline-secondary" data-copy-target="<?php echo $token_data['api_token_uuid'] ?>" title="Copy ID">

View File

@@ -24,11 +24,11 @@ if (!$API->checkPermissions('admin-access-admins', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['Generatepassword'] = true; $jsScriptLoadData['/src/js/sentri/Generatepassword.js'] = true;
$jsScriptLoadData['passwordGenOnLoad'] = true; $jsScriptLoadData['/src/js/sentri/passwordGenOnLoad.js'] = true;
$jsScriptLoadData['passwordShowHide'] = true; $jsScriptLoadData['/src/js/sentri/passwordShowHide.js'] = true;
$jsScriptLoadData['passwordRegen'] = true; $jsScriptLoadData['/src/js/sentri/passwordRegen.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -25,7 +25,7 @@ if (!$API->checkPermissions('admin-access-admins', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -23,13 +23,13 @@ if (!$API->checkPermissions('admin-access-admins', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['Generatepassword'] = true; $jsScriptLoadData['/src/js/sentri/Generatepassword.js'] = true;
$jsScriptLoadData['passwordShowHide'] = true; $jsScriptLoadData['/src/js/sentri/passwordShowHide.js'] = true;
$jsScriptLoadData['passwordRegen'] = true; $jsScriptLoadData['/src/js/sentri/passwordRegen.js'] = true;
$jsScriptLoadData['enableButtonOnImageUpload'] = true; $jsScriptLoadData['/src/js/sentri/enableButtonOnImageUpload.js'] = true;
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
$jsScriptLoadData['updateToggle'] = true; $jsScriptLoadData['/src/js/sentri/updateToggle.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -25,8 +25,8 @@ if (!$API->isSuperuser()) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'][] = true; $jsScriptLoadData['form'][] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -28,7 +28,7 @@ if (!$API->isSuperuser()) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'][] = true; $jsScriptLoadData['form'][] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -24,10 +24,10 @@ if (!$API->checkPermissions('admin-access-control-permissions', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['updatePermissions'] = true; $jsScriptLoadData['/src/js/sentri/updatePermissions.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -25,8 +25,8 @@ if (!$API->checkPermissions('admin-access-control-user-groups', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'][] = true; $jsScriptLoadData['form'][] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,8 +27,8 @@ if (!$API->checkPermissions('admin-access-control-user-groups', 'RW', true)) {
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['form'] = true; $jsScriptLoadData['form'] = true;
$jsScriptLoadData['slugify'] = true; $jsScriptLoadData['/src/js/sentri/slugify.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -22,8 +22,8 @@ if (!$API->checkPermissions('admin-access-control-user-groups', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
$jsScriptLoadData['updatePermissions'] = true; $jsScriptLoadData['/src/js/sentri/updatePermissions.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -17,10 +17,10 @@ $API = new API();
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['activeTabOnRefresh'] = true; $jsScriptLoadData['/src/js/sentri/activeTabOnRefresh.js'] = true;
$jsScriptLoadData['multiFilterSelect'] = true; $jsScriptLoadData['/src/js/sentri/multiFilterSelect.js'] = true;
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
# PageClasses Setup # PageClasses Setup

View File

@@ -3,7 +3,7 @@ if (!defined('APP_INIT')) {
exit; exit;
} }
$jsScriptLoadData['activeTabOnRefresh'] = true; $jsScriptLoadData['/src/js/sentri/activeTabOnRefresh.js'] = true;
?> ?>
<div class="card-body activeTabOnRefresh"> <div class="card-body activeTabOnRefresh">

View File

@@ -18,9 +18,9 @@ $API = new API();
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['activeTabOnRefresh'] = true; $jsScriptLoadData['/src/js/sentri/activeTabOnRefresh.js'] = true;
$jsScriptLoadData['copyInputValue'] = true; $jsScriptLoadData['/src/js/sentri/copyInputValue.js'] = true;
$jsScriptLoadData['updateToggle'] = true; $jsScriptLoadData['/src/js/sentri/updateToggle.js'] = true;
# PageClasses Setup # PageClasses Setup

View File

@@ -20,12 +20,12 @@ $API->checkPermissions('admin-sources', 'RO');
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['activeTabOnRefresh'] = true; $jsScriptLoadData['/src/js/sentri/activeTabOnRefresh.js'] = true;
$jsScriptLoadData['copyInputValue'] = true; $jsScriptLoadData['/src/js/sentri/copyInputValue.js'] = true;
$jsScriptLoadData['updateToggle'] = true; $jsScriptLoadData['/src/js/sentri/updateToggle.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
$jsScriptLoadData['inserve_source'] = true; $jsScriptLoadData['/src/js/sentri/inserve_source.js'] = true;
$jsScriptLoadData['validateJson'] = true; $jsScriptLoadData['/src/js/sentri/validateJson.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,10 +27,10 @@ if (!$API->checkPermissions('servers', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['breadCrumbs'] = true; $jsScriptLoadData['/src/js/sentri/breadCrumbs.js'] = true;
$jsScriptLoadData['codeblocks'] = true; $jsScriptLoadData['codeblocks'] = true;
$jsScriptLoadData['serverView'] = true; $jsScriptLoadData['/src/js/sentri/serverView.js'] = true;
# PageClasses Setup # PageClasses Setup
$pageNavbar = new pageNavbar(true); $pageNavbar = new pageNavbar(true);

View File

@@ -27,9 +27,9 @@ if (!$API_servers->checkPermissions('servers', 'RO', true)) {
# Page functions # Page functions
# JS Scripts to load for this page # JS Scripts to load for this page
$jsScriptLoadData['delete_confirmation'] = true; $jsScriptLoadData['/src/js/sentri/delete_confirmation.js'] = true;
$jsScriptLoadData['datatables'] = true; $jsScriptLoadData['/src/js/plugin/datatables/datatables.min.js'] = true;
$jsScriptLoadData['multiFilterSelectServers'] = true; $jsScriptLoadData['/src/js/sentri/multiFilterSelectServers.js'] = true;
# PageClasses Setup # PageClasses Setup
$serverOverview = new serverOverviewBuilder(); $serverOverview = new serverOverviewBuilder();

View File

@@ -305,7 +305,7 @@ class pageBuilder
</nav> </nav>
<div class="copyright"> <div class="copyright">
<?php echo __('version') ?> <?php echo __('version') ?>
<a class="text-primary" href="/changelog/">1.2.3</a> <a class="text-primary" href="/changelog/">1.2.4</a>
</div> </div>
<div> <div>
<span class="navbar-text">Sentri</span> <span class="navbar-text">Sentri</span>
@@ -336,34 +336,37 @@ class pageBuilder
<!-- jQuery Scrollbar --> <!-- jQuery Scrollbar -->
<script src="/src/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js"></script> <script src="/src/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js"></script>
<!-- Load Other Js scripts -->
<!-- Chart JS
<script src="/src/js/plugin/chart.js/chart.min.js"></script>
-->
<!-- jQuery Sparkline
<script src="/src/js/plugin/jquery.sparkline/jquery.sparkline.min.js"></script>
-->
<!-- Chart Circle
<script src="/src/js/plugin/chart-circle/circles.min.js"></script>
-->
<!-- jQuery Vector Maps
<script src="/src/js/plugin/jsvectormap/jsvectormap.min.js"></script>
<script src="/src/js/plugin/jsvectormap/world.js"></script>
-->
<?php <?php
if (isset($this->jsScriptLoadData)) {
foreach ($this->jsScriptLoadData as $key => $script) {
if ($key === 'form') { ?>
<script src="/src/js/plugin/select2/select2.full.min.js"></script><!-- Bootstrap Tagsinput -->
<script src="/src/js/plugin/bootstrap-tagsinput/bootstrap-tagsinput.min.js"></script><!-- jQuery Moment.JS -->
<script src="/src/js/plugin/moment/moment.min.js"></script><!-- Bootstrap datetimepicker -->
<script src="/src/js/plugin/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"></script><!-- validate forms -->
<script src="/src/js/plugin/jquery.validate/jquery.validate.min.js"></script><!-- dropzone -->
<script src="/src/js/plugin/dropzone/dropzone.min.js"></script>
<script src="/src/js/sentri/form.js"></script>
<?php } elseif ($key === 'codeblocks') { ?>
<link rel="stylesheet" href="/src/css/prism.css">
<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-json.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs/plugins/toolbar/prism-toolbar.css">
<script src="https://cdn.jsdelivr.net/npm/prismjs/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
<?php } elseif ($key === 'datepicker') { ?>
<script src="/src/js/plugin/moment/moment.min.js"></script>
<script src="/src/js/plugin/datepicker/bootstrap-datetimepicker.min.js"></script>
<script src="/src/js/sentri/datepicker.js"></script>
<?php } else { ?>
<script src="<?php echo $key ?>"></script>
<?php } ?><?php }
}
# keeps refreshing the timeZoneCookie # keeps refreshing the timeZoneCookie
setTimeZoneCookie(); setTimeZoneCookie();
if (isset($this->jsScriptLoadData)) {
require_once "{$_SERVER['DOCUMENT_ROOT']}/bin/php/jsScripts.php";
}
# process response from actions
if (isset($_SESSION['response'])) { ?>
<script src="/src/js/sentri/response.js"></script>
<?php }
} }
} }

View File

@@ -26,6 +26,7 @@ class serverOverviewBuilder
'server_licenses' => false, 'server_licenses' => false,
'server_backup' => false, 'server_backup' => false,
'server_description' => false, 'server_description' => false,
'server_modified_timestamp' => false,
); );
public array $allBackupTypes = []; public array $allBackupTypes = [];
@@ -83,6 +84,7 @@ class serverOverviewBuilder
$this->showColumns['server_memory_demand'] = true; $this->showColumns['server_memory_demand'] = true;
$this->showColumns['server_disks'] = true; $this->showColumns['server_disks'] = true;
$this->showColumns['server_state'] = true; $this->showColumns['server_state'] = true;
$this->showColumns['server_modified_timestamp'] = true;
} }
} }
@@ -171,6 +173,10 @@ class serverOverviewBuilder
<input type="checkbox" name="value" value="server_power_state" class="selectgroup-input" <?php echo($this->showColumns['server_power_state'] ? 'checked=""' : '') ?>> <input type="checkbox" name="value" value="server_power_state" class="selectgroup-input" <?php echo($this->showColumns['server_power_state'] ? 'checked=""' : '') ?>>
<span class="selectgroup-button"><?php echo __('server_power_state') ?></span> <span class="selectgroup-button"><?php echo __('server_power_state') ?></span>
</label> </label>
<label class="selectgroup-item">
<input type="checkbox" name="value" value="server_modified_timestamp" class="selectgroup-input" <?php echo($this->showColumns['server_modified_timestamp'] ? 'checked=""' : '') ?>>
<span class="selectgroup-button"><?php echo __('last_modified_date') ?></span>
</label>
<label class="selectgroup-item"> <label class="selectgroup-item">
<input type="checkbox" name="value" value="server_description" class="selectgroup-input" <?php echo($this->showColumns['server_description'] ? 'checked=""' : '') ?>> <input type="checkbox" name="value" value="server_description" class="selectgroup-input" <?php echo($this->showColumns['server_description'] ? 'checked=""' : '') ?>>
<span class="selectgroup-button"><?php echo __('description') ?></span> <span class="selectgroup-button"><?php echo __('description') ?></span>
@@ -232,6 +238,7 @@ class serverOverviewBuilder
<?php } <?php }
?> ?>
<th data-column="server_power_state"><?php echo __('server_power_state') ?></th> <th data-column="server_power_state"><?php echo __('server_power_state') ?></th>
<th data-column="last_modified_date"><?php echo __('last_modified_date') ?></th>
<th data-column="server_description"><?php echo __('description') ?></th> <th data-column="server_description"><?php echo __('description') ?></th>
<th data-column="action"> <th data-column="action">
<?php echo __('action') ?> <?php echo __('action') ?>
@@ -385,6 +392,8 @@ class serverOverviewBuilder
$server_state_color = returnServerStateColor($server['server_state']); $server_state_color = returnServerStateColor($server['server_state']);
$server_modified_timestamp = ($server['server_modified_timestamp']) ? date('Y-m-d H:i:s', $server['server_modified_timestamp']) : __('never');
?> ?>
<tr data-item-id="<?php echo $server['server_uuid'] ?>"> <tr data-item-id="<?php echo $server['server_uuid'] ?>">
@@ -465,6 +474,9 @@ class serverOverviewBuilder
echo '<i class="fa-solid text-success fa-toggle-on"></i>'; echo '<i class="fa-solid text-success fa-toggle-on"></i>';
} ?> } ?>
</td> </td>
<td data-column="server_modified_timestamp" class="text-nowrap" data-sort="<?php echo $server['server_modified_timestamp']; ?>" data-filter="<?php echo $server_modified_timestamp; ?>">
<?php echo $server_modified_timestamp; ?>
</td>
<td data-column="server_description" class="text-nowrap" data-sort="<?php echo htmlspecialchars($server['server_description']); ?>" data-filter="<?php echo $server['server_description']; ?>"> <td data-column="server_description" class="text-nowrap" data-sort="<?php echo htmlspecialchars($server['server_description']); ?>" data-filter="<?php echo $server['server_description']; ?>">
<?php echo $server['server_description']; ?> <?php echo $server['server_description']; ?>
</td> </td>

View File

@@ -1,130 +0,0 @@
<?php
if (!defined('APP_INIT')) {
exit;
}
if (isset($this->jsScriptLoadData['form'])) { ?>
<!-- Select2 -->
<script src="/src/js/plugin/select2/select2.full.min.js"></script><!-- Bootstrap Tagsinput -->
<script src="/src/js/plugin/bootstrap-tagsinput/bootstrap-tagsinput.min.js"></script><!-- jQuery Moment.JS -->
<script src="/src/js/plugin/moment/moment.min.js"></script><!-- Bootstrap datetimepicker -->
<script src="/src/js/plugin/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"></script><!-- valicate forms -->
<script src="/src/js/plugin/jquery.validate/jquery.validate.min.js"></script><!-- dropzone -->
<script src="/src/js/plugin/dropzone/dropzone.min.js"></script>
<script src="/src/js/sentri/form.js"></script>
<?php }
if (isset($this->jsScriptLoadData['datatables'])) { ?>
<script src="/src/js/plugin/datatables/datatables.min.js"></script>
<?php }
if (isset($this->jsScriptLoadData['codeblocks'])) { ?>
<link rel="stylesheet" href="/src/css/prism.css">
<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-json.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs/plugins/toolbar/prism-toolbar.css">
<script src="https://cdn.jsdelivr.net/npm/prismjs/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
<?php } ?>
<?php
# Filter datatables
if (isset($this->jsScriptLoadData['multiFilterSelect'])) { ?>
<script src="/src/js/sentri/multiFilterSelect.js"></script>
<?php }
// multipleselect loading
if (isset($this->jsScriptLoadData['multiple_select'])) { ?>
<script src="/src/js/sentri/multiple_select.js"></script>
<?php }
// Function to generate a random password
if (isset($this->jsScriptLoadData['Generatepassword'])) { ?>
<script src="/src/js/sentri/Generatepassword.js"></script>
<?php }
if (isset($this->jsScriptLoadData['passwordGenOnLoad'])) { ?>
<script src="/src/js/sentri/passwordGenOnLoad.js"></script>
<?php }
if (isset($this->jsScriptLoadData['passwordShowHide'])) { ?>
<script src="/src/js/sentri/passwordShowHide.js"></script>
<?php }
if (isset($this->jsScriptLoadData['passwordRegen'])) { ?>
<script src="/src/js/sentri/passwordRegen.js"></script>
<?php }
// Create an datepicker input
if (isset($this->jsScriptLoadData['datepicker'])) { ?>
<script src="/src/js/plugin/moment/moment.min.js"></script>
<script src="/src/js/plugin/datepicker/bootstrap-datetimepicker.min.js"></script>
<script src="/src/js/sentri/datepicker.js"></script>
<?php }
// Activate the right panel and tab on refresh based on the #hash in the url
if (isset($this->jsScriptLoadData['activeTabOnRefresh'])) { ?>
<script src="/src/js/sentri/activeTabOnRefresh.js"></script>
<?php }
if (isset($this->jsScriptLoadData['activateCompany'])) { ?>
<script src="/src/js/sentri/activateCompany.js"></script>
<?php }
if (isset($this->jsScriptLoadData['multiFilterSelectServers'])) { ?>
<script src="/src/js/sentri/multiFilterSelectServers.js"></script>
<?php }
if (isset($this->jsScriptLoadData['inserve_source'])) { ?>
<script src="/src/js/sentri/inserve_source.js"></script>
<?php }
if (isset($this->jsScriptLoadData['serverView'])) { ?>
<script src="/src/js/sentri/serverView.js"></script>
<?php }
// slugify an input field
if (isset($this->jsScriptLoadData['slugify'])) { ?>
<script src="/src/js/sentri/slugify.js"></script>
<?php }
// Clicking on a btn will copy the value of an input to the clipboard
if (isset($this->jsScriptLoadData['copyInputValue'])) { ?>
<script src="/src/js/sentri/copyInputValue.js"></script>
<?php }
if (isset($this->jsScriptLoadData['CopyTargetData'])) { ?>
<script src="/src/js/sentri/CopyTargetData.js"></script>
<?php }
if (isset($this->jsScriptLoadData['validateJson'])) { ?>
<script src="/src/js/sentri/validateJson.js"></script>
<?php }
if (isset($this->jsScriptLoadData['stompjes'])) { ?>
<script src="/src/js/plugin/chart.js/chart.min.js"></script>
<script src="/src/js/sentri/stompjes.js"></script>
<?php }
if (isset($this->jsScriptLoadData['delete_confirmation'])) { ?>
<script src="/src/js/sentri/delete_confirmation.js"></script>
<?php }
if (isset($this->jsScriptLoadData['load_dropzone'])) { ?>
<script src="/src/js/sentri/load_dropzone.js"></script>
<?php }
if (isset($this->jsScriptLoadData['updateToggle'])) { ?>
<script src="/src/js/sentri/updateToggle.js"></script>
<?php }
if (isset($this->jsScriptLoadData['updatePermissions'])) { ?>
<script src="/src/js/sentri/updatePermissions.js"></script>
<?php }
if (isset($this->jsScriptLoadData['enableButtonOnImageUpload'])) { ?>
<script src="/src/js/sentri/enableButtonOnImageUpload.js"></script>
<?php }
if (isset($this->jsScriptLoadData['breadCrumbs'])) { ?>
<script src="/src/js/sentri/breadCrumbs.js"></script>
<?php } ?>

View File

@@ -29,36 +29,6 @@ $loginAttempts = checkLoginAttempts();
<link rel="apple-touch-icon" sizes="180x180" href="/src/images/favicon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/src/images/favicon/apple-touch-icon.png">
<link rel="manifest" href="/src/images/favicon/site.webmanifest"> <link rel="manifest" href="/src/images/favicon/site.webmanifest">
<style>
body {
font-family: Arial, sans-serif;
background-color: #1d222b;
}
.portal-image {
width: 100%;
height: auto;
aspect-ratio: 3 / 1;
object-fit: contain;
display: block;
min-height: 200px; /* Prevent layout shift during image load */
}
#code-container {
display: flex;
justify-content: center;
gap: 10px;
}
.code-input {
width: 40px;
height: 40px;
font-size: 24px;
text-align: center;
margin: 5px;
}
</style>
<link rel="stylesheet" href="css/style.full.css" as="style"> <link rel="stylesheet" href="css/style.full.css" as="style">
</head> </head>
<body> <body>
@@ -105,7 +75,7 @@ $loginAttempts = checkLoginAttempts();
<div class="card col-md-5 text-white bg-transparent py-0 border-0"> <div class="card col-md-5 text-white bg-transparent py-0 border-0">
<div class="card-body text-center pt-5"> <div class="card-body text-center pt-5">
<div> <div>
<img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265" style="height: auto;"> <img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -139,7 +139,7 @@ if ($loginAttemptCount = checkLoginAttempts() > 3) {
<div class="card col-md-5 text-white bg-transparent py-5 border-0"> <div class="card col-md-5 text-white bg-transparent py-5 border-0">
<div class="card-body text-center pt-3"> <div class="card-body text-center pt-3">
<div> <div>
<img class="pt-3 w-100 portal-image" alt="portal-image" width="500" height="265" style="height: auto;" src=""> <img class="pt-3 w-100 portal-image" alt="portal-image" width="500" height="265" src="">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,36 @@
const password = document.getElementById("password");
const confirmPassword = document.getElementById("confirmPassword");
const submitBtn = document.getElementById("submitBtn");
const passwordHelp = document.getElementById("passwordHelp");
const passwordPolicyError = document.getElementById("passwordPolicyError");
function checkPasswords() {
const pwValue = password.value;
const confirmValue = confirmPassword.value;
// Check length
if (pwValue.length < 13) {
passwordPolicyError.classList.remove("d-none");
submitBtn.disabled = true;
return;
} else {
passwordPolicyError.classList.add("d-none");
}
// Check match
if (pwValue && confirmValue) {
if (pwValue === confirmValue) {
passwordHelp.classList.add("d-none");
submitBtn.disabled = false;
} else {
passwordHelp.classList.remove("d-none");
submitBtn.disabled = true;
}
} else {
passwordHelp.classList.add("d-none");
submitBtn.disabled = true;
}
}
password.addEventListener("input", checkPasswords);
confirmPassword.addEventListener("input", checkPasswords);

View File

@@ -56,36 +56,6 @@ if (checkLoginAttempts() > 20) {
<link rel="apple-touch-icon" sizes="180x180" href="/src/images/favicon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/src/images/favicon/apple-touch-icon.png">
<link rel="manifest" href="/src/images/favicon/site.webmanifest"> <link rel="manifest" href="/src/images/favicon/site.webmanifest">
<style>
body {
font-family: Arial, sans-serif;
background-color: #1d222b;
}
.portal-image {
width: 100%;
height: auto;
aspect-ratio: 3 / 1;
object-fit: contain;
display: block;
min-height: 200px; /* Prevent layout shift during image load */
}
#code-container {
display: flex;
justify-content: center;
gap: 10px;
}
.code-input {
width: 40px;
height: 40px;
font-size: 24px;
text-align: center;
margin: 5px;
}
</style>
<link rel="stylesheet" href="css/style.full.css" as="style"> <link rel="stylesheet" href="css/style.full.css" as="style">
</head> </head>
<body> <body>
@@ -143,7 +113,7 @@ if (checkLoginAttempts() > 20) {
<div class="card col-md-5 text-white bg-transparent py-5"> <div class="card col-md-5 text-white bg-transparent py-5">
<div class="card-body text-center pt-5"> <div class="card-body text-center pt-5">
<div> <div>
<img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265" style="height: auto;"> <img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265">
</div> </div>
</div> </div>
</div> </div>
@@ -153,43 +123,6 @@ if (checkLoginAttempts() > 20) {
</div> </div>
</div> </div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<script> <script src="/login/js/checkPasswords.js"></script>
const password = document.getElementById("password");
const confirmPassword = document.getElementById("confirmPassword");
const submitBtn = document.getElementById("submitBtn");
const passwordHelp = document.getElementById("passwordHelp");
const passwordPolicyError = document.getElementById("passwordPolicyError");
function checkPasswords() {
const pwValue = password.value;
const confirmValue = confirmPassword.value;
// Check length
if (pwValue.length < 13) {
passwordPolicyError.classList.remove("d-none");
submitBtn.disabled = true;
return;
} else {
passwordPolicyError.classList.add("d-none");
}
// Check match
if (pwValue && confirmValue) {
if (pwValue === confirmValue) {
passwordHelp.classList.add("d-none");
submitBtn.disabled = false;
} else {
passwordHelp.classList.remove("d-none");
submitBtn.disabled = true;
}
} else {
passwordHelp.classList.add("d-none");
submitBtn.disabled = true;
}
}
password.addEventListener("input", checkPasswords);
confirmPassword.addEventListener("input", checkPasswords);
</script>
</body> </body>
</html> </html>

View File

@@ -98,7 +98,7 @@ if (checkLoginAttempts() > 20) {
<div class="card col-md-5 text-white bg-transparent py-5"> <div class="card col-md-5 text-white bg-transparent py-5">
<div class="card-body text-center pt-5"> <div class="card-body text-center pt-5">
<div> <div>
<img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265" style="height: auto;"> <img class="pt-3 w-100 portal-image" alt="portal-image" src="" width="500" height="265">
</div> </div>
</div> </div>
</div> </div>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -392,7 +392,6 @@ body {
/* No Box-Shadow Style */ /* No Box-Shadow Style */
.no-box-shadow-style * { .no-box-shadow-style * {
-webkit-box-shadow: none !important; -webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important; box-shadow: none !important;
} }
@@ -1016,7 +1015,6 @@ body {
} }
.sidebar .nav > .nav-item a[data-toggle=collapse][aria-expanded=true] .caret { .sidebar .nav > .nav-item a[data-toggle=collapse][aria-expanded=true] .caret {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
transform: rotate(-180deg); transform: rotate(-180deg);
} }
@@ -1604,11 +1602,6 @@ body {
opacity: 1; opacity: 1;
} }
.main-header .navbar-header .nav-search .input-group .form-control:-ms-input-placeholder {
/* IE 10+ */
opacity: 1;
}
.main-header .navbar-header .nav-search .input-group .form-control:-moz-placeholder { .main-header .navbar-header .nav-search .input-group .form-control:-moz-placeholder {
/* Firefox 18- */ /* Firefox 18- */
opacity: 1; opacity: 1;
@@ -1632,11 +1625,6 @@ body {
color: var(--bs-body-color) !important; color: var(--bs-body-color) !important;
} }
.main-header .navbar-header #search-nav.focus .nav-search .input-group .form-control:-ms-input-placeholder {
/* IE 10+ */
color: var(--bs-body-color) !important;
}
.main-header .navbar-header #search-nav.focus .nav-search .input-group .form-control:-moz-placeholder { .main-header .navbar-header #search-nav.focus .nav-search .input-group .form-control:-moz-placeholder {
/* Firefox 18- */ /* Firefox 18- */
color: var(--bs-body-color) !important; color: var(--bs-body-color) !important;
@@ -2015,7 +2003,6 @@ body {
background-color: var(--bs-secondary-bg); background-color: var(--bs-secondary-bg);
margin-bottom: 30px; margin-bottom: 30px;
-webkit-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1); -webkit-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
-moz-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1); box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
border: 0; border: 0;
} }
@@ -2626,7 +2613,6 @@ label {
position: relative; position: relative;
border-radius: 10px; border-radius: 10px;
-webkit-box-shadow: 0 1px 15px 1px rgba(69, 65, 78, 0.08); -webkit-box-shadow: 0 1px 15px 1px rgba(69, 65, 78, 0.08);
-moz-box-shadow: 0 1px 15px 1px rgba(69, 65, 78, 0.08);
box-shadow: var(--bs-box-shadow); box-shadow: var(--bs-box-shadow);
} }
@@ -3295,7 +3281,6 @@ label {
padding-bottom: 15px; padding-bottom: 15px;
position: relative; position: relative;
-webkit-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1); -webkit-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
-moz-box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1); box-shadow: 2px 6px 15px 0 rgba(69, 65, 78, 0.1);
border: 0; border: 0;
} }
@@ -3547,16 +3532,6 @@ label {
opacity: 0.7; opacity: 0.7;
} }
.form-control:-ms-input-placeholder {
color: inherit;
opacity: 0.7;
}
.form-control::-ms-input-placeholder {
color: inherit;
opacity: 0.7;
}
.input-group-text { .input-group-text {
border-color: var(--bs-border-color) !important; border-color: var(--bs-border-color) !important;
} }
@@ -3847,10 +3822,6 @@ label {
color: transparent; color: transparent;
} }
.form-floating-custom .form-control :-ms-input-placeholder {
color: transparent;
}
.form-floating-custom > .form-select ~ label::after { .form-floating-custom > .form-select ~ label::after {
display: none !important; display: none !important;
} }
@@ -4739,11 +4710,6 @@ label.error {
color: var(--bs-secondary-color) !important; color: var(--bs-secondary-color) !important;
} }
.dropdown-search .nav-search .input-group .form-control:-ms-input-placeholder {
/* IE 10+ */
color: var(--bs-secondary-color) !important;
}
.dropdown-search .nav-search .input-group .form-control:-moz-placeholder { .dropdown-search .nav-search .input-group .form-control:-moz-placeholder {
/* Firefox 18- */ /* Firefox 18- */
color: var(--bs-secondary-color) !important; color: var(--bs-secondary-color) !important;
@@ -5276,7 +5242,6 @@ label.error {
color: inherit; color: inherit;
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
-webkit-box-shadow: 1px 1px 14px 0 rgba(var(--bs-body-bg-rgb) 0.26); -webkit-box-shadow: 1px 1px 14px 0 rgba(var(--bs-body-bg-rgb) 0.26);
-moz-box-shadow: 1px 1px 14px 0 rgba(var(--bs-body-bg-rgb) 0.26);
box-shadow: 1px 1px 14px 0 rgba(var(--bs-body-bg-rgb) 0.26); box-shadow: 1px 1px 14px 0 rgba(var(--bs-body-bg-rgb) 0.26);
} }
@@ -6547,7 +6512,6 @@ label.error {
padding: 20px; padding: 20px;
position: relative; position: relative;
-webkit-box-shadow: var(--bs-box-shadow); -webkit-box-shadow: var(--bs-box-shadow);
-moz-box-shadow: var(--bs-box-shadow);
box-shadow: var(--bs-box-shadow); box-shadow: var(--bs-box-shadow);
} }
@@ -6714,7 +6678,6 @@ label.error {
position: absolute; position: absolute;
display: none; display: none;
-webkit-border-radius: 3px; -webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px; border-radius: 3px;
background: var(--bs-body-bg); background: var(--bs-body-bg);
color: var(--bs-body-color); color: var(--bs-body-color);

File diff suppressed because one or more lines are too long

View File

@@ -22,7 +22,8 @@ async function loadTranslations() {
const response = await fetch('/api/v1/frontend/locale/'); const response = await fetch('/api/v1/frontend/locale/');
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP ${response.status}`); console.error(`HTTP ${response.status}`);
return;
} }
const data = await response.json(); const data = await response.json();

View File

@@ -15,12 +15,31 @@ document.addEventListener("DOMContentLoaded", function () {
cardBody.querySelectorAll('.tab-pane').forEach(content => content.classList.remove('show', 'active')); cardBody.querySelectorAll('.tab-pane').forEach(content => content.classList.remove('show', 'active'));
selectedTab.classList.add('active'); selectedTab.classList.add('active');
selectedContent.classList.add('show', 'active'); selectedContent.classList.add('show', 'active');
// Give the browser a moment to render the tab
setTimeout(() => {
$.fn.dataTable.tables({
visible: true,
api: true
})
.columns.adjust()
.draw();
}, 0);
} }
cardBody.querySelectorAll('.nav-link').forEach(tab => { cardBody.querySelectorAll('.nav-link').forEach(tab => {
tab.addEventListener("click", function () { tab.addEventListener("click", function () {
let targetTab = this.getAttribute("href"); let targetTab = this.getAttribute("href");
history.replaceState(null, null, targetTab); history.replaceState(null, null, targetTab);
setTimeout(() => {
$.fn.dataTable.tables({
visible: true,
api: true
})
.columns.adjust()
.draw();
}, 0);
}); });
}); });

View File

@@ -5,7 +5,8 @@ document.addEventListener("DOMContentLoaded", async function () {
const response = await fetch("/api/v1/frontend/breadcrumbs/"); const response = await fetch("/api/v1/frontend/breadcrumbs/");
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP ${response.status}`); console.error(`HTTP ${response.status}`);
return;
} }
breadcrumbArray = await response.json(); breadcrumbArray = await response.json();

View File

@@ -3,7 +3,8 @@ document.addEventListener("DOMContentLoaded", async function () {
const response = await fetch("/api/v1/frontend/response/"); const response = await fetch("/api/v1/frontend/response/");
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP ${response.status}`); console.error(`HTTP ${response.status}`);
return;
} }
const data = await response.json(); const data = await response.json();

View File

@@ -197,19 +197,6 @@ function getColorForUser(name) {
return finalColor; return finalColor;
} }
// Helper: get all dates between two dates (inclusive)
function getDatesBetween(startDate, endDate) {
const dates = [];
let current = new Date(startDate);
const end = new Date(endDate);
while (current <= end) {
dates.push(current.toISOString().slice(0, 10));
current.setDate(current.getDate() + 1);
}
return dates;
}
let stompChart = null; let stompChart = null;
// Convert dd/mm/yyyy → Date safely // Convert dd/mm/yyyy → Date safely
@@ -253,7 +240,8 @@ async function loadChart() {
const res = await fetch('/api/v1/office/stompjes/?frontend=1'); const res = await fetch('/api/v1/office/stompjes/?frontend=1');
if (!res.ok) { if (!res.ok) {
throw new Error(`HTTP ${res.status}`); console.error(`HTTP ${res.status}`);
return;
} }
const data = await res.json(); const data = await res.json();