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

refactor: create ProvideCanonicalUrl component #2572

Merged
merged 11 commits into from
Feb 12, 2025
7 changes: 7 additions & 0 deletions packages/portal/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,13 @@ export default {
loader: 'file-loader'
});

// Handle .mjs files, e.g. for @vueuse/core
config.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: 'javascript/auto'
});

// Extend webpack config only for client bundle
if (isClient) {
// Build source maps to aid debugging in production builds
Expand Down
5 changes: 2 additions & 3 deletions packages/portal/src/components/download/DownloadButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
<script>
import axios from 'axios';
import LoadingSpinner from '../generic/LoadingSpinner';
import canonicalUrlMixin from '@/mixins/canonicalUrl';
import logEventMixin from '@/mixins/logEvent';
import { ITEM_URL_PREFIX } from '@/plugins/europeana/data.js';

Expand All @@ -32,9 +31,9 @@
LoadingSpinner
},
mixins: [
canonicalUrlMixin,
logEventMixin
],
inject: ['canonicalUrl'],
props: {
url: {
type: String,
Expand Down Expand Up @@ -136,7 +135,7 @@
if (!this.disabled) {
this.logEvent('download', `${ITEM_URL_PREFIX}${this.identifier}`);
if (this.$matomo) {
this.$matomo.trackLink(this.canonicalUrl({ fullPath: false, locale: false }), 'download');
this.$matomo.trackLink(this.canonicalUrl.withNeitherLocaleNorQuery, 'download');
if (!this.clicked) {
this.$matomo.trackEvent('Item_download', 'Click download button', this.url);
this.clicked = true;
Expand Down
8 changes: 3 additions & 5 deletions packages/portal/src/components/generic/ViewCount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
<script>
import axios from 'axios';

import canonicalUrlMixin from '@/mixins/canonicalUrl';

export default {
name: 'ViewCount',

mixins: [
canonicalUrlMixin
inject: [
'canonicalUrl'
],

props: {
Expand All @@ -42,7 +40,7 @@
return;
}

const url = this.url || this.canonicalUrl({ fullPath: true, locale: false });
const url = this.url || this.canonicalUrl.withOnlyQuery;

const viewsResponse = await axios({
baseURL: this.$config.app.baseUrl,
Expand Down
79 changes: 79 additions & 0 deletions packages/portal/src/components/provide/ProvideCanonicalUrl.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template>
<div>
<slot />
</div>
</template>

<script>
import { computed } from 'vue';

// This would ideally be a composable, but couldn't get that working wrt
// provision of baseUrl, i18n and route from Options API setup function where
// there is no vue/nuxt context available, and lack of v3 helpers like useContext
export default {
name: 'ProvideCanonicalUrl',

provide() {
return {
canonicalUrl: computed(() => this.canonicalUrl)
};
},

data() {
return {
canonicalUrl: {}
};
},

head() {
return {
link: [
{ hreflang: 'x-default', rel: 'alternate', href: this.canonicalUrl.withOnlyQuery }
],
meta: [
{ hid: 'og:url', property: 'og:url', content: this.canonicalUrl.withBothLocaleAndQuery }
]
};
},

watch: {
$route: {
handler() {
this.setCanonicalUrl();
},
deep: true
},
'$i18n.locale'() {
this.setCanonicalUrl();
}
},

created() {
this.setCanonicalUrl();
},

methods: {
pathToUrl(path) {
return `${this.$config.app.baseUrl}${path}`;
},

pathWithoutLocale(path) {
if (this.$route.path === `/${this.$i18n.locale}`) {
return path.replace(this.$i18n.locale, '');
} else if (path.startsWith(`/${this.$i18n.locale}/`)) {
return path.slice(3);
}
return path;
},

setCanonicalUrl() {
this.canonicalUrl = {
withBothLocaleAndQuery: this.pathToUrl(this.$route.fullPath),
withOnlyQuery: this.pathToUrl(this.pathWithoutLocale(this.$route.fullPath)),
withOnlyLocale: this.pathToUrl(this.$route.path),
withNeitherLocaleNorQuery: this.pathToUrl(this.pathWithoutLocale(this.$route.path))
};
}
}
};
</script>
8 changes: 3 additions & 5 deletions packages/portal/src/components/share/ShareSocialButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@
</template>

<script>
import canonicalUrlMixin from '@/mixins/canonicalUrl';

export default {
name: 'ShareSocialButtons',

mixins: [
canonicalUrlMixin
inject: [
'canonicalUrl'
],

props: {
Expand All @@ -45,7 +43,7 @@

computed: {
shareUrl() {
return this.canonicalUrl({ fullPath: true, locale: false });
return this.canonicalUrl.withOnlyQuery;
},
networks() {
return [
Expand Down
26 changes: 13 additions & 13 deletions packages/portal/src/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
:text="$t(`notificationBanner.text.${notificationBanner}`)"
/>
</client-only>
<nuxt
id="main"
/>
<ProvideCanonicalUrl>
<nuxt
id="main"
/>
</ProvideCanonicalUrl>
</main>
<client-only>
<NewFeatureNotification
Expand All @@ -58,9 +60,9 @@

<script>
import ClientOnly from 'vue-client-only';
import PageHeader from '../components/page/PageHeader';
import ErrorModal from '../components/error/ErrorModal';
import canonicalUrlMixin from '@/mixins/canonicalUrl';
import PageHeader from '@/components/page/PageHeader';
import ProvideCanonicalUrl from '@/components/provide/ProvideCanonicalUrl';
import ErrorModal from '@/components/error/ErrorModal';
import makeToastMixin from '@/mixins/makeToast';
import versions from '../../pkg-versions';
import { activeFeatureNotification } from '@/features/notifications';
Expand All @@ -69,18 +71,18 @@
name: 'DefaultLayout',

components: {
DebugApiRequests: () => import('../components/debug/DebugApiRequests'),
DebugApiRequests: () => import('@/components/debug/DebugApiRequests'),
ClientOnly,
PageCookiesWidget: () => import('@/components/page/PageCookiesWidget'),
PageHeader,
PageFooter: () => import('../components/page/PageFooter'),
NewFeatureNotification: () => import('../components/generic/NewFeatureNotification'),
PageFooter: () => import('@/components/page/PageFooter'),
ProvideCanonicalUrl,
NewFeatureNotification: () => import('@/components/generic/NewFeatureNotification'),
NotificationBanner: () => import('@/components/generic/NotificationBanner'),
ErrorModal
},

mixins: [
canonicalUrlMixin,
makeToastMixin
],

Expand All @@ -107,14 +109,12 @@
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap@${versions.bootstrap}/dist/css/bootstrap.min.css` },
{ rel: 'preload', as: 'style', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` },
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` },
{ hreflang: 'x-default', rel: 'alternate', href: this.canonicalUrl({ fullPath: true, locale: false }) },
...i18nHead.link
],
meta: [
...i18nHead.meta,
{ hid: 'description', name: 'description', content: this.$config.app.siteName },
{ hid: 'og:description', property: 'og:description', content: this.$config.app.siteName },
{ hid: 'og:url', property: 'og:url', content: this.canonicalUrl({ fullPath: true, locale: true }) }
{ hid: 'og:description', property: 'og:description', content: this.$config.app.siteName }
]
};
},
Expand Down
20 changes: 8 additions & 12 deletions packages/portal/src/layouts/ds4ch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
id="ds4ch"
role="main"
>
<nuxt
id="main"
/>
<ProvideCanonicalUrl>
<nuxt
id="main"
/>
</ProvideCanonicalUrl>
</main>
<DS4CHPageFooter />
<client-only>
Expand All @@ -32,7 +34,7 @@

import DS4CHPageHeader from '@/components/DS4CH/DS4CHPageHeader';
import DS4CHPageFooter from '@/components/DS4CH/DS4CHPageFooter';
import canonicalUrlMixin from '@/mixins/canonicalUrl';
import ProvideCanonicalUrl from '@/components/provide/ProvideCanonicalUrl';
import versions from '../../pkg-versions';

export default {
Expand All @@ -42,13 +44,10 @@
ClientOnly,
DS4CHPageHeader,
DS4CHPageFooter,
PageCookiesWidget: () => import('@/components/page/PageCookiesWidget')
PageCookiesWidget: () => import('@/components/page/PageCookiesWidget'),
ProvideCanonicalUrl
},

mixins: [
canonicalUrlMixin
],

head() {
return {
link: [
Expand All @@ -57,9 +56,6 @@
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap@${versions.bootstrap}/dist/css/bootstrap.min.css` },
{ rel: 'preload', as: 'style', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` },
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` }
],
meta: [
{ hid: 'og:url', property: 'og:url', content: this.canonicalUrl({ fullPath: true, locale: true }) }
]
};
}
Expand Down
20 changes: 8 additions & 12 deletions packages/portal/src/layouts/landing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
id="landing-layout"
role="main"
>
<nuxt
id="main"
/>
<ProvideCanonicalUrl>
<nuxt
id="main"
/>
</ProvideCanonicalUrl>
</main>
<LandingPageFooter />
<client-only>
Expand All @@ -30,7 +32,7 @@
<script>
import LandingPageHeader from '@/components/landing/LandingPageHeader';
import LandingPageFooter from '@/components/landing/LandingPageFooter';
import canonicalUrlMixin from '@/mixins/canonicalUrl';
import ProvideCanonicalUrl from '@/components/provide/ProvideCanonicalUrl';
import versions from '../../pkg-versions';

export default {
Expand All @@ -39,13 +41,10 @@
components: {
LandingPageHeader,
LandingPageFooter,
PageCookiesWidget: () => import('@/components/page/PageCookiesWidget')
PageCookiesWidget: () => import('@/components/page/PageCookiesWidget'),
ProvideCanonicalUrl
},

mixins: [
canonicalUrlMixin
],

head() {
return {
link: [
Expand All @@ -54,9 +53,6 @@
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap@${versions.bootstrap}/dist/css/bootstrap.min.css` },
{ rel: 'preload', as: 'style', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` },
{ rel: 'stylesheet', href: `https://cdn.jsdelivr.net/npm/bootstrap-vue@${versions['bootstrap-vue']}/dist/bootstrap-vue.min.css` }
],
meta: [
{ hid: 'og:url', property: 'og:url', content: this.canonicalUrl({ fullPath: true }) }
]
};
}
Expand Down
17 changes: 0 additions & 17 deletions packages/portal/src/mixins/canonicalUrl.js

This file was deleted.

7 changes: 4 additions & 3 deletions packages/portal/src/pages/exhibitions/_exhibition/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@
import exhibitionChapters from '@/mixins/exhibitionChapters';
import pageMetaMixin from '@/mixins/pageMeta';
import logEventMixin from '@/mixins/logEvent';
import canonicalUrlMixin from '@/mixins/canonicalUrl';

export default {
name: 'ExhibitionPage',
Expand All @@ -137,11 +136,13 @@
ViewCount
},
mixins: [
canonicalUrlMixin,
exhibitionChapters,
logEventMixin,
pageMetaMixin
],
inject: [
'canonicalUrl'
],
asyncData({ params, query, error, app, redirect }) {
if (params.exhibition === undefined) {
redirect(app.localePath({ name: 'exhibitions' }));
Expand Down Expand Up @@ -198,7 +199,7 @@
},

mounted() {
this.logEvent('view', this.canonicalUrl({ fullPath: true, locale: false }));
this.logEvent('view', this.canonicalUrl.withOnlyQuery);
}
};
</script>
Loading
Loading