From d335700562f7e5c43d4255f1eecced774f388964 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Wed, 19 Aug 2020 15:11:50 -0400 Subject: [PATCH 01/27] Convert sermons list to table --- package.json | 1 + src/templates/sermons.factory.js | 12 +++---- src/templates/sermons.factory.spec.js | 16 ++++++++++ src/templates/sermons.js | 46 ++++++++++++++++++++++++--- src/templates/sermons.spec.js | 20 +++++++++++- 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index be824666..69b847e1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "gatsby-source-graphql": "^2.6.1", "gatsby-transformer-sharp": "^2.5.7", "lodash": "^4.17.19", + "moment": "^2.27.0", "node-sass": "^4.14.1", "prop-types": "^15.7.2", "react": "^16.12.0", diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index 8e07220e..f129bfb9 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -6,14 +6,9 @@ const _ = require(`lodash`), const query = ` query loadPagesQuery($language: AVORG_Language!, $cursor: String) { avorg { - sermons(language: $language, after: $cursor) { - nodes { - title - } + sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { pageInfo { hasNextPage - hasPreviousPage - startCursor endCursor } aggregate { @@ -39,6 +34,7 @@ const createPagesByLang = async ( const baseUrl = constants.languages[langKey].base_url, nodes = _.get(page, 'nodes'), sermonCount = _.get(page, 'aggregate.count', 0), + cursor = _.get(page, 'pageInfo.endCursor'), pageNumber = i + 1 return createPage({ @@ -49,7 +45,9 @@ const createPagesByLang = async ( pagination: { total: Math.ceil(sermonCount / 10), current: pageNumber - } + }, + language: langKey, + cursor } }) })) diff --git a/src/templates/sermons.factory.spec.js b/src/templates/sermons.factory.spec.js index a1b4db32..4b9158cb 100644 --- a/src/templates/sermons.factory.spec.js +++ b/src/templates/sermons.factory.spec.js @@ -184,4 +184,20 @@ describe("sermons factory", () => { expect(graphql).toBeCalledTimes(10) }) }) + + it("passes language to page", async () => { + const {createPage} = await testCreatePages() + + expect(createPage.mock.calls[0][0].context.language) + .toEqual("ENGLISH") + }) + + it("passes cursor to page", async () => { + const {createPage} = await testCreatePages({ + returnValue: {data:{avorg:{sermons:{pageInfo:{endCursor:"the_cursor"}}}}} + }) + + expect(createPage.mock.calls[0][0].context.cursor) + .toEqual("the_cursor") + }) }) diff --git a/src/templates/sermons.js b/src/templates/sermons.js index dd7fe178..2cbff4c7 100644 --- a/src/templates/sermons.js +++ b/src/templates/sermons.js @@ -2,16 +2,52 @@ import React from "react" import Layout from "../components/layout" import './sermons.scss' import Pagination from "../components/molecules/pagination" +import {graphql} from "gatsby"; +import moment from "moment"; -export default function Sermons({ pageContext }) { - const sermons = pageContext.nodes, +export default function Sermons({pageContext, data}) { + if (!data) { + return

Page query failed

+ } + + console.log(data) + + const sermons = data.avorg.sermons.nodes, {total, current} = pageContext.pagination; return ( - + + {sermons.map((n, i) => + + + + + + )} +
{n.title}{n.title}{n.persons.map(p => p.name).join(', ')}{moment(n.recordingDate).fromNow()}{new Date(1000 * n.duration).toISOString().substr(11, 8)}
- +
) -} \ No newline at end of file +} + +export const query = graphql` + query loadPage($language: AVORG_Language!, $cursor: String) { + avorg { + sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { + nodes { + title + imageWithFallback { + url(size: 50) + } + persons { + name + } + duration + recordingDate + } + } + } + } +` diff --git a/src/templates/sermons.spec.js b/src/templates/sermons.spec.js index fc708e35..33b2bdea 100644 --- a/src/templates/sermons.spec.js +++ b/src/templates/sermons.spec.js @@ -28,6 +28,12 @@ describe("sermons component", () => { current: 1, total: 42 } + }} data={{ + avorg: { + sermons: { + nodes: [] + } + } }} />) expect(getByText('42')).toBeDefined() @@ -40,6 +46,12 @@ describe("sermons component", () => { current: 3, total: 5 } + }} data={{ + avorg: { + sermons: { + nodes: [] + } + } }} />) const listItem = getByText('3').closest('li') @@ -54,8 +66,14 @@ describe("sermons component", () => { current: 3, total: 5 } + }} data={{ + avorg: { + sermons: { + nodes: [] + } + } }} />) expect(getByText('3').href).toContain('/en/sermons/page/3') }) -}) \ No newline at end of file +}) From 89dc68a696665fdfdaa69e534a182ab9e0ac77f9 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Wed, 19 Aug 2020 15:47:37 -0400 Subject: [PATCH 02/27] style sermons table; link titles --- src/common.scss | 13 +++++++------ src/components/layout.scss | 3 +-- src/components/molecules/pagination.scss | 4 ++-- src/templates/sermon.factory.js | 2 +- src/templates/sermons.js | 3 ++- src/templates/sermons.scss | 16 +++++++++++++++- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/common.scss b/src/common.scss index abd20849..fe7041b7 100644 --- a/src/common.scss +++ b/src/common.scss @@ -1,9 +1,10 @@ $gray-night: #1c1c1d; -$gray-dark: #242426; -$gray-mid: #262627; -$gray-light: #747474; -$gray-lighter: #dbdbdb; -$gray-lightest: #e5e5e5; -$gray-bleached: #eee; +$gray-darkest: #242426; +$gray-darker: #262627; +$gray-dark: #747474; +$gray-mid: #dbdbdb; +$gray-light: #e5e5e5; +$gray-lighter: #eee; +$gray-lightest: #f7f7f7; $accent: #3DA88E; diff --git a/src/components/layout.scss b/src/components/layout.scss index f0af6170..140d00aa 100644 --- a/src/components/layout.scss +++ b/src/components/layout.scss @@ -5,7 +5,7 @@ } .organism-header { - background-color: $gray-dark; + background-color: $gray-darkest; } // CSS Reset, Etc: @@ -571,7 +571,6 @@ thead { td, th { text-align: left; - border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); font-feature-settings: "tnum"; -moz-font-feature-settings: "tnum"; -ms-font-feature-settings: "tnum"; diff --git a/src/components/molecules/pagination.scss b/src/components/molecules/pagination.scss index ebb3a4c1..e53d88d3 100644 --- a/src/components/molecules/pagination.scss +++ b/src/components/molecules/pagination.scss @@ -9,7 +9,7 @@ margin-right: .2em; a { - color: $gray-light; + color: $gray-dark; text-decoration: none; display: block; border-radius: 3px; @@ -17,7 +17,7 @@ } &:not(.active) a:hover { - background-color: $gray-bleached; + background-color: $gray-lighter; } } diff --git a/src/templates/sermon.factory.js b/src/templates/sermon.factory.js index a55a5151..436aa74b 100644 --- a/src/templates/sermon.factory.js +++ b/src/templates/sermon.factory.js @@ -6,7 +6,7 @@ const _ = require(`lodash`), const query = ` query loadPagesQuery($language: AVORG_Language!, $cursor: String) { avorg { - sermons(language: $language, first: 50, after: $cursor) { + sermons(language: $language, first: 50, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { nodes { title id diff --git a/src/templates/sermons.js b/src/templates/sermons.js index 2cbff4c7..41b283ee 100644 --- a/src/templates/sermons.js +++ b/src/templates/sermons.js @@ -20,7 +20,7 @@ export default function Sermons({pageContext, data}) { {sermons.map((n, i) => - + @@ -38,6 +38,7 @@ export const query = graphql` sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { nodes { title + id imageWithFallback { url(size: 50) } diff --git a/src/templates/sermons.scss b/src/templates/sermons.scss index ff5d6d26..c1d214bb 100644 --- a/src/templates/sermons.scss +++ b/src/templates/sermons.scss @@ -1,2 +1,16 @@ +@import "../common"; + .template-sermons { -} \ No newline at end of file + img { + border-radius: 100%; + } + tr { + border-top: 2px solid $gray-lightest; + } + tr:nth-child(even) { + background-color: $gray-lightest; + } + td { + padding: .5em; + } +} From 2972893174c1541f18e3f3981e506d12a4c83eb2 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 10:27:42 -0400 Subject: [PATCH 03/27] Add deploy step to ci.yml --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cc9b258..adfa4901 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,4 +29,29 @@ jobs: run: npm ci - name: Run tests run: npm test + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies + run: npm ci + - name: Build site + run: npm run build + - name: Deploy to Netlify + uses: nwtgck/actions-netlify@v1.1 + with: + publish-dir: './public' + production-branch: master + github-token: ${{ secrets.GITHUB_TOKEN }} + deploy-message: "Deploy from GitHub Actions" + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout_minutes: 1 From 0f5250bc1215b88981c518554eaa774655a7a111 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 10:31:27 -0400 Subject: [PATCH 04/27] attempt ci fix --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adfa4901..12d2d177 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,5 +53,5 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout_minutes: 1 + timeout-minutes: 1 From 2e3ba718de3bd56d15e9f3d71f0cc5388e254db5 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 10:32:57 -0400 Subject: [PATCH 05/27] only run ci on push --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12d2d177..74ead593 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ name: CI -on: [push, pull_request] +on: push jobs: audit: runs-on: ubuntu-latest From cf784cf3b6290174b5de3823380f38e860d55253 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 10:50:10 -0400 Subject: [PATCH 06/27] increase deploy timeout; add incremental build caching --- .github/workflows/ci.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74ead593..acca7079 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,12 +33,27 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - name: Cache npm dependencies + uses: actions/cache@v2 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- + - name: Cache Gatsby cache folder + uses: actions/cache@v2 + with: + path: ~/.cache + key: ${{ runner.os }}-cache-gatsby + restore-keys: | + ${{ runner.os }}-cache-gatsby + - name: Cache Gatsby build folder + uses: actions/cache@v2 + with: + path: ~/public + key: ${{ runner.os }}-public-gatsby + restore-keys: | + ${{ runner.os }}-public-gatsby - name: Install dependencies run: npm ci - name: Build site @@ -53,5 +68,5 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 1 + timeout-minutes: 3 From 993f4a1f1edf5bfedc89b0480526a8c81e537a7f Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 11:06:18 -0400 Subject: [PATCH 07/27] remove ci timeout; clean up build logs --- .github/workflows/ci.yml | 1 - package.json | 2 +- src/templates/sermons.js | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acca7079..5a59a5c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,5 +68,4 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 3 diff --git a/package.json b/package.json index 69b847e1..67edf0ad 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ ], "license": "0BSD", "scripts": { - "build": "GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build --log-pages", + "build": "GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build", "develop": "gatsby develop", "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"", "start": "npm run develop", diff --git a/src/templates/sermons.js b/src/templates/sermons.js index 41b283ee..9bdb3e7e 100644 --- a/src/templates/sermons.js +++ b/src/templates/sermons.js @@ -10,8 +10,6 @@ export default function Sermons({pageContext, data}) { return

Page query failed

} - console.log(data) - const sermons = data.avorg.sermons.nodes, {total, current} = pageContext.pagination; From 7265e9c8f2a3ea7087bfe74d0b9ab23981a4eea0 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 13:33:36 -0400 Subject: [PATCH 08/27] replace timeout --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a59a5c3..acca7079 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,4 +68,5 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 3 From 2c4ec941a31e1d8430edc1d397bff47b390a6116 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 20 Aug 2020 16:16:00 -0400 Subject: [PATCH 09/27] Move most of sermon query into template; fix sermon detail image --- src/templates/sermon.factory.js | 14 +----------- src/templates/sermon.factory.spec.js | 16 +++++++------- src/templates/sermon.js | 31 ++++++++++++++++++++++----- src/templates/sermons.factory.js | 2 -- src/templates/sermons.factory.spec.js | 10 --------- 5 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/templates/sermon.factory.js b/src/templates/sermon.factory.js index 436aa74b..4194b4b4 100644 --- a/src/templates/sermon.factory.js +++ b/src/templates/sermon.factory.js @@ -8,19 +8,7 @@ query loadPagesQuery($language: AVORG_Language!, $cursor: String) { avorg { sermons(language: $language, first: 50, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { nodes { - title id - persons { - name - imageWithFallback { - url(size: 50) - } - } - audioFiles { - url - } - recordingDate - description } pageInfo { hasNextPage @@ -47,7 +35,7 @@ const createSermon = async (createPage, node, pathPrefix) => { await createPage({ path: `${pathPrefix}/sermons/${nodeId}`, component: path.resolve(`./src/templates/sermon.js`), - context: {node} + context: {id: nodeId} }) } diff --git a/src/templates/sermon.factory.spec.js b/src/templates/sermon.factory.spec.js index 2fffc43a..455b58a3 100644 --- a/src/templates/sermon.factory.spec.js +++ b/src/templates/sermon.factory.spec.js @@ -40,14 +40,6 @@ describe("sermon factory", () => { expect(createPage.mock.calls[0][0].path).toContain('en/sermons/') }) - it("passes sermon data", async () => { - const {createPage} = await testCreatePages([{ - 'title': 'the_title' - }]) - - expect(createPage.mock.calls[0][0].context.node).toEqual({'title': 'the_title'}) - }) - it("uses sermon id in url", async () => { const {createPage} = await testCreatePages([{id: 3}]) @@ -59,4 +51,12 @@ describe("sermon factory", () => { expect(graphql.mock.calls[0][0]).toContain("loadPagesQuery($language: AVORG_Language!, $cursor: String)") }) + + it("passes id to page", async () => { + const {createPage} = await testCreatePages([{ + 'id': 'the_id' + }]) + + expect(createPage.mock.calls[0][0].context.id).toEqual('the_id') + }) }) diff --git a/src/templates/sermon.js b/src/templates/sermon.js index 14ac669b..a8e4e8be 100644 --- a/src/templates/sermon.js +++ b/src/templates/sermon.js @@ -1,12 +1,12 @@ import React from "react" import Layout from "../components/layout" import './sermon.scss' +import {graphql} from "gatsby"; -export default function Sermon({ pageContext }) { - const sermon = pageContext.node, - firstPresenter = sermon.persons[0], - imageSrc = firstPresenter && firstPresenter.imageWithFallback.url, - imageAlt = firstPresenter && firstPresenter.name; +export default function Sermon({ data }) { + const sermon = data.avorg.sermon, + imageSrc = sermon.imageWithFallback.url, + imageAlt = sermon.title; return ( @@ -34,3 +34,24 @@ export default function Sermon({ pageContext }) { ) } + +export const query = graphql` + query ($id: ID!) { + avorg { + sermon(id: $id) { + title + persons { + name + } + audioFiles { + url + } + recordingDate + description + imageWithFallback { + url(size: 50) + } + } + } + } +` diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index f129bfb9..0f77ad36 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -32,7 +32,6 @@ const createPagesByLang = async ( await Promise.all(pages.map((page, i) => { const baseUrl = constants.languages[langKey].base_url, - nodes = _.get(page, 'nodes'), sermonCount = _.get(page, 'aggregate.count', 0), cursor = _.get(page, 'pageInfo.endCursor'), pageNumber = i + 1 @@ -41,7 +40,6 @@ const createPagesByLang = async ( path: `${baseUrl}/sermons/page/${pageNumber}`, component: path.resolve(`./src/templates/sermons.js`), context: { - nodes, pagination: { total: Math.ceil(sermonCount / 10), current: pageNumber diff --git a/src/templates/sermons.factory.spec.js b/src/templates/sermons.factory.spec.js index 4b9158cb..a44fbb11 100644 --- a/src/templates/sermons.factory.spec.js +++ b/src/templates/sermons.factory.spec.js @@ -72,16 +72,6 @@ describe("sermons factory", () => { }) }) - it("passes sermons to createPage", async () => { - const sermons = ["sermons"], - returnValue = {data:{avorg:{sermons:{nodes:sermons}}}} - - const {createPage} = await testCreatePages({returnValue}) - - expect(createPage.mock.calls[0][0].context.nodes) - .toEqual(sermons) - }) - it("awaits page create", async () => { let done = false; From da3eef1a35d702cdb19c0a05f44efc0be7a9cf86 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 10:47:49 -0400 Subject: [PATCH 10/27] try to debug ci --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acca7079..46f56ac1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,5 +68,6 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + DEBUG: * timeout-minutes: 3 From 485e09b70876c4fb5dbb073a23507237feb052a1 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 10:54:13 -0400 Subject: [PATCH 11/27] try to debug ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46f56ac1..f26c1f8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,6 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - DEBUG: * + DEBUG: "*" timeout-minutes: 3 From 4bd040bc1e6a1af19fdcee42a6eaa87f49c0303a Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 11:43:44 -0400 Subject: [PATCH 12/27] log build stats --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f26c1f8d..5e814277 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,12 @@ jobs: run: npm ci - name: Build site run: npm run build + - name: Finished build stats + run: | + echo "Size of build folder:" + du -hd 0 ./src + echo "Number of files in build folder:" + find ./src -type f | wc -l - name: Deploy to Netlify uses: nwtgck/actions-netlify@v1.1 with: @@ -68,6 +74,5 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - DEBUG: "*" timeout-minutes: 3 From 76b62193a150982e8294a2aa7d77e2792d531911 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 12:07:30 -0400 Subject: [PATCH 13/27] fix build stats --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e814277..791feb83 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,9 +61,9 @@ jobs: - name: Finished build stats run: | echo "Size of build folder:" - du -hd 0 ./src + du -hd 0 ./public echo "Number of files in build folder:" - find ./src -type f | wc -l + find ./public -type f | wc -l - name: Deploy to Netlify uses: nwtgck/actions-netlify@v1.1 with: From 822b5c5205634ae14e998f41aaf519b508c04fc9 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 12:43:15 -0400 Subject: [PATCH 14/27] Attempt deploying compressed build --- .github/workflows/ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 791feb83..5ce82662 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,16 +58,20 @@ jobs: run: npm ci - name: Build site run: npm run build + - name: Compress build + run: zip -r public.zip ./public - name: Finished build stats run: | - echo "Size of build folder:" - du -hd 0 ./public echo "Number of files in build folder:" find ./public -type f | wc -l + echo "Size of build folder:" + du -hd 0 ./public + echo "Size of compressed build:" + du -h ./public.zip - name: Deploy to Netlify uses: nwtgck/actions-netlify@v1.1 with: - publish-dir: './public' + publish-dir: './public.zip' production-branch: master github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: "Deploy from GitHub Actions" From bb13f0a998ae6996cfe78f0276fe6d2fbe97f7e2 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 15:54:20 -0400 Subject: [PATCH 15/27] Try to deploy zip using Neltify API --- .github/workflows/ci.yml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ce82662..0de64238 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,8 +56,8 @@ jobs: ${{ runner.os }}-public-gatsby - name: Install dependencies run: npm ci - - name: Build site - run: npm run build +# - name: Build site +# run: npm run build - name: Compress build run: zip -r public.zip ./public - name: Finished build stats @@ -68,15 +68,21 @@ jobs: du -hd 0 ./public echo "Size of compressed build:" du -h ./public.zip +# - name: Deploy to Netlify +# uses: nwtgck/actions-netlify@v1.1 +# with: +# publish-dir: './public.zip' +# production-branch: master +# github-token: ${{ secrets.GITHUB_TOKEN }} +# deploy-message: "Deploy from GitHub Actions" +# env: +# NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} +# NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} +# timeout-minutes: 3 - name: Deploy to Netlify - uses: nwtgck/actions-netlify@v1.1 - with: - publish-dir: './public.zip' - production-branch: master - github-token: ${{ secrets.GITHUB_TOKEN }} - deploy-message: "Deploy from GitHub Actions" - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 3 + run: | + curl -H "Content-Type: application/zip" \ + -H "Authorization: Bearer ${{ secrets.NETLIFY_AUTH_TOKEN }}" + --data-binary "@public.zip" \ + https://api.netlify.com/api/v1/sites/${{ secrets.NETLIFY_SITE_ID }}/deploys From fae39c01a580c47751e65742671fa96483eada07 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 15:56:41 -0400 Subject: [PATCH 16/27] try to fix caching; re-enable build step --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0de64238..29a85787 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,28 +36,28 @@ jobs: - name: Cache npm dependencies uses: actions/cache@v2 with: - path: ~/.npm + path: ./.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - name: Cache Gatsby cache folder uses: actions/cache@v2 with: - path: ~/.cache + path: ./.cache key: ${{ runner.os }}-cache-gatsby restore-keys: | ${{ runner.os }}-cache-gatsby - name: Cache Gatsby build folder uses: actions/cache@v2 with: - path: ~/public + path: ./public key: ${{ runner.os }}-public-gatsby restore-keys: | ${{ runner.os }}-public-gatsby - name: Install dependencies run: npm ci -# - name: Build site -# run: npm run build + - name: Build site + run: npm run build - name: Compress build run: zip -r public.zip ./public - name: Finished build stats From 7ae3115d05fe107f64b6e72ba4b2471a52b22047 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Mon, 24 Aug 2020 16:21:36 -0400 Subject: [PATCH 17/27] try to fix deploy step --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29a85787..c4553c49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: - name: Deploy to Netlify run: | curl -H "Content-Type: application/zip" \ - -H "Authorization: Bearer ${{ secrets.NETLIFY_AUTH_TOKEN }}" + -H "Authorization: Bearer ${{ secrets.NETLIFY_AUTH_TOKEN }}" \ --data-binary "@public.zip" \ https://api.netlify.com/api/v1/sites/${{ secrets.NETLIFY_SITE_ID }}/deploys From fe97c1e569b307521c355041cfc2fe19ff4cc29a Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Tue, 25 Aug 2020 15:14:48 -0400 Subject: [PATCH 18/27] Delete deploy CI job --- .github/workflows/ci.yml | 56 ---------------------------------------- 1 file changed, 56 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4553c49..2b9d859c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,60 +29,4 @@ jobs: run: npm ci - name: Run tests run: npm test - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Cache npm dependencies - uses: actions/cache@v2 - with: - path: ./.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: Cache Gatsby cache folder - uses: actions/cache@v2 - with: - path: ./.cache - key: ${{ runner.os }}-cache-gatsby - restore-keys: | - ${{ runner.os }}-cache-gatsby - - name: Cache Gatsby build folder - uses: actions/cache@v2 - with: - path: ./public - key: ${{ runner.os }}-public-gatsby - restore-keys: | - ${{ runner.os }}-public-gatsby - - name: Install dependencies - run: npm ci - - name: Build site - run: npm run build - - name: Compress build - run: zip -r public.zip ./public - - name: Finished build stats - run: | - echo "Number of files in build folder:" - find ./public -type f | wc -l - echo "Size of build folder:" - du -hd 0 ./public - echo "Size of compressed build:" - du -h ./public.zip -# - name: Deploy to Netlify -# uses: nwtgck/actions-netlify@v1.1 -# with: -# publish-dir: './public.zip' -# production-branch: master -# github-token: ${{ secrets.GITHUB_TOKEN }} -# deploy-message: "Deploy from GitHub Actions" -# env: -# NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} -# NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} -# timeout-minutes: 3 - - name: Deploy to Netlify - run: | - curl -H "Content-Type: application/zip" \ - -H "Authorization: Bearer ${{ secrets.NETLIFY_AUTH_TOKEN }}" \ - --data-binary "@public.zip" \ - https://api.netlify.com/api/v1/sites/${{ secrets.NETLIFY_SITE_ID }}/deploys From 85ac4f3b3b69905c13a43db6d1e0eea2e69a8839 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Tue, 25 Aug 2020 16:50:25 -0400 Subject: [PATCH 19/27] Put querys back in node, extract path helper --- src/helpers/paths.js | 1 + src/templates/sermon.factory.js | 14 ++++++++++- src/templates/sermon.factory.spec.js | 12 ++++----- src/templates/sermon.js | 26 ++------------------ src/templates/sermons.factory.js | 18 +++++++++++--- src/templates/sermons.factory.spec.js | 19 +++++++-------- src/templates/sermons.js | 35 ++++----------------------- 7 files changed, 51 insertions(+), 74 deletions(-) create mode 100644 src/helpers/paths.js diff --git a/src/helpers/paths.js b/src/helpers/paths.js new file mode 100644 index 00000000..2e835ab9 --- /dev/null +++ b/src/helpers/paths.js @@ -0,0 +1 @@ +export const getSermonPath = (node, languageCode) => `/${languageCode}/sermons/${node.id}` diff --git a/src/templates/sermon.factory.js b/src/templates/sermon.factory.js index 4194b4b4..42d81272 100644 --- a/src/templates/sermon.factory.js +++ b/src/templates/sermon.factory.js @@ -9,6 +9,18 @@ query loadPagesQuery($language: AVORG_Language!, $cursor: String) { sermons(language: $language, first: 50, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { nodes { id + title + persons { + name + } + audioFiles { + url + } + recordingDate + description + imageWithFallback { + url(size: 50) + } } pageInfo { hasNextPage @@ -35,7 +47,7 @@ const createSermon = async (createPage, node, pathPrefix) => { await createPage({ path: `${pathPrefix}/sermons/${nodeId}`, component: path.resolve(`./src/templates/sermon.js`), - context: {id: nodeId} + context: {node} }) } diff --git a/src/templates/sermon.factory.spec.js b/src/templates/sermon.factory.spec.js index 455b58a3..307cdd7d 100644 --- a/src/templates/sermon.factory.spec.js +++ b/src/templates/sermon.factory.spec.js @@ -49,14 +49,14 @@ describe("sermon factory", () => { it("defines query variables", async () => { const {graphql} = await testCreatePages() - expect(graphql.mock.calls[0][0]).toContain("loadPagesQuery($language: AVORG_Language!, $cursor: String)") + expect(graphql.mock.calls[0][0]) + .toContain("loadPagesQuery($language: AVORG_Language!, $cursor: String)") }) - it("passes id to page", async () => { - const {createPage} = await testCreatePages([{ - 'id': 'the_id' - }]) + it("passes node to page", async () => { + const {createPage} = await testCreatePages([{'the':'node'}]) - expect(createPage.mock.calls[0][0].context.id).toEqual('the_id') + expect(createPage.mock.calls[0][0].context.node) + .toStrictEqual({'the':'node'}) }) }) diff --git a/src/templates/sermon.js b/src/templates/sermon.js index a8e4e8be..de025a48 100644 --- a/src/templates/sermon.js +++ b/src/templates/sermon.js @@ -1,10 +1,9 @@ import React from "react" import Layout from "../components/layout" import './sermon.scss' -import {graphql} from "gatsby"; -export default function Sermon({ data }) { - const sermon = data.avorg.sermon, +export default function Sermon({ pageContext }) { + const sermon = pageContext.node, imageSrc = sermon.imageWithFallback.url, imageAlt = sermon.title; @@ -34,24 +33,3 @@ export default function Sermon({ data }) { ) } - -export const query = graphql` - query ($id: ID!) { - avorg { - sermon(id: $id) { - title - persons { - name - } - audioFiles { - url - } - recordingDate - description - imageWithFallback { - url(size: 50) - } - } - } - } -` diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index 0f77ad36..7712ac83 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -7,6 +7,18 @@ const query = ` query loadPagesQuery($language: AVORG_Language!, $cursor: String) { avorg { sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { + nodes { + title + id + imageWithFallback { + url(size: 50) + } + persons { + name + } + duration + recordingDate + } pageInfo { hasNextPage endCursor @@ -33,7 +45,7 @@ const createPagesByLang = async ( await Promise.all(pages.map((page, i) => { const baseUrl = constants.languages[langKey].base_url, sermonCount = _.get(page, 'aggregate.count', 0), - cursor = _.get(page, 'pageInfo.endCursor'), + nodes = _.get(page, 'nodes'), pageNumber = i + 1 return createPage({ @@ -44,8 +56,8 @@ const createPagesByLang = async ( total: Math.ceil(sermonCount / 10), current: pageNumber }, - language: langKey, - cursor + lang: baseUrl, + nodes } }) })) diff --git a/src/templates/sermons.factory.spec.js b/src/templates/sermons.factory.spec.js index a44fbb11..a4c43abe 100644 --- a/src/templates/sermons.factory.spec.js +++ b/src/templates/sermons.factory.spec.js @@ -175,19 +175,18 @@ describe("sermons factory", () => { }) }) - it("passes language to page", async () => { - const {createPage} = await testCreatePages() + it("passes nodes to page", async () => { + const {createPage} = await testCreatePages({ + returnValue: {data:{avorg:{sermons:{nodes:[{'the':'node'}]}}}} + }) - expect(createPage.mock.calls[0][0].context.language) - .toEqual("ENGLISH") + expect(createPage.mock.calls[0][0].context.nodes) + .toStrictEqual([{'the':'node'}]) }) - it("passes cursor to page", async () => { - const {createPage} = await testCreatePages({ - returnValue: {data:{avorg:{sermons:{pageInfo:{endCursor:"the_cursor"}}}}} - }) + it("passes nodes to page", async () => { + const {createPage} = await testCreatePages() - expect(createPage.mock.calls[0][0].context.cursor) - .toEqual("the_cursor") + expect(createPage.mock.calls[0][0].context.lang).toEqual('en') }) }) diff --git a/src/templates/sermons.js b/src/templates/sermons.js index 9bdb3e7e..5ab17775 100644 --- a/src/templates/sermons.js +++ b/src/templates/sermons.js @@ -2,23 +2,19 @@ import React from "react" import Layout from "../components/layout" import './sermons.scss' import Pagination from "../components/molecules/pagination" -import {graphql} from "gatsby"; import moment from "moment"; +import {getSermonPath} from "../helpers/paths"; -export default function Sermons({pageContext, data}) { - if (!data) { - return

Page query failed

- } - - const sermons = data.avorg.sermons.nodes, +export default function Sermons({pageContext}) { + const {nodes, lang} = pageContext, {total, current} = pageContext.pagination; return (
{n.title}{n.title}{n.title} {n.persons.map(p => p.name).join(', ')} {moment(n.recordingDate).fromNow()} {new Date(1000 * n.duration).toISOString().substr(11, 8)}
- {sermons.map((n, i) => + {nodes.map((n, i) => - + @@ -29,24 +25,3 @@ export default function Sermons({pageContext, data}) { ) } - -export const query = graphql` - query loadPage($language: AVORG_Language!, $cursor: String) { - avorg { - sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { - nodes { - title - id - imageWithFallback { - url(size: 50) - } - persons { - name - } - duration - recordingDate - } - } - } - } -` From 299f9f0e209145f9eb4560e6895eca68f4d49b93 Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Wed, 26 Aug 2020 15:59:32 -0400 Subject: [PATCH 20/27] Implement Matthew's parallel strategy --- gatsby-node.js | 6 +- gatsby-node.spec.js | 9 +- src/helpers/queries.js | 38 ++- src/templates/sermon.factory.js | 69 ------ src/templates/sermon.factory.spec.js | 62 ----- .../{sermon.js => sermons.detail.js} | 4 +- .../{sermon.scss => sermons.detail.scss} | 0 src/templates/sermons.factory.js | 86 ++++--- src/templates/sermons.factory.spec.js | 226 +++++++++++++----- src/templates/{sermons.js => sermons.list.js} | 4 +- .../{sermons.scss => sermons.list.scss} | 0 src/templates/sermons.spec.js | 10 +- 12 files changed, 257 insertions(+), 257 deletions(-) delete mode 100644 src/templates/sermon.factory.js delete mode 100644 src/templates/sermon.factory.spec.js rename src/templates/{sermon.js => sermons.detail.js} (93%) rename src/templates/{sermon.scss => sermons.detail.scss} (100%) rename src/templates/{sermons.js => sermons.list.js} (92%) rename src/templates/{sermons.scss => sermons.list.scss} (100%) diff --git a/gatsby-node.js b/gatsby-node.js index ae99dd9a..8495867e 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -4,12 +4,10 @@ * See: https://www.gatsbyjs.org/docs/node-apis/ */ -const sermonFactory = require('./src/templates/sermon.factory.js'), - sermonsFactory = require('./src/templates/sermons.factory.js') +const sermonFactory = require('./src/templates/sermons.factory.js') exports.createPages = async ({graphql, actions}) => { const {createPage} = actions await sermonFactory.createPages(graphql, createPage) - await sermonsFactory.createPages(graphql, createPage) -} \ No newline at end of file +} diff --git a/gatsby-node.spec.js b/gatsby-node.spec.js index 69291a8b..bf2f76de 100644 --- a/gatsby-node.spec.js +++ b/gatsby-node.spec.js @@ -10,10 +10,7 @@ describe("gatsby node", () => { data: { avorg: { sermons: { - nodes: [], - pageInfo: { - hasNextPage: false - } + nodes: [{}] } } } @@ -25,6 +22,6 @@ describe("gatsby node", () => { await createPages(args) - expect(path.resolve).toBeCalledWith(`./src/templates/sermons.js`) + expect(path.resolve).toBeCalledWith(`./src/templates/sermons.list.js`) }) -}) \ No newline at end of file +}) diff --git a/src/helpers/queries.js b/src/helpers/queries.js index c8842307..b8f4db3c 100644 --- a/src/helpers/queries.js +++ b/src/helpers/queries.js @@ -1,30 +1,28 @@ const _ = require(`lodash`), constants = require(`../constants`) -// Must include pageInfo.hasNextPage and pageInfo.endCursor in generated queries -exports.getPages = async (graphql, query, queryArgs, pageSelector, cursor = null, pages = []) => { - queryArgs.cursor = cursor +const NUM_PER_PAGE = 250; - const result = await graphql(query, queryArgs), - page = _.get(result, pageSelector) - - pages.push(page) +exports.NUM_PER_PAGE = NUM_PER_PAGE; - const hasNextPage = _.get(page, 'pageInfo.hasNextPage') && - pages.length < constants.query_page_limit +// Required in query: +// pageInfo.hasNextPage +// pageInfo.endCursor +// aggregate.count +exports.getPages = async (graphql, query, queryArgs, pageSelector) => { + const result = await graphql(query, queryArgs), + page = _.get(result, pageSelector), + pages = [page], + pageCount = Math.ceil(_.get(page, 'aggregate.count') / NUM_PER_PAGE), + maxPage = Math.min(pageCount, constants.query_page_limit) - if (hasNextPage) { - const nextCursor = _.get(page, 'pageInfo.endCursor') + if (!page) return []; + if (!maxPage || maxPage < 1) return pages; - return exports.getPages( - graphql, - query, - queryArgs, - pageSelector, - nextCursor, - pages - ) - } + pages.push(...await Promise.all(_.range(1, maxPage).map(i => graphql(query, { + ...queryArgs, + cursor: Buffer.from(i * NUM_PER_PAGE + 1 + '').toString('base64') + }).then(result => _.get(result, pageSelector))))); return pages } diff --git a/src/templates/sermon.factory.js b/src/templates/sermon.factory.js deleted file mode 100644 index 42d81272..00000000 --- a/src/templates/sermon.factory.js +++ /dev/null @@ -1,69 +0,0 @@ -const _ = require(`lodash`), - path = require(`path`), - constants = require(`../constants.js`), - queries = require(`../helpers/queries`) - -const query = ` -query loadPagesQuery($language: AVORG_Language!, $cursor: String) { - avorg { - sermons(language: $language, first: 50, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { - nodes { - id - title - persons { - name - } - audioFiles { - url - } - recordingDate - description - imageWithFallback { - url(size: 50) - } - } - pageInfo { - hasNextPage - endCursor - } - } - } -}` - -const getSermons = async (graphql, language = "ENGLISH") => { - const pages = await queries.getPages( - graphql, - query, - {language}, - 'data.avorg.sermons' - ) - - return pages.map(p => p.nodes).flat() -} - -const createSermon = async (createPage, node, pathPrefix) => { - const nodeId = _.get(node, 'id') - - await createPage({ - path: `${pathPrefix}/sermons/${nodeId}`, - component: path.resolve(`./src/templates/sermon.js`), - context: {node} - }) -} - -const createLanguageSermons = async (graphql, createPage, pathPrefix, language) => { - const sermons = await getSermons(graphql, language) - - await Promise.all(sermons.map(node => createSermon(createPage, node, pathPrefix))) -} - -exports.createPages = async (graphql, createPage) => { - await Promise.all(Object.keys(constants.languages).map((language) => { - return createLanguageSermons( - graphql, - createPage, - constants.languages[language].base_url, - language - ) - })) -}; diff --git a/src/templates/sermon.factory.spec.js b/src/templates/sermon.factory.spec.js deleted file mode 100644 index 307cdd7d..00000000 --- a/src/templates/sermon.factory.spec.js +++ /dev/null @@ -1,62 +0,0 @@ -import React from "react"; -import {describe, expect, it, jest} from "@jest/globals"; - -const factory = require('./sermon.factory.js') - -const testCreatePages = async (nodes = []) => { - const returnValue = { - data: { - avorg: { - sermons: { - nodes, - pageInfo: { - hasNextPage: false - } - } - } - } - }, - graphql = jest.fn(() => Promise.resolve(returnValue)), - createPage = jest.fn(); - - await factory.createPages(graphql, createPage) - - return {graphql, createPage} -} - -describe("sermon factory", () => { - it("gets English sermons", async () => { - const {graphql} = await testCreatePages() - - expect(graphql.mock.calls[0][1]).toStrictEqual({ - language: 'ENGLISH', - cursor: null - }) - }) - - it("creates English page", async () => { - const {createPage} = await testCreatePages([{}]) - - expect(createPage.mock.calls[0][0].path).toContain('en/sermons/') - }) - - it("uses sermon id in url", async () => { - const {createPage} = await testCreatePages([{id: 3}]) - - expect(createPage.mock.calls[0][0].path).toContain('en/sermons/3') - }) - - it("defines query variables", async () => { - const {graphql} = await testCreatePages() - - expect(graphql.mock.calls[0][0]) - .toContain("loadPagesQuery($language: AVORG_Language!, $cursor: String)") - }) - - it("passes node to page", async () => { - const {createPage} = await testCreatePages([{'the':'node'}]) - - expect(createPage.mock.calls[0][0].context.node) - .toStrictEqual({'the':'node'}) - }) -}) diff --git a/src/templates/sermon.js b/src/templates/sermons.detail.js similarity index 93% rename from src/templates/sermon.js rename to src/templates/sermons.detail.js index de025a48..7e4312c5 100644 --- a/src/templates/sermon.js +++ b/src/templates/sermons.detail.js @@ -1,8 +1,8 @@ import React from "react" import Layout from "../components/layout" -import './sermon.scss' +import './sermons.detail.scss' -export default function Sermon({ pageContext }) { +export default function SermonsDetail({ pageContext }) { const sermon = pageContext.node, imageSrc = sermon.imageWithFallback.url, imageAlt = sermon.title; diff --git a/src/templates/sermon.scss b/src/templates/sermons.detail.scss similarity index 100% rename from src/templates/sermon.scss rename to src/templates/sermons.detail.scss diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index 7712ac83..eb41b4bb 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -4,20 +4,12 @@ const _ = require(`lodash`), queries = require(`../helpers/queries`) const query = ` -query loadPagesQuery($language: AVORG_Language!, $cursor: String) { +query loadPagesQuery($language: AVORG_Language!, $cursor: String, $first: Int!) { avorg { - sermons(language: $language, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { + sermons(language: $language, first: $first, after: $cursor, orderBy: {direction: DESC, field: CREATED_AT}) { nodes { - title - id - imageWithFallback { - url(size: 50) - } - persons { - name - } - duration - recordingDate + ...SermonsFragment + ...SermonFragment } pageInfo { hasNextPage @@ -28,6 +20,33 @@ query loadPagesQuery($language: AVORG_Language!, $cursor: String) { } } } +} +fragment SermonsFragment on AVORG_Recording { + id + title + imageWithFallback { + url(size: 50) + } + persons { + name + } + duration + recordingDate +} +fragment SermonFragment on AVORG_Recording { + id + title + persons { + name + } + audioFiles { + url + } + recordingDate + description + imageWithFallback { + url(size: 50) + } }` const createPagesByLang = async ( @@ -35,36 +54,43 @@ const createPagesByLang = async ( graphql, createPage ) => { - const pages = await queries.getPages( + const queryPages = await queries.getPages( graphql, query, - {language: langKey}, + {language: langKey, first: queries.NUM_PER_PAGE}, 'data.avorg.sermons' - ) + ), + nodes = queryPages.map(p => _.get(p, 'nodes')).flat(), + baseUrl = constants.languages[langKey].base_url, + sermonCount = nodes.length, + pageSize = 10, + pageCount = Math.ceil(sermonCount / pageSize), + pageNumbers = Array.from(Array(pageCount).keys()), + pages = pageNumbers.map(i => nodes.slice(i, i + pageSize)) - await Promise.all(pages.map((page, i) => { - const baseUrl = constants.languages[langKey].base_url, - sermonCount = _.get(page, 'aggregate.count', 0), - nodes = _.get(page, 'nodes'), - pageNumber = i + 1 - - return createPage({ - path: `${baseUrl}/sermons/page/${pageNumber}`, - component: path.resolve(`./src/templates/sermons.js`), + await Promise.all([ + ...pages.map((p, i) => createPage({ + path: `${baseUrl}/sermons/page/${i + 1}`, + component: path.resolve(`./src/templates/sermons.list.js`), context: { pagination: { - total: Math.ceil(sermonCount / 10), - current: pageNumber + total: pageCount, + current: i + 1 }, lang: baseUrl, - nodes + nodes: p } - }) - })) + })), + ...nodes.map(node => createPage({ + path: `${baseUrl}/sermons/${_.get(node, 'id')}`, + component: path.resolve(`./src/templates/sermons.detail.js`), + context: {node} + })) + ]) } exports.createPages = async (graphql, createPage) => { const langKeys = Object.keys(constants.languages) await Promise.all(langKeys.map((key) => createPagesByLang(key, graphql, createPage))) -} +}; diff --git a/src/templates/sermons.factory.spec.js b/src/templates/sermons.factory.spec.js index a4c43abe..2641fb04 100644 --- a/src/templates/sermons.factory.spec.js +++ b/src/templates/sermons.factory.spec.js @@ -1,7 +1,8 @@ import React from "react"; +import {describe, expect, it, jest} from "@jest/globals"; import path from "path" -import _ from "lodash" -import constants from "../constants" +import constants from "../constants"; +import _ from "lodash"; jest.mock(`path`) @@ -20,6 +21,23 @@ const testCreatePages = async ({returnValue, returnValues} = {}) => { return {graphql, createPage} } +const testCreateSermons = async (nodes = []) => { + const returnValue = { + data: { + avorg: { + sermons: { + nodes, + pageInfo: { + hasNextPage: false + } + } + } + } + }; + + return testCreatePages({returnValue}) +} + const runWithMockedConstants = async (modifications, closure) => { const backup = {...constants} @@ -36,7 +54,60 @@ const expectAnyCallToMatch = (mock, callable) => { expect(matches.length).toBeGreaterThan(0) } -describe("sermons factory", () => { +describe("sermon detail pages creation", () => { + it("gets English sermons", async () => { + const {graphql} = await testCreateSermons() + + expect(graphql.mock.calls[0][1]).toStrictEqual({ + language: 'ENGLISH', + first: 250 + }) + }) + + it("creates English page", async () => { + const {createPage} = await testCreateSermons([{}]) + + expect(createPage.mock.calls[0][0].path).toContain('en/sermons/') + }) + + it("uses sermon id in url", async () => { + const {createPage} = await testCreateSermons([{id: 3}]) + + const allPaths = createPage.mock.calls.map(c => _.get(c[0], 'path')) + + expect(allPaths).toContain('en/sermons/3') + }) + + it("defines query variables", async () => { + const {graphql} = await testCreateSermons() + + const allQueries = graphql.mock.calls.map(c => c[0]) + + expect(allQueries).toEqual( + expect.arrayContaining([ + expect.stringContaining( + "language: $language" + ) + ]) + ) + }) + + it("passes node to page", async () => { + const {createPage} = await testCreateSermons([{'the': 'node'}]) + + const candidates = createPage.mock.calls.map(c => _.get(c[0], 'context.node.the')) + + expect(candidates).toContain('node') + }) + + it("gets component", async () => { + await testCreateSermons() + + expect(path.resolve).toBeCalledWith(`./src/templates/sermons.detail.js`) + }) +}) + +describe("sermon list pages creation", () => { it("has factory method", () => { expect(factory.createPages).toBeDefined() }) @@ -44,22 +115,32 @@ describe("sermons factory", () => { it("queries sermons type", async () => { const {graphql} = await testCreatePages() - expect(graphql.mock.calls[0][0]) - .toContain('sermons') + const all_queries = graphql.mock.calls.map(call => call[0]) + + expect(all_queries).toEqual( + expect.arrayContaining([ + expect.stringContaining('sermons') + ]) + ) }) it("creates English page", async () => { - const {createPage} = await testCreatePages() + const {createPage} = await testCreateSermons([{}]) expect(createPage.mock.calls[0][0].path) .toContain('en/sermons') }) it("creates Spanish page", async () => { - const {createPage} = await testCreatePages() + const {createPage} = await testCreateSermons([{}]) - expect(createPage.mock.calls[1][0].path) - .toContain('es/sermons') + const allPaths = createPage.mock.calls.map(c => _.get(c[0], 'path')) + + expect(allPaths).toEqual( + expect.arrayContaining([ + expect.stringContaining('es/sermons') + ]) + ) }) it("gets Spanish sermons", async () => { @@ -68,14 +149,16 @@ describe("sermons factory", () => { expect(graphql.mock.calls[1][1]) .toStrictEqual({ language: 'SPANISH', - cursor: null + first: 250 }) }) it("awaits page create", async () => { let done = false; - const graphql = jest.fn(() => Promise.resolve()), + const returnValue = _.set({}, 'data.avorg.sermons.nodes', [{}]) + + const graphql = jest.fn(() => Promise.resolve(returnValue)), createPage = jest.fn(async () => { await new Promise(r => setTimeout(r, 2)); done = true; @@ -87,85 +170,93 @@ describe("sermons factory", () => { }) it("gets component", async () => { - await testCreatePages() + await testCreateSermons([{},{}]) - expect(path.resolve).toBeCalledWith(`./src/templates/sermons.js`) + expect(path.resolve).toBeCalledWith(`./src/templates/sermons.list.js`) }) it("creates first English page", async () => { - const {createPage} = await testCreatePages({}) + const {createPage} = await testCreateSermons([{}]) - expect(createPage.mock.calls[0][0].path) - .toContain('en/sermons/page/1') + const all_paths = createPage.mock.calls.map(c => c[0].path) + + expect(all_paths).toEqual( + expect.arrayContaining([ + expect.stringContaining('en/sermons/page/1') + ]) + ) }) it("creates second English page", async () => { - const {createPage} = await testCreatePages({ - returnValues: [ - {data:{avorg:{sermons:{pageInfo:{hasNextPage:true}}}}} - ] - }) + const {createPage} = await testCreateSermons((new Array(20)).fill({})) - expectAnyCallToMatch(createPage, call => { - return call[0].path.includes('en/sermons/page/2') - }) + const allPaths = createPage.mock.calls.map(c => _.get(c[0], 'path')) + + expect(allPaths).toEqual( + expect.arrayContaining([ + expect.stringContaining( + 'en/sermons/page/2' + ) + ]) + ) }) it("uses cursors", async () => { const {graphql} = await testCreatePages({ returnValues: [ - {data:{avorg:{sermons:{pageInfo:{ - hasNextPage:true, endCursor:'the_cursor' - }}}}} + { + data: { + avorg: { + sermons: { + pageInfo: { + hasNextPage: true, endCursor: 'the_cursor' + } + } + } + } + } ] }) - expectAnyCallToMatch(graphql, call => { - return call[1].cursor === "the_cursor" - }) + const allCursors = graphql.mock.calls.map(c => _.get(c[1], 'cursor')) + + expect(typeof allCursors[0] === 'string' || allCursors[0] instanceof String) }) it("provides number of pages", async () => { - const {createPage} = await testCreatePages({ - returnValues: [ - {data:{avorg:{sermons:{aggregate:{count:50}}}}} - ] - }) + const {createPage} = await testCreateSermons((new Array(10 * 5)).fill({})) - expectAnyCallToMatch(createPage, call => { - return call[0].context.pagination.total === 5 - }) + const all_totals = createPage.mock.calls.map(c => _.get(c[0], 'context.pagination.total')) + + expect(all_totals).toContain(5) }) it("rounds number of pages up", async () => { - const {createPage} = await testCreatePages({ - returnValues: [ - {data:{avorg:{sermons:{aggregate:{count:55}}}}} - ] - }) + const {createPage} = await testCreateSermons((new Array(10 * 5.5)).fill({})) - expectAnyCallToMatch(createPage, call => { - return call[0].context.pagination.total === 6 - }) + const all_totals = createPage.mock.calls.map(c => _.get(c[0], 'context.pagination.total')) + + expect(all_totals).toContain(6) }) it("includes current page number", async () => { - const {createPage} = await testCreatePages() + const {createPage} = await testCreateSermons([{}]) - expectAnyCallToMatch(createPage, call => { - return call[0].context.pagination.current === 1 - }) + const all_current = createPage.mock.calls.map(c => _.get(c[0], 'context.pagination.current')) + + expect(all_current).toContain(1) }) it("respects dev query limits", async () => { await runWithMockedConstants({ - languages: {'ENGLISH': { base_url: 'en' },}, + languages: {'ENGLISH': {base_url: 'en'},}, query_page_limit: 10 }, async () => { const returnValue = {} _.set(returnValue, 'data.avorg.sermons.pageInfo.hasNextPage', true) _.set(returnValue, 'data.avorg.sermons.pageInfo.endCursor', 'the_cursor') + _.set(returnValue, 'data.avorg.sermons.aggregate.count', 10000) const returnValues = new Array(11).fill(returnValue); @@ -177,16 +268,37 @@ describe("sermons factory", () => { it("passes nodes to page", async () => { const {createPage} = await testCreatePages({ - returnValue: {data:{avorg:{sermons:{nodes:[{'the':'node'}]}}}} + returnValue: {data: {avorg: {sermons: {nodes: [{'the': 'node'}]}}}} }) - expect(createPage.mock.calls[0][0].context.nodes) - .toStrictEqual([{'the':'node'}]) + const all_nodes = createPage.mock.calls.map(call => _.get(call[0], 'context.nodes')) + + expect(all_nodes).toEqual( + expect.arrayContaining([ + expect.arrayContaining([ + expect.objectContaining({ + the: 'node' + }) + ]) + ]) + ) }) - it("passes nodes to page", async () => { - const {createPage} = await testCreatePages() + it("passes lang to page", async () => { + const {createPage} = await testCreateSermons([{}]) + + const all_lang = createPage.mock.calls.map(c => _.get(c[0], 'context.lang')) + + expect(all_lang).toContain('en') + }) + + it("paginates by 10", async () => { + const nodes = (new Array(250)).fill({}) + + const {createPage} = await testCreateSermons(nodes) + + const allNodes = createPage.mock.calls.map(c => _.get(c[0], 'context.nodes')) - expect(createPage.mock.calls[0][0].context.lang).toEqual('en') + expect(allNodes[0].length).toEqual(10) }) }) diff --git a/src/templates/sermons.js b/src/templates/sermons.list.js similarity index 92% rename from src/templates/sermons.js rename to src/templates/sermons.list.js index 5ab17775..d53681e6 100644 --- a/src/templates/sermons.js +++ b/src/templates/sermons.list.js @@ -1,11 +1,11 @@ import React from "react" import Layout from "../components/layout" -import './sermons.scss' +import './sermons.list.scss' import Pagination from "../components/molecules/pagination" import moment from "moment"; import {getSermonPath} from "../helpers/paths"; -export default function Sermons({pageContext}) { +export default function SermonsList({pageContext}) { const {nodes, lang} = pageContext, {total, current} = pageContext.pagination; diff --git a/src/templates/sermons.scss b/src/templates/sermons.list.scss similarity index 100% rename from src/templates/sermons.scss rename to src/templates/sermons.list.scss diff --git a/src/templates/sermons.spec.js b/src/templates/sermons.spec.js index 33b2bdea..90a82694 100644 --- a/src/templates/sermons.spec.js +++ b/src/templates/sermons.spec.js @@ -1,7 +1,7 @@ import {describe, expect, it, jest} from "@jest/globals"; import {render} from "@testing-library/react" import React from "react"; -import Sermons from "./sermons"; +import SermonsList from "./sermons.list"; import Layout from "../components/layout" jest.mock("../components/layout") @@ -10,7 +10,7 @@ Layout.mockImplementation(({children}) => <>{children}) describe("sermons component", () => { it("hides next when unneeded", () => { - const {getByText} = render( { }) it("uses pagination total", () => { - const {getByText} = render( { }) it("highlights active page", () => { - const {getByText} = render( { }) it("links to pages", () => { - const {getByText} = render( Date: Wed, 26 Aug 2020 16:14:05 -0400 Subject: [PATCH 21/27] trigger branch preview From 155da8f3a5fca8127e536f3f8e2110a03a075933 Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Wed, 26 Aug 2020 16:05:52 -0600 Subject: [PATCH 22/27] Trigger build --- src/templates/sermons.factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index eb41b4bb..1019523f 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -42,8 +42,8 @@ fragment SermonFragment on AVORG_Recording { audioFiles { url } - recordingDate description + recordingDate imageWithFallback { url(size: 50) } From 39669d7636d621101457cde65327ec7bffb2eee2 Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Wed, 26 Aug 2020 16:34:02 -0600 Subject: [PATCH 23/27] Test incremental build speed --- src/templates/sermons.factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/sermons.factory.js b/src/templates/sermons.factory.js index 1019523f..0d02ed86 100644 --- a/src/templates/sermons.factory.js +++ b/src/templates/sermons.factory.js @@ -43,10 +43,10 @@ fragment SermonFragment on AVORG_Recording { url } description - recordingDate imageWithFallback { url(size: 50) } + recordingDate }` const createPagesByLang = async ( From 161840d78daaad0e92fc1e11272fd8d53d061936 Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Thu, 27 Aug 2020 10:16:27 -0600 Subject: [PATCH 24/27] Test incremental build speed --- src/pages/page-2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/page-2.js b/src/pages/page-2.js index 666c23ef..3a611cdd 100644 --- a/src/pages/page-2.js +++ b/src/pages/page-2.js @@ -8,7 +8,7 @@ const SecondPage = () => (

Hi from the second page

-

Welcome to page 2

+

Welcome to page two

Go back to the homepage
) From 0a5165c44eed649e9777fe9739246e534356b40b Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Thu, 27 Aug 2020 12:32:11 -0600 Subject: [PATCH 25/27] Test incremental deploy with Gatsby Cloud + Netlify --- src/pages/page-2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/page-2.js b/src/pages/page-2.js index 3a611cdd..666c23ef 100644 --- a/src/pages/page-2.js +++ b/src/pages/page-2.js @@ -8,7 +8,7 @@ const SecondPage = () => (

Hi from the second page

-

Welcome to page two

+

Welcome to page 2

Go back to the homepage
) From 8e1668040b3db5a7f15129b10a1e02ca4b607bb8 Mon Sep 17 00:00:00 2001 From: Matthew Leffler Date: Thu, 27 Aug 2020 13:33:18 -0600 Subject: [PATCH 26/27] Test Gatsby Cloud with S3 --- src/pages/page-2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/page-2.js b/src/pages/page-2.js index 666c23ef..3a611cdd 100644 --- a/src/pages/page-2.js +++ b/src/pages/page-2.js @@ -8,7 +8,7 @@ const SecondPage = () => (

Hi from the second page

-

Welcome to page 2

+

Welcome to page two

Go back to the homepage
) From ecbbd68a9e2220822e23a20746676e329a029a1b Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Thu, 27 Aug 2020 16:24:24 -0400 Subject: [PATCH 27/27] Add gh-pages deploy --- .github/workflows/ci.yml | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b9d859c..f539344d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,4 +29,44 @@ jobs: run: npm ci - name: Run tests run: npm test - + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Cache npm dependencies + uses: actions/cache@v2 + with: + path: ./.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Cache Gatsby cache folder + uses: actions/cache@v2 + with: + path: ./.cache + key: ${{ runner.os }}-cache-gatsby + restore-keys: | + ${{ runner.os }}-cache-gatsby + - name: Cache Gatsby build folder + uses: actions/cache@v2 + with: + path: ./public + key: ${{ runner.os }}-public-gatsby + restore-keys: | + ${{ runner.os }}-public-gatsby + - name: Install dependencies + run: npm ci + - name: Build site + run: npm run build + - name: Finished build stats + run: | + echo "Number of files in build folder:" + find ./public -type f | wc -l + echo "Size of build folder:" + du -hd 0 ./public + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@3.5.9 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: public # The folder the action should deploy.
{n.title}{n.title}{n.title} {n.persons.map(p => p.name).join(', ')} {moment(n.recordingDate).fromNow()} {new Date(1000 * n.duration).toISOString().substr(11, 8)}