mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-23 00:24:19 +08:00
This commit converts the Backups page in the admin interface to follow our new admin interface guidelines. As part of this work, I've also made `AdminPageHeader` and `AdminPageSubheader` components that can be reused on any admin page for consistency, that handle the title and action buttons and also breadcrumbs. Also renamed `AdminPluginFilteredSiteSettings` to `AdminFilteredSiteSettings` since it can be used generally to show a subset of filtered site settings, not only settings for a plugin. Not sure if it's ideal to have to define a new route for this for every config area, but not sure how else to do it right now.
181 lines
4.9 KiB
JavaScript
Vendored
181 lines
4.9 KiB
JavaScript
Vendored
import EmberObject, { action } from "@ember/object";
|
|
import { service } from "@ember/service";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import { extractError } from "discourse/lib/ajax-error";
|
|
import PreloadStore from "discourse/lib/preload-store";
|
|
import DiscourseRoute from "discourse/routes/discourse";
|
|
import getURL from "discourse-common/lib/get-url";
|
|
import { bind } from "discourse-common/utils/decorators";
|
|
import I18n from "discourse-i18n";
|
|
import StartBackupModal from "admin/components/modal/start-backup";
|
|
import Backup from "admin/models/backup";
|
|
import BackupStatus from "admin/models/backup-status";
|
|
|
|
const LOG_CHANNEL = "/admin/backups/logs";
|
|
|
|
export default class AdminBackupsRoute extends DiscourseRoute {
|
|
@service currentUser;
|
|
@service dialog;
|
|
@service router;
|
|
@service messageBus;
|
|
@service modal;
|
|
|
|
titleToken() {
|
|
return I18n.t("admin.backups.title");
|
|
}
|
|
|
|
activate() {
|
|
this.messageBus.subscribe(LOG_CHANNEL, this.onMessage);
|
|
}
|
|
|
|
deactivate() {
|
|
this.messageBus.unsubscribe(LOG_CHANNEL, this.onMessage);
|
|
}
|
|
|
|
async model() {
|
|
const status = await PreloadStore.getAndRemove("operations_status", () =>
|
|
ajax("/admin/backups/status.json")
|
|
);
|
|
|
|
return BackupStatus.create({
|
|
isOperationRunning: status.is_operation_running,
|
|
canRollback: status.can_rollback,
|
|
allowRestore: status.allow_restore,
|
|
});
|
|
}
|
|
|
|
@bind
|
|
onMessage(log) {
|
|
if (log.message === "[STARTED]") {
|
|
this.currentUser.set("hideReadOnlyAlert", true);
|
|
this.controllerFor("adminBackups").set("model.isOperationRunning", true);
|
|
this.controllerFor("adminBackupsLogs").get("logs").clear();
|
|
} else if (log.message === "[FAILED]") {
|
|
this.controllerFor("adminBackups").set("model.isOperationRunning", false);
|
|
this.dialog.alert(
|
|
I18n.t("admin.backups.operations.failed", {
|
|
operation: log.operation,
|
|
})
|
|
);
|
|
} else if (log.message === "[SUCCESS]") {
|
|
this.currentUser.set("hideReadOnlyAlert", false);
|
|
this.controllerFor("adminBackups").set("model.isOperationRunning", false);
|
|
if (log.operation === "restore") {
|
|
// redirect to homepage when the restore is done (session might be lost)
|
|
window.location = getURL("/");
|
|
}
|
|
} else {
|
|
this.controllerFor("adminBackupsLogs")
|
|
.get("logs")
|
|
.pushObject(EmberObject.create(log));
|
|
}
|
|
}
|
|
|
|
@action
|
|
showStartBackupModal() {
|
|
this.modal.show(StartBackupModal, {
|
|
model: { startBackup: this.startBackup },
|
|
});
|
|
}
|
|
|
|
@action
|
|
startBackup(withUploads) {
|
|
this.router.transitionTo("admin.backups.logs");
|
|
Backup.start(withUploads).then((result) => {
|
|
if (!result.success) {
|
|
this.dialog.alert(result.message);
|
|
}
|
|
});
|
|
}
|
|
|
|
@action
|
|
destroyBackup(backup) {
|
|
return this.dialog.yesNoConfirm({
|
|
message: I18n.t("admin.backups.operations.destroy.confirm"),
|
|
didConfirm: () => {
|
|
backup
|
|
.destroy()
|
|
.then(() =>
|
|
this.controllerFor("adminBackupsIndex")
|
|
.get("model")
|
|
.removeObject(backup)
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
@action
|
|
startRestore(backup) {
|
|
this.dialog.yesNoConfirm({
|
|
message: I18n.t("admin.backups.operations.restore.confirm"),
|
|
didConfirm: () => {
|
|
this.router.transitionTo("admin.backups.logs");
|
|
backup.restore();
|
|
},
|
|
});
|
|
}
|
|
|
|
@action
|
|
cancelOperation() {
|
|
this.dialog.yesNoConfirm({
|
|
message: I18n.t("admin.backups.operations.cancel.confirm"),
|
|
didConfirm: () => {
|
|
Backup.cancel().then(() => {
|
|
this.controllerFor("adminBackups").set(
|
|
"model.isOperationRunning",
|
|
false
|
|
);
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
@action
|
|
rollback() {
|
|
return this.dialog.yesNoConfirm({
|
|
message: I18n.t("admin.backups.operations.rollback.confirm"),
|
|
didConfirm: () => {
|
|
Backup.rollback().then((result) => {
|
|
if (!result.success) {
|
|
this.dialog.alert(result.message);
|
|
} else {
|
|
// redirect to homepage (session might be lost)
|
|
window.location = getURL("/");
|
|
}
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
@action
|
|
uploadSuccess(filename) {
|
|
this.dialog.alert(I18n.t("admin.backups.upload.success", { filename }));
|
|
}
|
|
|
|
@action
|
|
uploadError(filename, message) {
|
|
this.dialog.alert(
|
|
I18n.t("admin.backups.upload.error", { filename, message })
|
|
);
|
|
}
|
|
|
|
@action
|
|
remoteUploadSuccess() {
|
|
Backup.find()
|
|
.then((backups) => backups.map((backup) => Backup.create(backup)))
|
|
.then((backups) => {
|
|
this.controllerFor("adminBackupsIndex").set(
|
|
"model",
|
|
backups.map((backup) => Backup.create(backup))
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
this.dialog.alert(
|
|
I18n.t("admin.backups.backup_storage_error", {
|
|
error_message: extractError(error),
|
|
})
|
|
);
|
|
return [];
|
|
});
|
|
}
|
|
}
|