Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add confirm-route-leave composable #5121

Merged
merged 10 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/web/src/common/components/modals/ConfirmBackModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
import DeleteModal from '@/common/components/modals/DeleteModal.vue';

const props = defineProps<{
visible: boolean
visible: boolean;
hideCloseButton?: boolean;
}>();
const emit = defineEmits<{(e: 'update:visible', value: boolean): void;
(e: 'confirm'): void;
(e: 'close'): void;
(e: 'cancel'): void;
}>();
const handleClickConfirm = () => {
emit('update:visible', false);
Expand All @@ -18,7 +21,10 @@ const handleClickConfirm = () => {
:header-title="$t('COMMON.CONFIRM_BACK_MODAL.TITLE')"
:visible="props.visible"
:contents="$t('COMMON.CONFIRM_BACK_MODAL.CANNOT_CANCEL')"
:hide-close-button="props.hideCloseButton"
@update:visible="emit('update:visible', $event)"
@confirm="handleClickConfirm"
@close="emit('close')"
@cancel="emit('cancel')"
/>
</template>
5 changes: 5 additions & 0 deletions apps/web/src/common/components/modals/DeleteModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
:hide-footer="hideFooter"
theme-color="alert"
:loading="loading"
:hide-header-close-button="hideCloseButton"
@confirm="handleConfirm"
@close="$emit('close')"
@cancel="$emit('cancel')"
Expand Down Expand Up @@ -96,6 +97,10 @@ export default {
type: Boolean,
default: false,
},
hideCloseButton: {
type: Boolean,
default: false,
},
},
setup(props, { emit }: SetupContext) {
const state = reactive({
Expand Down
52 changes: 52 additions & 0 deletions apps/web/src/common/composables/confirm-route-leave/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { Ref } from 'vue';
import {
ref, readonly,
} from 'vue';
import type { Location } from 'vue-router';

// CAUTION: Do not change to useRouter() because useRouter is only available in script setup
import { SpaceRouter } from '@/router';

export const useConfirmRouteLeave = ({
passConfirmation,
}: {
passConfirmation?: Ref<boolean>
} = {}) => {
const isConfirmLeaveModalVisible = ref(false);
const isConfirmed = ref(false);
let nextRoute: Location|undefined;

const openConfirmBackModal = () => {
isConfirmLeaveModalVisible.value = true;
};
const confirmRouteLeave = () => {
isConfirmed.value = true;
isConfirmLeaveModalVisible.value = false;
if (nextRoute) SpaceRouter.router.push(nextRoute);
};
const stopRouteLeave = () => {
isConfirmLeaveModalVisible.value = false;
nextRoute = undefined;
};

const handleBeforeRouteLeave = (to, from, next) => {
if (passConfirmation?.value) {
next();
return;
}
if (!isConfirmed.value) {
nextRoute = to;
openConfirmBackModal();
next(false);
} else {
next();
}
};

return {
isConfirmLeaveModalVisible: readonly(isConfirmLeaveModalVisible),
confirmRouteLeave,
stopRouteLeave,
handleBeforeRouteLeave,
};
};
2 changes: 2 additions & 0 deletions apps/web/src/common/composables/go-back/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Location } from 'vue-router';

// CAUTION: Do not change to useRouter() because useRouter is only available in script setup
import { SpaceRouter } from '@/router';

export const useGoBack = (mainRoute: Location) => {
Expand All @@ -21,5 +22,6 @@ export const useGoBack = (mainRoute: Location) => {
return {
setPathFrom,
handleClickBackButton,
goBack: handleClickBackButton,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
PSpinner,
} from '@cloudforet/mirinae';

const props = defineProps<{
loading: boolean;
}>();
</script>

<template>
<div class="relative">
<div v-show="props.loading"
class="absolute flex flex-col px-4 w-full"
>
<p-spinner size="md" />
</div>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ import * as PFieldGroupStories from './PFieldGroup.stories';

<br/>

## No Spacing
<Canvas of={PFieldGroupStories.NoSpacing} />

<br/>

## Playground
<Canvas of={PFieldGroupStories.Playground} />
<Controls of={PFieldGroupStories.Playground} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const Template: Story = {
:help-text="helpText" :required="required"
:label="label"
:style-type="styleType"
:no-spacing="noSpacing"
>
<template v-if="labelSlot" #label>
<div v-html="labelSlot"/>
Expand Down Expand Up @@ -135,6 +136,32 @@ export const StyleType: Story = {
}),
};

export const NoSpacing: Story = {
render: () => ({
components: { PFieldGroup, PTextInput },
template: `
<div>
<p-field-group label="Primary" style-type="primary" no-spacing>
<p-text-input value="Wanjin"/>
</p-field-group>
<br/>
<p-field-group label="Secondary" style-type="secondary" no-spacing>
<p-text-input value="Wanjin"/>
</p-field-group>
<br/>
<p-field-group label="Invalid Text" invalid invalid-text="name is required field." no-spacing>
<p-text-input placeholder="Name" invalid value=""/>
</p-field-group>
<br/>
<p-field-group label="Valid Text" valid valid-text="this is an appropriate name." no-spacing>
<p-text-input placeholder="Name" value="Wanjin"/>
</p-field-group>
<br/>
</div>
`,
}),
};

export const Playground: Story = {
...Template,
};
32 changes: 30 additions & 2 deletions packages/mirinae/src/controls/forms/field-group/PFieldGroup.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="p-field-group"
:class="[styleType]"
:class="{[styleType]: true, 'no-spacing': noSpacing}"
>
<div class="field-title-box">
<p-field-title v-if="label || $scopedSlots.label"
Expand Down Expand Up @@ -61,6 +61,7 @@ interface Props {
valid?: boolean;
required?: boolean;
styleType?: FieldGroupStyleType;
noSpacing?: boolean;
}

export default defineComponent<Props>({
Expand Down Expand Up @@ -99,6 +100,10 @@ export default defineComponent<Props>({
type: String,
default: 'primary',
},
noSpacing: {
type: Boolean,
default: false,
},
},
});
</script>
Expand All @@ -124,8 +129,8 @@ export default defineComponent<Props>({
font-size: 0.75rem;
line-height: 1.4;
margin-left: 0.25rem;
margin-bottom: 0.25rem;
font-weight: normal;
margin-bottom: 0.25rem;
}
.help-msg {
@apply block mb-2;
Expand All @@ -148,6 +153,29 @@ export default defineComponent<Props>({
.is-invalid {
@apply border border-alert;
}
&.no-spacing {
&.primary {
margin-bottom: 0;
}
&.secondary {
margin-bottom: 0;
}
.form-label {
padding-bottom: 0;
}
.optional-mark {
margin-bottom: 0;
}
.help-msg {
margin-bottom: 0;
}
.invalid-feedback {
margin-top: 0;
}
.valid-feedback {
margin-top: 0;
}
}
}

</style>
16 changes: 16 additions & 0 deletions packages/mirinae/src/controls/forms/field-group/story-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const getPFieldGroupArgs = (): Args => ({
valid: false,
required: false,
styleType: 'primary',
noSpacing: false,
labelSlot: null,
labelExtraSlot: null,
validSlot: null,
Expand Down Expand Up @@ -147,6 +148,21 @@ export const getPFieldGroupArgTypes = (): ArgTypes => ({
control: 'select',
options: ['primary', 'secondary'],
},
noSpacing: {
name: 'noSpacing',
type: { name: 'boolean' },
description: 'Props for hide spacing',
table: {
type: {
summary: 'boolean',
},
category: 'props',
defaultValue: {
summary: false,
},
},
control: 'boolean',
},
labelSlot: {
name: 'label',
description: 'Slot for label',
Expand Down
3 changes: 3 additions & 0 deletions packages/mirinae/src/data-display/badge/PBadge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ const state = reactive({
@mixin subtle gray200, theme('colors.gray.200'), theme('colors.gray.900');
@mixin subtle yellow200, theme('colors.yellow.200'), theme('colors.gray.900');
@mixin subtle red100, theme('colors.red.100'), theme('colors.red.500');
@mixin subtle peacock200, theme('colors.peacock.200'), theme('colors.peacock.700');
@mixin subtle coral200, theme('colors.coral.200'), theme('colors.coral.700');
@mixin subtle red200, theme('colors.red.200'), theme('colors.red.700');
}

</style>
3 changes: 3 additions & 0 deletions packages/mirinae/src/data-display/badge/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export const SUBTLE_STYLE_TYPE = {
gray200: 'gray200',
yellow200: 'yellow200',
red100: 'red100',
peacock200: 'peacock200',
coral200: 'coral200',
red200: 'red200',
} as const;
export const BADGE_STYLE_TYPE = {
...SOLID_STYLE_TYPE,
Expand Down
Loading