diff --git a/agent/calendar.php b/agent/calendar.php index fff173bb8..54705d058 100644 --- a/agent/calendar.php +++ b/agent/calendar.php @@ -194,7 +194,7 @@ while ($row = mysqli_fetch_assoc($sql)) { allDayToggle.checked = true; $(allDayToggle).trigger("change"); } - $("#addCalendarEventModal").modal(); + bootstrap.Modal.getOrCreateInstance(document.getElementById('addCalendarEventModal')).show(); } } }, @@ -274,7 +274,7 @@ while ($row = mysqli_fetch_assoc($sql)) { } calendar.unselect(); - $("#addCalendarEventModal").modal(); + bootstrap.Modal.getOrCreateInstance(document.getElementById('addCalendarEventModal')).show(); }, eventClick: function(editEvent) { var eventId = editEvent.event.id; diff --git a/agent/files.php b/agent/files.php index 9e63e9027..6cc9c014a 100644 --- a/agent/files.php +++ b/agent/files.php @@ -967,7 +967,7 @@ $num_root_items = intval($row_root_files['num']) + intval($row_root_docs['num']) function openModal(index) { currentIndex = index; updateModalContent(); - $('#viewFileModal').modal('show'); + bootstrap.Modal.getOrCreateInstance(document.getElementById('viewFileModal')).show(); } function updateModalContent() { diff --git a/agent/js/credential_show_password_via_id.js b/agent/js/credential_show_password_via_id.js index 846f4f90e..6989046fe 100644 --- a/agent/js/credential_show_password_via_id.js +++ b/agent/js/credential_show_password_via_id.js @@ -10,11 +10,12 @@ function showPasswordViaCredentialID(button, credential_id) { // (Re)create the popover with the fetched password and show it // trigger: focus dismisses it when the user clicks away - jQuery(button).popover('dispose').popover({ + bootstrap.Popover.getInstance(button)?.dispose(); + new bootstrap.Popover(button, { content: credential.password, placement: 'top', trigger: 'focus' - }).popover('show'); + }).show(); } ); } diff --git a/agent/user/mfa_enforcement.php b/agent/user/mfa_enforcement.php index 522dded92..1a2d4a831 100644 --- a/agent/user/mfa_enforcement.php +++ b/agent/user/mfa_enforcement.php @@ -116,17 +116,20 @@ $data = "otpauth://totp/ITFlow:$session_email?secret=$token"; // on screen. This page is standalone and does not load js/app.js, so it // carries its own copy of the helper. function flashTooltip(button, message) { - $(button) - .tooltip('dispose') - .tooltip({ - trigger: 'manual', - placement: 'bottom', - title: message - }) - .tooltip('show'); + const el = button instanceof Element ? button : $(button)[0]; + if (!el) { + return; + } + bootstrap.Tooltip.getInstance(el)?.dispose(); + const tip = new bootstrap.Tooltip(el, { + trigger: 'manual', + placement: 'bottom', + title: message + }); + tip.show(); - setTimeout(function() { - $(button).tooltip('dispose'); + setTimeout(function () { + tip.dispose(); }, 1000); } @@ -144,7 +147,9 @@ $data = "otpauth://totp/ITFlow:$session_email?secret=$token"; // Enable Popovers $(function () { - $('[data-bs-toggle="popover"]').popover() + document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function (el) { + bootstrap.Popover.getOrCreateInstance(el); + }) }); diff --git a/agent/user/user_security.php b/agent/user/user_security.php index ab87e2963..735260a5f 100644 --- a/agent/user/user_security.php +++ b/agent/user/user_security.php @@ -87,7 +87,7 @@ if (!empty($_SESSION['show_mfa_modal'])) { "; unset($_SESSION['show_mfa_modal']); diff --git a/css/itflow_custom.css b/css/itflow_custom.css index 9cee58d6f..09cd85dc8 100644 --- a/css/itflow_custom.css +++ b/css/itflow_custom.css @@ -58,3 +58,157 @@ position: static; margin: 0; } + +/* --------------------------------------------------------------- + AdminLTE 4 compatibility. + v4 dropped .text-sm and the accent-* / navbar-* / sidebar-dark-* + trio that ITFlow's 16 theme choices were built on. In v3 the theme + colour drove the TOP NAVBAR, link colours and the active sidebar + item - the sidebar itself was always dark. That is reproduced here. + --------------------------------------------------------------- */ +.text-sm, .text-sm .form-control, .text-sm .form-select, +.text-sm .btn, .text-sm .nav-link, .text-sm table { + font-size: .875rem; +} + +/* one accent per theme - v3 used the same hex for navbar, links and + the active sidebar item */ +.theme-black { --itflow-accent: #000000; } +.theme-blue { --itflow-accent: #007bff; } +.theme-cyan { --itflow-accent: #17a2b8; } +.theme-fuchsia { --itflow-accent: #f012be; } +.theme-gray { --itflow-accent: #6c757d; } +.theme-green { --itflow-accent: #28a745; } +.theme-indigo { --itflow-accent: #6610f2; } +.theme-lightblue { --itflow-accent: #3c8dbc; } +.theme-maroon { --itflow-accent: #d81b60; } +.theme-navy { --itflow-accent: #001f3f; } +.theme-olive { --itflow-accent: #3d9970; } +.theme-orange { --itflow-accent: #fd7e14; } +.theme-pink { --itflow-accent: #e83e8c; } +.theme-purple { --itflow-accent: #6f42c1; } +.theme-red { --itflow-accent: #dc3545; } +.theme-teal { --itflow-accent: #20c997; } + +/* top navbar takes the theme colour */ +.app-header.navbar { + background-color: var(--itflow-accent, #007bff) !important; +} + +/* sidebar stays dark; only the ACTIVE item picks up the theme */ +.app-sidebar .sidebar-menu > .nav-item > .nav-link.active, +.app-sidebar .nav-treeview > .nav-item > .nav-link.active { + background-color: var(--itflow-accent, #007bff); + color: #fff; +} + +/* Bootstrap 5's reboot underlines every link; Bootstrap 4 did not, and + AdminLTE 3 additionally suppressed the hover underline. Restored so links + read the way they did before the migration. */ +a, +a:hover, +a:focus { + text-decoration: none; +} + +/* links and accented controls */ +a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn) { + color: var(--itflow-accent, #007bff); +} +a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, +.btn-link:hover, +.nav-tabs .nav-link:hover { + /* v3 darkened the accent by exactly 15% HSL lightness on hover */ + color: color-mix(in srgb, var(--itflow-accent, #007bff) 70%, #000); + color: hsl(from var(--itflow-accent, #007bff) h s calc(l - 15%)); +} +.nav-tabs .nav-link.active { color: var(--itflow-accent, #007bff); } +.page-item .page-link { color: var(--itflow-accent, #007bff); } +.page-item.active .page-link { + background-color: var(--itflow-accent, #007bff); + border-color: var(--itflow-accent, #007bff); +} +.dropdown-item.active, .dropdown-item:active { + background-color: var(--itflow-accent, #007bff); +} +.form-control:focus, .form-select:focus, .form-check-input:focus { + border-color: var(--itflow-accent, #007bff); +} +.form-check-input:checked { + background-color: var(--itflow-accent, #007bff); + border-color: var(--itflow-accent, #007bff); +} + +/* sidebar is ALWAYS dark - v4 gives .app-sidebar no background at all. + These are AdminLTE 3.2.0's [class*=sidebar-dark-] values verbatim. */ +.app-sidebar { + background-color: #343a40; +} +.app-sidebar .brand-link { + background-color: #343a40; + color: #fff; +} +.app-sidebar .sidebar-menu .nav-link, +.app-sidebar .nav-header { + color: #c2c7d0; +} +.app-sidebar .sidebar-menu > .nav-item > .nav-link:focus, +.app-sidebar .sidebar-menu > .nav-item:hover > .nav-link, +.app-sidebar .sidebar-menu > .nav-item.menu-open > .nav-link { + background-color: rgba(255, 255, 255, .1); + color: #fff; +} +.app-sidebar .sidebar-menu > .nav-item > .nav-link.active { + color: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24); +} +.app-sidebar .nav-treeview { + background-color: transparent; +} + +/* Navbar search. v3 tinted the field with a LIGHTENED version of the theme + colour (navy #001f3f -> #002953 at rest, lighter again on focus) rather + than a fixed grey. The color-mix line is the fallback; the relative-colour + line reproduces v3's HSL lighten exactly where the browser supports it. */ +.app-header .form-control-navbar, +.app-header .btn-navbar { + background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 90%, #fff); + background-color: hsl(from var(--itflow-accent, #007bff) h s calc(l + 4%)); + border-color: color-mix(in srgb, var(--itflow-accent, #007bff) 78%, #fff); + border-color: hsl(from var(--itflow-accent, #007bff) h s calc(l + 9%)); + color: rgba(255, 255, 255, .8); + box-shadow: none; +} +.app-header .form-control-navbar::placeholder { + color: rgba(255, 255, 255, .6); +} +.app-header .form-control-navbar:focus, +.app-header .form-control-navbar:focus + .btn-navbar { + background-color: color-mix(in srgb, var(--itflow-accent, #007bff) 82%, #fff); + background-color: hsl(from var(--itflow-accent, #007bff) h s calc(l + 9%)); + border-color: hsl(from var(--itflow-accent, #007bff) h s calc(l + 14%)); + color: #fff; + box-shadow: none; +} +.app-header .form-control-navbar:focus::placeholder { + color: #fff; +} + +/* box/card colours AdminLTE 4 also dropped (bg-purple, bg-pink, + bg-olive and bg-gray are still used on a few pages) */ +.bg-black { background-color: #000 !important; } +.bg-blue { background-color: rgba(63,103,145,.9) !important; } +.bg-cyan { background-color: rgba(52,152,219,.9) !important; } +.bg-fuchsia { background-color: rgba(246,114,216,.9) !important; } +.bg-gray { background-color: rgba(108,117,125,.9) !important; } +.bg-green { background-color: rgba(0,188,140,.9) !important; } +.bg-indigo { background-color: rgba(102,16,242,.9) !important; } +.bg-lightblue { background-color: rgba(134,186,216,.9) !important; } +.bg-maroon { background-color: rgba(237,108,155,.9) !important; } +.bg-navy { background-color: rgba(0,44,89,.9) !important; } +.bg-olive { background-color: rgba(116,200,163,.9) !important; } +.bg-orange { background-color: rgba(253,126,20,.9) !important; } +.bg-pink { background-color: rgba(232,62,140,.9) !important; } +.bg-purple { background-color: rgba(111,66,193,.9) !important; } +.bg-red { background-color: rgba(231,76,60,.9) !important; } +.bg-teal { background-color: rgba(32,201,151,.9) !important; } diff --git a/includes/header.php b/includes/header.php index 4307569b4..9bb0c05ee 100644 --- a/includes/header.php +++ b/includes/header.php @@ -41,6 +41,6 @@ header("X-Frame-Options: DENY"); - +
diff --git a/includes/top_nav.php b/includes/top_nav.php index 866399e30..b25a1157b 100644 --- a/includes/top_nav.php +++ b/includes/top_nav.php @@ -1,5 +1,5 @@ -
`; - $('.content-wrapper').append(modalHtml); + $('.app-main').append(modalHtml); const $modal = $('#' + modalId); - $modal.modal('show'); + bootstrap.Modal.getOrCreateInstance($modal[0]).show(); $modal.on('hidden.bs.modal', function () { $(this).remove(); diff --git a/js/app.js b/js/app.js index acb0777e5..0bf99fd51 100644 --- a/js/app.js +++ b/js/app.js @@ -427,7 +427,9 @@ $(document).ready(function() { // Enable Popovers $(function() { - $('[data-bs-toggle="popover"]').popover(); + document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function (el) { + bootstrap.Popover.getOrCreateInstance(el); + }); }); // Data Tables @@ -538,16 +540,19 @@ $(document).off('change.itflowEventTime').on('change.itflowEventTime', '.event-s * until the next page load. */ function flashTooltip(button, message) { - $(button) - .tooltip('dispose') - .tooltip({ - trigger: 'manual', - placement: 'bottom', - title: message - }) - .tooltip('show'); + const el = button instanceof Element ? button : $(button)[0]; + if (!el) { + return; + } + bootstrap.Tooltip.getInstance(el)?.dispose(); + const tip = new bootstrap.Tooltip(el, { + trigger: 'manual', + placement: 'bottom', + title: message + }); + tip.show(); - setTimeout(function() { - $(button).tooltip('dispose'); + setTimeout(function () { + tip.dispose(); }, 1000); } diff --git a/js/confirm_modal.js b/js/confirm_modal.js index 682a52111..f0cafc659 100644 --- a/js/confirm_modal.js +++ b/js/confirm_modal.js @@ -8,7 +8,7 @@ $(document).ready(function() { var linkReference = this; // Show the confirmation modal - $("#confirmationModal").modal('show'); + bootstrap.Modal.getOrCreateInstance(document.getElementById('confirmationModal')).show(); // When the submission is confirmed via the modal $("#confirmSubmitBtn").off('click').on('click', function() { diff --git a/js/show_modals.js b/js/show_modals.js index 4358aa2f4..a8f99d62d 100644 --- a/js/show_modals.js +++ b/js/show_modals.js @@ -2,7 +2,7 @@ $(document).ready(function () { $('.modal').each(function () { const modalId = `#${$(this).attr('id')}`; if (window.location.href.indexOf(modalId) !== -1) { - $(modalId).modal('show'); + bootstrap.Modal.getOrCreateInstance($(modalId)[0]).show(); } }); }); \ No newline at end of file