refactoring
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
/* Archived CMap administration view. */
|
||||
|
||||
class ArchivedCmapsAdmin {
|
||||
/**
|
||||
* goal : Create the archived-CMap administration controller.
|
||||
* pre : formatDate formats database timestamps; reloadConceptMaps refreshes
|
||||
* ordinary CMap navigation after a restore.
|
||||
* post : The controller is ready to load and restore archived maps.
|
||||
* result : A directly usable archived-CMap controller.
|
||||
*/
|
||||
constructor(api, translate, formatDate, reloadConceptMaps) {
|
||||
this.api = api;
|
||||
this.translate = translate;
|
||||
this.formatDate = formatDate;
|
||||
this.reloadConceptMaps = reloadConceptMaps;
|
||||
this.list = document.getElementById("archived-cmaps-list");
|
||||
this.status = document.getElementById("archived-cmaps-status");
|
||||
}
|
||||
|
||||
/**
|
||||
* goal : Load and render all archived concept maps.
|
||||
* pre : The current session has administrator permission.
|
||||
* post : The archived-CMap list represents the current server state.
|
||||
* result : A promise that resolves when all map rows have been rendered.
|
||||
*/
|
||||
async load() {
|
||||
this.status.textContent = "";
|
||||
const result = await this.api("/api/admin/cmaps/archived");
|
||||
const conceptMaps = Array.isArray(result.conceptMaps) ? result.conceptMaps : [];
|
||||
this.list.replaceChildren();
|
||||
|
||||
if (conceptMaps.length === 0) {
|
||||
const empty = document.createElement("p");
|
||||
empty.className = "muted";
|
||||
empty.textContent = this.translate(
|
||||
"no-archived-concept-maps", "No archived CMaps.");
|
||||
this.list.append(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const conceptMap of conceptMaps) {
|
||||
this.list.append(this.#renderConceptMap(conceptMap));
|
||||
}
|
||||
}
|
||||
|
||||
/** Build one archived map row and its restore action. */
|
||||
#renderConceptMap(conceptMap) {
|
||||
const row = document.createElement("article");
|
||||
row.className = "archived-cmap-row";
|
||||
|
||||
const title = document.createElement("strong");
|
||||
title.textContent = conceptMap.title;
|
||||
|
||||
const archivedAt = conceptMap.archivedAt
|
||||
? this.formatDate(conceptMap.archivedAt)
|
||||
: "";
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "muted";
|
||||
meta.textContent = [
|
||||
`cmap:${conceptMap.slug}`,
|
||||
archivedAt
|
||||
? `${this.translate("archived", "Archived")} ${archivedAt}`
|
||||
: this.translate("archived", "Archived"),
|
||||
conceptMap.archivedBy
|
||||
? `${this.translate("by", "by")} ${conceptMap.archivedBy}`
|
||||
: ""
|
||||
].filter(Boolean).join(" · ");
|
||||
|
||||
const restore = document.createElement("button");
|
||||
restore.type = "button";
|
||||
restore.textContent = this.translate("restore-concept-map", "Restore CMap");
|
||||
restore.addEventListener("click", () => {
|
||||
this.#restore(conceptMap, restore).catch((error) => console.error(error));
|
||||
});
|
||||
|
||||
row.append(title, meta, restore);
|
||||
return row;
|
||||
}
|
||||
|
||||
/** Confirm and restore one CMap, then refresh both CMap catalogues. */
|
||||
async #restore(conceptMap, button) {
|
||||
const question = this.translate(
|
||||
"restore-concept-map-confirm", "Restore concept map \"{title}\"?")
|
||||
.replace("{title}", conceptMap.title);
|
||||
if (!window.confirm(question)) return;
|
||||
|
||||
button.disabled = true;
|
||||
try {
|
||||
await this.api(
|
||||
`/api/admin/cmaps/archived/${encodeURIComponent(conceptMap.slug)}/restore`,
|
||||
{ method: "POST" });
|
||||
await this.reloadConceptMaps();
|
||||
await this.load();
|
||||
this.status.textContent = this.translate(
|
||||
"concept-map-restored", "CMap restored.");
|
||||
} catch (error) {
|
||||
button.disabled = false;
|
||||
this.status.textContent = error.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { ArchivedCmapsAdmin };
|
||||
Reference in New Issue
Block a user