Skip to content

Commit a07e500

Browse files
authored
fix: broken redirects in setup (#1065)
1 parent 71fdd6e commit a07e500

5 files changed

Lines changed: 54 additions & 16 deletions

File tree

composables/useCurrentOwned.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ export function useCurrentOwned() {
3939
return organizations.value[route.params.oid] || null
4040
}
4141

42+
// Route explicitly identifies a user context, so no organization. Reading
43+
// currentOwnedId here would couple this getter to mutations performed by
44+
// the currentUser getter below, causing SSR-vs-hydration mismatches on
45+
// routes like /admin/me/datasets where a fetch had populated currentOwnedId
46+
// before render but currentUser then resets it.
47+
if (route.params.uid || route.fullPath.includes('/admin/me/')) return null
48+
4249
if (!currentOwnedId.value) return null
4350
if (!('organization' in currentOwnedId.value)) return null
4451

@@ -58,6 +65,9 @@ export function useCurrentOwned() {
5865
return me.value
5966
}
6067

68+
// Symmetrical to currentOrganization: route identifies an organization, no user
69+
if (route.params.oid) return null
70+
6171
if (!currentOwnedId.value) return null
6272
if (!('user' in currentOwnedId.value)) return null
6373

pages/admin.vue

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,27 @@ import type { OrganizationReference } from '@datagouv/components-next'
5757
5858
definePageMeta({
5959
layout: 'fluid',
60-
middleware: ['auth'],
60+
middleware: [
61+
'auth',
62+
(to) => {
63+
if (to.path !== '/admin' && to.path !== '/admin/') return
64+
const me = useMaybeMe()
65+
const target = me.value && me.value.organizations.length > 0
66+
? `/admin/organizations/${me.value.organizations[0].id}/datasets`
67+
: '/admin/me/datasets'
68+
return navigateTo(target, { replace: true })
69+
},
70+
],
6171
matomoIgnore: true,
6272
})
6373
6474
const { t } = useTranslation()
65-
const route = useRoute()
66-
const { resolve } = useRouter()
6775
const me = useMe()
6876
6977
useSeoMeta({ title: 'Admin' })
7078
7179
const { organizations, users } = useCurrentOwned()
7280
const isSiteAdmin = computed(() => me.value.roles?.includes('admin') || false)
73-
74-
if (route.name === resolve('/admin')?.name) {
75-
if (me.value.organizations.length > 0) {
76-
await navigateTo(`/admin/organizations/${me.value.organizations[0].id}/datasets`, { replace: true })
77-
}
78-
else {
79-
await navigateTo('/admin/me/datasets', { replace: true })
80-
}
81-
}
8281
</script>
8382

8483
<style>

pages/organizations/[oid]/index.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
<script setup lang="ts">
66
import type { Organization } from '@datagouv/components-next'
77
8+
definePageMeta({
9+
middleware: to => navigateTo(`/organizations/${to.params.oid}/datasets`, { replace: true }),
10+
})
11+
812
defineProps<{
913
organization: Organization
1014
}>()
11-
12-
const route = useRoute()
13-
14-
await navigateTo(`/organizations/${route.params.oid}/datasets`, { replace: true })
1515
</script>

tests/admin/redirect.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { test, expect } from '../base'
2+
3+
test('clicking Administration in the header redirects and renders content', async ({ page }) => {
4+
await page.goto('/')
5+
6+
await page.getByRole('banner').getByRole('link', { name: 'Administration' }).click()
7+
8+
await expect(page).toHaveURL(/\/admin\/(me|organizations\/[^/]+)\/datasets/)
9+
await expect(page.getByRole('heading', { level: 1, name: 'Jeux de données' })).toBeVisible()
10+
})
11+
12+
test('clicking Administration breadcrumb from an admin page redirects and renders content', async ({ page }) => {
13+
await page.goto('/admin/me/datasets')
14+
await expect(page.getByRole('heading', { level: 1, name: 'Jeux de données' })).toBeVisible()
15+
16+
await page.getByLabel('Vous êtes ici :').getByRole('link', { name: 'Administration' }).click()
17+
18+
await expect(page).toHaveURL(/\/admin\/(me|organizations\/[^/]+)\/datasets/)
19+
await expect(page.getByRole('heading', { level: 1, name: 'Jeux de données' })).toBeVisible()
20+
})

tests/organizations/[oid].spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ test('organization root redirects to datasets tab', async ({ page }) => {
1515
await expect(page).toHaveURL(/\/organizations\/sobrana\/datasets/)
1616
})
1717

18+
test('clicking an organization from the list redirects and renders the page', async ({ page }) => {
19+
await page.goto('/organizations')
20+
21+
await page.getByRole('link', { name: /sobrana/i }).first().click()
22+
23+
await expect(page).toHaveURL(/\/organizations\/sobrana\/datasets/)
24+
await expect(page.getByRole('heading', { level: 1, name: /SOBRANA/i })).toBeVisible()
25+
})
26+
1827
test('tabs display correct counts', async ({ page }) => {
1928
await page.goto(`/organizations/${ORG_SLUG}/datasets`)
2029

0 commit comments

Comments
 (0)