Streamline "maybe save" props
This commit is contained in:
parent
8e8bbb48ba
commit
34d5224c11
|
@ -3,47 +3,45 @@
|
|||
.modal-header: h5.modal-title(id="maybeSaveLabel") Unsaved Changes
|
||||
.modal-body You have modified the data on this page since it was last saved. What would you like to do?
|
||||
.modal-footer
|
||||
button.btn.btn-secondary(type="button" @click.prevent="onStay") Stay on This Page
|
||||
button.btn.btn-primary(type="button" @click.prevent="onSave") Save Changes
|
||||
button.btn.btn-danger(type="button" @click.prevent="onDiscard") Discard Changes
|
||||
button.btn.btn-secondary(type="button" @click.prevent="close") Stay on This Page
|
||||
button.btn.btn-primary(type="button" @click.prevent="save") Save Changes
|
||||
button.btn.btn-danger(type="button" @click.prevent="discard") Discard Changes
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, Ref, watch } from "vue"
|
||||
import { RouteLocationNormalized, useRouter } from "vue-router"
|
||||
import { onMounted, ref, Ref } from "vue"
|
||||
import { onBeforeRouteLeave, RouteLocationNormalized, useRouter } from "vue-router"
|
||||
import { Validation } from "@vuelidate/core"
|
||||
import { Modal } from "bootstrap"
|
||||
|
||||
const props = defineProps<{
|
||||
isShown: boolean
|
||||
toRoute: RouteLocationNormalized
|
||||
saveAction?: () => Promise<unknown>
|
||||
saveAction: () => Promise<unknown>
|
||||
validator?: Validation
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "close") : void
|
||||
(e: "discard") : void
|
||||
(e: "cancel") : void
|
||||
}>()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
/** Reference to the modal dialog (we can't get it until the component is rendered) */
|
||||
const modal : Ref<Modal | undefined> = ref(undefined)
|
||||
|
||||
/** Save changes (if required) and go to the next route */
|
||||
const onSave = async () => {
|
||||
if (props.saveAction) await props.saveAction()
|
||||
emit("close")
|
||||
router.push(props.toRoute)
|
||||
/** The route to which navigation was intercepted, and will be resumed */
|
||||
let nextRoute : RouteLocationNormalized
|
||||
|
||||
/** Close the modal window */
|
||||
const close = () => modal.value?.hide()
|
||||
|
||||
/** Save changes and go to the next route */
|
||||
const save = async () => {
|
||||
await props.saveAction()
|
||||
close()
|
||||
router.push(nextRoute)
|
||||
}
|
||||
|
||||
/** Discard changes (if required) and go to the next route */
|
||||
const onDiscard = () => {
|
||||
/** Discard changes and go to the next route */
|
||||
const discard = () => {
|
||||
if (props.validator) props.validator.$reset()
|
||||
emit("close")
|
||||
router.push(props.toRoute)
|
||||
close()
|
||||
router.push(nextRoute)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -51,17 +49,11 @@ onMounted(() => {
|
|||
{ backdrop: "static", keyboard: false })
|
||||
})
|
||||
|
||||
/** Show or hide the modal based on the property value changing */
|
||||
watch(() => props.isShown, (toShow) => {
|
||||
if (modal.value) {
|
||||
if (toShow) {
|
||||
modal.value.show()
|
||||
} else {
|
||||
modal.value.hide()
|
||||
}
|
||||
}
|
||||
/** Prompt for save if the user navigates away with unsaved changes */
|
||||
onBeforeRouteLeave(async (to, from) => { // eslint-disable-line
|
||||
if (!props.validator || !props.validator.$anyDirty) return true
|
||||
nextRoute = to
|
||||
modal.value?.show()
|
||||
return false
|
||||
})
|
||||
|
||||
/** Stay on this page with no changes; just close the modal */
|
||||
const onStay = () => emit("close")
|
||||
</script>
|
||||
|
|
|
@ -64,13 +64,11 @@ article
|
|||
p.text-muted.fst-italic.
|
||||
(If you want to delete your profile, or your entire account,
|
||||
#[router-link(to="/so-long/options") see your deletion options here].)
|
||||
maybe-save(:isShown="confirmNavShown" :toRoute="nextRoute" :saveAction="saveProfile" :validator="v$"
|
||||
@close="confirmClose")
|
||||
maybe-save(:saveAction="saveProfile" :validator="v$")
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, reactive, Ref } from "vue"
|
||||
import { onBeforeRouteLeave, RouteLocationNormalized } from "vue-router"
|
||||
import { computed, ref, reactive } from "vue"
|
||||
import useVuelidate from "@vuelidate/core"
|
||||
import { required } from "@vuelidate/validators"
|
||||
|
||||
|
@ -183,21 +181,4 @@ const saveProfile = async () => {
|
|||
v$.value.$reset()
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether the navigation confirmation is shown */
|
||||
const confirmNavShown = ref(false)
|
||||
|
||||
/** The "next" route (will be navigated or cleared) */
|
||||
const nextRoute : Ref<RouteLocationNormalized | undefined> = ref(undefined)
|
||||
|
||||
/** If the user has unsaved changes, give them an opportunity to save before moving on */
|
||||
onBeforeRouteLeave(async (to, from) => { // eslint-disable-line
|
||||
if (!v$.value.$anyDirty) return true
|
||||
nextRoute.value = to
|
||||
confirmNavShown.value = true
|
||||
return false
|
||||
})
|
||||
|
||||
/** Close the navigation confirmation modal */
|
||||
const confirmClose = () => { confirmNavShown.value = false }
|
||||
</script>
|
||||
|
|
|
@ -32,12 +32,12 @@ article
|
|||
.col-12
|
||||
p.text-danger(v-if="v$.$error") Please correct the errors above
|
||||
button.btn.btn-primary(@click.prevent="saveListing(true)") #[icon(icon="content-save-outline")] Save
|
||||
maybe-save(:isShown="confirmNavShown" :toRoute="nextRoute" :saveAction="doSave" :validator="v$" @close="confirmClose")
|
||||
maybe-save(:saveAction="doSave" :validator="v$")
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, Ref } from "vue"
|
||||
import { onBeforeRouteLeave, RouteLocationNormalized, useRoute, useRouter } from "vue-router"
|
||||
import { computed, reactive } from "vue"
|
||||
import { useRoute, useRouter } from "vue-router"
|
||||
import useVuelidate from "@vuelidate/core"
|
||||
import { required } from "@vuelidate/validators"
|
||||
|
||||
|
@ -130,23 +130,6 @@ const saveListing = async (navigate : boolean) => {
|
|||
}
|
||||
}
|
||||
|
||||
/** Whether the navigation confirmation is shown */
|
||||
const confirmNavShown = ref(false)
|
||||
|
||||
/** The "next" route (will be navigated or cleared) */
|
||||
const nextRoute : Ref<RouteLocationNormalized | undefined> = ref(undefined)
|
||||
|
||||
/** If the user has unsaved changes, give them an opportunity to save before moving on */
|
||||
onBeforeRouteLeave(async (to, from) => { // eslint-disable-line
|
||||
if (!v$.value.$anyDirty) return true
|
||||
nextRoute.value = to
|
||||
confirmNavShown.value = true
|
||||
return false
|
||||
})
|
||||
|
||||
/** Parameterless save function (used to save when navigating away) */
|
||||
const doSave = async () => await saveListing(false)
|
||||
|
||||
/** Close the navigation confirmation modal */
|
||||
const confirmClose = () => { confirmNavShown.value = false }
|
||||
</script>
|
||||
|
|
|
@ -18,12 +18,12 @@ article
|
|||
.col-12
|
||||
button.btn.btn-primary(@click.prevent="expireListing").
|
||||
#[icon(icon="text-box-remove-outline")] Expire Listing
|
||||
maybe-save(:isShown="confirmNavShown" :toRoute="nextRoute" :saveAction="doSave" :validator="v$" @close="confirmClose")
|
||||
maybe-save(:saveAction="doSave" :validator="v$")
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, Ref, ref } from "vue"
|
||||
import { onBeforeRouteLeave, RouteLocationNormalized, useRoute, useRouter } from "vue-router"
|
||||
import { useRoute, useRouter } from "vue-router"
|
||||
import useVuelidate from "@vuelidate/core"
|
||||
|
||||
import api, { Listing, ListingExpireForm, LogOnSuccess } from "@/api"
|
||||
|
@ -89,23 +89,6 @@ const expireListing = async (navigate : boolean) => {
|
|||
}
|
||||
}
|
||||
|
||||
/** Whether the navigation confirmation is shown */
|
||||
const confirmNavShown = ref(false)
|
||||
|
||||
/** The "next" route (will be navigated or cleared) */
|
||||
const nextRoute : Ref<RouteLocationNormalized | undefined> = ref(undefined)
|
||||
|
||||
/** Prompt for save if the user navigates away with unsaved changes */
|
||||
onBeforeRouteLeave(async (to, from) => { // eslint-disable-line
|
||||
if (!v$.value.$anyDirty) return true
|
||||
nextRoute.value = to
|
||||
confirmNavShown.value = true
|
||||
return false
|
||||
})
|
||||
|
||||
/** No-parameter save function (used for save-on-navigate) */
|
||||
const doSave = async () => await expireListing(false)
|
||||
|
||||
/** Close the confirm navigation modal */
|
||||
const confirmClose = () => { confirmNavShown.value = false }
|
||||
</script>
|
||||
|
|
|
@ -15,12 +15,12 @@ article
|
|||
button.btn.btn-primary(type="submit" @click.prevent="saveStory(true)").
|
||||
#[icon(icon="content-save-outline")] Save
|
||||
p(v-if="isNew"): em (Saving this will set “Seeking Employment” to “No” on your profile.)
|
||||
maybe-save(:isShown="confirmNavShown" :toRoute="nextRoute" :saveAction="doSave" :validator="v$" @close="confirmClose")
|
||||
maybe-save(:saveAction="doSave" :validator="v$")
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, Ref } from "vue"
|
||||
import { onBeforeRouteLeave, RouteLocationNormalized, useRoute, useRouter } from "vue-router"
|
||||
import { computed, reactive } from "vue"
|
||||
import { useRoute, useRouter } from "vue-router"
|
||||
import useVuelidate from "@vuelidate/core"
|
||||
|
||||
import api, { LogOnSuccess, StoryForm } from "@/api"
|
||||
|
@ -106,23 +106,6 @@ const saveStory = async (navigate : boolean) => {
|
|||
}
|
||||
}
|
||||
|
||||
/** Whether the navigation confirmation is shown */
|
||||
const confirmNavShown = ref(false)
|
||||
|
||||
/** The "next" route (will be navigated or cleared) */
|
||||
const nextRoute : Ref<RouteLocationNormalized | undefined> = ref(undefined)
|
||||
|
||||
/** Prompt for save if the user navigates away with unsaved changes */
|
||||
onBeforeRouteLeave(async (to, from) => { // eslint-disable-line
|
||||
if (!v$.value.$anyDirty) return true
|
||||
nextRoute.value = to
|
||||
confirmNavShown.value = true
|
||||
return false
|
||||
})
|
||||
|
||||
/** No-parameter save function (used for save-on-navigate) */
|
||||
const doSave = async () => await saveStory(false)
|
||||
|
||||
/** Close the confirm navigation modal */
|
||||
const confirmClose = () => { confirmNavShown.value = false }
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue
Block a user