37 Commits

Author SHA1 Message Date
Johnny
7e658ee1f2 Merge pull request #1177 from itflow-org/develop
Release v25.02.1
2025-03-01 12:29:14 -05:00
Johnny
bbee81c3bb Merge pull request #1176 from Whit3XLightning/Whit3XLightning-patch-2
Update folder_create_modal.php
2025-03-01 12:11:59 -05:00
johnnyq
45b61ba335 Updated Changelog 2025-03-01 12:09:43 -05:00
johnnyq
32e6345cbc Add Paid to the top of a pdf invoice if paid 2025-03-01 12:03:48 -05:00
Tallyn Morse
afff46972a Update folder_create_modal.php
$folder['folder_name']; did not exist in the scope of where folder_create_modal.php was being required in the client_files.php and client_documents.php leading to null array pointer exception. While dirty the new way will reliably retrieve the name of the current folder the user is browsing to correctly name the modal.
2025-02-28 23:26:39 -06:00
johnnyq
d197995226 Updated Changelog, and Updated version to 25.02.1 2025-02-28 15:24:47 -05:00
johnnyq
09fa23519d Use Generated Thumbnail images if available in Gallery view for files, add options to download Original, Preview (Optimized) or Thumbnail 2025-02-28 14:43:03 -05:00
johnnyq
9da736daee Enhance the file picture upload optimization to read EXIF data when available and correctly adjust the image orientation for the optimized version. 2025-02-28 13:55:32 -05:00
johnnyq
410d1e0f86 Add Fade Animation to ajax modals 2025-02-28 13:34:26 -05:00
johnnyq
12ad7962c0 Wrap text in notifications 2025-02-28 13:31:53 -05:00
Johnny
397ebc5112 Merge pull request #1175 from ssteeltm/fix-kanban-dragging-touch
fix: kanban cards dragging when on touch devices
2025-02-27 23:25:58 -05:00
ssteeltm
d48823925a fix: kanban cards dragging when on touch devices 2025-02-27 18:36:34 -03:00
johnnyq
6f49f16f6b Fix Links cannot contain directories that exist https://forum.itflow.org/d/1568-bulk-send-email-links-cannot-contain-directories-that-exist 2025-02-27 15:21:04 -05:00
johnnyq
c2664a2888 Add .zed to the .gitignore 2025-02-27 11:46:29 -05:00
johnnyq
4529a56d7b Fix Sort Newest to oldest in notifications 2025-02-27 11:22:02 -05:00
johnnyq
fded8177c5 Added contact and Asset Indicators with quick links to credentials page 2025-02-26 16:00:22 -05:00
johnnyq
e670a9847a Added Indicator Counts for assets, credentials, licenses, tickets and documnent in Contacts Listing 2025-02-26 15:35:14 -05:00
johnnyq
8aada99f06 Added Edit to asset and contact details ajax modal for quick edits, added more links to the vendor details ajax modal 2025-02-26 13:46:04 -05:00
johnnyq
04e624cc14 Added Purchase Reference to Software Licneses 2025-02-26 12:59:03 -05:00
johnnyq
55ebe70808 Add Vendor Details Popup, works with Domain Vendors right now, Added fallBack function when no text is present use a placeholder 2025-02-25 18:16:03 -05:00
johnnyq
f23afdd85c Added Quick Category/Tag Add throughout utilizes the new ajax modal 2025-02-25 17:05:34 -05:00
johnnyq
bac76871c1 Added vendor UI select elements for software 2025-02-24 21:36:30 -05:00
johnnyq
56cbcf2921 Removed Single Link Vendor Login and single link software login. These are unused will be moved to multi to multi relationship, also added vendor_id to software to reference a vendor 2025-02-24 21:24:57 -05:00
johnnyq
f2dc25aedb Added Link to and unlink Items in Asset Details 2025-02-24 19:08:00 -05:00
johnnyq
2367ca2255 Remove expire record limits and only include items expiring within 45 days instead of 90 in client overview 2025-02-24 17:24:43 -05:00
johnnyq
f28c1ce398 In-App alerts are spawned 1,7 and 45 days instead of 1,7,14,30 and 90 2025-02-24 17:03:29 -05:00
johnnyq
6cc6e80f92 Fixed ticket link for agent email notifications on scheduling tickets 2025-02-24 16:19:22 -05:00
johnnyq
9aeda2ce53 Set Array instead of selecting Days to Expire in client overview 2025-02-24 13:18:32 -05:00
johnnyq
a08393b4d4 Fix Redirect Link when scheduling tickets that conflict with other scheduled tickets 2025-02-24 12:52:35 -05:00
johnnyq
02c1446cb8 Fix Transfer Asset(s) to Client 2025-02-24 12:42:31 -05:00
johnnyq
8e66434ec4 Updated asset details Link in rack, fixed opening asset details modal when clicking on a connected asset in asset details page 2025-02-23 15:48:47 -05:00
johnnyq
66d43d8a95 Dashboard When clicking domains or certificates sort by expire date asc 2025-02-23 12:30:47 -05:00
johnnyq
6c7052ea0d Fix missing public key var in certificate edit 2025-02-23 12:23:13 -05:00
johnnyq
a994bb7e8c Update Links on Project and and client listing 2025-02-22 17:37:35 -05:00
johnnyq
9b109c7abd Update links in project list 2025-02-22 17:29:19 -05:00
johnnyq
95855fc22e Update links in client overview 2025-02-22 17:27:16 -05:00
johnnyq
3218ea85b2 Bug Fix Contact Detail Modal not showing Credentials or Tickets 2025-02-22 17:15:41 -05:00
84 changed files with 2257 additions and 849 deletions

1
.gitignore vendored
View File

@@ -26,3 +26,4 @@ xcustom/*
!xcustom/readme.php
post/xcustom
!post/xcustom/readme.php
.zed

View File

@@ -2,6 +2,30 @@
This file documents all notable changes made to ITFlow.
## [25.02.1]
### Fixed
- Resolved broken links in the client overview, project and client listings, and rack details.
- Corrected asset transfer functionality to clients.
- Fixed the ticket scheduling redirect.
- Corrected the ticket link in the Scheduled Ticket Agent Notification email.
- Addressed issues with credentials and ticket actions in the Contact Detail Modal.
- Fixed text wrapping in notifications.
- Adjusted notifications so that they are sorted with the newest first.
- Fixed drag-and-drop functionality for tickets in the Kanban view on mobile devices.
- Resolved a weird issue with TinyMCE that prevented using links referencing your ITFlow instance url.
- Corrected image orientation issues during upload and the preview optimization process.
### Added / Changed
- Introduced entity link indicator icons and counts in the contacts and credentials section.
- Implemented a fade animation for the new AJAX modal.
- Removed the Client Overview Expire Day Select and replaced it with simplified 1, 7, or 45-day options.
- Added the ability to link and unlink entities within asset details.
- Introduced quick tag/category creation across the app.
- Added a Vendor Quick Details Modal.
- Enabled vendor linking and added a License Purchase Reference in the Software Licenses section.
- Added download original, optimized and thumbnail option for images.
- Added Paid status to the top corner of Invoice PDFs
## [25.02]
### Fixed
- Migrated several reports to the new permissions/roles system

View File

@@ -37,7 +37,7 @@ require_once "includes/inc_all_admin.php";
<th>
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7, 14, 30 and 90 days prior to expiry.)
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
@@ -54,7 +54,7 @@ require_once "includes/inc_all_admin.php";
<th>
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7, 14, 30 and 90 days prior to expiry.)
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
@@ -67,7 +67,7 @@ require_once "includes/inc_all_admin.php";
<th>
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7, 14, 30 and 90 days prior to expiry.)
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>

View File

@@ -121,9 +121,7 @@ $sql_related_credentials = mysqli_query($mysqli, "
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_vendor_id,
logins.login_asset_id,
logins.login_software_id
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
@@ -474,9 +472,7 @@ ob_start();
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
// Tags
$login_tag_name_display_array = array();
@@ -852,7 +848,11 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="asset_details.php?<?php echo $client_url; ?>asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white">More Details</span></a>
<a href="asset_details.php?<?php echo $client_url; ?>asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
<a href="#" class="btn btn-secondary"
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_asset_edit.php" data-ajax-id="<?php echo $asset_id; ?>">
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span>
</a>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Close</button>
</div>

View File

@@ -0,0 +1,43 @@
<?php
require_once '../includes/ajax_header.php';
$category = nullable_htmlentities($_GET['category']);
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-list-ul mr-2"></i>New Category</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="type" value="<?php echo ($category); ?>">
<div class="modal-body bg-white">
<div class="form-row">
<div class="form-group col-sm-9">
<div class="input-group">
<input type="text" class="form-control" name="name" placeholder="Category name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group col-sm-3">
<div class="input-group">
<input type="color" class="form-control" name="color" required>
</div>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_category" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -12,6 +12,7 @@ $certificate_description = nullable_htmlentities($row['certificate_description']
$certificate_domain = nullable_htmlentities($row['certificate_domain']);
$certificate_domain_id = intval($row['certificate_domain_id']);
$certificate_issued_by = nullable_htmlentities($row['certificate_issued_by']);
$certificate_public_key = nullable_htmlentities($row['certificate_public_key']);
$certificate_expire = nullable_htmlentities($row['certificate_expire']);
$certificate_created_at = nullable_htmlentities($row['certificate_created_at']);
$client_id = intval($row['certificate_client_id']);

View File

@@ -125,6 +125,14 @@ ob_start();
}
?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Referral">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
@@ -157,6 +165,15 @@ ob_start();
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="1">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -402,7 +402,7 @@ ob_start();
<?php } ?>
<?php if ($credential_count) { ?>
<div class="tab-pane fade" id="pills-contact-credentials<?php echo $asset_id; ?>">
<div class="tab-pane fade" id="pills-contact-credentials<?php echo $contact_id; ?>">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm">
<thead>
@@ -446,9 +446,7 @@ ob_start();
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
// Tags
$login_tag_name_display_array = array();
@@ -499,7 +497,7 @@ ob_start();
<?php } ?>
<?php if ($ticket_count) { ?>
<div class="tab-pane fade" id="pills-contact-tickets<?php echo $asset_id; ?>">
<div class="tab-pane fade" id="pills-contact-tickets<?php echo $contact_id; ?>">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm">
<thead class="text-dark">
@@ -848,7 +846,13 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold"><span class="text-white">More Details</span></a>
<a href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
<span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span>
</a>
<a href="#" class="btn btn-secondary"
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_contact_edit.php" data-ajax-id="<?php echo $contact_id; ?>">
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span>
</a>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Close</button>
</div>

View File

@@ -311,6 +311,15 @@ ob_start();
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="3">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -21,9 +21,7 @@ $login_created_at = nullable_htmlentities($row['login_created_at']);
$login_archived_at = nullable_htmlentities($row['login_archived_at']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
// Tags
$login_tag_id_array = array();
@@ -189,28 +187,6 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="0">- None -</option>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);
?>
<option <?php if ($login_vendor_id == $vendor_id_select) { echo "selected"; } ?> value="<?php echo $vendor_id_select; ?>"><?php echo $vendor_name_select; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Asset</label>
<div class="input-group">
@@ -240,28 +216,6 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Software</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-box"></i></span>
</div>
<select class="form-control select2" name="software">
<option value="0">- None -</option>
<?php
$sql_software = mysqli_query($mysqli, "SELECT software_id, software_name FROM software WHERE software_client_id = $client_id ORDER BY software_name ASC");
while ($row = mysqli_fetch_array($sql_software)) {
$software_id_select = intval($row['software_id']);
$software_name_select = nullable_htmlentities($row['software_name']);
?>
<option <?php if ($login_software_id == $software_id_select) { echo "selected"; } ?> value="<?php echo $software_id_select; ?>"><?php echo $software_name_select; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-login-notes<?php echo $login_id; ?>">
@@ -288,6 +242,15 @@ ob_start();
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="4">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -0,0 +1,94 @@
<?php
require_once '../includes/ajax_header.php';
$login_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $login_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark text-white">
<div class="d-flex align-items-center">
<i class="fas fa-fw fa-building fa-2x mr-3"></i>
<div>
<h5 class="modal-title mb-0"><?php echo $name; ?></h5>
<div class="text-muted"><?php echo getFallback($description); ?></div>
</div>
</div>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body bg-light">
<!-- Vendor Info Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-info-circle mr-2"></i>Vendor Details</h6>
<div class="row">
<div class="col-sm-6">
<div><strong>Account Number:</strong> <?php echo getFallback($account_number); ?></div>
<div><strong>Hours:</strong> <?php echo getFallback($hours); ?></div>
<div><strong>SLA:</strong> <?php echo getFallback($sla); ?></div>
</div>
<div class="col-sm-6">
<div><strong>Code:</strong> <?php echo getFallback($code); ?></div>
<div><strong>Website:</strong> <?php echo !empty($website) ? '<a href="' . $website . '" target="_blank" class="text-primary">' . $website . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div>
</div>
</div>
</div>
</div>
<!-- Contact Info Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-user mr-2"></i>Contact Information</h6>
<div class="row">
<div class="col-sm-6">
<div><strong>Contact Name:</strong> <?php echo getFallback($contact_name); ?></div>
<div><strong>Phone:</strong> <?php echo getFallback($phone); ?></div>
</div>
<div class="col-sm-6">
<div><strong>Email:</strong> <?php echo !empty($email) ? '<a href="mailto:' . $email . '" class="text-primary">' . $email . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div>
</div>
</div>
</div>
</div>
<!-- Notes Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-sticky-note mr-2"></i>Notes</h6>
<div>
<?php echo getFallback($notes); ?>
</div>
</div>
</div>
</div>
<script src="js/credential_show_otp_via_id.js"></script>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -131,7 +131,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="vendors.php" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Expense">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
@@ -176,7 +181,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Expense" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Expense">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -77,7 +77,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -254,6 +254,15 @@ ob_start();
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="2">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -1,11 +1,13 @@
<?php
require_once '../includes/ajax_header.php';
require_once "../includes/ajax_header.php";
$sql = mysqli_query($mysqli, "SELECT * FROM notifications
$sql = mysqli_query(
$mysqli,
"SELECT * FROM notifications
WHERE notification_user_id = $session_user_id
AND notification_dismissed_at IS NULL
ORDER BY notification_id"
ORDER BY notification_id DESC"
);
$num_notifications = mysqli_num_rows($sql);
@@ -24,19 +26,24 @@ ob_start();
<div class="modal-body bg-white">
<?php if ($num_notifications) { ?>
<?php
<?php while ($row = mysqli_fetch_array($sql)) {
while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row['notification_id']);
$notification_type = nullable_htmlentities($row['notification_type']);
$notification_details = nullable_htmlentities($row['notification']);
$notification_action = nullable_htmlentities($row['notification_action']);
$notification_timestamp_formated = date('M d g:ia',strtotime($row['notification_timestamp']));
$notification_client_id = intval($row['notification_client_id']);
if(empty($notification_action)) { $notification_action = "#"; }
?>
$notification_id = intval($row["notification_id"]);
$notification_type = nullable_htmlentities($row["notification_type"]);
$notification_details = nullable_htmlentities($row["notification"]);
$notification_action = nullable_htmlentities(
$row["notification_action"]
);
$notification_timestamp_formated = date(
"M d g:ia",
strtotime($row["notification_timestamp"])
);
$notification_client_id = intval($row["notification_client_id"]);
if (empty($notification_action)) {
$notification_action = "#";
}
?>
<a class="text-dark dropdown-item px-1" href="<?php echo $notification_action; ?>">
<div>
<span class="text-bold">
@@ -46,14 +53,11 @@ ob_start();
<?php echo $notification_timestamp_formated; ?>
</small>
</div>
<small class="text-secondary"><?php echo $notification_details; ?></small>
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
</a>
<?php
}
} else {
?>
<?php
}} else { ?>
<div class="text-center text-secondary py-5">
<i class='far fa-6x fa-bell-slash'></i>
<h3 class="mt-3">No Notifications</h3>
@@ -62,7 +66,9 @@ ob_start();
</div>
<div class="modal-footer bg-white justify-content-end">
<?php if ($num_notifications) { ?>
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION['csrf_token'] ?>" class="btn btn-primary">
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION[
"csrf_token"
]; ?>" class="btn btn-primary">
<span class="text-white text-bold"><i class="fas fa-check mr-2"></i>Dismiss all</span>
</a>
<?php } else { ?>
@@ -75,5 +81,4 @@ ob_start();
</button>
</div>
<?php
require_once "../includes/ajax_footer.php";
<?php require_once "../includes/ajax_footer.php";

View File

@@ -59,7 +59,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -73,7 +73,12 @@ ob_start();
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -214,7 +214,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Expense" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Expense">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -88,7 +88,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -125,7 +125,12 @@ ob_start();
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -275,7 +275,16 @@ ob_start();
<ul>
<?php
while ($row = mysqli_fetch_array($sql_vendors)) {
echo "<li><a href=\"vendors.php?client_id=$client_id&q=$row[vendor_name]\">$row[vendor_name]</a></li>";
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_vendor_details.php'
data-ajax-id='$vendor_id'>
$vendor_name
</a>
</li>";
}
?>
</ul>
@@ -379,7 +388,15 @@ ob_start();
mysqli_data_seek($sql_docs, 0);
while ($row = mysqli_fetch_array($sql_docs)) {
echo "<li><a href=\"client_document_details.php?client_id=$client_id&document_id=$row[document_id]\">$row[document_name]</a></li>";
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_document_view.php'
data-ajax-id='$document_id'>
$document_name
</a>
</li>";
}
?>
</ul>

View File

@@ -14,10 +14,12 @@ $software_type = nullable_htmlentities($row['software_type']);
$software_license_type = nullable_htmlentities($row['software_license_type']);
$software_key = nullable_htmlentities($row['software_key']);
$software_seats = nullable_htmlentities($row['software_seats']);
$software_purchase_reference = nullable_htmlentities($row['software_purchase_reference']);
$software_purchase = nullable_htmlentities($row['software_purchase']);
$software_expire = nullable_htmlentities($row['software_expire']);
$software_notes = nullable_htmlentities($row['software_notes']);
$software_created_at = nullable_htmlentities($row['software_created_at']);
$software_vendor_id = intval($row['software_vendor_id']);
$client_id = intval($row['software_client_id']);
$seat_count = 0;
@@ -107,6 +109,28 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="">- Select Vendor -</option>
<?php
$vendor_sql = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($vendor_sql)) {
$vendor_id = $row['vendor_id'];
$vendor_name = $row['vendor_name'];
?>
<option <?php if ($software_vendor_id == $vendor_id) { echo "selected"; } ?> value="<?php echo $vendor_id; ?>"><?php echo $vendor_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Type <strong class="text-danger">*</strong></label>
<div class="input-group">
@@ -160,6 +184,16 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Purchase Reference</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
</div>
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" value="<?php echo $software_purchase_reference; ?>">
</div>
</div>
<div class="form-group">
<label>Purchase Date</label>
<div class="input-group">

49
ajax/ajax_tag_add.php Normal file
View File

@@ -0,0 +1,49 @@
<?php
require_once '../includes/ajax_header.php';
$type = intval($_GET['id']);
?>
<!-- <option value="1">Client Tag</option> -->
<!-- <option value="2">Location Tag</option> -->
<!-- <option value="3">Contact Tag</option> -->
<!-- <option value="4">Credential Tag</option> -->
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i>New Tag</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="type" value="<?php echo $type; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="name" placeholder="Tag name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="icon" placeholder="Icon ex handshake">
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -107,6 +107,14 @@ ob_start();
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Ticket">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,89 @@
<?php
require_once '../includes/ajax_header.php';
$vendor_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_id = $vendor_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$name = sanitizeInput($row['vendor_name']);
$description = sanitizeInput($row['vendor_description']);
$account_number = sanitizeInput($row['vendor_account_number']);
$contact_name = sanitizeInput($row['vendor_contact_name']);
$phone = preg_replace("/[^0-9]/", '',$row['vendor_phone']);
$extension = preg_replace("/[^0-9]/", '',$row['vendor_extension']);
$email = sanitizeInput($row['vendor_email']);
$website = sanitizeInput($row['vendor_website']);
$hours = sanitizeInput($row['vendor_hours']);
$sla = sanitizeInput($row['vendor_sla']);
$code = sanitizeInput($row['vendor_code']);
$notes = sanitizeInput($row['vendor_notes']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark text-white">
<div class="d-flex align-items-center">
<i class="fas fa-fw fa-building fa-2x mr-3"></i>
<div>
<h5 class="modal-title mb-0"><?php echo $name; ?></h5>
<div class="text-muted"><?php echo getFallback($description); ?></div>
</div>
</div>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body bg-light">
<!-- Vendor Info Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-info-circle mr-2"></i>Vendor Details</h6>
<div class="row">
<div class="col-sm-6">
<div><strong>Account Number:</strong> <?php echo getFallback($account_number); ?></div>
<div><strong>Hours:</strong> <?php echo getFallback($hours); ?></div>
<div><strong>SLA:</strong> <?php echo getFallback($sla); ?></div>
</div>
<div class="col-sm-6">
<div><strong>Code:</strong> <?php echo getFallback($code); ?></div>
<div><strong>Website:</strong> <?php echo !empty($website) ? '<a href="' . $website . '" target="_blank" class="text-primary">' . $website . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div>
</div>
</div>
</div>
</div>
<!-- Contact Info Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-user mr-2"></i>Contact Information</h6>
<div class="row">
<div class="col-sm-6">
<div><strong>Contact Name:</strong> <?php echo getFallback($contact_name); ?></div>
<div><strong>Phone:</strong> <?php echo getFallback($phone); ?></div>
</div>
<div class="col-sm-6">
<div><strong>Email:</strong> <?php echo !empty($email) ? '<a href="mailto:' . $email . '" class="text-primary">' . $email . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div>
</div>
</div>
</div>
</div>
<!-- Notes Card -->
<div class="card mb-3 shadow-sm rounded">
<div class="card-body">
<h6 class="text-secondary"><i class="fas fa-sticky-note mr-2"></i>Notes</h6>
<div>
<?php echo getFallback($notes); ?>
</div>
</div>
</div>
</div>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -192,9 +192,7 @@ if (isset($_GET['asset_id'])) {
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_vendor_id,
logins.login_asset_id,
logins.login_software_id
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
@@ -217,6 +215,16 @@ if (isset($_GET['asset_id'])) {
$software_count = mysqli_num_rows($sql_related_software);
// Linked Services
$sql_linked_services = mysqli_query($mysqli, "SELECT * FROM service_assets, services
WHERE service_assets.asset_id = $asset_id
AND service_assets.service_id = services.service_id
ORDER BY service_name ASC"
);
$service_count = mysqli_num_rows($sql_linked_services);
$linked_services = array();
?>
<div class="row">
@@ -357,28 +365,24 @@ if (isset($_GET['asset_id'])) {
<div class="dropdown dropleft">
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
<div class="dropdown-menu">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkAssetModal">
<i class="fa fa-fw fa-desktop mr-2"></i>Asset (WIP)
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
<i class="fa fa-fw fa-cube mr-2"></i>License (WIP)
<i class="fa fa-fw fa-cube mr-2"></i>License
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
<i class="fa fa-fw fa-key mr-2"></i>Credential (WIP)
<i class="fa fa-fw fa-key mr-2"></i>Credential
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
<i class="fa fa-fw fa-stream mr-2"></i>Service (WIP)
<i class="fa fa-fw fa-stream mr-2"></i>Service
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
<i class="fa fa-fw fa-folder mr-2"></i>Document (WIP)
<i class="fa fa-fw fa-folder mr-2"></i>Document
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
<i class="fa fa-fw fa-paperclip mr-2"></i>File (WIP)
<i class="fa fa-fw fa-paperclip mr-2"></i>File
</a>
@@ -460,6 +464,7 @@ if (isset($_GET['asset_id'])) {
// Show either "-" or "AssetName - Port"
if ($connected_asset_name) {
$connected_to_display = "<a href='#'
data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_asset_details.php'
data-ajax-id='$connected_asset_id'>
@@ -561,9 +566,7 @@ if (isset($_GET['asset_id'])) {
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
// Tags
$login_tag_name_display_array = array();
@@ -622,6 +625,10 @@ if (isset($_GET['asset_id'])) {
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Login', $login_id"; ?>)">
<i class="fas fa-fw fa-share-alt mr-2"></i>Share
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?unlink_credential_from_asset&asset_id=<?php echo $asset_id; ?>&login_id=<?php echo $login_id; ?>">
<i class="fas fa-fw fa-unlink mr-2"></i>Unlink
</a>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" href="post.php?delete_login=<?php echo $login_id; ?>">
@@ -659,6 +666,7 @@ if (isset($_GET['asset_id'])) {
<th>Type</th>
<th>License Type</th>
<th>Seats</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
@@ -701,6 +709,8 @@ if (isset($_GET['asset_id'])) {
}
$contact_licenses = implode(',', $contact_licenses_array);
$linked_software[] = $software_id;
?>
<tr>
<td>
@@ -715,6 +725,9 @@ if (isset($_GET['asset_id'])) {
<td><?php echo $software_type; ?></td>
<td><?php echo $software_license_type; ?></td>
<td><?php echo "$seat_count / $software_seats"; ?></td>
<td class="text-center">
<a href="post.php?unlink_software_from_asset&asset_id=<?php echo $asset_id; ?>&software_id=<?php echo $software_id; ?>" class="btn btn-secondary btn-sm" title="Unlink"><i class="fas fa-fw fa-unlink"></i></a>
</td>
</tr>
<?php
@@ -825,7 +838,7 @@ if (isset($_GET['asset_id'])) {
<tr>
<th>Name</th>
<th>Uploaded</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
@@ -861,10 +874,16 @@ if (isset($_GET['asset_id'])) {
$file_icon = "file";
}
$file_created_at = nullable_htmlentities($row['file_created_at']);
$linked_files[] = $file_id;
?>
<tr>
<td><a class="text-dark" href="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" target="_blank" ><?php echo "$file_name<br><span class='text-secondary'>$file_description</span>"; ?></a></td>
<td><?php echo $file_created_at; ?></td>
<td class="text-center">
<a href="post.php?unlink_asset_from_file&asset_id=<?php echo $asset_id; ?>&file_id=<?php echo $file_id; ?>" class="btn btn-secondary btn-sm" title="Unlink"><i class="fas fa-fw fa-unlink"></i></a>
</td>
</tr>
<?php
@@ -1047,6 +1066,64 @@ if (isset($_GET['asset_id'])) {
</div>
</div>
<div class="card card-dark <?php if ($service_count == 0) { echo "d-none"; } ?>">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-stream mr-2"></i>Linked Services</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#linkServiceModal">
<i class="fas fa-link mr-2"></i>Link Service
</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover dataTables" style="width:100%">
<thead class="text-dark">
<tr>
<th>Service</th>
<th>Category</th>
<th>Importance</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_linked_services)) {
$service_id = intval($row['service_id']);
$service_name = nullable_htmlentities($row['service_name']);
$service_description = nullable_htmlentities($row['service_description']);
$service_category = nullable_htmlentities($row['service_category']);
$service_importance = nullable_htmlentities($row['service_importance']);
$linked_services[] = $service_id;
?>
<tr>
<td>
<div><?php echo $service_name; ?></div>
<div class="text-secondary"><?php echo $service_description; ?></div>
</td>
<td><?php echo $service_category; ?></td>
<td><?php echo $service_importance; ?></td>
<td class="text-center">
<a href="post.php?unlink_service_from_asset&asset_id=<?php echo $asset_id; ?>&service_id=<?php echo $service_id; ?>" class="btn btn-secondary btn-sm" title="Unlink"><i class="fas fa-fw fa-unlink"></i></a>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@@ -1101,4 +1178,11 @@ require_once "modals/asset_interface_import_modal.php";
require_once "modals/asset_interface_export_modal.php";
require_once "modals/ticket_add_modal.php";
require_once "modals/recurring_ticket_add_modal.php";
require_once "modals/asset_link_software_modal.php";
require_once "modals/asset_link_credential_modal.php";
require_once "modals/asset_link_service_modal.php";
require_once "modals/asset_link_document_modal.php";
require_once "modals/asset_link_file_modal.php";
require_once "includes/footer.php";

View File

@@ -340,7 +340,12 @@ $page_title = $row['document_name'];
?>
<div class="ml-2">
<a href="vendors.php?client_id=<?php echo $client_id; ?>&q=<?php echo $vendor_name; ?>" target="_blank"><?php echo $vendor_name; ?></a>
<a href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_vendor_details.php"
data-ajax-id="<?php echo $vendor_id; ?>">
<?php echo $vendor_name; ?>
</a>
<a class="confirm-link float-right" href="post.php?unlink_vendor_from_document&vendor_id=<?php echo $vendor_id; ?>&document_id=<?php echo $document_id; ?>">
<i class="fas fa-fw fa-trash-alt text-secondary"></i>
</a>

View File

@@ -345,7 +345,7 @@ while ($folder_id > 0) {
<div class="col-xl-2 col-lg-2 col-md-6 col-sm-6 mb-3 text-center">
<a href="#" onclick="openModal(<?php echo count($files)-1; ?>)"><!-- passing the index -->
<img class="img-thumbnail" src="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" alt="<?php echo $file_reference_name ?>">
<img class="img-thumbnail" src="<?php echo "uploads/clients/$client_id/$file_thumbnail_source"; ?>" alt="<?php echo $file_reference_name ?>">
</a>
<div>
@@ -356,8 +356,18 @@ while ($folder_id > 0) {
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" download="<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Original
</a>
<?php if ($file_has_preview) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/preview_$file_reference_name"; ?>" download="preview_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Optimized
</a>
<?php } ?>
<?php if ($file_has_thumbnail) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/thumbnail_$file_reference_name"; ?>" download="thumbnail_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Thumbnail
</a>
<?php } ?>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'File', $file_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
</a>
@@ -563,8 +573,18 @@ while ($folder_id > 0) {
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" download="<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Original
</a>
<?php if ($file_has_preview) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/preview_$file_reference_name"; ?>" download="preview_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Optimized
</a>
<?php } ?>
<?php if ($file_has_thumbnail) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/thumbnail_$file_reference_name"; ?>" download="thumbnail_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Thumbnail
</a>
<?php } ?>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'File', $file_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
</a>

View File

@@ -2,8 +2,6 @@
require_once "includes/inc_all_client.php";
// Get expiration days from select box
$expiration_days = isset($_GET['expiration_days']) ? intval($_GET['expiration_days']) : 90;
$sql_recent_activities = mysqli_query(
$mysqli,
@@ -61,13 +59,14 @@ $sql_stale_tickets = mysqli_query(
$mysqli,
"SELECT * FROM tickets
WHERE ticket_client_id = $client_id
AND ticket_updated_at < CURRENT_DATE - INTERVAL 3 DAY
AND ticket_updated_at < CURRENT_DATE - INTERVAL 7 DAY
AND ticket_resolved_At IS NULL
AND ticket_closed_at IS NULL
ORDER BY ticket_updated_at ASC
LIMIT 5"
ORDER BY ticket_updated_at ASC"
);
// 8 - 45 Day Warning
// Get Domains Expiring
$sql_domains_expiring = mysqli_query(
$mysqli,
@@ -76,9 +75,8 @@ $sql_domains_expiring = mysqli_query(
AND domain_expire IS NOT NULL
AND domain_archived_at IS NULL
AND domain_expire > CURRENT_DATE
AND domain_expire < CURRENT_DATE + INTERVAL $expiration_days DAY
ORDER BY domain_expire ASC
LIMIT 5"
AND domain_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY domain_expire ASC"
);
// Get Certificates Expiring
@@ -89,9 +87,8 @@ $sql_certificates_expiring = mysqli_query(
AND certificate_expire IS NOT NULL
AND certificate_archived_at IS NULL
AND certificate_expire > CURRENT_DATE
AND certificate_expire < CURRENT_DATE + INTERVAL $expiration_days DAY
ORDER BY certificate_expire ASC
LIMIT 5"
AND certificate_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY certificate_expire ASC"
);
// Get Licenses Expiring
@@ -102,9 +99,8 @@ $sql_licenses_expiring = mysqli_query(
AND software_expire IS NOT NULL
AND software_archived_at IS NULL
AND software_expire > CURRENT_DATE
AND software_expire < CURRENT_DATE + INTERVAL $expiration_days DAY
ORDER BY software_expire ASC
LIMIT 5"
AND software_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY software_expire ASC"
);
// Get Asset Warranties Expiring
@@ -115,9 +111,8 @@ $sql_asset_warranties_expiring = mysqli_query(
AND asset_warranty_expire IS NOT NULL
AND asset_archived_at IS NULL
AND asset_warranty_expire > CURRENT_DATE
AND asset_warranty_expire < CURRENT_DATE + INTERVAL $expiration_days DAY
ORDER BY asset_warranty_expire ASC
LIMIT 5"
AND asset_warranty_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY asset_warranty_expire ASC"
);
// Get Assets Retiring 7 Year
@@ -127,10 +122,9 @@ $sql_asset_retire = mysqli_query(
WHERE asset_client_id = $client_id
AND asset_install_date IS NOT NULL
AND asset_archived_at IS NULL
AND asset_install_date + INTERVAL 7 YEAR > CURRENT_DATE -- Not yet expired
AND asset_install_date + INTERVAL 7 YEAR <= CURRENT_DATE + INTERVAL $expiration_days DAY
ORDER BY asset_install_date ASC
LIMIT 5"
AND asset_install_date + INTERVAL 7 YEAR > CURRENT_DATE
AND asset_install_date + INTERVAL 7 YEAR <= CURRENT_DATE + INTERVAL 45 DAY
ORDER BY asset_install_date ASC"
);
/*
@@ -145,8 +139,7 @@ $sql_domains_expired = mysqli_query(
AND domain_expire IS NOT NULL
AND domain_archived_at IS NULL
AND domain_expire < CURRENT_DATE
ORDER BY domain_expire ASC
LIMIT 5"
ORDER BY domain_expire ASC"
);
// Get Certificates Expired
@@ -157,8 +150,7 @@ $sql_certificates_expired = mysqli_query(
AND certificate_expire IS NOT NULL
AND certificate_archived_at IS NULL
AND certificate_expire < CURRENT_DATE
ORDER BY certificate_expire ASC
LIMIT 5"
ORDER BY certificate_expire ASC"
);
// Get Licenses Expired
@@ -169,8 +161,7 @@ $sql_licenses_expired = mysqli_query(
AND software_expire IS NOT NULL
AND software_archived_at IS NULL
AND software_expire < CURRENT_DATE
ORDER BY software_expire ASC
LIMIT 5"
ORDER BY software_expire ASC"
);
// Get Asset Warranties Expired
@@ -181,8 +172,7 @@ $sql_asset_warranties_expired = mysqli_query(
AND asset_warranty_expire IS NOT NULL
AND asset_archived_at IS NULL
AND asset_warranty_expire < CURRENT_DATE
ORDER BY asset_warranty_expire ASC
LIMIT 5"
ORDER BY asset_warranty_expire ASC"
);
// Get Retired Assets
@@ -193,8 +183,7 @@ $sql_asset_retired = mysqli_query(
AND asset_install_date IS NOT NULL
AND asset_archived_at IS NULL
AND asset_install_date + INTERVAL 7 YEAR < CURRENT_DATE -- Assets retired (installed more than 7 years ago)
ORDER BY asset_install_date ASC
LIMIT 5"
ORDER BY asset_install_date ASC"
);
@@ -353,17 +342,7 @@ $sql_asset_retired = mysqli_query(
<div class="card card-dark mb-3">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-fw fa-exclamation-triangle text-warning mr-2"></i>Upcoming Expirations</h5>
<div class="card-tools">
<form class="form-inline">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<select onchange="this.form.submit()" class="form-control form-control-sm" name="expiration_days">
<option value="7" <?php if ($expiration_days == 7) { echo "selected"; } ?>>Within 7 Days</option>
<option value="30" <?php if ($expiration_days == 30) { echo "selected"; } ?>>Within 30 Days</option>
<option value="90" <?php if ($expiration_days == 90) { echo "selected"; } ?>>Within 90 Days</option>
</select>
</form>
</div>
<h5 class="card-title"><i class="fa fa-fw fa-exclamation-triangle text-warning mr-2"></i>Expiring in the Next 45 Days</h5>
</div>
<div class="card-body p-2">
@@ -378,8 +357,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-globe text-secondary mr-1"></i>
<a href="client_domains.php?client_id=<?php echo $client_id; ?>&q=<?php echo $domain_name; ?>"><?php echo $domain_name; ?></a>
<span>-- <?php echo $domain_expire_human; ?> <small class="text-muted"><?php echo $domain_expire; ?></small></span>
<a href="domains.php?client_id=<?php echo $client_id; ?>&q=<?php echo $domain_name; ?>">Domain: <?php echo $domain_name; ?></a>
<span>-- <?php echo $domain_expire; ?> (<?php echo $domain_expire_human; ?>)</span>
</p>
<?php
}
@@ -396,8 +375,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-lock text-secondary mr-1"></i>
<a href="client_certificates.php?client_id=<?php echo $client_id; ?>&q=<?php echo $certificate_name; ?>"><?php echo $certificate_name; ?></a>
<span>-- <?php echo $certificate_expire_human; ?> <small class="text-muted"><?php echo $certificate_expire; ?></small></span>
<a href="certificates.php?client_id=<?php echo $client_id; ?>&q=<?php echo $certificate_name; ?>">Certificate: <?php echo $certificate_name; ?></a>
<span>-- <?php echo $certificate_expire; ?> (<?php echo $certificate_expire_human; ?>)</span>
</p>
<?php
}
@@ -414,8 +393,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-laptop text-secondary mr-1"></i>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_warranty_expire_human; ?> <small class="text-muted"><?php echo $asset_warranty_expire; ?></small></span>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">Asset Warranty: <?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_warranty_expire; ?> (<?php echo $asset_warranty_expire_human; ?>)</span>
</p>
@@ -434,8 +413,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-laptop text-secondary mr-1"></i>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_install_date_human; ?> <small class="text-muted"><?php echo $asset_install_date; ?></small></span>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">Asset Retire: <?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_install_date; ?> (<?php echo $asset_install_date_human; ?>)</span>
</p>
<?php
@@ -453,8 +432,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-cube text-secondary mr-1"></i>
<a href="client_software.php?client_id=<?php echo $client_id; ?>&q=<?php echo $software_name; ?>"><?php echo $software_name; ?></a>
<span>-- <?php echo $software_expire_human; ?> <small class="text-muted"><?php echo $software_expire; ?></small></span>
<a href="software.php?client_id=<?php echo $client_id; ?>&q=<?php echo $software_name; ?>">License: <?php echo $software_name; ?></a>
<span>-- <?php echo $software_expire; ?> (<?php echo $software_expire_human; ?>)</span>
</p>
<?php
@@ -496,8 +475,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-globe text-secondary mr-1"></i>
<a href="client_domains.php?client_id=<?php echo $client_id; ?>&q=<?php echo $domain_name; ?>"><?php echo $domain_name; ?></a>
<span>-- <?php echo $domain_expire_human; ?> <small class="text-muted"><?php echo $domain_expire; ?></small></span>
<a href="domains.php?client_id=<?php echo $client_id; ?>&q=<?php echo $domain_name; ?>">Domain: <?php echo $domain_name; ?></a>
<span>-- <?php echo $domain_expire; ?> (<?php echo $domain_expire_human; ?>)</span>
</p>
<?php
}
@@ -514,8 +493,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-lock text-secondary mr-1"></i>
<a href="client_certificates.php?client_id=<?php echo $client_id; ?>&q=<?php echo $certificate_name; ?>"><?php echo $certificate_name; ?></a>
<span>-- <?php echo $certificate_expire_human; ?> <small class="text-muted"><?php echo $certificate_expire; ?></small></span>
<a href="certificates.php?client_id=<?php echo $client_id; ?>&q=<?php echo $certificate_name; ?>">Certificate: <?php echo $certificate_name; ?></a>
<span>-- <?php echo $certificate_expire; ?> (<?php echo $certificate_expire_human; ?>)</span>
</p>
<?php
}
@@ -531,9 +510,9 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-laptop text-secondary mr-1"></i>
<i class="fa fa-fw fa-laptop text-secondary mr-1"></i>Asset Warranty:
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_warranty_expire_human; ?> <small class="text-muted"><?php echo $asset_warranty_expire; ?></small></span>
<span>-- <?php echo $asset_warranty_expire; ?> (<?php echo $asset_warranty_expire_human; ?>)</span>
</p>
@@ -552,8 +531,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-laptop text-secondary mr-1"></i>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_install_date_human; ?> <small class="text-muted"><?php echo $asset_install_date; ?></small></span>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">Asset Retire: <?php echo $asset_name; ?></a>
<span>-- <?php echo $asset_install_date; ?> (<?php echo $asset_install_date_human; ?>)</span>
</p>
<?php
@@ -571,8 +550,8 @@ $sql_asset_retired = mysqli_query(
?>
<p class="mb-1">
<i class="fa fa-fw fa-cube text-secondary mr-1"></i>
<a href="client_software.php?client_id=<?php echo $client_id; ?>&q=<?php echo $software_name; ?>"><?php echo $software_name; ?></a>
<span>-- <?php echo $software_expire_human; ?> <small class="text-muted"><?php echo $software_expire; ?></small></span>
<a href="software.php?client_id=<?php echo $client_id; ?>&q=<?php echo $software_name; ?>">Software: <?php echo $software_name; ?></a>
<span>-- <?php echo $software_expire; ?> (<?php echo $software_expire_human; ?>)</span>
</p>
<?php

View File

@@ -261,7 +261,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$icon = $d['icon']; // already from getAssetIcon
?>
<i class="fa fa-<?php echo $icon; ?>"></i>
<a href="client_asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $d['asset_id']; ?>"
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $d['asset_id']; ?>"
target="_blank">
<?php echo $d['asset_name']; ?>
<i class="fas fa-external-link-alt ml-1"></i>

View File

@@ -185,8 +185,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Tag</label>
<label>Tag</label>
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php
$sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 1");
@@ -198,6 +199,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="1">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<div class="col-sm-2">
@@ -398,7 +408,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if (!empty($contact_name)) { ?>
<div class="text-bold">
<i class="fa fa-fw fa-user text-secondary mr-2 mb-2"></i><a href="client_contact_details.php?client_id=<?php echo $client_id ?>&contact_id=<?php echo $contact_id ?>"><?php echo $contact_name; ?></a>
<i class="fa fa-fw fa-user text-secondary mr-2 mb-2"></i>
<a href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_contact_details.php?client_id=<?php echo $client_id; ?>"
data-ajax-id="<?php echo $contact_id; ?>">
<?php echo $contact_name; ?>
</a>
</div>
<?php } else {
echo "-";

View File

@@ -495,9 +495,7 @@ if (isset($_GET['contact_id'])) {
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
// Tags
$login_tag_name_display_array = array();

View File

@@ -53,9 +53,6 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
$location_filter = '';
}
//Rebuild URL
//$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS contacts.*, clients.*, locations.*, users.*, GROUP_CONCAT(tags.tag_name) FROM contacts
LEFT JOIN clients ON client_id = contact_client_id
LEFT JOIN locations ON location_id = contact_location_id
@@ -76,433 +73,470 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-address-book mr-2"></i>Contacts</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addContactModal">
<i class="fas fa-plus mr-2"></i>New Contact
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#contactInviteModal"><i class="fas fa-fw fa-paper-plane mr-2"></i>Invite</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#importContactModal">
<i class="fa fa-fw fa-upload mr-2"></i>Import
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportContactModal">
<i class="fa fa-fw fa-download mr-2"></i>Export
</a>
</div>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-address-book mr-2"></i>Contacts</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addContactModal">
<i class="fas fa-plus mr-2"></i>New Contact
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#contactInviteModal"><i class="fas fa-fw fa-paper-plane mr-2"></i>Invite</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#importContactModal">
<i class="fa fa-fw fa-upload mr-2"></i>Import
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportContactModal">
<i class="fa fa-fw fa-download mr-2"></i>Export
</a>
</div>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?>
<input type="hidden" name="archived" value="<?php echo $archived; ?>">
<div class="row">
</div>
<div class="card-body">
<form autocomplete="off">
<?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?>
<input type="hidden" name="archived" value="<?php echo $archived; ?>">
<div class="row">
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Contacts">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Contacts">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 3");
while ($row = mysqli_fetch_array($sql_tags)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && is_array($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<?php } ?>
</select>
</div>
</div>
<?php if ($client_url) { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="location" onchange="this.form.submit()">
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
while ($row = mysqli_fetch_array($sql_locations_filter)) {
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
?>
<option <?php if ($location_filter == $location_id) { echo "selected"; } ?> value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-3">
<div class="btn-group float-right">
<a href="?<?php echo $client_url; ?>archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
<i class="fa fa-fw fa-archive mr-2"></i>Archived
</a>
<div class="dropdown ml-2" id="bulkActionButton" hidden>
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignLocationModal">
<i class="fas fa-fw fa-map-marker-alt mr-2"></i>Assign Location
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditPhoneModal">
<i class="fas fa-fw fa-phone-alt mr-2"></i>Set Phone Number
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditDepartmentModal">
<i class="fas fa-fw fa-users mr-2"></i>Set Department
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditRoleModal">
<i class="fas fa-fw fa-user-shield mr-2"></i>Set Roles
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignTagsModal">
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkSendEmailModal">
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
</a>
<?php if ($archived) { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-info"
type="submit" form="bulkActions" name="bulk_unarchive_contacts">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_contacts">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
<?php } else { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger confirm-link"
type="submit" form="bulkActions" name="bulk_archive_contacts">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</button>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
</form>
<hr>
<form id="bulkActions" action="post.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="table-responsive-sm">
<table class="table border">
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
<tr>
<td class="bg-light pr-0">
<div class="form-check">
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
</div>
</td>
<th>
<a class="text-secondary ml-3" href="?<?php echo $url_query_strings_sort; ?>&sort=contact_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'contact_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=contact_department&order=<?php echo $disp; ?>">
Department <?php if ($sort == 'contact_department') { echo $order_icon; } ?>
</a>
</th>
<th>Contact</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=location_name&order=<?php echo $disp; ?>">
Location <?php if ($sort == 'location_name') { echo $order_icon; } ?>
</a>
</th>
<?php if (!$client_url) { ?>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a>
</th>
<div class="col-md-3">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 3");
while ($row = mysqli_fetch_array($sql_tags)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && is_array($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<?php } ?>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="2">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
if (empty($contact_title)) {
$contact_title_display = "";
} else {
$contact_title_display = "<small class='text-secondary'>$contact_title</small>";
}
$contact_department = nullable_htmlentities($row['contact_department']);
if (empty($contact_department)) {
$contact_department_display = "-";
} else {
$contact_department_display = $contact_department;
}
$contact_extension = nullable_htmlentities($row['contact_extension']);
if (empty($contact_extension)) {
$contact_extension_display = "";
} else {
$contact_extension_display = "<small class='text-secondary ml-1'>x$contact_extension</small>";
}
$contact_phone = formatPhoneNumber($row['contact_phone']);
if (empty($contact_phone)) {
$contact_phone_display = "";
} else {
$contact_phone_display = "<div><i class='fas fa-fw fa-phone mr-2'></i><a href='tel:$contact_phone'>$contact_phone$contact_extension_display</a></div>";
}
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
if (empty($contact_mobile)) {
$contact_mobile_display = "";
} else {
$contact_mobile_display = "<div class='mt-2'><i class='fas fa-fw fa-mobile-alt mr-2'></i><a href='tel:$contact_mobile'>$contact_mobile</a></div>";
}
$contact_email = nullable_htmlentities($row['contact_email']);
if (empty($contact_email)) {
$contact_email_display = "";
} else {
$contact_email_display = "<div class='mt-1'><i class='fas fa-fw fa-envelope mr-2'></i><a href='mailto:$contact_email'>$contact_email</a><button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$contact_email'><i class='far fa-copy text-secondary'></i></button></div>";
}
$contact_info_display = "$contact_phone_display $contact_mobile_display $contact_email_display";
if (empty($contact_info_display)) {
$contact_info_display = "-";
}
$contact_pin = nullable_htmlentities($row['contact_pin']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
$contact_initials = initials($contact_name);
$contact_notes = nullable_htmlentities($row['contact_notes']);
$contact_primary = intval($row['contact_primary']);
$contact_important = intval($row['contact_important']);
$contact_billing = intval($row['contact_billing']);
$contact_technical = intval($row['contact_technical']);
$contact_created_at = nullable_htmlentities($row['contact_created_at']);
$contact_archived_at = nullable_htmlentities($row['contact_archived_at']);
if ($contact_primary == 1) {
$contact_primary_display = "<small class='text-success'>Primary Contact</small>";
} else {
$contact_primary_display = false;
}
$contact_location_id = intval($row['contact_location_id']);
$location_name = nullable_htmlentities($row['location_name']);
if (empty($location_name)) {
$location_name = "-";
}
$location_archived_at = nullable_htmlentities($row['location_archived_at']);
if ($location_archived_at) {
$location_name_display = "<div class='text-danger' title='Archived'><s>$location_name</s></div>";
} else {
$location_name_display = $location_name;
}
$auth_method = nullable_htmlentities($row['user_auth_method']);
$contact_user_id = intval($row['contact_user_id']);
// Related Assets Query
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_contact_id = $contact_id ORDER BY asset_id DESC");
$asset_count = mysqli_num_rows($sql_related_assets);
// Related Logins Query
$sql_related_logins = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_contact_id = $contact_id ORDER BY login_id DESC");
$login_count = mysqli_num_rows($sql_related_logins);
// Related Software Query
$sql_related_software = mysqli_query($mysqli, "SELECT * FROM software, software_contacts WHERE software.software_id = software_contacts.software_id AND software_contacts.contact_id = $contact_id ORDER BY software.software_id DESC");
$software_count = mysqli_num_rows($sql_related_software);
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_contact_id = $contact_id ORDER BY ticket_id DESC");
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Tags
$contact_tag_name_display_array = array();
$contact_tag_id_array = array();
$sql_contact_tags = mysqli_query($mysqli, "SELECT * FROM contact_tags LEFT JOIN tags ON contact_tags.tag_id = tags.tag_id WHERE contact_id = $contact_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_contact_tags)) {
$contact_tag_id = intval($row['tag_id']);
$contact_tag_name = nullable_htmlentities($row['tag_name']);
$contact_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($contact_tag_color)) {
$contact_tag_color = "dark";
}
$contact_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($contact_tag_icon)) {
$contact_tag_icon = "tag";
}
$contact_tag_id_array[] = $contact_tag_id;
$contact_tag_name_display_array[] = "<a href='contacts.php?$client_url tags[]=$contact_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $contact_tag_color;'><i class='fa fa-fw fa-$contact_tag_icon mr-2'></i>$contact_tag_name</span></a>";
}
$contact_tags_display = implode('', $contact_tag_name_display_array);
?>
<tr>
<td class="pr-0 bg-light">
<div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="contact_ids[]" value="<?php echo $contact_id ?>">
</div>
</td>
<td>
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_contact_details.php?<?php echo $client_url; ?>"
data-ajax-id="<?php echo $contact_id; ?>">
<div class="media">
<?php if ($contact_photo) { ?>
<span class="fa-stack fa-2x mr-3 text-center">
<img class="img-size-50 img-circle" src="<?php echo "uploads/clients/$client_id/$contact_photo"; ?>">
</span>
<?php } else { ?>
<span class="fa-stack fa-2x mr-3">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?php echo $contact_initials; ?></span>
</span>
<?php } ?>
<div class="media-body">
<div class="<?php if($contact_important) { echo "text-bold"; } ?>"><?php echo $contact_name; ?></div>
<?php echo $contact_title_display; ?>
<div><?php echo $contact_primary_display; ?></div>
<?php
if (!empty($contact_tags_display)) { ?>
<div class="mt-1">
<?php echo $contact_tags_display; ?>
</div>
<?php } ?>
</div>
</div>
</a>
</td>
<td><?php echo $contact_department_display; ?></td>
<td><?php echo $contact_info_display; ?></td>
<td><?php echo $location_name_display; ?></td>
<?php if (!$client_url) { ?>
<td><a href="contacts.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<?php } ?>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-eye mr-2"></i>Details
</a>
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_contact_note_create.php"
data-ajax-id="<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-sticky-note mr-2"></i>Make Note
</a>
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_contact_edit.php"
data-ajax-id="<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<?php if ($session_user_role == 3 && $contact_primary == 0) { ?>
<?php if ($contact_archived_at) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-info confirm-link" href="post.php?unarchive_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</a>
<?php } else { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?anonymize_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-user-secret mr-2"></i>Anonymize & Archive
</a>
<?php } ?>
<?php if ($config_destructive_deletes_enable) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
<?php } ?>
</div>
</div>
</td>
</tr>
<?php if ($client_url) { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="location" onchange="this.form.submit()">
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
while ($row = mysqli_fetch_array($sql_locations_filter)) {
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
?>
<option <?php if ($location_filter == $location_id) { echo "selected"; } ?> value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-3">
<div class="btn-group float-right">
<a href="?<?php echo $client_url; ?>archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
<i class="fa fa-fw fa-archive mr-2"></i>Archived
</a>
<div class="dropdown ml-2" id="bulkActionButton" hidden>
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignLocationModal">
<i class="fas fa-fw fa-map-marker-alt mr-2"></i>Assign Location
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditPhoneModal">
<i class="fas fa-fw fa-phone-alt mr-2"></i>Set Phone Number
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditDepartmentModal">
<i class="fas fa-fw fa-users mr-2"></i>Set Department
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditRoleModal">
<i class="fas fa-fw fa-user-shield mr-2"></i>Set Roles
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignTagsModal">
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkSendEmailModal">
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
</a>
<?php if ($archived) { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-info"
type="submit" form="bulkActions" name="bulk_unarchive_contacts">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_contacts">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
<?php } else { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger confirm-link"
type="submit" form="bulkActions" name="bulk_archive_contacts">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</button>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
</form>
<hr>
<form id="bulkActions" action="post.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="table-responsive-sm">
<table class="table border">
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
<tr>
<td class="bg-light pr-0">
<div class="form-check">
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
</div>
</td>
<th>
<a class="text-secondary ml-3" href="?<?php echo $url_query_strings_sort; ?>&sort=contact_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'contact_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=contact_department&order=<?php echo $disp; ?>">
Department <?php if ($sort == 'contact_department') { echo $order_icon; } ?>
</a>
</th>
<th>Contact</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=location_name&order=<?php echo $disp; ?>">
Location <?php if ($sort == 'location_name') { echo $order_icon; } ?>
</a>
</th>
<th></th>
<?php if (!$client_url) { ?>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a>
</th>
<?php } ?>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
if (empty($contact_title)) {
$contact_title_display = "";
} else {
$contact_title_display = "<small class='text-secondary'>$contact_title</small>";
}
$contact_department = getFallBack(nullable_htmlentities($row['contact_department']));
$contact_extension = nullable_htmlentities($row['contact_extension']);
if (empty($contact_extension)) {
$contact_extension_display = "";
} else {
$contact_extension_display = "<small class='text-secondary ml-1'>x$contact_extension</small>";
}
$contact_phone = formatPhoneNumber($row['contact_phone']);
if (empty($contact_phone)) {
$contact_phone_display = "";
} else {
$contact_phone_display = "<div><i class='fas fa-fw fa-phone mr-2'></i><a href='tel:$contact_phone'>$contact_phone$contact_extension_display</a></div>";
}
?>
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
if (empty($contact_mobile)) {
$contact_mobile_display = "";
} else {
$contact_mobile_display = "<div class='mt-2'><i class='fas fa-fw fa-mobile-alt mr-2'></i><a href='tel:$contact_mobile'>$contact_mobile</a></div>";
}
$contact_email = nullable_htmlentities($row['contact_email']);
if (empty($contact_email)) {
$contact_email_display = "";
} else {
$contact_email_display = "<div class='mt-1'><i class='fas fa-fw fa-envelope mr-2'></i><a href='mailto:$contact_email'>$contact_email</a><button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$contact_email'><i class='far fa-copy text-secondary'></i></button></div>";
}
$contact_info_display = "$contact_phone_display $contact_mobile_display $contact_email_display";
if (empty($contact_info_display)) {
$contact_info_display = "-";
}
$contact_pin = nullable_htmlentities($row['contact_pin']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
$contact_initials = initials($contact_name);
$contact_notes = nullable_htmlentities($row['contact_notes']);
$contact_primary = intval($row['contact_primary']);
$contact_important = intval($row['contact_important']);
$contact_billing = intval($row['contact_billing']);
$contact_technical = intval($row['contact_technical']);
$contact_created_at = nullable_htmlentities($row['contact_created_at']);
$contact_archived_at = nullable_htmlentities($row['contact_archived_at']);
if ($contact_primary == 1) {
$contact_primary_display = "<small class='text-success'>Primary Contact</small>";
} else {
$contact_primary_display = false;
}
$contact_location_id = intval($row['contact_location_id']);
$location_name = nullable_htmlentities($row['location_name']);
if (empty($location_name)) {
$location_name = "<span class='text-muted'>N/A</span>";
}
$location_archived_at = nullable_htmlentities($row['location_archived_at']);
if ($location_archived_at) {
$location_name_display = "<div class='text-danger' title='Archived'><s>$location_name</s></div>";
} else {
$location_name_display = $location_name;
}
$auth_method = nullable_htmlentities($row['user_auth_method']);
$contact_user_id = intval($row['contact_user_id']);
</tbody>
</table>
</div>
<?php require_once "modals/contact_bulk_assign_location_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_phone_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_department_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_role_modal.php"; ?>
<?php require_once "modals/contact_bulk_assign_tags_modal.php"; ?>
<?php require_once "modals/contact_bulk_email_modal.php"; ?>
</form>
<?php require_once "includes/filter_footer.php";
// Related Assets Query
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_contact_id = $contact_id ORDER BY asset_id DESC");
$asset_count = mysqli_num_rows($sql_related_assets);
if ($asset_count) {
$asset_count_display = "<span class='mr-2 badge badge-pill badge-dark p-2' title='$asset_count Assets'><i class='fas fa-fw fa-desktop mr-2'></i>$asset_count</span>";
} else {
$asset_count_display = '';
}
// Related Logins Query
$sql_related_logins = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_contact_id = $contact_id ORDER BY login_id DESC");
$login_count = mysqli_num_rows($sql_related_logins);
if ($login_count) {
$login_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$login_count Credentials'><i class='fas fa-fw fa-key mr-2'></i>$login_count</span>";
} else {
$login_count_display = '';
}
// Related Software Query
$sql_related_software = mysqli_query($mysqli, "SELECT * FROM software, software_contacts WHERE software.software_id = software_contacts.software_id AND software_contacts.contact_id = $contact_id");
$software_count = mysqli_num_rows($sql_related_software);
if ($software_count) {
$software_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$software_count Licenses'><i class='fas fa-fw fa-cube mr-2'></i>$software_count</span>";
} else {
$software_count_display = '';
}
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_contact_id = $contact_id");
$ticket_count = mysqli_num_rows($sql_related_tickets);
if ($ticket_count) {
$ticket_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$ticket_count Tickets'><i class='fas fa-fw fa-life-ring mr-2'></i>$ticket_count</span>";
} else {
$software_count_display = '';
}
// Related Documents Query
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM documents, contact_documents WHERE documents.document_id = contact_documents.document_id AND contact_documents.contact_id = $contact_id");
$document_count = mysqli_num_rows($sql_related_documents);
if ($document_count) {
$document_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$document_count Documents'><i class='fas fa-fw fa-file-alt mr-2'></i>$document_count</span>";
} else {
$document_count_display = '';
}
// Tags
$contact_tag_name_display_array = array();
$contact_tag_id_array = array();
$sql_contact_tags = mysqli_query($mysqli, "SELECT * FROM contact_tags LEFT JOIN tags ON contact_tags.tag_id = tags.tag_id WHERE contact_id = $contact_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_contact_tags)) {
$contact_tag_id = intval($row['tag_id']);
$contact_tag_name = nullable_htmlentities($row['tag_name']);
$contact_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($contact_tag_color)) {
$contact_tag_color = "dark";
}
$contact_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($contact_tag_icon)) {
$contact_tag_icon = "tag";
}
$contact_tag_id_array[] = $contact_tag_id;
$contact_tag_name_display_array[] = "<a href='contacts.php?$client_url tags[]=$contact_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $contact_tag_color;'><i class='fa fa-fw fa-$contact_tag_icon mr-2'></i>$contact_tag_name</span></a>";
}
$contact_tags_display = implode('', $contact_tag_name_display_array);
?>
<tr>
<td class="pr-0 bg-light">
<div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="contact_ids[]" value="<?php echo $contact_id ?>">
</div>
</td>
<td>
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_contact_details.php?<?php echo $client_url; ?>"
data-ajax-id="<?php echo $contact_id; ?>">
<div class="media">
<?php if ($contact_photo) { ?>
<span class="fa-stack fa-2x mr-3 text-center">
<img class="img-size-50 img-circle" src="<?php echo "uploads/clients/$client_id/$contact_photo"; ?>">
</span>
<?php } else { ?>
<span class="fa-stack fa-2x mr-3">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?php echo $contact_initials; ?></span>
</span>
<?php } ?>
<div class="media-body">
<div class="<?php if($contact_important) { echo "text-bold"; } ?>"><?php echo $contact_name; ?></div>
<?php echo $contact_title_display; ?>
<div><?php echo $contact_primary_display; ?></div>
<?php
if (!empty($contact_tags_display)) { ?>
<div class="mt-1">
<?php echo $contact_tags_display; ?>
</div>
<?php } ?>
</div>
</div>
</a>
</td>
<td><?php echo $contact_department; ?></td>
<td><?php echo $contact_info_display; ?></td>
<td><?php echo $location_name_display; ?></td>
<td>
<?php echo "$asset_count_display$login_count_display$software_count_display$ticket_count_display$document_count_display"; ?>
</td>
<?php if (!$client_url) { ?>
<td><a href="contacts.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<?php } ?>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-eye mr-2"></i>Details
</a>
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_contact_note_create.php"
data-ajax-id="<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-sticky-note mr-2"></i>Make Note
</a>
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_contact_edit.php"
data-ajax-id="<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<?php if ($session_user_role == 3 && $contact_primary == 0) { ?>
<?php if ($contact_archived_at) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-info confirm-link" href="post.php?unarchive_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</a>
<?php } else { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?anonymize_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-user-secret mr-2"></i>Anonymize & Archive
</a>
<?php } ?>
<?php if ($config_destructive_deletes_enable) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_contact=<?php echo $contact_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
<?php } ?>
</div>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<?php require_once "modals/contact_bulk_assign_location_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_phone_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_department_modal.php"; ?>
<?php require_once "modals/contact_bulk_edit_role_modal.php"; ?>
<?php require_once "modals/contact_bulk_assign_tags_modal.php"; ?>
<?php require_once "modals/contact_bulk_email_modal.php"; ?>
</form>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
</div>
<!-- JavaScript to Show/Hide Password Form Group -->
<script>

View File

@@ -64,11 +64,13 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS l.login_id AS l_login_id, l.*, login_tags.*, tags.*, clients.*
"SELECT SQL_CALC_FOUND_ROWS l.login_id AS l_login_id, l.*, login_tags.*, tags.*, clients.*, contacts.*, assets.*
FROM logins l
LEFT JOIN login_tags ON login_tags.login_id = l.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
LEFT JOIN clients ON client_id = login_client_id
LEFT JOIN contacts ON contact_id = login_contact_id
LEFT JOIN assets ON asset_id = login_asset_id
$location_query_innerjoin
WHERE l.login_$archive_query
$tag_query
@@ -168,7 +170,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
<div class="col-md-3">
<div class="form-group">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 4");
@@ -180,6 +182,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="4">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
@@ -293,9 +304,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$login_archived_at = nullable_htmlentities($row['login_archived_at']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_vendor_id = intval($row['login_vendor_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$login_asset_id = intval($row['login_asset_id']);
$login_software_id = intval($row['login_software_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
// Tags
$login_tag_name_display_array = array();
@@ -319,6 +330,27 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
$login_tags_display = implode('', $login_tag_name_display_array);
if ($login_contact_id) {
$login_contact_display = "<a href='#' class='mr-2 badge badge-pill badge-dark p-2' title='$contact_name'
data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_contact_details.php'
data-ajax-id='$login_contact_id'>
<i class='fas fa-fw fa-user'></i></a>";
} else {
$login_contact_display = '';
}
if ($login_asset_id) {
$login_asset_display = "<a href='#' class='mr-2 badge badge-pill badge-secondary p-2' title='$asset_name' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_asset_details.php'
data-ajax-id='$login_asset_id'>
<i class='fas fa-fw fa-desktop'></i></a>";
} else {
$login_asset_display = '';
}
// Check if shared
$sql_shared = mysqli_query(
$mysqli,
@@ -383,6 +415,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td>
<?php echo "$login_contact_display$login_asset_display"; ?>
<?php if (mysqli_num_rows($sql_shared) > 0) { ?>
<div class="media" title="Expires <?php echo $item_expire_at_human; ?>">
<i class="fas fa-link mr-2 mt-1"></i>

View File

@@ -32,4 +32,10 @@
margin: 5px 0;
padding: 10px;
border: 1px solid #ddd;
user-select: none; /* Prevent text selection */
}
.drag-handle-class {
touch-action: none;
float: right;
}

View File

@@ -586,7 +586,7 @@ if ($user_config_dashboard_technical_enable == 1) {
<!-- ./col -->
<div class="col-lg-4 col-6">
<a class="small-box bg-success">
<a class="small-box bg-success" href="contacts.php">
<div class="inner">
<h3><?php echo $contacts_added; ?></h3>
<p>New Contacts</p>
@@ -625,7 +625,7 @@ if ($user_config_dashboard_technical_enable == 1) {
<!-- ./col -->
<div class="col-lg-4 col-6">
<a class="small-box bg-warning" href="domains.php">
<a class="small-box bg-warning" href="domains.php?sort=domain_expire&order=ASC">
<div class="inner">
<h3><?php echo $expiring_domains; ?></h3>
<p>Expiring Domains</p>
@@ -638,7 +638,7 @@ if ($user_config_dashboard_technical_enable == 1) {
<!-- ./col -->
<div class="col-lg-4 col-6">
<a class="small-box bg-primary">
<a class="small-box bg-primary" href="certificates.php?sort=certificate_expire&order=ASC">
<div class="inner">
<h3><?php echo $expiring_certificates; ?></h3>
<p>Expiring Certificates</p>

View File

@@ -2505,10 +2505,25 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.4'");
}
// if (CURRENT_DATABASE_VERSION == '1.8.4') {
// // Insert queries here required to update to DB version 1.8.5
if (CURRENT_DATABASE_VERSION == '1.8.4') {
mysqli_query($mysqli, "ALTER TABLE `logins` DROP `login_software_id`");
mysqli_query($mysqli, "ALTER TABLE `logins` DROP `login_vendor_id`");
mysqli_query($mysqli, "ALTER TABLE `software` DROP `software_login_id`");
mysqli_query($mysqli, "ALTER TABLE `software` ADD `software_vendor_id` INT(11) DEFAULT 0 AFTER `software_accessed_at`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.5'");
}
if (CURRENT_DATABASE_VERSION == '1.8.5') {
mysqli_query($mysqli, "ALTER TABLE `software` ADD `software_purchase_reference` VARCHAR(200) DEFAULT NULL AFTER `software_seats`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.6'");
}
// if (CURRENT_DATABASE_VERSION == '1.8.6') {
// // Insert queries here required to update to DB version 1.8.7
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.5'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.7'");
// }
} else {

7
db.sql
View File

@@ -1033,9 +1033,7 @@ CREATE TABLE `logins` (
`login_password_changed_at` datetime DEFAULT current_timestamp(),
`login_folder_id` int(11) NOT NULL DEFAULT 0,
`login_contact_id` int(11) NOT NULL DEFAULT 0,
`login_vendor_id` int(11) NOT NULL DEFAULT 0,
`login_asset_id` int(11) NOT NULL DEFAULT 0,
`login_software_id` int(11) NOT NULL DEFAULT 0,
`login_client_id` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`login_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
@@ -1805,6 +1803,7 @@ CREATE TABLE `software` (
`software_license_type` varchar(200) DEFAULT NULL,
`software_key` varchar(200) DEFAULT NULL,
`software_seats` int(11) DEFAULT NULL,
`software_purchase_reference` varchar(200) DEFAULT NULL,
`software_purchase` date DEFAULT NULL,
`software_expire` date DEFAULT NULL,
`software_notes` text DEFAULT NULL,
@@ -1813,7 +1812,7 @@ CREATE TABLE `software` (
`software_updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp(),
`software_archived_at` datetime DEFAULT NULL,
`software_accessed_at` datetime DEFAULT NULL,
`software_login_id` int(11) NOT NULL DEFAULT 0,
`software_vendor_id` int(11) DEFAULT 0,
`software_client_id` int(11) NOT NULL,
`software_template_id` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`software_id`)
@@ -2363,4 +2362,4 @@ CREATE TABLE `vendors` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-02-18 17:21:45
-- Dump completed on 2025-02-26 12:58:39

View File

@@ -22,9 +22,13 @@ enforceUserPermission('module_support');
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS domains.*, clients.*,
registrar.vendor_id AS registrar_id,
registrar.vendor_name AS registrar_name,
dnshost.vendor_id AS dnshost_id,
dnshost.vendor_name AS dnshost_name,
mailhost.vendor_id AS mailhost_id,
mailhost.vendor_name AS mailhost_name,
webhost.vendor_id AS webhost_id,
webhost.vendor_name AS webhost_name
FROM domains
LEFT JOIN clients ON client_id = domain_client_id
@@ -191,12 +195,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
} else {
$tr_class = '';
}
$domain_registrar_id = intval($row['registrar_id']);
$domain_webhost_id = intval($row['webhost_id']);
$domain_dnshost_id = intval($row['dnshost_id']);
$domain_mailhost_id = intval($row['mailhost_id']);
$domain_registrar_name = nullable_htmlentities($row['registrar_name']);
if($domain_registrar_name) {
$domain_registrar_name_display = $domain_registrar_name;
} else {
$domain_registrar_name_display = "-";
}
$domain_webhost_name = nullable_htmlentities($row['webhost_name']);
$domain_dnshost_name = nullable_htmlentities($row['dnshost_name']);
$domain_mailhost_name = nullable_htmlentities($row['mailhost_name']);
@@ -205,10 +208,26 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$client_id = intval($row['domain_client_id']);
$client_name = nullable_htmlentities($row['client_name']);
// Add - if empty on the table
$domain_registrar_name_display = $domain_registrar_name ? $domain_registrar_name : "-";
$domain_webhost_name_display = $domain_webhost_name ? $domain_webhost_name : "-";
$domain_dnshost_name_display = $domain_dnshost_name ? $domain_dnshost_name : "-";
$domain_mailhost_name_display = $domain_mailhost_name ? $domain_mailhost_name : "-";
$domain_registrar_name_display = $domain_registrar_name ? "
<a href='#' data-toggle='ajax-modal'
data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$domain_registrar_id'>
$domain_registrar_name
</a>" : "-";
$domain_webhost_name_display = $domain_webhost_name ? "
<a href='#' data-toggle='ajax-modal'
data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$domain_webhost_id'>
$domain_webhost_name
</a>" : "-";
$domain_dnshost_name_display = $domain_dnshost_name ? "
<a href='#' data-toggle='ajax-modal'
data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$domain_dnshost_id'>
$domain_dnshost_name
</a>" : "-";
$domain_mailhost_name_display = $domain_mailhost_name ? "
<a href='#' data-toggle='ajax-modal'
data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$domain_mailhost_id'>
$domain_mailhost_name
</a>" : "-";
?>
<tr class="<?php echo $tr_class; ?>">

View File

@@ -1408,4 +1408,9 @@ function logAuth($status, $details) {
}
mysqli_query($mysqli, "INSERT INTO auth_logs SET auth_log_status = $status, auth_log_details = '$details', auth_log_ip = '$session_ip', auth_log_user_agent = '$session_user_agent', auth_log_user_id = $session_user_id");
}
// Helper function for missing data fallback
function getFallback($data) {
return !empty($data) ? $data : '<span class="text-muted">N/A</span>';
}

View File

@@ -377,6 +377,13 @@ if ($balance > 0) {
style: 'invoiceNumber',
width: '*'
},
<?php if ($invoice_status == "Paid") { ?>
{
text: 'PAID',
style: 'invoicePaid',
width: '*'
},
<?php } ?>
],
],
},
@@ -666,6 +673,14 @@ if ($balance > 0) {
fontSize: 14,
alignment: 'right'
},
// Invoice Paid
invoicePaid: {
fontSize: 13,
bold: true,
margin: [0,5,0,0],
alignment: 'right',
color: 'green'
},
// Billing Headers
invoiceBillingTitle: {
fontSize: 14,

View File

@@ -5,4 +5,4 @@
* Update this file each time we merge develop into master. Format is YY.MM (add a .v if there is more than one release a month.
*/
DEFINE("APP_VERSION", "25.02");
DEFINE("APP_VERSION", "25.02.1");

View File

@@ -5,4 +5,4 @@
* It is used in conjunction with database_updates.php
*/
DEFINE("LATEST_DATABASE_VERSION", "1.8.4");
DEFINE("LATEST_DATABASE_VERSION", "1.8.6");

View File

@@ -216,18 +216,18 @@ if (isset($_GET['client_id'])) {
// Expiring Items
// Count Domains Expiring within 90 Days
// Count Domains Expiring within 45 Days
$row = mysqli_fetch_assoc(mysqli_query(
$mysqli,
"SELECT COUNT('domain_id') AS num FROM domains
WHERE domain_client_id = $client_id
AND domain_expire IS NOT NULL
AND domain_expire < CURRENT_DATE + INTERVAL 90 DAY
AND domain_expire < CURRENT_DATE + INTERVAL 45 DAY
AND domain_archived_at IS NULL"
));
$num_domains_expiring = intval($row['num']);
$num_domains_expiring_warning= intval($row['num']);
// Count Domains Expired or within 14 days
// Count Domains Expired or within 7 days
$row = mysqli_fetch_assoc(mysqli_query(
$mysqli,
"SELECT COUNT('domain_id') AS num FROM domains
@@ -235,24 +235,24 @@ if (isset($_GET['client_id'])) {
AND domain_expire IS NOT NULL
AND (
domain_expire < CURRENT_DATE
OR domain_expire < CURRENT_DATE + INTERVAL 14 DAY
OR domain_expire < CURRENT_DATE + INTERVAL 7 DAY
)
AND domain_archived_at IS NULL"
));
$num_domains_expired = intval($row['num']);
$num_domains_urgent = intval($row['num']);
// Count Certificates Expiring within 90 Days
// Count Certificates Expiring within 45 Days
$row = mysqli_fetch_assoc(mysqli_query(
$mysqli,
"SELECT COUNT('certificate_id') AS num FROM certificates
WHERE certificate_client_id = $client_id
AND certificate_expire IS NOT NULL
AND certificate_expire < CURRENT_DATE + INTERVAL 90 DAY
AND certificate_expire < CURRENT_DATE + INTERVAL 45 DAY
AND certificate_archived_at IS NULL"
));
$num_certificates_expiring = intval($row['num']);
// Count Certificates Expired or within 14 days
// Count Certificates Expired or within 7 days
$row = mysqli_fetch_assoc(mysqli_query(
$mysqli,
"SELECT COUNT('certificate_id') AS num FROM certificates
@@ -260,7 +260,7 @@ if (isset($_GET['client_id'])) {
AND certificate_expire IS NOT NULL
AND (
certificate_expire < CURRENT_DATE
OR certificate_expire < CURRENT_DATE + INTERVAL 14 DAY
OR certificate_expire < CURRENT_DATE + INTERVAL 7 DAY
)
AND certificate_archived_at IS NULL"
));
@@ -272,7 +272,7 @@ if (isset($_GET['client_id'])) {
"SELECT COUNT('software_id') AS num FROM software
WHERE software_client_id = $client_id
AND software_expire IS NOT NULL
AND software_expire < CURRENT_DATE + INTERVAL 90 DAY
AND software_expire < CURRENT_DATE + INTERVAL 45 DAY
AND software_archived_at IS NULL"
));
$num_software_expiring = intval($row['num']);
@@ -285,7 +285,7 @@ if (isset($_GET['client_id'])) {
AND software_expire IS NOT NULL
AND (
software_expire < CURRENT_DATE
OR software_expire < CURRENT_DATE + INTERVAL 14 DAY
OR software_expire < CURRENT_DATE + INTERVAL 7 DAY
)
AND software_archived_at IS NULL"
));

View File

@@ -742,6 +742,13 @@ require_once "includes/footer.php";
style: 'invoiceNumber',
width: '*'
},
<?php if ($invoice_status == "Paid") { ?>
{
text: 'PAID',
style: 'invoicePaid',
width: '*'
},
<?php } ?>
],
],
},
@@ -1031,6 +1038,14 @@ require_once "includes/footer.php";
fontSize: 14,
alignment: 'right'
},
// Invoice Paid
invoicePaid: {
fontSize: 13,
bold: true,
margin: [0,5,0,0],
alignment: 'right',
color: 'green'
},
// Billing Headers
invoiceBillingTitle: {
fontSize: 14,

View File

@@ -42,7 +42,7 @@ $(document).on('click', '[data-toggle="ajax-modal"]', function (e) {
// Build the modal HTML using the returned title and content.
var modalHtml =
'<div class="modal text-sm" id="' + modalId + '" tabindex="-1">' +
'<div class="modal fade text-sm" id="' + modalId + '" tabindex="-1">' +
' <div class="modal-dialog modal-'+ modalSize +'">' +
' <div class="modal-content bg-dark">'
+ response.content +

View File

@@ -39,6 +39,7 @@ tinymce.init({
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl'
});
@@ -70,6 +71,7 @@ tinymce.init({
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {
@@ -168,6 +170,7 @@ tinymce.init({
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code fullscreen autoresize',
license_key: 'gpl'
});
@@ -196,6 +199,7 @@ tinymce.init({
menubar: false,
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {

View File

@@ -1,6 +1,12 @@
$(document).ready(function() {
console.log('CONFIG_TICKET_MOVING_COLUMNS: ' + CONFIG_TICKET_MOVING_COLUMNS);
console.log('CONFIG_TICKET_ORDERING: ' + CONFIG_TICKET_ORDERING);
// Function to detect touch devices
function isTouchDevice() {
return 'ontouchstart' in window || navigator.maxTouchPoints;
}
// Initialize Dragula for the Kanban board
let boardDrake = dragula([
document.querySelector('#kanban-board')
@@ -54,8 +60,30 @@ $(document).ready(function() {
// Initialize Dragula for the Kanban Cards
let drake = dragula([
...document.querySelectorAll('#status')
]);
], {
moves: function(el, container, handle) {
if (isTouchDevice()) {
return handle.classList.contains('drag-handle-class');
} else {
return true; // Allow dragging on the entire task element for desktop
}
}
});
if (isTouchDevice()) {
const moveList = document.querySelectorAll('.task');
moveList.forEach(task => {
task.querySelector('.drag-handle-class').style.display = 'inline';
});
}
drake.on('drag', function(el) {
el.style.cursor = 'grabbing';
});
drake.on('dragend', function(el) {
el.style.cursor = 'grab';
});
// Add event listener for the drop event
drake.on('drop', function (el, target, source, sibling) {
// Log the target ID to the console

View File

@@ -94,7 +94,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<div class="col-md-3">
<div class="form-group">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 2");
while ($row = mysqli_fetch_array($sql_tags)) {
@@ -105,6 +105,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="3">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -1,68 +1,66 @@
<div class="modal" id="addTagModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i>New Tag</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Tag name" maxlength="200" required autofocus>
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i>New Tag</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Tag name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<label>Type <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-th"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<option value="1">Client Tag</option>
<option value="2">Location Tag</option>
<option value="3">Contact Tag</option>
<option value="4">Credential Tag</option>
</select>
</div>
</div>
<div class="form-group">
<label>Type <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-th"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<option value="1">Client Tag</option>
<option value="2">Location Tag</option>
<option value="3">Contact Tag</option>
<option value="4">Credential Tag</option>
</select>
</div>
</div>
<div class="form-group">
<label>Color <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
<div class="form-group">
<label>Color <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
<div class="form-group">
<label>Icon</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-image"></i></span>
</div>
<input type="text" class="form-control" name="icon" placeholder="Icon ex handshake">
</div>
</div>
<div class="form-group">
<label>Icon</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-image"></i></span>
</div>
<input type="text" class="form-control" name="icon" placeholder="Icon ex handshake">
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,51 @@
<div class="modal" id="linkCredentialModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<select class="form-control select2" name="login_id">
<option value="">- Select a Credential -</option>
<?php
$sql_logins_select = mysqli_query($mysqli, "SELECT login_id, login_name FROM logins
WHERE login_client_id = $client_id
AND login_asset_id != $contact_id
AND login_asset_id = 0
AND login_archived_at IS NULL
ORDER BY login_name ASC"
);
while ($row = mysqli_fetch_array($sql_logins_select)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
?>
<option value="<?php echo $login_id ?>"><?php echo $login_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,57 @@
<div class="modal" id="linkDocumentModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
</div>
<select class="form-control select2" name="document_id">
<option value="">- Select a Document -</option>
<?php
// Check if there are any associated documents
if ($linked_documents) {
$excluded_document_ids = implode(",", $linked_documents);
$exclude_condition = "AND document_id NOT IN ($excluded_document_ids)";
} else {
$exclude_condition = ""; // No condition if there are no displayed documents
}
$sql_documents_select = mysqli_query($mysqli, "SELECT * FROM documents
WHERE document_client_id = $client_id
AND document_archived_at IS NULL
$exclude_condition
ORDER BY document_name ASC"
);
while ($row = mysqli_fetch_array($sql_documents_select)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
?>
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,59 @@
<div class="modal" id="linkFileModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
</div>
<select class="form-control select2" name="file_id">
<option value="">- Select a File -</option>
<?php
// Check if there are any associated files
if (!empty($linked_files)) {
$excluded_file_ids = implode(",", $linked_files);
$exclude_condition = "AND file_id NOT IN ($excluded_file_ids)";
} else {
$exclude_condition = ""; // No condition if there are no displayed vendors
}
$sql_files_select = mysqli_query($mysqli, "SELECT * FROM files
LEFT JOIN folders ON folder_id = file_folder_id
WHERE file_client_id = $client_id
$exclude_condition
ORDER BY folder_name ASC, file_name ASC"
);
while ($row = mysqli_fetch_array($sql_files_select)) {
$file_id = intval($row['file_id']);
$file_name = nullable_htmlentities($row['file_name']);
$folder_name = nullable_htmlentities($row['folder_name']);
?>
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,56 @@
<div class="modal" id="linkServiceModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
</div>
<select class="form-control select2" name="service_id">
<option value="">- Select a Service -</option>
<?php
// Check if there are any associated services
if (!empty($linked_services)) {
$excluded_service_ids = implode(",", $linked_services);
$exclude_condition = "AND service_id NOT IN ($excluded_service_ids)";
} else {
$exclude_condition = ""; // No condition if there are no displayed services
}
$sql_services_select = mysqli_query($mysqli, "SELECT * FROM services
WHERE service_client_id = $client_id
$exclude_condition
ORDER BY service_name ASC"
);
while ($row = mysqli_fetch_array($sql_services_select)) {
$service_id = intval($row['service_id']);
$service_name = nullable_htmlentities($row['service_name']);
?>
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_service_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,58 @@
<div class="modal" id="linkSoftwareModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
</div>
<select class="form-control select2" name="software_id">
<option value="">- Select a Device Software License -</option>
<?php
// Check if there are any associated sofctware
if (!empty($linked_software)) {
$excluded_software_ids = implode(",", $linked_software);
$exclude_condition = "AND software_id NOT IN ($excluded_software_ids)";
} else {
$exclude_condition = ""; // No condition if there are no displayed software
}
$sql_software_select = mysqli_query($mysqli, "SELECT * FROM software
WHERE software_client_id = $client_id
AND software_archived_at IS NULL
AND software_license_type = 'Device'
$exclude_condition
ORDER BY software_name ASC"
);
while ($row = mysqli_fetch_array($sql_software_select)) {
$software_id = intval($row['software_id']);
$software_name = nullable_htmlentities($row['software_name']);
?>
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_software_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>

View File

@@ -89,6 +89,14 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Referral">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
@@ -120,6 +128,15 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="1">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -271,6 +271,15 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="3">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -171,30 +171,6 @@
</div>
</div>
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="">- Vendor -</option>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_client_id = $client_id ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
?>
<option value="<?php echo $vendor_id; ?>"><?php echo $vendor_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Asset</label>
<div class="input-group">
@@ -225,31 +201,6 @@
</select>
</div>
</div>
<div class="form-group">
<label>Software</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-box"></i></span>
</div>
<select class="form-control select2" name="software">
<option value="">- Software -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id = $client_id ORDER BY software_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$software_id = intval($row['software_id']);
$software_name = nullable_htmlentities($row['software_name']);
?>
<option value="<?php echo $software_id; ?>"><?php echo $software_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<?php } ?>
@@ -277,6 +228,15 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="4">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -34,6 +34,15 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="4">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -140,7 +140,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Expense" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Expense">
<i class="fas fa-plus"></i>
</button>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-folder-plus mr-2"></i>Creating folder in <strong><?php if($get_folder_id > 0) { echo $folder['folder_name']; } else { echo "/"; } ?></strong></h5>
<h5 class="modal-title"><i class="fa fa-fw fa-folder-plus mr-2"></i>Creating folder in <strong><?php if($get_folder_id > 0) { echo $folder_path[count($folder_path)-1]['folder_name']; } else { echo "/"; } ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>

View File

@@ -73,7 +73,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -232,6 +232,15 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="2">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -42,7 +42,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -71,7 +71,12 @@
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -182,7 +182,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Expense" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Expense">
<i class="fas fa-plus"></i>
</button>
</div>
</div>

View File

@@ -97,7 +97,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -99,7 +99,12 @@
?>
</select>
<div class="input-group-append">
<a class="btn btn-secondary" href="admin_category.php?category=Income" target="_blank"><i class="fas fa-fw fa-plus"></i></a>
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>

View File

@@ -93,6 +93,29 @@
</div>
</div>
<?php if ($client_url) { ?>
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="">- Select Vendor -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT vendor_name, vendor_id FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
?>
<option value="<?php echo $vendor_id; ?>"><?php echo $vendor_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<?php } ?>
<div class="form-group">
<label>Type <strong class="text-danger">*</strong></label>
<div class="input-group">
@@ -100,7 +123,7 @@
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<option value="">- Select Type -</option>
<?php foreach ($software_types_array as $software_type) { ?>
<option><?php echo $software_type; ?></option>
<?php } ?>
@@ -147,6 +170,16 @@
</div>
</div>
<div class="form-group">
<label>Purchase Reference</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
</div>
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number">
</div>
</div>
<div class="form-group">
<label>Purchase Date</label>
<div class="input-group">

View File

@@ -152,6 +152,14 @@
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Ticket">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
</div>

View File

@@ -295,10 +295,9 @@ if (isset($_POST['bulk_transfer_client_asset'])) {
while ($row = mysqli_fetch_array($sql_interfaces)) {
$interface_name = sanitizeInput($row['interface_name']);
$interface_mac = sanitizeInput($row['interface_mac']);
$interface_port = sanitizeInput($row['interface_port']);
$interface_primary = intval($row['interface_primary']);
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '$interface_name', interface_mac = '$interface_mac', interface_port = '$interface_port', interface_primary = $interface_primary, interface_asset_id = $new_asset_id");
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '$interface_name', interface_mac = '$interface_mac', interface_primary = $interface_primary, interface_asset_id = $new_asset_id");
}
@@ -331,7 +330,7 @@ if (isset($_POST['bulk_transfer_client_asset'])) {
$_SESSION['alert_message'] = "Transferred <strong>$asset_count</strong> assets to <strong>$new_client_name</strong>.";
}
header("Location: client_assets.php?client_id=$new_client_id&asset_id=$new_asset_id");
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['bulk_assign_asset_contact'])) {
@@ -496,6 +495,248 @@ if (isset($_POST['bulk_unarchive_assets'])) {
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
// BEGIN LINKING
if (isset($_POST['link_software_to_asset'])) {
enforceUserPermission('module_support', 2);
$software_id = intval($_POST['software_id']);
$asset_id = intval($_POST['asset_id']);
// Get software Name and Client ID for logging
$sql_software = mysqli_query($mysqli,"SELECT software_name, software_client_id FROM software WHERE software_id = $software_id");
$row = mysqli_fetch_array($sql_software);
$software_name = sanitizeInput($row['software_name']);
$client_id = intval($row['software_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"INSERT INTO software_assets SET asset_id = $asset_id, software_id = $software_id");
// Logging
logAction("Software", "Link", "$session_name added software license $software_name to asset $asset_name", $client_id, $software_id);
$_SESSION['alert_message'] = "Software <strong>$software_name</strong> licensed for asset <strong>$asset_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['unlink_software_from_asset'])) {
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$software_id = intval($_GET['software_id']);
// Get software Name and Client ID for logging
$sql_software = mysqli_query($mysqli,"SELECT software_name, software_client_id FROM software WHERE software_id = $software_id");
$row = mysqli_fetch_array($sql_software);
$software_name = sanitizeInput($row['software_name']);
$client_id = intval($row['software_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"DELETE FROM software_assets WHERE asset_id = $asset_id AND software_id = $software_id");
//Logging
logAction("software", "Unlink", "$session_name removed software license $software_name from asset $asset_name", $client_id, $software_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Removed Software License <strong>$software_name</strong> for Asset <strong>$asset_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
// Right now 1 login and have many assets but not many to many
if (isset($_POST['link_asset_to_credential'])) {
enforceUserPermission('module_support', 2);
$login_id = intval($_POST['login_id']);
$asset_id = intval($_POST['asset_id']);
// Get login Name and Client ID for logging
$sql_login = mysqli_query($mysqli,"SELECT login_name, login_client_id FROM logins WHERE login_id = $login_id");
$row = mysqli_fetch_array($sql_login);
$login_name = sanitizeInput($row['login_name']);
$client_id = intval($row['login_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"UPDATE logins SET login_asset_id = $asset_id WHERE login_id = $login_id");
// Logging
logAction("Credential", "Link", "$session_name linked credential $login_name to asset $asset_name", $client_id, $login_id);
$_SESSION['alert_message'] = "Asset <strong>$asset_name</strong> linked with credential <strong>$login_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['unlink_credential_from_asset'])) {
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$login_id = intval($_GET['login_id']);
// Get login Name and Client ID for logging
$sql_login = mysqli_query($mysqli,"SELECT login_name, login_client_id FROM logins WHERE login_id = $login_id");
$row = mysqli_fetch_array($sql_login);
$login_name = sanitizeInput($row['login_name']);
$client_id = intval($row['login_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"UPDATE logins SET login_asset_id = 0 WHERE login_id = $login_id");
//Logging
logAction("Credential", "Unlink", "$session_name unlinked asset $asset_name from credential $login_name", $client_id, $login_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Credential <strong>$login_name</strong> unlinked from Asset <strong>$asset_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['link_service_to_asset'])) {
enforceUserPermission('module_support', 2);
$service_id = intval($_POST['service_id']);
$asset_id = intval($_POST['asset_id']);
// Get service Name and Client ID for logging
$sql_service = mysqli_query($mysqli,"SELECT service_name, service_client_id FROM services WHERE service_id = $service_id");
$row = mysqli_fetch_array($sql_service);
$service_name = sanitizeInput($row['service_name']);
$client_id = intval($row['service_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"INSERT INTO service_assets SET asset_id = $asset_id, service_id = $service_id");
// Logging
logAction("Service", "Link", "$session_name linked asset $asset_name to service $service_name", $client_id, $service_id);
$_SESSION['alert_message'] = "Service <strong>$service_name</strong> linked with asset <strong>$asset_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['unlink_service_from_asset'])) {
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$service_id = intval($_GET['service_id']);
// Get service Name and Client ID for logging
$sql_service = mysqli_query($mysqli,"SELECT service_name, service_client_id FROM services WHERE service_id = $service_id");
$row = mysqli_fetch_array($sql_service);
$service_name = sanitizeInput($row['service_name']);
$client_id = intval($row['service_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"DELETE FROM service_assets WHERE asset_id = $asset_id AND service_id = $service_id");
//Logging
logAction("Service", "Unlink", "$session_name unlinked asset $asset_name from service $service_name", $client_id, $service_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Asset <strong>$asset_name</strong> unlinked from service <strong>$service_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['link_asset_to_file'])) {
enforceUserPermission('module_support', 2);
$file_id = intval($_POST['file_id']);
$asset_id = intval($_POST['asset_id']);
// Get file Name and Client ID for logging
$sql_file = mysqli_query($mysqli,"SELECT file_name, file_client_id FROM files WHERE file_id = $file_id");
$row = mysqli_fetch_array($sql_file);
$file_name = sanitizeInput($row['file_name']);
$client_id = intval($row['file_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
// asset add query
mysqli_query($mysqli,"INSERT INTO asset_files SET asset_id = $asset_id, file_id = $file_id");
// Logging
logAction("File", "Link", "$session_name linked asset $asset_name to file $file_name", $client_id, $file_id);
$_SESSION['alert_message'] = "Asset <strong>$asset_name</strong> linked with File <strong>$file_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['unlink_asset_from_file'])) {
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$file_id = intval($_GET['file_id']);
// Get file Name and Client ID for logging
$sql_file = mysqli_query($mysqli,"SELECT file_name, file_client_id FROM files WHERE file_id = $file_id");
$row = mysqli_fetch_array($sql_file);
$file_name = sanitizeInput($row['file_name']);
$client_id = intval($row['file_client_id']);
// Get Asset Name for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_array($sql_asset);
$asset_name = sanitizeInput($row['asset_name']);
mysqli_query($mysqli,"DELETE FROM asset_files WHERE asset_id = $asset_id AND file_id = $file_id");
//Logging
logAction("File", "Unlink", "$session_name unlinked asset $asset_name from file $file_name", $client_id, $file_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Asset <strong>$asset_name</strong> unlinked from file <strong>$file_name</strong>";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
// END LINKING
if (isset($_POST["import_assets_csv"])) {
enforceUserPermission('module_support', 2);

24
post/user/category.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
/*
* ITFlow - GET/POST request handler for categories ('category')
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_category'])) {
require_once 'post/user/category_model.php';
mysqli_query($mysqli,"INSERT INTO categories SET category_name = '$name', category_type = '$type', category_color = '$color'");
$category_id = mysqli_insert_id($mysqli);
// Logging
logAction("Category", "Create", "$session_name created category $type $name", 0, $category_id);
$_SESSION['alert_message'] = "Category $type <strong>$name</strong> created";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}

View File

@@ -0,0 +1,6 @@
<?php
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
$name = sanitizeInput($_POST['name']);
$type = sanitizeInput($_POST['type']);
$color = sanitizeInput($_POST['color']);

View File

@@ -13,6 +13,4 @@ $otp_secret = sanitizeInput($_POST['otp_secret']);
$note = sanitizeInput($_POST['note']);
$important = intval($_POST['important'] ?? 0);
$contact_id = intval($_POST['contact'] ?? 0);
$vendor_id = intval($_POST['vendor'] ?? 0);
$asset_id = intval($_POST['asset'] ?? 0);
$software_id = intval($_POST['software'] ?? 0);

View File

@@ -7,66 +7,83 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['upload_files'])) {
enforceUserPermission('module_support', 2);
$client_id = intval($_POST['client_id']);
$folder_id = intval($_POST['folder_id']);
// Enforce required user permission
enforceUserPermission('module_support', 2);
// Sanitize and initialize inputs
$client_id = intval($_POST['client_id']);
$folder_id = intval($_POST['folder_id']);
$description = sanitizeInput($_POST['description']);
$client_dir = "uploads/clients/$client_id";
if (!file_exists("uploads/clients/$client_id")) {
mkdir("uploads/clients/$client_id");
// Create client directory if it doesn't exist
if (!is_dir($client_dir)) {
mkdir($client_dir, 0755, true);
}
for ($i = 0; $i < count($_FILES['file']['name']); $i++) {
// Extract file details for this iteration
// Allowed file extensions list
$allowedExtensions = [
'jpg', 'jpeg', 'gif', 'png', 'webp', 'pdf', 'txt', 'md', 'doc', 'docx',
'odt', 'csv', 'xls', 'xlsx', 'ods', 'pptx', 'odp', 'zip', 'tar', 'gz',
'xml', 'msg', 'json', 'wav', 'mp3', 'ogg', 'mov', 'mp4', 'av1', 'ovpn',
'cfg', 'ps1', 'vsdx', 'drawio', 'pfx', 'pages', 'numbers', 'unf', 'key'
];
// Loop through each uploaded file
foreach ($_FILES['file']['name'] as $index => $originalName) {
// Build a file array for this iteration
$single_file = [
'name' => $_FILES['file']['name'][$i],
'type' => $_FILES['file']['type'][$i],
'tmp_name' => $_FILES['file']['tmp_name'][$i],
'error' => $_FILES['file']['error'][$i],
'size' => $_FILES['file']['size'][$i]
'name' => $_FILES['file']['name'][$index],
'type' => $_FILES['file']['type'][$index],
'tmp_name' => $_FILES['file']['tmp_name'][$index],
'error' => $_FILES['file']['error'][$index],
'size' => $_FILES['file']['size'][$index]
];
if ($file_reference_name = checkFileUpload($single_file, array('jpg', 'jpeg', 'gif', 'png', 'webp', 'pdf', 'txt', 'md', 'doc', 'docx', 'odt', 'csv', 'xls', 'xlsx', 'ods', 'pptx', 'odp', 'zip', 'tar', 'gz', 'xml', 'msg', 'json', 'wav', 'mp3', 'ogg', 'mov', 'mp4', 'av1', 'ovpn', 'cfg', 'ps1', 'vsdx', 'drawio', 'pfx', 'pages', 'numbers', 'unf', 'key'))) {
// Validate and get a safe file reference name
if ($file_reference_name = checkFileUpload($single_file, $allowedExtensions)) {
$file_tmp_path = $_FILES['file']['tmp_name'][$i];
$file_tmp_path = $single_file['tmp_name'];
$file_name = sanitizeInput($originalName);
$extParts = explode('.', $file_name);
$file_extension = strtolower(end($extParts));
$file_mime_type = sanitizeInput($single_file['type']);
$file_size = intval($single_file['size']);
$file_name = sanitizeInput($_FILES['file']['name'][$i]);
$extarr = explode('.', $_FILES['file']['name'][$i]);
$file_extension = sanitizeInput(strtolower(end($extarr)));
// Define destination path and move the uploaded file
$upload_file_dir = $client_dir . "/";
$dest_path = $upload_file_dir . $file_reference_name;
// Extract the file mime type and size
$file_mime_type = sanitizeInput($single_file['type']);
$file_size = intval($single_file['size']);
if (!move_uploaded_file($file_tmp_path, $dest_path)) {
$_SESSION['alert_type'] = 'error';
$_SESSION['alert_message'] = 'Error moving file to upload directory. Please ensure the directory is writable.';
continue; // Skip processing this file
}
// directory in which the uploaded file will be moved
$upload_file_dir = "uploads/clients/$client_id/";
$dest_path = $upload_file_dir . $file_reference_name;
move_uploaded_file($file_tmp_path, $dest_path);
// Extract .ext from reference file name to be used to store SHA256 hash
// Use the file reference (without extension) as the file hash
$file_hash = strstr($file_reference_name, '.', true) ?: $file_reference_name;
mysqli_query($mysqli,"INSERT INTO files SET file_reference_name = '$file_reference_name', file_name = '$file_name', file_description = '$description', file_ext = '$file_extension', file_hash = '$file_hash', file_mime_type = '$file_mime_type', file_size = $file_size, file_created_by = $session_user_id, file_folder_id = $folder_id, file_client_id = $client_id");
// Insert file metadata into the database
$query = "INSERT INTO files SET
file_reference_name = '$file_reference_name',
file_name = '$file_name',
file_description = '$description',
file_ext = '$file_extension',
file_hash = '$file_hash',
file_mime_type = '$file_mime_type',
file_size = $file_size,
file_created_by = $session_user_id,
file_folder_id = $folder_id,
file_client_id = $client_id";
mysqli_query($mysqli, $query);
$file_id = mysqli_insert_id($mysqli);
// If the file is an image, create a thumbnail and an optimized preview image
// If the file is an image, create a thumbnail and an optimized preview
if (in_array($file_extension, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
// Thumbnail dimensions
$thumbnail_width = 200;
$thumbnail_height = 200;
// Optimized preview dimensions
$preview_max_width = 1200;
$preview_max_height = 1200;
// Get original dimensions
list($orig_width, $orig_height) = getimagesize($dest_path);
// Create image resource from the original file
// Create image resource based on file extension
switch ($file_extension) {
case 'jpg':
case 'jpeg':
@@ -81,21 +98,42 @@ if (isset($_POST['upload_files'])) {
case 'webp':
$src_img = imagecreatefromwebp($dest_path);
break;
default:
$src_img = false;
}
if ($src_img) {
// -------------------------
// CREATE THUMBNAIL
// -------------------------
// Fix image rotation for JPEG images using EXIF data
if (in_array($file_extension, ['jpg', 'jpeg']) && function_exists('exif_read_data')) {
$exif = @exif_read_data($dest_path);
if (!empty($exif['Orientation'])) {
switch ($exif['Orientation']) {
case 3:
$src_img = imagerotate($src_img, 180, 0);
break;
case 6:
$src_img = imagerotate($src_img, -90, 0);
break;
case 8:
$src_img = imagerotate($src_img, 90, 0);
break;
}
}
}
// Get original image dimensions
list($orig_width, $orig_height) = getimagesize($dest_path);
/* --- CREATE THUMBNAIL --- */
$thumbnail_width = 200;
$thumbnail_height = 200;
$thumb_img = imagecreatetruecolor($thumbnail_width, $thumbnail_height);
imagecopyresampled($thumb_img, $src_img, 0, 0, 0, 0,
$thumbnail_width, $thumbnail_height,
$orig_width, $orig_height);
$thumbnail_width, $thumbnail_height, $orig_width, $orig_height);
$thumbnail_file_name = 'thumbnail_' . $file_reference_name;
$thumb_path = $upload_file_dir . $thumbnail_file_name;
// Save thumbnail to disk
switch ($file_extension) {
case 'jpg':
case 'jpeg':
@@ -111,44 +149,39 @@ if (isset($_POST['upload_files'])) {
imagewebp($thumb_img, $thumb_path);
break;
}
imagedestroy($thumb_img);
mysqli_query($mysqli, "UPDATE files SET file_has_thumbnail = 1 WHERE file_id = $file_id");
mysqli_query($mysqli,"UPDATE files SET file_has_thumbnail = 1 WHERE file_id = $file_id");
// -------------------------
// CREATE OPTIMIZED PREVIEW IMAGE
// -------------------------
/* --- CREATE OPTIMIZED PREVIEW IMAGE --- */
$preview_max_width = 1200;
$preview_max_height = 1200;
$aspect_ratio = $orig_width / $orig_height;
if ($orig_width <= $preview_max_width && $orig_height <= $preview_max_height) {
$preview_new_width = $orig_width;
$preview_new_width = $orig_width;
$preview_new_height = $orig_height;
} elseif ($aspect_ratio > 1) {
// Wider than tall
$preview_new_width = $preview_max_width;
$preview_new_width = $preview_max_width;
$preview_new_height = (int)($preview_max_width / $aspect_ratio);
} else {
// Taller or square
$preview_new_height = $preview_max_height;
$preview_new_width = (int)($preview_max_height * $aspect_ratio);
$preview_new_width = (int)($preview_max_height * $aspect_ratio);
}
$preview_img = imagecreatetruecolor($preview_new_width, $preview_new_height);
imagecopyresampled($preview_img, $src_img, 0, 0, 0, 0,
$preview_new_width, $preview_new_height,
$orig_width, $orig_height);
$preview_new_width, $preview_new_height, $orig_width, $orig_height);
$preview_file_name = 'preview_' . $file_reference_name;
$preview_path = $upload_file_dir . $preview_file_name;
switch ($file_extension) {
case 'jpg':
case 'jpeg':
// Lower quality for optimization (70 is example)
imagejpeg($preview_img, $preview_path, 70);
break;
case 'png':
// Higher compression level (0-9), 7 is an example
imagepng($preview_img, $preview_path, 7);
break;
case 'gif':
@@ -158,25 +191,24 @@ if (isset($_POST['upload_files'])) {
imagewebp($preview_img, $preview_path, 70);
break;
}
imagedestroy($preview_img);
imagedestroy($src_img);
mysqli_query($mysqli,"UPDATE files SET file_has_preview = 1 WHERE file_id = $file_id");
mysqli_query($mysqli, "UPDATE files SET file_has_preview = 1 WHERE file_id = $file_id");
}
}
// Logging
// Log the file upload action
logAction("File", "Upload", "$session_name uploaded file $file_name", $client_id, $file_id);
$_SESSION['alert_message'] = "Uploaded file <strong>$file_name</strong>";
} else {
$_SESSION['alert_type'] = 'error';
$_SESSION['alert_message'] = 'There was an error moving the file to upload directory. Please make sure the upload directory is writable by web server.';
$_SESSION['alert_message'] = 'There was an error processing the file upload. Please ensure the upload directory is writable by the web server.';
}
}
// Redirect at the end, after processing all files
// Redirect back to the previous page after processing
header("Location: " . $_SERVER["HTTP_REFERER"]);
exit;
}
if (isset($_POST['rename_file'])) {

View File

@@ -23,9 +23,10 @@ if (isset($_POST['add_software_from_template'])) {
$type = sanitizeInput($row['software_type']);
$license_type = sanitizeInput($row['software_license_type']);
$notes = sanitizeInput($row['software_notes']);
$vendor = sanitizeInput($_POST['vendor'] ?? 0);
// Software add query
mysqli_query($mysqli,"INSERT INTO software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_license_type = '$license_type', software_notes = '$notes', software_client_id = $client_id");
mysqli_query($mysqli,"INSERT INTO software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_license_type = '$license_type', software_notes = '$notes', software_vendor_id = $vendor, software_client_id = $client_id");
$software_id = mysqli_insert_id($mysqli);
@@ -51,6 +52,7 @@ if (isset($_POST['add_software'])) {
$notes = sanitizeInput($_POST['notes']);
$key = sanitizeInput($_POST['key']);
$seats = intval($_POST['seats']);
$purchase_reference = sanitizeInput($_POST['purchase_reference']);
$purchase = sanitizeInput($_POST['purchase']);
if (empty($purchase)) {
$purchase = "NULL";
@@ -64,8 +66,9 @@ if (isset($_POST['add_software'])) {
$expire = "'" . $expire . "'";
}
$notes = sanitizeInput($_POST['notes']);
$vendor = sanitizeInput($_POST['vendor'] ?? 0);
mysqli_query($mysqli,"INSERT INTO software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase = $purchase, software_expire = $expire, software_notes = '$notes', software_client_id = $client_id");
mysqli_query($mysqli,"INSERT INTO software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase_reference = '$purchase_reference', software_purchase = $purchase, software_expire = $expire, software_notes = '$notes', software_vendor_id = $vendor, software_client_id = $client_id");
$software_id = mysqli_insert_id($mysqli);
@@ -110,6 +113,7 @@ if (isset($_POST['edit_software'])) {
$notes = sanitizeInput($_POST['notes']);
$key = sanitizeInput($_POST['key']);
$seats = intval($_POST['seats']);
$purchase_reference = sanitizeInput($_POST['purchase_reference']);
$purchase = sanitizeInput($_POST['purchase']);
if (empty($purchase)) {
$purchase = "NULL";
@@ -123,8 +127,9 @@ if (isset($_POST['edit_software'])) {
$expire = "'" . $expire . "'";
}
$notes = sanitizeInput($_POST['notes']);
$vendor = sanitizeInput($_POST['vendor'] ?? 0);
mysqli_query($mysqli,"UPDATE software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase = $purchase, software_expire = $expire, software_notes = '$notes' WHERE software_id = $software_id");
mysqli_query($mysqli,"UPDATE software SET software_name = '$name', software_version = '$version', software_description = '$description', software_type = '$type', software_key = '$key', software_license_type = '$license_type', software_seats = $seats, software_purchase_reference = '$purchase_reference', software_purchase = $purchase, software_expire = $expire, software_notes = '$notes', software_vendor_id = $vendor WHERE software_id = $software_id");
// Update Asset Licenses

24
post/user/tag.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
/*
* ITFlow - GET/POST request handler for tagging
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_tag'])) {
require_once 'post/user/tag_model.php';
mysqli_query($mysqli,"INSERT INTO tags SET tag_name = '$name', tag_type = $type, tag_color = '$color', tag_icon = '$icon'");
$tag_id = mysqli_insert_id($mysqli);
// Logging
logAction("Tag", "Create", "$session_name created tag $name", 0, $tag_id);
$_SESSION['alert_message'] = "Tag <strong>$name</strong> created";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}

7
post/user/tag_model.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
$name = sanitizeInput($_POST['name']);
$type = intval($_POST['type']);
$color = sanitizeInput($_POST['color']);
$icon = preg_replace("/[^0-9a-zA-Z-]/", "", sanitizeInput($_POST['icon']));

View File

@@ -2338,7 +2338,7 @@ if (isset($_POST['edit_ticket_schedule'])) {
'recipient' => $user_email,
'recipient_name' => $user_name,
'subject' => "Ticket Scheduled - [$ticket_prefix$ticket_number] - $ticket_subject",
'body' => "Hello, " . $user_name . "<br><br>The ticket regarding $ticket_subject has been scheduled for $email_datetime.<br><br>--------------------------------<br><a href=\"https://$config_base_url/ticket.php?id=$ticket_id\">$ticket_link</a><br>--------------------------------<br><br>Please do not reply to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Portal: https://$config_base_url/ticket.php?id=$ticket_id<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email",
'body' => "Hello, " . $user_name . "<br><br>The ticket regarding $ticket_subject has been scheduled for $email_datetime.<br><br>--------------------------------<br><a href=\"https://$config_base_url/ticket.php?ticket_id=$ticket_id\">$ticket_link</a><br>--------------------------------<br><br>Please do not reply to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Portal: https://$config_base_url/ticket.php?ticket_id=$ticket_id<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email",
'cal_str' => $cal_str
];
@@ -2430,7 +2430,7 @@ if (isset($_POST['edit_ticket_schedule'])) {
} else {
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Ticket scheduled for $email_datetime. Yet there are conflicting tickets scheduled for the same time: <br>" . implode(", <br>", $conflicting_tickets);
header("Location: calendar_events.php");
header("Location: calendar.php");
}
}
@@ -2491,7 +2491,7 @@ if (isset($_GET['cancel_ticket_schedule'])) {
'recipient' => $user_email,
'recipient_name' => $user_name,
'subject' => "Ticket Schedule Cancelled - [$ticket_prefix$ticket_number] - $ticket_subject",
'body' => "Hello, " . $user_name . "<br><br>Scheduled work for the ticket regarding $ticket_subject has been cancelled.<br><br>--------------------------------<br><a href=\"https://$config_base_url/ticket.php?id=$ticket_id\">$ticket_link</a><br>--------------------------------<br><br>Please do not reply to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Portal: https://$config_base_url/ticket.php?id=$ticket_id<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email",
'body' => "Hello, " . $user_name . "<br><br>Scheduled work for the ticket regarding $ticket_subject has been cancelled.<br><br>--------------------------------<br><a href=\"https://$config_base_url/ticket.php?ticket_id=$ticket_id\">$ticket_link</a><br>--------------------------------<br><br>Please do not reply to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Portal: https://$config_base_url/ticket.php?id=$ticket_id<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email",
'cal_str' => $cal_str
];

View File

@@ -67,8 +67,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<div class="col-sm-3">
<div class="input-group">
<select class="form-control select2" name="category" onchange="this.form.submit()">
<option value="">- All Categories -</option>
@@ -84,9 +84,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Income">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="col-md-5">
<div class="btn-group float-right">
<a href="?<?php echo $url_query_strings_sort ?>&archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">

View File

@@ -170,7 +170,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
if ($client_name) {
$client_name_display = "<a href='client_tickets.php?client_id=$client_id'>$client_name</a>";
$client_name_display = "<a href='tickets.php?client_id=$client_id'>$client_name</a>";
} else {
$client_name_display = "-";
}

View File

@@ -179,7 +179,7 @@ if ($config_whitelabel_enabled && !validateWhitelabelKey($config_whitelabel_key)
if ($config_enable_alert_domain_expire == 1) {
$domainAlertArray = [1,7,14,30,90];
$domainAlertArray = [1,7,45];
foreach ($domainAlertArray as $day) {
@@ -209,7 +209,7 @@ if ($config_enable_alert_domain_expire == 1) {
// CERTIFICATES EXPIRING
$certificateAlertArray = [1,7,14,30,90];
$certificateAlertArray = [1,7,45];
foreach ($certificateAlertArray as $day) {
@@ -239,7 +239,7 @@ foreach ($certificateAlertArray as $day) {
// Asset Warranties Expiring
$warranty_alert_array = [1,7,14,30,90];
$warranty_alert_array = [1,7,45];
foreach ($warranty_alert_array as $day) {

View File

@@ -22,6 +22,7 @@ $sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM software
LEFT JOIN clients ON client_id = software_client_id
LEFT JOIN vendors ON vendor_id = software_vendor_id
WHERE software_template = 0
AND software_$archive_query
AND (software_name LIKE '%$q%' OR software_type LIKE '%$q%' OR software_key LIKE '%$q%' OR client_name LIKE '%$q%')
@@ -114,6 +115,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
Expire <?php if ($sort == 'software_expire') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
</a>
</th>
<?php if (!$client_url) { ?>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
@@ -135,11 +141,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$software_description = nullable_htmlentities($row['software_description']);
$software_version = nullable_htmlentities($row['software_version']);
$software_type = nullable_htmlentities($row['software_type']);
$software_license_type = nullable_htmlentities($row['software_license_type']);
$software_key = nullable_htmlentities($row['software_key']);
$software_license_type = getFallBack(nullable_htmlentities($row['software_license_type']));
$software_seats = nullable_htmlentities($row['software_seats']);
$software_purchase = nullable_htmlentities($row['software_purchase']);
$software_expire = nullable_htmlentities($row['software_expire']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_id = intval($row['vendor_id']);
if ($vendor_name) {
$vendor_display = "<a href='#' data-toggle='ajax-modal' data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$vendor_id'>$vendor_name</a>";
} else {
$vendor_display = "<span class='text-muted'>N/A</span>";
}
if ($software_expire) {
$software_expire_ago = timeAgo($software_expire);
$software_expire_display = "<div>$software_expire</div><div><small>$software_expire_ago</small></div>";
@@ -154,19 +165,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
// Determine the class based on the number of days until expiry
if ($days_until_expiry <= 0) {
$tr_class = "table-secondary";
} elseif ($days_until_expiry <= 14) {
} elseif ($days_until_expiry <= 7) {
$tr_class = "table-danger";
} elseif ($days_until_expiry <= 90) {
} elseif ($days_until_expiry <= 45) {
$tr_class = "table-warning";
} else {
$tr_class = '';
}
} else {
$software_expire_display = "-";
$software_expire_display = "<span class='text-muted'>N/A</span>";
}
$software_notes = nullable_htmlentities($row['software_notes']);
$software_created_at = nullable_htmlentities($row['software_created_at']);
$seat_count = 0;
@@ -212,6 +222,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<td><?php echo $software_license_type; ?></td>
<td><?php echo "$seat_count / $software_seats"; ?></td>
<td><?php echo $software_expire_display; ?></td>
<td><?php echo $vendor_display; ?></td>
<?php if (!$client_url) { ?>
<td><a href="software.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<?php } ?>

View File

@@ -95,11 +95,10 @@ $kanban = array_values($statuses);
?>
<div
class="task"
class="task grab-cursor"
data-ticket-id= "<?=$item['ticket_id']?>"
data-ticket-status-id= "<?=$item['ticket_status_id']?>"
ondblclick="window.location.href='ticket.php?ticket_id=<?php echo $item['ticket_id']; ?>'"
style="cursor: grabbing;"
>
<span class='badge badge-<?php echo $ticket_priority_color; ?>'>
<?php echo $item['ticket_priority']; ?>
@@ -107,8 +106,10 @@ $kanban = array_values($statuses);
<span class='badge badge-secondary'>
<?php echo $item['category_name']; ?>
</span>
<div class='btn btn-secondary drag-handle-class' style="display: none;">
<i class="drag-handle-class fas fa-bars"></i>
</div>
<br>
<b>
<?php
if (!$client_url) {