7 day trash bin
This commit is contained in:
@@ -105,6 +105,7 @@ function routeFor(path) {
|
||||
if (path.startsWith("/reconciliation")) return "reconciliation";
|
||||
if (path.startsWith("/activity/fslogix")) return "activity-fslogix";
|
||||
if (path.startsWith("/activity")) return "activity";
|
||||
if (path.startsWith("/trash")) return "trash";
|
||||
if (path.startsWith("/backup")) return "backup";
|
||||
if (path.startsWith("/report")) return "report";
|
||||
if (path.startsWith("/system")) return "system";
|
||||
@@ -127,6 +128,7 @@ async function navigate(path, replace = false) {
|
||||
if (route === "storage-users") await renderStorage("users");
|
||||
if (route === "activity") await renderActivity();
|
||||
if (route === "activity-fslogix") await renderActivity("fslogix");
|
||||
if (route === "trash") await renderTrash();
|
||||
if (route === "backup") await renderBackup();
|
||||
if (route === "report") await renderReport();
|
||||
if (route === "system") await renderSystem();
|
||||
@@ -303,6 +305,68 @@ async function renderActivity(stream = "main") {
|
||||
await load(false);
|
||||
}
|
||||
|
||||
async function renderTrash() {
|
||||
content.innerHTML = pageHead(
|
||||
"Papierkorb",
|
||||
"Gelöschte Dateien sieben Tage lang herunterladen oder am Originalpfad wiederherstellen.",
|
||||
) + `
|
||||
<section class="panel">
|
||||
<form id="trash-filter" class="filters">
|
||||
<label>Freigabe<select name="share"><option value="">Alle Freigaben</option><option>Data</option><option>Private</option><option>FSLogix</option></select></label>
|
||||
<label class="wide">Pfad enthält<input name="path" placeholder="Ordner oder Dateiname"></label>
|
||||
<button type="submit">Aktualisieren</button>
|
||||
</form>
|
||||
<p id="trash-summary" class="muted"></p>
|
||||
<div class="table-wrap"><table><thead><tr><th>Gelöscht (UTC)</th><th>Benutzer</th><th>Freigabe</th><th>Originalpfad</th><th>Größe</th><th>Verfügbar bis</th><th>Aktionen</th></tr></thead><tbody id="trash-rows"></tbody></table></div>
|
||||
</section>`;
|
||||
const form = document.querySelector("#trash-filter");
|
||||
const load = async () => {
|
||||
const params = new URLSearchParams(new FormData(form));
|
||||
params.set("limit", "500");
|
||||
const result = await api(`/api/trash?${params}`);
|
||||
const body = document.querySelector("#trash-rows");
|
||||
if (!result.items.length) {
|
||||
body.innerHTML = '<tr><td colspan="7" class="empty">Keine gelöschten Dateien</td></tr>';
|
||||
} else {
|
||||
body.innerHTML = result.items.map(item => `<tr>
|
||||
<td class="timestamp">${esc(utcTime(item.deletedAt))}</td>
|
||||
<td>${esc(item.deletedBy)}</td>
|
||||
<td>${esc(item.share)}</td>
|
||||
<td class="path">${esc(item.path)}</td>
|
||||
<td class="numeric">${bytes(item.size)}</td>
|
||||
<td class="timestamp">${esc(utcTime(item.expiresAt))}</td>
|
||||
<td><div class="row-actions"><a class="button" href="/api/trash/download?id=${encodeURIComponent(item.id)}" download>Herunterladen</a><button type="button" data-restore="${esc(item.id)}">Wiederherstellen</button></div></td>
|
||||
</tr>`).join("");
|
||||
}
|
||||
const shown = result.items.length.toLocaleString("de-DE");
|
||||
const total = Number(result.matched || 0).toLocaleString("de-DE");
|
||||
const suffix = result.truncated ? ` · ${shown} von ${total} angezeigt` : "";
|
||||
document.querySelector("#trash-summary").textContent = `${total} Dateien · Aufbewahrung ${result.retentionDays} Tage${suffix}`;
|
||||
};
|
||||
form.addEventListener("submit", async event => {
|
||||
event.preventDefault();
|
||||
try { await load(); } catch (error) { notice(error.message); }
|
||||
});
|
||||
document.querySelector("#trash-rows").addEventListener("click", async event => {
|
||||
const button = event.target.closest("button[data-restore]");
|
||||
if (!button) return;
|
||||
if (!window.confirm("Datei am Originalpfad wiederherstellen?")) return;
|
||||
button.disabled = true;
|
||||
try {
|
||||
const result = await api("/api/trash/restore", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({id: button.dataset.restore}),
|
||||
});
|
||||
notice(`${result.share}: ${result.path} wurde wiederhergestellt.`);
|
||||
await load();
|
||||
} catch (error) {
|
||||
notice(error.message);
|
||||
button.disabled = false;
|
||||
}
|
||||
});
|
||||
await load();
|
||||
}
|
||||
|
||||
function triggerLabel(value) {
|
||||
return ({automatic: "Automatisch", web: "Weboberfläche", manual: "Befehlszeile", startup: "Systemstart"}[value] || value || "—");
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<a href="/storage/users" data-route="storage-users">Benutzerbelegung</a>
|
||||
<a href="/activity" data-route="activity">Aktivitätsprotokoll</a>
|
||||
<a href="/activity/fslogix" data-route="activity-fslogix">FSLogix-Protokoll</a>
|
||||
<a href="/trash" data-route="trash">Papierkorb</a>
|
||||
<a href="/backup" data-route="backup">Sicherungen</a>
|
||||
<a href="/report" data-route="report">PDF-Bericht</a>
|
||||
<a href="/system" data-route="system">System</a>
|
||||
|
||||
+2
-1
@@ -8,7 +8,7 @@
|
||||
body { margin: 0; min-height: 100vh; }
|
||||
a { color: #0645ad; }
|
||||
button, input, select { font: inherit; }
|
||||
button { padding: .4rem .7rem; border: 1px solid #777; color: #111; background: #eee; cursor: pointer; }
|
||||
button, .button { display: inline-block; padding: .4rem .7rem; border: 1px solid #777; color: #111; background: #eee; cursor: pointer; text-decoration: none; white-space: nowrap; }
|
||||
button:disabled { color: #777; cursor: wait; }
|
||||
input, select { width: 100%; padding: .4rem; border: 1px solid #999; background: #fff; }
|
||||
button:focus, input:focus, select:focus, a:focus { outline: 2px solid #0645ad; outline-offset: 1px; }
|
||||
@@ -64,6 +64,7 @@ th, td { padding: .5rem; border-bottom: 1px solid #ccc; vertical-align: top; }
|
||||
.badge.warn { color: #750; }
|
||||
.toolbar { display: flex; flex-wrap: wrap; gap: .5rem; }
|
||||
.toolbar input { max-width: 340px; }
|
||||
.row-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
|
||||
.list { margin: 0; padding: 0; list-style: none; }
|
||||
.select-row { width: 100%; display: grid; grid-template-columns: 1fr auto; gap: .5rem; border: 0; border-bottom: 1px solid #ccc; background: #fff; text-align: left; }
|
||||
.select-row.active { font-weight: bold; background: #eee; }
|
||||
|
||||
Reference in New Issue
Block a user