Skip to content

Commit

Permalink
Merge pull request #216 from Police-Data-Accessibility-Project/featur…
Browse files Browse the repository at this point in the history
…e/open-graph-defaults

feat(router): add logic to router to handle meta tags
  • Loading branch information
mbodeantor committed Mar 20, 2024
2 parents a35e2c7 + 4642765 commit d6db7e4
Showing 1 changed file with 89 additions and 4 deletions.
93 changes: 89 additions & 4 deletions client/src/router.js
Expand Up @@ -8,10 +8,21 @@ import QuickSearchPage from '../src/pages/QuickSearchPage.vue';
import ResetPassword from './pages/ResetPassword.vue';
import SearchResultPage from '../src/pages/SearchResultPage.vue';

export const PRIVATE_ROUTES = ['/change-password'];
import acronym from 'pdap-design-system/images/acronym.svg';

const routes = [
{ path: '/', component: QuickSearchPage, name: 'QuickSearchPage' },
{
path: '/',
component: QuickSearchPage,
name: 'QuickSearchPage',
// Use meta property on route to override meta tag defaults
// meta: { title: 'Police Data Accessibility Project - Search', metaTags: [{ property: 'og:title', title: 'Police Data Accessibility Project - Search' }] },
},
{
path: '/search',
component: SearchResultPage,
name: 'SearchResultPage',
},
{
path: '/search/:searchTerm/:location',
component: SearchResultPage,
Expand Down Expand Up @@ -44,14 +55,88 @@ const router = createRouter({
routes,
});

router.beforeEach(async (to) => {
router.beforeEach(async (to, _, next) => {
// Update meta tags per route
refreshMetaTagsByRoute(to);

// redirect to login page if not logged in and trying to access a restricted page
const auth = useAuthStore();

if (PRIVATE_ROUTES.includes(to.fullPath) && !auth.userId) {
auth.returnUrl = to.path;
router.push('/login');
}

next();
});

// Util
export const PRIVATE_ROUTES = ['/change-password'];

const DEFAULT_META_TAGS = new Map([
[
'description',
'Data and tools for answering questions about any police system in the United States',
],
['title', 'Police Data Accessibility Project'],
[
'og:description',
'Data and tools for answering questions about any police system in the United States',
],
['og:title', 'Police Data Accessibility Project'],
['og:type', 'website'],
['og:site_name', 'PDAP'],
['og:image', acronym],
]);
const META_PROPERTIES = [...DEFAULT_META_TAGS.keys(), 'og:url'];

/**
* Adds meta tags by route
* @param {RouteLocationNormalized} to Vue router route location
*/
function refreshMetaTagsByRoute(to) {
// Get nearest matched route that has title / meta tag overrides
const nearestRouteWithTitle = [...to.matched]
.reverse()
.find((route) => route?.meta?.title);

const nearestRouteWithMeta = [...to.matched]
.reverse()
.find((route) => route?.meta?.metaTags);

// Update document title
document.title =
nearestRouteWithTitle?.meta?.title ?? DEFAULT_META_TAGS.get('title');

// Update meta tags
Array.from(document.querySelectorAll('[data-controlled-meta]')).forEach(
(el) => el.parentNode.removeChild(el),
);

META_PROPERTIES.filter((prop) => prop !== 'title')
.map((prop) => {
const tagInRouteMetaData = nearestRouteWithMeta?.meta?.metaTags?.find(
(tag) => tag.property === prop,
);

let content;
switch (true) {
case prop === 'og:url':
content = `${import.meta.env.VITE_VUE_APP_BASE_URL}${to.fullPath}`;
break;
case Boolean(tagInRouteMetaData):
content = tagInRouteMetaData.content;
break;
default:
content = DEFAULT_META_TAGS.get(prop);
}

const tag = document.createElement('meta');
tag.setAttribute(prop.includes(':') ? 'property' : 'name', prop);
tag.setAttribute('content', content);
tag.setAttribute('data-controlled-meta', true);
return tag;
})
.forEach((tag) => document.head.appendChild(tag));
}

export default router;

0 comments on commit d6db7e4

Please sign in to comment.