mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-10-12 02:24:05 +00:00
fix(xo6): prevent unwanted inherited route params (#10511)
This commit is contained in:
@@ -376,15 +376,69 @@ See [named routes documentation](https://router.vuejs.org/guide/essentials/named
|
||||
❌ Bad
|
||||
|
||||
```vue
|
||||
<UiLink :to="`/vm/${vm.id}/dashboard`">
|
||||
{{ t('dashboard') }}
|
||||
</UiLink>
|
||||
<template>
|
||||
<UiLink :to="`/vm/${vm.id}/dashboard`">
|
||||
{{ t('dashboard') }}
|
||||
</UiLink>
|
||||
</template>
|
||||
```
|
||||
|
||||
✅ Good
|
||||
|
||||
```vue
|
||||
<UiLink :to="{ name: '/vm/[id]/dashboard', params: { id: vm.id } }">
|
||||
{{ t('dashboard') }}
|
||||
</UiLink>
|
||||
<template>
|
||||
<UiLink :to="{ name: '/vm/[id]/dashboard', params: { id: vm.id } }">
|
||||
{{ t('dashboard') }}
|
||||
</UiLink>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Route params MUST NOT be passed as `undefined`
|
||||
|
||||
When building a named route location for `<UiLink>`, `<RouterLink>`, or `router.push()`, Vue Router merges params with the active route. If a param value is `undefined`, the router reuses the current route’s param with the same name, which produces incorrect URLs.
|
||||
|
||||
Either use a computed to return `undefined` as the route (disabling the link while still showing the component), or guard the link with a `v-if` (hide the link entirely).
|
||||
|
||||
❌ Bad
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UiLink :to="{ name: '/vdi/[id]/general', params: { id: vdi.$snapshot_of } }">
|
||||
{{ vdi.name_label }}
|
||||
</UiLink>
|
||||
</template>
|
||||
```
|
||||
|
||||
✅ Good
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UiLink :to="vdiRoute">{{ vdi.name_label }}</UiLink>
|
||||
</template
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { RouteLocationAsRelative } from 'vue-router'
|
||||
|
||||
const vdiRoute = computed<RouteLocationAsRelative | undefined>(() => {
|
||||
if (!vdi.$snapshot_of) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
name: '/vdi/[id]/general',
|
||||
params: { id: vdi.$snapshot_of },
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
✅ Also good
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UiLink v-if="vdi.$snapshot_of" :to="{ name: '/vdi/[id]/general', params: { id: vdi.$snapshot_of } }">
|
||||
{{ vdi.name_label }}
|
||||
</UiLink>
|
||||
</template>
|
||||
```
|
||||
|
||||
+14
-6
@@ -4,12 +4,7 @@
|
||||
{{ t('run') }}
|
||||
</template>
|
||||
<template #value>
|
||||
<UiLink
|
||||
v-if="backupRun.id"
|
||||
size="small"
|
||||
icon="object:backup-run"
|
||||
:to="{ name: '/backup/[id]/runs', params: { id: backupRun.jobId }, query: { id: backupRun.id } }"
|
||||
>
|
||||
<UiLink size="small" icon="object:backup-run" :to="backupRunRoute">
|
||||
{{ backupRun.id }}
|
||||
</UiLink>
|
||||
</template>
|
||||
@@ -66,6 +61,7 @@ import UiLink from '@core/components/ui/link/UiLink.vue'
|
||||
import UiLogEntryViewer from '@core/components/ui/log-entry-viewer/UiLogEntryViewer.vue'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { RouteLocationAsRelative } from 'vue-router'
|
||||
|
||||
const { backupRun } = defineProps<{
|
||||
backupRun: FrontXoBackupLog
|
||||
@@ -91,4 +87,16 @@ const logContent = computed(() => {
|
||||
})
|
||||
|
||||
const scheduleName = computed(() => schedules.value.find(schedule => schedule.jobId === backupRun.jobId)?.name)
|
||||
|
||||
const backupRunRoute = computed<RouteLocationAsRelative | undefined>(() => {
|
||||
if (!backupRun.jobId) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
name: '/backup/[id]/runs',
|
||||
params: { id: backupRun.jobId },
|
||||
query: { id: backupRun.id },
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+15
-5
@@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<UiLink
|
||||
:to="{ name: '/vdi/[id]/general', params: { id: vdi.$snapshot_of }, query: { from: VDI_PAGE_CONTEXT.SNAPSHOT } }"
|
||||
:icon="vbdsSnapshotStatus"
|
||||
size="medium"
|
||||
>
|
||||
<UiLink :to="vdiRoute" :icon="vbdsSnapshotStatus" size="medium">
|
||||
{{ vdi.name_label }}
|
||||
</UiLink>
|
||||
</template>
|
||||
@@ -15,6 +11,8 @@ import { VDI_PAGE_CONTEXT } from '@/shared/constants.ts'
|
||||
import type { IconName } from '@core/icons'
|
||||
import UiLink from '@core/components/ui/link/UiLink.vue'
|
||||
import { useMapper } from '@core/packages/mapper'
|
||||
import { computed } from 'vue'
|
||||
import type { RouteLocationAsRelative } from 'vue-router'
|
||||
|
||||
const { vdi } = defineProps<{ vdi: FrontXoVdiSnapshot }>()
|
||||
|
||||
@@ -29,4 +27,16 @@ const vbdsSnapshotStatus = useMapper<VbdAttachmentStatus, IconName>(
|
||||
},
|
||||
'someAttached'
|
||||
)
|
||||
|
||||
const vdiRoute = computed<RouteLocationAsRelative | undefined>(() => {
|
||||
if (!vdi.$snapshot_of) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
name: '/vdi/[id]/general',
|
||||
params: { id: vdi.$snapshot_of },
|
||||
query: { from: VDI_PAGE_CONTEXT.SNAPSHOT },
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
- [Backup/replication] fix to ensure distributed replications are deleted according to retention( PR [#10491] (https://github.com/vatesfr/xen-orchestra/pull/10491))
|
||||
- [Replication] Fix `Cannot read properties of undefined (reading 'get')` error on continuous replication to multiple SRs (PR [#10519](https://github.com/vatesfr/xen-orchestra/pull/10519))
|
||||
- [VM/Snapshot] In the side panel, correctly filter VDIs associated with the VM snapshot (PR [#10510](https://github.com/vatesfr/xen-orchestra/pull/10510))
|
||||
|
||||
- [XO6] Fix sometimes incorrect IDs in URLs (PR [#10511](https://github.com/vatesfr/xen-orchestra/pull/10511))
|
||||
|
||||
### Packages to release
|
||||
|
||||
|
||||
Reference in New Issue
Block a user