116 lines
4.4 KiB
JavaScript
116 lines
4.4 KiB
JavaScript
/**
|
|
* 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;
|
|
}
|
|
}
|