diff --git a/agent/client_overview.php b/agent/client_overview.php index 50d3b6499..3032b5163 100644 --- a/agent/client_overview.php +++ b/agent/client_overview.php @@ -354,14 +354,25 @@ $money_format = function ($amount) use ($currency_format, $client_currency_code,
'key', 'Document' => 'file-alt', 'File' => 'paperclip'][$item['item_type']] ?? 'share-square'; $item_views = intval($item['item_views']); $item_limit = intval($item['item_view_limit']); + $item_related_id = intval($item['item_related_id']); + $item_label = escapeHtml($item['item_name'] ?: $item['item_type']); + // Documents and files look and open as they do everywhere else + if ($item['item_type'] === 'Document') { + $item_tile = documentTile('sm'); + $item_label = "$item_label"; + } elseif ($item['item_type'] === 'File') { + $item_tile = fileTypeTile($item['file_ext'], 'sm'); + $item_label = "$item_label"; + } else { + $item_tile = ''; + } ?>
- + - + view, expires diff --git a/agent/global_search.php b/agent/global_search.php index a477954b1..d46e15c85 100644 --- a/agent/global_search.php +++ b/agent/global_search.php @@ -163,6 +163,9 @@ function searchResultBadge($badge) { $item_url = escapeHtml($item['url']); ?>
+ + +
-
    - -
  • - - -
  • + +
@@ -490,12 +475,10 @@ ob_start();
-
    - -
  • - - -
  • + +
diff --git a/agent/modals/asset/asset_documents.php b/agent/modals/asset/asset_documents.php deleted file mode 100644 index 410dfe2c0..000000000 --- a/agent/modals/asset/asset_documents.php +++ /dev/null @@ -1,27 +0,0 @@ - diff --git a/agent/modals/contact/contact.php b/agent/modals/contact/contact.php index c294fc106..3de111d65 100644 --- a/agent/modals/contact/contact.php +++ b/agent/modals/contact/contact.php @@ -124,24 +124,12 @@ $sql_linked_software = mysqli_query($mysqli, "SELECT software.software_id, softw $software_count = mysqli_num_rows($sql_linked_software); // Documents -$sql_linked_documents = mysqli_query($mysqli, "SELECT documents.document_id, document_name, document_created_at, document_updated_at - FROM contact_documents - JOIN documents ON documents.document_id = contact_documents.document_id - WHERE contact_documents.contact_id = $contact_id - AND document_archived_at IS NULL - ORDER BY document_name ASC" -); -$document_count = mysqli_num_rows($sql_linked_documents); +$linked_documents = linkedRecords('contact', $contact_id, 'document'); +$document_count = count($linked_documents); // Files -$sql_linked_files = mysqli_query($mysqli, "SELECT files.file_id, file_name, file_ext, file_created_at - FROM contact_files - JOIN files ON files.file_id = contact_files.file_id - WHERE contact_files.contact_id = $contact_id - AND file_archived_at IS NULL - ORDER BY file_name ASC" -); -$file_count = mysqli_num_rows($sql_linked_files); +$linked_files = linkedRecords('contact', $contact_id, 'file'); +$file_count = count($linked_files); // Notes $sql_related_notes = mysqli_query($mysqli, "SELECT contact_note, contact_note_created_at, contact_note_type, user_name FROM contact_notes @@ -399,13 +387,10 @@ ob_start();
-
    - -
  • - - -
  • + +
@@ -413,12 +398,10 @@ ob_start();
-
    - -
  • - - -
  • + +
diff --git a/agent/modals/service/service.php b/agent/modals/service/service.php index 2c686be0a..c54b26353 100644 --- a/agent/modals/service/service.php +++ b/agent/modals/service/service.php @@ -89,9 +89,11 @@ $sql_contacts = mysqli_query( // Associated Documents $sql_docs = mysqli_query( $mysqli, - "SELECT documents.document_id, document_name FROM service_documents - LEFT JOIN documents ON service_documents.document_id = documents.document_id - WHERE service_id = $service_id" + "SELECT documents.document_id AS id, document_name AS name, document_description, document_created_at, document_updated_at + FROM service_documents + JOIN documents ON service_documents.document_id = documents.document_id + WHERE service_id = $service_id AND document_archived_at IS NULL + ORDER BY document_name ASC" ); ob_start(); @@ -297,12 +299,11 @@ ob_start(); 0) { - echo "
Documents
    "; + // The same rows as a document's Linked card + echo "
    Documents
    "; } diff --git a/agent/modals/service/service_add.php b/agent/modals/service/service_add.php index d332fb772..90dcf4cd5 100644 --- a/agent/modals/service/service_add.php +++ b/agent/modals/service/service_add.php @@ -152,11 +152,11 @@ ob_start(); diff --git a/agent/modals/service/service_edit.php b/agent/modals/service/service_edit.php index ea92ecc3f..5665ed797 100644 --- a/agent/modals/service/service_edit.php +++ b/agent/modals/service/service_edit.php @@ -224,18 +224,12 @@ ob_start(); $document_name"; - } - else{ - echo ""; - } - + $document_selected = in_array($document_id, $selected_ids) ? ' selected' : ''; + echo ""; } ?> diff --git a/agent/quote.php b/agent/quote.php index a90f2e5de..e45fc92d8 100644 --- a/agent/quote.php +++ b/agent/quote.php @@ -133,7 +133,7 @@ if (isset($_GET['quote_id'])) { // Quote File Attachments $sql_quote_files = mysqli_query( $mysqli, - "SELECT file_reference_name, file_name, file_created_at FROM quote_files LEFT JOIN files ON quote_files.file_id = files.file_id WHERE quote_id = $quote_id" + "SELECT files.file_id, file_name, file_ext, file_size, file_created_at FROM quote_files JOIN files ON quote_files.file_id = files.file_id WHERE quote_id = $quote_id AND file_archived_at IS NULL ORDER BY file_name ASC" ); ?> @@ -526,30 +526,31 @@ if (isset($_GET['quote_id'])) {
- - + +
+ - - + + + - + - - + + + - - +
File NameUpload dateFileUploaded
+
+ + + +
+
diff --git a/agent/ticket.php b/agent/ticket.php index 28aa1f3d9..19b565a2b 100644 --- a/agent/ticket.php +++ b/agent/ticket.php @@ -639,7 +639,7 @@ if (isset($_GET['ticket_id'])) { $ticket_attachment_name = escapeHtml($ticket_attachment['ticket_attachment_name']); ?>
- + View Download = 3) { ?> @@ -932,7 +932,7 @@ if (isset($_GET['ticket_id'])) { $ticket_attachment_name = escapeHtml($ticket_attachment['ticket_attachment_name']); ?>
- + View Download = 3) { ?> diff --git a/client/documents.php b/client/documents.php index 2a62db22b..258d92302 100644 --- a/client/documents.php +++ b/client/documents.php @@ -10,7 +10,7 @@ require_once "includes/inc_all.php"; enforceContactCan('itdoc'); -$documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, document_created_at, folder_name FROM documents LEFT JOIN folders ON document_folder_id = folder_id WHERE document_client_visible = 1 AND document_client_id = $session_client_id AND document_archived_at IS NULL ORDER BY folder_id, document_name DESC"); +$documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, document_description, document_created_at, document_updated_at, folder_name FROM documents LEFT JOIN folders ON document_folder_id = folder_id WHERE document_client_visible = 1 AND document_client_id = $session_client_id AND document_archived_at IS NULL ORDER BY folder_id, document_name DESC"); ?>
@@ -34,11 +34,11 @@ $documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, docum - +
- + @@ -49,23 +49,25 @@ $documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, docum $document_id = intval($row['document_id']); $folder_name = escapeHtml($row['folder_name']); $document_name = escapeHtml($row['document_name']); - $document_created_at = escapeHtml($row['document_created_at']); + $document_updated_at = $row['document_updated_at'] ?: $row['document_created_at']; ?> - +
NameCreatedUpdated Actions
- - - - +
+ +
+ +
+ + · + +
+
+
diff --git a/css/itflow_custom.css b/css/itflow_custom.css index b1a5b39cd..5b8b4422c 100644 --- a/css/itflow_custom.css +++ b/css/itflow_custom.css @@ -4017,6 +4017,12 @@ img.itflow-contact-avatar { border-radius: var(--bs-border-radius); font-size: .8rem; } +.itflow-file-icon-xs { + width: 1.25rem; + height: 1.25rem; + border-radius: var(--bs-border-radius-sm); + font-size: .65rem; +} .itflow-file-icon-lg { width: 3.5rem; height: 3.5rem; @@ -4451,3 +4457,9 @@ img.itflow-contact-avatar { box-shadow: none; } } +/* In a quick look's tabs the rows sit flush with the pane, like its other lists */ +.itflow-asset-quick-related .itflow-link-row { + margin: 0; + padding-left: 0; + padding-right: 0; +} diff --git a/functions/client_overview.php b/functions/client_overview.php index 703cd4fd4..a84e0705d 100644 --- a/functions/client_overview.php +++ b/functions/client_overview.php @@ -340,7 +340,7 @@ function clientOverviewSharedItems($client_id) { global $mysqli; $sql = mysqli_query($mysqli, "SELECT item_id, item_type, item_related_id, item_recipient, item_views, item_view_limit, item_expire_at, - COALESCE(credential_name, document_name, file_name) AS item_name + COALESCE(credential_name, document_name, file_name) AS item_name, file_ext FROM shared_items LEFT JOIN credentials ON item_type = 'Credential' AND credential_id = item_related_id AND credential_client_id = $client_id LEFT JOIN documents ON item_type = 'Document' AND document_id = item_related_id AND document_client_id = $client_id diff --git a/functions/search.php b/functions/search.php index 1b47f796f..be674f416 100644 --- a/functions/search.php +++ b/functions/search.php @@ -271,13 +271,14 @@ function globalSearchGroups($terms, $deep) { 'subtitle' => $row['document_description'], 'context' => $row['client_name'], 'url' => globalSearchClientUrl('document.php', $row['document_client_id'], ['document_id' => intval($row['document_id'])]), + 'tile' => ['tone' => 'document', 'icon' => 'file-alt', 'label' => 'Document'], ]; }, ]; $groups[] = [ 'key' => 'files', 'label' => 'Files', 'icon' => 'paperclip', 'module' => 'module_support', - 'select' => 'file_id, file_name, file_description, file_client_id, file_folder_id, client_name, folder_name', + 'select' => 'file_id, file_name, file_ext, file_description, file_client_id, file_folder_id, client_name, folder_name', 'from' => 'files LEFT JOIN clients ON file_client_id = client_id LEFT JOIN folders ON file_folder_id = folder_id', @@ -290,7 +291,9 @@ function globalSearchGroups($terms, $deep) { 'title' => $row['file_name'], 'subtitle' => implode(' · ', array_filter([$row['folder_name'], $row['file_description']])), 'context' => $row['client_name'], - 'url' => globalSearchClientUrl('files.php', $row['file_client_id'], ['folder_id' => intval($row['file_folder_id'])]), + // Its folder, narrowed to it - one click from its quick look + 'url' => globalSearchClientUrl('files.php', $row['file_client_id'], ['folder_id' => intval($row['file_folder_id']), 'q' => $row['file_name']]), + 'tile' => ['tone' => fileTypeInfo($row['file_ext'])['tone'], 'icon' => fileTypeInfo($row['file_ext'])['icon'], 'label' => fileTypeInfo($row['file_ext'])['label']], ]; }, ]; diff --git a/js/global_search.js b/js/global_search.js index adffd4aef..ccb34f537 100644 --- a/js/global_search.js +++ b/js/global_search.js @@ -36,6 +36,7 @@ const CACHE_SIZE = 50; const BADGE_VARIANTS = ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']; const AVATAR_TONES = ['primary', 'success', 'info', 'warning', 'secondary']; + const FILE_TONES = ['pdf', 'word', 'excel', 'slides', 'image', 'media', 'archive', 'text', 'code', 'drawing', 'cert', 'other', 'document']; const MOD_KEY = /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || '') ? '⌘' : 'Ctrl'; let modalEl = null; @@ -138,6 +139,18 @@ return node; } + // A file's type tile, or a document's - fileTypeTile() draws the same server side + function tile(spec) { + if (!spec || FILE_TONES.indexOf(spec.tone) === -1 || !/^[a-z0-9-]+$/.test(spec.icon || '')) { + return null; + } + const node = el('span', 'itflow-file-icon itflow-file-icon-xs itflow-file-tone-' + spec.tone); + node.title = spec.label || ''; + node.setAttribute('aria-hidden', 'true'); + node.appendChild(el('i', 'fas fa-fw fa-' + spec.icon)); + return node; + } + function badge(spec) { if (!spec || !spec.text) { return null; @@ -178,7 +191,7 @@ body.append(sub); } - link.append(avatar(parts.avatar) || icon(iconName, 'itflow-search-item-icon'), body); + link.append(avatar(parts.avatar) || tile(parts.tile) || icon(iconName, 'itflow-search-item-icon'), body); const status = badge(parts.badge); if (status || parts.context) {