mirror of
https://github.com/itflow-org/itflow
synced 2026-11-11 07:01:16 +00:00
Files and documents everywhere else: asset and contact quick looks list their documents and files with the same tiles and rows as the document page, files opening their quick look instead of a raw download; client overview share links show document and file tiles and open the document page or file quick look; service quick look shows linked documents as tiles and leaves out archived ones, service add and edit document pickers carry an icon and summary; global search shows file and document type tiles in the palette and on the results page, and a file result opens its folder narrowed to that file; quote attachments show their tile and size, open the file quick look and download through file.php instead of linking straight into the uploads folder; ticket attachments show their file type tile; client portal documents list shows the document tile, folder and summary with the last updated date; removed unused modals/asset/asset_documents.php
This commit is contained in:
@@ -354,14 +354,25 @@ $money_format = function ($amount) use ($currency_format, $client_currency_code,
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<?php foreach ($shared_items as $item) {
|
||||
$item_icon = ['Credential' => '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 = "<a href=\"document.php?client_id=$client_id&document_id=$item_related_id\">$item_label</a>";
|
||||
} elseif ($item['item_type'] === 'File') {
|
||||
$item_tile = fileTypeTile($item['file_ext'], 'sm');
|
||||
$item_label = "<a class=\"ajax-modal\" href=\"#\" data-modal-size=\"lg\" data-modal-url=\"modals/file/file.php?id=$item_related_id\">$item_label</a>";
|
||||
} else {
|
||||
$item_tile = '<span class="itflow-link-icon" title="' . escapeHtml($item['item_type']) . '" aria-hidden="true"><i class="fas fa-fw fa-' . ($item['item_type'] === 'Credential' ? 'key' : 'share-square') . '"></i></span>';
|
||||
}
|
||||
?>
|
||||
<div class="list-group-item d-flex align-items-center gap-2 py-2">
|
||||
<i class="fas fa-fw fa-<?= $item_icon ?> text-body-secondary" title="<?= escapeHtml($item['item_type']) ?>"></i>
|
||||
<?= $item_tile ?>
|
||||
<span class="flex-grow-1 overflow-hidden">
|
||||
<span class="d-block text-truncate"><?= escapeHtml($item['item_name'] ?: $item['item_type']) ?></span>
|
||||
<span class="d-block text-truncate"><?= $item_label ?></span>
|
||||
<span class="d-block small text-body-secondary text-truncate">
|
||||
<?= $item['item_recipient'] ? escapeHtml($item['item_recipient']) . ', ' : '' ?><?= $item_views ?><?= $item_limit ? " of $item_limit" : '' ?> view<?= ($item_limit ?: $item_views) === 1 ? '' : 's' ?>, expires <?= escapeHtml(timeAgo($item['item_expire_at'])) ?>
|
||||
</span>
|
||||
|
||||
@@ -163,6 +163,9 @@ function searchResultBadge($badge) {
|
||||
$item_url = escapeHtml($item['url']);
|
||||
?>
|
||||
<div class="list-group-item d-flex align-items-center gap-3 py-2">
|
||||
<?php if (!empty($item['tile']) && preg_match('/^[a-z]+$/', $item['tile']['tone']) && preg_match('/^[a-z0-9-]+$/', $item['tile']['icon'])) { ?>
|
||||
<span class="itflow-file-icon itflow-file-icon-sm itflow-file-tone-<?= $item['tile']['tone'] ?>" title="<?= escapeHtml($item['tile']['label']) ?>" aria-hidden="true"><i class="fas fa-fw fa-<?= $item['tile']['icon'] ?>"></i></span>
|
||||
<?php } ?>
|
||||
<?php if (!empty($item['avatar'])) {
|
||||
// A contact - their avatar, as everywhere else they appear
|
||||
$avatar = $item['avatar'];
|
||||
|
||||
@@ -154,24 +154,12 @@ $sql_related_software = mysqli_query($mysqli, "SELECT software_assets.software_i
|
||||
$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 ASC"
|
||||
);
|
||||
$document_count = mysqli_num_rows($sql_related_documents);
|
||||
$linked_documents = linkedRecords('asset', $asset_id, 'document');
|
||||
$document_count = count($linked_documents);
|
||||
|
||||
// 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 ASC"
|
||||
);
|
||||
$file_count = mysqli_num_rows($sql_related_files);
|
||||
$linked_files = linkedRecords('asset', $asset_id, 'file');
|
||||
$file_count = count($linked_files);
|
||||
|
||||
// Notes
|
||||
$sql_related_notes = mysqli_query($mysqli, "SELECT asset_note, asset_note_created_at, asset_note_type, user_name FROM asset_notes
|
||||
@@ -476,13 +464,10 @@ ob_start();
|
||||
|
||||
<?php if ($document_count) { ?>
|
||||
<div class="tab-pane fade <?= $first_tab === 'documents' ? 'show active' : '' ?>" id="asset-quick-<?= $asset_id ?>-documents" role="tabpanel">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php while ($row = mysqli_fetch_assoc($sql_related_documents)) {
|
||||
$document_last = $row['document_updated_at'] ?: $row['document_created_at']; ?>
|
||||
<li class="list-group-item px-0 d-flex justify-content-between gap-3">
|
||||
<a class="ajax-modal" href="#" data-modal-size="lg" data-modal-url="modals/document/document_view.php?id=<?= intval($row['document_id']) ?>"><i class="fas fa-fw fa-file-alt text-secondary me-2"></i><?= escapeHtml($row['document_name']) ?></a>
|
||||
<span class="small text-body-secondary text-nowrap" title="<?= escapeHtml($document_last) ?>"><?= timeAgo($document_last) ?></span>
|
||||
</li>
|
||||
<!-- The same rows as a document's Linked card - tile, name, when it changed -->
|
||||
<ul class="list-unstyled mb-0 itflow-links">
|
||||
<?php foreach ($linked_documents as $row) { ?>
|
||||
<li class="itflow-link-row"><?= linkRowHtml('document', $row, $client_id) ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -490,12 +475,10 @@ ob_start();
|
||||
|
||||
<?php if ($file_count) { ?>
|
||||
<div class="tab-pane fade <?= $first_tab === 'files' ? 'show active' : '' ?>" id="asset-quick-<?= $asset_id ?>-files" role="tabpanel">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php while ($row = mysqli_fetch_assoc($sql_related_files)) { ?>
|
||||
<li class="list-group-item px-0 d-flex justify-content-between gap-3">
|
||||
<a href="file.php?file_id=<?= intval($row['file_id']) ?>&action=view" target="_blank" rel="noopener"><i class="fas fa-fw fa-<?= getFileIcon((string) $row['file_ext']) ?> text-secondary me-2"></i><?= escapeHtml($row['file_name']) ?></a>
|
||||
<span class="small text-body-secondary text-nowrap" title="<?= escapeHtml($row['file_created_at']) ?>"><?= timeAgo($row['file_created_at']) ?></span>
|
||||
</li>
|
||||
<!-- Each opens its quick look - preview, details, what else it is linked to -->
|
||||
<ul class="list-unstyled mb-0 itflow-links">
|
||||
<?php foreach ($linked_files as $row) { ?>
|
||||
<li class="itflow-link-row"><?= linkRowHtml('file', $row, $client_id) ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<div class="modal" id="assetDocumentsModal<?= $asset_id ?>" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-<?= $device_icon ?> me-2"></i><?= $asset_name ?> Documents</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<?php
|
||||
while ($row = mysqli_fetch_assoc($sql_related_documents)) {
|
||||
$related_document_id = intval($row['document_id']);
|
||||
$related_document_name = escapeHtml($row['document_name']);
|
||||
?>
|
||||
<p>
|
||||
<i class="fas fa-fw fa-document text-secondary"></i>
|
||||
<?= $related_document_name ?> <a href="client_documents.php?q=<?= $related_document_name ?>"><?= $related_document_name ?></a>
|
||||
</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><i class="fa fa-times me-2"></i>Cancel</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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();
|
||||
|
||||
<?php if ($document_count) { ?>
|
||||
<div class="tab-pane fade <?= $first_tab === 'documents' ? 'show active' : '' ?>" id="contact-quick-<?= $contact_id ?>-documents" role="tabpanel">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php while ($row = mysqli_fetch_assoc($sql_linked_documents)) {
|
||||
$document_last = $row['document_updated_at'] ?: $row['document_created_at']; ?>
|
||||
<li class="list-group-item px-0 d-flex justify-content-between gap-3">
|
||||
<a class="ajax-modal" href="#" data-modal-size="lg" data-modal-url="modals/document/document_view.php?id=<?= intval($row['document_id']) ?>"><i class="fas fa-fw fa-file-alt text-secondary me-2"></i><?= escapeHtml($row['document_name']) ?></a>
|
||||
<span class="small text-body-secondary text-nowrap" title="<?= escapeHtml($document_last) ?>"><?= timeAgo($document_last) ?></span>
|
||||
</li>
|
||||
<!-- The same rows as a document's Linked card - tile, name, when it changed -->
|
||||
<ul class="list-unstyled mb-0 itflow-links">
|
||||
<?php foreach ($linked_documents as $row) { ?>
|
||||
<li class="itflow-link-row"><?= linkRowHtml('document', $row, $client_id) ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -413,12 +398,10 @@ ob_start();
|
||||
|
||||
<?php if ($file_count) { ?>
|
||||
<div class="tab-pane fade <?= $first_tab === 'files' ? 'show active' : '' ?>" id="contact-quick-<?= $contact_id ?>-files" role="tabpanel">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php while ($row = mysqli_fetch_assoc($sql_linked_files)) { ?>
|
||||
<li class="list-group-item px-0 d-flex justify-content-between gap-3">
|
||||
<a href="file.php?file_id=<?= intval($row['file_id']) ?>&action=view" target="_blank" rel="noopener"><i class="fas fa-fw fa-<?= getFileIcon((string) $row['file_ext']) ?> text-secondary me-2"></i><?= escapeHtml($row['file_name']) ?></a>
|
||||
<span class="small text-body-secondary text-nowrap" title="<?= escapeHtml($row['file_created_at']) ?>"><?= timeAgo($row['file_created_at']) ?></span>
|
||||
</li>
|
||||
<!-- Each opens its quick look - preview, details, what else it is linked to -->
|
||||
<ul class="list-unstyled mb-0 itflow-links">
|
||||
<?php foreach ($linked_files as $row) { ?>
|
||||
<li class="itflow-link-row"><?= linkRowHtml('file', $row, $client_id) ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -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();
|
||||
<!-- Documents -->
|
||||
<?php
|
||||
if (mysqli_num_rows($sql_docs) > 0) {
|
||||
echo "<h5><i class='fas fa-fw fa-file-alt me-2'></i>Documents</h5><ul>";
|
||||
// The same rows as a document's Linked card
|
||||
echo "<h5><i class='fas fa-fw fa-file-alt me-2'></i>Documents</h5><ul class='list-unstyled itflow-links'>";
|
||||
mysqli_data_seek($sql_docs, 0);
|
||||
while ($row = mysqli_fetch_assoc($sql_docs)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = escapeHtml($row['document_name']);
|
||||
echo "<li><a class='ajax-modal' href='#' data-modal-size='lg' data-modal-url='modals/document/document_view.php?id=$document_id'>$document_name</a></li>";
|
||||
echo '<li class="itflow-link-row">' . linkRowHtml('document', $row, $client_id) . '</li>';
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
|
||||
@@ -152,11 +152,11 @@ ob_start();
|
||||
<label for="documents">Select related documents</label>
|
||||
<select class="form-select select2" id="documents" name="documents[]" multiple>
|
||||
<?php
|
||||
$sql = mysqli_query($mysqli, "SELECT document_id, document_name FROM documents WHERE document_archived_at IS NULL AND document_client_id = $client_id");
|
||||
$sql = mysqli_query($mysqli, "SELECT document_id, document_name, document_description FROM documents WHERE document_archived_at IS NULL AND document_client_id = $client_id ORDER BY document_name ASC");
|
||||
while ($row = mysqli_fetch_assoc($sql)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = escapeHtml($row['document_name']);
|
||||
echo "<option value=\"$document_id\">$document_name</option>";
|
||||
echo "<option value=\"$document_id\"" . selectOptionData(['icon' => 'fas fa-file-alt', 'description' => $row['document_description']]) . ">$document_name</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -224,18 +224,12 @@ ob_start();
|
||||
<?php
|
||||
$selected_ids = array_column(mysqli_fetch_all($sql_docs, MYSQLI_ASSOC), "document_id");
|
||||
|
||||
$sql_all = mysqli_query($mysqli, "SELECT document_id, document_name FROM documents WHERE document_archived_at IS NULL AND document_client_id = $client_id");
|
||||
$sql_all = mysqli_query($mysqli, "SELECT document_id, document_name, document_description FROM documents WHERE document_archived_at IS NULL AND document_client_id = $client_id ORDER BY document_name ASC");
|
||||
while ($row_all = mysqli_fetch_assoc($sql_all)) {
|
||||
$document_id = intval($row_all['document_id']);
|
||||
$document_name = escapeHtml($row_all['document_name']);
|
||||
|
||||
if (in_array($document_id, $selected_ids)) {
|
||||
echo "<option value=\"$document_id\" selected>$document_name</option>";
|
||||
}
|
||||
else{
|
||||
echo "<option value=\"$document_id\">$document_name</option>";
|
||||
}
|
||||
|
||||
$document_selected = in_array($document_id, $selected_ids) ? ' selected' : '';
|
||||
echo "<option value=\"$document_id\"$document_selected" . selectOptionData(['icon' => 'fas fa-file-alt', 'description' => $row_all['document_description']]) . ">$document_name</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
@@ -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'])) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<?php /* Through the file quick look and agent/file.php, which check access -
|
||||
not a link straight into the uploads folder */ ?>
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>File Name</th>
|
||||
<th>Upload date</th>
|
||||
<th>File</th>
|
||||
<th>Uploaded</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($quote_file = mysqli_fetch_assoc($sql_quote_files)) {
|
||||
$name = escapeHtml($quote_file['file_name']);
|
||||
$ref_name = escapeHtml($quote_file['file_reference_name']);
|
||||
$created = escapeHtml($quote_file['file_created_at']);
|
||||
|
||||
?>
|
||||
<?php while ($quote_file = mysqli_fetch_assoc($sql_quote_files)) {
|
||||
$quote_file_id = intval($quote_file['file_id']); ?>
|
||||
<tr>
|
||||
<td><a target="_blank" href="../uploads/clients/<?= $client_id ?>/<?= $ref_name ?>"><?= $name ?></a></td>
|
||||
<td><?= $created ?></td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<?= fileTypeTile($quote_file['file_ext'], 'sm') ?>
|
||||
<a class="ajax-modal text-break" href="#" data-modal-size="lg" data-modal-url="modals/file/file.php?id=<?= $quote_file_id ?>"><?= escapeHtml($quote_file['file_name']) ?></a>
|
||||
<span class="small text-body-secondary text-nowrap"><?= formatBytes(intval($quote_file['file_size'])) ?></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="small text-nowrap" title="<?= escapeHtml($quote_file['file_created_at']) ?>"><?= timeAgo($quote_file['file_created_at']) ?></td>
|
||||
<td class="text-end"><a class="btn btn-sm btn-light" href="file.php?file_id=<?= $quote_file_id ?>" title="Download"><i class="fas fa-fw fa-download"></i></a></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -639,7 +639,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
$ticket_attachment_name = escapeHtml($ticket_attachment['ticket_attachment_name']);
|
||||
?>
|
||||
<div class="mt-1">
|
||||
<i class="fas fa-fw fa-paperclip text-secondary me-1"></i><?= $ticket_attachment_name ?>
|
||||
<span class="me-1 align-middle"><?= fileTypeTile(pathinfo($ticket_attachment['ticket_attachment_name'], PATHINFO_EXTENSION), 'xs') ?></span><?= $ticket_attachment_name ?>
|
||||
<a target="_blank" class="ms-2 small" href="ticket_attachment.php?attachment_id=<?= $ticket_attachment_id ?>&action=view">View</a>
|
||||
<a class="ms-2 small" href="ticket_attachment.php?attachment_id=<?= $ticket_attachment_id ?>">Download</a>
|
||||
<?php if (lookupUserPermission("module_support") >= 3) { ?>
|
||||
@@ -932,7 +932,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
$ticket_attachment_name = escapeHtml($ticket_attachment['ticket_attachment_name']);
|
||||
?>
|
||||
<div class="mt-1">
|
||||
<i class="fas fa-fw fa-paperclip text-secondary me-1"></i><?= $ticket_attachment_name ?>
|
||||
<span class="me-1 align-middle"><?= fileTypeTile(pathinfo($ticket_attachment['ticket_attachment_name'], PATHINFO_EXTENSION), 'xs') ?></span><?= $ticket_attachment_name ?>
|
||||
<a target="_blank" class="ms-2 small" href="ticket_attachment.php?attachment_id=<?= $ticket_attachment_id ?>&action=view">View</a>
|
||||
<a class="ms-2 small" href="ticket_attachment.php?attachment_id=<?= $ticket_attachment_id ?>">Download</a>
|
||||
<?php if (lookupUserPermission("module_support") >= 3) { ?>
|
||||
|
||||
@@ -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");
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
@@ -34,11 +34,11 @@ $documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, docum
|
||||
<?php if (mysqli_num_rows($documents_sql) == 0) { ?>
|
||||
<?= portalEmptyState('There are no documents shared with you yet.') ?>
|
||||
<?php } else { ?>
|
||||
<table class="table table-bordered border border-dark">
|
||||
<table class="table table-hover align-middle border">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Created</th>
|
||||
<th>Updated</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -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'];
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<a href="document.php?id=<?= $document_id ?>">
|
||||
<i class="fas fa-file-alt me-2"></i>
|
||||
<?php
|
||||
if (!empty($folder_name)) {
|
||||
echo "$folder_name / ";
|
||||
}
|
||||
echo $document_name;
|
||||
?>
|
||||
</a>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<?= documentTile() ?>
|
||||
<div class="min-w-0">
|
||||
<a class="fw-semibold" href="document.php?id=<?= $document_id ?>"><?= $document_name ?></a>
|
||||
<div class="small text-body-secondary">
|
||||
<?php if ($folder_name) { ?><i class="fas fa-folder me-1"></i><?= $folder_name ?><?php } ?>
|
||||
<?php if ($folder_name && $row['document_description']) { ?> · <?php } ?>
|
||||
<?= escapeHtml($row['document_description']) ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><?= date('M j, Y', strtotime($document_created_at)) ?></td>
|
||||
<td class="text-nowrap"><?= date('M j, Y', strtotime($document_updated_at)) ?></td>
|
||||
<td class="text-center">
|
||||
<a href="document.php?id=<?= $document_id ?>" class="btn btn-sm btn-outline-primary" title="View document">
|
||||
<i class="fas fa-eye"></i>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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']],
|
||||
];
|
||||
},
|
||||
];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user