Skip to content
Snippets Groups Projects
Commit 1bb3e58c authored by simon.mellerin's avatar simon.mellerin
Browse files

Merge branch 'route-naming' into 'main'

Route naming

See merge request !36
parents fd46fffe 90492f22
No related branches found
No related tags found
1 merge request!36Route naming
Pipeline #10356 passed
Showing
with 158 additions and 65 deletions
...@@ -31,7 +31,7 @@ const home: MenuItem = { ...@@ -31,7 +31,7 @@ const home: MenuItem = {
label: '', label: '',
key: 'home', key: 'home',
icon: type2IconsDict['home'], icon: type2IconsDict['home'],
to: '' to: { name: 'index' }
} }
function ocBreadcrumbItem2menuItem(item: OcBreadcrumbItem): MenuItem { function ocBreadcrumbItem2menuItem(item: OcBreadcrumbItem): MenuItem {
...@@ -45,6 +45,7 @@ function ocBreadcrumbItem2menuItem(item: OcBreadcrumbItem): MenuItem { ...@@ -45,6 +45,7 @@ function ocBreadcrumbItem2menuItem(item: OcBreadcrumbItem): MenuItem {
const formattedItems = computed(() => props.items.map((item) => ocBreadcrumbItem2menuItem(item))) const formattedItems = computed(() => props.items.map((item) => ocBreadcrumbItem2menuItem(item)))
</script> </script>
<style scoped> <style scoped>
.p-breadcrumb { .p-breadcrumb {
--p-breadcrumb-gap: 0.2rem; --p-breadcrumb-gap: 0.2rem;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
</p> </p>
<OcLink <OcLink
:title="t('home.goToCommunity', { label: title })" :title="t('home.goToCommunity', { label: title })"
:to="'/community/' + community.name" :to="{ name: 'community', params: { community: community.name } }"
class="absolute top-0 left-0 h-full w-full" class="absolute top-0 left-0 h-full w-full"
/> />
</div> </div>
......
...@@ -5,14 +5,27 @@ ...@@ -5,14 +5,27 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import type { PropType } from 'vue'
import { useI18n } from 'vue-i18n'; import { computed } from 'vue'
import { type RouterLinkProps } from 'vue-router' import { useI18n } from 'vue-i18n'
import type { RouteLocationAsRelativeGeneric } from 'vue-router'
const { locale } = useI18n() const { locale } = useI18n()
const props = defineProps<RouterLinkProps>() const props = defineProps({
to: {
type: Object as PropType<RouteLocationAsRelativeGeneric>,
required: true
}
})
const routerLinkPropsTo = computed(() => '/' + locale.value + props.to) const routerLinkPropsTo = computed(() => {
const route = { ...props.to }
route.params = {
...route.params,
lang: locale.value
}
</script> return route
\ No newline at end of file })
</script>
<template> <template>
<div class="w-full bg-white sticky top-0 flex justify-start items-center drop-shadow-lg px-4 gap-4 z-10 h-16"> <div
<OcLink to="" class="flex items-center"> class="w-full bg-white sticky top-0 flex justify-start items-center drop-shadow-lg px-4 gap-4 z-10 h-16"
>
<OcLink :to="{ name: 'index' }" class="flex items-center">
<img src="/logo.png" class="h-6" /> <img src="/logo.png" class="h-6" />
<p class="font-title font-bold text-2xl uppercase text-primary ml-4 pb-1">Open Common</p> <p class="font-title font-bold text-2xl uppercase text-primary ml-4 pb-1">Open Common</p>
</OcLink> </OcLink>
......
<template> <template>
<div class="flex items-center"> <div class="flex items-center">
<Button v-if="!isAuthenticated" :as="OcLink" to="/connection" size="small"> <Button v-if="!isAuthenticated" :as="OcLink" :to="{ name: 'connection' }" size="small">
{{ t('topMenu.signIn') }} {{ t('topMenu.signIn') }}
</Button> </Button>
<Menubar ref="menu" id="overlay_menu_top" :model="menuItems" :popup="true" :style="menuStyle" /> <Menubar ref="menu" id="overlay_menu_top" :model="menuItems" :popup="true" :style="menuStyle" />
...@@ -75,11 +75,11 @@ const menuItems = computed(() => { ...@@ -75,11 +75,11 @@ const menuItems = computed(() => {
items: [ items: [
{ {
label: t('profile.profile'), label: t('profile.profile'),
command: () => router.push(`/${locale.value}/profile`) command: () => router.push({ name: 'profile', params: { lang: locale.value } })
}, },
{ {
label: t('connection.logout'), label: t('connection.logout'),
command: () => router.push(`/${locale.value}/logout`) command: () => router.push({ name: 'logout', params: { lang: locale.value } })
} }
] ]
}) })
......
import { useAccountStore } from "@/stores/account"
import { useI18n } from "vue-i18n"
import { useRoute, useRouter } from "vue-router"
export function useAuthentificationCheck() {
const accountStore = useAccountStore()
const router = useRouter()
const route = useRoute()
const { locale } = useI18n()
if (!accountStore.isAuthenticated) {
router.push({
name: `/:lang/[...path]`,
params: {
lang: locale.value,
path: 'error'
},
query: {
code: 403,
from: route.path
}
})
}
}
\ No newline at end of file
...@@ -20,7 +20,7 @@ export const useCommunityData = defineBasicLoader( ...@@ -20,7 +20,7 @@ export const useCommunityData = defineBasicLoader(
// @see https://uvr.esm.is/data-loaders/navigation-aware.html#navigation-aware // @see https://uvr.esm.is/data-loaders/navigation-aware.html#navigation-aware
// As DataLoader is an experimental feature, I let it like this for now. // As DataLoader is an experimental feature, I let it like this for now.
router.push({ router.push({
name: `/:lang/[...path]`, name: 'catchall',
params: { params: {
lang: locale.value, lang: locale.value,
path: 'error' path: 'error'
......
...@@ -76,12 +76,12 @@ onBeforeMount(() => treeStore.fetchIfEmpty()) ...@@ -76,12 +76,12 @@ onBeforeMount(() => treeStore.fetchIfEmpty())
function onNodeSelect(node: TreeNode) { function onNodeSelect(node: TreeNode) {
if (node.uri === homeNodeUri) { if (node.uri === homeNodeUri) {
router.push({ router.push({
name: '/:lang/community/[community]/', name: 'community',
params: { lang: locale.value, community: props.community?.name } params: { lang: locale.value, community: props.community?.name }
}) })
} else { } else {
router.push({ router.push({
name: '/:lang/community/[community]/resource/[identifier]', name: 'community.resource',
params: { lang: locale.value, community: props.community?.name, identifier: node.key } params: { lang: locale.value, community: props.community?.name, identifier: node.key }
}) })
} }
......
<template> <template>
<header class="bg-primary p-10 flex justify-center"> <header class="bg-primary p-10 flex justify-center">
<OcLink to=""> <OcLink :to="{ name: 'index' }">
<img src=" /logo-text.png" class="h-20" alt="Open Common" /> <img src=" /logo-text.png" class="h-20" alt="Open Common" />
</OcLink> </OcLink>
</header> </header>
...@@ -24,10 +24,16 @@ ...@@ -24,10 +24,16 @@
</p> </p>
</div> </div>
<Button :as="OcLink" to="">{{ t('backHome') }}</Button> <Button :as="OcLink" :to="{ name: 'index' }">{{ t('backHome') }}</Button>
</div> </div>
</template> </template>
<route lang="json">
{
"name": "catchall"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcLink from '@/components/OcLink.vue' import OcLink from '@/components/OcLink.vue'
import Button from 'primevue/button' import Button from 'primevue/button'
......
...@@ -59,9 +59,17 @@ ...@@ -59,9 +59,17 @@
</OcLayoutSimple> </OcLayoutSimple>
</template> </template>
<route lang="json">
{
"name": "community.datasets.new",
"meta": {
"needAuthent": true
}
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcLayoutSimple from '@/layout/OcLayoutSimple/OcLayoutSimple.vue' import OcLayoutSimple from '@/layout/OcLayoutSimple/OcLayoutSimple.vue'
import { useAuthentificationCheck } from '@/composables/authentificationCheck'
import type { OcBreadcrumbItem, OcDataset, OcVocabulary } from '@/declarations' import type { OcBreadcrumbItem, OcDataset, OcVocabulary } from '@/declarations'
import { useAccountStore } from '@/stores/account' import { useAccountStore } from '@/stores/account'
import { computed } from 'vue' import { computed } from 'vue'
...@@ -84,8 +92,6 @@ import { ref } from 'vue' ...@@ -84,8 +92,6 @@ import { ref } from 'vue'
import { insertDataset } from '@/sparql/datasets' import { insertDataset } from '@/sparql/datasets'
import { useCommunityData } from '@/dataLoaders/community' import { useCommunityData } from '@/dataLoaders/community'
useAuthentificationCheck()
const { translateValue } = useTranslateValue() const { translateValue } = useTranslateValue()
const accountStore = useAccountStore() const accountStore = useAccountStore()
const { t, locale } = useI18n() const { t, locale } = useI18n()
......
...@@ -19,7 +19,11 @@ ...@@ -19,7 +19,11 @@
</div> </div>
<div class="flex justify-center"> <div class="flex justify-center">
<Button :as="OcLink" :to="'/community/' + community?.name" severity="secondary"> <Button
:as="OcLink"
:to="{ name: 'community', params: { community: community.name } }"
severity="secondary"
>
{{ t('connection.continueAsGuest') }} {{ t('connection.continueAsGuest') }}
</Button> </Button>
</div> </div>
...@@ -29,7 +33,7 @@ ...@@ -29,7 +33,7 @@
<i class="fa-solid fa-circle-check text-6xl text-center text-primary mb-6"></i> <i class="fa-solid fa-circle-check text-6xl text-center text-primary mb-6"></i>
<p class="text-center mb-6">{{ t('community.askJoin.confirmation.1') }}</p> <p class="text-center mb-6">{{ t('community.askJoin.confirmation.1') }}</p>
<p class="text-center mb-6">{{ t('community.askJoin.confirmation.2') }}</p> <p class="text-center mb-6">{{ t('community.askJoin.confirmation.2') }}</p>
<Button :as="OcLink" :to="'/community/' + community?.name" severity="secondary" rounded> <Button :as="OcLink" :to="'/community/' + community.name" severity="secondary" rounded>
{{ t('connection.continueAsGuest') }} {{ t('connection.continueAsGuest') }}
</Button> </Button>
</div> </div>
...@@ -37,6 +41,15 @@ ...@@ -37,6 +41,15 @@
</OcLayoutBiColumn> </OcLayoutBiColumn>
</template> </template>
<route lang="json">
{
"name": "community.join",
"meta": {
"needAuthent": true
}
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcLink from '@/components/OcLink.vue' import OcLink from '@/components/OcLink.vue'
import { useTranslateValue } from '@/composables/translateValue' import { useTranslateValue } from '@/composables/translateValue'
......
<template> <template>
<OcLayoutCommunityWithTree <OcLayoutCommunityWithTree
v-if="community"
:community="community" :community="community"
:is-authenticated="accountStore.isAuthenticated" :is-authenticated="accountStore.isAuthenticated"
:breadcrumb-items="breadcrumbItems" :breadcrumb-items="breadcrumbItems"
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<Button <Button
v-if="!account.isAuthenticated" v-if="!account.isAuthenticated"
:as="OcLink" :as="OcLink"
to="/connection" :to="{ name: 'connection' }"
size="large" size="large"
:class="`bg-${color}-400 hover:bg-${color}-700 text-white font-bold shadow-md border-0 mt-8 p-4 rounded-md m-auto`" :class="`bg-${color}-400 hover:bg-${color}-700 text-white font-bold shadow-md border-0 mt-8 p-4 rounded-md m-auto`"
> >
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<Button <Button
v-else-if="!isMemberOfCurrentCommunity" v-else-if="!isMemberOfCurrentCommunity"
:as="OcLink" :as="OcLink"
:to="'/community/' + name + '/join'" :to="{ name: 'community.join', params: { community: community.name } }"
size="large" size="large"
:class="`bg-${color}-400 hover:bg-${color}-700 text-white border-0 mt-8 p-4 rounded-md m-auto`" :class="`bg-${color}-400 hover:bg-${color}-700 text-white border-0 mt-8 p-4 rounded-md m-auto`"
> >
...@@ -60,6 +60,13 @@ ...@@ -60,6 +60,13 @@
></OcHomeCommunityActionList> ></OcHomeCommunityActionList>
</div> </div>
</template> </template>
<route lang="json">
{
"name": "community"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useAccountStore } from '@/stores/account' import { useAccountStore } from '@/stores/account'
...@@ -85,7 +92,6 @@ const { memberCommunitiesList } = storeToRefs(account) ...@@ -85,7 +92,6 @@ const { memberCommunitiesList } = storeToRefs(account)
const { data: community } = useCommunityData() const { data: community } = useCommunityData()
const title = computed(() => translateValue(community.value?.title)) const title = computed(() => translateValue(community.value?.title))
const name = computed(() => community.value?.name ?? '')
const abstract = computed(() => translateValue(community.value?.abstract)) const abstract = computed(() => translateValue(community.value?.abstract))
const logoUrl = computed(() => community.value?.logo ?? null) const logoUrl = computed(() => community.value?.logo ?? null)
const color = computed(() => getColor(community.value)) const color = computed(() => getColor(community.value))
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
<h2>identifier: {{ identifier }}</h2> <h2>identifier: {{ identifier }}</h2>
<p>WIP</p> <p>WIP</p>
</template> </template>
<route lang="json">
{
"name": "community.resource"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
......
...@@ -20,13 +20,15 @@ ...@@ -20,13 +20,15 @@
<hr class="my-8" /> <hr class="my-8" />
<div class="flex justify-center"> <div class="flex justify-center">
<Button outlined :as="OcLink" to="/register">{{ t('connection.createAccount') }}</Button> <Button outlined :as="OcLink" :to="{ name: 'register' }">{{
t('connection.createAccount')
}}</Button>
</div> </div>
<hr class="my-8" /> <hr class="my-8" />
<div class="flex justify-center"> <div class="flex justify-center">
<Button :as="OcLink" to="" severity="secondary"> <Button :as="OcLink" :to="{ name: 'index' }" severity="secondary">
{{ t('connection.continueAsGuest') }} {{ t('connection.continueAsGuest') }}
</Button> </Button>
</div> </div>
...@@ -34,6 +36,12 @@ ...@@ -34,6 +36,12 @@
</OcLayoutBiColumn> </OcLayoutBiColumn>
</template> </template>
<route lang="json">
{
"name": "connection"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcConnectionForm from '@/components/OcConnectionForm/OcConnectionForm.vue' import OcConnectionForm from '@/components/OcConnectionForm/OcConnectionForm.vue'
import OcLink from '@/components/OcLink.vue' import OcLink from '@/components/OcLink.vue'
...@@ -73,7 +81,7 @@ async function connection(username: string, password: string) { ...@@ -73,7 +81,7 @@ async function connection(username: string, password: string) {
accountStore.profile = profileInfos.profile accountStore.profile = profileInfos.profile
accountStore.memberships = profileInfos.memberships accountStore.memberships = profileInfos.memberships
router.push(`/${locale.value}`) router.push({ name: 'index', params: { lang: locale.value } })
} else { } else {
loginError.value = true loginError.value = true
} }
......
...@@ -34,6 +34,12 @@ ...@@ -34,6 +34,12 @@
</div> </div>
</template> </template>
<route lang="json">
{
"name": "index"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue' import { onMounted } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
......
...@@ -6,17 +6,26 @@ ...@@ -6,17 +6,26 @@
<div class="w-11/12 md:w-10/12 xl:w-7/12"> <div class="w-11/12 md:w-10/12 xl:w-7/12">
<img src="/logo.png" class="h-16" /> <img src="/logo.png" class="h-16" />
<p class="font-title font-bold text-5xl uppercase text-primary mb-4">Open Common</p> <p class="font-title font-bold text-5xl uppercase text-primary mb-4">Open Common</p>
<p class="text-lg line mb-8">{{ $t('connection.catchphrase') }}</p> <p class="text-lg line mb-8">{{ t('connection.catchphrase') }}</p>
<Message class="mb-8" severity="success">{{ $t('connection.logoutSuccess') }}</Message> <Message class="mb-8" severity="success">{{ t('connection.logoutSuccess') }}</Message>
<div class="flex justify-center"> <div class="flex justify-center">
<Button :as="OcLink" to="">{{ $t('backHome') }}</Button> <Button :as="OcLink" :to="{ name: 'index' }">{{ t('backHome') }}</Button>
</div> </div>
</div> </div>
</OcLayoutBiColumn> </OcLayoutBiColumn>
</template> </template>
<route lang="json">
{
"name": "logout",
"meta": {
"needAuthent": true
}
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcLink from '@/components/OcLink.vue' import OcLink from '@/components/OcLink.vue'
import type { OcBreadcrumbItem } from '@/declarations' import type { OcBreadcrumbItem } from '@/declarations'
......
...@@ -37,6 +37,15 @@ ...@@ -37,6 +37,15 @@
</OcLayoutSimple> </OcLayoutSimple>
</template> </template>
<route lang="json">
{
"name": "profile",
"meta": {
"needAuthent": true
}
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import type { OcBreadcrumbItem } from '@/declarations' import type { OcBreadcrumbItem } from '@/declarations'
import OcLayoutSimple from '@/layout/OcLayoutSimple/OcLayoutSimple.vue' import OcLayoutSimple from '@/layout/OcLayoutSimple/OcLayoutSimple.vue'
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<i class="fa-solid fa-circle-check text-6xl text-center text-primary mb-6"></i> <i class="fa-solid fa-circle-check text-6xl text-center text-primary mb-6"></i>
<p class="text-center mb-6">{{ t('register.confirmation.1') }}</p> <p class="text-center mb-6">{{ t('register.confirmation.1') }}</p>
<p class="text-center mb-6">{{ t('register.confirmation.2') }}</p> <p class="text-center mb-6">{{ t('register.confirmation.2') }}</p>
<Button :as="OcLink" to="" severity="secondary"> <Button :as="OcLink" :to="{ name: 'index' }" severity="secondary">
{{ t('connection.continueAsGuest') }} {{ t('connection.continueAsGuest') }}
</Button> </Button>
</div> </div>
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
</OcLayoutBiColumn> </OcLayoutBiColumn>
</template> </template>
<route lang="json">
{
"name": "register"
}
</route>
<script setup lang="ts"> <script setup lang="ts">
import OcLink from '@/components/OcLink.vue' import OcLink from '@/components/OcLink.vue'
import OcRegisterForm from '@/components/OcRegisterForm/OcRegisterForm.vue' import OcRegisterForm from '@/components/OcRegisterForm/OcRegisterForm.vue'
......
...@@ -16,9 +16,9 @@ const router = createRouter({ ...@@ -16,9 +16,9 @@ const router = createRouter({
redirect() { redirect() {
const language = navigator.language.split('-')[0] as typeof i18n.global.locale.value const language = navigator.language.split('-')[0] as typeof i18n.global.locale.value
if (i18n.global.availableLocales.includes(language)) { if (i18n.global.availableLocales.includes(language)) {
return { path: `${language}` } return { name: 'index', params: { lang: language } }
} else { } else {
return { path: `${i18n.global.fallbackLocale}` } return { name: 'index', params: { lang: i18n.global.fallbackLocale } }
} }
}, },
}, },
...@@ -36,7 +36,7 @@ router.beforeResolve((to) => { ...@@ -36,7 +36,7 @@ router.beforeResolve((to) => {
i18n.global.locale.value = language i18n.global.locale.value = language
} else { } else {
return { return {
name: `/:lang/[...path]`, name: `catchall`,
params: { params: {
lang: i18n.global.locale.value, lang: i18n.global.locale.value,
path: 'error' path: 'error'
...@@ -56,11 +56,37 @@ router.beforeEach(async () => { ...@@ -56,11 +56,37 @@ router.beforeEach(async () => {
const accountStore = useAccountStore() const accountStore = useAccountStore()
if (accountStore.isAuthenticated && accountStore.profile === null) { if (accountStore.isAuthenticated && accountStore.profile === null) {
const { infos, profile, memberships } = await getProfileInfos(accountStore.auth as Credentials) getProfileInfos(accountStore.auth as Credentials)
.then(({ infos, profile, memberships }) => {
accountStore.profile = profile
accountStore.infos = infos
accountStore.memberships = memberships
})
}
})
/**
* Authentification guard.
*/
router.beforeEach(async (to) => {
if (!to.meta.needAuthent) {
return
}
const accountStore = useAccountStore()
accountStore.profile = profile if (!accountStore.isAuthenticated) {
accountStore.infos = infos router.push({
accountStore.memberships = memberships name: 'catchall',
params: {
lang: i18n.global.locale.value,
path: 'error'
},
query: {
code: 403,
from: to.path
}
})
} }
}) })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment