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-3139 Add GQL Query and Create catch all page [...slug].vue #109

Merged
merged 49 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
31e589f
updates queries and add generalcontent slug page
jendiamond Feb 6, 2025
f89939c
update the query
jendiamond Feb 7, 2025
bff385b
update the query
jendiamond Feb 7, 2025
8069d0d
update the query
jendiamond Feb 7, 2025
8d1a2d2
component and gql updates
jendiamond Feb 8, 2025
2ef64f5
Merge branch 'main' into APPS-3139_add-gql-query-and-create-catch-all…
jendiamond Feb 8, 2025
cd5cc5f
update for Page Anchor component
jendiamond Feb 8, 2025
8e6c8c5
component library update to 3.47..0
jendiamond Feb 8, 2025
1d54cb9
linting
jendiamond Feb 8, 2025
34588ad
linting
jendiamond Feb 8, 2025
5058387
delete styles
jendiamond Feb 8, 2025
7f75e34
delete styles
jendiamond Feb 8, 2025
f9a919e
comment out console statement with // eslint-disable-next-line no-con…
jendiamond Feb 8, 2025
02b1311
Merge branch 'main' into APPS-3139_add-gql-query-and-create-catch-all…
jendiamond Feb 11, 2025
dcc0152
update FTVAGeneralContentDetail.gql
jendiamond Feb 12, 2025
f782f74
update FTVAGeneralContentDetail.gql
jendiamond Feb 12, 2025
c0329d8
update to data.value.entry && import.meta.prerender
jendiamond Feb 12, 2025
de19fc2
update AllFtvaFpb.gql and fragments info blck and associatedTopicCards
jendiamond Feb 14, 2025
ba4722b
fix AllFtvaFpb.gql and fragments
jendiamond Feb 18, 2025
3055b07
update gql query to lookfor the slug instead of the uri
jendiamond Feb 18, 2025
4a082b8
comment
jendiamond Feb 18, 2025
da0d142
clean up
jendiamond Feb 18, 2025
f353055
navbreadcrumb updates
jendiamond Feb 19, 2025
1dd1b2f
update from plugin to util
jendiamond Feb 19, 2025
f83829a
change from plugin to util
jendiamond Feb 19, 2025
1ea1a94
update getHeaders onMounted
jendiamond Feb 19, 2025
1c0bc49
name change
jendiamond Feb 19, 2025
01265b1
linting
jendiamond Feb 19, 2025
15bdb19
linting
jendiamond Feb 19, 2025
3dcbdf9
update nuxt.config.ts to get rid of the ftva in the url
jendiamond Feb 19, 2025
f3a0e14
remove parseParentTitle
jendiamond Feb 19, 2025
2f28f7c
remove util import
jendiamond Feb 19, 2025
963f715
remove parseTitle computed property
jendiamond Feb 19, 2025
d80b39e
update cardMeta from using the prop to using the slot
jendiamond Feb 19, 2025
d9458eb
update comment
jendiamond Feb 19, 2025
9e55540
update comment
jendiamond Feb 19, 2025
e1e392e
update getHeaders on the [...slug] page and in the util, add image to…
jendiamond Feb 19, 2025
d9519e5
update styles, fix PageAnchor, add carousel image
jendiamond Feb 20, 2025
35df856
linting
jendiamond Feb 20, 2025
c0434f6
linting
jendiamond Feb 20, 2025
31d767f
linting
jendiamond Feb 20, 2025
dacb0ba
linting
jendiamond Feb 20, 2025
e0a08ff
update css
jendiamond Feb 20, 2025
2ac3238
update h3 header
jendiamond Feb 20, 2025
7107322
updated the onMounted for getHeaders
jendiamond Feb 21, 2025
7b7d546
updated the onMounted for getHeaders
jendiamond Feb 21, 2025
e4343d4
updated the onMounted for getHeaders
jendiamond Feb 21, 2025
4ec2d54
updated the onMounted for getHeaders add import.meta.client
jendiamond Feb 21, 2025
ebc07ca
update the comment in the getHeaders file
jendiamond Feb 21, 2025
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
34 changes: 17 additions & 17 deletions gql/fragments/BlockAssociatedTopicCardsFragment.gql
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
fragment BlockAssociatedTopicCardsFragment on ElementInterface {
id
typeHandle
sectionTitle: titleGeneral
sectionSummary: summary
associatedTopicsFlexiblePageBlock {
... on associatedTopicsFlexiblePageBlock_associatedTopics_BlockType {
id
topics {
title
typeHandle
externalResourceUrl
uri
text: summary
uri
iconName: illustrationsResourcesAndServices
}
}
id
typeHandle
sectionTitle: titleGeneral
sectionSummary: summary
associatedTopicsFlexiblePageBlock {
... on associatedTopicsFlexiblePageBlock_associatedTopics_BlockType {
id
topics {
title
typeHandle
externalResourceUrl
uri
text: summary
uri
iconName: illustrationsResourcesAndServices
}
}
}
}
10 changes: 0 additions & 10 deletions gql/fragments/BlockContactInfoFragment.gql

This file was deleted.

18 changes: 18 additions & 0 deletions gql/fragments/BlockInfoFragment.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
fragment BlockInfoFragment on ElementInterface {
id
typeHandle
infoBlock {
... on infoBlock_infoBlock_BlockType {
typeHandle
icon
heading
text
}
... on infoBlock_contactInfoBlock_BlockType {
typeHandle
email
phone
address
}
}
}
14 changes: 8 additions & 6 deletions gql/fragments/collections/AllFtvaFpb.gql
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#import "../gql/fragments/Image.gql"
#import "../gql/fragments/MediaAsset.gql"
#import "../gql/fragments/BlockAssociatedTopicCardsFragment.gql"
#import "../gql/fragments/BlockCallToActionFragment.gql"
#import "../gql/fragments/BlockContactInfoFragment.gql"
#import "../gql/fragments/BlockFormFragment.gql"
#import "../gql/fragments/BlockHorizontalDividerFragment.gql"
#import "../gql/fragments/BlockImpactNumberCardsFragment.gql"
#import "../gql/fragments/BlockInfoFragment.gql"
#import "../gql/fragments/BlockMediaGalleryFragment.gql"
#import "../gql/fragments/BlockMediaWithTextFragment.gql"
#import "../gql/fragments/BlockPullQuoteFragment.gql"
Expand All @@ -16,12 +15,12 @@ fragment AllFtvaFpb on ElementInterface {
id
typeHandle

... on allFtvaFpb_associatedTopics_BlockType {
...BlockAssociatedTopicCardsFragment
}
... on allFtvaFpb_callToAction_BlockType {
...BlockCallToActionFragment
}
... on allFtvaFpb_contactInfo_BlockType {
...BlockContactInfoFragment
}
... on allFtvaFpb_form_BlockType {
...BlockFormFragment
}
Expand All @@ -31,6 +30,9 @@ fragment AllFtvaFpb on ElementInterface {
... on allFtvaFpb_impactNumberCards_BlockType {
...BlockImpactNumberCardsFragment
}
... on allFtvaFpb_infoBlock_BlockType {
...BlockInfoFragment
}
... on allFtvaFpb_mediaGallery_BlockType {
...BlockMediaGalleryFragment
}
Expand Down
28 changes: 28 additions & 0 deletions gql/queries/FTVAGeneralContentDetail.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#import "../gql/fragments/collections/AllFtvaFpb.gql"
#import "../gql/fragments/Image.gql"

query FTVAGeneralContent($slug: [String!]) {
entry(section: "ftvaGeneralContentPage", slug: $slug) {
... on ftvaGeneralContentPage_generalContentPage_Entry {
id
uri
slug
title
formattedTitle
ftvaHomepageDescription
imageCarousel {
...on imageCarousel_imageCarousel_BlockType {
image {
...Image
}
creditText
}
}
...AllFtvaFpb
}
}
}

# Because the generalcontent page uses ftva/ in the uri
# to differentiate between the library and meap websites
# the GQL query will need the slug instead of the uri
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default defineNuxtConfig({
const postPages = await response.json()
// console.log('All pages', JSON.stringify(postPages.data.entries))
if (postPages && postPages.data && postPages.data.entries) {
const postWithoutPayloadRoutes = postPages.data.entries.filter(item => item.sectionHandle.includes('ftva')).map(entry => '/' + entry.uri)
const postWithoutPayloadRoutes = postPages.data.entries.filter(item => item.sectionHandle.includes('ftva')).map(entry => '/' + entry.uri.replace(/^ftva\//, ''))
allRoutes.push(...postWithoutPayloadRoutes)
}

Expand Down
189 changes: 189 additions & 0 deletions pages/[...slug].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<script setup>
// COMPONENT RE-IMPORTS
// TODO: remove when we have implemented component library as a module
// https://nuxt.com/docs/guide/directory-structure/components#library-authors
import {
TwoColLayoutWStickySideBar, NavBreadcrumb, ResponsiveImage, CardMeta, RichText, PageAnchor, FlexibleBlocks, SectionWrapper,
} from 'ucla-library-website-components'

import { onMounted, nextTick } from 'vue'

// HELPERS
import _get from 'lodash/get'

// GQL
import FTVA_GENERAL_CONTENT_DETAIL from '../gql/queries/FTVAGeneralContentDetail.gql'

const { $graphql } = useNuxtApp()

const route = useRoute()

const path = route.path.replace(/^\/|\/$/g, '') // trim initial and/or final slashes

// Because the generalcontent page uses ftva / in the uri
// to differentiate between the library and meap websites
// the GQL query will need the slug instead of the uri
const { data, error } = await useAsyncData(`general-content-${path}`, async () => {
const data = await $graphql.default.request(FTVA_GENERAL_CONTENT_DETAIL, {
slug: path.substring(
path.lastIndexOf('/') + 1
),
})
return data
})

if (error.value) {
throw createError({
...error.value, statusMessage: 'Page not found.' + error.value, fatal: true
})
}

if (!data.value.entry) {
// console.log('no data')
throw createError({
statusCode: 404,
statusMessage: 'Page Not Found',
fatal: true
})
}

if (data.value.entry && import.meta.prerender) {
// Call the composable to use the indexing function
const { indexContent } = useContentIndexer()
await indexContent(data.value.entry, path.replaceAll('/', '--'))
}

const page = ref(_get(data.value, 'entry', {}))

watch(data, (newVal, oldVal) => {
// eslint-disable-next-line no-console
console.log('In watch preview enabled, newVal, oldVal', newVal, oldVal)
page.value = _get(newVal, 'entry', {})
})

const h2Array = ref([]) // anchor tags

// Get data for Image or Carousel at top of page
const parsedImage = computed(() => {
return page.value.imageCarousel
})

// Transform data for Carousel
const parsedCarouselData = computed(() => {
// map image to item, map creditText to credit
return parsedImage.value.map((rawItem, index) => {
return {
item: [{ ...rawItem.image[0], kind: 'image' }], // Carousels on this page are always images, no videos
credit: rawItem?.creditText,
}
})
})

useHead({
title: page.value ? page.value.title : '... loading'
})

onMounted(() => {
if (import.meta.client) {
// Directly access headers assuming the DOM is ready
h2Array.value = getHeaders()
}
})
</script>

<template lang="html">
<main
id="main"
class="page page-detail page-general-content"
>
<div class="one-column">
<NavBreadcrumb data-test="breadcrumb" />

<ResponsiveImage
v-if="parsedImage && parsedImage.length === 1 && parsedImage[0]?.image && parsedImage[0]?.image?.length === 1"
data-test="single-image"
:media="parsedImage[0]?.image[0]"
:aspect-ratio="43.103"
/>

<div
v-else
class="lightbox-container"
>
<FlexibleMediaGalleryNewLightbox
data-test="image-carousel"
:items="parsedCarouselData"
inline="true"
>
<template #default="slotProps">
<BlockTag
data-test="credit-text"
:label="parsedCarouselData[slotProps.selectionIndex]?.creditText"
/>
</template>
</FlexibleMediaGalleryNewLightbox>
</div>
</div>

<TwoColLayoutWStickySideBar
data-test="second-column"
class="two-column"
>
<template #primaryTop>
<div v-if="page.formattedTitle">
<h3 class="page-title">
<rich-text :rich-text-content="page.formattedTitle" />
</h3>
</div>

<div v-else>
<h3 class="page-title">
{{ page.title }}
</h3>
</div>
</template>

<template #primaryMid>
<FlexibleBlocks
class="flexible-content"
:blocks="page.blocks"
/>
</template>

<template #sidebarTop>
<PageAnchor
v-if="h2Array.length >= 3"
:section-titles="h2Array"
/>
</template>
</TwoColLayoutWStickySideBar>

<SectionWrapper section-title="HEADERS for the PageAnchors">
<code> {{ getHeaders() }}</code>
</SectionWrapper>

<SectionWrapper section-title="PAGE DATA">
<code>{{ page }}</code>
</SectionWrapper>
</main>
</template>

<style lang="scss" scoped>
.page-general-content {
position: relative;

.page-title {
display: block;

.translation {
display: block;
}

@include ftva-h2;
color: $heading-grey;
margin: 0 0 24px;
}
}

@import 'assets/styles/slug-pages.scss';
</style>
2 changes: 1 addition & 1 deletion pages/series/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ watch(() => route.query,
<SectionPagination
v-if="
totalPages
!== 1 && !isMobile"
!== 1 && !isMobile"
class="pagination"
:pages="totalPages"
:initial-current-page="currentPage"
Expand Down
43 changes: 43 additions & 0 deletions utils/getHeaders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export default function getHeaders() {
if (typeof document === 'undefined') {
// eslint-disable-next-line no-console
console.warn('getHeaders() called on server-side. Skipping execution.')
return []
}

const elements = document.querySelectorAll('.section-title, .section-header2, .section-header3, section-header4')

if (!elements.length) {
// eslint-disable-next-line no-console
console.warn('No header elements found. getHeaders() is running too early.')
return []
}

const h2Array = []

elements.forEach((element) => {
if (element.textContent.trim() !== 'More Information') {
h2Array.push(element.textContent.trim())
}
})
// console.log('HEY HEY HEY HEADER ARRAY:', h2Array)
return h2Array
}

// This Function
// Finds all elements with class name "section-header2" or "section-header3"
// Loop through each section-header element and push it into the array
// Excludes the section-header2 More Information which is a visually-hidden element above the divider-way-finder in the Flexible Block component

// This Function along with the onMounted function on the page
// Prevents getHeaders() from running during SSR (Server-Side Rendering).
// Adds a setTimeout(500ms) delay to ensure DOM updates are finished.
// Checks for document and .section-header elements before running querySelectorAll().

// See the [...slug].vue page around line 70
// onMounted(() => {
// if (import.meta.client) {
// // Directly access headers assuming the DOM is ready
// h2Array.value = getHeaders()
// }
// })
Loading