From fb084ae50468bd337f0bf7ba9544f2893e28743b Mon Sep 17 00:00:00 2001 From: johnnyq Date: Wed, 14 Oct 2026 17:15:17 -0400 Subject: [PATCH] Assets: change status, location and assigned contact in place on the assets list, the asset page and the quick look, using the same quick pickers as tickets (location and contact only offer the asset's own client's); Add/Edit/Copy form split into tabs (Details, Assignment, Network, Purchase, Login or History, Notes) that jumps to a required field left empty on another tab; Printers tab on the assets list with New Printer and a Printers export filter; asset quick look rebuilt as a compact asset page: header with type icon and status, IP/MAC/serial with copy, warranty, location, contact and rack on a few lines, connect buttons, counted tabs showing only what has something in them and reopening on the last one used, open tickets first with a link to the rest, Open asset in the footer. Fixes bulk assign contact/location changing assets of a different client, quick look notes saving the underlying page's asset notes over the connected asset's, and a query per license on the quick look. No DB change --- agent/ajax.php | 46 +- agent/asset.php | 34 +- agent/assets.php | 37 +- agent/modals/asset/asset.php | 1323 ++++++++++----------------- agent/modals/asset/asset_add.php | 2 +- agent/modals/asset/asset_export.php | 1 + agent/modals/asset/asset_form.php | 198 ++-- agent/post/asset.php | 35 +- css/itflow_custom.css | 166 ++++ functions/asset.php | 243 +++++ functions/ticket_fields.php | 13 +- js/quick_pick.js | 51 +- 12 files changed, 1154 insertions(+), 995 deletions(-) diff --git a/agent/ajax.php b/agent/ajax.php index ba6962307..8cd109b15 100644 --- a/agent/ajax.php +++ b/agent/ajax.php @@ -181,8 +181,8 @@ if (isset($_POST['tag_picker_set']) || isset($_POST['tag_picker_create'])) { /* * Quick pickers (js/quick_pick.js) - a ticket's status, priority, assignee - * and billable, a project's manager and a recurring ticket's assignee, - * changed in place instead of through a modal. GET lists the choices; POST makes the change through the same + * and billable, a project's manager, a recurring ticket's assignee and an + * asset's status, location and contact, changed in place instead of through a modal. GET lists the choices; POST makes the change through the same * functions the post.php handlers use (functions/ticket_fields.php) and sends * back the redrawn values. */ @@ -210,6 +210,14 @@ if (isset($_GET['quick_pick_options'])) { $options = quickPickAgents(); } elseif ($field === 'project_manager') { $options = quickPickAgents('No manager'); + } elseif (in_array($field, ASSET_QUICK_FIELDS, true)) { + // Locations and contacts are the asset's client's own - functions/asset.php + $options = assetQuickOptions($field, intval($_GET['scope'] ?? 0)); + if ($options === null) { + http_response_code(403); + echo json_encode(['error' => 'You cannot see that client.']); + exit(); + } } else { http_response_code(400); echo json_encode(['error' => 'Unknown field']); @@ -230,6 +238,40 @@ if (isset($_POST['quick_pick_set'])) { $value = (string) ($_POST['value'] ?? ''); $ticket_ids = array_values(array_unique(array_filter(array_map('intval', (array) ($_POST['ids'] ?? []))))); + // An asset's status, location or contact - assets of clients this agent + // can reach, with the same permission as Edit Asset (functions/asset.php) + if (in_array($field, ASSET_QUICK_FIELDS, true)) { + $asset_ids = $ticket_ids; + $allowed = lookupUserPermission('module_support') >= 2 && $asset_ids; + foreach ($allowed ? $asset_ids : [] as $id) { + $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT asset_client_id FROM assets WHERE asset_id = $id")); + if (!$row || !hasClientAccess($row['asset_client_id'])) { + $allowed = false; + break; + } + } + if (!$allowed) { + http_response_code(403); + echo json_encode(['error' => 'You cannot change that on these assets.']); + exit(); + } + + $message = ''; + $response = ['records' => []]; + foreach ($asset_ids as $id) { + [$ok, $message] = assetQuickSet($id, $field, $value); + if (!$ok) { + http_response_code(422); + echo json_encode(['error' => $message]); + exit(); + } + $response['records'][$id] = assetQuickRecord($id, $field); + } + $response['message'] = count($asset_ids) === 1 ? $message : 'Updated ' . count($asset_ids) . ' assets'; + echo json_encode($response); + exit(); + } + // A project's manager or a recurring ticket's assignee - open projects // and recurring tickets of clients this agent can reach, like their edit modals if ($field === 'project_manager' || $field === 'recurring_assignee') { diff --git a/agent/asset.php b/agent/asset.php index 4a68bc74c..a698d806e 100644 --- a/agent/asset.php +++ b/agent/asset.php @@ -29,13 +29,13 @@ enforceUserPermission('module_support'); $asset_id = intval($_GET['asset_id'] ?? 0); -$sql = mysqli_query($mysqli, "SELECT asset_archived_at, asset_contact_id, asset_created_at, asset_description, asset_favorite, asset_id, +$sql = mysqli_query($mysqli, "SELECT asset_archived_at, asset_client_id, asset_contact_id, asset_created_at, asset_description, asset_favorite, asset_id, asset_install_date, asset_location_id, asset_make, asset_model, asset_name, asset_notes, asset_os, asset_photo, asset_physical_location, asset_purchase_date, asset_purchase_reference, asset_serial, asset_status, asset_type, asset_uri, asset_uri_2, asset_uri_client, asset_vendor_id, asset_warranty_expire, client_id, client_name, contact_archived_at, contact_email, contact_extension, contact_mobile, - contact_mobile_country_code, contact_name, contact_phone, contact_phone_country_code, + contact_mobile_country_code, contact_name, contact_phone, contact_phone_country_code, contact_photo, interface_ip, interface_ipv6, interface_mac, interface_nat_ip, interface_network_id, location_archived_at, location_name, network_name, vendor_name FROM assets LEFT JOIN clients ON client_id = asset_client_id @@ -57,6 +57,7 @@ if (mysqli_num_rows($sql) == 0) { } else { $row = mysqli_fetch_assoc($sql); + $asset_row = $row; // raw, for the quick pickers - $row gets reused below $client_id = intval($row['client_id']); $client_name = escapeHtml($row['client_name']); $asset_id = intval($row['asset_id']); @@ -95,10 +96,6 @@ if (mysqli_num_rows($sql) == 0) { $vendor_name = escapeHtml($row['vendor_name']); $contact_name = escapeHtml($row['contact_name']); - $contact_email = escapeHtml($row['contact_email']); - $contact_phone = escapeHtml(formatPhoneNumber($row['contact_phone'], $row['contact_phone_country_code'])); - $contact_extension = escapeHtml($row['contact_extension']); - $contact_mobile = escapeHtml(formatPhoneNumber($row['contact_mobile'], $row['contact_mobile_country_code'])); $contact_archived = !empty($row['contact_archived_at']); $location_name = escapeHtml($row['location_name']); $location_archived = !empty($row['location_archived_at']); @@ -312,7 +309,11 @@ if (mysqli_num_rows($sql) == 0) { Archived - + + + + +
@@ -511,7 +512,9 @@ if (mysqli_num_rows($sql) == 0) {
Location
- + + + > - @@ -526,20 +529,15 @@ if (mysqli_num_rows($sql) == 0) {
Assigned
- + + + > - -
- - -
- - -
- Nobody + +
diff --git a/agent/assets.php b/agent/assets.php index fc3e4ea56..2ea142fda 100644 --- a/agent/assets.php +++ b/agent/assets.php @@ -51,7 +51,8 @@ $asset_type_tabs = [ 'server' => ['label' => 'Servers', 'icon' => 'fa-server', 'query' => "asset_type = 'Server'"], 'virtual' => ['label' => 'Virtual', 'icon' => 'fa-cloud', 'query' => "asset_type = 'Virtual Machine'"], 'network' => ['label' => 'Network', 'icon' => 'fa-network-wired', 'query' => "asset_type IN ('Firewall/Router', 'Switch', 'Access Point')"], - 'other' => ['label' => 'Other', 'icon' => 'fa-tag', 'query' => "asset_type NOT IN ('Desktop', 'Laptop', 'Server', 'Virtual Machine', 'Firewall/Router', 'Switch', 'Access Point')"], + 'printer' => ['label' => 'Printers', 'icon' => 'fa-print', 'query' => "asset_type = 'Printer'"], + 'other' => ['label' => 'Other', 'icon' => 'fa-tag', 'query' => "asset_type NOT IN ('Desktop', 'Laptop', 'Server', 'Virtual Machine', 'Firewall/Router', 'Switch', 'Access Point', 'Printer')"], ]; $type_filter = (isset($_GET['type']) && isset($asset_type_tabs[$_GET['type']])) ? $_GET['type'] : ''; $_GET['type'] = $type_filter; @@ -113,8 +114,8 @@ $show_purchase = in_array('Purchase_Date', $extra_columns, true); $show_install = in_array('Install_Date', $extra_columns, true); $show_warranty = in_array('Warranty_Expire', $extra_columns, true); -// Assigned To only means something for workstations and the like -$show_contact = !in_array($type_filter, ['network', 'server', 'other'], true); +// Assigned To only means something for workstations and the like - printers are shared +$show_contact = !in_array($type_filter, ['network', 'server', 'printer', 'other'], true); $show_model = $type_filter !== 'virtual'; // Only these sort - filter_header.php will hand through any lowercase word, and @@ -138,7 +139,8 @@ $row = mysqli_fetch_assoc(mysqli_query($mysqli, " SUM(asset_type = 'Server') AS server_count, SUM(asset_type = 'Virtual Machine') AS virtual_count, SUM(asset_type IN ('Firewall/Router', 'Switch', 'Access Point')) AS network_count, - SUM(asset_type NOT IN ('Laptop', 'Desktop', 'Server', 'Virtual Machine', 'Firewall/Router', 'Switch', 'Access Point')) AS other_count + SUM(asset_type = 'Printer') AS printer_count, + SUM(asset_type NOT IN ('Laptop', 'Desktop', 'Server', 'Virtual Machine', 'Firewall/Router', 'Switch', 'Access Point', 'Printer')) AS other_count FROM assets LEFT JOIN clients ON client_id = asset_client_id WHERE $archive_query @@ -152,16 +154,17 @@ $tab_counts = [ 'server' => intval($row['server_count']), 'virtual' => intval($row['virtual_count']), 'network' => intval($row['network_count']), + 'printer' => intval($row['printer_count']), 'other' => intval($row['other_count']), ]; $sql = mysqli_query( $mysqli, - "SELECT SQL_CALC_FOUND_ROWS asset_archived_at, asset_contact_id, asset_description, asset_favorite, - asset_id, asset_install_date, asset_make, asset_model, asset_name, asset_os, asset_physical_location, + "SELECT SQL_CALC_FOUND_ROWS asset_archived_at, asset_client_id, asset_contact_id, asset_description, asset_favorite, + asset_id, asset_install_date, asset_location_id, asset_make, asset_model, asset_name, asset_os, asset_physical_location, asset_purchase_date, asset_serial, asset_status, asset_type, asset_uri, asset_uri_2, asset_uri_client, asset_warranty_expire, client_id, client_name, - contact_archived_at, contact_name, interface_ip, interface_ipv6, interface_mac, + contact_archived_at, contact_name, contact_photo, interface_ip, interface_ipv6, interface_mac, location_archived_at, location_name FROM assets LEFT JOIN clients ON asset_client_id = client_id LEFT JOIN contacts ON asset_contact_id = contact_id @@ -653,7 +656,9 @@ $search_noun = $type_filter ? $asset_type_tabs[$type_filter]['label'] : 'assets' - + + + > - @@ -661,21 +666,29 @@ $search_noun = $type_filter ? $asset_type_tabs[$type_filter]['label'] : 'assets' - + + +
>
- -
+
- + · - -' ?> + + + + + -' ?> + + diff --git a/agent/modals/asset/asset.php b/agent/modals/asset/asset.php index 2684fa00d..0d0f6a661 100644 --- a/agent/modals/asset/asset.php +++ b/agent/modals/asset/asset.php @@ -1,21 +1,29 @@ 'That asset no longer exists.']); + exit; +} -$client_id = intval($row['client_id']); +$client_id = intval($asset_row['asset_client_id']); enforceClientAccess(); -$client_name = escapeHtml($row['client_name']); -$asset_id = intval($row['asset_id']); -$asset_type = escapeHtml($row['asset_type']); -$asset_name = escapeHtml($row['asset_name']); -$asset_description = escapeHtml($row['asset_description']); -$asset_make = escapeHtml($row['asset_make']); -$asset_model = escapeHtml($row['asset_model']); -$asset_serial = escapeHtml($row['asset_serial']); -$asset_os = escapeHtml($row['asset_os']); -$asset_uri = escapeUrl($row['asset_uri']); -$asset_uri_2 = escapeUrl($row['asset_uri_2']); -$asset_uri_client = escapeUrl($row['asset_uri_client']); -$asset_status = escapeHtml($row['asset_status']); -$asset_purchase_reference = escapeHtml($row['asset_purchase_reference']); -$asset_purchase_date = escapeHtml($row['asset_purchase_date']); -$asset_warranty_expire = escapeHtml($row['asset_warranty_expire']); -$asset_install_date = escapeHtml($row['asset_install_date']); -$asset_photo = escapeHtml($row['asset_photo']); -$asset_physical_location = escapeHtml($row['asset_physical_location']); -$asset_notes = escapeHtml($row['asset_notes']); -$asset_favorite = intval($row['asset_favorite']); -$asset_created_at = escapeHtml($row['asset_created_at']); -$asset_vendor_id = intval($row['asset_vendor_id']); -$asset_location_id = intval($row['asset_location_id']); -$asset_contact_id = intval($row['asset_contact_id']); +$can_edit = lookupUserPermission('module_support') >= 2; +$can_credentials = lookupUserPermission('module_credential') >= 1; -$asset_ip = escapeHtml($row['interface_ip']); -$asset_ipv6 = escapeHtml($row['interface_ipv6']); -$asset_nat_ip = escapeHtml($row['interface_nat_ip']); -$asset_mac = escapeHtml($row['interface_mac']); -$asset_network_id = intval($row['interface_network_id']); - -$device_icon = getAssetIcon($asset_type); - -$contact_name = escapeHtml($row['contact_name']); -$contact_email = escapeHtml($row['contact_email']); -$contact_phone_country_code = escapeHtml($row['contact_phone_country_code']); -$contact_phone = escapeHtml(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code)); -$contact_extension = escapeHtml($row['contact_extension']); -$contact_mobile_country_code = escapeHtml($row['contact_mobile_country_code']); -$contact_mobile = escapeHtml(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code)); -$contact_archived_at = escapeHtml($row['contact_archived_at']); -if ($contact_archived_at) { - $contact_name_display = "$contact_name"; -} else { - $contact_name_display = $contact_name; -} -$location_name = escapeHtml($row['location_name']); -if (empty($location_name)) { - $location_name = "-"; -} -$location_archived_at = escapeHtml($row['location_archived_at']); -if ($location_archived_at) { - $location_name_display = "$location_name"; -} else { - $location_name_display = $location_name; -} +$asset_name = escapeHtml($asset_row['asset_name']); +$asset_type = escapeHtml($asset_row['asset_type']); +$asset_description = escapeHtml($asset_row['asset_description']); +$asset_make_model = escapeHtml(trim($asset_row['asset_make'] . ' ' . $asset_row['asset_model'])); +$asset_os = escapeHtml($asset_row['asset_os']); +$asset_os_icon = assetOsIcon($asset_row['asset_os']); +$asset_serial = escapeHtml($asset_row['asset_serial']); +$asset_ip = escapeHtml($asset_row['interface_ip']); +$asset_mac = escapeHtml($asset_row['interface_mac']); +$asset_links = assetLinks($asset_row['asset_uri'], $asset_row['asset_uri_2'], $asset_row['asset_uri_client']); +$asset_warranty = assetWarranty($asset_row['asset_warranty_expire']); +$asset_photo = escapeHtml($asset_row['asset_photo']); +$asset_physical_location = escapeHtml($asset_row['asset_physical_location']); +$asset_notes = escapeHtml($asset_row['asset_notes']); +$asset_favorite = intval($asset_row['asset_favorite']); +$asset_archived = !empty($asset_row['asset_archived_at']); +$asset_contact_id = intval($asset_row['asset_contact_id']); +$asset_tone = assetTypeTone($asset_row['asset_type']); +$device_icon = getAssetIcon($asset_row['asset_type']); +$asset_tags_display = tagPills('asset', $asset_id, tagsForRecord('asset', $asset_id), "assets.php?client_id=$client_id&"); // The rack it sits in, if any $asset_rack = rackPositionForAsset($asset_id); -if ($asset_rack) { - $asset_rack_id = intval($asset_rack['rack_id']); - $asset_rack_name = escapeHtml($asset_rack['rack_name']); - $asset_rack_position = rackPositionLabel($asset_rack['unit_start_number'], $asset_rack['unit_end_number']) . ', ' . ($asset_rack['unit_face'] === 'rear' ? 'rear' : 'front'); -} -// Tags - many to many relationship -// Tags - functions/tags.php -$asset_tags_display = tagPills('asset', $asset_id, tagsForRecord('asset', $asset_id), "assets.php?client_id=$client_id&"); - -// Network Interfaces +// Interfaces, primary first, and what each one is plugged into $sql_related_interfaces = mysqli_query($mysqli, " - SELECT - ai.interface_id, - ai.interface_name, - ai.interface_description, - ai.interface_type, - ai.interface_mac, - ai.interface_ip, - ai.interface_nat_ip, - ai.interface_ipv6, - ai.interface_primary, - ai.interface_notes, - n.network_name, - n.network_id, - connected_interfaces.interface_id AS connected_interface_id, + SELECT ai.interface_id, ai.interface_name, ai.interface_mac, ai.interface_ip, ai.interface_primary, connected_interfaces.interface_name AS connected_interface_name, connected_assets.asset_name AS connected_asset_name, connected_assets.asset_id AS connected_asset_id, connected_assets.asset_type AS connected_asset_type FROM asset_interfaces AS ai - LEFT JOIN networks AS n - ON n.network_id = ai.interface_network_id LEFT JOIN asset_interface_links AS ail ON (ail.interface_a_id = ai.interface_id OR ail.interface_b_id = ai.interface_id) LEFT JOIN asset_interfaces AS connected_interfaces @@ -132,849 +86,494 @@ $sql_related_interfaces = mysqli_query($mysqli, " ) LEFT JOIN assets AS connected_assets ON connected_assets.asset_id = connected_interfaces.interface_asset_id - WHERE - ai.interface_asset_id = $asset_id - AND ai.interface_archived_at IS NULL - ORDER BY ai.interface_name ASC + WHERE ai.interface_asset_id = $asset_id + AND ai.interface_archived_at IS NULL + ORDER BY ai.interface_primary DESC, ai.interface_name ASC "); $interface_count = mysqli_num_rows($sql_related_interfaces); -// Related Credentials Query -$sql_related_credentials = mysqli_query($mysqli, " - SELECT - credentials.credential_id AS credential_id, - credentials.credential_name, - credentials.credential_description, - credentials.credential_uri, - credentials.credential_username, - credentials.credential_password, - credentials.credential_otp_secret, - credentials.credential_note, - credentials.credential_favorite, - credentials.credential_contact_id, - credentials.credential_asset_id - FROM credentials - WHERE credential_asset_id = $asset_id - AND credential_archived_at IS NULL - GROUP BY credentials.credential_id - ORDER BY credential_name DESC -"); -// No module_credential, no Credentials tab - the pane below was already gated, the tab wasn't -$credential_count = lookupUserPermission('module_credential') ? mysqli_num_rows($sql_related_credentials) : 0; +// Credentials - only for agents who may see them +$credential_count = 0; +if ($can_credentials) { + $sql_related_credentials = mysqli_query($mysqli, " + SELECT credential_id, credential_name, credential_uri, credential_username, credential_otp_secret + FROM credentials + WHERE credential_asset_id = $asset_id + AND credential_archived_at IS NULL + ORDER BY credential_name ASC + "); + $credential_count = mysqli_num_rows($sql_related_credentials); +} -// Related Tickets Query +// Tickets - open ones first; the most recent few here, the rest on the asset page +$quick_ticket_limit = 8; $sql_related_tickets = mysqli_query($mysqli, " - SELECT tickets.ticket_id, ticket_prefix, ticket_number, ticket_subject, ticket_priority, ticket_created_at, - ticket_updated_at, ticket_closed_at, ticket_assigned_to, user_name, user_avatar, - ticket_status_id, ticket_status_name, ticket_status_color + SELECT tickets.ticket_id, ticket_prefix, ticket_number, ticket_subject, ticket_updated_at, ticket_created_at, + ticket_resolved_at, ticket_closed_at, ticket_assigned_to, user_name, user_avatar, + ticket_status_name, ticket_status_color FROM tickets LEFT JOIN users ON ticket_assigned_to = user_id LEFT JOIN ticket_statuses ON ticket_status_id = ticket_status LEFT JOIN ticket_assets ON tickets.ticket_id = ticket_assets.ticket_id WHERE ticket_asset_id = $asset_id OR ticket_assets.asset_id = $asset_id GROUP BY tickets.ticket_id - ORDER BY ticket_number DESC + ORDER BY (ticket_resolved_at IS NULL AND ticket_closed_at IS NULL) DESC, ticket_number DESC "); $ticket_count = mysqli_num_rows($sql_related_tickets); +$ticket_open_count = 0; +$related_tickets = []; +while ($row = mysqli_fetch_assoc($sql_related_tickets)) { + $is_open = empty($row['ticket_resolved_at']) && empty($row['ticket_closed_at']); + $ticket_open_count += $is_open ? 1 : 0; + if (count($related_tickets) < $quick_ticket_limit) { + $related_tickets[] = $row + ['is_open' => $is_open]; + } +} -// Related Recurring Tickets Query -$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT recurring_ticket_frequency, recurring_ticket_assets.recurring_ticket_id, - recurring_ticket_next_run, recurring_ticket_priority, recurring_ticket_subject FROM recurring_tickets +// Recurring tickets +$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT recurring_tickets.recurring_ticket_id, recurring_ticket_subject, + recurring_ticket_frequency, recurring_ticket_next_run + FROM recurring_tickets LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id GROUP BY recurring_tickets.recurring_ticket_id - ORDER BY recurring_ticket_next_run DESC" + ORDER BY recurring_ticket_next_run ASC" ); $recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets); -// Related Documents -$sql_related_documents = mysqli_query($mysqli, "SELECT document_created_at, document_description, documents.document_id, document_name, - document_updated_at, user_name FROM asset_documents - LEFT JOIN documents ON asset_documents.document_id = documents.document_id - LEFT JOIN users ON user_id = document_created_by +// Licenses, with seats in use counted in the same query +$sql_related_software = mysqli_query($mysqli, "SELECT software_assets.software_id, software_name, software_version, software_seats, + (SELECT COUNT(*) FROM software_assets AS sa WHERE sa.software_id = software.software_id) + + (SELECT COUNT(*) FROM software_contacts AS sc WHERE sc.software_id = software.software_id) AS seats_used + FROM software_assets + LEFT JOIN software ON software_assets.software_id = software.software_id + WHERE software_assets.asset_id = $asset_id + AND software_archived_at IS NULL + ORDER BY software_name ASC" +); +$software_count = mysqli_num_rows($sql_related_software); + +// Documents +$sql_related_documents = mysqli_query($mysqli, "SELECT documents.document_id, document_name, document_created_at, document_updated_at + FROM asset_documents + JOIN documents ON asset_documents.document_id = documents.document_id WHERE asset_documents.asset_id = $asset_id - AND document_archived_at IS NULL - ORDER BY document_name DESC" + AND document_archived_at IS NULL + ORDER BY document_name ASC" ); $document_count = mysqli_num_rows($sql_related_documents); -// Related Files -$sql_related_files = mysqli_query($mysqli, "SELECT file_created_at, file_description, file_ext, files.file_id, file_mime_type, file_name FROM asset_files - LEFT JOIN files ON asset_files.file_id = files.file_id +// Files +$sql_related_files = mysqli_query($mysqli, "SELECT files.file_id, file_name, file_ext, file_created_at + FROM asset_files + JOIN files ON asset_files.file_id = files.file_id WHERE asset_files.asset_id = $asset_id - AND file_archived_at IS NULL - ORDER BY file_name DESC" + AND file_archived_at IS NULL + ORDER BY file_name ASC" ); $file_count = mysqli_num_rows($sql_related_files); -// Related Software Query -$sql_related_software = mysqli_query( - $mysqli, - "SELECT software_expire, software_assets.software_id, software_key, software_license_type, - software_name, software_notes, software_purchase, software_seats, software_type, - software_version FROM software_assets - LEFT JOIN software ON software_assets.software_id = software.software_id - WHERE software_assets.asset_id = $asset_id - AND software_archived_at IS NULL - ORDER BY software_name DESC" -); - -$software_count = mysqli_num_rows($sql_related_software); - -// Related Notes +// Notes $sql_related_notes = mysqli_query($mysqli, "SELECT asset_note, asset_note_created_at, asset_note_type, user_name FROM asset_notes LEFT JOIN users ON asset_note_created_by = user_id WHERE asset_note_asset_id = $asset_id - AND asset_note_archived_at IS NULL + AND asset_note_archived_at IS NULL ORDER BY asset_note_created_at DESC" ); $note_count = mysqli_num_rows($sql_related_notes); - -// Note type icons, read from the categories list -$note_type_icons = array(); +$note_type_icons = []; $sql_note_type_icons = mysqli_query($mysqli, "SELECT category_name, category_icon FROM categories WHERE category_type = 'asset_note_type'"); while ($row = mysqli_fetch_assoc($sql_note_type_icons)) { - $note_type_icons[escapeHtml($row['category_name'])] = escapeHtml($row['category_icon']); + $note_type_icons[$row['category_name']] = escapeHtml($row['category_icon']); } -if (isset($_GET['client_id'])) { - $client_url = "client_id=$client_id&"; -} else { - $client_url = ''; -} +// Only the tabs with something in them - same order as the asset page +$quick_tabs = array_filter([ + 'interfaces' => ['label' => 'Interfaces', 'count' => $interface_count], + 'credentials' => ['label' => 'Credentials', 'count' => $credential_count], + 'tickets' => ['label' => 'Tickets', 'count' => $ticket_count, 'badge' => $ticket_open_count], + 'recurring' => ['label' => 'Recurring', 'count' => $recurring_ticket_count], + 'licenses' => ['label' => 'Licenses', 'count' => $software_count], + 'documents' => ['label' => 'Documents', 'count' => $document_count], + 'files' => ['label' => 'Files', 'count' => $file_count], + 'notes' => ['label' => 'Notes', 'count' => $note_count], +], function ($tab) { + return $tab['count'] > 0; +}); +$first_tab = array_key_first($quick_tabs); + +$has_left = $asset_ip || $asset_mac || $asset_serial || $asset_warranty; +$has_right = $can_edit || $asset_row['location_name'] || $asset_row['contact_name'] || $asset_rack; ob_start(); ?> -