mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-11-09 17:06:13 -06:00
Compare commits
1 Commits
8025af3cc8
...
web-core/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6510716ef8 |
@@ -1,8 +1,8 @@
|
||||
import type { XenApiNetwork } from '@/libs/xen-api/xen-api.types.ts'
|
||||
import { useNetworkDeleteJob } from '@/modules/network/jobs/network-delete.job.ts'
|
||||
import { useDeleteModal } from '@core/composables/modals/use-delete-modal.ts'
|
||||
import { useErrorModal } from '@core/composables/modals/use-error-modal.ts'
|
||||
import { useRouteQuery } from '@core/composables/route-query.composable.ts'
|
||||
import { useOverlay } from '@core/packages/overlay/use-overlay.ts'
|
||||
import { toComputed } from '@core/utils/to-computed.util.ts'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -23,12 +23,7 @@ export function useNetworkDelete(rawNetworks: MaybeRefOrGetter<XenApiNetwork[]>)
|
||||
|
||||
const { open: openNetworkDeleteModal } = useDeleteModal()
|
||||
|
||||
const { open: openNetworkDeleteErrorModal } = useOverlay({
|
||||
component: () => import('@core/components/modal/VtsErrorModal.vue'),
|
||||
events: {
|
||||
onClose: true,
|
||||
},
|
||||
})
|
||||
const { open: openNetworkDeleteErrorModal } = useErrorModal()
|
||||
|
||||
function deleteNetworks() {
|
||||
if (!canDeleteNetworks.value) {
|
||||
|
||||
13
@xen-orchestra/lite/src/route-map.d.ts
vendored
13
@xen-orchestra/lite/src/route-map.d.ts
vendored
@@ -408,6 +408,13 @@ declare module 'vue-router/auto-routes' {
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/story/web-core/modal/vts-error-modal': RouteRecordInfo<
|
||||
'/story/web-core/modal/vts-error-modal',
|
||||
'/story/web-core/modal/vts-error-modal',
|
||||
Record<never, never>,
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/story/web-core/object-icon/vts-object-icon': RouteRecordInfo<
|
||||
'/story/web-core/object-icon/vts-object-icon',
|
||||
'/story/web-core/object-icon/vts-object-icon',
|
||||
@@ -1421,6 +1428,12 @@ declare module 'vue-router/auto-routes' {
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/stories/web-core/modal/vts-error-modal.story.vue': {
|
||||
routes:
|
||||
| '/story/web-core/modal/vts-error-modal'
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/stories/web-core/object-icon/vts-object-icon.story.vue': {
|
||||
routes:
|
||||
| '/story/web-core/object-icon/vts-object-icon'
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Usage
|
||||
|
||||
Open the modal with `useErrorModal`.
|
||||
|
||||
```vue-script
|
||||
import { useErrorModal } from '@core/composables/modals/use-error-modal.ts'
|
||||
|
||||
const { open: openErrorModal } = useErrorModal()
|
||||
|
||||
try {
|
||||
// ...
|
||||
} catch (error) {
|
||||
void openErrorModal({
|
||||
props: {
|
||||
title: 'Unable to create cluster',
|
||||
error: 'An error occurred',
|
||||
details: error,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
The `details` prop is displayed below the message, even when the `content` slot is overridden:
|
||||
|
||||
```vue-template
|
||||
<VtsErrorModal title="Unable to delete network" :details @close="close()">
|
||||
<template #content>Custom error message</template>
|
||||
</VtsErrorModal>
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<ComponentStory
|
||||
v-slot="{ properties, settings }"
|
||||
:params="[
|
||||
prop('title').str().required().preset('Unable to create cluster').widget(),
|
||||
prop('error').str().preset('An error occurred').widget(),
|
||||
prop('details')
|
||||
.type('string | object')
|
||||
.preset(details1)
|
||||
.widget(object())
|
||||
.help('When set, displayed in a log entry viewer below the error message'),
|
||||
event('close'),
|
||||
slot('content').help('Replaces the error message. The details are still displayed below it'),
|
||||
setting('contentSlotContent').widget(text()).help('Leave empty to use the error prop'),
|
||||
]"
|
||||
:presets
|
||||
>
|
||||
<VtsErrorModal class="story" v-bind="properties">
|
||||
<template v-if="settings.contentSlotContent" #content>{{ settings.contentSlotContent }}</template>
|
||||
</VtsErrorModal>
|
||||
</ComponentStory>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ComponentStory from '@/components/component-story/ComponentStory.vue'
|
||||
import { event, prop, setting, slot } from '@/libs/story/story-param.ts'
|
||||
import { object, text } from '@/libs/story/story-widget.ts'
|
||||
import VtsErrorModal from '@core/components/modal/VtsErrorModal.vue'
|
||||
|
||||
const details1 = {
|
||||
code: 'HOST_NOT_ENOUGH_FREE_MEMORY',
|
||||
params: ['8589934592', '2147483648'],
|
||||
call: {
|
||||
method: 'VM.start',
|
||||
params: ['OpaqueRef:3f2a9c1e-7b4d-4e8a-9f6c-2d1b5a8e7c90', false, false],
|
||||
},
|
||||
}
|
||||
|
||||
const details2 =
|
||||
'TypeError: Failed to fetch\n at fetchApi (rest-api.ts:42:11)\n at async createCluster (cluster-create.job.ts:88:5)'
|
||||
|
||||
const presets = {
|
||||
'Without details': {
|
||||
props: { details: undefined },
|
||||
},
|
||||
'With details object': {
|
||||
props: { details: details1 },
|
||||
},
|
||||
'With details string': {
|
||||
props: { details: details2 },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.story {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,29 @@
|
||||
<template>
|
||||
<UiModal accent="danger" icon="status:danger-picto" @dismiss="emit('close')" @confirm="emit('close')">
|
||||
<UiModal
|
||||
class="vts-error-modal"
|
||||
accent="danger"
|
||||
icon="status:info-picto"
|
||||
@dismiss="emit('close')"
|
||||
@confirm="emit('close')"
|
||||
>
|
||||
<template #title>
|
||||
{{ title }}
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<slot name="content">
|
||||
{{ error }}
|
||||
</slot>
|
||||
<div class="content">
|
||||
<slot name="content">
|
||||
{{ error }}
|
||||
</slot>
|
||||
<UiLogEntryViewer
|
||||
v-if="details !== undefined"
|
||||
:label="t('see-details')"
|
||||
:content="details"
|
||||
accent="danger"
|
||||
size="small"
|
||||
class="details"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #buttons>
|
||||
@@ -20,12 +36,14 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import VtsOverlayConfirmButton from '@core/components/overlay/VtsOverlayConfirmButton.vue'
|
||||
import UiLogEntryViewer from '@core/components/ui/log-entry-viewer/UiLogEntryViewer.vue'
|
||||
import UiModal from '@core/components/ui/modal/UiModal.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{
|
||||
title: string
|
||||
error?: string
|
||||
details?: string | object
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -38,3 +56,19 @@ defineSlots<{
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.vts-error-modal {
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.details {
|
||||
text-align: start;
|
||||
/* The small action buttons must not overflow the scrollable modal content */
|
||||
overflow-x: clip;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useOverlay } from '@core/packages/overlay/use-overlay.ts'
|
||||
|
||||
export function useErrorModal() {
|
||||
return useOverlay({
|
||||
component: () => import('@core/components/modal/VtsErrorModal.vue'),
|
||||
events: {
|
||||
onClose: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
<template>
|
||||
<VtsErrorModal :title="t('unable-to-delete-network')" @close="emit('close')">
|
||||
<template #content>
|
||||
{{ error ?? t('error') }}
|
||||
<template v-if="showConnectedVifsMessage">
|
||||
<br />
|
||||
<I18nT keypath="disconnect-vifs-in-xo-5-to-delete-network" scope="global">
|
||||
<template #xo-5>
|
||||
<UiLink :href="xo5Link" size="medium">
|
||||
{{ t('xo-5') }}
|
||||
</UiLink>
|
||||
</template>
|
||||
</I18nT>
|
||||
</template>
|
||||
<p>{{ error ?? t('error') }}</p>
|
||||
<I18nT v-if="showConnectedVifsMessage" keypath="disconnect-vifs-in-xo-5-to-delete-network" scope="global" tag="p">
|
||||
<template #xo-5>
|
||||
<UiLink :href="xo5Link" size="medium">
|
||||
{{ t('xo-5') }}
|
||||
</UiLink>
|
||||
</template>
|
||||
</I18nT>
|
||||
</template>
|
||||
</VtsErrorModal>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user