Help wanted #23
| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user