feat(#37): Add prompt when leaving with unsaved changes
This commit is contained in:
@@ -97,6 +97,44 @@ const isReadOnly = computed(() => {
|
||||
return applicationForm.value?.createdBy?.keycloakId !== user.value?.keycloakId
|
||||
})
|
||||
|
||||
// Unsaved changes tracking
|
||||
const originalFormJson = ref<string>('')
|
||||
|
||||
onMounted(() => {
|
||||
originalFormJson.value = JSON.stringify(applicationForm.value)
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
const hasUnsavedChanges = computed(() => {
|
||||
if (!originalFormJson.value) return false
|
||||
return JSON.stringify(applicationForm.value) !== originalFormJson.value
|
||||
})
|
||||
|
||||
function handleBeforeUnload(e: BeforeUnloadEvent) {
|
||||
if (hasUnsavedChanges.value) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
// Allow navigation between sections of the same form
|
||||
if (to.params.id === from.params.id) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
if (hasUnsavedChanges.value) {
|
||||
const answer = window.confirm($t('applicationForms.unsavedWarning'))
|
||||
next(answer)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
|
||||
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)
|
||||
|
||||
@@ -126,6 +164,7 @@ async function onSave() {
|
||||
const updated = await updateForm(applicationForm.value.id, applicationForm.value)
|
||||
if (updated) {
|
||||
updateApplicationForm(updated)
|
||||
originalFormJson.value = JSON.stringify(updated)
|
||||
toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,38 @@ const applicationFormTemplate = computed(
|
||||
const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
|
||||
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)
|
||||
|
||||
// Unsaved changes tracking
|
||||
const originalFormJson = ref<string>('')
|
||||
|
||||
onMounted(() => {
|
||||
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
const hasUnsavedChanges = computed(() => {
|
||||
if (!originalFormJson.value) return false
|
||||
return JSON.stringify(applicationFormTemplate.value) !== originalFormJson.value
|
||||
})
|
||||
|
||||
function handleBeforeUnload(e: BeforeUnloadEvent) {
|
||||
if (hasUnsavedChanges.value) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((_to, _from, next) => {
|
||||
if (hasUnsavedChanges.value) {
|
||||
const answer = window.confirm($t('applicationForms.unsavedWarning'))
|
||||
next(answer)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
const allFormElements = computed(() => {
|
||||
return (
|
||||
applicationFormTemplate.value?.formElementSections?.flatMap((section: FormElementSectionDto) =>
|
||||
@@ -105,8 +137,11 @@ watch(
|
||||
|
||||
async function onSave() {
|
||||
const applicationForm = await prepareAndCreateApplicationForm()
|
||||
if (applicationForm) {
|
||||
if (applicationForm?.id) {
|
||||
// Reset to prevent unsaved changes warning when navigating
|
||||
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
|
||||
toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
|
||||
await navigateTo(`/application-forms/${applicationForm.id}/0`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +149,8 @@ async function onSubmit() {
|
||||
const applicationForm = await prepareAndCreateApplicationForm()
|
||||
if (applicationForm?.id) {
|
||||
await submitApplicationForm(applicationForm.id)
|
||||
// Reset to prevent unsaved changes warning when navigating
|
||||
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
|
||||
await navigateTo('/')
|
||||
toast.add({ title: $t('common.success'), description: $t('applicationForms.submitted'), color: 'success' })
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
"form": "Formular",
|
||||
"versions": "Versionen",
|
||||
"preview": "Vorschau"
|
||||
}
|
||||
},
|
||||
"unsavedWarning": "Sie haben ungespeicherte Änderungen. Möchten Sie die Seite wirklich verlassen?"
|
||||
},
|
||||
"templates": {
|
||||
"title": "Vorlagen",
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
"form": "Form",
|
||||
"versions": "Versions",
|
||||
"preview": "Preview"
|
||||
}
|
||||
},
|
||||
"unsavedWarning": "You have unsaved changes. Do you really want to leave this page?"
|
||||
},
|
||||
"templates": {
|
||||
"title": "Templates",
|
||||
|
||||
Reference in New Issue
Block a user