Files

165 lines
8.6 KiB
PHP
Raw Permalink 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 = 'folders';
$dashboardTitle = dbnToolsT('dash_title_folders', dbnToolsCurrentLanguage()) ?: 'Folders';
$dashboardLead = dbnToolsT('dash_lead_folders', dbnToolsCurrentLanguage()) ?: 'Organise documents and set per-folder access.';
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="folderCrumbs"><span>Pick a folder on the left</span></div>
<div class="dms-toolbar__actions">
<button class="dash-btn dash-btn--primary" id="folderNewBtn" type="button">+ New folder</button>
</div>
</div>
<div id="folderDetail">
<div class="dms-list__empty">
<strong>Select a folder</strong>
<span>Use the tree on the left, or create a new folder.</span>
</div>
</div>
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function () {
'use strict';
const DMS = window.DBN_DMS;
const $tree = document.getElementById('dmsTree');
const $detail = document.getElementById('folderDetail');
const $crumbs = document.getElementById('folderCrumbs');
let selectedFolderId = null;
async function loadTree() {
await DMS.Tree.load();
DMS.Tree.render($tree, { activeFolderId: selectedFolderId });
}
async function showDetail(folderId) {
if (folderId === 'all' || folderId === 'unassigned' || folderId === 'trash') {
$detail.innerHTML = '<div class="dms-list__empty"><strong>System folder</strong><span>Cannot configure access for system folders.</span></div>';
return;
}
selectedFolderId = folderId;
$detail.innerHTML = '<div class="dms-loading"></div>';
try {
const [perms, crumbsData] = await Promise.all([
DMS.api('/folders.php?action=list_permissions&folder_id=' + folderId),
DMS.api('/folders.php?action=get_breadcrumb&folder_id=' + folderId),
]);
$crumbs.innerHTML = (crumbsData.breadcrumb || []).map((b, i, a) =>
(i ? '<span class="dms-toolbar__crumb-sep"></span>' : '')
+ (i === a.length - 1
? '<span class="dms-toolbar__crumb--current">' + DMS.safe(b.name) + '</span>'
: '<span>' + DMS.safe(b.name) + '</span>')
).join('');
const rows = (perms.permissions || []).map(p => {
const who = p.user_id
? '👤 ' + DMS.safe(p.user_email || ('user #' + p.user_id))
: '🛡 role ≥ ' + DMS.safe(p.min_role);
return '<div class="dms-perm-row">' +
'<div>' + who + '</div>' +
'<div>' + (p.can_read ? '✓' : '—') + ' read</div>' +
'<div>' + (p.can_write ? '✓' : '—') + ' write</div>' +
'<div>' + (p.can_manage ? '✓' : '—') + ' manage</div>' +
'<div><button class="dms-list__more" data-pid="' + p.id + '" type="button" aria-label="Remove">✕</button></div>' +
'</div>';
}).join('');
$detail.innerHTML =
'<div class="dms-toolbar"><div class="dms-toolbar__crumbs"><strong>Access control</strong></div>' +
'<div class="dms-toolbar__actions">' +
'<button class="dash-btn" type="button" id="folderRename">Rename</button>' +
'<button class="dash-btn dash-btn--danger" type="button" id="folderDelete">Delete</button>' +
'<button class="dash-btn dash-btn--primary" type="button" id="folderAddAcl">+ Add rule</button>' +
'</div></div>' +
'<div class="dms-list">' +
(rows ||
'<div class="dms-list__empty"><strong>Open to all in tenant</strong>' +
'<span>No rules set — add one to restrict access.</span></div>') +
(rows ? '' : '') +
'</div>';
$detail.querySelector('#folderRename').addEventListener('click', () => {
DMS.folderModal.open({ folderId, name: crumbsData.breadcrumb.slice(-1)[0]?.name || '' });
});
$detail.querySelector('#folderDelete').addEventListener('click', async () => {
if (!confirm('Soft-delete this folder? Documents inside will move to Trash.')) return;
try {
await DMS.api('/folders.php?action=delete', { method: 'POST', body: { folder_id: folderId } });
selectedFolderId = null;
$detail.innerHTML = '<div class="dms-list__empty"><strong>Deleted</strong></div>';
await loadTree();
} catch (e) { alert(e.message); }
});
$detail.querySelector('#folderAddAcl').addEventListener('click', () => openAclModal(folderId));
$detail.querySelectorAll('[data-pid]').forEach(btn => {
btn.addEventListener('click', async () => {
if (!confirm('Remove this access rule?')) return;
try {
await DMS.api('/folders.php?action=remove_permission', { method: 'POST', body: { permission_id: Number(btn.dataset.pid) } });
showDetail(folderId);
} catch (e) { alert(e.message); }
});
});
} catch (e) {
$detail.innerHTML = '<div class="dms-list__empty"><strong>Error</strong><span>' + DMS.safe(e.message) + '</span></div>';
}
}
function openAclModal(folderId) {
DMS.openModal({
title: 'Add access rule',
body:
'<div class="dms-field"><label>Grantee type</label>' +
'<select id="aclType"><option value="role">Role-based</option><option value="user">Specific user (by id)</option></select></div>' +
'<div class="dms-field" id="aclRoleField"><label>Minimum role</label>' +
'<select id="aclRole"><option>viewer</option><option>editor</option><option>admin</option><option>owner</option></select></div>' +
'<div class="dms-field" id="aclUserField" style="display:none"><label>User ID</label><input type="number" id="aclUser"></div>' +
'<div class="dms-field dms-field--inline"><label>Permissions</label>' +
'<label><input type="checkbox" id="aclRead" checked> read</label>' +
'<label><input type="checkbox" id="aclWrite"> write</label>' +
'<label><input type="checkbox" id="aclManage"> manage</label></div>',
actions: [
{ label: 'Cancel', cls: 'dash-btn', onclick: DMS.closeModal },
{ label: 'Add', cls: 'dash-btn dash-btn--primary', onclick: async () => {
const type = document.getElementById('aclType').value;
const body = { folder_id: folderId,
can_read: document.getElementById('aclRead').checked,
can_write: document.getElementById('aclWrite').checked,
can_manage: document.getElementById('aclManage').checked,
};
if (type === 'role') body.min_role = document.getElementById('aclRole').value;
else body.user_id = Number(document.getElementById('aclUser').value || 0);
try {
await DMS.api('/folders.php?action=set_permission', { method: 'POST', body });
DMS.closeModal();
showDetail(folderId);
} catch (e) { alert(e.message); }
}},
],
});
document.getElementById('aclType').addEventListener('change', e => {
document.getElementById('aclRoleField').style.display = e.target.value === 'role' ? '' : 'none';
document.getElementById('aclUserField').style.display = e.target.value === 'user' ? '' : 'none';
});
}
document.addEventListener('dms:folder-changed', e => showDetail(e.detail.folderId));
document.addEventListener('dms:reload-required', loadTree);
document.addEventListener('dms:reload-tree', loadTree);
document.getElementById('folderNewBtn').addEventListener('click', () => DMS.folderModal.open({}));
loadTree();
});
</script>
<?php require_once __DIR__ . '/../includes/layout_dashboard_footer.php'; ?>