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

fix: redirect redirect/returnLink with query #129

Merged
merged 1 commit into from
Nov 28, 2023
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
2 changes: 1 addition & 1 deletion src/components/EntityForm/EntityForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export default {
if (this.onFormCancel) {
this.onFormCancel()
} else if (this.redirectPath) {
this.$router.push({ path: this.redirectPath })
this.$router.push(this.redirectPath)
} else if (this.$router.previous) {
this.$router.push({ ...this.$router.previous })
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/components/EntityForm/NativeEntityForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ export default {
if (this.onFormCancel) {
return this.onFormCancel()
} else if (this.redirectPath) {
return this.$router.push({ path: this.redirectPath })
return this.$router.push(this.redirectPath)
} else if (this.$router.previous) {
return this.$router.push({ ...this.$router.previous })
} else {
Expand Down
10 changes: 5 additions & 5 deletions src/components/EntityForm/mixins/FormPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default {
*/
redirectRoute () {
if (this.redirectPath) {
return { path: this.redirectPath }
return this.redirectPath
}

return { name: this.resourceEndpoint }
Expand Down Expand Up @@ -92,10 +92,10 @@ export default {
return redirectCreateRoute === '-1' ? this.$router.go(-1) : this.$router.push({ name: redirectCreateRoute, params: this.$router.params })
}

const link = this.redirectPath || this.returnLink || this.$route.query.returnLink
const link = this.redirectPath || this.returnLink

if (link) {
return this.$router.push({ path: link })
return this.$router.push(link)
}

const location = typeof callback === 'function'
Expand All @@ -111,7 +111,7 @@ export default {
async updateRecord (model) {
return apiService.updateRecord(this.resourceEndpoint, this.id, model)
.then(res => {
const link = this.redirectPath || this.returnLink || this.$route.query.returnLink || this.$route.query.redirect
const link = this.redirectPath || this.returnLink

// if parent form defines a redirectRouteNames object, we either go back to previous page if -1 is passed
// else we go to the named route
Expand All @@ -121,7 +121,7 @@ export default {
}

if (link) {
return this.$router.push({ path: link })
return this.$router.push(link)
}

redirectOnResponseStatus(this.$router, 200, { name: this.resourceEndpoint })(res)
Expand Down
30 changes: 24 additions & 6 deletions src/components/EntityForm/mixins/RedirectMixin.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
const extractRedirectPath = ($route, urlKey) => {
const query = $route.query[urlKey]
let url = null

if (Array.isArray(query)) {
url = query[0]
console.warn(`extractRedirectPath: "${urlKey}" in query should not be an array, using first element this time`)
} else if (typeof query === 'string') {
url = query
}

return url
}

export default {
computed: {
redirectPath () {
return this.$route.query.redirect
return extractRedirectPath(this.$route, 'redirect')
},
redirectRouteQuery () {
return { redirect: this.redirectPath }
},
postDeletePath () {
return this.$route.query.postDelete
return extractRedirectPath(this.$route, 'postDelete')
},
postDeleteRouteQuery () {
return { postDelete: this.postDeletePath }
},
},
methods: {
createRedirectRouteQuery (redirectPath = this.$route.fullPath) {
return { redirect: redirectPath }
createRedirectRouteQuery (redirect = this.$route.fullPath) {
return { redirect }
},
createPostDeleteRouteQuery (postDeletePath = this.postDeletePath || this.$route.fullPath) {
return { postDelete: postDeletePath }
createPostDeleteRouteQuery (postDelete) {
if (typeof postDelete !== 'string') {
postDelete = this.postDeletePath ?? this.$route.fullPath
}

return { postDelete }
},
redirect (replace = false, goBack = false) {
const routerFn = replace ? this.$router.replace : this.$router.push
Expand Down
28 changes: 15 additions & 13 deletions src/components/HeaderBackButton.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
<template>
<KButton
data-testid="header-back-button"
:to="backPath"
appearance="tertiary"
@click="back"
>
{{ t('global.buttons.back') }}
</KButton>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useRouter } from 'vue-router'
import type { RouteLocationRaw } from 'vue-router'

import { useI18n } from '@/composables/useI18n'
import { useURLFromRouteQuery } from '@/composables/useRedirect'

const props = defineProps({
entity: {
Expand All @@ -21,19 +23,19 @@ const props = defineProps({
},
})

const route = useRoute()
const { t } = useI18n()
const router = useRouter()
const redirectURL = useURLFromRouteQuery('redirect')

const backPath = computed(() => {
const { query } = route
if (query?.redirect) {
return {
path: query.redirect,
}
const back = () => {
let backTo: RouteLocationRaw = {
name: props.entity ? `${props.entity}-list` : 'overview',
}

return {
name: props.entity ? `${props.entity}-list` : 'overview',
if (redirectURL.value) {
backTo = redirectURL.value
}
})

router.replace(backTo)
}
</script>
26 changes: 15 additions & 11 deletions src/composables/useFormRedirect.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { computed } from 'vue'
import { useRoute, useRouter, type RouteLocationRaw, type MatcherLocationAsPath } from 'vue-router'
import { useRouter } from 'vue-router'
import type { RouteLocationRaw } from 'vue-router'

import { useURLFromRouteQuery } from './useRedirect'

export const useFormRedirectOnCancel = (fallback: RouteLocationRaw) => {
const route = useRoute()
const router = useRouter()
const redirectPath = computed(() => route.query.redirect)
const redirectRouteLocation = useURLFromRouteQuery('redirect')

const routeOnCancel = computed(() => {
if (redirectPath.value) {
return { path: redirectPath.value } as MatcherLocationAsPath
if (redirectRouteLocation.value) {
return redirectRouteLocation.value
}

const previousPath = router.options?.history?.state?.back
if (previousPath) {
return { path: previousPath } as MatcherLocationAsPath
if (typeof previousPath === 'string') {
return router.resolve(previousPath)
}

return fallback
Expand All @@ -22,13 +25,14 @@ export const useFormRedirectOnCancel = (fallback: RouteLocationRaw) => {
}

export const useFormRedirectOnUpdate = (fallback: RouteLocationRaw) => {
const route = useRoute()
const redirectPath = computed(() => route.query.redirect)
const redirectRouteLocation = useURLFromRouteQuery('redirect')

const routeOnUpdate = computed(() => {
const link = redirectPath.value || route.query.returnLink || route.query.redirect
if (redirectRouteLocation.value) {
return redirectRouteLocation.value
}

return link ? ({ path: link } as MatcherLocationAsPath) : fallback
return fallback
})

return routeOnUpdate.value
Expand Down
5 changes: 3 additions & 2 deletions src/composables/useListRedirect.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { LocationQueryValue } from 'vue-router'

import { useURLFromRouteQuery } from './useRedirect'

export const useListRedirect = () => {
const route = useRoute()
const router = useRouter()

const redirectPath = computed(() => route.query.redirect as LocationQueryValue)
const redirectPath = useURLFromRouteQuery('redirect')
const redirectRouteQuery = computed(() => ({ redirect: redirectPath.value }))

const createRedirectRouteQuery = (redirect = route.fullPath) => {
Expand Down
21 changes: 21 additions & 0 deletions src/composables/useRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import type { LocationQueryValue } from 'vue-router'

export const useURLFromRouteQuery = (urlKey: string) => {
const route = useRoute()

return computed(() => {
const query = route.query[urlKey]
let url: LocationQueryValue = null

if (Array.isArray(query)) {
url = query[0]
console.warn(`useURLFromRouteQuery: "${urlKey}" in query should not be an array, using first element this time`)
} else if (typeof query === 'string') {
url = query
}

return url
})
}
6 changes: 3 additions & 3 deletions src/pages/consumers/ConsumerCredentials.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ import { pluginMeta } from '@/pages/plugins/PluginMeta'
import { useI18n } from '@/composables/useI18n'
import { useInfoStore } from '@/stores/info'
import CredentialList from './CredentialList.vue'
import { useListRedirect } from '@/composables/useListRedirect'

const router = useRouter()
const { t } = useI18n()
const infoStore = useInfoStore()
const { createRedirectRouteQuery } = useListRedirect()

const enabledPlugins = computed(() => infoStore.plugins.enabledInCluster)
const enabledPluginsFetched = ref(false)
Expand All @@ -58,9 +60,7 @@ const hasEnabledPlugins = computed(() => credentialPlugins.some(({ pluginType })
const navigateToPluginSelection = () => {
router.push({
name: 'plugin-select',
query: {
redirect: router.currentRoute.value.fullPath,
},
query: createRedirectRouteQuery(),
})
}

Expand Down
19 changes: 4 additions & 15 deletions src/pages/plugins/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,6 @@ export default {
type: String,
default: null,
},

returnLinkPath: {
type: String,
default: null,
},
useKonnectSchema: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -298,18 +293,14 @@ export default {
return this.redirectPath
}

if (this.returnLinkPath) {
return this.returnLinkPath
}

const entityId = this.resourceEndpoint.match(new RegExp(uuidRegEx))

if (entityId && this.$route.query.entity_id) {
// e.g. /consumers/e22cf8e2-795a-4eac-8da1-76b47de30b5c
return `/${this.resourceEndpoint.split('/')[0]}/${entityId}`
}

return this.$route.query.returnLink
return null
},

docsLink () {
Expand Down Expand Up @@ -440,9 +431,7 @@ export default {
methods: {
onCancel () {
if (this.redirectPath) {
this.$router.push({ path: this.redirectPath })
} else if (this.returnLinkPath) {
this.$router.push({ path: this.returnLinkPath })
this.$router.push(this.redirectPath)
} else if (this.$router.previous) {
this.$router.push({ ...this.$router.previous })
} else {
Expand Down Expand Up @@ -489,7 +478,7 @@ export default {
}

this.returnLink
? this.$router.push({ path: this.returnLink })
? this.$router.push(this.returnLink)
: redirectOnResponseStatus(this.$router, 201, { name: 'plugin-list' })(res)

return res.data
Expand Down Expand Up @@ -536,7 +525,7 @@ export default {
}

this.returnLink
? this.$router.push({ path: this.returnLink })
? this.$router.push(this.returnLink)
: redirectOnResponseStatus(this.$router, 200, { name: 'plugin-detail', params: { id: this.id } })(res)

return res.data
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright/specs/services/01-Service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ test.describe('services', () => {
await withNavigation(page, () =>
page
.locator('.page-header')
.locator('a[type="button"]:has-text("Back")')
.locator('[type="button"]:has-text("Back")')
.click()
)
await page.waitForSelector('.kong-ui-entities-gateway-services-list')
Expand Down
Loading