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

feat: APPS-2928 prerendering error pages and draft previews layout #36

Merged
merged 5 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@
import { provideTheme } from '@/composables/provideTheme'
provideTheme()
const { enabled, state } = usePreviewMode()
console.log('App.vue', enabled.value, state.token)
const route = useRoute()

const globalStore = useGlobalStore()
const { header, setHeader } = useHeader()
setHeader(globalStore)
const classes = ref(['layout',
'layout-default'])
const primaryMenuItems = computed(() => {
// convert file to typescript if we want to use '?' operator to avoid this
// ex: return globalStore?.header?.primary
return header?.value?.primary
})
watch(globalStore.header, (newVal, oldVal) => {
console.log('Global store changed for draft previews', newVal, oldVal)
setHeader(globalStore)
})
const { $layoutData } = useNuxtApp()
onMounted(async () => {
// globalstore state is lost due to 404 error for draft previews, this is hack to repopulate state on client side
console.log('No layout query', route.query, 'preview enabled', enabled.value, 'state?.token', state?.token)
if (process.env.NODE_ENV !== 'development' && (route.query?.preview === 'true' || enabled.value) && (route.query?.token !== undefined || state?.token !== undefined)) {
await $layoutData()
}
})
</script>

<template>
Expand All @@ -14,8 +39,55 @@ const { enabled, state } = usePreviewMode()
to="#main"
label="Skip to main content"
/>
<NuxtLayout>
<div :class="classes">
<site-brand-bar class="brand-bar" />
<header-sticky
v-if="primaryMenuItems"
class="primary"
:primary-items="primaryMenuItems"
/>
<NuxtPage />
</NuxtLayout>
<footer data-test="footer">
<footer-main />
</footer>
</div>
</div>
</template>
<style lang="scss" scoped>
.layout-default {
min-height: 100vh;

display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-between;
align-content: center;
align-items: center;

:deep(>*) {
width: 100%;
}

flex: 1 1 auto;

.brand-bar {
width: 100%;
z-index: 100;
}

.primary {
position: sticky;
will-change: top;
}

@media #{$small} {
.brand-bar {
display: none;
}
}
}

.vue-skip-to {
z-index: 300;
}
</style>
15 changes: 15 additions & 0 deletions composables/useHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const useHeader = () => {
const header = useState('header', () => {})

const setHeader = (store) => {
console.log('set header', import.meta.server)
console.log('setHeader', store, header.value || 'None!')
if (!header.value) {
header.value = store.header
}
}
return {
header,
setHeader
}
}
3 changes: 2 additions & 1 deletion error.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ const props = defineProps({
error: Object as () => NuxtError
})
const isDevelopment = computed(() => process.env.NODE_ENV === 'development')

</script>

<template>
<NuxtLayout>
<NuxtLayout :is-error="true">
<main
id="main"
class="page page-error"
Expand Down
10 changes: 0 additions & 10 deletions gql/queries/FTVAFooterLinks.gql

This file was deleted.

10 changes: 0 additions & 10 deletions gql/queries/FTVAFooterPrimaryItems.gql

This file was deleted.

7 changes: 0 additions & 7 deletions gql/queries/FTVAFooterSockItems.gql

This file was deleted.

27 changes: 27 additions & 0 deletions gql/queries/FTVALayout.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#import "../gql/fragments/MenuItem.gql"

query FTVALayout {
primary: nodes(navHandle: "ftvaPrimaryMenu", level: 1) {
...MenuItem
children {
...MenuItem
}
}
footerPrimary: nodes(navHandle: "footerPrimary", level: 1) {
...MenuItem
children {
...MenuItem
}
}
footerLinks: nodes(navHandle: "ftvaFooterNav", level: 1) {
category: title
children(level: 2) {
...MenuItem
}
}

footerSock: nodes(navHandle: "footerSockLinks") {
...MenuItem
}

}
13 changes: 0 additions & 13 deletions gql/queries/HeaderMainMenuItems.gql

This file was deleted.

31 changes: 18 additions & 13 deletions layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
<script setup>

// This layout is only used for error.vue page, for the rest of the page templates we have layout added to app.vue

import { provideTheme } from '@/composables/provideTheme'
provideTheme()

const { enabled, state } = usePreviewMode()
const layoutCustomProps = useAttrs()
const globalStore = useGlobalStore()

const classes = ref(['layout',
'layout-default',])

Expand All @@ -13,8 +19,19 @@ const primaryMenuItems = computed(() => {
})

const isMobile = ref(false)
watch(globalStore, (newVal, oldVal) => {
console.log('Global store changed', newVal, oldVal)
})
const { $layoutData } = useNuxtApp()
// globalstore state is lost when error page is generated , this is hack to repopulate state on client side
onMounted(async () => {
console.log('In default layout', enabled.value, state?.token)

if (process.env.NODE_ENV !== 'development' && layoutCustomProps['is-error']) {
console.log('In SSG refresh layout data as state is not maintained after an error response')
await $layoutData()
}

onMounted(() => {
classes.value.push({ 'has-scrolled': globalStore.sTop })
classes.value.push({ 'has-scrolled-past-header': globalStore.sTop >= 150 })
isMobile.value = globalStore.winWidth <= 1024
Expand All @@ -30,19 +47,7 @@ onMounted(() => {
class="primary"
:primary-items="primaryMenuItems"
/>

<slot />
<div
v-if="$route.path === '/'"
style="padding: 50px 250px"
>
<hr>
<pre>FOOTER Primary {{ globalStore.footerPrimary }}</pre>
<hr>
<pre>FOOTER LINKS{{ globalStore.footerLinks }}</pre>
<hr>
</div>

<footer data-test="footer">
<footer-main />
</footer>
Expand Down
1 change: 0 additions & 1 deletion pages/events/[slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import FTVAEventDetail from '../gql/queries/FTVAEventDetail.gql'
const { $graphql } = useNuxtApp()

const route = useRoute()

// DATA
const { data, error } = await useAsyncData(`events-detail-${route.params.slug}`, async () => {
const data = await $graphql.default.request(FTVAEventDetail, { slug: route.params.slug })
Expand Down
4 changes: 1 addition & 3 deletions pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,6 @@ useHead({

<style lang="scss" scoped>
.page-home {
.button-more {
margin: var(--space-2xl) auto;
}
margin: 20px;
}
</style>
37 changes: 37 additions & 0 deletions plugins/craft-layout-data.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// GQL
import FTVALayout from '../gql/queries/FTVALayout.gql'

export default defineNuxtPlugin((nuxtApp) => { //
const { $graphql } = useNuxtApp()
const globalStore = useGlobalStore()
// console.log('Nuxt plugin client side called from Default layout')
const layoutData = async () => {
// console.log('Nuxt plugin ready to call graphQL API in Default layout')

const data = await $graphql.default.request(FTVALayout)

// console.log('Pinia store Global Data object:' + JSON.stringify(data))
if (data) {
globalStore.header.primary = data?.primary
globalStore.footerLinks.nodes = data?.footerLinks
globalStore.footerSock.nodes = data?.footerSock
globalStore.footerPrimary = {
nodes: [
{
...data?.footerPrimary[0]
},
{
...data?.footerPrimary[1]
}
]
}

console.log('globalStore.footerPrimary', JSON.stringify(globalStore.footerPrimary))
}
}
return {
provide: {
layoutData,
},
}
})
Loading