mirror of
https://github.com/itflow-org/itflow
synced 2026-08-17 13:05:12 +00:00
Fixed Side nav titles, Fixed ajax on bootstrap modals, fixed pagination all regressions
This commit is contained in:
@@ -1,13 +1,11 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
<a class="brand-link pb-1 mt-1" href="/agent/<?= $config_start_page ?>">
|
<div class="sidebar-brand">
|
||||||
<p class="h6">
|
<a class="brand-link" href="/agent/<?= $config_start_page ?>">
|
||||||
<i class="nav-icon fas fa-arrow-left ms-3 me-2"></i>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
<span class="brand-text">
|
<span class="brand-text h6 mb-0">Back | <strong>Administration</strong></span>
|
||||||
Back | <strong>Administration</strong>
|
</a>
|
||||||
</span>
|
</div>
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ ob_start();
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
function generatePassword() {
|
function generatePassword() {
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"/agent/ajax.php", {
|
"/agent/ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ ob_start();
|
|||||||
|
|
||||||
function generatePassword() {
|
function generatePassword() {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"/agent/ajax.php", {
|
"/agent/ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1338,7 +1338,7 @@ if (isset($_GET['asset_id'])) {
|
|||||||
var notes = document.getElementById("assetNotes").value;
|
var notes = document.getElementById("assetNotes").value;
|
||||||
|
|
||||||
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
||||||
jQuery.post(
|
itflowPost(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{
|
{
|
||||||
asset_set_notes: 'TRUE',
|
asset_set_notes: 'TRUE',
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ $sql_asset_retired = mysqli_query(
|
|||||||
var notes = document.getElementById("clientNotes").value;
|
var notes = document.getElementById("clientNotes").value;
|
||||||
|
|
||||||
// Send a POST request to ajax.php as ajax.php with data client_set_notes=true, client_id=NUM, notes=NOTES
|
// Send a POST request to ajax.php as ajax.php with data client_set_notes=true, client_id=NUM, notes=NOTES
|
||||||
jQuery.post(
|
itflowPost(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{
|
{
|
||||||
client_set_notes: 'TRUE',
|
client_set_notes: 'TRUE',
|
||||||
|
|||||||
@@ -1193,7 +1193,7 @@ if (isset($_GET['contact_id'])) {
|
|||||||
var notes = document.getElementById("contactNotes").value;
|
var notes = document.getElementById("contactNotes").value;
|
||||||
|
|
||||||
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
||||||
jQuery.post(
|
itflowPost(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{
|
{
|
||||||
contact_set_notes: 'TRUE',
|
contact_set_notes: 'TRUE',
|
||||||
@@ -1210,7 +1210,7 @@ if (isset($_GET['contact_id'])) {
|
|||||||
|
|
||||||
function generatePassword(type, id) {
|
function generatePassword(type, id) {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="pb-1 mt-1 brand-link" href="../<?= $config_start_page ?>">
|
<div class="sidebar-brand">
|
||||||
<p class="h5"><i class="nav-icon fas fa-arrow-left ms-3 me-2"></i>
|
<a class="brand-link" href="../<?= $config_start_page ?>">
|
||||||
<span class="brand-text ">Back | <strong>Custom</strong>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
</p>
|
<span class="brand-text h5 mb-0">Back | <strong>Custom</strong></span>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -33,11 +33,12 @@ $num_software = $row['num'];
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="pb-1 mt-1 brand-link" href="clients.php">
|
<div class="sidebar-brand">
|
||||||
<p class="h6"><i class="nav-icon fas fa-arrow-left ms-3 me-2"></i>
|
<a class="brand-link" href="clients.php">
|
||||||
<span class="brand-text ">Back | <strong>All Client Docs</strong>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
</p>
|
<span class="brand-text h6 mb-0">Back | <strong>All Client Docs</strong></span>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="brand-link pb-1 mt-1" href="/agent/clients.php">
|
<div class="sidebar-brand">
|
||||||
<p class="h5">
|
<a class="brand-link" href="/agent/clients.php">
|
||||||
<i class="nav-icon fas fa-arrow-left ms-3 me-1"></i>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
<span class="brand-text">
|
<span class="brand-text h5 mb-0">Back | <strong><?= $client_name_truncated ?></strong></span>
|
||||||
Back | <strong><?= $client_name_truncated ?></strong>
|
</a>
|
||||||
</span>
|
</div>
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="brand-link" href="/agent/dashboard.php">
|
<div class="sidebar-brand">
|
||||||
<div class="brand-image"></div>
|
<a class="brand-link" href="/agent/dashboard.php">
|
||||||
<span class="brand-text h4"><?= escapeHtml($session_company_name) ?></span>
|
<span class="brand-text h4"><?= escapeHtml($session_company_name) ?></span>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ function fetchSSL(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Send a GET request to post.php as post.php?certificate_fetch_parse_json_details=TRUE&domain=DOMAIN
|
//Send a GET request to post.php as post.php?certificate_fetch_parse_json_details=TRUE&domain=DOMAIN
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{certificate_fetch_parse_json_details: 'TRUE', domain: domain},
|
{certificate_fetch_parse_json_details: 'TRUE', domain: domain},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function showOTPViaCredentialID(credential_id) {
|
function showOTPViaCredentialID(credential_id) {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&credential_id=ID
|
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&credential_id=ID
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_totp_token_via_id: 'true',
|
get_totp_token_via_id: 'true',
|
||||||
credential_id: credential_id
|
credential_id: credential_id
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function showPasswordViaCredentialID(button, credential_id) {
|
function showPasswordViaCredentialID(button, credential_id) {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_credential_via_id=true&credential_id=ID
|
// Send a GET request to ajax.php as ajax.php?get_credential_via_id=true&credential_id=ID
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_credential_via_id: 'true',
|
get_credential_via_id: 'true',
|
||||||
credential_id: credential_id
|
credential_id: credential_id
|
||||||
@@ -21,7 +21,7 @@ function showPasswordViaCredentialID(button, credential_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function copyPasswordViaCredentialID(button, credential_id) {
|
function copyPasswordViaCredentialID(button, credential_id) {
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_credential_via_id: 'true',
|
get_credential_via_id: 'true',
|
||||||
credential_id: credential_id
|
credential_id: credential_id
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function generatePassword(login_id) {
|
function generatePassword(login_id) {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ function generateShareLink() {
|
|||||||
// Check values are provided
|
// Check values are provided
|
||||||
if (item_expires) {
|
if (item_expires) {
|
||||||
// Send a GET request to ajax.php as ajax.php?share_generate_link=true....
|
// Send a GET request to ajax.php as ajax.php?share_generate_link=true....
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{share_generate_link: 'true', csrf_token: csrf_token, client_id: client_id, type: item_type, id: item_ref_id, note: item_note ,views: item_views, expires: item_expires, contact_email},
|
{share_generate_link: 'true', csrf_token: csrf_token, client_id: client_id, type: item_type, id: item_ref_id, note: item_note ,views: item_views, expires: item_expires, contact_email},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function ticket_collision_detection() {
|
|||||||
var ticket_id = document.getElementById("ticket_id").value;
|
var ticket_id = document.getElementById("ticket_id").value;
|
||||||
|
|
||||||
//Send a GET request to ajax.php as ajax.php?ticket_add_view=true&ticket_id=NUMBER
|
//Send a GET request to ajax.php as ajax.php?ticket_add_view=true&ticket_id=NUMBER
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{ticket_add_view: 'true', ticket_id: ticket_id},
|
{ticket_add_view: 'true', ticket_id: ticket_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
@@ -16,7 +16,7 @@ function ticket_collision_detection() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
//Send a GET request to ajax.php as ajax.php?ticket_query_views=true&ticket_id=NUMBER
|
//Send a GET request to ajax.php as ajax.php?ticket_query_views=true&ticket_id=NUMBER
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{ticket_query_views: 'true', ticket_id: ticket_id},
|
{ticket_query_views: 'true', ticket_id: ticket_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -164,7 +164,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send a GET request to ajax.php as ajax.php?get_client_contacts=true&client_id=NUM
|
// Send a GET request to ajax.php as ajax.php?get_client_contacts=true&client_id=NUM
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{get_client_contacts: 'true', client_id: client_id},
|
{get_client_contacts: 'true', client_id: client_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
@@ -229,7 +229,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{get_client_assets: 'true', client_id: client_id},
|
{get_client_assets: 'true', client_id: client_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
@@ -279,7 +279,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{get_client_locations: 'true', client_id: client_id},
|
{get_client_locations: 'true', client_id: client_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{get_client_vendors: 'true', client_id: client_id},
|
{get_client_vendors: 'true', client_id: client_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
@@ -347,7 +347,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{get_client_projects: 'true', client_id: client_id},
|
{get_client_projects: 'true', client_id: client_id},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ ob_start();
|
|||||||
var notes = document.getElementById("assetNotes").value;
|
var notes = document.getElementById("assetNotes").value;
|
||||||
|
|
||||||
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
||||||
jQuery.post(
|
itflowPost(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{
|
{
|
||||||
asset_set_notes: 'TRUE',
|
asset_set_notes: 'TRUE',
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ ob_start();
|
|||||||
function checkClientDuplicate() {
|
function checkClientDuplicate() {
|
||||||
var name = document.getElementById("client_name").value;
|
var name = document.getElementById("client_name").value;
|
||||||
//Send a GET request to ajax.php as ajax.php?client_duplicate_check=true&name=NAME
|
//Send a GET request to ajax.php as ajax.php?client_duplicate_check=true&name=NAME
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{client_duplicate_check: 'true', name: name},
|
{client_duplicate_check: 'true', name: name},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ ob_start();
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
function generatePassword() {
|
function generatePassword() {
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
@@ -321,7 +321,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
function checkContactEmail() {
|
function checkContactEmail() {
|
||||||
var email = document.getElementById("contact_email").value;
|
var email = document.getElementById("contact_email").value;
|
||||||
//Send a GET request to ajax.php as ajax.php?contact_email_check=true&email=email
|
//Send a GET request to ajax.php as ajax.php?contact_email_check=true&email=email
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{contact_email_check: 'true', email: email},
|
{contact_email_check: 'true', email: email},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ ob_start();
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
function generatePassword() {
|
function generatePassword() {
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php", {
|
"ajax.php", {
|
||||||
get_readable_pass: 'true'
|
get_readable_pass: 'true'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ ob_start();
|
|||||||
function checkApexDomain() {
|
function checkApexDomain() {
|
||||||
var domain = document.getElementById("domain_name").value;
|
var domain = document.getElementById("domain_name").value;
|
||||||
//Send a GET request to ajax.php as ajax.php?apex_domain_check=true&domain=domain
|
//Send a GET request to ajax.php as ajax.php?apex_domain_check=true&domain=domain
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{apex_domain_check: 'true', domain: domain},
|
{apex_domain_check: 'true', domain: domain},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="pb-1 mt-1 brand-link" href="/agent/<?= $config_start_page ?>">
|
<div class="sidebar-brand">
|
||||||
<p class="h5"><i class="nav-icon fas fa-arrow-left ms-3 me-2"></i>
|
<a class="brand-link" href="/agent/<?= $config_start_page ?>">
|
||||||
<span class="brand-text ">Back | <strong>Reports</strong>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
</p>
|
<span class="brand-text h5 mb-0">Back | <strong>Reports</strong></span>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
<a class="brand-link pb-1 mt-1" href="/agent/<?= $config_start_page ?>">
|
<div class="sidebar-brand">
|
||||||
<p class="h5">
|
<a class="brand-link" href="/agent/<?= $config_start_page ?>">
|
||||||
<i class="nav-icon fas fa-arrow-left ms-3 me-2"></i>
|
<i class="fas fa-arrow-left me-2"></i>
|
||||||
<span class="brand-text">
|
<span class="brand-text h5 mb-0">Back | <strong>Account</strong></span>
|
||||||
Back | <strong>Account</strong>
|
</a>
|
||||||
</span>
|
</div>
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar-wrapper">
|
<div class="sidebar-wrapper">
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ $data = "otpauth://totp/ITFlow:$session_email?secret=$token";
|
|||||||
<!-- REQUIRED SCRIPTS -->
|
<!-- REQUIRED SCRIPTS -->
|
||||||
|
|
||||||
<!-- Bootstrap 4 -->
|
<!-- Bootstrap 4 -->
|
||||||
|
<script src="/js/http.js"></script>
|
||||||
<script src="../../libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="../../libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
<!-- Custom js-->
|
<!-- Custom js-->
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
<!-- Bootstrap 4 -->
|
<!-- Bootstrap 4 -->
|
||||||
<script src="/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="/js/http.js"></script>
|
||||||
|
|
||||||
<!--- TinyMCE -->
|
<!--- TinyMCE -->
|
||||||
<script src="/libs/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
<script src="/libs/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
||||||
|
|||||||
@@ -168,10 +168,19 @@ a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-li
|
|||||||
color: hsl(from var(--itflow-accent, #007bff) h s calc(l - 15%));
|
color: hsl(from var(--itflow-accent, #007bff) h s calc(l - 15%));
|
||||||
}
|
}
|
||||||
.nav-tabs .nav-link.active { color: var(--itflow-accent, #007bff); }
|
.nav-tabs .nav-link.active { color: var(--itflow-accent, #007bff); }
|
||||||
.page-item .page-link { color: var(--itflow-accent, #007bff); }
|
/* Pagination. Driving Bootstrap's own variables rather than overriding
|
||||||
.page-item.active .page-link {
|
.page-link directly: a flat `.page-item .page-link{color:...}` ties with
|
||||||
background-color: var(--itflow-accent, #007bff);
|
BS5's `.active>.page-link` and `.disabled>.page-link` on specificity and,
|
||||||
border-color: var(--itflow-accent, #007bff);
|
because this sheet loads last, silently won both - so the active number was
|
||||||
|
accent-on-accent (invisible) and disabled Prev/Next lost their muted grey. */
|
||||||
|
.pagination {
|
||||||
|
--bs-pagination-color: var(--itflow-accent, #007bff);
|
||||||
|
--bs-pagination-hover-color: color-mix(in srgb, var(--itflow-accent, #007bff) 70%, #000);
|
||||||
|
--bs-pagination-hover-color: hsl(from var(--itflow-accent, #007bff) h s calc(l - 15%));
|
||||||
|
--bs-pagination-focus-color: var(--itflow-accent, #007bff);
|
||||||
|
--bs-pagination-active-color: #fff;
|
||||||
|
--bs-pagination-active-bg: var(--itflow-accent, #007bff);
|
||||||
|
--bs-pagination-active-border-color: var(--itflow-accent, #007bff);
|
||||||
}
|
}
|
||||||
.dropdown-item.active, .dropdown-item:active {
|
.dropdown-item.active, .dropdown-item:active {
|
||||||
background-color: var(--itflow-accent, #007bff);
|
background-color: var(--itflow-accent, #007bff);
|
||||||
@@ -189,8 +198,26 @@ a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-li
|
|||||||
.app-sidebar {
|
.app-sidebar {
|
||||||
background-color: #343a40;
|
background-color: #343a40;
|
||||||
}
|
}
|
||||||
.app-sidebar .brand-link {
|
/* Sidebar header. v4 scopes its brand rules under .sidebar-brand, and its own
|
||||||
|
defaults centre the brand in a fixed 2.75rem box. v3's .brand-link was a
|
||||||
|
left-aligned block, and several of these headers carry a "Back | ..." line
|
||||||
|
that is taller than that, so height is relaxed and alignment restored. */
|
||||||
|
.app-sidebar .sidebar-brand {
|
||||||
|
/* v4 deliberately pairs .sidebar-brand{height:2.75rem} with
|
||||||
|
.app-header{max-height:2.75rem} so the sidebar header lines up with the
|
||||||
|
top bar. Keep that height and cut the vertical padding instead - v4's
|
||||||
|
.8125rem leaves only 18px of the 44px box, which clips even an h6. */
|
||||||
|
height: 2.75rem;
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
justify-content: flex-start;
|
||||||
background-color: #343a40;
|
background-color: #343a40;
|
||||||
|
border-bottom: 1px solid #4b545c;
|
||||||
|
}
|
||||||
|
.app-sidebar .sidebar-brand .brand-link {
|
||||||
|
width: 100%;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.app-sidebar .sidebar-brand .brand-text {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.app-sidebar .sidebar-menu .nav-link,
|
.app-sidebar .sidebar-menu .nav-link,
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ if ($item_type == "Document") {
|
|||||||
<script>
|
<script>
|
||||||
function refreshOTP() {
|
function refreshOTP() {
|
||||||
// Send a GET request to guest_ajax.php as guest_ajax.php?get_share_totp_token=true&id=ID&key=KEY
|
// Send a GET request to guest_ajax.php as guest_ajax.php?get_share_totp_token=true&id=ID&key=KEY
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"guest_ajax.php",
|
"guest_ajax.php",
|
||||||
{
|
{
|
||||||
get_share_totp_token: 'true',
|
get_share_totp_token: 'true',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ if (basename(dirname($_SERVER['REQUEST_URI'])) === 'guest') { ?>
|
|||||||
|
|
||||||
<!-- Bootstrap 5 -->
|
<!-- Bootstrap 5 -->
|
||||||
<script src="/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="/js/http.js"></script>
|
||||||
|
|
||||||
<!-- Custom js-->
|
<!-- Custom js-->
|
||||||
<script src="/libs/chart.js/chart.umd.min.js"></script>
|
<script src="/libs/chart.js/chart.umd.min.js"></script>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<script src="/js/http.js"></script>
|
||||||
<script src="/js/autocomplete.js"></script>
|
<script src="/js/autocomplete.js"></script>
|
||||||
<script src="/js/app.js"></script>
|
<script src="/js/app.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Re-run <script> elements that arrived via innerHTML, strictly in order.
|
||||||
|
*
|
||||||
|
* External scripts are awaited before the next one starts; inline scripts run
|
||||||
|
* synchronously. Order matters because a modal's own script is emitted before
|
||||||
|
* modal_footer.php's http.js / autocomplete.js / app.js, and depends on them.
|
||||||
|
*/
|
||||||
|
function runScriptsInOrder(scripts) {
|
||||||
|
return scripts.reduce(function (chain, old) {
|
||||||
|
return chain.then(function () {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
const s = document.createElement('script');
|
||||||
|
for (const attr of old.attributes) {
|
||||||
|
s.setAttribute(attr.name, attr.value);
|
||||||
|
}
|
||||||
|
if (old.src) {
|
||||||
|
s.async = false;
|
||||||
|
s.onload = resolve;
|
||||||
|
s.onerror = function () {
|
||||||
|
console.error('ajax-modal: failed to load', old.src);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
old.replaceWith(s);
|
||||||
|
} else {
|
||||||
|
s.textContent = old.textContent;
|
||||||
|
old.replaceWith(s);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, Promise.resolve());
|
||||||
|
}
|
||||||
|
|
||||||
// Ajax Modal Load Script
|
// Ajax Modal Load Script
|
||||||
document.addEventListener('click', function (e) {
|
document.addEventListener('click', function (e) {
|
||||||
const trigger = e.target.closest('.ajax-modal');
|
const trigger = e.target.closest('.ajax-modal');
|
||||||
@@ -64,19 +97,17 @@ document.addEventListener('click', function (e) {
|
|||||||
'</div>';
|
'</div>';
|
||||||
host.appendChild(wrapper);
|
host.appendChild(wrapper);
|
||||||
|
|
||||||
// innerHTML does not execute <script> tags. The modal payload ends
|
// innerHTML does not execute <script> tags, so they have to be
|
||||||
// with modal_footer.php, which re-runs app.js to wire up Tom Select,
|
// re-injected. They must also run IN ORDER: a modal payload loads
|
||||||
// IMask, flatpickr and friends - so re-inject them by hand.
|
// its own script first and modal_footer.php's http.js / app.js
|
||||||
wrapper.querySelectorAll('script').forEach(function (old) {
|
// after, and the modal script depends on helpers those define.
|
||||||
const s = document.createElement('script');
|
// A dynamically created <script src> is async by default and would
|
||||||
for (const attr of old.attributes) {
|
// run in completion order instead - jQuery's .append() loaded them
|
||||||
s.setAttribute(attr.name, attr.value);
|
// sequentially, which is the behaviour reproduced here.
|
||||||
}
|
runScriptsInOrder(Array.from(wrapper.querySelectorAll('script')))
|
||||||
s.textContent = old.textContent;
|
.then(function () {
|
||||||
old.replaceWith(s);
|
bootstrap.Modal.getOrCreateInstance(wrapper).show();
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap.Modal.getOrCreateInstance(wrapper).show();
|
|
||||||
|
|
||||||
wrapper.addEventListener('hidden.bs.modal', function () {
|
wrapper.addEventListener('hidden.bs.modal', function () {
|
||||||
wrapper.remove();
|
wrapper.remove();
|
||||||
|
|||||||
74
js/app.js
74
js/app.js
@@ -8,38 +8,20 @@
|
|||||||
* jQuery's delegation contract so the handler bodies are unchanged.
|
* jQuery's delegation contract so the handler bodies are unchanged.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* $.post replacement. jQuery serialised nested arrays/objects into PHP-style
|
* Run one initialiser in isolation.
|
||||||
* bracket params (positions[0][status_id]=...), which is what ajax.php parses,
|
*
|
||||||
* so that encoding is reproduced here rather than sending JSON.
|
* itflowInit() sets up eight independent libraries in sequence. Without this,
|
||||||
|
* a throw in any one of them aborts the whole function and every initialiser
|
||||||
|
* after it silently never runs - which is exactly the kind of failure that
|
||||||
|
* looks like "everything is broken" while the console shows one error from a
|
||||||
|
* library you were not looking at.
|
||||||
*/
|
*/
|
||||||
function itflowPostForm(url, data) {
|
function itflowStep(name, fn) {
|
||||||
const params = new URLSearchParams();
|
try {
|
||||||
|
fn();
|
||||||
(function add(prefix, value) {
|
} catch (e) {
|
||||||
if (Array.isArray(value)) {
|
console.error('itflow init [' + name + '] failed:', e);
|
||||||
value.forEach(function (v, i) {
|
}
|
||||||
add(prefix + '[' + i + ']', v);
|
|
||||||
});
|
|
||||||
} else if (value !== null && typeof value === 'object') {
|
|
||||||
Object.keys(value).forEach(function (k) {
|
|
||||||
add(prefix ? prefix + '[' + k + ']' : k, value[k]);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
params.append(prefix, value === true ? 'true' : String(value));
|
|
||||||
}
|
|
||||||
})('', data);
|
|
||||||
|
|
||||||
return fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
credentials: 'same-origin',
|
|
||||||
body: params.toString()
|
|
||||||
}).then(function (res) {
|
|
||||||
if (!res.ok) {
|
|
||||||
throw new Error('HTTP ' + res.status);
|
|
||||||
}
|
|
||||||
return res.text();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function itflowBindOnce(name, type, selector, handler) {
|
function itflowBindOnce(name, type, selector, handler) {
|
||||||
@@ -90,8 +72,10 @@ function itflowInit() {
|
|||||||
|
|
||||||
// Initialize Tom Select (replaces Select2). Every instance is reachable
|
// Initialize Tom Select (replaces Select2). Every instance is reachable
|
||||||
// afterwards as element.tomselect, which is how the helpers below reach it.
|
// afterwards as element.tomselect, which is how the helpers below reach it.
|
||||||
document.querySelectorAll('.select2').forEach(function (el) {
|
itflowStep('tom-select', function () {
|
||||||
initTomSelect(el);
|
document.querySelectorAll('.select2').forEach(function (el) {
|
||||||
|
initTomSelect(el);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize TinyMCE
|
// Initialize TinyMCE
|
||||||
@@ -532,23 +516,29 @@ function itflowInit() {
|
|||||||
// the lever, not a Bootstrap patch.
|
// the lever, not a Bootstrap patch.
|
||||||
|
|
||||||
// Clipboard
|
// Clipboard
|
||||||
var clipboard = new ClipboardJS('.clipboardjs');
|
itflowStep('clipboard', function () {
|
||||||
|
var clipboard = new ClipboardJS('.clipboardjs');
|
||||||
|
|
||||||
clipboard.on('success', function(e) {
|
clipboard.on('success', function(e) {
|
||||||
flashTooltip(e.trigger, 'Copied!');
|
flashTooltip(e.trigger, 'Copied!');
|
||||||
});
|
});
|
||||||
|
|
||||||
clipboard.on('error', function(e) {
|
clipboard.on('error', function(e) {
|
||||||
flashTooltip(e.trigger, 'Failed!');
|
flashTooltip(e.trigger, 'Failed!');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enable Popovers
|
// Enable Popovers
|
||||||
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function (el) {
|
itflowStep('popovers', function () {
|
||||||
bootstrap.Popover.getOrCreateInstance(el);
|
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function (el) {
|
||||||
|
bootstrap.Popover.getOrCreateInstance(el);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Data Tables
|
// Data Tables
|
||||||
new DataTable('.dataTables');
|
itflowStep('datatables', function () {
|
||||||
|
new DataTable('.dataTables');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// modal_footer.php re-loads this file on every ajax modal open, so run now if
|
// modal_footer.php re-loads this file on every ajax modal open, so run now if
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function showOTPViaCredentialID(credential_id) {
|
function showOTPViaCredentialID(credential_id) {
|
||||||
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&credential_id=ID
|
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&credential_id=ID
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"../ajax.php", {
|
"../ajax.php", {
|
||||||
get_totp_token_via_id: 'true',
|
get_totp_token_via_id: 'true',
|
||||||
credential_id: credential_id
|
credential_id: credential_id
|
||||||
|
|||||||
96
js/http.js
Normal file
96
js/http.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Drop-in replacements for itflowGet() and itflowPost().
|
||||||
|
*
|
||||||
|
* These keep jQuery's exact call shape - itflowGet(url, data, success, error) -
|
||||||
|
* so the ~28 existing call sites did not have to be restructured when jQuery
|
||||||
|
* was removed. Every one of them uses the plain callback form; none chained
|
||||||
|
* .done()/.fail() or passed a dataType, so nothing else is reproduced here.
|
||||||
|
*
|
||||||
|
* The success callback receives the raw response TEXT, matching jQuery's
|
||||||
|
* behaviour when the server does not send a JSON content type. Several call
|
||||||
|
* sites do their own JSON.parse(), so returning a parsed object here would
|
||||||
|
* break them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Serialise to PHP-style bracket params, the way jQuery did. */
|
||||||
|
function itflowSerialize(data) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
(function add(prefix, value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach(function (v, i) {
|
||||||
|
add(prefix + '[' + i + ']', v);
|
||||||
|
});
|
||||||
|
} else if (value !== null && typeof value === 'object') {
|
||||||
|
Object.keys(value).forEach(function (k) {
|
||||||
|
add(prefix ? prefix + '[' + k + ']' : k, value[k]);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
params.append(prefix, value === true ? 'true' : String(value));
|
||||||
|
}
|
||||||
|
})('', data || {});
|
||||||
|
|
||||||
|
return params.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function itflowGet(url, data, success, error) {
|
||||||
|
const query = itflowSerialize(data);
|
||||||
|
const sep = url.indexOf('?') === -1 ? '?' : '&';
|
||||||
|
|
||||||
|
return fetch(query ? url + sep + query : url, {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'same-origin'
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error('HTTP ' + res.status);
|
||||||
|
}
|
||||||
|
return res.text();
|
||||||
|
})
|
||||||
|
.then(function (text) {
|
||||||
|
if (typeof success === 'function') {
|
||||||
|
success(text);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
if (typeof error === 'function') {
|
||||||
|
error(err);
|
||||||
|
} else {
|
||||||
|
console.error('itflowGet ' + url + ':', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function itflowPost(url, data, success, error) {
|
||||||
|
return fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: itflowSerialize(data)
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error('HTTP ' + res.status);
|
||||||
|
}
|
||||||
|
return res.text();
|
||||||
|
})
|
||||||
|
.then(function (text) {
|
||||||
|
if (typeof success === 'function') {
|
||||||
|
success(text);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
if (typeof error === 'function') {
|
||||||
|
error(err);
|
||||||
|
} else {
|
||||||
|
console.error('itflowPost ' + url + ':', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Kept for the kanban and invoice item-order callers, which use this name. */
|
||||||
|
function itflowPostForm(url, data) {
|
||||||
|
return itflowPost(url, data);
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
function keep_alive() {
|
function keep_alive() {
|
||||||
|
|
||||||
//Send a GET request to keepalive.php as keepalive.php?keepalive
|
//Send a GET request to keepalive.php as keepalive.php?keepalive
|
||||||
jQuery.get(
|
itflowGet(
|
||||||
"/keepalive.php",
|
"/keepalive.php",
|
||||||
{keepalive: 'true'},
|
{keepalive: 'true'},
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
@@ -574,9 +574,11 @@ if (isset($_POST['add_telemetry'])) {
|
|||||||
<aside class="app-sidebar shadow" data-bs-theme="dark">
|
<aside class="app-sidebar shadow" data-bs-theme="dark">
|
||||||
|
|
||||||
<!-- Brand Logo -->
|
<!-- Brand Logo -->
|
||||||
<a href="https://itflow.org" class="brand-link">
|
<div class="sidebar-brand">
|
||||||
<h3 class="brand-text fw-light"><i class="fas fa-paper-plane text-primary me-2"></i><span class="text-primary text-bold">IT</span>Flow</h3>
|
<a href="https://itflow.org" class="brand-link">
|
||||||
</a>
|
<h3 class="brand-text fw-light"><i class="fas fa-paper-plane text-primary me-2"></i><span class="text-primary text-bold">IT</span>Flow</h3>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
|
|||||||
Reference in New Issue
Block a user