refactoring of cmaps, widgets, etc.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user