Skip to content
This repository was archived by the owner on Feb 27, 2024. It is now read-only.

Commit e3860e1

Browse files
author
Mike England
committed
git Merge branch 'feature/45-input-error-component' of github.com:WebDevStudios/nextjs-wordpress-starter into feature/45-input-error-component
2 parents f589f5a + 217ec3d commit e3860e1

39 files changed

+625
-486
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import queryDefaultSeo from '../_global/queryDefaultSeo'
2+
import formatDefaultSeoData from '@/functions/formatDefaultSeoData'
3+
import {initializeWpApollo} from '../connector'
4+
5+
// Define SEO for Frontend routes.
6+
export const frontendPageSeo = {
7+
search: {
8+
title: 'Search',
9+
description: 'Search page'
10+
}
11+
}
12+
13+
/**
14+
* Retrieve data for Frontend-only route (i.e., page does not exist in WordPress).
15+
*
16+
* @author WebDevStudios
17+
* @param {string} route Frontend route.
18+
* @return {object} Object containing Apollo client instance and post data or error object.
19+
*/
20+
export default async function getFrontendPage(route) {
21+
// Get/create Apollo instance.
22+
const apolloClient = initializeWpApollo()
23+
24+
// Set up return object.
25+
const response = {
26+
apolloClient,
27+
error: false,
28+
errorMessage: null
29+
}
30+
31+
// Execute query.
32+
response.post = await apolloClient
33+
.query({query: queryDefaultSeo})
34+
.then((res) => {
35+
const {homepageSettings, siteSeo} = res.data
36+
37+
// Retrieve default SEO data.
38+
response.defaultSeo = formatDefaultSeoData({homepageSettings, siteSeo})
39+
40+
// Set route SEO.
41+
return {
42+
seo: {
43+
title: `${frontendPageSeo?.[route]?.title} - ${
44+
response.defaultSeo?.openGraph?.siteName ?? ''
45+
}`,
46+
metaDesc: frontendPageSeo?.[route]?.description,
47+
canonical: `${response.defaultSeo?.openGraph?.url ?? ''}/${route}`
48+
}
49+
}
50+
})
51+
.catch((error) => {
52+
response.error = true
53+
response.errorMessage = error.message
54+
55+
return null
56+
})
57+
58+
return response
59+
}

api/wordpress/_global/getPostTypeArchive.js

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,46 @@ import queryServicesArchive from '../services/queryServicesArchive'
77
import queryTeamsArchive from '../teams/queryTeamsArchive'
88
import queryPortfoliosArchive from '../portfolios/queryPortfoliosArchive'
99
import queryTestimonialsArchive from '../testimonials/queryTestimonialsArchive'
10+
import formatDefaultSeoData from '@/functions/formatDefaultSeoData'
11+
12+
// Define SEO for archives.
13+
export const archiveSeo = {
14+
career: {
15+
title: 'Careers',
16+
description: '',
17+
route: 'careers'
18+
},
19+
event: {
20+
title: 'Events',
21+
description: '',
22+
route: 'events'
23+
},
24+
portfolio: {
25+
title: 'Portfolio',
26+
description: '',
27+
route: 'portfolio'
28+
},
29+
post: {
30+
title: 'Blog',
31+
description: '',
32+
route: 'blog'
33+
},
34+
service: {
35+
title: 'Services',
36+
description: '',
37+
route: 'service'
38+
},
39+
team: {
40+
title: 'Team Members',
41+
description: '',
42+
route: 'team'
43+
},
44+
testimonial: {
45+
title: 'Testimonials',
46+
description: '',
47+
route: 'testimonial'
48+
}
49+
}
1050

1151
/**
1252
* Retrieve post archive.
@@ -77,8 +117,13 @@ export default async function getPostTypeArchive(
77117
await apolloClient
78118
.query({query, variables})
79119
.then((archive) => {
120+
const {homepageSettings, siteSeo, ...archiveData} = archive.data
121+
122+
// Retrieve default SEO data.
123+
response.defaultSeo = formatDefaultSeoData({homepageSettings, siteSeo})
124+
80125
const pluralType = postTypes[postType] ?? postType
81-
const data = archive?.data?.[pluralType] ?? null
126+
const data = archiveData?.[pluralType] ?? null
82127

83128
// Set error props if data not found.
84129
if (!data?.edges || !data?.pageInfo) {
@@ -91,6 +136,29 @@ export default async function getPostTypeArchive(
91136
// Flatten posts array to include inner node post data.
92137
response.posts = data.edges.map((post) => post.node)
93138

139+
// Attempt to use posts page for blog, default to custom SEO.
140+
response.post = {
141+
seo:
142+
'post' === postType && homepageSettings?.postsPage?.seo
143+
? {
144+
...homepageSettings.postsPage.seo,
145+
canonical: `${response.defaultSeo?.openGraph?.url ?? ''}/${
146+
archiveSeo?.[postType]?.route
147+
}`
148+
}
149+
: {
150+
title: `${archiveSeo?.[postType]?.title} - ${
151+
response.defaultSeo?.openGraph?.siteName ?? ''
152+
}`,
153+
metaDesc: archiveSeo?.[postType]?.description,
154+
canonical: `${response.defaultSeo?.openGraph?.url ?? ''}/${
155+
archiveSeo?.[postType]?.route
156+
}`,
157+
metaRobotsNofollow: 'follow',
158+
metaRobotsNoindex: 'index'
159+
}
160+
}
161+
94162
// Extract pagination data.
95163
response.pagination = data.pageInfo
96164
})

api/wordpress/_global/getPostTypeById.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import queryServiceById from '../services/queryServiceById'
99
import queryTeamById from '../teams/queryTeamById'
1010
import queryPortfolioById from '../portfolios/queryPortfolioById'
1111
import queryTestimonialById from '../testimonials/queryTestimonialById'
12+
import formatDefaultSeoData from '@/functions/formatDefaultSeoData'
1213

1314
/**
1415
* Retrieve single post by specified identifier.
@@ -63,29 +64,42 @@ export default async function getPostTypeById(postType, id, idType = 'SLUG') {
6364
// Execute query.
6465
response.post = await apolloClient
6566
.query({query, variables: {id, idType}})
66-
.then((post) => {
67+
.then((res) => {
68+
const {homepageSettings, siteSeo, ...postData} = res.data
69+
70+
// Retrieve default SEO data.
71+
response.defaultSeo = formatDefaultSeoData({homepageSettings, siteSeo})
72+
73+
const post = postData?.[postType]
74+
6775
// Set error props if data not found.
68-
if (!post?.data?.[postType]) {
76+
if (!post) {
6977
response.error = true
7078
response.errorMessage = `An error occurred while trying to retrieve data for ${postType} "${id}."`
7179

7280
return null
7381
}
7482

75-
return post.data[postType]
83+
return post
7684
})
7785
.then(async (post) => {
86+
// Add slug/ID to post.
87+
const newPost = {
88+
...post,
89+
slug: id
90+
}
91+
7892
// Handle blocks.
7993
if (!post || !post?.blocksJSON) {
8094
return post
8195
}
8296

83-
const newPost = {...post}
84-
8597
newPost.blocks = await formatBlockData(
8698
JSON.parse(newPost.blocksJSON) ?? []
8799
)
88100

101+
delete newPost.blocksJSON
102+
89103
return newPost
90104
})
91105
.catch((error) => {

api/wordpress/_global/getPostTypeStaticProps.js

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import getPostTypeArchive from './getPostTypeArchive'
44
import {addApolloState} from '@/api/apolloConfig'
55
import getMenus from '@/api/wordpress/menus/getMenus'
66
import config from '@/functions/config'
7+
import getFrontendPage, {frontendPageSeo} from './getFrontendPage'
78

89
/**
910
* Retrieve static props by post type.
@@ -22,25 +23,42 @@ export default async function getPostTypeStaticProps(
2223
// Get WP Nav Menus.
2324
const menus = await getMenus(config.menuLocations)
2425

25-
// Check for dynamic archive display.
26-
if (!Object.keys(params).length) {
27-
const {apolloClient, ...archiveData} = await getPostTypeArchive(postType)
26+
// Set revalidate length (seconds).
27+
const revalidate = 60 * 5
2828

29-
// Add WP Nav Menus to archive.
30-
archiveData.menus = menus
31-
32-
// Add Algolia env vars to archive.
33-
archiveData.algolia = {
29+
// Set sharedProps.
30+
const sharedProps = {
31+
menus,
32+
algolia: {
3433
indexName: algoliaIndexName
3534
}
35+
}
36+
37+
// Check for Frontend-only routes.
38+
if (Object.keys(frontendPageSeo).includes(postType)) {
39+
const {apolloClient, ...routeData} = await getFrontendPage(postType)
40+
41+
return addApolloState(apolloClient, {
42+
props: {
43+
...routeData,
44+
...sharedProps
45+
},
46+
revalidate
47+
})
48+
}
49+
50+
// Check for dynamic archive display.
51+
if (!Object.keys(params).length) {
52+
const {apolloClient, ...archiveData} = await getPostTypeArchive(postType)
3653

3754
// Merge in query results as Apollo state.
3855
return addApolloState(apolloClient, {
3956
props: {
4057
...archiveData,
58+
...sharedProps,
4159
archive: true
4260
},
43-
revalidate: 60 * 5
61+
revalidate
4462
})
4563
}
4664

@@ -53,26 +71,22 @@ export default async function getPostTypeStaticProps(
5371
slug
5472
)
5573

56-
const props = {...postData, error}
74+
const props = {
75+
...postData,
76+
...sharedProps,
77+
error
78+
}
5779

5880
// Custom handling for homepage.
59-
if (error) {
81+
if ('/' === slug && error) {
6082
// Fallback to empty props if homepage not set in WP.
6183
props.post = null
6284
props.error = false
6385
}
6486

65-
// Set WP Nav Menus.
66-
props.menus = menus
67-
68-
// Add Algolia env vars.
69-
props.algolia = {
70-
indexName: algoliaIndexName
71-
}
72-
7387
// Merge in query results as Apollo state.
7488
return addApolloState(apolloClient, {
7589
props,
76-
revalidate: 60 * 5
90+
revalidate
7791
})
7892
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {gql} from '@apollo/client'
2+
import defaultSeoFields from '../_partials/defaultSeoFields'
3+
4+
// Query: retrieve default SEO data.
5+
const queryDefaultSeo = gql`
6+
query GET_DEFAULT_SEO {
7+
${defaultSeoFields}
8+
}
9+
`
10+
11+
export default queryDefaultSeo
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const {default: seoPostFields} = require('./seoPostFields')
2+
3+
// Query partial: retrieve homepage & site SEO fields.
4+
const defaultSeoFields = `
5+
homepageSettings {
6+
frontPage {
7+
${seoPostFields}
8+
}
9+
}
10+
siteSeo: seo {
11+
schema {
12+
siteName
13+
siteUrl
14+
}
15+
openGraph {
16+
defaultImage {
17+
altText
18+
sourceUrl(size: THUMBNAIL)
19+
}
20+
}
21+
social {
22+
facebook {
23+
url
24+
}
25+
instagram {
26+
url
27+
}
28+
linkedIn {
29+
url
30+
}
31+
mySpace {
32+
url
33+
}
34+
pinterest {
35+
url
36+
}
37+
twitter {
38+
username
39+
}
40+
wikipedia {
41+
url
42+
}
43+
youTube {
44+
url
45+
}
46+
}
47+
}
48+
`
49+
50+
export default defaultSeoFields

api/wordpress/_partials/seoPostFields.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ const seoPostFields = `
66
metaDesc
77
metaRobotsNofollow
88
metaRobotsNoindex
9+
opengraphAuthor
10+
opengraphModifiedTime
11+
opengraphPublishedTime
912
opengraphImage {
10-
sourceUrl
13+
altText
14+
sourceUrl(size: THUMBNAIL)
1115
}
1216
}
1317
`

api/wordpress/careers/queryCareerById.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import globalPostFields from '../_partials/globalPostFields'
22
import seoPostFields from '../_partials/seoPostFields'
33
import featuredImagePostFields from '../_partials/featuredImagePostFields'
44
import {gql} from '@apollo/client'
5+
import defaultSeoFields from '../_partials/defaultSeoFields'
56

67
// Fragment: retrieve single career fields.
78
const singleCareerFragment = gql`
@@ -21,6 +22,7 @@ const queryCareerById = gql`
2122
$idType: CareerIdType = SLUG
2223
$imageSize: MediaItemSizeEnum = LARGE
2324
) {
25+
${defaultSeoFields}
2426
career(id: $id, idType: $idType) {
2527
...SingleCareerFields
2628
}

0 commit comments

Comments
 (0)