diff --git a/.flotiq/.env.dist b/.flotiq/.env.dist new file mode 100644 index 0000000..1f07687 --- /dev/null +++ b/.flotiq/.env.dist @@ -0,0 +1,3 @@ +FLOTIQ_API_KEY= +SCOPED_FLOTIQ_API_KEY=YOUR_SCOPED_FOR_POSTS_SEARCH_FLOTIQ_API_KEY +GA_TRACKING_ID=YOUR_GA_TRACKING_KEY diff --git a/.flotiq/ContentType3/ContentTypeDefinition.json b/.flotiq/ContentType3/ContentTypeDefinition.json index ea92ba6..56ad0c6 100644 --- a/.flotiq/ContentType3/ContentTypeDefinition.json +++ b/.flotiq/ContentType3/ContentTypeDefinition.json @@ -19,7 +19,7 @@ "items": { "$ref": "#/components/schemas/DataSource" }, - "minItems": 0 + "minItems": 1 }, "title": { "type": "string", @@ -30,7 +30,7 @@ "items": { "$ref": "#/components/schemas/DataSource" }, - "minItems": 0 + "minItems": 1 }, "status": { "type": "string", @@ -101,7 +101,9 @@ "status", "excerpt", "metaDescription", - "content" + "content", + "tags", + "author" ], "additionalProperties": false }, @@ -187,7 +189,7 @@ "headerImage": { "label": "Header Image", "unique": false, - "helpText": "", + "helpText": "Recommended size 1920x1080 (16:9)", "inputType": "datasource", "validation": { "relationContenttype": "_media" diff --git a/.flotiq/ContentType5/ContenTypeDefinition.json b/.flotiq/ContentType5/ContentTypeDefinition.json similarity index 99% rename from .flotiq/ContentType5/ContenTypeDefinition.json rename to .flotiq/ContentType5/ContentTypeDefinition.json index 472222b..2783204 100644 --- a/.flotiq/ContentType5/ContenTypeDefinition.json +++ b/.flotiq/ContentType5/ContentTypeDefinition.json @@ -134,4 +134,4 @@ } } } -} +} \ No newline at end of file diff --git a/.flotiq/ContentType6/ContentTypeDefinition.json b/.flotiq/ContentType6/ContentTypeDefinition.json index b1ac8c5..98ded10 100644 --- a/.flotiq/ContentType6/ContentTypeDefinition.json +++ b/.flotiq/ContentType6/ContentTypeDefinition.json @@ -16,6 +16,9 @@ "github_url": { "type": "string" }, + "reddit_url": { + "type": "string" + }, "description": { "type": "string" }, @@ -139,6 +142,7 @@ "twitter_url", "facebook_url", "linkedin_url", + "reddit_url", "privacy_policy_page", "terms_of_service_page", "cookie_policy_page", @@ -165,6 +169,12 @@ "helpText": "", "inputType": "text" }, + "reddit_url": { + "label": "Reddit url", + "unique": false, + "helpText": "", + "inputType": "text" + }, "description": { "label": "Description", "unique": false, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ccfd15..9c84c7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Production +name: Deploy production # Controls when the action will run. Triggers the workflow on push # events but only for the master branch on: @@ -18,27 +18,27 @@ jobs: echo FLOTIQ_BASE_URL=https://api.flotiq.com >> .env.production echo FLOTIQ_API_KEY="$FLOTIQ_API_KEY" >> .env.production echo SCOPED_FLOTIQ_API_KEY="$SCOPED_FLOTIQ_API_KEY" >> .env.production - echo GA_TRACKING_ID="$GA_TRACKING_ID" >> .env.production + echo GA_MEASUREMENT_ID="$GA_MEASUREMENT_ID" >> .env.production shell: bash env: FLOTIQ_API_KEY: ${{ secrets.FLOTIQ_API_KEY }} SCOPED_FLOTIQ_API_KEY: ${{ secrets.SCOPED_FLOTIQ_API_KEY }} - GA_TRACKING_ID: ${{ secrets.GA_TRACKING_ID }} + GA_MEASUREMENT_ID: ${{ secrets.GA_MEASUREMENT_ID }} - uses: actions/setup-node@v1 with: node-version: '14' - - run: npm install + - run: yarn install - name: Gatsby run: | - npm install -g gatsby-cli + npm install -g gatsby-cli@4.25.0 gatsby clean gatsby build --prefix-paths rm -rf public/blog mkdir -p public/blog find public/ -maxdepth 1 -mindepth 1 -not -name blog -exec mv '{}' public/blog/ \; - +# find public/blog -name index.html -exec sed -i 's\window.pagePath="\window.pagePath="/blog\g' {} \; - name: Cloudflare run: | npm install -g @cloudflare/wrangler @@ -53,9 +53,13 @@ jobs: mkdir -p /home/runner/.wrangler/config/ echo api_token = '"'"$API_TOKEN"'"' > /home/runner/.wrangler/config/default.toml cat wrangler.toml + cp worker-index.js workers-site/index.js wrangler publish --env=production + # Refresh sitemap in Google and Bing + curl "https://www.google.com/webmasters/sitemaps/ping?sitemap=https://flotiq.com/blog/sitemap/sitemap-index.xml" + curl "https://www.bing.com/webmaster/ping.aspx?siteMap=https://flotiq.com/blog/sitemap/sitemap-index.xml" shell: bash env: API_TOKEN: ${{ secrets.API_TOKEN }} ACCOUNT_ID: ${{ secrets.ACCOUNT_ID }} - ZONE_ID: ${{ secrets.ZONE_ID }} \ No newline at end of file + ZONE_ID: ${{ secrets.ZONE_ID }} diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index b1b47a9..b3500df 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -1,4 +1,4 @@ -name: Staging +name: Deploy staging # Controls when the action will run. Triggers the workflow on push # events but only for the master branch on: @@ -18,44 +18,47 @@ jobs: echo FLOTIQ_BASE_URL=https://api.flotiq.com >> .env.production echo FLOTIQ_API_KEY="$FLOTIQ_API_KEY" >> .env.production echo SCOPED_FLOTIQ_API_KEY="$SCOPED_FLOTIQ_API_KEY" >> .env.production - echo GA_TRACKING_ID="$GA_TRACKING_ID" >> .env.production + echo GA_MEASUREMENT_ID="$GA_MEASUREMENT_ID" >> .env.production shell: bash env: FLOTIQ_API_KEY: ${{ secrets.FLOTIQ_API_KEY }} SCOPED_FLOTIQ_API_KEY: ${{ secrets.SCOPED_FLOTIQ_API_KEY }} - GA_TRACKING_ID: ${{ secrets.GA_TRACKING_ID }} + GA_MEASUREMENT_ID: ${{ secrets.GA_MEASUREMENT_ID }} - uses: actions/setup-node@v1 with: node-version: '14' - - run: npm install + - run: yarn install - name: Gatsby run: | - npm install -g gatsby-cli + npm install -g gatsby-cli@4.25.0 gatsby clean gatsby build --prefix-paths - rm -rf public/blog - mkdir -p public/blog - find public/ -maxdepth 1 -mindepth 1 -not -name blog -exec mv '{}' public/blog/ \; - + rm -rf public/blog-staging + mkdir -p public/blog-staging + find public/ -maxdepth 1 -mindepth 1 -not -name blog-staging -exec mv '{}' public/blog-staging/ \; - name: Cloudflare run: | npm install -g @cloudflare/wrangler - wrangler init --site flotiq-blog + wrangler init --site flotiq-blog-staging sed -i 's+account_id = '\'\''+account_id = '"'"$ACCOUNT_ID"'"'+g' wrangler.toml sed -i 's+bucket = ""+bucket = "public"+g' wrangler.toml sed -i 's+zone_id = '\'\''+zone_id = '"'"$ZONE_ID"'"'+g' wrangler.toml sed -i 's+workers_dev = true++g' wrangler.toml - echo "[env.staging]" >> wrangler.toml - echo "route = 'staging.flotiq-blog-production.cdwv.workers.dev'" >> wrangler.toml + echo "[env.production]" >> wrangler.toml + echo "route = 'flotiq.com/blog-staging/*'" >> wrangler.toml echo 'zone_id = '"'"$ZONE_ID"'" >> wrangler.toml mkdir -p /home/runner/.wrangler/config/ echo api_token = '"'"$API_TOKEN"'"' > /home/runner/.wrangler/config/default.toml cat wrangler.toml - wrangler publish --env=staging + cp worker-index.js workers-site/index.js + wrangler publish --env=production + # Refresh sitemap in Google and Bing + curl "https://www.google.com/webmasters/sitemaps/ping?sitemap=https://flotiq.com/blog-staging/sitemap/sitemap-index.xml" + curl "https://www.bing.com/webmaster/ping.aspx?siteMap=https://flotiq.com/blog-staging/sitemap/sitemap-index.xml" shell: bash env: API_TOKEN: ${{ secrets.API_TOKEN }} ACCOUNT_ID: ${{ secrets.ACCOUNT_ID }} - ZONE_ID: ${{ secrets.ZONE_ID }} \ No newline at end of file + ZONE_ID: ${{ secrets.ZONE_ID }} diff --git a/README.md b/README.md index ca8a4fe..207edb0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Screenshot ```bash npm install -g flotiq-cli - flotiq start [flotiqApiKey] [projectName] https://github.com/flotiq/flotiq-blog.git + flotiq start [projectName] https://github.com/flotiq/flotiq-blog.git [flotiqApiKey] ``` * `flotiqApKey` - Read and write API key to your Flotiq account * `projectName` - project name or project path (if you wish to start or import data from the current directory - use `.`) @@ -38,7 +38,7 @@ Screenshot If you wish to import example posts, tags and authors to your account, before running `gatsby develop` run: ```sh - flotiq import [flotiqApiKey] . + flotiq import . [flotiqApiKey] ``` It will add 4 images, 1 tag, 1 author and 3 posts to your Flotiq account. @@ -54,7 +54,7 @@ Screenshot ``` FLOTIQ_API_KEY=YOUR FLOTIQ API KEY SCOPED_FLOTIQ_API_KEY=YOUR SCOPED FOR POSTS SEARCH FLOTIQ API KEY - GA_TRACKING_ID=YOUR GA TRACKING KEY + GA_MEASUREMENT_ID=YOUR GA4 MEASUREMENT ID ``` `FLOTIQ_API_KEY` should be the Read-only Application key and `SCOPED_FLOTIQ_API_KEY` should be Scoped User key with read-only access to blog posts, media, tags and authors. @@ -65,7 +65,7 @@ Screenshot ```sh cd flotiq-blog - npm install + yarn install gatsby develop ``` diff --git a/gatsby-browser.js b/gatsby-browser.js index dc2fe44..8baaacd 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -10,3 +10,14 @@ require('@fontsource/inter/latin-ext-500.css'); require('@fontsource/inter/latin-700.css'); require('@fontsource/inter/latin-ext-700.css'); require('./src/style/app.scss'); + +exports.onInitialClientRender = () => { + window.scrollTo(0, 0); +}; + +exports.shouldUpdateScroll = (prevRouterProps, { location }) => { + window.scrollTo(0, 0); + const body = document.getElementsByTagName('body')[0]; + body.scrollTop = 0; + return false; +}; diff --git a/gatsby-config.js b/gatsby-config.js index b38b12e..907e56a 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -15,23 +15,22 @@ module.exports = { plugins: [ 'gatsby-plugin-sass', { - resolve: 'gatsby-plugin-google-analytics', - options: { - trackingId: process.env.GA_TRACKING_ID || '', - // Puts tracking script in the head instead of the body - head: true, - // IP anonymization for GDPR compliance - anonymize: true, - // Disable analytics for users with `Do Not Track` enabled - respectDNT: true, - // Avoids sending pageview hits from custom paths - exclude: ['/preview/**'], - // Specifies what percentage of users should be tracked - sampleRate: 100, - // Determines how often site speed tracking beacons will be sent - siteSpeedSampleRate: 10, - }, - }, + resolve: 'gatsby-plugin-google-gtag', + options: { + trackingIds: [ + process.env.GA_MEASUREMENT_ID, // GA Measurement + ], + gtagConfig: { + optimize_id: 'OPT_CONTAINER_ID', + anonymize_ip: true, + cookie_expires: 0, + }, + pluginConfig: { + head: true, + respectDNT: true, + }, + }, + }, 'gatsby-plugin-react-helmet', 'gatsby-plugin-sitemap', { @@ -40,9 +39,10 @@ module.exports = { authToken: process.env.FLOTIQ_API_KEY, timeout: 30000, downloadMediaFile: true, - forceReload: true, + forceReload: false, includeTypes: [ '_media', + '_tag', 'flotiq_main_settings', 'static_pages', 'flotiqBlogAuthor', diff --git a/gatsby-node.js b/gatsby-node.js index 3b7b193..20dba68 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -6,11 +6,12 @@ exports.createPages = async ({ graphql, actions }) => { const result = await graphql(` query MainQuery { - allFlotiqBlogPost(sort: {fields: publish_date, order: DESC}, limit: 10000) { + allFlotiqBlogPost(sort: {fields: publish_date, order: DESC}, limit: 10000, filter: {status: {eq: "public"}}) { edges { node { id slug + status tags { id tag diff --git a/package.json b/package.json index 0038627..877bf4b 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,10 @@ "@restart/ui": "0.2.3", "babel-eslint": "^10.1.0", "bootstrap": "^4.6.0", + "flotiq-components-react": "^0.4.13", "gatsby": "^4.4.0", "gatsby-plugin-disqus": "^1.2.3", - "gatsby-plugin-google-analytics": "^4.4.0", + "gatsby-plugin-google-gtag": "4", "gatsby-plugin-hotjar": "^1.1.1", "gatsby-plugin-image": "^2.4.0", "gatsby-plugin-manifest": "^4.4.0", @@ -31,7 +32,7 @@ "gatsby-plugin-sharp": "^4.4.0", "gatsby-plugin-sitemap": "^5.4.0", "gatsby-source-filesystem": "^4.4.0", - "gatsby-source-flotiq": "^4.1.3", + "gatsby-source-flotiq": "^4.1.5", "gatsby-transformer-sharp": "^4.4.0", "highlight.js": "^11.3.1", "lodash": "^4.17.21", diff --git a/src/assets/blog-footer-image-mobile.svg b/src/assets/blog-footer-image-mobile.svg new file mode 100644 index 0000000..bd8b24a --- /dev/null +++ b/src/assets/blog-footer-image-mobile.svg @@ -0,0 +1,8445 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/blog-footer-image.svg b/src/assets/blog-footer-image.svg index 86ebc9c..40f0fd0 100644 --- a/src/assets/blog-footer-image.svg +++ b/src/assets/blog-footer-image.svg @@ -1,3613 +1,110 @@ - + + viewBox="0 0 3764.8 768.1" style="enable-background:new 0 0 3764.8 768.1;" xml:space="preserve"> - - - - - - - - - - - - - - - - + + + + + + + + - - +yiijjDLKKKOMMs5D/P9f4Al6uaJHYwAAAABJRU5ErkJggg==" transform="matrix(0.5708 0 0 0.5708 571.2009 0)"> + + + diff --git a/src/assets/register-banner-icon.svg b/src/assets/register-banner-icon.svg new file mode 100644 index 0000000..52c2f65 --- /dev/null +++ b/src/assets/register-banner-icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/Button/Button.js b/src/components/Button/Button.js index fb05c64..7b58945 100644 --- a/src/components/Button/Button.js +++ b/src/components/Button/Button.js @@ -1,5 +1,3 @@ -import './Button.scss'; - import React from 'react'; function Button({ additionalClasses = [], additionalAttributes, children, click }) { diff --git a/src/components/CookieInfo/CookieInfo.js b/src/components/CookieInfo/CookieInfo.js index 11bee37..0abd5aa 100644 --- a/src/components/CookieInfo/CookieInfo.js +++ b/src/components/CookieInfo/CookieInfo.js @@ -1,5 +1,3 @@ -import './CookieInfo.scss'; - import React, { useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; @@ -36,7 +34,7 @@ const CookieInfo = ({ cookieText }) => { /> - ) : '' + ) : null ); }; diff --git a/src/components/DiscoverMoreTopics/DiscoverMoreTopics.js b/src/components/DiscoverMoreTopics/DiscoverMoreTopics.js index 33b8159..1b8e604 100644 --- a/src/components/DiscoverMoreTopics/DiscoverMoreTopics.js +++ b/src/components/DiscoverMoreTopics/DiscoverMoreTopics.js @@ -1,5 +1,3 @@ -import './DiscoverMoreTopics.scss'; - import { Link } from 'gatsby'; import React from 'react'; diff --git a/src/components/FlotiqLinkButton/FlotiqLinkButton.js b/src/components/FlotiqLinkButton/FlotiqLinkButton.js new file mode 100644 index 0000000..ac9869e --- /dev/null +++ b/src/components/FlotiqLinkButton/FlotiqLinkButton.js @@ -0,0 +1,29 @@ +import React from 'react'; +import Button from "../Button/Button"; +import {Nav} from "react-bootstrap"; +import {useCookies} from 'react-cookie'; + +const FlotiqLinkButton = ({additionalClasses = []}) => { + const [cookies] = useCookies(['logged']); + return (<> + {cookies.logged ? ( + + ) : ( + + )} + + ); +} + +export default FlotiqLinkButton; diff --git a/src/components/JoinNewsletter/JoinNewsletter.js b/src/components/JoinNewsletter/JoinNewsletter.js index f6ab8a1..bd5f187 100644 --- a/src/components/JoinNewsletter/JoinNewsletter.js +++ b/src/components/JoinNewsletter/JoinNewsletter.js @@ -1,41 +1,80 @@ -import './JoinNewsletter.scss'; - import React from 'react'; -import { Container } from 'react-bootstrap'; +import { Container, Row } from 'react-bootstrap'; import { useCookies } from 'react-cookie'; import Close from '../../assets/close-black.svg'; const COOKIE_KEY2 = 'fq_join_newsletter_dismiss'; -const JoinNewsletter = () => { +const JoinNewsletter = ({ addMargin = false }) => { const [cookies, setCookie] = useCookies([COOKIE_KEY2]); const isBrowser = () => typeof window !== 'undefined'; + const nextWeek = () => { + const today = new Date(); + return new Date(today.getTime() + (7 * 24 * 60 * 60 * 1000)); + }; const dismiss = () => { - setCookie(COOKIE_KEY2, 1); + setCookie(COOKIE_KEY2, 1, { expires: nextWeek() }); }; const action = 'https://flotiq.us18.list-manage.com/subscribe/post?u=5f7db102d539d8f65a3639f8d&id=da58181767'; return ( - (isBrowser() && cookies && !cookies[COOKIE_KEY2]) - ? ( - -
-
-
-
-

Join our newsletter

+ + { + (isBrowser() && cookies && !cookies[COOKIE_KEY2]) ? ( + +
+ +
+
+

Join our newsletter

+ +
+
+ + + +
-
- - - -
- -
- -
- - ) : null + +
+ + ) : null + } + ); }; diff --git a/src/components/MadeWithFlotiq/MadeWithFlotiq.js b/src/components/MadeWithFlotiq/MadeWithFlotiq.js index 802f583..d82787d 100644 --- a/src/components/MadeWithFlotiq/MadeWithFlotiq.js +++ b/src/components/MadeWithFlotiq/MadeWithFlotiq.js @@ -1,5 +1,3 @@ -import './MadeWithFlotiq.scss'; - import React from 'react'; import Logo from '../../assets/favicons/favicon-16x16.png'; diff --git a/src/components/Navbar/Navbar.js b/src/components/Navbar/Navbar.js index f5b09fa..2b6aa3d 100644 --- a/src/components/Navbar/Navbar.js +++ b/src/components/Navbar/Navbar.js @@ -1,14 +1,12 @@ -import './Navbar.scss'; - import { graphql, useStaticQuery } from 'gatsby'; import React, { useState } from 'react'; import { Container, Nav, Navbar, NavDropdown } from 'react-bootstrap'; - -import Button from '../Button/Button'; +import FlotiqLinkButton from '../FlotiqLinkButton/FlotiqLinkButton'; import Logo from '../../assets/Logo3.svg'; import Logo2 from '../../assets/Logo4.svg'; import Search from '../../assets/search.svg'; +import Button from '../Button/Button'; const CustomNavbar = () => { const [isOpen, setIsOpen] = useState(false); @@ -16,72 +14,106 @@ const CustomNavbar = () => { const [visible, setVisible] = React.useState(false); const data = useStaticQuery(query); return ( - - {visible - && ( + + {visible && (
setVisible(false)} /> )} - {visible - && ( + {visible && (
- {data.allFeatures.nodes.map((feature, index) => (index < 5 ? ( - - - {feature.name} - - {feature.name} - - ) : null))} + {data.allFeatures.nodes.map((feature, index) => + index < 5 ? ( + + + {feature.name} + + {feature.name} + + ) : null + )}
- {data.allFeatures.nodes.map((feature, index) => (index > 4 && index < 10 ? ( - - - {feature.name} - - {feature.name} - - ) : null))} + {data.allFeatures.nodes.map((feature, index) => + index > 4 && index < 10 ? ( + + + {feature.name} + + {feature.name} + + ) : null + )}

Missing a feature?

- + Request new feature
- {data.allFeatures.nodes.map((feature, index) => (index > 9 ? ( - - - {feature.name} - - {feature.name} - - ) : null))} + {data.allFeatures.nodes.map((feature, index) => + index > 9 ? ( + + + {feature.name} + + {feature.name} + + ) : null + )}

Missing a feature?

- + Request new feature
@@ -90,16 +122,20 @@ const CustomNavbar = () => {
)} - Flotiq - Flotiq + Flotiq + Flotiq
- - setIsOpen(!isOpen)} /> + setIsOpen(!isOpen)} + />
- + />
diff --git a/src/components/Pagination/Pagination.js b/src/components/Pagination/Pagination.js index 4cd7697..fb356ce 100644 --- a/src/components/Pagination/Pagination.js +++ b/src/components/Pagination/Pagination.js @@ -1,5 +1,3 @@ -import './Pagination.scss'; - import { graphql, useStaticQuery } from 'gatsby'; import React from 'react'; import { Pagination } from 'react-bootstrap'; diff --git a/src/components/PostCard/PostCard.js b/src/components/PostCard/PostCard.js index 2d20607..fa28822 100644 --- a/src/components/PostCard/PostCard.js +++ b/src/components/PostCard/PostCard.js @@ -1,6 +1,4 @@ -import './PostCard.scss'; - -import { navigate } from 'gatsby'; +import { Link } from 'gatsby'; import { GatsbyImage, getImage } from 'gatsby-plugin-image'; import React from 'react'; @@ -10,40 +8,45 @@ import TagPill from '../TagPill/TagPill'; const PostCard = ({ post, showDescription, additionalClass }) => (
navigate(`/${post.slug}`)} className={`post-card pb-4 ${additionalClass}`} >
- { + + { // eslint-disable-next-line no-nested-ternary - post.headerImage ? ( - post.headerImage[0].extension !== 'svg' - && post.headerImage[0].localFile - && post.headerImage[0].localFile.childImageSharp - ? ( - - ) - : ( - {post.title} - )) : null - } + post.headerImage ? ( + post.headerImage[0].extension !== 'svg' + && post.headerImage[0].localFile + && post.headerImage[0].localFile.childImageSharp + ? ( + + ) + : ( + {post.title} + )) : null + } +
{post.tags && post.tags.map((tag) => ( ))}
-

{post.title}

- {showDescription &&
{post.excerpt}
} + +

{post.title}

+ {showDescription &&
{post.excerpt}
} +
{post.content && typeof post.content === 'object' && ( -

{getReadingTime(post.content.blocks)}

+ +

{getReadingTime(post.content.blocks)}

+ )}
); diff --git a/src/components/RegisterBanner/RegisterBanner.js b/src/components/RegisterBanner/RegisterBanner.js new file mode 100644 index 0000000..6a29c4b --- /dev/null +++ b/src/components/RegisterBanner/RegisterBanner.js @@ -0,0 +1,31 @@ +import React, { useCallback } from 'react'; +import Button from '../Button/Button'; +import registerBannerIcon from '../../assets/register-banner-icon.svg'; + +export const RegisterBanner = () => { + const Url = 'https://editor.flotiq.com'; + + const handleButton = useCallback(() => window.open(Url), [Url]); + + return ( +
+
+
+

Discover how to build

+

Better products with Flotiq

+
+ + +
+ + Flotiq +
+ ); +}; + +export default RegisterBanner; diff --git a/src/components/SharePostButtons/SharePostButtons.js b/src/components/SharePostButtons/SharePostButtons.js index 5f217db..cc8a40b 100644 --- a/src/components/SharePostButtons/SharePostButtons.js +++ b/src/components/SharePostButtons/SharePostButtons.js @@ -1,5 +1,3 @@ -import './SharePostButtons.scss'; - import React, { useEffect, useState } from 'react'; const SharePostButtons = () => { diff --git a/src/components/TagPill/TagPill.js b/src/components/TagPill/TagPill.js index 405e94e..4cc45df 100644 --- a/src/components/TagPill/TagPill.js +++ b/src/components/TagPill/TagPill.js @@ -1,5 +1,3 @@ -import './TagPill.scss'; - import { Link } from 'gatsby'; import React from 'react'; diff --git a/src/helpers/blocksEmbed.js b/src/helpers/blocksEmbed.js new file mode 100644 index 0000000..a75d566 --- /dev/null +++ b/src/helpers/blocksEmbed.js @@ -0,0 +1,32 @@ +import RegisterBanner from '../components/RegisterBanner/RegisterBanner'; +import React from 'react'; + +/** + * object with available shortcodes as keys and their components + * @type {{register_banner: JSX.Element}} + */ +const blocksMap = { + ['register_banner']: , +}; + +/** + * + * @param data array with Flotiq block editor content + * @returns {*} + */ +export const blocksEmbed = (data) => { + for (const property in data) { + Object.keys(blocksMap).map((code) => { + if ( + (data[property].data.text instanceof String || + typeof data[property].data.text === 'string') && + data[property].data.text.indexOf(`[[${code}]]`) > -1 + ) { + data[property].data.text = blocksMap[code]; + } + }); + } + return data; +}; + +export default blocksEmbed; diff --git a/src/helpers/readingTime.js b/src/helpers/readingTime.js index 75a7817..f27b6af 100644 --- a/src/helpers/readingTime.js +++ b/src/helpers/readingTime.js @@ -10,7 +10,11 @@ export const getReadingTime = (content) => { if (block.data.message) { numOfWords += block.data.message.replace(' ', ' ').split(' ').length; } - if (block.data.text) { + if ( + (block.data.text + || block.data.text instanceof String) + && typeof block.data.text === 'string' + ) { numOfWords += block.data.text.replace(' ', ' ').split(' ').length; } if (block.data.title) { @@ -34,7 +38,9 @@ export const getReadingTime = (content) => { if (block.data.content) { block.data.content.forEach((row) => { row.forEach((column) => { - numOfWords += column.replace(' ', ' ').split(' ').length; + if (block.data.title) { + numOfWords += column.replace(' ', ' ').split(' ').length; + } }); }); } diff --git a/src/layouts/layout.js b/src/layouts/layout.js new file mode 100644 index 0000000..2f9c263 --- /dev/null +++ b/src/layouts/layout.js @@ -0,0 +1,39 @@ +import { graphql, useStaticQuery } from 'gatsby'; +import React from 'react'; +import { Helmet } from 'react-helmet'; + +import CookieInfo from '../components/CookieInfo/CookieInfo'; +import MadeWithFlotiq from '../components/MadeWithFlotiq/MadeWithFlotiq'; +import Navbar from '../components/Navbar/Navbar'; +import Footer from '../sections/Footer/Footer'; + +const Layout = ({ children, navbarSettings = {}, mainSettings = {} }) => { + const data = useStaticQuery(query); + return ( +
+ + + + + + + {children} + +
+ +
+ ); +}; + +const query = graphql` + query LayoutQuery { + allFlotiqMainSettings { + nodes { + cookie_policy_popup_text + } + } + }`; + +export default Layout; diff --git a/src/pages/search.js b/src/pages/search.js index 9b0dcba..b1feaf6 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -4,10 +4,10 @@ import React, { useEffect, useState } from 'react'; import { Col, Container, Row } from 'react-bootstrap'; import { Helmet } from 'react-helmet'; -import Navbar from '../components/Navbar/Navbar'; import CookieInfo from '../components/CookieInfo/CookieInfo'; import DiscoverMoreTopics from '../components/DiscoverMoreTopics/DiscoverMoreTopics'; import MadeWithFlotiq from '../components/MadeWithFlotiq/MadeWithFlotiq'; +import Navbar from '../components/Navbar/Navbar'; import PostCard from '../components/PostCard/PostCard'; import Footer from '../sections/Footer/Footer'; diff --git a/src/sections/FlotiqPlatform/FlotiqPlatform.js b/src/sections/FlotiqPlatform/FlotiqPlatform.js index 282328e..b24ecc6 100644 --- a/src/sections/FlotiqPlatform/FlotiqPlatform.js +++ b/src/sections/FlotiqPlatform/FlotiqPlatform.js @@ -1,25 +1,33 @@ -import './FlotiqPlatform.scss'; - import React from 'react'; import { Container } from 'react-bootstrap'; import Image from '../../assets/blog-footer-image.svg'; +import ImageMobile from '../../assets/blog-footer-image-mobile.svg'; import Button from '../../components/Button/Button'; const FlotiqPlatform = () => ( - Flotiq headless CMS platform + Flotiq headless CMS platform + Flotiq headless CMS platform

Enjoy fast and painless content delivery to any channel.

-
+
diff --git a/src/sections/Footer/Footer.js b/src/sections/Footer/Footer.js index ddc0941..00ac6dd 100644 --- a/src/sections/Footer/Footer.js +++ b/src/sections/Footer/Footer.js @@ -1,5 +1,3 @@ -import './Footer.scss'; - import { graphql, useStaticQuery } from 'gatsby'; import React from 'react'; diff --git a/src/sections/TextContent/TextContent.js b/src/sections/TextContent/TextContent.js deleted file mode 100644 index dbc3e55..0000000 --- a/src/sections/TextContent/TextContent.js +++ /dev/null @@ -1,165 +0,0 @@ -import './TextContent.scss'; - -import highlight from 'highlight.js'; -import React, { Fragment, useEffect } from 'react'; -import { Container } from 'react-bootstrap'; - -const Header = ({ block }) => { - switch (block.data.level) { - case 1: - return ( -

- ); - case 2: - return ( -

- ); - case 3: - return ( -

- ); - case 4: - return ( -

- ); - case 5: - return ( -

- ); - case 6: - return ( -
- ); - default: - return null; - } -}; - -const Text = ({ block }) => ( -

-); - -const List = ({ block }) => { - const children = block.items.map((item) => ( - -

  • - {item.items.length > 0 && } - - )); - return block.style === 'ordered' - ?
      {children}
    - :
      {children}
    ; -}; - -const Image = ({ block }) => ( -
    - {block.caption} -

    {block.caption}

    -
    -); - -const Quote = ({ block }) => ( -
    -

    {block.text}

    -

    {block.caption}

    -
    -); - -const YouTubeEmbed = ({ block }) => { - const url = block.url.replace('/watch?v=', '/embed/'); - return ( -