diff --git a/gatsby-config.js b/gatsby-config.js index 03967df9491..dd03da7c1f7 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -71,7 +71,7 @@ module.exports = { ], serialize: ({ site, allSitePage }) => allSitePage.edges.map((edge) => { - const ignore_localized_regex = /careers|besquare|blog/ + const ignore_localized_regex = /careers|besquare|blog|academy/ const path = edge.node.path let priority = 0.7 const languages = Object.keys(language_config) @@ -211,7 +211,7 @@ module.exports = { { resolve: 'gatsby-plugin-page-progress', options: { - includePaths: [{ regex: '^/blog/article/' }], + includePaths: [{ regex: '^/academy/blog/posts/' }], excludePaths: [], height: 4, prependToBody: true, diff --git a/gatsby-node.js b/gatsby-node.js index 18d5df268f2..d0fb5ab91ff 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -103,7 +103,7 @@ exports.onCreatePage = ({ page, actions }) => { const localized_path = is_default ? page.path : `${path}${page.path}` const is_production = process.env.GATSBY_ENV === 'production' const excluded_pages_regex = - /^[a-z-]+\/(careers|endpoint|offline-plugin-app-shell-fallback|besquare|blog)\//g + /^[a-z-]+\/(careers|endpoint|offline-plugin-app-shell-fallback|besquare|blog|academy)\//g if (is_production) { if (path === 'ach') return @@ -252,40 +252,35 @@ exports.onCreateWebpackConfig = ({ actions, getConfig }, { ...options }) => { } // TODO: To be updated to the new shape of the API of the new endpoint -// exports.createPages = async ({ reporter, actions, graphql }) => { -// const { createPage } = actions -// const articleTemplate = path.resolve(__dirname, 'src/templates/article.js') +exports.createPages = async ({ reporter, actions, graphql }) => { + const { createPage } = actions + const articleTemplate = path.resolve(__dirname, 'src/templates/article.js') -// Query our published articles -// const result = await graphql(` -// query MyQuery { -// directus { -// articles(filter: { status: { _eq: "published" } }) { -// article_title -// article_url -// translations { -// article_title -// languages_id -// } -// } -// } -// } -// `) - -// if (result.errors) { -// reporter.panic(result.errors) -// } -// const articles = result.data.directus.articles + // Query our published articles + const result = await graphql(` + query MyQuery { + directus { + blog(filter: { status: { _eq: "published" } }) { + id + slug + } + } + } + `) -// articles.forEach((article) => { -// createPage({ -// path: `/blog/articles/${article.article_url}`, -// component: articleTemplate, -// context: { -// locale: 'en', -// pathname: `/blog/articles/${article.article_url}`, -// slug: article.article_url, -// }, -// }) -// }) -// } + if (result.errors) { + reporter.panic(result.errors) + } + const blog = result.data.directus.blog + blog.forEach((blog_post) => { + createPage({ + path: `/academy/blog/posts/${blog_post.slug}`, + component: articleTemplate, + context: { + locale: 'en', + pathname: `/academy/blog/posts/${blog_post.slug}`, + slug: blog_post.slug, + }, + }) + }) +} diff --git a/src/common/utility.js b/src/common/utility.js index b72b559eb7f..8bf0354ac37 100644 --- a/src/common/utility.js +++ b/src/common/utility.js @@ -244,3 +244,14 @@ export const redirectOpenLiveChatBox = (is_redirect) => { navigate(live_chat_redirection_link, { replace: true }) } } + +export const convertDate = (date) => { + const newdate = new Date(date) + return ( + newdate.toLocaleString('en', { day: 'numeric' }) + + ' ' + + newdate.toLocaleString('en', { month: 'long' }) + + ' ' + + newdate.toLocaleString('en', { year: 'numeric' }) + ) +} diff --git a/src/pages/academy/blog/posts/_style.js b/src/pages/academy/blog/posts/_style.js new file mode 100644 index 00000000000..5af906a8d3c --- /dev/null +++ b/src/pages/academy/blog/posts/_style.js @@ -0,0 +1,329 @@ +import styled from 'styled-components' +import { Box, Flex, Container } from 'components/containers' +import { Text } from 'components/elements' +import device from 'themes/device' + +export const Background = styled.div` + background: var(--color-grey-8); + width: 100%; + height: 100%; + + @media ${device.laptop} { + background-image: linear-gradient(var(--color-grey-8) 84%, var(--color-white) 20%); + } +` +export const HeroContainer = styled(Container)` + height: 566px; + padding: 76px 0 0; + align-items: flex-start; + margin-bottom: 86px; + + @media (max-width: 1300px) { + padding: 76px 16px 0; + } + + @media ${device.laptopM} { + padding-top: 65px; + height: 500px; + margin-bottom: 48px; + } + @media ${device.laptop} { + width: 100%; + max-width: 58.8rem; + height: auto; + margin-bottom: 0; + padding: 36px 16px 0; + flex-direction: column; + } +` +export const HeroLeftWrapper = styled(Box)` + max-width: 384px; + margin-right: 24px; + + @media (max-width: 1300px) { + max-width: 360px; + margin-right: 16px; + } + + @media ${device.laptop} { + max-width: 100%; + margin-right: 0; + } +` +export const HeroRightWrapper = styled.div` + position: relative; + max-width: 792px; + max-height: 532px; + width: 100%; + + @media (max-width: 1300px) { + max-width: 100%; + max-height: 460px; + overflow: hidden; + } +` +export const HeroImageContainer = styled(Box)` + position: absolute; + top: 10%; + right: 0%; + max-height: 532px; + overflow: hidden; + + @media (max-width: 1300px) { + position: relative; + top: unset; + right: unset; + max-height: 460px; + } + + @media ${device.laptop} { + margin: auto; + } + + > img { + max-width: 100%; + height: auto; + } +` +export const InfoText = styled(Text)` + @media ${device.laptop} { + font-size: 12px; + } +` +export const WriterImage = styled.div` + width: 48px; + height: 48px; + border-radius: 50px; + margin-right: 8px; + @media ${device.laptop} { + width: 40px; + height: 40px; + + > img { + max-width: 100%; + height: auto; + } + } +` +export const WrittenbyText = styled(Text)` + @media ${device.laptop} { + font-size: 10px; + } +` +export const BodyContainer = styled(Container)` + align-items: flex-start; + padding: 0 0 40px; + + @media ${device.laptop} { + flex-direction: column; + margin-top: 24px; + max-width: 58.8rem; + } +` +export const LeftBodyContainerWrapper = styled(Flex)` + max-width: 384px; + margin-right: 24px; + justify-content: flex-start; +` +export const RightBodyContainerWrapper = styled(Flex)` + position: relative; + max-width: 792px; + width: 100%; + + @media ${device.laptop} { + margin-top: 40px; + } +` +export const SideBarContainer = styled(Flex)` + max-width: 282px; + + @media ${device.laptop} { + margin: 24px 0 32px; + } +` +export const Tag = styled(Flex)` + height: 22px; + width: auto; + color: var(--color-blue-9); + font-weight: bold; + font-size: 14px; + border-radius: 8px; + background-color: var(--color-blue-10); + padding: 1px 8px 0; + justify-content: center; + align-items: center; + margin-right: 16px; + margin-bottom: 16px; + @media ${device.laptop} { + height: 20px; + margin-right: 8px; + font-size: 12px; + } +` +export const PreviewContainer = styled(Box)` + font-size: 16px; + max-width: 792px; + width: 100%; + padding-bottom: 16px; + + & br { + display: none; + } + & p { + margin-top: 22px; + font-weight: 400; + line-height: 24px; + font-size: 16px; + + :first-child { + margin-top: 0; + } + } + & hr { + margin: 32px 0; + } + & ul { + margin-top: 32px; + list-style-type: disc; + margin-block-start: 10px; + margin-block-end: 10px; + + > li { + margin: 8px 0 0 18px; + padding: 0; + line-height: 24px; + font-size: 16px; + } + } + li > strong { + display: inline-block; + margin: 16px 0 0 8px; + padding: 0; + line-height: 24px; + font-size: 16px; + font-weight: bold; + } + & a { + font-size: 16px; + color: var(--color-red); + text-decoration: none; + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + & img { + max-width: 100%; + height: auto; + display: block; + margin: auto; + margin-top: 16px; + } + & img[width='full'] { + margin-left: calc(50% - 50vw); + margin-right: calc(50% - 50vw); + max-width: 100vw; + } + & h1 { + font-size: 64px; + line-height: 80px; + margin-top: 32px; + font-weight: bold; + } + & h2 { + font-size: 48px; + line-height: 60px; + margin-top: 32px; + font-weight: bold; + } + & h3 { + font-size: 32px; + line-height: 40px; + margin-top: 40px; + font-weight: bold; + + & + p { + margin-top: 8px; + } + } + & h4 { + font-size: 24px; + line-height: 36px; + margin-top: 40px; + font-weight: bold; + + & + p { + margin-top: 8px; + } + } + & h5 { + font-size: 20px; + line-height: 30px; + margin-top: 24px; + font-weight: bold; + } + & h6 { + font-size: 16px; + line-height: 24px; + margin-top: 40px; + font-weight: bold; + } + @media ${device.laptop} { + max-width: none; + + & p { + font-size: 14px; + } + & ul { + > li { + font-size: 14px; + line-height: 20px; + } + } + & h1 { + font-size: 32px; + line-height: 40px; + } + & h2 { + font-size: 28px; + line-height: 34px; + } + & h3 { + font-size: 24px; + line-height: 30px; + + & + p { + margin-top: 8px; + } + } + & h4 { + font-size: 18px; + line-height: 26px; + + & + p { + margin-top: 8px; + } + } + & h5 { + font-size: 16px; + line-height: 24px; + } + & h6 { + font-size: 14px; + line-height: 20px; + } + } +` +export const SocialComponentsWrapper = styled(Flex)` + justify-content: space-between; + border-top: 1px solid var(--color-grey-6); + padding-top: 24px; + margin: 40px 0; +` +export const LeftSocialComponents = styled.div` + width: 10px; +` +export const RightSocialComponents = styled.div` + width: auto; +` diff --git a/src/pages/academy/blog/posts/preview/index.js b/src/pages/academy/blog/posts/preview/index.js new file mode 100644 index 00000000000..9ea40571d71 --- /dev/null +++ b/src/pages/academy/blog/posts/preview/index.js @@ -0,0 +1,311 @@ +import React, { useEffect, useState } from 'react' +import PropTypes from 'prop-types' +import { graphql, useStaticQuery } from 'gatsby' +import { + Background, + HeroContainer, + HeroLeftWrapper, + HeroRightWrapper, + HeroImageContainer, + InfoText, + WriterImage, + WrittenbyText, + BodyContainer, + LeftBodyContainerWrapper, + RightBodyContainerWrapper, + SideBarContainer, + Tag, + PreviewContainer, + SocialComponentsWrapper, + LeftSocialComponents, + RightSocialComponents, +} from '../_style' +import Banner from '../../../../blog/components/_banner' +import SocialSharing from '../../../../blog/_social-sharing' +import { localize, WithIntl } from 'components/localization' +import Layout from 'components/layout/layout' +import { SEO, Show, Box, Flex, SectionContainer } from 'components/containers' +import { Header, QueryImage } from 'components/elements' +import { convertDate, isBrowser } from 'common/utility' + +const query_preview = graphql` + query Preview { + directus { + blog { + id + slug + blog_title + published_date + read_time_in_minutes + blog_post + author { + id + name + image { + id + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + main_image { + id + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + tags { + id + tags_id { + id + tag_name + } + } + footer_banners { + id + cta_url + name + desktop_banner_image { + id + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + mobile_banner_image { + id + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + side_banners { + id + cta_url + name + banner_image { + id + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + } + } + } +` + +const BlogPreview = (props) => { + const data = useStaticQuery(query_preview) + const pathname = props.pageContext.pathname + const [post_data, setPostData] = useState() + const [isMounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + + if (isMounted && isBrowser()) { + const query_string = window.location.search + const url_params = new URLSearchParams(query_string) + const params = url_params.get('id') + const item_data = data.directus.blog.find((items) => { + return items.id == params + }) + setPostData(item_data) + } + }, [isMounted]) + + const footer_banner_data = post_data?.footer_banners + const side_banner_data = post_data?.side_banners + + const side_banner_data_details = { + max_w_value: '328px', + max_w_tablet: '320px', + isExternal: true, + redirectLink: side_banner_data?.cta_url, + imgSrcDesktop: side_banner_data?.banner_image?.imageFile, + } + + const footer_banner_details = { + max_w_value: '792px', + max_w_tablet: '580px', + isExternal: true, + redirectLink: footer_banner_data?.cta_url, + imgSrcDesktop: footer_banner_data?.desktop_banner_image?.imageFile, + imgSrcMobile: footer_banner_data?.mobile_banner_image?.imageFile, + } + + return ( + + + + + + + + + {post_data?.published_date && + localize(convertDate(post_data?.published_date))} + +
+ {post_data?.blog_title} +
+ + {post_data?.read_time_in_minutes && + localize(post_data?.read_time_in_minutes + ' min read')} + + + + + {post_data?.tags.map((tag) => { + return ( + <> + {tag?.tags_id?.id && ( + + {tag?.tags_id?.tag_name} + + )} + + ) + })} + + + + + + {post_data?.author && ( + + <> + {post_data?.author?.image && ( + + + + )} + + + + + {localize('Written by')} + + {localize(post_data?.author?.name)} + + + )} + +
+ + + + + +
+
+ + + + + {post_data?.author && ( + + <> + {post_data?.author?.image && ( + + + + )} + + + + + {localize('Written by')} + + {localize(post_data?.author?.name)} + + + )} + + + + + {post_data?.tags.map((tag) => { + return ( + <> + {tag?.tags_id?.id && ( + + {tag?.tags_id?.tag_name} + + )} + + ) + })} + + {side_banner_data_details && ( + + )} + + + + + + <\/p>/g, '/>'), + }} + /> + + {footer_banner_details && } + + + + + + + + {side_banner_data_details && ( + + + + + + )} + + + +
+
+ ) +} + +BlogPreview.propTypes = { + pageContext: PropTypes.object, +} + +export default WithIntl()(BlogPreview) diff --git a/src/pages/blog/_social-sharing.js b/src/pages/blog/_social-sharing.js index 8ea598568c2..a53988eed8d 100644 --- a/src/pages/blog/_social-sharing.js +++ b/src/pages/blog/_social-sharing.js @@ -1,7 +1,7 @@ import React from 'react' import styled from 'styled-components' import PropTypes from 'prop-types' -import { SectionContainer, Container, Flex } from 'components/containers' +import { Flex } from 'components/containers' import { LocalizedLink } from 'components/localization' import { Header } from 'components/elements/typography' import device from 'themes/device' @@ -31,71 +31,67 @@ const StyledFlex = styled(Flex)` const SocialSharing = ({ pathname }) => { return ( - - - - -
- Share this post -
-
- - - - - - - - - - - - - - - - -
-
-
+ + + +
+ Share this post +
+
+ + + + + + + + + + + + + + + + +
+
) } diff --git a/src/pages/blog/components/_banner.js b/src/pages/blog/components/_banner.js new file mode 100644 index 00000000000..7d3de72d6d7 --- /dev/null +++ b/src/pages/blog/components/_banner.js @@ -0,0 +1,72 @@ +import React from 'react' +import styled from 'styled-components' +import PropTypes from 'prop-types' +import { QueryImage } from 'components/elements' +import { Flex } from 'components/containers' +import { LocalizedLink } from 'components/localization' +import device from 'themes/device' + +const ParentWrapper = styled(Flex)` + max-width: ${(props) => (props.max_w ? props.max_w : '792px')}; + margin: 0 auto; + + @media ${device.tabletS} { + max-width: ${(props) => (props.max_w_tablet ? props.max_w_tablet : '100%')}; + } +` +const DesktopWrapper = styled(Flex)` + @media ${device.tabletS} { + display: none; + } +` +const MobileWrapper = styled.div` + display: none; + + @media ${device.tabletS} { + display: flex; + } +` + +const Banner = ({ detailsObj }) => { + return ( + + + {detailsObj.imgSrcDesktop && !detailsObj.imgSrcMobile && ( + <> + + + )} + {detailsObj.imgSrcDesktop && detailsObj.imgSrcMobile && ( + <> + + + + + + + + )} + + + ) +} + +Banner.propTypes = { + detailsObj: PropTypes.object, +} + +export default Banner diff --git a/src/templates/article.js b/src/templates/article.js index ec901c05515..4a2d7796cc8 100644 --- a/src/templates/article.js +++ b/src/templates/article.js @@ -1,153 +1,294 @@ import React from 'react' import PropTypes from 'prop-types' -import styled from 'styled-components' -// import { graphql } from 'gatsby' -import Layout from 'components/layout/layout' +import { graphql } from 'gatsby' +import { + Background, + HeroContainer, + HeroLeftWrapper, + HeroRightWrapper, + HeroImageContainer, + InfoText, + WriterImage, + WrittenbyText, + BodyContainer, + LeftBodyContainerWrapper, + RightBodyContainerWrapper, + SideBarContainer, + Tag, + PreviewContainer, + SocialComponentsWrapper, + LeftSocialComponents, + RightSocialComponents, +} from '../pages/academy/blog/posts/_style' +import Banner from '../pages/blog/components/_banner' +import SocialSharing from '../pages/blog/_social-sharing' import { localize, WithIntl } from 'components/localization' -import { SEO, SectionContainer, SmallContainer, Flex } from 'components/containers' +import Layout from 'components/layout/layout' +import { SEO, Show, Box, Flex, SectionContainer } from 'components/containers' import { Header, QueryImage } from 'components/elements' +import { convertDate } from 'common/utility' -const PreviewContainer = styled.div` - font-size: 16px; +const ArticlesTemplate = (props) => { + const pathname = props.pageContext.pathname + const post_data = props.data.directus.blog[0] + const footer_banner_data = post_data?.footer_banners + const side_banner_data = post_data?.side_banners + const meta_title = post_data?.meta_title + const meta_description = post_data?.meta_description - & p { - margin-top: 32px; - font-weight: 400; - line-height: 32px; - font-size: 20px; - } - & blockquote { - margin-top: 32px; - border-left: 0.25rem solid #ff1a75; - padding-left: 2rem; - font-style: italic; - line-height: 32px; - } - & hr { - margin: 32px 0; + const side_banner_data_details = { + max_w_value: '328px', + max_w_tablet: '320px', + isExternal: true, + redirectLink: side_banner_data?.cta_url, + imgSrcDesktop: side_banner_data?.banner_image?.imageFile, + imgAltDesktop: side_banner_data?.banner_image?.description, } - & ul { - margin-top: 32px; - list-style-type: disc; - margin-block-start: 1em; - margin-block-end: 1em; - > li { - margin: 10px 0 0 24px; - padding: 0 0 0 6px; - line-height: 32px; - font-size: 20px; - - :first-child { - margin: 0 0 0 24px; - } - } + const footer_banner_details = { + max_w_value: '792px', + max_w_tablet: '580px', + isExternal: true, + redirectLink: footer_banner_data?.cta_url, + imgSrcDesktop: footer_banner_data?.desktop_banner_image?.imageFile, + imgAltDesktop: footer_banner_data?.desktop_banner_image?.description, + imgSrcMobile: footer_banner_data?.mobile_banner_image?.imageFile, + imgAltMobile: footer_banner_data?.mobile_banner_image?.description, } - & a { - font-size: 20px; - color: var(--color-red); - text-decoration: none; - cursor: pointer; - &:hover { - text-decoration: underline; - } - } - & figure { - display: flex; - justify-content: center; - } - & img { - max-width: 100%; - height: auto; - } - & img[width='full'] { - margin-left: calc(50% - 50vw); - margin-right: calc(50% - 50vw); - max-width: 100vw; - } - & video { - width: 100%; - height: auto; - } - & h1 { - font-size: 48px; - line-height: 32px; - margin-top: 32px; - font-weight: bold; - } - & h2 { - font-size: 32px; - line-height: 32px; - margin-top: 32px; - font-weight: bold; - } -` - -const ArticleTemplate = (props) => { - const post_data = props.data.directus.articles[0] - const main_image = post_data?.main_image?.imageFile - const main_video = post_data?.main_video?.imageFile?.publicURL return ( - - {main_image && } - {main_video && ( - - - )} - - -
- {post_data.article_title} -
+ + + + + + + + {post_data?.published_date && + convertDate(post_data?.published_date)} + +
+ {post_data?.blog_title} +
+ + {post_data?.read_time_in_minutes && + localize(post_data?.read_time_in_minutes + ' min read')} + + + + + {post_data?.tags.map((tag) => { + return ( + + {tag.tags_id.tag_name} + + ) + })} + + + + + + {post_data?.author && ( + + <> + {post_data?.author?.image && ( + + + + )} + + + + + {localize('Written by')} + + {localize(post_data?.author?.name)} + + + )} + +
+ + + + + +
+
+ + + + + {post_data?.author && ( + + <> + {post_data?.author?.image && ( + + + + )} + - -
+ + + {localize('Written by')} + + {localize(post_data?.author?.name)} + + + )} + + + + + {post_data?.tags.map((tag) => { + return ( + {tag.tags_id.tag_name} + ) + })} + + {side_banner_data_details && ( + + )} + + + + + + <\/p>/g, '/>'), + }} + /> + + {footer_banner_details && } + + + + + + + + {side_banner_data_details && ( + + + + + + )} + + +
) } -ArticleTemplate.propTypes = { +ArticlesTemplate.propTypes = { data: PropTypes.object, + pageContext: PropTypes.object, } -export default WithIntl()(ArticleTemplate) +export default WithIntl()(ArticlesTemplate) // Query our published articles by slug -// export const query = graphql` -// query MyQuery($slug: String) { -// directus { -// articles(filter: { article_url: { _eq: $slug } }) { -// article_title -// article_tags -// date_created -// featured -// article_body -// main_image { -// id -// imageFile { -// childImageSharp { -// gatsbyImageData -// } -// } -// } -// main_video { -// id -// imageFile { -// id -// publicURL -// } -// } -// } -// } -// } -// ` +export const query = graphql` + query Article($slug: String) { + directus { + blog(filter: { slug: { _eq: $slug } }) { + id + blog_title + meta_title + meta_description + published_date + read_time_in_minutes + blog_post + author { + id + name + image { + id + description + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + main_image { + id + description + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + tags { + id + tags_id { + id + tag_name + } + } + footer_banners { + id + cta_url + name + desktop_banner_image { + id + description + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + mobile_banner_image { + id + description + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + side_banners { + id + cta_url + name + banner_image { + id + description + imageFile { + childImageSharp { + gatsbyImageData + } + } + } + } + } + } + } +`