(function ()
{
"use strict";
var $ = window.MailSharp;
var state = {
page: 1,
pageSize: 50,
totalCount: 0,
statusLoaded: false,
metricsLoaded: false,
logsLoaded: false
};
function reportError(err)
{
if (err.cancelled) return;
window.alert(err.message);
}
function formatSize(bytes)
{
if (!bytes) return "0 KB";
var kb = bytes / 1024;
return kb >= 1024 ? (kb / 1024).toFixed(1) + " MB" : kb.toFixed(1) + " KB";
}
function bootstrap()
{
$.initHeader().then(function ()
{
loadStatus();
}).catch(reportError);
}
function loadStatus()
{
state.statusLoaded = true;
$.apiFetch("api/maintenance/status").then(function (s)
{
renderIndexingStatus(s.indexing);
renderIndexTotals(s.index);
renderCacheStats(s.cache);
}).catch(reportError);
}
function renderIndexingStatus(indexing)
{
var el = document.getElementById("maintenanceStatus");
var text = "Achtergrondindexering: " + (indexing.maxConcurrentIndexing - indexing.currentlyAvailableSlots) + " / " + indexing.maxConcurrentIndexing + " actief.";
if (indexing.inProgress.length > 0)
{
text += " Bezig met: " + indexing.inProgress.map(function (entry)
{
if (!entry.total) return entry.key;
var percent = Math.round((entry.processed / entry.total) * 100);
return entry.key + " (" + entry.processed + " / " + entry.total + ", " + percent + "%)";
}).join(", ");
}
else
{
text += " Niets in behandeling.";
}
el.textContent = text;
}
function renderIndexTotals(index)
{
document.getElementById("indexTotals").textContent =
index.totalIndexedFolders + " geïndexeerde mappen, " + index.totalIndexedMessages + " berichten, " + formatSize(index.totalIndexedSizeBytes) + " totaal.";
var rows = index.accounts.map(function (a)
{
return "
' +
'
' + $.esc(e.level) + " " + $.esc(meta) + "
" +
'
' + body + "
" +
"
";
});
document.getElementById("logsBody").innerHTML = rows.join("");
var totalPages = Math.max(1, Math.ceil(state.totalCount / state.pageSize));
document.getElementById("logsPageInfo").textContent = "Pagina " + state.page + " van " + totalPages + " (" + state.totalCount + " logregels)";
}).catch(reportError);
}
document.getElementById("logFilterBtn").addEventListener("click", function (e)
{
e.preventDefault();
state.page = 1;
loadLogs();
});
document.getElementById("logClearBtn").addEventListener("click", function (e)
{
e.preventDefault();
if (!window.confirm("Alle logregels definitief verwijderen?")) return;
$.apiFetch("api/maintenance/logs/clear", { method: "POST" }).then(function ()
{
state.page = 1;
loadLogs();
}).catch(reportError);
});
// The level select filters immediately on change, unlike the free-text/account inputs (which
// wait for the Filteren button so every keystroke doesn't fire a request) - a dropdown change
// is already a single deliberate action, so there's no "still typing" state to debounce.
document.getElementById("logLevelFilter").addEventListener("change", function ()
{
state.page = 1;
loadLogs();
});
document.getElementById("logsPrevBtn").addEventListener("click", function (e)
{
e.preventDefault();
if (state.page > 1) { state.page--; loadLogs(); }
});
document.getElementById("logsNextBtn").addEventListener("click", function (e)
{
e.preventDefault();
var totalPages = Math.max(1, Math.ceil(state.totalCount / state.pageSize));
if (state.page < totalPages) { state.page++; loadLogs(); }
});
// ---------- tabs ----------
document.getElementById("maintenanceTabs").addEventListener("click", function (e)
{
var tab = e.target.closest(".subheader-tab");
if (!tab) return;
e.preventDefault();
var name = tab.getAttribute("data-tab");
document.querySelectorAll(".subheader-tab").forEach(function (t) { t.classList.toggle("active", t === tab); });
document.querySelectorAll("[data-tab-panel]").forEach(function (p)
{
p.style.display = p.getAttribute("data-tab-panel") === name ? "" : "none";
});
if (name === "metrics" && !state.metricsLoaded) loadMetrics();
if (name === "logs" && !state.logsLoaded) loadLogs();
});
bootstrap();
})();