Files
dobetternorge-tools/dashboard/documents.php
T

217 lines
9.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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'; ?>