diff --git a/frontend/__tests__/components/GLogin.spec.js b/frontend/__tests__/components/GLogin.spec.js index 2c000036a3..cdcaf4633f 100644 --- a/frontend/__tests__/components/GLogin.spec.js +++ b/frontend/__tests__/components/GLogin.spec.js @@ -34,8 +34,6 @@ describe('components', () => { let loginStore // eslint-disable-line no-unused-vars let localStorageStore let mockRoute - let mockRouter - let mockNext function mountLogin () { return mount(GLogin, { @@ -49,7 +47,6 @@ describe('components', () => { ], mocks: { $route: mockRoute, - $router: mockRouter, }, }, }) @@ -73,10 +70,6 @@ describe('components', () => { redirectPath: '/namespace/garden/shoots', }, } - mockRouter = { - push: vi.fn(), - replace: vi.fn(), - } pinia = createTestingPinia({ stubActions: false, initialState: { @@ -120,16 +113,10 @@ describe('components', () => { title: error.title, }), } - mockNext = vi.fn().mockImplementation(fn => { - if (typeof fn === 'function') { - fn(wrapper.vm) - } - }) - await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined, mockNext) - expect(wrapper.vm.error.message).toBe(error.message) - await GLogin.beforeRouteUpdate.call(wrapper.vm, undefined, undefined, () => {}) - expect(mockNext).toBeCalledTimes(1) - expect(mockNext.mock.calls[0]).toEqual([expect.any(Function)]) + + await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined) + expect(wrapper.vm.loginError.message).toBe(error.message) + await GLogin.mounted.call(wrapper.vm) expect(appStore.setError).toBeCalledTimes(1) expect(appStore.setError.mock.calls[0]).toEqual([ expect.objectContaining({ @@ -137,8 +124,6 @@ describe('components', () => { title: 'title', }), ]) - expect(mockRouter.replace).toBeCalledTimes(1) - expect(mockRouter.replace.mock.calls[0]).toEqual(['/login']) }) it('should not show a login error', async () => { @@ -150,17 +135,10 @@ describe('components', () => { title: error.title, }), } - mockNext = vi.fn().mockImplementation(fn => { - if (typeof fn === 'function') { - fn(wrapper.vm) - } - }) - await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined, mockNext) - expect(mockNext).toBeCalledTimes(1) - expect(mockNext.mock.calls[0]).toEqual([expect.any(Function)]) + + await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined) + await GLogin.mounted.call(wrapper.vm) expect(appStore.setError).not.toBeCalled() - expect(mockRouter.replace).toBeCalledTimes(1) - expect(mockRouter.replace.mock.calls[0]).toEqual(['/login']) }) it('should automatically login', async () => { @@ -171,10 +149,7 @@ describe('components', () => { redirectPath: '/namespace/garden-foo/shoots', }, } - mockNext = vi.fn() - await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined, mockNext) - expect(mockNext).toBeCalledTimes(1) - expect(mockNext.mock.calls[0]).toEqual([false]) + await GLogin.beforeRouteEnter.call(wrapper.vm, to, undefined) expect(authnStore.signinWithOidc).toBeCalledTimes(1) expect(authnStore.signinWithOidc.mock.calls[0]).toEqual([to.query.redirectPath]) }) diff --git a/frontend/src/layouts/GDefault.vue b/frontend/src/layouts/GDefault.vue index c88fc73192..5845815bc9 100644 --- a/frontend/src/layouts/GDefault.vue +++ b/frontend/src/layouts/GDefault.vue @@ -97,9 +97,8 @@ function onClick () { } // hooks -onBeforeRouteUpdate((to, from, next) => { +onBeforeRouteUpdate(() => { mainContent.value?.setScrollTop(0) - next() }) onMounted(() => { diff --git a/frontend/src/layouts/GLogin.vue b/frontend/src/layouts/GLogin.vue index f9cf505fe3..e68b1b5f96 100644 --- a/frontend/src/layouts/GLogin.vue +++ b/frontend/src/layouts/GLogin.vue @@ -151,7 +151,7 @@ export default { GNotify, }, inject: ['api'], - async beforeRouteEnter (to, from, next) { + async beforeRouteEnter (to) { let err if (/^#.+/.test(to.hash)) { const searchParams = new URLSearchParams(to.hash.substring(1)) @@ -168,31 +168,18 @@ export default { const redirectPath = get(to.query, ['redirectPath'], '/') const authnStore = useAuthnStore() authnStore.signinWithOidc(redirectPath) - return next(false) + return false } - next(vm => { - if (err) { - if (err.message !== 'NoAutoLogin') { - vm.error = err - } - vm.$router.replace('/login') - } - }) - }, - beforeRouteUpdate (to, from, next) { - if (this.error) { - const err = this.error - this.error = null - this.setError(err) + if (err && err.message !== 'NoAutoLogin') { + loginStore.loginError = err + return { path: '/login', replace: true } } - next() }, data () { return { showToken: false, token: '', - error: null, } }, computed: { @@ -203,6 +190,7 @@ export default { ]), ...mapWritableState(useLoginStore, [ 'loginType', + 'loginError', ]), breakpointName () { return this.$vuetify.display.name @@ -281,6 +269,13 @@ export default { immediate: true, }, }, + mounted () { + if (this.loginError) { + const err = this.loginError + this.loginError = null + this.setError(err) + } + }, methods: { ...mapActions(useAppStore, [ 'setError', diff --git a/frontend/src/views/GNewShoot.vue b/frontend/src/views/GNewShoot.vue index e66d41dd7a..fa8ae86b2e 100644 --- a/frontend/src/views/GNewShoot.vue +++ b/frontend/src/views/GNewShoot.vue @@ -174,30 +174,28 @@ export default { GToolbar, }, inject: ['api', 'logger'], - async beforeRouteLeave (to, from, next) { + async beforeRouteLeave (to) { if (!this.sortedInfraProviderTypeList.length) { - return next() + return true } if (to.name === 'NewShootEditor') { if (this.v$.$invalid && !await this.confirmNavigateToYamlIfInvalid()) { - return next(false) + return false } - return next() + return true } if (!this.isShootCreated && this.isShootDirty && !await this.confirmNavigation()) { - return next(false) + return false } - - return next() }, - async beforeRouteUpdate (to, from, next) { + async beforeRouteUpdate () { if (!this.isShootCreated && this.isShootDirty && !await this.confirmNavigation()) { - return next(false) + return false } - return next() + return true }, setup () { const { diff --git a/frontend/src/views/GNewShootEditor.vue b/frontend/src/views/GNewShootEditor.vue index c551e2d651..f84397266f 100644 --- a/frontend/src/views/GNewShootEditor.vue +++ b/frontend/src/views/GNewShootEditor.vue @@ -123,35 +123,35 @@ async function save () { } } -onBeforeRouteLeave(async (to, from, next) => { +onBeforeRouteLeave(async to => { if (to.name === 'NewShoot') { try { setShootManifest(getEditorValue()) - return next() + return true } catch (err) { errorMessage.value = err.message - return next(false) + return false } } if (isShootCreated.value) { - return next() + return true } if (!clean.value || isShootDirty.value) { if (!await confirmEditorNavigation()) { focusEditor() - return next(false) + return false } } - return next() + return true }) -onBeforeRouteUpdate(async (to, from, next) => { +onBeforeRouteUpdate(async () => { if (!clean.value || isShootDirty.value) { if (!await confirmEditorNavigation()) { focusEditor() - return next(false) + return false } } - return next() + return true }) diff --git a/frontend/src/views/GShootItemEditor.vue b/frontend/src/views/GShootItemEditor.vue index df924f8fea..f1713009aa 100644 --- a/frontend/src/views/GShootItemEditor.vue +++ b/frontend/src/views/GShootItemEditor.vue @@ -153,19 +153,15 @@ function confirmOverwrite () { }) } -onBeforeRouteLeave(async (to, from, next) => { +onBeforeRouteLeave(async () => { if (clean.value) { - return next() + return true } - try { - if (await confirmEditorNavigation()) { - next() - } else { - focusEditor() - next(false) - } - } catch (err) { - next(err) + if (await confirmEditorNavigation()) { + return true + } else { + focusEditor() + return false } }) diff --git a/frontend/src/views/GShootList.vue b/frontend/src/views/GShootList.vue index d85e041a1a..838ab34c41 100644 --- a/frontend/src/views/GShootList.vue +++ b/frontend/src/views/GShootList.vue @@ -182,7 +182,7 @@ export default { GTableSearch, }, inject: ['logger'], - beforeRouteUpdate (to, from, next) { + beforeRouteUpdate (to, from) { if (to.path !== from.path) { this.setShootSearch('') } @@ -191,14 +191,10 @@ export default { // Reset expanded state in case project changes this.resetState(this.expandedWorkerGroups, { default: false }) this.resetState(this.expandedAccessRestrictions, { default: false }) - - next() }, - beforeRouteLeave (to, from, next) { + beforeRouteLeave () { this.setShootSearch('') this.focusModeInternal = false - - next() }, setup () { const projectStore = useProjectStore() @@ -692,6 +688,9 @@ export default { } }, }, + mounted () { + this.updateTableSettings() + }, methods: { ...mapActions(useShootStore, [ 'toogleShootListFilter',