refactoring of cmaps, widgets, etc.

This commit is contained in:
2026-09-02 16:06:26 +02:00
parent 38f255c1a4
commit f0562a06cc
52 changed files with 3626 additions and 2642 deletions
@@ -0,0 +1,115 @@
/**
* Present and maintain the stored history of one CMap.
*
* History records come from CmapRepository. Loading a version is delegated to
* the workspace because it controls unsaved-change transitions and the editor.
*/
export class CmapHistoryDialog {
constructor(dialog, repository, tr, pageDisplayDate, can, loadVersion, showStatus) {
this.dialog = dialog;
this.repository = repository;
this.tr = tr;
this.pageDisplayDate = pageDisplayDate;
this.can = can;
this.loadVersion = loadVersion;
this.showStatus = showStatus;
this.list = dialog.querySelector("#cmap-history-list");
dialog.querySelector("#cmap-history-close").addEventListener("click", () => dialog.close());
}
async open(conceptMap) {
const versions = await this.repository.history(conceptMap);
this.list.replaceChildren();
if (!versions.length) this.showEmptyMessage();
for (const version of versions) this.list.append(this.versionRow(conceptMap, version));
this.dialog.showModal();
}
showEmptyMessage() {
const empty = document.createElement("p");
empty.className = "muted cmap-history-empty";
empty.textContent = this.tr(
"no-concept-map-history", "No snapshots or manual saves yet.");
this.list.append(empty);
}
versionRow(conceptMap, version) {
const row = document.createElement("div");
row.className = "cmap-history-row";
const label = document.createElement("div");
const heading = document.createElement("strong");
heading.textContent = `${this.tr("version", "Version")} ${version.version}${version.title}`;
const meta = document.createElement("div");
meta.className = "muted";
meta.textContent = `${this.pageDisplayDate(version.createdAt)} · ${version.author} · ${this.versionSummary(version)}`;
label.append(heading, document.createElement("br"), meta);
const actions = document.createElement("div");
actions.className = "cmap-history-actions";
actions.append(this.loadButton(conceptMap, version));
if (this.can("editor")) actions.append(this.deleteButton(conceptMap, version, row));
row.append(label, actions);
return row;
}
versionSummary(version) {
const knownSummaries = {
create: this.tr("concept-map-created-version", "CMap created"),
rename: this.tr("concept-map-renamed-version", "CMap renamed")
};
let summary = knownSummaries[version.action] || version.summary;
if (version.action === "snapshot") {
const snapshotLabel = this.tr("snapshot", "Snapshot");
if (version.summary === "Current state when CMap history was enabled") {
summary = this.tr("concept-map-initial-version", "Initial available version");
} else {
summary = version.summary === snapshotLabel ?
snapshotLabel : `${snapshotLabel}${version.summary}`;
}
}
if (version.summary === "Automatic save") {
summary = this.tr("automatic-save", "Automatic save");
}
if (version.summary === "Manual save") summary = this.tr("manual-save", "Manual save");
return summary;
}
loadButton(conceptMap, version) {
const load = document.createElement("button");
load.type = "button";
load.textContent = version.version === conceptMap.currentVersion ?
this.tr("current-version", "Current") : this.tr("load-version", "Load version");
load.disabled = version.version === conceptMap.currentVersion;
load.addEventListener("click", () => {
this.dialog.close();
this.loadVersion(version.version);
});
return load;
}
deleteButton(conceptMap, version, row) {
const remove = document.createElement("button");
remove.type = "button";
remove.textContent = this.tr("delete-history-item", "Delete");
remove.addEventListener("click", async () => {
const question = this.tr(
"delete-concept-map-history-confirm",
"Delete CMap history version {version}? The current CMap will not be changed.")
.replace("{version}", String(version.version));
if (!window.confirm(question)) return;
remove.disabled = true;
try {
await this.repository.deleteVersion(conceptMap, version.version);
row.remove();
if (!this.list.querySelector(".cmap-history-row")) this.showEmptyMessage();
this.showStatus(
this.tr("concept-map-history-deleted", "History item deleted"), true);
} catch (error) {
remove.disabled = false;
this.showStatus(error.message);
}
});
return remove;
}
}