From 8c38f4c64837dcbc8cfe7c0aa45f66a02f5605e6 Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Tue, 19 Sep 2023 12:19:47 +0300 Subject: [PATCH 1/3] Remove ghostCMS and netlify --- .../codeforafrica-deploy-review-app.yml | 2 - Dockerfile.codeforafrica | 6 +- apps/codeforafrica/src/lib/api.ghost/ghost.js | 9 - apps/codeforafrica/src/lib/api.ghost/index.js | 45 -- apps/codeforafrica/src/lib/api.ghost/posts.js | 147 ---- .../src/lib/api.netlify-cms/getBadges.js | 10 - .../src/lib/api.netlify-cms/getBody.js | 11 - .../lib/api.netlify-cms/getCollectionData.js | 10 - .../src/lib/api.netlify-cms/getContactForm.js | 15 - .../src/lib/api.netlify-cms/getDonors.js | 10 - .../src/lib/api.netlify-cms/getGetInTouch.js | 8 - .../api.netlify-cms/getGuidingPrinciples.js | 9 - .../src/lib/api.netlify-cms/getImpactList.js | 18 - .../src/lib/api.netlify-cms/getJoinUs.js | 10 - .../lib/api.netlify-cms/getNewsAndStories.js | 17 - .../src/lib/api.netlify-cms/getOffices.js | 27 - .../getOurGuidingPrinciples.js | 30 - .../src/lib/api.netlify-cms/getOurImpact.js | 23 - .../src/lib/api.netlify-cms/getOurMission.js | 18 - .../src/lib/api.netlify-cms/getOurOffices.js | 9 - .../api.netlify-cms/getOurOpportunities.js | 12 - .../src/lib/api.netlify-cms/getOurPartners.js | 37 - .../src/lib/api.netlify-cms/getOurProjects.js | 12 - .../src/lib/api.netlify-cms/getOurStories.js | 9 - .../src/lib/api.netlify-cms/getOurTeam.js | 9 - .../src/lib/api.netlify-cms/getPartners.js | 13 - .../src/lib/api.netlify-cms/getProjectTeam.js | 9 - .../src/lib/api.netlify-cms/getProjects.js | 62 -- .../lib/api.netlify-cms/getRelatedProjects.js | 11 - .../src/lib/api.netlify-cms/getTeam.js | 15 - .../src/lib/api.netlify-cms/index.js | 47 -- .../sections/getMeetOurTeam.js | 19 - .../api.netlify-cms/sections/getSettings.js | 9 - .../src/lib/api.netlify-cms/seo.js | 29 - .../src/lib/api.netlify-cms/utils.js | 44 - apps/codeforafrica/src/lib/index.js | 757 ------------------ 36 files changed, 1 insertion(+), 1527 deletions(-) delete mode 100644 apps/codeforafrica/src/lib/api.ghost/ghost.js delete mode 100644 apps/codeforafrica/src/lib/api.ghost/index.js delete mode 100644 apps/codeforafrica/src/lib/api.ghost/posts.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getBadges.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getBody.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getCollectionData.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getContactForm.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getDonors.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getGetInTouch.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getGuidingPrinciples.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getImpactList.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getJoinUs.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getNewsAndStories.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOffices.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurGuidingPrinciples.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurImpact.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurMission.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurOffices.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurOpportunities.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurPartners.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurProjects.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurStories.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getOurTeam.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getPartners.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getProjectTeam.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getProjects.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getRelatedProjects.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/getTeam.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/index.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/sections/getMeetOurTeam.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/sections/getSettings.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/seo.js delete mode 100644 apps/codeforafrica/src/lib/api.netlify-cms/utils.js delete mode 100644 apps/codeforafrica/src/lib/index.js diff --git a/.github/workflows/codeforafrica-deploy-review-app.yml b/.github/workflows/codeforafrica-deploy-review-app.yml index 7eec5f81e..0d2f232e6 100644 --- a/.github/workflows/codeforafrica-deploy-review-app.yml +++ b/.github/workflows/codeforafrica-deploy-review-app.yml @@ -57,8 +57,6 @@ jobs: MONGODB_URL=${{ secrets.CODEFORAFRICA_MONGO_URL }}/${{ env.APP_NAME }} NEXT_PUBLIC_APP_URL=${{ env.NEXT_PUBLIC_APP_URL }} PAYLOAD_SECRET=${{ secrets.CODEFORAFRICA_PAYLOAD_SECRET_KEY }} - GHOST_URL=${{ secrets.GHOST_URL }} - GHOST_API_KEY=${{ secrets.GHOST_API_KEY }} NEXT_PUBLIC_APP_LOGO_URL=${{ secrets.NEXT_PUBLIC_APP_CFA_LOGO_URL }} NEXT_PUBLIC_APP_NAME=${{ secrets.NEXT_PUBLIC_APP_CFA_NAME }} cache-from: type=local,src=/tmp/.buildx-cache diff --git a/Dockerfile.codeforafrica b/Dockerfile.codeforafrica index 0cb590d89..9ae89ad8f 100644 --- a/Dockerfile.codeforafrica +++ b/Dockerfile.codeforafrica @@ -33,9 +33,7 @@ RUN pnpm install --recursive --offline --frozen-lockfile ARG PORT=3000 \ MONGODB_URL \ PAYLOAD_SECRET \ - NEXT_PUBLIC_APP_URL=http://localhost:3000 \ - GHOST_URL \ - GHOST_API_KEY + NEXT_PUBLIC_APP_URL=http://localhost:3000 RUN pnpm build-next --filter=codeforafrica @@ -62,8 +60,6 @@ ENV NODE_ENV=production \ PAYLOAD_CONFIG_PATH=${PAYLOAD_CONFIG_PATH} \ PAYLOAD_SECRET=${PAYLOAD_SECRET} \ MONGODB_URL=${MONGODB_URL} \ - GHOST_URL=${GHOST_URL} \ - GHOST_API_KEY=${GHOST_API_KEY} \ NEXT_PUBLIC_APP_LOGO_URL=${NEXT_PUBLIC_APP_LOGO_URL} \ NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME} \ NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} diff --git a/apps/codeforafrica/src/lib/api.ghost/ghost.js b/apps/codeforafrica/src/lib/api.ghost/ghost.js deleted file mode 100644 index df8241647..000000000 --- a/apps/codeforafrica/src/lib/api.ghost/ghost.js +++ /dev/null @@ -1,9 +0,0 @@ -import GhostContentAPI from "@tryghost/content-api"; - -export default function initializeContentAPI() { - return new GhostContentAPI({ - url: process.env.GHOST_URL, - key: process.env.GHOST_API_KEY, - version: process.env.GHOST_API_VERSION || "v5.0", - }); -} diff --git a/apps/codeforafrica/src/lib/api.ghost/index.js b/apps/codeforafrica/src/lib/api.ghost/index.js deleted file mode 100644 index a5dc694a8..000000000 --- a/apps/codeforafrica/src/lib/api.ghost/index.js +++ /dev/null @@ -1,45 +0,0 @@ -import { getAllPosts, getPost } from "@/codeforafrica/lib/api.ghost/posts"; -import equalsIgnoreCase from "@/codeforafrica/utils/equalsIgnoreCase"; - -export async function getAllOpportunities() { - const allPosts = await getAllPosts(); - return allPosts.filter((post) => - equalsIgnoreCase(post.primaryTag.name, "opportunities"), - ); -} - -export async function getAllOpportunitiesTags() { - const opportunities = await getAllOpportunities(); - const tags = opportunities.flatMap((post) => post.tags); - return ["All", ...new Set(tags)]; -} - -export async function getOpportnity(slug) { - return getPost(slug); -} - -export async function getAllStories() { - const allPosts = await getAllPosts(); - return allPosts.filter((post) => - equalsIgnoreCase(post.primaryTag.name, "stories"), - ); -} - -export async function getAllStoriesTags() { - const stories = await getAllStories(); - const tags = stories.flatMap((post) => post.tags); - return ["All", ...new Set(tags)]; -} - -export async function getStory(slug) { - return getPost(slug); -} - -export async function getRelatedStoriesByTags(tags, story = {}) { - const stories = await getAllStories(); - return stories.filter( - (s) => - s.id !== story.id && - s.tags.some((t) => tags.find((st) => equalsIgnoreCase(t, st))), - ); -} diff --git a/apps/codeforafrica/src/lib/api.ghost/posts.js b/apps/codeforafrica/src/lib/api.ghost/posts.js deleted file mode 100644 index 6f43cde8c..000000000 --- a/apps/codeforafrica/src/lib/api.ghost/posts.js +++ /dev/null @@ -1,147 +0,0 @@ -import { promises as fs } from "fs"; -import { join } from "path"; - -import camelcaseKeys from "camelcase-keys"; - -import initializeContentAPI from "@/codeforafrica/lib/api.ghost/ghost"; -import equalsIgnoreCase from "@/codeforafrica/utils/equalsIgnoreCase"; - -const cacheDir = join(process.cwd(), "public/data"); - -function transformPost(post) { - const { - customExcerpt, - excerpt: originalExcerpt, - featureImage, - featureImageAlt, - featureImageCaption, - metaDescription, - metaTitle, - primaryAuthor, - primaryTag, - publishedAt: publishedAtRaw, - slug, - tags: originalTags, - title, - twitterDescription, - twitterImage, - twitterTitle, - ogDescription, - ogImage, - ogTitle, - updatedAt, - ...other - } = camelcaseKeys(post, { deep: true }); - - const excerpt = customExcerpt || originalExcerpt || null; - const href = `/${primaryTag.slug}/${slug}`; - const publishedAt = new Date(publishedAtRaw).toLocaleDateString("en", { - year: "numeric", - month: "short", - day: "numeric", - }); - const tags = originalTags - .filter((t) => !equalsIgnoreCase(t.name, primaryTag.name)) - .map((tag) => tag.name); - - const seo = { - title: metaTitle || title, - description: metaDescription || excerpt, - openGraph: { - type: "article", - article: { - publishedTime: publishedAtRaw, - modifiedTime: updatedAt, - tags, - }, - }, - twitter: { - handle: primaryAuthor.twitter, - }, - }; - // seo will be merged with individual story page seo. This means "empty" - // values should be excluded. - const computedOgDescription = ogDescription || twitterDescription; - if (computedOgDescription) { - seo.openGraph.description = computedOgDescription; - } - const computedOgTitle = ogTitle || twitterTitle; - if (computedOgTitle) { - seo.openGraph.title = computedOgTitle; - } - const computedOgImage = ogImage || twitterImage || featureImage; - if (computedOgImage) { - seo.openGraph.images = [ - { - url: computedOgImage, - alt: - featureImageAlt || - featureImageCaption || - computedOgTitle || - seo.title, - }, - ]; - } - - return { - excerpt, - featureImage, - href, - primaryTag, - publishedAt, - slug, - tags, - seo, - title, - primaryAuthor, - ...other, - }; -} - -async function cachePosts(posts) { - const cacheFile = join(cacheDir, "posts.json"); - const data = { - date: new Date().toISOString(), - posts, - }; - await fs.writeFile(cacheFile, JSON.stringify(data)); -} - -async function getCachedPosts() { - try { - const cacheFile = join(cacheDir, "posts.json"); - const data = await fs.readFile(cacheFile, "utf8"); - return JSON.parse(data); - } catch (error) { - return null; - } -} - -export async function getAllPosts() { - // Check if we have a cached version of the posts - const cachedPosts = await getCachedPosts(); - if (cachedPosts) { - // check if the cache is older than 5 mins - // is 5 mins a good cache age? - // TODO: make this configurable - const cacheAge = new Date() - new Date(cachedPosts.date); - if (cacheAge < 300000) { - return cachedPosts.posts; - } - } - // If not, fetch from Ghost - const api = initializeContentAPI(); - const posts = await api.posts.browse({ - include: "authors,tags", - limit: "all", - }); - const allPosts = posts.map(transformPost); - // Cache the posts - await cachePosts(allPosts); - return allPosts; -} - -export async function getPost(slug) { - const allPost = await getAllPosts(); - return allPost.find((p) => p.slug === slug); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getBadges.js b/apps/codeforafrica/src/lib/api.netlify-cms/getBadges.js deleted file mode 100644 index 38db75923..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getBadges.js +++ /dev/null @@ -1,10 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const badgesDir = join(process.cwd(), "content/badges"); - -export default function getBadges(fields) { - const badges = getCollectionData(badgesDir, fields); - return badges; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getBody.js b/apps/codeforafrica/src/lib/api.netlify-cms/getBody.js deleted file mode 100644 index 711d77fb2..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getBody.js +++ /dev/null @@ -1,11 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -function getBody(page) { - const { content } = getCollectionBySlug("content/pages", page, [ - "content", - ]).items; - - return { content }; -} - -export default getBody; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getCollectionData.js b/apps/codeforafrica/src/lib/api.netlify-cms/getCollectionData.js deleted file mode 100644 index 554e6301a..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getCollectionData.js +++ /dev/null @@ -1,10 +0,0 @@ -import { getCollectionSlugs, getCollectionBySlug } from "./utils"; - -export default function getCollectionData(collectionDir, fields) { - const slugs = getCollectionSlugs(collectionDir); - const collections = slugs.map((slug) => { - const collection = getCollectionBySlug(collectionDir, slug, fields); - return fields?.length ? collection.items : collection.data; - }); - return collections; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getContactForm.js b/apps/codeforafrica/src/lib/api.netlify-cms/getContactForm.js deleted file mode 100644 index f30853e50..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getContactForm.js +++ /dev/null @@ -1,15 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "contact-form"; - -function getContactForm() { - const contactForm = getCollectionBySlug("content/pages", "contact", [ - FIELD_NAME, - "slug", - ]).items[FIELD_NAME]; - const { "embed-code": embedCode, slug } = contactForm || {}; - - return { embedCode, slug }; -} - -export default getContactForm; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getDonors.js b/apps/codeforafrica/src/lib/api.netlify-cms/getDonors.js deleted file mode 100644 index e9573225c..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getDonors.js +++ /dev/null @@ -1,10 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const donorsDir = join(process.cwd(), "content/donors"); - -export default function getDonors(fields) { - const donors = getCollectionData(donorsDir, fields); - return donors; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getGetInTouch.js b/apps/codeforafrica/src/lib/api.netlify-cms/getGetInTouch.js deleted file mode 100644 index c9fb5a508..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getGetInTouch.js +++ /dev/null @@ -1,8 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "get-in-touch"; - -export default function getGetInTouch() { - return getCollectionBySlug("content/pages", "about", [FIELD_NAME, "slug"]) - .items[FIELD_NAME]; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getGuidingPrinciples.js b/apps/codeforafrica/src/lib/api.netlify-cms/getGuidingPrinciples.js deleted file mode 100644 index 3814964ed..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getGuidingPrinciples.js +++ /dev/null @@ -1,9 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const dir = join(process.cwd(), "content/guiding-principles"); - -export default function getGuidingPrinciples(fields) { - return getCollectionData(dir, fields); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getImpactList.js b/apps/codeforafrica/src/lib/api.netlify-cms/getImpactList.js deleted file mode 100644 index 71b547ebe..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getImpactList.js +++ /dev/null @@ -1,18 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const impactDir = join(process.cwd(), "content/impact"); - -function getImpactList() { - return getCollectionData(impactDir, [ - "id", - "slug", - "title", - "value", - "image", - "content", - ]); -} - -export default getImpactList; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getJoinUs.js b/apps/codeforafrica/src/lib/api.netlify-cms/getJoinUs.js deleted file mode 100644 index fcd77e8a1..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getJoinUs.js +++ /dev/null @@ -1,10 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "join-our-slack"; - -function getJoinUs() { - return getCollectionBySlug("content/pages", "contact", [FIELD_NAME, "slug"]) - .items[FIELD_NAME]; -} - -export default getJoinUs; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getNewsAndStories.js b/apps/codeforafrica/src/lib/api.netlify-cms/getNewsAndStories.js deleted file mode 100644 index 147f6f33a..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getNewsAndStories.js +++ /dev/null @@ -1,17 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "news-stories"; - -function getNewsAndStories(page) { - const { - "articles-count": count, - title, - slug, - } = getCollectionBySlug("content/pages", page, [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; - - return { count, title, slug }; -} - -export default getNewsAndStories; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOffices.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOffices.js deleted file mode 100644 index 3fabd374c..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOffices.js +++ /dev/null @@ -1,27 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const officesDir = join(process.cwd(), "content/offices"); - -export default function getOffices(fields) { - const offices = getCollectionData(officesDir, fields); - return offices.map((office) => { - const lat = office.location.latitude; - const lng = office.location.longitude; - return { - map: { - center: { - lat, - lng, - }, - position: { - lat, - lng, - }, - }, - content: office.content, - title: office.name, - }; - }); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurGuidingPrinciples.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurGuidingPrinciples.js deleted file mode 100644 index c5c6ad594..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurGuidingPrinciples.js +++ /dev/null @@ -1,30 +0,0 @@ -import { join } from "path"; - -import getGuidingPrinciples from "./getGuidingPrinciples"; -import { getCollectionBySlug } from "./utils"; - -const pagesDir = join(process.cwd(), "content/pages"); - -const FIELD_NAME = "guiding-principles"; - -function getOurGuidingPrinciples() { - const { - title, - "guiding-principle-list": principleIds, - slug, - } = getCollectionBySlug(pagesDir, "about", [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; - const allPrinciples = getGuidingPrinciples([ - "id", - "title", - "icon", - "content", - ]); - - const list = - principleIds?.map((id) => allPrinciples.find((p) => p.id === id)) ?? null; - return { title, list, slug }; -} - -export default getOurGuidingPrinciples; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurImpact.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurImpact.js deleted file mode 100644 index ca7c8aca4..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurImpact.js +++ /dev/null @@ -1,23 +0,0 @@ -import { join } from "path"; - -import getImpactList from "./getImpactList"; -import { getCollectionBySlug } from "./utils"; - -const pageDir = join(process.cwd(), "content/pages"); -const FIELD_NAME = "our-impact"; - -export default function geOurImpact(page = "index") { - const { - "our-impact": { - action = null, - "impact-list": impactIds, - title = null, - slug = null, - }, - } = getCollectionBySlug(pageDir, page, [FIELD_NAME, "slug"]).items; - const impact = getImpactList(); - // Need to maintain order of how impact were selected in ourImpact - const list = impactIds?.map((id) => impact.find((i) => i.id === id)) ?? null; - - return { action, list, title, slug }; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurMission.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurMission.js deleted file mode 100644 index 18507a1a8..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurMission.js +++ /dev/null @@ -1,18 +0,0 @@ -import { join } from "path"; - -import { getCollectionBySlug } from "./utils"; - -import marked from "@/codeforafrica/lib/marked"; - -const pagesDir = join(process.cwd(), "content/pages"); -const FIELD_NAME = "our-mission"; - -export default function getOurMission() { - const { "our-mission": ourMission } = getCollectionBySlug(pagesDir, "about", [ - FIELD_NAME, - "slug", - ]).items; - ourMission.description = marked(ourMission.description); - - return ourMission; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurOffices.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurOffices.js deleted file mode 100644 index e9572e71c..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurOffices.js +++ /dev/null @@ -1,9 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "our-offices"; - -export default function getOurOffices(page = "contact") { - return getCollectionBySlug("content/pages", page, [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurOpportunities.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurOpportunities.js deleted file mode 100644 index 756ff319d..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurOpportunities.js +++ /dev/null @@ -1,12 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "opportunities"; - -export default function getOurOpportunities(page = "opportunities") { - const { slug } = getCollectionBySlug("content/pages", page, [ - FIELD_NAME, - "slug", - ]).items[FIELD_NAME]; - - return { slug }; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurPartners.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurPartners.js deleted file mode 100644 index 1fc920666..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurPartners.js +++ /dev/null @@ -1,37 +0,0 @@ -import { join } from "path"; - -import getPartners from "./getPartners"; -import { getCollectionBySlug } from "./utils"; - -import marked from "@/codeforafrica/lib/marked"; - -const pageDir = join(process.cwd(), "content/pages"); -const FIELD_NAME = "our-partners"; - -export default function geOurPartners(page = "index") { - const { - "our-partners": { - slug, - title: originalTitle, - "partners-list": partnersIds, - action = null, - }, - } = getCollectionBySlug(pageDir, page, [FIELD_NAME, "slug"]).items; - const title = marked.parseInline(originalTitle); - const allPartners = getPartners([ - "id", - "slug", - "name", - "content", - "href", - "logo", - "links", - ]); - // Need to maintain order of how partners were selected in ourPartners - const list = - page === "index" - ? partnersIds?.map((id) => allPartners.find((p) => p.id === id)) ?? null - : allPartners; - - return { slug, partners: { title, list, action } }; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurProjects.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurProjects.js deleted file mode 100644 index ccfc31d56..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurProjects.js +++ /dev/null @@ -1,12 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "projects"; - -export default function geOurProjects(page = "index") { - const { slug } = getCollectionBySlug("content/pages", page, [ - FIELD_NAME, - "slug", - ]).items[FIELD_NAME]; - - return { slug }; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurStories.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurStories.js deleted file mode 100644 index 7a14ae72f..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurStories.js +++ /dev/null @@ -1,9 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "stories"; - -export default function getOurStories(page = "stories") { - return getCollectionBySlug("content/pages", page, [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getOurTeam.js b/apps/codeforafrica/src/lib/api.netlify-cms/getOurTeam.js deleted file mode 100644 index 950473562..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getOurTeam.js +++ /dev/null @@ -1,9 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -export default function geOurPartners() { - const { - "our-team": { title, slug }, - } = getCollectionBySlug("content/pages", "about", ["our-team", "slug"]).items; - - return { title, slug }; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getPartners.js b/apps/codeforafrica/src/lib/api.netlify-cms/getPartners.js deleted file mode 100644 index fcebeb226..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getPartners.js +++ /dev/null @@ -1,13 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const partnersDir = join(process.cwd(), "content/partners"); - -export default function getPartners(fields) { - const partners = getCollectionData(partnersDir, fields); - return partners.map(({ slug = null, ...other }) => { - const href = slug ? `/about/partners/${slug}` : null; - return { ...other, slug, href }; - }); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getProjectTeam.js b/apps/codeforafrica/src/lib/api.netlify-cms/getProjectTeam.js deleted file mode 100644 index 7aba99fef..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getProjectTeam.js +++ /dev/null @@ -1,9 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "team"; - -export default function getProjectTeam(page = "our-work-individual") { - return getCollectionBySlug("content/pages", page, [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getProjects.js b/apps/codeforafrica/src/lib/api.netlify-cms/getProjects.js deleted file mode 100644 index e6d72b3ad..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getProjects.js +++ /dev/null @@ -1,62 +0,0 @@ -import { join } from "path"; - -import getBadges from "./getBadges"; -import getDonors from "./getDonors"; -import getPartners from "./getPartners"; -import getTeam from "./getTeam"; -import { getCollectionSlugs, getCollectionBySlug } from "./utils"; - -import marked from "@/codeforafrica/lib/marked"; - -const projectsDir = join(process.cwd(), "content/projects"); - -export default function getProjects(fields) { - const slugs = getCollectionSlugs(projectsDir); - return slugs.map((_slug) => { - const collection = getCollectionBySlug(projectsDir, _slug, fields); - const project = collection.items; - if (project.badges?.length) { - const badges = getBadges(["id", "name", "content", "date"]); - project.badges = project.badges.map((id) => - badges.find((badge) => badge.id === id), - ); - } - if (project.partners?.length) { - const partners = getPartners([ - "id", - "slug", - "name", - "content", - "href", - "logo", - ]); - project.partners = { - title: "Partners", - list: project.partners.map((id) => - partners.find((partner) => partner.id === id), - ), - }; - } - if (project.donors?.length) { - const donors = getDonors(); - project.donors = { - title: "Donors", - list: project.donors.map((id) => - donors.find((donor) => donor.id === id), - ), - }; - } - - if (project.team?.length) { - const team = getTeam(); - project.team = { - title: "Team", - list: project.team.map((id) => team.find((m) => m.id === id)), - }; - } - - project.subtitle = marked(project.subtitle); - project.href = `/projects/${project.slug}`; - return project; - }); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getRelatedProjects.js b/apps/codeforafrica/src/lib/api.netlify-cms/getRelatedProjects.js deleted file mode 100644 index 9a6cffb57..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getRelatedProjects.js +++ /dev/null @@ -1,11 +0,0 @@ -import { getCollectionBySlug } from "./utils"; - -const FIELD_NAME = "related-projects"; - -function getRelatedProjects(page) { - return getCollectionBySlug("content/pages", page, [FIELD_NAME, "slug"]).items[ - FIELD_NAME - ]; -} - -export default getRelatedProjects; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/getTeam.js b/apps/codeforafrica/src/lib/api.netlify-cms/getTeam.js deleted file mode 100644 index 2f9f8672e..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/getTeam.js +++ /dev/null @@ -1,15 +0,0 @@ -import { join } from "path"; - -import getCollectionData from "./getCollectionData"; - -const teamDir = join(process.cwd(), "content/team"); - -export default function getTeam(fields) { - const teams = getCollectionData(teamDir, fields); - return teams - .filter((member) => !member.deactivated) - .map(({ slug = null, ...other }) => { - const href = slug ? `/about/members/${slug}` : null; - return { ...other, slug, href }; - }); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/index.js b/apps/codeforafrica/src/lib/api.netlify-cms/index.js deleted file mode 100644 index 0a8fc7a61..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/index.js +++ /dev/null @@ -1,47 +0,0 @@ -import getBody from "./getBody"; -import getContactForm from "./getContactForm"; -import getGetInTouch from "./getGetInTouch"; -import getJoinUs from "./getJoinUs"; -import getNewsAndStories from "./getNewsAndStories"; -import getOffices from "./getOffices"; -import getOurGuidingPrinciples from "./getOurGuidingPrinciples"; -import getOurImpact from "./getOurImpact"; -import getOurMission from "./getOurMission"; -import getOurOffices from "./getOurOffices"; -import getOurOpportunities from "./getOurOpportunities"; -import getOurPartners from "./getOurPartners"; -import getOurProjects from "./getOurProjects"; -import getOurStories from "./getOurStories"; -import getOurTeam from "./getOurTeam"; -import getPartners from "./getPartners"; -import getCmsProjects from "./getProjects"; -import getProjectTeam from "./getProjectTeam"; -import getRelatedProjects from "./getRelatedProjects"; -import getTeam from "./getTeam"; -import getMeetOurTeam from "./sections/getMeetOurTeam"; -import getSeo from "./seo"; - -export { - getBody, - getContactForm, - getCmsProjects, - getGetInTouch, - getJoinUs, - getMeetOurTeam, - getNewsAndStories, - getOffices, - getOurGuidingPrinciples, - getOurImpact, - getOurMission, - getOurOffices, - getOurOpportunities, - getOurPartners, - getOurProjects, - getOurStories, - getSeo, - getRelatedProjects, - getOurTeam, - getPartners, - getProjectTeam, - getTeam, -}; diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/sections/getMeetOurTeam.js b/apps/codeforafrica/src/lib/api.netlify-cms/sections/getMeetOurTeam.js deleted file mode 100644 index 63ea47092..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/sections/getMeetOurTeam.js +++ /dev/null @@ -1,19 +0,0 @@ -import { join } from "path"; - -import { getCollectionBySlug } from "../utils"; - -import marked from "@/codeforafrica/lib/marked"; - -const indexPageDir = join(process.cwd(), "content/pages"); - -export default function getMeetOurTeam( - page = "index", - fields = ["meet-our-team", "slug"], -) { - const meetOurTeam = getCollectionBySlug(indexPageDir, page, fields).items[ - "meet-our-team" - ]; - meetOurTeam.logo = meetOurTeam.image?.src; - meetOurTeam.description = marked(meetOurTeam.description); - return meetOurTeam; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/sections/getSettings.js b/apps/codeforafrica/src/lib/api.netlify-cms/sections/getSettings.js deleted file mode 100644 index dc11d88b5..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/sections/getSettings.js +++ /dev/null @@ -1,9 +0,0 @@ -import { join } from "path"; - -import { getCollectionBySlug } from "../utils"; - -const settingsPageDir = join(process.cwd(), "content/settings"); - -export default function getSettings(section) { - return getCollectionBySlug(settingsPageDir, section).data; -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/seo.js b/apps/codeforafrica/src/lib/api.netlify-cms/seo.js deleted file mode 100644 index f5d91c099..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/seo.js +++ /dev/null @@ -1,29 +0,0 @@ -import { deepmerge } from "@mui/utils"; -import camelcaseKeys from "camelcase-keys"; - -import getSettings from "./sections/getSettings"; -import { getCollectionBySlug } from "./utils"; - -// 1. Since getCollectionBySlug creates a new object on every call, -// we don't need to clone when deep-merging. -// -// 2. If we have meta (at site or page seo level), it's title and description -// should override that level's title and description. - -function createSeo(pageSeo) { - const { - seo: { meta, ...siteSeo }, - site: { title, description }, - } = getSettings("general"); - - const seo = deepmerge(siteSeo, { title, description, ...meta, ...pageSeo }); - return camelcaseKeys(seo); -} - -export default function getSeo(page, pageSeo) { - const { - seo: { meta, ...seo }, - } = getCollectionBySlug("content/pages", page, ["seo"]).items; - - return createSeo(deepmerge({ ...seo, ...meta }, pageSeo)); -} diff --git a/apps/codeforafrica/src/lib/api.netlify-cms/utils.js b/apps/codeforafrica/src/lib/api.netlify-cms/utils.js deleted file mode 100644 index 490ba3cda..000000000 --- a/apps/codeforafrica/src/lib/api.netlify-cms/utils.js +++ /dev/null @@ -1,44 +0,0 @@ -import fs from "fs"; -import { join } from "path"; - -import matter from "gray-matter"; - -import marked from "@/codeforafrica/lib/marked"; - -export function getCollectionSlugs(collectionDir) { - return fs.readdirSync(collectionDir); -} - -export function getCollectionBySlug(collectionDir, slug, fields) { - const realSlug = slug.replace(/\.md$/, ""); - const fullPath = join(collectionDir, `${realSlug}.md`); - const fileContents = fs.readFileSync(fullPath, "utf8"); - const { data, content } = matter(fileContents); - - const markedContent = marked(content); - - data.slug = realSlug; - data.content = markedContent; - - const items = fields?.reduce((acc, curr) => { - if (curr === "content") { - acc.content = markedContent; - } else if (curr === "slug") { - acc.slug = realSlug; - } else { - // The slug field above works for folder-based collections e.g. impact - // but not for file-based collections e.g. get-in-touch in about. - // Since field names are guaranteed to be unique (in page) and are set - // in config, we can set the slug to be field name in file-based - // collections - let currData = data[curr] || null; - if (currData?.constructor === Object && fields.includes("slug")) { - currData = { slug: curr, ...currData }; - } - acc[curr] = currData; - } - return acc; - }, {}); - - return { items, data }; // return data which can be used as default incase of no fields -} diff --git a/apps/codeforafrica/src/lib/index.js b/apps/codeforafrica/src/lib/index.js deleted file mode 100644 index e61fdec30..000000000 --- a/apps/codeforafrica/src/lib/index.js +++ /dev/null @@ -1,757 +0,0 @@ -import fuse from "./api.fuse"; -import { - getBody, - getContactForm, - getCmsProjects, - getGetInTouch, - getJoinUs, - getMeetOurTeam, - getNewsAndStories, - getOffices, - getOurGuidingPrinciples, - getOurImpact, - getOurMission, - getOurOffices, - getOurOpportunities, - getOurPartners, - getOurProjects, - getOurStories, - getOurTeam, - getPartners, - getProjectTeam, - getRelatedProjects, - getTeam, - getSeo, -} from "./api.netlify-cms"; - -import { - getAllOpportunities, - getAllOpportunitiesTags, - getAllStories, - getAllStoriesTags, - getStory, - getRelatedStoriesByTags, -} from "@/codeforafrica/lib/api.ghost"; -import equalsIgnoreCase from "@/codeforafrica/utils/equalsIgnoreCase"; - -export const partners = getPartners([ - "id", - "slug", - "name", - "content", - "href", - "logo", - "links", -]); - -export const projects = getCmsProjects([ - "tag", - "name", - "slug", - "tagLine", - "icon", - "title", - "subtitle", - "content", - "thumbnail", - "href", - "externalHref", - "badges", - "partners", - "donors", - "team", - "links", -]); - -function getRandomInt(max) { - return Math.floor(Math.random() * max); -} - -function getRandomStartIndex(length, size) { - const max = length >= size ? length - size : length; - return getRandomInt(max); -} - -const meetOurTeam = getMeetOurTeam(); - -export const team = getTeam(); - -const DEFAULT_REVALIDATE = 3 * 60; // 3 minutes - -const ALL_TAG = "All"; - -function getProjectTags(options = { includeAll: true }) { - const tags = Array.from( - new Set(projects?.flatMap((a) => a.tag || [])), - ).sort(); - if (options?.includeAll) { - return [ALL_TAG, ...tags]; - } - return tags; -} - -function paginateResults(items, page, pageSize) { - // We need to initialize to null for serialization. - let count = null; - let results = []; - let pageNumber = null; - let pageSizeNumber = null; - if (items?.length) { - // Need to ensure page, pageSize are numbers and not strings - pageNumber = Number.parseInt(page, 10) || 1; - pageSizeNumber = Number.parseInt(pageSize, 10) || 6; - count = Math.ceil(items.length / pageSizeNumber); - results = items.slice( - (pageNumber - 1) * pageSizeNumber, - pageNumber * pageSizeNumber, - ); - } - return { - pagination: { - count, - page: pageNumber, - pageSize: pageSizeNumber, - }, - results, - }; -} - -function prioritiseFeaturedStory(stories) { - const index = stories.findIndex((s) => s.featured); - // If we have a featured story and it's not the first story, - if (index > 0) { - // we need to "push" the featured story to the top of list. - const featuredStory = stories[index]; - return [featuredStory, ...stories.filter((_, i) => i !== index)]; - } - return stories; -} - -export async function getStories(options) { - const { - tag: originalTag, - page = 1, - "page-size": pageSize = 10, - q, - } = options || {}; - const tag = originalTag || ALL_TAG; - - let stories = await getAllStories(); - if (equalsIgnoreCase(tag, ALL_TAG) && page === 1 && !q) { - stories = prioritiseFeaturedStory(stories); - } else { - if (!equalsIgnoreCase(tag, ALL_TAG)) { - stories = stories.filter((s) => - s.tags.some((t) => equalsIgnoreCase(t, tag)), - ); - } - if (q && stories.length) { - stories = fuse - .stories(stories) - .search(q) - .map((p) => p.item); - } - } - - return paginateResults(stories, page, pageSize); -} - -async function getProcessedNewsAndStories() { - const { title, count = 4, slug } = getNewsAndStories("index"); - const allStories = await getAllStories(); - const articles = prioritiseFeaturedStory(allStories).slice(0, count); - - return { title, articles, slug }; -} - -async function getHomePageStaticProps() { - const seo = getSeo("index"); - return { - props: { - seo, - sections: [ - { - ...getOurProjects(), - projects, - tags: getProjectTags({ includeAll: false }), - }, - { ...meetOurTeam }, - { - ...(await getProcessedNewsAndStories()), - }, - { - ...getOurPartners(), - }, - { - ...getOurImpact(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -export function getProjects(options) { - const { tag: originalTag, page, "page-size": pageSize, q } = options || {}; - const tag = originalTag || ALL_TAG; - - let found = projects.filter( - (p) => equalsIgnoreCase(tag, ALL_TAG) || equalsIgnoreCase(tag, p.tag), - ); - if (found.length && q) { - found = fuse - .projects(found) - .search(q) - .map((p) => p.item); - } - - return paginateResults(found, page, pageSize); -} - -export async function getOpportunities(options) { - const { tag: originalTag, page, "page-size": pageSize, q } = options || {}; - const tag = originalTag || ALL_TAG; - - let opportunities = await getAllOpportunities(); - if (!equalsIgnoreCase(tag, ALL_TAG)) { - opportunities = opportunities.filter((opportunity) => { - return opportunity.tags.some((t) => equalsIgnoreCase(t, tag)); - }); - } - if (opportunities.length && q) { - opportunities = fuse - .opportunities(opportunities) - .search(q) - .map((p) => p.item); - } - - return paginateResults(opportunities, page, pageSize); -} - -async function getOpportunitiesPageStaticProps() { - const allOpportunities = await getAllOpportunities(); - const tags = await getAllOpportunitiesTags(); - const seo = getSeo("opportunities"); - - return { - props: { - seo, - sections: [ - { - ...getOurOpportunities(), - opportunities: paginateResults(allOpportunities), - tags, - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function getOpportunityPageStaticProps(params) { - const actualSlug = params.slug.split("/")[2]; - const foundOpportunity = await getStory(actualSlug); - - if (foundOpportunity) { - const { seo: pageSeo, ...opportunity } = foundOpportunity; - const seo = getSeo("opportunities-individual", pageSeo); - - return { - props: { - seo, - opportunity, - }, - revalidate: DEFAULT_REVALIDATE, - }; - } - return { notFound: true }; -} - -function getImprintPageStaticProps() { - const seo = getSeo("imprint"); - - return { - props: { - seo, - ...getBody("imprint"), - sections: [], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -function getPrivacyPageStaticProps() { - const seo = getSeo("privacy-policy"); - - return { - props: { - seo, - ...getBody("privacy-policy"), - sections: [], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function getProjectPageStaticProps(params) { - const project = projects.find(({ href }) => - equalsIgnoreCase(href, params?.slug), - ); - - if (project) { - const { title, count = 3, slug } = getNewsAndStories("our-work-individual"); - const relatedStories = await getRelatedStoriesByTags([project.name]); - const relatedProjects = getRelatedProjects("our-work-individual"); - const seo = getSeo("our-work-individual", { - title: project.name, - description: - // subtitle could contain html content - project.subtitle.replace(/<[^>]*>/g, "").trim() || project.title, - }); - const startIndex = getRandomStartIndex(projects.length, 3); - - return { - props: { - seo, - project, - sections: [ - { - ...getProjectTeam(), - team: project?.team?.list || null, - }, - { - slug, - title, - articles: relatedStories.slice(0, count), - }, - { - ...relatedProjects, - projects: projects - .filter((p) => p.slug !== project.slug) - .slice(startIndex, startIndex + 3), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; - } - return { notFound: true }; -} - -function getProjectsPageStaticProps() { - const seo = getSeo("our-work"); - - return { - props: { - seo, - sections: [ - { - ...getOurProjects("our-work"), - tags: getProjectTags(), - projects: getProjects(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function getStoriesPageStaticProps() { - const articles = await getAllStories(); - const tags = await getAllStoriesTags(); - const seo = getSeo("stories"); - - return { - props: { - seo, - sections: [ - { - ...getOurStories(), - articles: paginateResults(articles), - tags, - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function getStoryPageStaticProps(slug) { - const actualSlug = slug.slug.split("/")[2]; - const story = await getStory(actualSlug); - const relatedArticles = await getRelatedStoriesByTags(story.tags, story); - - if (story) { - const { - title, - count = 3, - slug: articlesSlug, - } = getNewsAndStories("stories-individual"); - const { seo: pageSeo, ...article } = story; - const seo = getSeo("stories-individual", pageSeo); - - return { - props: { - seo, - article, - sections: [ - { - slug: articlesSlug, - title, - articles: relatedArticles?.slice(0, count) ?? null, - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; - } - return { notFound: true }; -} - -function getMembersFieldTags(options = { includeAll: true }) { - let countries = Array.from( - new Set(team?.flatMap((m) => m.country || [])), - ).sort(); - let teams = Array.from(new Set(team?.flatMap((m) => m.team || []))).sort(); - if (options?.includeAll) { - countries = [ALL_TAG, ...countries]; - teams = [ALL_TAG, ...teams]; - } - return [ - { field: "Country", tags: countries }, - { field: "Team", tags: teams }, - ]; -} - -export function getMembers(options) { - const { - field, - page, - "page-size": pageSize = 18, - q, - tag: originalTag, - } = options || {}; - const tag = originalTag || ALL_TAG; - - let found = team.filter( - (m) => - equalsIgnoreCase(tag, ALL_TAG) || - (field && equalsIgnoreCase(tag, m[field])), - ); - if (found.length && q) { - found = fuse - .members(found) - .search(q) - .map((p) => p.item); - } - - return paginateResults(found, page, pageSize); -} - -function getAboutImpactPageStaticProps() { - const seo = getSeo("about-impact"); - - return { - props: { - seo, - unit: "impact", - crumbs: [{ href: "/about", label: "About us" }, { label: "Impact" }], - sections: [ - { - ...getOurImpact("about"), - }, - { - ...getGetInTouch(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -function getAboutMemberPageStaticProps(params) { - const member = team.find(({ href }) => equalsIgnoreCase(href, params?.slug)); - - if (member) { - const relatedProjects = getRelatedProjects("about-members-individual"); - const seo = getSeo("about-members-individual", { - title: member.name, - description: member.title, - }); - - return { - props: { - seo, - member, - sections: [ - { - ...relatedProjects, - projects: projects.filter((p) => - p.team?.list?.find((m) => m.id === member.id), - ), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; - } - return { notFound: true }; -} - -function getAboutMembersPageStaticProps() { - const seo = getSeo("about-members"); - - return { - props: { - seo, - unit: "members", - crumbs: [{ href: "/about", label: "About us" }, { label: "Members" }], - sections: [ - { - ...getOurTeam(), - pathname: "/about/members", - tags: getMembersFieldTags(), - team: getMembers(), - }, - { - ...getGetInTouch(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -function getAboutPageStaticProps() { - const seo = getSeo("about"); - - return { - props: { - seo, - sections: [ - { - ...getOurMission(), - }, - { - ...getOurGuidingPrinciples(), - }, - - { - ...getOurTeam(), - tags: getMembersFieldTags(), - team: getMembers(), - }, - { - ...getOurPartners("about"), - }, - { - ...getOurImpact("about"), - }, - { - ...getGetInTouch(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -function getAboutPartnerPageStaticProps(params) { - const partner = partners.find(({ slug }) => - equalsIgnoreCase(`/about/partners/${slug}`, params?.slug), - ); - - if (partner) { - const relatedProjects = getRelatedProjects("about-partners-individual"); - const seo = getSeo("about-partners-individual", { - title: partner.name, - // TODO(kilemens): Add short description to each partner - }); - - return { - props: { - seo, - partner: { ...partner, image: partner.logo, title: "Partner" }, - sections: [ - { - ...relatedProjects, - projects: projects.filter((p) => - p.partners?.list?.find((l) => l.id === partner.id), - ), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; - } - return { notFound: true }; -} - -function getAboutPartnersPageStaticProps() { - const seo = getSeo("about-partners"); - - return { - props: { - seo, - unit: "partners", - crumbs: [{ href: "/about", label: "About us" }, { label: "Partners" }], - sections: [ - { - ...getOurPartners("about"), - }, - { - ...getGetInTouch(), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -function getContactPageStaticProps() { - const seo = getSeo("contact"); - - return { - props: { - seo, - sections: [ - { - ...getContactForm(), - }, - { - ...getJoinUs(), - }, - { - ...getOurOffices(), - addresses: getOffices(), - map: { - apiKey: process.env.GOOGLE_API_KEY ?? null, - zoom: 20, - zoomControl: false, - mapTypeControl: false, - scaleControl: false, - streetViewControl: false, - rotateControl: false, - fullscreenControl: false, - }, - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function getProcessedRecentStories(page) { - const allStories = await getAllStories(); - const { title, count = 3, slug } = getNewsAndStories(page); - const articles = allStories.slice(0, count); - return { title, articles, slug }; -} - -async function getErrorPageStaticProps() { - const seo = getSeo("error"); - - return { - props: { - seo, - sections: [ - { - ...(await getProcessedRecentStories("error")), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -async function get404PageStaticProps() { - const seo = getSeo("404"); - - return { - props: { - seo, - sections: [ - { - ...(await getProcessedRecentStories("404")), - }, - ], - }, - revalidate: DEFAULT_REVALIDATE, - }; -} - -export async function getPageStaticProps(params) { - switch (params?.slug) { - case "/": { - return getHomePageStaticProps(params); - } - case "/about": { - return getAboutPageStaticProps(params); - } - case "/about/members": { - return getAboutMembersPageStaticProps(params); - } - case "/about/partners": { - return getAboutPartnersPageStaticProps(params); - } - case "/about/impact": { - return getAboutImpactPageStaticProps(); - } - case "/contact": { - return getContactPageStaticProps(params); - } - case "/imprint": { - return getImprintPageStaticProps(params); - } - case "/opportunities": { - return getOpportunitiesPageStaticProps(params); - } - case "/privacy": { - return getPrivacyPageStaticProps(params); - } - case "/projects": { - return getProjectsPageStaticProps(params); - } - case "/stories": { - return getStoriesPageStaticProps(params); - } - case "/404": { - return get404PageStaticProps(); - } - case "/_error": { - return getErrorPageStaticProps(); - } - default: - if (params?.slug?.startsWith("/about/members/")) { - return getAboutMemberPageStaticProps(params); - } - if (params?.slug?.startsWith("/about/partners/")) { - return getAboutPartnerPageStaticProps(params); - } - if (params?.slug?.startsWith("/opportunities/")) { - return getOpportunityPageStaticProps(params); - } - if (params?.slug?.startsWith("/projects/")) { - return getProjectPageStaticProps(params); - } - if (params?.slug?.startsWith("/stories/")) { - return getStoryPageStaticProps(params); - } - return { notFound: true }; - } -} - -export async function getPageStaticPaths(primaryTag) { - const posts = - primaryTag === "stories" - ? await getAllStories() - : await getAllOpportunities(); - - // filter out items with slug to remove pagination - const actualPosts = posts.filter((post) => post.slug); - const path = actualPosts.map((post) => ({ - params: { slug: post.slug }, - })); - - return path; -} From f3c6cb3b7ac59332d97d46ee2c186c339e688789 Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Tue, 19 Sep 2023 12:57:11 +0300 Subject: [PATCH 2/3] Fix failing build --- .../TeamMembers/TeamMembers.snap.js | 127 +- .../TeamMembers/TeamMembers.test.js | 3 +- .../src/pages/api/admin/config.js | 2029 ----------------- .../src/pages/api/admin/config.yml.page.js | 29 - .../src/pages/api/members/index.page.js | 20 - .../codeforafrica/src/pages/api/oauth/auth.js | 37 - .../src/pages/api/oauth/auth.page.js | 7 - .../src/pages/api/oauth/callback.js | 14 - .../src/pages/api/oauth/callback.page.js | 41 - .../src/pages/api/opportunities/index.page.js | 20 - .../src/pages/api/projects/index.page.js | 20 - .../src/pages/api/stories/index.page.js | 20 - 12 files changed, 2 insertions(+), 2365 deletions(-) delete mode 100644 apps/codeforafrica/src/pages/api/admin/config.js delete mode 100644 apps/codeforafrica/src/pages/api/admin/config.yml.page.js delete mode 100644 apps/codeforafrica/src/pages/api/members/index.page.js delete mode 100644 apps/codeforafrica/src/pages/api/oauth/auth.js delete mode 100644 apps/codeforafrica/src/pages/api/oauth/auth.page.js delete mode 100644 apps/codeforafrica/src/pages/api/oauth/callback.js delete mode 100644 apps/codeforafrica/src/pages/api/oauth/callback.page.js delete mode 100644 apps/codeforafrica/src/pages/api/opportunities/index.page.js delete mode 100644 apps/codeforafrica/src/pages/api/projects/index.page.js delete mode 100644 apps/codeforafrica/src/pages/api/stories/index.page.js diff --git a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.snap.js b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.snap.js index d89212ffe..be1521b9b 100644 --- a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.snap.js +++ b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.snap.js @@ -1,128 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` renders unchanged 1`] = ` -
- -
-`; +exports[` renders unchanged 1`] = `
`; diff --git a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js index 018bcc6cf..be9d86367 100644 --- a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js +++ b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js @@ -3,7 +3,6 @@ import React from "react"; import TeamMembers from "./TeamMembers"; -import { team } from "@/codeforafrica/lib"; import theme from "@/codeforafrica/theme"; // eslint-disable-next-line testing-library/render-result-naming-convention @@ -11,7 +10,7 @@ const render = createRender({ theme }); const defaultProps = { title: "Team", - team: team.slice(0, 3), + team: [], }; describe("", () => { diff --git a/apps/codeforafrica/src/pages/api/admin/config.js b/apps/codeforafrica/src/pages/api/admin/config.js deleted file mode 100644 index c6bcbd32e..000000000 --- a/apps/codeforafrica/src/pages/api/admin/config.js +++ /dev/null @@ -1,2029 +0,0 @@ -const APP_DIRECTORY = process.env.NEXT_PUBLIC_APP_DIRECTORY; - -const seoFields = { - label: "SEO", - name: "seo", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - required: false, - }, - { - label: "Description", - name: "description", - widget: "string", - required: false, - pattern: ["^.{1,150}$", "Must be up to 156 characters"], - }, - { - label: "Title Template", - name: "title-template", - widget: "string", - hint: "Uses title template from Settings | General if not provided", - required: false, - }, - { - label: "Meta data", - name: "meta", - widget: "object", - hint: "Search engines support", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - required: false, - hint: "Uses page title if not provided", - pattern: ["^.{1,70}$", "Must be up to 70 characters"], - }, - { - label: "Description", - name: "description", - widget: "text", - required: false, - hint: "Uses page description if not provided", - pattern: ["^.{1,150}$", "Must be up to 156 characters"], - }, - ], - }, - { - label: "Open Graph", - name: "open-graph", - hint: "Facebook, Slack, and other social media platforms", - widget: "object", - fields: [ - { - label: "Title", - hint: "Uses page title if not provided", - name: "title", - widget: "string", - required: false, - }, - { - label: "Description", - name: "description", - widget: "string", - hint: "Uses page description if not provided", - required: false, - }, - { - label: "Images", - name: "images", - widget: "list", - min: 1, - max: 1, - required: false, - fields: [ - { - name: "url", - label: "URL", - widget: "string", - }, - { - name: "width", - label: "Width", - widget: "string", - }, - { - name: "height", - label: "Height", - widget: "string", - }, - { - name: "alt", - label: "Alt Text", - widget: "string", - }, - ], - }, - ], - }, - { - label: "Twitter", - name: "twitter", - widget: "object", - fields: [ - { - label: "Handle", - name: "handle", - hint: "@username of content creator", - widget: "string", - required: false, - default: "@Code4Africa", - }, - ], - }, - ], -}; - -module.exports = { - backend: { - name: "github", - branch: "main", - repo: "CodeForAfrica/ui", - proxy_url: "http://localhost:8081/api/v1", // Set proxy to work on local repo - }, - media_folder: `${APP_DIRECTORY}public/images`, - public_folder: "/images", - local_backend: true, - collections: [ - { - name: "pages", - label: "Pages", - files: [ - { - label: "Index", - name: "index", - file: `${APP_DIRECTORY}content/pages/index.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "markdown", - }, - { - label: "Messages", - name: "messages", - widget: "list", - min: 3, - max: 3, - }, - { - label: "Subtitle", - name: "subtitle", - widget: "text", - }, - { - label: "Image", - name: "image", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Projects", - name: "projects", - widget: "object", - collapsed: true, - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - label: "Meet Our Team", - name: "meet-our-team", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Description", - name: "description", - widget: "markdown", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - { - label: "Image", - name: "image", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Our partners", - name: "our-partners", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "markdown", - }, - { - label: "Action", - name: "action", - widget: "object", - fields: [ - { - name: "content", - widget: "string", - }, - { - name: "href", - widget: "string", - }, - ], - }, - { - label: "Partners", - name: "partners-list", - widget: "relation", - collection: "partners", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - ], - }, - { - label: "News and stories", - name: "news-stories", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Number of stories", - name: "articles-count", - hint: "Including the featured story", - widget: "number", - value_type: "int", - min: 3, - }, - ], - }, - { - label: "Our Impact", - name: "our-impact", - widget: "object", - fields: [ - { - label: "Impact", - name: "impact-list", - widget: "relation", - collection: "impact", - search_fields: ["title"], - value_field: "id", - display_fields: ["title"], - multiple: true, - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "About", - name: "about", - file: `${APP_DIRECTORY}content/pages/about.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "text", - }, - { - label: "Background Image", - name: "image", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Our Mission", - name: "our-mission", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - name: "description", - widget: "markdown", - }, - ], - }, - { - label: "Guiding Principles", - name: "guiding-principles", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Guiding Principles", - name: "guiding-principle-list", - label_singular: "Guiding Principle", - widget: "relation", - collection: "guiding-principles", - search_fields: ["title"], - value_field: "id", - display_fields: ["title"], - multiple: true, - }, - ], - }, - { - label: "Our team", - name: "our-team", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - label: "Our partners", - name: "our-partners", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Partners", - name: "partners-list", - widget: "relation", - collection: "partners", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - ], - }, - { - label: "Our Impact", - name: "our-impact", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Impact", - name: "impact-list", - widget: "relation", - collection: "impact", - search_fields: ["title"], - value_field: "id", - display_fields: ["title"], - multiple: true, - }, - ], - }, - { - label: "Get in touch", - name: "get-in-touch", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - { - label: "Action", - name: "action", - widget: "object", - fields: [ - { - name: "content", - widget: "string", - }, - { - name: "href", - widget: "string", - }, - ], - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "About | Impact", - name: "about-impact", - file: `${APP_DIRECTORY}content/pages/about-impact.md`, - fields: [ - { - ...seoFields, - }, - ], - }, - { - label: "About | Members", - name: "about-members", - file: `${APP_DIRECTORY}content/pages/about-members.md`, - fields: [ - { - ...seoFields, - }, - ], - }, - { - label: "About | Members | Individual member", - name: "about-members-individual", - file: `${APP_DIRECTORY}content/pages/about-members-individual.md`, - fields: [ - { - label: "Related Projects", - name: "related-projects", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "About | Partners", - name: "about-partners", - file: `${APP_DIRECTORY}content/pages/about-partners.md`, - fields: [ - { - ...seoFields, - }, - ], - }, - { - label: "About | Partners | Individual partner", - name: "about-partners-individual", - file: `${APP_DIRECTORY}content/pages/about-partners-individual.md`, - fields: [ - { - label: "Related Projects", - name: "related-projects", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Contact Us", - name: "contact", - file: `${APP_DIRECTORY}content/pages/contact.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - ], - }, - { - label: "Contact form", - name: "contact-form", - widget: "object", - fields: [ - { - label: "Mailchimp code", - name: "embed-code", - widget: "code", - allow_language_selection: false, - default_language: "html", - output_code_only: true, - }, - ], - }, - { - label: "Join our Slack", - name: "join-our-slack", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - { - label: "Action", - name: "action", - widget: "object", - fields: [ - { - label: "Label", - name: "label", - widget: "string", - }, - { - label: "Link", - name: "href", - widget: "string", - }, - ], - }, - ], - }, - { - label: "Our offices", - name: "our-offices", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Our Work", - name: "our-work", - file: `${APP_DIRECTORY}content/pages/our-work.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - ], - }, - { - label: "Projects", - name: "projects", - widget: "object", - collapsed: true, - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Our Work | Individual work", - name: "our-work-individual", - file: `${APP_DIRECTORY}content/pages/our-work-individual.md`, - fields: [ - { - label: "Team", - name: "team", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - label: "Related Stories", - name: "news-stories", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Number of stories", - name: "articles-count", - widget: "number", - value_type: "int", - min: 3, - }, - ], - }, - { - label: "Related Projects", - name: "related-projects", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Opportunities", - name: "opportunities", - file: `${APP_DIRECTORY}content/pages/opportunities.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - ], - }, - { - label: "Opportunities", - name: "opportunities", - widget: "object", - collapsed: true, - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Opportunities | Individual opportunity", - name: "opportunities-individual", - file: `${APP_DIRECTORY}content/pages/opportunities-individual.md`, - fields: [ - { - ...seoFields, - }, - ], - }, - { - label: "Stories", - name: "stories", - file: `${APP_DIRECTORY}content/pages/stories.md`, - fields: [ - { - label: "Stories", - name: "stories", - widget: "object", - collapsed: true, - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Stories | Individual story", - name: "stories-individual", - file: `${APP_DIRECTORY}content/pages/stories-individual.md`, - fields: [ - { - label: "Related Stories", - name: "news-stories", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Number of stories", - name: "articles-count", - widget: "number", - value_type: "int", - min: 3, - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Imprint", - name: "imprint", - file: `${APP_DIRECTORY}content/pages/imprint.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - ], - }, - { - label: "Body", - name: "body", - widget: "markdown", - }, - { - ...seoFields, - }, - ], - }, - { - label: "Privacy Policy", - name: "privacy-policy", - file: `${APP_DIRECTORY}content/pages/privacy-policy.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "string", - }, - ], - }, - { - label: "Body", - name: "body", - widget: "markdown", - }, - { - ...seoFields, - }, - ], - }, - { - label: "404", - name: "404", - file: `${APP_DIRECTORY}content/pages/404.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "markdown", - }, - ], - }, - { - label: "News and stories", - name: "news-stories", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Number of stories", - name: "articles-count", - widget: "number", - value_type: "int", - min: 3, - }, - ], - }, - { - ...seoFields, - }, - ], - }, - { - label: "Error", - name: "error", - file: `${APP_DIRECTORY}content/pages/error.md`, - fields: [ - { - label: "Hero", - name: "hero", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "markdown", - }, - ], - }, - { - label: "News and stories", - name: "news-stories", - widget: "object", - collapsed: true, - summary: "{{fields.title}}", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Number of stories", - name: "articles-count", - widget: "number", - value_type: "int", - min: 3, - }, - ], - }, - { - ...seoFields, - }, - ], - }, - ], - }, - { - label: "Data | Badges", - name: "badges", - label_singular: "Badge", - folder: `${APP_DIRECTORY}content/badges`, - create: true, - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Date", - name: "date", - widget: "datetime", - format: "MMMM Do YYYY", - }, - ], - }, - { - name: "donors", - label: "Data | Donors", - label_singular: "Donor", - folder: `${APP_DIRECTORY}content/donors`, - create: true, - identifier_field: "name", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Logo", - name: "logo", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - required: false, - }, - ], - }, - ], - }, - { - label: "Data | Guiding Principles", - name: "guiding-principles", - label_singular: "Guiding Principle", - folder: `${APP_DIRECTORY}content/guiding-principles`, - create: true, - identifier_field: "title", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Icon", - name: "icon", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Data | Impact", - name: "impact", - label_singular: "Impact", - folder: `${APP_DIRECTORY}content/impact`, - create: true, - identifier_field: "title", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Value", - name: "value", - widget: "string", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Image", - name: "image", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Data | Offices", - name: "offices-addresses", - label_singular: "Office", - folder: `${APP_DIRECTORY}content/offices`, - create: true, - identifier_field: "name", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Address", - name: "body", - widget: "markdown", - }, - { - label: "Location", - name: "location", - widget: "object", - fields: [ - { - label: "Latitude", - name: "latitude", - widget: "number", - value_type: "float", - }, - { - label: "Longitude", - name: "longitude", - widget: "number", - value_type: "float", - }, - ], - }, - ], - }, - { - name: "partners", - label: "Data | Partners", - folder: `${APP_DIRECTORY}content/partners`, - create: true, - identifier_field: "name", - label_singular: "Partner", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Href", - name: "href", - widget: "string", - required: false, - }, - { - label: "Logo", - name: "logo", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - ], - }, - - { - label: "Links", - name: "links", - widget: "object", - fields: [ - { - label: "Facebook", - name: "facebook", - widget: "string", - required: false, - }, - { - label: "Twitter", - name: "twitter", - widget: "string", - required: false, - }, - { - label: "LinkedIn", - name: "linkedIn", - widget: "string", - required: false, - }, - { - label: "Instagram", - name: "instagram", - widget: "string", - required: false, - }, - { - label: "Github", - name: "github", - widget: "string", - required: false, - }, - { - label: "Slack", - name: "slack", - widget: "string", - required: false, - }, - ], - }, - ], - }, - { - label: "Data | Projects", - name: "projects", - folder: `${APP_DIRECTORY}content/projects`, - create: true, - label_singular: "Project", - identifier_field: "name", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Tag Line", - name: "tagLine", - widget: "string", - }, - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Subtitle", - name: "subtitle", - widget: "markdown", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Tag", - name: "tag", - widget: "string", - }, - { - label: "Icon", - name: "icon", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - ], - }, - { - label: "Thumbnail", - name: "thumbnail", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - ], - }, - { - label: "External URL", - name: "externalHref", - widget: "string", - }, - { - label: "Badges", - name: "badges", - widget: "relation", - label_singular: "Badge", - collection: "badges", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - { - name: "partners", - label: "Partners", - widget: "relation", - label_singular: "Partner", - collection: "partners", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - { - name: "donors", - label: "Donors", - widget: "relation", - label_singular: "Donor", - collection: "donors", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - { - name: "team", - label: "Team", - widget: "relation", - label_singular: "Team Member", - collection: "team", - search_fields: ["name"], - value_field: "id", - display_fields: ["name"], - multiple: true, - }, - { - name: "links", - label: "Links", - label_singular: "Link", - widget: "list", - summary: "{{content}} - {{href}}", - fields: [ - { - label: "slug", - name: "slug", - widget: "string", - }, - { - label: "Content", - name: "content", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - { - label: "Icon", - name: "icon", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - ], - }, - { - label: "Data | Team", - name: "team", - label_singular: "Team Member", - folder: `${APP_DIRECTORY}content/team`, - create: true, - identifier_field: "name", - fields: [ - { - label: "Id", - name: "id", - widget: "uuid", - }, - { - label: "Name", - name: "name", - widget: "string", - }, - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Description", - name: "body", - widget: "markdown", - }, - { - label: "Thumbnail", - name: "thumbnail", - widget: "object", - fields: [ - { - label: "Source", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - { - name: "links", - label: "Links", - widget: "object", - label_singular: "Link", - collapsed: true, - fields: [ - { - label: "Twitter", - name: "twitter", - widget: "string", - required: false, - }, - { - label: "Github", - name: "github", - widget: "string", - required: false, - }, - { - label: "LinkedIn", - name: "linkedin", - widget: "string", - required: false, - }, - { - label: "Facebook", - name: "facebook", - widget: "string", - required: false, - }, - { - label: "Instagram", - name: "instagram", - widget: "string", - required: false, - }, - { - label: "Slack", - name: "slack", - widget: "string", - required: false, - }, - ], - }, - { - label: "Country", - name: "country", - widget: "string", - }, - { - label: "Team", - name: "team", - widget: "string", - }, - { - label: "Deactivated", - name: "deactivated", - widget: "boolean", - default: false, - }, - ], - }, - { - name: "settings", - label: "Settings", - files: [ - { - name: "general", - label: "General", - file: `${APP_DIRECTORY}content/settings/general.md`, - fields: [ - { - label: "Site", - name: "site", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - hint: "The name of the site", - }, - { - label: "Description", - name: "description", - widget: "text", - required: false, - hint: "Helps with search results and when shared in social media platforms", - }, - ], - }, - { - label: "SEO", - name: "seo", - widget: "object", - fields: [ - { - label: "Title Template", - name: "title-template", - widget: "string", - hint: '"pre/suffix that should be included with every page. It replaces %s with your title string e.g. "%s | CfA" template will render "About | CfA" in about page with title "About"', - }, - { - label: "Meta data", - name: "meta", - widget: "object", - hint: "Search engines support", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - required: false, - hint: "Uses page title if not provided", - pattern: ["^.{1,70}$", "Must be up to 70 characters"], - }, - { - label: "Description", - name: "description", - widget: "text", - required: false, - hint: "Uses page description if not provided", - pattern: ["^.{1,150}$", "Must be up to 156 characters"], - }, - ], - }, - { - label: "Open Graph", - name: "open-graph", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - required: false, - hint: "Uses page title if not provided", - }, - { - label: "Description", - name: "description", - widget: "string", - required: false, - hint: "Uses page description if not provided", - }, - { - label: "Images", - name: "images", - widget: "list", - max: 1, - min: 1, - required: false, - fields: [ - { - name: "url", - label: "URL", - widget: "string", - }, - { - name: "width", - label: "Width", - widget: "string", - }, - { - name: "height", - label: "Height", - widget: "string", - }, - { - name: "alt", - label: "Alt Text", - widget: "string", - }, - ], - }, - ], - }, - { - label: "Twitter", - name: "twitter", - widget: "object", - fields: [ - { - label: "@Site", - name: "site", - widget: "string", - required: false, - default: "@Code4Africa", - }, - { - label: "Card Type", - name: "cardType", - widget: "hidden", - default: "summary_large_image", - }, - ], - }, - ], - }, - ], - }, - { - label: "Header", - name: "header", - file: `${APP_DIRECTORY}content/settings/header.md`, - fields: [ - { - label: "Logo", - name: "logo", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - { - label: "Main Navigation", - name: "main-navigation", - label_singular: "Navigation item", - widget: "list", - fields: [ - { - label: "Label", - name: "content", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - ], - }, - { - label: "Social Media Link", - name: "social-media-link", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - { - label: "Mobile Icon", - name: "mobile-icon", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - { - label: "Desktop Icon", - name: "desktop-icon", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - ], - }, - { - label: "Footer", - name: "footer", - file: `${APP_DIRECTORY}content/settings/footer.md`, - fields: [ - { - label: "Logo", - name: "logo", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - { - label: "Description", - name: "description", - widget: "markdown", - }, - { - label: "Stay in touch", - name: "stay-in-touch", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Links", - name: "links", - label_singular: "Link", - widget: "list", - fields: [ - { - label: "Label", - name: "label", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - { - label: "Icon", - name: "icon", - widget: "object", - fields: [ - { - label: "Src", - name: "src", - widget: "image", - }, - { - label: "Height", - name: "height", - widget: "string", - required: false, - }, - { - label: "Width", - name: "width", - widget: "string", - required: false, - }, - ], - }, - ], - }, - ], - }, - { - label: "Main Navigation", - name: "main-navigation", - label_singular: "Navigation item", - widget: "list", - fields: [ - { - label: "Label", - name: "content", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - ], - }, - { - label: "Secondary Navigation", - name: "secondary-navigation", - label_singular: "Navigation item", - widget: "list", - fields: [ - { - label: "Label", - name: "content", - widget: "string", - }, - { - label: "Href", - name: "href", - widget: "string", - }, - ], - }, - { - label: "Newsletter subscription", - name: "newsletter-subscription", - widget: "object", - fields: [ - { - label: "Title", - name: "title", - widget: "string", - }, - { - label: "Mailchimp code", - name: "embed-code", - widget: "code", - allow_language_selection: false, - default_language: "html", - output_code_only: true, - }, - ], - }, - ], - }, - ], - }, - ], -}; diff --git a/apps/codeforafrica/src/pages/api/admin/config.yml.page.js b/apps/codeforafrica/src/pages/api/admin/config.yml.page.js deleted file mode 100644 index 8ddba0207..000000000 --- a/apps/codeforafrica/src/pages/api/admin/config.yml.page.js +++ /dev/null @@ -1,29 +0,0 @@ -import yaml from "js-yaml"; - -import config from "./config"; - -import site from "@/codeforafrica/utils/site"; - -export default function handler(req, res) { - if (req.method === "GET") { - if (process.env.NODE_ENV === "production") { - // Set production configurations - config.backend.name = "github"; - config.backend.repo = process.env.GITHUB_BACKEND_REPO; - config.backend.base_url = site.url.replace(/\/+$/, ""); - config.backend.auth_endpoint = process.env.GITHUB_AUTH_ENDPOINT; - config.publish_mode = "editorial_workflow"; - // Remove dev configurations - config.local_backend = undefined; - config.backend.proxy_url = undefined; - } - config.logo_url = site.logoUrl; - const configFile = yaml.dump(config); - - res.setHeader("Content-Type", "text/yaml"); - res.setHeader("Content-Disposition", "attachment; filename=config.yml"); - res.send(configFile); - } - - return res.status(405).end(); -} diff --git a/apps/codeforafrica/src/pages/api/members/index.page.js b/apps/codeforafrica/src/pages/api/members/index.page.js deleted file mode 100644 index b24614719..000000000 --- a/apps/codeforafrica/src/pages/api/members/index.page.js +++ /dev/null @@ -1,20 +0,0 @@ -import { getMembers } from "@/codeforafrica/lib"; - -const QUERY_PARAM_NAMES = ["field", "page", "page-size", "q", "tag"]; - -export default function handler(req, res) { - if (req.method === "GET") { - const { query: originalQuery } = req; - const query = Object.keys(originalQuery).reduce((acc, key) => { - const paramName = key.toLocaleLowerCase(); - if (QUERY_PARAM_NAMES.includes(key)) { - acc[paramName] = originalQuery[key]; - } - return acc; - }, {}); - const projects = getMembers(query); - return res.status(200).json(projects); - } - - return res.status(405).end(); -} diff --git a/apps/codeforafrica/src/pages/api/oauth/auth.js b/apps/codeforafrica/src/pages/api/oauth/auth.js deleted file mode 100644 index 84d325f5c..000000000 --- a/apps/codeforafrica/src/pages/api/oauth/auth.js +++ /dev/null @@ -1,37 +0,0 @@ -import { nanoid } from "nanoid"; -import { AuthorizationCode } from "simple-oauth2"; - -import site from "@/codeforafrica/utils/site"; - -const config = { - cms: { - oauth: { - redirectUrl: `${site.environmentUrl.replace( - /\/+$/, - "", - )}/api/oauth/callback`, - scope: "user, repo", - }, - }, -}; - -const client = new AuthorizationCode({ - client: { - id: process.env.OAUTH_CLIENT_ID, - secret: process.env.OAUTH_CLIENT_SECRET, - }, - auth: { - tokenHost: "https://github.com", - authorizePath: "/login/oauth/authorize", - }, -}); - -// Authorization uri definition -const authorizationUri = client.authorizeURL({ - redirect_uri: config.cms.oauth.redirectUrl, - scope: config.cms.oauth.scope, - state: nanoid(), -}); - -// Initial page redirecting to Github -export default authorizationUri; diff --git a/apps/codeforafrica/src/pages/api/oauth/auth.page.js b/apps/codeforafrica/src/pages/api/oauth/auth.page.js deleted file mode 100644 index 103b8b60c..000000000 --- a/apps/codeforafrica/src/pages/api/oauth/auth.page.js +++ /dev/null @@ -1,7 +0,0 @@ -import authorizationUri from "./auth"; - -// Initial page redirecting to Github -export default async (req, res) => { - res.writeHead(302, { Location: authorizationUri }); - res.end(); -}; diff --git a/apps/codeforafrica/src/pages/api/oauth/callback.js b/apps/codeforafrica/src/pages/api/oauth/callback.js deleted file mode 100644 index ddd71ba55..000000000 --- a/apps/codeforafrica/src/pages/api/oauth/callback.js +++ /dev/null @@ -1,14 +0,0 @@ -import { AuthorizationCode } from "simple-oauth2"; - -const client = new AuthorizationCode({ - client: { - id: process.env.OAUTH_CLIENT_ID, - secret: process.env.OAUTH_CLIENT_SECRET, - }, - auth: { - tokenHost: "https://github.com", - tokenPath: "/login/oauth/access_token", - }, -}); - -export default client; diff --git a/apps/codeforafrica/src/pages/api/oauth/callback.page.js b/apps/codeforafrica/src/pages/api/oauth/callback.page.js deleted file mode 100644 index 18aecebcd..000000000 --- a/apps/codeforafrica/src/pages/api/oauth/callback.page.js +++ /dev/null @@ -1,41 +0,0 @@ -import client from "./callback"; - -const oauthProvider = "github"; - -export default async (req, res) => { - const { code, state } = req.query; - const tokenParams = { - code, - state, - }; - - let status = "error"; - let content; - try { - const accessToken = await client.getToken(tokenParams); - status = "success"; - content = { - token: accessToken.token.access_token, - provider: oauthProvider, - }; - } catch (error) { - content = JSON.stringify(error); - } - - const script = ` - `; - return res.end(script); -}; diff --git a/apps/codeforafrica/src/pages/api/opportunities/index.page.js b/apps/codeforafrica/src/pages/api/opportunities/index.page.js deleted file mode 100644 index 2f29f9448..000000000 --- a/apps/codeforafrica/src/pages/api/opportunities/index.page.js +++ /dev/null @@ -1,20 +0,0 @@ -import { getOpportunities } from "@/codeforafrica/lib"; - -const QUERY_PARAM_NAMES = ["tag", "page", "q"]; - -export default async function handler(req, res) { - if (req.method === "GET") { - const { query: originalQuery } = req; - const query = Object.keys(originalQuery).reduce((acc, key) => { - const paramName = key.toLocaleLowerCase(); - if (QUERY_PARAM_NAMES.includes(key)) { - acc[paramName] = originalQuery[key]; - } - return acc; - }, {}); - const projects = await getOpportunities(query); - return res.status(200).json(projects); - } - - return res.status(405).end(); -} diff --git a/apps/codeforafrica/src/pages/api/projects/index.page.js b/apps/codeforafrica/src/pages/api/projects/index.page.js deleted file mode 100644 index 952bdc3ba..000000000 --- a/apps/codeforafrica/src/pages/api/projects/index.page.js +++ /dev/null @@ -1,20 +0,0 @@ -import { getProjects } from "@/codeforafrica/lib"; - -const QUERY_PARAM_NAMES = ["tag", "page", "q"]; - -export default function handler(req, res) { - if (req.method === "GET") { - const { query: originalQuery } = req; - const query = Object.keys(originalQuery).reduce((acc, key) => { - const paramName = key.toLocaleLowerCase(); - if (QUERY_PARAM_NAMES.includes(key)) { - acc[paramName] = originalQuery[key]; - } - return acc; - }, {}); - const projects = getProjects(query); - return res.status(200).json(projects); - } - - return res.status(405).end(); -} diff --git a/apps/codeforafrica/src/pages/api/stories/index.page.js b/apps/codeforafrica/src/pages/api/stories/index.page.js deleted file mode 100644 index 99bd73cc9..000000000 --- a/apps/codeforafrica/src/pages/api/stories/index.page.js +++ /dev/null @@ -1,20 +0,0 @@ -import { getStories } from "@/codeforafrica/lib"; - -const QUERY_PARAM_NAMES = ["field", "page", "page-size", "q", "tag"]; - -export default async function handler(req, res) { - if (req.method === "GET") { - const { query: originalQuery } = req; - const query = Object.keys(originalQuery).reduce((acc, key) => { - const paramName = key.toLocaleLowerCase(); - if (QUERY_PARAM_NAMES.includes(key)) { - acc[paramName] = originalQuery[key]; - } - return acc; - }, {}); - const stories = await getStories(query); - return res.status(200).json(stories); - } - - return res.status(405).end(); -} From 57f54246a75337472b1da47859cf165b1045ee29 Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Wed, 20 Sep 2023 11:44:10 +0300 Subject: [PATCH 3/3] Update tests --- .../codeforafrica/src/components/TeamMembers/TeamMembers.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js index be9d86367..fcff42135 100644 --- a/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js +++ b/apps/codeforafrica/src/components/TeamMembers/TeamMembers.test.js @@ -10,7 +10,6 @@ const render = createRender({ theme }); const defaultProps = { title: "Team", - team: [], }; describe("", () => {