From d413e7f58b8071694a7c3a6614293713aa0dbce6 Mon Sep 17 00:00:00 2001 From: Joshua Isaac Date: Wed, 9 Dec 2020 18:38:24 -0500 Subject: [PATCH] added language toggle support to starter --- gatsby-config.js | 47 ++--- package-lock.json | 24 +-- package.json | 2 +- src/AgilityPage.js | 75 +++++--- .../components/StaticMultiLangPreviewPage.js | 31 +++ src/agility/utils.js | 176 +++++++++--------- src/components/GlobalHeader.js | 147 ++++++++------- 7 files changed, 290 insertions(+), 212 deletions(-) create mode 100644 src/agility/components/StaticMultiLangPreviewPage.js diff --git a/gatsby-config.js b/gatsby-config.js index 3edb846..7ef0474 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -7,7 +7,7 @@ require("dotenv").config({ const agilityConfig = { guid: process.env.AGILITY_GUID, apiKey: process.env.AGILITY_API_KEY, - isPreview: process.env.AGILITY_API_ISPREVIEW + isPreview: process.env.AGILITY_API_ISPREVIEW, } /** @@ -19,47 +19,50 @@ const agilityConfig = { module.exports = { siteMetadata: { title: "Agility CMS Gatsby Starter", - }, plugins: [ `gatsby-plugin-netlify`, `gatsby-plugin-react-helmet`, { //the name of the plugin - resolve: "@agility/gatsby-source-agilitycms", + resolve: "@agility/gatsby-source-agilitycms", //the options for our plugin options: { //your Agility Content Fetch API Guid - guid: agilityConfig.guid, + guid: agilityConfig.guid, //your Agility Content Fetch API Key - apiKey: agilityConfig.apiKey, + apiKey: agilityConfig.apiKey, //set this to true if you are using the preview API Key - isPreview: agilityConfig.isPreview, + isPreview: agilityConfig.isPreview, //set this to true to see expanded traces in the build logs debug: false, //the languages you want to source content for - languages: [{ - // The name of the language code - name: "English", - // The actual language code set in Agility CMS - code: "en-us", - // The name to be used in the URL path that represents the current language - path: "en" - }], + languages: [ + { + // The name of the language code + name: "English", + // The actual language code set in Agility CMS + code: "en-us", + // The name to be used in the URL path that represents the current language + path: "en", + }, + ], // The channels you want to include - channels: [{ - // The reference name for the website channel as it is defined in Agility CMS - referenceName: "website" - }], - //the page template that will be used to render Agility CMS pages - masterPageTemplate: "./src/AgilityPage.js" + channels: [ + { + // The reference name for the website channel as it is defined in Agility CMS + referenceName: "website", + }, + ], + //the page template that will be used to render Agility CMS pages + masterPageTemplate: "./src/AgilityPage.js", }, }, `gatsby-plugin-sharp`, `gatsby-transformer-sharp`, - { + { resolve: `gatsby-source-filesystem`, - options: { name: `images`, path: `./src/img/` } + options: { name: `images`, path: `./src/img/` }, }, ], } diff --git a/package-lock.json b/package-lock.json index 6530f1e..bed09d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,33 +1,33 @@ { "name": "agility-gatsby-starter", - "version": "2.3.0", + "version": "2.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { "@agility/content-fetch": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@agility/content-fetch/-/content-fetch-0.8.2.tgz", - "integrity": "sha512-4JjYYA94JtcDt7AVax6WQdkf+Pn1/JhRnFEKMiV4my0boq+GDtdcwOPXvcM6ccCaDx2bUDeXQil/lNRReBSXAw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@agility/content-fetch/-/content-fetch-1.0.0.tgz", + "integrity": "sha512-cG8XMT4OtlxbuEk7DW4jwe2MK5WuCvu4vClajjOD4DerkkINtWGfvt92XHlcFQ9Az4RmBnOR4/LQMnH3l7AjXg==", "requires": { "axios": "^0.18.1", "axios-cache-adapter": "^2.4.1" } }, "@agility/content-sync": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@agility/content-sync/-/content-sync-0.1.10.tgz", - "integrity": "sha512-MB+fg0uS3HCwqPmIqkOb0CExAMiZ1bmJSHKzFkG9KbJkhywAuh9kJVKjvEwr+QYVVYe7SefGTX6pTb+UmrhEoA==", + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/@agility/content-sync/-/content-sync-0.1.20.tgz", + "integrity": "sha512-U+H+EjEOOWXZz852VVOkmY8NLNALXPSd5uPL+CI8zmS5/qz48Ke0JLehiOpeQGXteXeeAtNhih0J6s/OJMPM8A==", "requires": { - "@agility/content-fetch": "^0.8.2", + "@agility/content-fetch": "^1.0.0", "dotenv": "^8.2.0" } }, "@agility/gatsby-source-agilitycms": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@agility/gatsby-source-agilitycms/-/gatsby-source-agilitycms-1.6.0.tgz", - "integrity": "sha512-byXrblgN3ZlMjQe8wj9u4zhDSEROonY1o6FN0X+1zhozkAc24KqO1fmnJeLKc00irCS7zBz8kZtpqWc6zyO3nw==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@agility/gatsby-source-agilitycms/-/gatsby-source-agilitycms-1.6.6.tgz", + "integrity": "sha512-Pf5nR5IQn56gGdN7Tdfm01CuL0JhI5i9w9h6chZpjQpwr6QE9kRqvCVcdiDJJs4twUsyPamz8nnOWV9dv70JOQ==", "requires": { - "@agility/content-sync": "^0.1.10" + "@agility/content-sync": "^0.1.20" } }, "@babel/code-frame": { diff --git a/package.json b/package.json index 7aca422..8a1fbd6 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" }, "dependencies": { - "@agility/gatsby-source-agilitycms": "^1.6.4", + "@agility/gatsby-source-agilitycms": "^1.6.6", "dotenv": "^8.1.0", "gatsby": "^2.21.4", "gatsby-image": "^2.3.2", diff --git a/src/AgilityPage.js b/src/AgilityPage.js index 2b0704d..8f8028d 100644 --- a/src/AgilityPage.js +++ b/src/AgilityPage.js @@ -1,40 +1,63 @@ -import React from 'react' +import React from "react" import { graphql } from "gatsby" -import agilityUtils from './agility/utils' -import AgilityPageTemplate from './agility/components/AgilityPageTemplate' +import agilityUtils from "./agility/utils" +import AgilityPageTemplate from "./agility/components/AgilityPageTemplate" //Some things we need for our layout import LayoutTemplate from "./components/LayoutTemplate" import PreviewBar from "./components/PreviewBar" -import GlobalHeader from './components/GlobalHeader' -import SEO from './components/SEO' - +import GlobalHeader from "./components/GlobalHeader" +import SEO from "./components/SEO" //Our query to get the our page data and check for a dynamic page item (agilityItem) export const query = graphql` query($pageID: Int!, $contentID: Int!, $languageCode: String!) { - agilitypage(languageCode: { eq: $languageCode }, itemID: { eq: $pageID }) { - pageJson - } - agilityitem(languageCode: {eq: $languageCode}, itemID: {eq: $contentID}) { - itemJson + pageJson } -} + agilityitem( + languageCode: { eq: $languageCode } + itemID: { eq: $contentID } + ) { + itemJson + } + pagesInOtherLanguages: allAgilitySitemapNode( + filter: { + languageCode: { ne: $languageCode } + pageID: { eq: $pageID } + contentID: { eq: $contentID } + } + ) { + nodes { + pageID + pagePath + path + languageCode + contentID + title + } + } + } ` const AgilityPage = ({ pageContext, data }) => { - const viewModel = agilityUtils.buildPageViewModel({ pageContext, data }); - return ( - - - - -
- -
-
- ); + const viewModel = agilityUtils.buildPageViewModel({ pageContext, data }) + return ( + + + + +
+ +
+
+ ) } -export default AgilityPage; - - +export default AgilityPage diff --git a/src/agility/components/StaticMultiLangPreviewPage.js b/src/agility/components/StaticMultiLangPreviewPage.js new file mode 100644 index 0000000..eb934f1 --- /dev/null +++ b/src/agility/components/StaticMultiLangPreviewPage.js @@ -0,0 +1,31 @@ +const StaticMultiLangPreviewPage = ({ pageContext }) => { + if (typeof window !== `undefined`) { + const requestedLangCode = getParameterByName({ + name: "lang", + url: window.location.href, + }) + + const { languages } = pageContext + + languages.map((language) => { + if (language.code === requestedLangCode) { + window.location = `/${language.path}${window.location.pathname}` + return null + } + }) + } + //no render + return null +} + +const getParameterByName = ({ name, url }) => { + if (!url) url = window.location.href + name = name.replace(/[[\]]/g, "\\$&") + var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), + results = regex.exec(url) + if (!results) return null + if (!results[2]) return "" + return decodeURIComponent(results[2].replace(/\+/g, " ")) +} + +export default StaticMultiLangPreviewPage diff --git a/src/agility/utils.js b/src/agility/utils.js index 0126728..3d19619 100644 --- a/src/agility/utils.js +++ b/src/agility/utils.js @@ -1,112 +1,114 @@ - const getDynamicPageItem = ({ contentID, agilityItem }) => { - if (contentID > 0 && agilityItem && agilityItem.itemJson) { - return JSON.parse(agilityItem.itemJson); - } +const getDynamicPageItem = ({ contentID, agilityItem }) => { + if (contentID > 0 && agilityItem && agilityItem.itemJson) { + return JSON.parse(agilityItem.itemJson) + } } -const buildPageViewModel = ( { pageContext, data }) => { - //Check if we have a dynamic page item contentID, if so, we are rendering a dynamic page and should pass the content item to Modules - const dynamicPageItem = getDynamicPageItem({ - contentID: pageContext.contentID, - agilityItem: data.agilityitem - }); +const buildPageViewModel = ({ pageContext, data }) => { + //Check if we have a dynamic page item contentID, if so, we are rendering a dynamic page and should pass the content item to Modules + const dynamicPageItem = getDynamicPageItem({ + contentID: pageContext.contentID, + agilityItem: data.agilityitem, + }) - const page = JSON.parse(data.agilitypage.pageJson); + const page = JSON.parse(data.agilitypage.pageJson) - if(dynamicPageItem) { - //replace the title with the title of the post - page.title = dynamicPageItem.customFields.title; - } + if (dynamicPageItem) { + //replace the title with the title of the post + page.title = dynamicPageItem.customFields.title + } - - //build the our viewModel - return { - page: page, - dynamicPageItem: dynamicPageItem, - isPreview: pageContext.isPreview, - languageCode: pageContext.languageCode, - isMultiLanguage: pageContext.isMultiLanguage - } + //build the our viewModel + return { + page: page, + dynamicPageItem: dynamicPageItem, + isPreview: pageContext.isPreview, + languageCode: pageContext.languageCode, + isMultiLanguage: pageContext.isMultiLanguage, + languages: pageContext.languages, + pagesInOtherLanguages: data.pagesInOtherLanguages, + } } const getLinkedContentItem = ({ type, linkedContentFieldName }) => { - const fieldResolver = - { - //we are telling it is going to return the 'agilityAuthor' node type + const fieldResolver = { + //we are telling it is going to return the 'agilityAuthor' node type + type: type, + //this is the function that is going to resolve it + resolve: async (source, args, context, info) => { + //query the graphql nodes to find the item you want to return + const node = context.nodeModel.runQuery({ + //find the author that matches our ID and language code + query: { + filter: { + contentID: { + eq: source.customFields[linkedContentFieldName].contentid, + }, + languageCode: { eq: source.languageCode }, + }, + }, type: type, - //this is the function that is going to resolve it - resolve: async (source, args, context, info) => { - //query the graphql nodes to find the item you want to return - const node = context.nodeModel.runQuery({ - //find the author that matches our ID and language code - query: { - filter: { - contentID: { eq: source.customFields[linkedContentFieldName].contentid }, - languageCode: { eq: source.languageCode} - } - }, - type: type, - //tell it to stop searching once we found our item - firstOnly: true, - }) - return node; - } - } - return fieldResolver; + //tell it to stop searching once we found our item + firstOnly: true, + }) + return node + }, + } + return fieldResolver } const getLinkedContentList = ({ type, linkedContentFieldName }) => { - const fieldResolver = - { - type: [type], - resolve: (source, args, context, info) => { - const list = context.nodeModel.getAllNodes({ type }); - const filteredList = list.filter( - item => item.properties.referenceName === source.customFields[linkedContentFieldName].referencename - ) - return filteredList; - } - } + const fieldResolver = { + type: [type], + resolve: (source, args, context, info) => { + const list = context.nodeModel.getAllNodes({ type }) + const filteredList = list.filter( + (item) => + item.properties.referenceName === + source.customFields[linkedContentFieldName].referencename + ) + return filteredList + }, + } - return fieldResolver; + return fieldResolver } const getDynamicPageItemSitemapNode = () => { - const fieldResolver = - { - type: 'agilitySitemapNode', - resolve: async (source, args, context, info) => { - const node = context.nodeModel.runQuery({ - query: { - filter: { - contentID: { eq: source.contentID }, - languageCode: { eq: source.languageCode} - } - }, - type: `agilitySitemapNode`, - firstOnly: true - }) - return node; - } - } - - return fieldResolver; + const fieldResolver = { + type: "agilitySitemapNode", + resolve: async (source, args, context, info) => { + const node = context.nodeModel.runQuery({ + query: { + filter: { + contentID: { eq: source.contentID }, + languageCode: { eq: source.languageCode }, + }, + }, + type: `agilitySitemapNode`, + firstOnly: true, + }) + return node + }, + } + + return fieldResolver } const renderHTML = (html) => { - return { __html: cleanHTML(html) }; + return { __html: cleanHTML(html) } } const cleanHTML = (html) => { - //fix '~' in links in HTML - return html.replace(/href="~\//gi, 'href="/') + //fix '~' in links in HTML + return html.replace(/href="~\//gi, 'href="/') } module.exports = { - buildPageViewModel, - getLinkedContentList, - getDynamicPageItemSitemapNode, - getLinkedContentItem, - renderHTML, - cleanHTML -} \ No newline at end of file + buildPageViewModel, + getLinkedContentList, + getDynamicPageItemSitemapNode, + getLinkedContentItem, + renderHTML, + cleanHTML, +} diff --git a/src/components/GlobalHeader.js b/src/components/GlobalHeader.js index 172114f..2e0121d 100644 --- a/src/components/GlobalHeader.js +++ b/src/components/GlobalHeader.js @@ -1,72 +1,91 @@ -import React, { Component } from 'react'; +import React, { Component } from "react" import { Link, graphql, StaticQuery } from "gatsby" -import './GlobalHeader.css' +import "./GlobalHeader.css" -export default props => ( - ( + { + const viewModel = { + languages: props.languages, + pagesInOtherLanguages: props.pagesInOtherLanguages, + item: queryData.agilityGlobalHeader, + menuLinks: queryData.allAgilitySitemapNode.nodes.filter( + (sitemapNode) => { + let isTopLevelPage = sitemapNode.path.split("/").length === 2 + const isThisLanguage = + sitemapNode.languageCode === props.languageCode + if (props.isMultiLanguage) { + isTopLevelPage = sitemapNode.path.split("/").length === 3 } - } - - `} - render={queryData => { - const viewModel = { - item: queryData.agilityGlobalHeader, - menuLinks: queryData.allAgilitySitemapNode.nodes.filter(sitemapNode => { - let isTopLevelPage = sitemapNode.path.split('/').length === 2; - const isThisLanguage = sitemapNode.languageCode === props.languageCode; - if(props.isMultiLanguage) { - isTopLevelPage = sitemapNode.path.split('/').length === 3 - } - //only return nodes from this language and top level links only - return isThisLanguage && isTopLevelPage - }) - } - return ( - - ); - }} - /> + //only return nodes from this language and top level links only + return isThisLanguage && isTopLevelPage + } + ), + } + return + }} + /> ) class GlobalHeader extends Component { - renderLinks = () => { - - let links = []; - this.props.menuLinks.forEach(node => { - links.push(
  • {node.menuText}
  • ) - }) - return links; - } - render() { - - return ( -
    -
    - Home - -
      - {this.renderLinks()} -
    -
    -
    - - ); - } + renderLinks = () => { + let links = [] + this.props.menuLinks.forEach((node) => { + links.push( +
  • + {node.menuText} +
  • + ) + }) + return links + } + render() { + return ( +
    +
    + + Home + + +
      + {this.renderLinks()} + {/* if more than 1 language, render out language toggles */} + {this.props.pagesInOtherLanguages.nodes.length >= 1 + ? this.props.pagesInOtherLanguages.nodes.map((node, i) => { + const languageCode = node.languageCode + const pagePath = node.path + return ( +
    • + + {languageCode} + +
    • + ) + }) + : null} +
    +
    +
    + ) + } } - -