Skip to content

Commit

Permalink
Merge pull request #987 from CodeForAfrica/chore/climatemappedafrica_…
Browse files Browse the repository at this point in the history
…static_build

@/climatemappedafrica Static Build
  • Loading branch information
kilemensi authored Nov 4, 2024
2 parents 1e2af03 + 927ee44 commit 37f75b3
Show file tree
Hide file tree
Showing 14 changed files with 1,985 additions and 1,678 deletions.
36 changes: 36 additions & 0 deletions apps/climatemappedafrica/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# dependencies
node_modules
.pnp
.pnp.js
.pnpm-debug.log

# typescript
dist/

# testing
coverage

# next.js
.next/
out/

# payload
build/

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Vercel
.vercel
.now

# turbo
.turbo
test-results/
playwright-report/
3 changes: 1 addition & 2 deletions apps/climatemappedafrica/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.3",
"private": true,
"author": "Code for Africa <[email protected]>",
"description": "Climate Mapped Africa ",
"description": "ClimateMapped Africa",
"keywords": [
"climatemappedafrica",
"next",
Expand Down Expand Up @@ -65,7 +65,6 @@
"next": "catalog:",
"next-images": "catalog:",
"next-seo": "catalog:",
"nodemailer-sendgrid": "catalog:",
"papaparse": "catalog:",
"payload": "catalog:",
"plaiceholder": "catalog:",
Expand Down
47 changes: 32 additions & 15 deletions apps/climatemappedafrica/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,29 @@ import path from "path";
import { spawn } from "child_process";
import express from "express";
import next from "next";
import nodemailerSendgrid from "nodemailer-sendgrid";
import payload from "payload";
import { Payload } from "payload/dist/payload";
import { loadEnvConfig } from "@next/env";
import type { Payload } from "payload/dist/payload";

// TODO(kilemensi): Figure out why alias "@/climatemappedafrica" doesn't work here
import { getClient } from "./src/lib/payload/payload-client";

const projectDir = process.cwd();
loadEnvConfig(projectDir);

const dev = process.env.NODE_ENV !== "production";
const hostname = process.env.NEXT_HOSTNAME || "localhost";
const port = parseInt(process.env.PORT || "3000", 10);
const sendGridAPIKey = process.env.SENDGRID_API_KEY;
// TODO(kilemensi): Migrate to SMTP email setup instead of SendGrid specific
const smtpAuthPass = process.env.SMTP_PASS || process.env.SENDGRID_API_KEY;
const smtpFromName =
process.env.SMTP_FROM_NAME ||
process.env.SENDGRID_FROM_NAME ||
"ClimateMapped Africa CMS";
const smtpFromAddress =
process.env.SMTP_FROM_ADDRESS ||
process.env.SENDGRID_FROM_EMAIL ||
"[email protected]";
const smtpPort = Number(process.env.SMTP_PORT || 587);

if (!process.env.NEXT_MANUAL_SIG_HANDLE) {
process.on("SIGTERM", () => process.exit(0));
Expand All @@ -25,24 +36,30 @@ const app = express();
const start = async (): Promise<void> => {
let localPayload: Payload;
try {
localPayload = await payload.init({
...(sendGridAPIKey
localPayload = await getClient({
...(smtpAuthPass
? {
email: {
transportOptions: nodemailerSendgrid({
apiKey: sendGridAPIKey,
}),
fromName:
process.env.SENDGRID_FROM_NAME || "ClimateMapped Africa CMS",
fromAddress:
process.env.SENDGRID_FROM_EMAIL || "[email protected]",
transportOptions: {
auth: {
user: process.env.SMTP_USER || "apikey",
apiKey: smtpAuthPass,
},
host: process.env.SMTP_HOST || "smtp.sendgrid.net",
port: smtpPort,
secure: smtpPort === 465, // true for port 465, false (the default) for 587 and others
},
fromName: smtpFromName,
fromAddress: smtpFromAddress,
},
}
: undefined),
secret: process.env.PAYLOAD_SECRET,
express: app,
local: false,
onInit: (initPayload) => {
initPayload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
initPayload.logger.info(
`Payload Admin URL: ${initPayload.getAdminURL()}`,
);
},
});
} catch (e: any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function Icon({ item, handleIconClick, currentItemIndex, index }) {
>
<Image
src={index === currentItemIndex ? secondaryIcon : primaryIcon}
layout="fill"
fill
/>
</Box>
<Typography
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RichText } from "@commons-ui/payload";
import { Grid, Typography, IconButton, Avatar } from "@mui/material";
import { useTour } from "@reactour/tour";
import Image from "next/image";
import Image from "next/legacy/image";
import PropTypes from "prop-types";
import React from "react";

Expand Down
37 changes: 35 additions & 2 deletions apps/climatemappedafrica/src/lib/data/common/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { blockify } from "@/climatemappedafrica/lib/data/blockify";
import { fetchProfile } from "@/climatemappedafrica/lib/hurumap";

// TODO(kilemensi): Use HURUmap APIs (or CMS) to pick geographies we'd like to
// build pages for at build time (It can't be all geographies
// as that will take forever)
const GEOGRAPHIES = ["af", "ke", "tz"];

export function imageFromMedia(alt, url) {
return { alt, src: url };
}
Expand Down Expand Up @@ -57,9 +62,37 @@ async function getNavBar(siteSettings, variant, { slug }, hurumapProfile) {
};
}

export async function getPagePaths(api) {
const hurumapSettings = await api.findGlobal("settings-hurumap");
const { docs: pages } = await api.getCollection("pages");
const {
page: { value: explorePage },
} = hurumapSettings;
const paths = pages.flatMap(({ slug }) => {
// TODO(kilemensi): Handle parent > child page relation e.g. /insights/news
if (slug !== explorePage?.slug) {
return {
params: {
slugs: [slug === "index" ? "" : slug],
},
};
}
// HURUmap profile page
return GEOGRAPHIES.map((code) => ({
params: {
slugs: [explorePage.slug, code],
},
}));
});
return {
paths,
fallback: true,
};
}

export async function getPageProps(api, context) {
// For now, ClimatemappedAfrica only supports single paths i.e. /, /about, etc.,
// so params.slug[0] is good enough
// For now, ClimateMappedAfrica only supports single paths i.e. /, /about, etc.,
// so params.slugs[0] is good enough
const slugs = context.params?.slugs || undefined;
const [slug] = slugs || ["index"];
const { draftMode = false } = context;
Expand Down
4 changes: 2 additions & 2 deletions apps/climatemappedafrica/src/lib/data/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { getPageStaticPaths, getPageStaticProps } from "./local";

export { getPageServerSideProps } from "./local";
export default undefined;
16 changes: 13 additions & 3 deletions apps/climatemappedafrica/src/lib/data/local/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { payload } from "@/climatemappedafrica/lib";
import { getPageProps } from "@/climatemappedafrica/lib/data/common";
import {
getPagePaths,
getPageProps,
} from "@/climatemappedafrica/lib/data/common";
import payload from "@/climatemappedafrica/lib/payload";

export const api = payload;

export async function getPageServerSideProps(context) {
export async function getPageStaticPaths() {
return getPagePaths(api);
}

export async function getPageStaticProps(context) {
const props = await getPageProps(api, context);

// TODO(kilemensi): We need to differentiate 404 from server errors (5xx)
// https://nextjs.org/docs/14/pages/building-your-application/data-fetching/incremental-static-regeneration#error-handling-and-revalidation
if (!props) {
return { notFound: true };
}
return {
props,
revalidate: 120, // in seconds
};
}
3 changes: 2 additions & 1 deletion apps/climatemappedafrica/src/lib/data/utils/get-members.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ function getQueryFromParams(params) {
};
}

export async function getMembers(api, params) {
// TODO(kilemensi): Confirm if params is undefined when using static build
export async function getMembers(api, params = {}) {
const { page: queryPage = 1 } = params;
const options = {
limit: 18,
Expand Down
8 changes: 7 additions & 1 deletion apps/climatemappedafrica/src/lib/payload/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import payload from "payload";
import { getClient } from "./payload-client";

async function findPage(slug, options) {
const payload = await getClient();
return payload.find({
...options,
collection: "pages",
Expand All @@ -14,6 +15,7 @@ async function findPage(slug, options) {
}

async function getCollection(collection, options) {
const payload = await getClient();
return payload.find({
limit: 0,
...options,
Expand All @@ -22,13 +24,15 @@ async function getCollection(collection, options) {
}

async function findGlobal(slug, options) {
const payload = await getClient();
return payload.findGlobal({
...options,
slug,
});
}

async function createCollection(collection, data, options) {
const payload = await getClient();
return payload.create({
collection,
data,
Expand All @@ -37,13 +41,15 @@ async function createCollection(collection, data, options) {
}

async function deleteCollection(collection, options) {
const payload = await getClient();
return payload.delete({
...options,
collection,
});
}

async function updateCollection(collection, id, data, options) {
const payload = await getClient();
const args = {
...options,
collection,
Expand Down
39 changes: 39 additions & 0 deletions apps/climatemappedafrica/src/lib/payload/payload-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// TODO(kilemensi): Need to update eslint to handle globalThis but we should
// do that when upgrading Next.js
/* eslint no-undef:0 */
import { loadEnvConfig } from "@next/env";
import payload from "payload";

const projectDir = process.cwd();
loadEnvConfig(projectDir);

let cached = globalThis.payload;

if (!cached) {
globalThis.payload = { client: null, promise: null };
cached = globalThis.payload;
}

export async function getClient(options) {
if (cached.client) {
return cached.client;
}

if (!cached.promise) {
cached.promise = payload.init({
// https://payloadcms.com/docs/local-api/overview#nextjs-conflict-with-local-api
local: !options?.express,
secret: process.env.PAYLOAD_SECRET,
...options,
});
}
try {
cached.client = await cached.promise;
} catch (e) {
cached.promise = null;
throw e;
}
return cached.client;
}

export default undefined;
17 changes: 12 additions & 5 deletions apps/climatemappedafrica/src/pages/[[...slugs]].js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import Tutorial from "@/climatemappedafrica/components/HURUmap/Tutorial";
import Navigation from "@/climatemappedafrica/components/Navigation";
import PageHero from "@/climatemappedafrica/components/PageHero";
import Summary from "@/climatemappedafrica/components/Summary";
import { getPageServerSideProps } from "@/climatemappedafrica/lib/data";
import {
getPageStaticPaths,
getPageStaticProps,
} from "@/climatemappedafrica/lib/data";

const componentsBySlugs = {
"data-indicators": DataIndicators,
Expand All @@ -27,7 +30,7 @@ const componentsBySlugs = {
team: AboutTeam,
};

function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) {
function Page({ blocks = [], menus, footer: footerProps, seo = {}, fallback }) {
const {
query: { showTutorial },
} = useRouter();
Expand Down Expand Up @@ -92,8 +95,12 @@ function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) {
);
}

export async function getServerSideProps(context) {
return getPageServerSideProps(context);
export async function getStaticPaths() {
return getPageStaticPaths();
}

export default Index;
export async function getStaticProps(context) {
return getPageStaticProps(context);
}

export default Page;
12 changes: 8 additions & 4 deletions apps/climatemappedafrica/turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
"NEXT_PUBLIC_VERCEL_ENV",
"NEXT_PUBLIC_VERCEL_URL",
"NODE_TLS_REJECT_UNAUTHORIZED",
"PAYLOAD_SECRET",
"PROJECT_ROOT",
"S3_UPLOAD_KEY",
"S3_UPLOAD_SECRET",
"S3_UPLOAD_BUCKET",
"S3_UPLOAD_REGION"
"S3_ACCESS_KEY_ID",
"S3_SECRET_ACCESS_KEY",
"S3_BUCKET",
"S3_REGION",
"SENDGRID_API_KEY",
"SENDGRID_FROM_EMAIL",
"SENDGRID_FROM_NAME"
]
}
}
Expand Down
Loading

0 comments on commit 37f75b3

Please sign in to comment.