217 lines
9.6 KiB
PHP
217 lines
9.6 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
$dashboardPage = 'documents';
|
||
$dashboardTitle = dbnToolsT('dash_title_docs', dbnToolsCurrentLanguage());
|
||
$dashboardLead = dbnToolsT('dash_lead_docs', dbnToolsCurrentLanguage());
|
||
require_once __DIR__ . '/../includes/layout_dashboard.php';
|
||
?>
|
||
<section class="dms-shell">
|
||
<aside class="dms-tree" id="dmsTree" aria-label="Folder tree">
|
||
<div class="dms-loading"></div>
|
||
</aside>
|
||
|
||
<div class="dms-main">
|
||
<div class="dms-toolbar">
|
||
<div class="dms-toolbar__crumbs" id="dmsCrumbs">
|
||
<a href="#" data-folder-id="all">🗂 <?= htmlspecialchars(dbnToolsT('dash_dms_all_files', $uiLang) ?: 'All files') ?></a>
|
||
</div>
|
||
<div class="dms-toolbar__actions">
|
||
<button class="dash-btn" id="dmsSaveSearch" type="button">★ <?= htmlspecialchars(dbnToolsT('dash_dms_save_view', $uiLang) ?: 'Save view') ?></button>
|
||
<a href="/dashboard/upload.php" class="dash-btn dash-btn--primary">+ <?= htmlspecialchars(dbnToolsT('dash_upload_btn_short', $uiLang)) ?></a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dms-filters">
|
||
<input type="search" id="dmsFilterQ" placeholder="<?= htmlspecialchars(dbnToolsT('dash_filter_q_ph', $uiLang)) ?>" autocomplete="off">
|
||
<select id="dmsFilterStatus">
|
||
<option value=""><?= htmlspecialchars(dbnToolsT('dash_filter_all_status', $uiLang)) ?></option>
|
||
<option value="ready">Ready</option>
|
||
<option value="pending">Pending</option>
|
||
<option value="processing">Processing</option>
|
||
<option value="error">Error</option>
|
||
</select>
|
||
<select id="dmsFilterCategory">
|
||
<option value=""><?= htmlspecialchars(dbnToolsT('dash_dms_all_categories', $uiLang) ?: 'All categories') ?></option>
|
||
</select>
|
||
<label style="font-size:13px;display:inline-flex;align-items:center;gap:4px;">
|
||
<input type="checkbox" id="dmsIncludeSub" checked>
|
||
<?= htmlspecialchars(dbnToolsT('dash_dms_include_sub', $uiLang) ?: 'Include subfolders') ?>
|
||
</label>
|
||
</div>
|
||
|
||
<div id="dmsListWrap"><div class="dms-loading"></div></div>
|
||
|
||
<div class="dash-pager" id="dmsPager" hidden>
|
||
<span id="dmsPagerLabel"></span>
|
||
<div class="dash-pager__actions">
|
||
<button class="dash-btn" id="dmsPagerPrev"><?= htmlspecialchars(dbnToolsT('dash_prev', $uiLang)) ?></button>
|
||
<button class="dash-btn" id="dmsPagerNext"><?= htmlspecialchars(dbnToolsT('dash_next', $uiLang)) ?></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
'use strict';
|
||
if (!window.DBN_DMS) { console.error('dms.js missing'); return; }
|
||
const DMS = window.DBN_DMS;
|
||
|
||
const $tree = document.getElementById('dmsTree');
|
||
const $list = document.getElementById('dmsListWrap');
|
||
const $crumbs = document.getElementById('dmsCrumbs');
|
||
const $pager = document.getElementById('dmsPager');
|
||
const $pl = document.getElementById('dmsPagerLabel');
|
||
const $prev = document.getElementById('dmsPagerPrev');
|
||
const $next = document.getElementById('dmsPagerNext');
|
||
const $fq = document.getElementById('dmsFilterQ');
|
||
const $fs = document.getElementById('dmsFilterStatus');
|
||
const $fc = document.getElementById('dmsFilterCategory');
|
||
const $sub = document.getElementById('dmsIncludeSub');
|
||
const $save = document.getElementById('dmsSaveSearch');
|
||
|
||
let debounce;
|
||
|
||
async function loadAll() {
|
||
$list.innerHTML = '<div class="dms-loading"></div>';
|
||
try {
|
||
await DMS.Tree.load();
|
||
DMS.Tree.render($tree, { activeFolderId: DMS.List.state.folderId });
|
||
await DMS.Smart.load();
|
||
await refreshCategories();
|
||
await refreshList();
|
||
} catch (e) {
|
||
$list.innerHTML = '<div class="dms-list__empty"><strong>Error</strong><span>' + DMS.safe(e.message) + '</span></div>';
|
||
}
|
||
}
|
||
|
||
async function refreshCategories() {
|
||
try {
|
||
const data = await DMS.api('/categories.php?action=list');
|
||
const opts = ['<option value="">All categories</option>'].concat(
|
||
(data.categories || []).map(c => '<option value="' + DMS.safe(c.slug) + '">' + DMS.safe(c.label) + ' (' + c.doc_count + ')</option>')
|
||
);
|
||
const prev = $fc.value;
|
||
$fc.innerHTML = opts.join('');
|
||
$fc.value = prev;
|
||
} catch (_) { /* ignored */ }
|
||
}
|
||
|
||
async function refreshList() {
|
||
try {
|
||
const data = await DMS.List.load();
|
||
DMS.List.render($list);
|
||
updateCrumbs(data.folder);
|
||
updatePager(data);
|
||
} catch (e) {
|
||
$list.innerHTML = '<div class="dms-list__empty"><strong>Error</strong><span>' + DMS.safe(e.message) + '</span></div>';
|
||
}
|
||
}
|
||
|
||
function updateCrumbs(folder) {
|
||
let html = '<a href="#" data-folder-id="all">🗂 All files</a>';
|
||
if (folder && folder.breadcrumb) {
|
||
folder.breadcrumb.forEach((b, i) => {
|
||
const isLast = i === folder.breadcrumb.length - 1;
|
||
html += '<span class="dms-toolbar__crumb-sep">›</span>';
|
||
if (isLast) html += '<span class="dms-toolbar__crumb--current">' + DMS.safe(b.name) + '</span>';
|
||
else html += '<a href="#" data-folder-id="' + b.id + '">' + DMS.safe(b.name) + '</a>';
|
||
});
|
||
} else if (DMS.List.state.folderId === 'unassigned') {
|
||
html += '<span class="dms-toolbar__crumb-sep">›</span><span class="dms-toolbar__crumb--current">Unassigned</span>';
|
||
}
|
||
$crumbs.innerHTML = html;
|
||
}
|
||
|
||
function updatePager(data) {
|
||
const total = data.total || 0;
|
||
const limit = DMS.List.state.limit;
|
||
const offset = DMS.List.state.offset;
|
||
if (total <= limit) { $pager.hidden = true; return; }
|
||
$pager.hidden = false;
|
||
$pl.textContent = (offset + 1) + '–' + Math.min(total, offset + limit) + ' / ' + total;
|
||
$prev.disabled = offset === 0;
|
||
$next.disabled = offset + limit >= total;
|
||
}
|
||
|
||
document.addEventListener('dms:folder-changed', e => {
|
||
const id = e.detail.folderId;
|
||
if (id === 'trash') { window.location.href = '/dashboard/trash.php'; return; }
|
||
DMS.List.state.folderId = id;
|
||
DMS.List.state.offset = 0;
|
||
DMS.List.state.selected.clear();
|
||
DMS.Tree.state.activeFolderId = id;
|
||
DMS.Tree.render($tree, { activeFolderId: id });
|
||
refreshList();
|
||
});
|
||
document.addEventListener('dms:reload-required', () => {
|
||
DMS.Tree.load().then(() => DMS.Tree.render($tree, { activeFolderId: DMS.List.state.folderId }));
|
||
refreshList();
|
||
});
|
||
document.addEventListener('dms:reload-tree', () => {
|
||
DMS.Tree.load().then(() => DMS.Tree.render($tree, { activeFolderId: DMS.List.state.folderId }));
|
||
});
|
||
document.addEventListener('dms:apply-smart', e => {
|
||
const q = e.detail || {};
|
||
if ('q' in q) $fq.value = q.q || '';
|
||
if ('status' in q) $fs.value = q.status || '';
|
||
if ('category' in q) $fc.value = q.category || '';
|
||
if ('folder_id' in q) DMS.List.state.folderId = String(q.folder_id == null ? 'all' : q.folder_id);
|
||
if ('include_subfolders' in q) $sub.checked = !!q.include_subfolders;
|
||
DMS.List.state.q = $fq.value;
|
||
DMS.List.state.status = $fs.value;
|
||
DMS.List.state.category = $fc.value;
|
||
DMS.List.state.includeSubfolders = $sub.checked;
|
||
DMS.List.state.offset = 0;
|
||
refreshList();
|
||
});
|
||
|
||
$crumbs.addEventListener('click', e => {
|
||
const a = e.target.closest('a[data-folder-id]');
|
||
if (!a) return;
|
||
e.preventDefault();
|
||
DMS.List.state.folderId = a.dataset.folderId;
|
||
DMS.List.state.offset = 0;
|
||
DMS.Tree.state.activeFolderId = a.dataset.folderId;
|
||
DMS.Tree.render($tree, { activeFolderId: a.dataset.folderId });
|
||
refreshList();
|
||
});
|
||
|
||
$fq.addEventListener('input', () => {
|
||
clearTimeout(debounce);
|
||
debounce = setTimeout(() => {
|
||
DMS.List.state.q = $fq.value.trim();
|
||
DMS.List.state.offset = 0;
|
||
refreshList();
|
||
}, 200);
|
||
});
|
||
$fs.addEventListener('change', () => { DMS.List.state.status = $fs.value; DMS.List.state.offset = 0; refreshList(); });
|
||
$fc.addEventListener('change', () => { DMS.List.state.category = $fc.value; DMS.List.state.offset = 0; refreshList(); });
|
||
$sub.addEventListener('change', () => { DMS.List.state.includeSubfolders = $sub.checked; refreshList(); });
|
||
|
||
$prev.addEventListener('click', () => { DMS.List.state.offset = Math.max(0, DMS.List.state.offset - DMS.List.state.limit); refreshList(); });
|
||
$next.addEventListener('click', () => { DMS.List.state.offset += DMS.List.state.limit; refreshList(); });
|
||
|
||
$save.addEventListener('click', () => {
|
||
DMS.Smart.save({
|
||
q: $fq.value, status: $fs.value, category: $fc.value,
|
||
folder_id: DMS.List.state.folderId,
|
||
include_subfolders: $sub.checked,
|
||
});
|
||
});
|
||
|
||
DMS.installDropAnywhereUpload({ getFolderId: () => {
|
||
const id = DMS.List.state.folderId;
|
||
return (id && id !== 'all' && id !== 'unassigned' && id !== 'trash') ? id : null;
|
||
}});
|
||
|
||
const params = new URLSearchParams(location.search);
|
||
if (params.get('folder')) DMS.List.state.folderId = params.get('folder');
|
||
|
||
loadAll();
|
||
});
|
||
</script>
|
||
|
||
<?php require_once __DIR__ . '/../includes/layout_dashboard_footer.php'; ?>
|