pages/_section/_slug.vue (171 lines of code) (raw):
<script>
import { GlNav, GlNavItem } from '../../helpers/gitlab_ui';
import PageContainer from '../../components/page_container.vue';
import PageHeader from '../../components/page_header.vue';
import { buildMeta } from '../../helpers/seo';
/*
We only need the "section" and "slug" of the routes to find the file.
Currently the "third" component is the "tab" (e.g. implementation on component pages)
and that is handled inside `componentinfo.vue` until we have better routing:
https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/1293
*/
const getPathFromRoute = (route) => {
const { section, slug } = route.params;
return [section, slug].filter(Boolean).join('/');
};
const componentNameToLabelMap = {
dropdowns: 'dropdown',
forms: 'form',
labels: 'label',
modals: 'modal',
'radio-button': 'radio',
tables: 'table',
tabs: 'tab',
toggles: 'toggle',
};
export default {
components: {
GlNav,
GlNavItem,
PageContainer,
PageHeader,
},
scrollToTop: true,
editThisPage: {
resolve: ({ route }) => `contents/${getPathFromRoute(route)}.md`,
},
async asyncData({ $content, route, error }) {
const path = getPathFromRoute(route);
let page = null;
try {
page = await $content(path).fetch();
} catch (e) {
error({ statusCode: 404, path, message: `${path} not found`, stack: e.stack });
}
if (Array.isArray(page)) {
error({
statusCode: 500,
path,
message: `@nuxt/content returned an array of pages instead of a single page for '${path}'`,
});
}
return { page };
},
data() {
return {
page: {},
};
},
head() {
return {
title: this.page.name,
meta: buildMeta({
titleChunk: this.page.name,
path: this.page.path,
description: this.page.description,
}),
};
},
computed: {
componentLabel() {
const { section, slug } = this.$route.params;
if (section !== 'components') {
return null;
}
if (this.page.componentLabel !== undefined) {
return this.page.componentLabel;
}
return componentNameToLabelMap[slug] || slug;
},
hasComponents() {
return Boolean(this.page?.components?.length);
},
showTabs() {
return Boolean(this.tabs.length);
},
tabs() {
let { tabs = [] } = this.page;
if (this.componentLabel) {
tabs = [
{
route: 'section-slug',
title: 'Usage',
},
...tabs,
];
if (this.hasComponents) {
tabs.push({
route: 'section-slug-code',
title: 'Implementation (Vue.js)',
});
tabs.push({
route: 'section-slug-lookbook',
title: 'Implementation (Rails)',
});
}
tabs.push({
route: 'section-slug-contribute',
title: 'Contribute',
});
}
if (this.page.foundationLabel) {
tabs = [
{
route: 'section-slug',
title: 'Overview',
},
...tabs,
];
tabs.push({
route: 'section-slug-contribute',
title: 'Contribute',
});
}
return tabs;
},
lastUpdatedAt() {
const { lastGitUpdate } = this.page || {};
if (!lastGitUpdate) {
return null;
}
return new Date(lastGitUpdate).toLocaleString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
});
},
},
};
</script>
<template>
<page-container class="gl-py-7">
<page-header
:heading="page.name"
:description="page.description"
:deprecated="page.deprecated"
/>
<gl-nav v-if="showTabs" class="gl-tabs-nav !gl-mb-5">
<gl-nav-item
v-for="tab in tabs"
:key="tab.route"
exact
:to="{ name: tab.route, params: $route.params }"
link-classes="gl-tab-nav-item"
active-class="gl-tab-nav-item-active"
>
{{ tab.title }}
</gl-nav-item>
</gl-nav>
<nuxt-child
:page="page"
:component-label="componentLabel"
:foundation-label="page.foundationLabel"
/>
<p v-if="lastUpdatedAt" class="gl-mb-0 gl-mt-5 gl-text-center">
Last updated at: <time :datetime="lastUpdatedAt">{{ lastUpdatedAt }}</time>
</p>
</page-container>
</template>