feat: Unsaved changes confirmation (#4)

pull/3756/head
Laurynas Gadliauskas 2021-06-01 12:35:56 +03:00 committed by GitHub
parent 641b3c45ed
commit b098e4cb99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 5 deletions

View File

@ -115,6 +115,7 @@
}, },
"permanent": "Permanent", "permanent": "Permanent",
"prompts": { "prompts": {
"unsavedChanges": "Changes that you made may not be saved. Leave page?",
"archive": "Archive", "archive": "Archive",
"archiveMessage": "Choose archive name and format:", "archiveMessage": "Choose archive name and format:",
"unarchive": "Unarchive", "unarchive": "Unarchive",

View File

@ -5,7 +5,11 @@
<breadcrumbs base="/files" /> <breadcrumbs base="/files" />
<errors v-if="error" :errorCode="error.message" /> <errors v-if="error" :errorCode="error.message" />
<component v-else-if="currentView" :is="currentView"></component> <component
v-else-if="currentView"
:is="currentView"
@changed="setChanged"
></component>
<div v-else> <div v-else>
<h2 class="message delayed"> <h2 class="message delayed">
<div class="spinner"> <div class="spinner">
@ -47,6 +51,7 @@ export default {
return { return {
error: null, error: null,
width: window.innerWidth, width: window.innerWidth,
unsavedChanges: false,
}; };
}, },
computed: { computed: {
@ -68,6 +73,12 @@ export default {
} }
}, },
}, },
beforeRouteUpdate(to, from, next) {
this.verifyRouteChange(next);
},
beforeRouteLeave(to, from, next) {
this.verifyRouteChange(next);
},
created() { created() {
this.fetchData(); this.fetchData();
}, },
@ -92,6 +103,21 @@ export default {
this.$store.commit("updateRequest", {}); this.$store.commit("updateRequest", {});
}, },
methods: { methods: {
verifyRouteChange(next) {
if (
this.currentView === "editor" &&
this.unsavedChanges &&
!confirm(this.$t("prompts.unsavedChanges"))
) {
next(false);
} else {
this.unsavedChanges = false;
next();
}
},
setChanged(value) {
this.unsavedChanges = value;
},
...mapMutations(["setLoading"]), ...mapMutations(["setLoading"]),
async fetchData() { async fetchData() {
// Reset view information. // Reset view information.

View File

@ -44,7 +44,9 @@ export default {
Breadcrumbs, Breadcrumbs,
}, },
data: function () { data: function () {
return {}; return {
unsavedChanges: false,
};
}, },
computed: { computed: {
...mapState(["req", "user"]), ...mapState(["req", "user"]),
@ -78,10 +80,17 @@ export default {
return breadcrumbs; return breadcrumbs;
}, },
}, },
watch: {
unsavedChanges() {
this.$emit("changed", this.unsavedChanges);
},
},
created() { created() {
window.addEventListener("beforeunload", this.beforeWindowUnload);
window.addEventListener("keydown", this.keyEvent); window.addEventListener("keydown", this.keyEvent);
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener("beforeunload", this.beforeWindowUnload);
window.removeEventListener("keydown", this.keyEvent); window.removeEventListener("keydown", this.keyEvent);
this.editor.destroy(); this.editor.destroy();
}, },
@ -97,14 +106,18 @@ export default {
wrap: true, wrap: true,
}); });
this.editor.on("change", () => (this.unsavedChanges = true));
if (theme == "dark") { if (theme == "dark") {
this.editor.setTheme("ace/theme/twilight"); this.editor.setTheme("ace/theme/twilight");
} }
}, },
methods: { methods: {
back() { beforeWindowUnload(e) {
let uri = url.removeLastDir(this.$route.path) + "/"; if (this.unsavedChanges) {
this.$router.push({ path: uri }); e.preventDefault();
e.returnValue = "";
}
}, },
keyEvent(event) { keyEvent(event) {
if (!event.ctrlKey && !event.metaKey) { if (!event.ctrlKey && !event.metaKey) {
@ -121,6 +134,7 @@ export default {
async save() { async save() {
const button = "save"; const button = "save";
buttons.loading("save"); buttons.loading("save");
this.unsavedChanges = false;
try { try {
await api.put(this.$route.path, this.editor.getValue()); await api.put(this.$route.path, this.editor.getValue());
@ -131,6 +145,10 @@ export default {
} }
}, },
close() { close() {
if (this.unsavedChanges && !confirm(this.$t("prompts.unsavedChanges"))) {
return;
}
this.$store.commit("updateRequest", {}); this.$store.commit("updateRequest", {});
let uri = url.removeLastDir(this.$route.path) + "/"; let uri = url.removeLastDir(this.$route.path) + "/";