feature: improve admin directory and crawl progress
This commit is contained in:
111
app/static/admin.js
Normal file
111
app/static/admin.js
Normal file
@@ -0,0 +1,111 @@
|
||||
(function () {
|
||||
const columnDefaults = [
|
||||
"full_name",
|
||||
"status",
|
||||
"positions",
|
||||
"hse_start_year",
|
||||
"email",
|
||||
"last_seen_at",
|
||||
"dismissed_at",
|
||||
"profile",
|
||||
];
|
||||
const storageKey = "miem.directory.columns";
|
||||
|
||||
function readColumns() {
|
||||
try {
|
||||
const stored = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
||||
return Array.isArray(stored) && stored.length ? stored : columnDefaults;
|
||||
} catch (_error) {
|
||||
return columnDefaults;
|
||||
}
|
||||
}
|
||||
|
||||
function writeColumns(columns) {
|
||||
localStorage.setItem(storageKey, JSON.stringify(columns));
|
||||
}
|
||||
|
||||
function applyColumns(columns) {
|
||||
document.querySelectorAll("[data-column]").forEach((node) => {
|
||||
const visible = columns.includes(node.dataset.column);
|
||||
node.classList.toggle("directory-table__cell--hidden", !visible && node.classList.contains("directory-table__cell"));
|
||||
node.classList.toggle("directory-table__head--hidden", !visible && node.classList.contains("directory-table__head"));
|
||||
});
|
||||
document.querySelectorAll("[data-column-toggle]").forEach((checkbox) => {
|
||||
checkbox.checked = columns.includes(checkbox.value);
|
||||
});
|
||||
}
|
||||
|
||||
function setupColumns() {
|
||||
if (!document.querySelector("[data-directory-table]")) return;
|
||||
let columns = readColumns();
|
||||
const modal = document.querySelector("[data-columns-modal]");
|
||||
applyColumns(columns);
|
||||
|
||||
document.querySelectorAll("[data-columns-open]").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
modal.hidden = false;
|
||||
});
|
||||
});
|
||||
document.querySelectorAll("[data-columns-close]").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
modal.hidden = true;
|
||||
});
|
||||
});
|
||||
document.querySelectorAll("[data-column-toggle]").forEach((checkbox) => {
|
||||
checkbox.addEventListener("change", () => {
|
||||
columns = Array.from(document.querySelectorAll("[data-column-toggle]:checked")).map((item) => item.value);
|
||||
if (!columns.length) columns = ["full_name"];
|
||||
writeColumns(columns);
|
||||
applyColumns(columns);
|
||||
});
|
||||
});
|
||||
document.querySelectorAll("[data-row-href]").forEach((row) => {
|
||||
row.addEventListener("click", (event) => {
|
||||
if (event.target.closest("a, button, input, select, label")) return;
|
||||
window.location.href = row.dataset.rowHref;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupProgress() {
|
||||
const panel = document.querySelector("[data-progress-panel]");
|
||||
if (!panel) return;
|
||||
|
||||
const update = (run) => {
|
||||
if (!run) return;
|
||||
const status = document.querySelector("[data-progress-status]");
|
||||
const processed = document.querySelector("[data-progress-processed]");
|
||||
const found = document.querySelector("[data-progress-found]");
|
||||
const errors = document.querySelector("[data-progress-errors]");
|
||||
const fill = document.querySelector("[data-progress-fill]");
|
||||
const percent = document.querySelector("[data-progress-percent]");
|
||||
if (status) status.textContent = run.status;
|
||||
if (processed) processed.textContent = run.processed_count;
|
||||
if (found) found.textContent = run.found_count;
|
||||
if (errors) errors.textContent = run.error_count;
|
||||
if (fill) fill.style.width = `${run.progress_percent}%`;
|
||||
if (percent) percent.textContent = run.progress_percent;
|
||||
};
|
||||
|
||||
const poll = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/crawl-runs/latest", { credentials: "same-origin" });
|
||||
if (!response.ok) return false;
|
||||
const data = await response.json();
|
||||
const run = data.running || data.latest;
|
||||
update(run);
|
||||
return Boolean(data.running);
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const interval = window.setInterval(async () => {
|
||||
const keepGoing = await poll();
|
||||
if (!keepGoing) window.clearInterval(interval);
|
||||
}, 4000);
|
||||
}
|
||||
|
||||
setupColumns();
|
||||
setupProgress();
|
||||
})();
|
||||
Reference in New Issue
Block a user