From fa2a33f9f224945e67f466af4f37d5b01417c4d2 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:55:30 +0300 Subject: [PATCH 01/20] Add default location to HURUMap config --- .../src/pages/api/hurumap/profiles.js | 25 +++++++++++ .../src/payload/fields/LocationSelect.js | 43 +++++++++++++++++++ .../src/payload/globals/HURUMap/index.js | 34 +++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 apps/climatemappedafrica/src/pages/api/hurumap/profiles.js create mode 100644 apps/climatemappedafrica/src/payload/fields/LocationSelect.js diff --git a/apps/climatemappedafrica/src/pages/api/hurumap/profiles.js b/apps/climatemappedafrica/src/pages/api/hurumap/profiles.js new file mode 100644 index 000000000..ae3ff17a5 --- /dev/null +++ b/apps/climatemappedafrica/src/pages/api/hurumap/profiles.js @@ -0,0 +1,25 @@ +import { fetchProfile } from "@/climatemappedafrica/lib/hurumap"; + +let cache = null; +let cacheExpiry = 0; + +export default async function handler(req, res) { + if (req.method === "GET") { + const now = Date.now(); + + if (cache && now < cacheExpiry) { + return res.status(200).json(cache); + } + + try { + const result = await fetchProfile(); + cache = result; + cacheExpiry = now + 5 * 60 * 1000; + return res.status(200).json(result); + } catch (err) { + return res.status(500).json(err.message); + } + } + + return res.status(405).end(); +} diff --git a/apps/climatemappedafrica/src/payload/fields/LocationSelect.js b/apps/climatemappedafrica/src/payload/fields/LocationSelect.js new file mode 100644 index 000000000..5e6e3bf94 --- /dev/null +++ b/apps/climatemappedafrica/src/payload/fields/LocationSelect.js @@ -0,0 +1,43 @@ +import { Select } from "payload/components/forms"; +import { select } from "payload/dist/fields/validations"; +import { createElement, useMemo } from "react"; +import useSWR from "swr"; + +const fetcher = (url) => fetch(url).then((res) => res.json()); +const apiUrl = process.env.PAYLOAD_PUBLIC_APP_URL; + +export async function validateLocation(value, { hasMany, required, t }) { + const response = await fetch(`${apiUrl}/api/hurumap/profiles`); + const data = await response.json(); + const { locations } = data ?? {}; + const options = + locations + ?.filter(({ level }) => level !== "region") + ?.map((location) => ({ + label: location.name, + value: location.code, + })) || []; + return select(value, { hasMany, options, required, t }); +} + +function LocationSelect(props) { + const url = `${apiUrl}/api/hurumap/profiles`; + const { data } = useSWR(url, fetcher, { + dedupingInterval: 60000, + revalidateOnFocus: false, + }); + const { locations } = data ?? {}; + const memoOptions = () => + ( + locations + ?.filter(({ level }) => level !== "region") + ?.map((location) => ({ + label: location.name, + value: location.code, + })) || [] + ).sort((a, b) => a.label.localeCompare(b.label)); + const options = useMemo(memoOptions, [locations]); + return createElement(Select, { ...props, options }); +} + +export default LocationSelect; diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js index 6a6592f31..3e3e9cc55 100644 --- a/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js +++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js @@ -1,11 +1,15 @@ +import LocationSelect, { validateLocation } from "../../fields/LocationSelect"; + const HURUMap = { slug: "settings-hurumap", label: "HURUMap", + description: "HURUMap Configuration", access: { read: () => true, }, admin: { group: "Settings", + hideAPIURL: true, }, fields: [ { @@ -15,6 +19,36 @@ const HURUMap = { relationTo: ["pages"], maxDepth: 1, required: true, + admin: { + description: + "The page to use as the Explore page. It will contain the interactive map.", + }, + }, + { + name: "initialLocation", + label: "Initial Location", + type: "group", + fields: [ + { + name: "name", + type: "text", + required: true, + hasMany: false, + defaultValue: "af", + validate: validateLocation, + admin: { + components: { + Field: LocationSelect, + }, + }, + }, + { + name: "center", + label: "Center Point", + type: "point", + defaultValue: [0.3051933453207569, 37.908818734483155], + }, + ], }, ], }; From 852494c6fbca0baeff2cba6344e4570788a51066 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:01:37 +0300 Subject: [PATCH 02/20] Improve LocationSelect --- .../src/payload/fields/LocationSelect.js | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/apps/climatemappedafrica/src/payload/fields/LocationSelect.js b/apps/climatemappedafrica/src/payload/fields/LocationSelect.js index 5e6e3bf94..293f4b762 100644 --- a/apps/climatemappedafrica/src/payload/fields/LocationSelect.js +++ b/apps/climatemappedafrica/src/payload/fields/LocationSelect.js @@ -3,40 +3,37 @@ import { select } from "payload/dist/fields/validations"; import { createElement, useMemo } from "react"; import useSWR from "swr"; -const fetcher = (url) => fetch(url).then((res) => res.json()); const apiUrl = process.env.PAYLOAD_PUBLIC_APP_URL; +const fetcher = (url) => fetch(url).then((res) => res.json()); + +const getOptions = (locations) => + locations + ?.filter(({ level }) => level !== "region") + ?.map((location) => ({ + label: location.name, + value: location.code, + })) || []; export async function validateLocation(value, { hasMany, required, t }) { - const response = await fetch(`${apiUrl}/api/hurumap/profiles`); - const data = await response.json(); - const { locations } = data ?? {}; - const options = - locations - ?.filter(({ level }) => level !== "region") - ?.map((location) => ({ - label: location.name, - value: location.code, - })) || []; + const data = await fetcher(`${apiUrl}/api/hurumap/profiles`); + const options = getOptions(data.locations); return select(value, { hasMany, options, required, t }); } function LocationSelect(props) { - const url = `${apiUrl}/api/hurumap/profiles`; - const { data } = useSWR(url, fetcher, { + const { data } = useSWR(`${apiUrl}/api/hurumap/profiles`, fetcher, { dedupingInterval: 60000, revalidateOnFocus: false, }); - const { locations } = data ?? {}; - const memoOptions = () => - ( - locations - ?.filter(({ level }) => level !== "region") - ?.map((location) => ({ - label: location.name, - value: location.code, - })) || [] - ).sort((a, b) => a.label.localeCompare(b.label)); - const options = useMemo(memoOptions, [locations]); + + const options = useMemo( + () => + getOptions(data?.locations).sort((a, b) => + a.label.localeCompare(b.label), + ), + [data], + ); + return createElement(Select, { ...props, options }); } From 61e80740702961098aa755a993cde21e2dfcd1b2 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:55:32 +0300 Subject: [PATCH 03/20] Working Explore Page --- .../src/lib/data/blockify/explore-page.js | 181 ++++++++++++++++++ .../src/lib/data/blockify/index.js | 2 + .../src/lib/data/common/index.js | 22 ++- .../src/pages/[[...slug]].js | 2 + 4 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 apps/climatemappedafrica/src/lib/data/blockify/explore-page.js diff --git a/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js new file mode 100644 index 000000000..a3a432129 --- /dev/null +++ b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js @@ -0,0 +1,181 @@ +const apiUrl = process.env.PAYLOAD_PUBLIC_APP_URL; +const fetcher = (url) => fetch(url).then((res) => res.json()); + +const fetchProfile = async () => { + const data = await fetcher(`${apiUrl}/api/hurumap/profiles`); + return data; +}; + +const fetchProfileGeography = async (geoCode) => { + const data = await fetcher(`${apiUrl}/api/hurumap/geographies/${geoCode}`); + return data; +}; + +async function explorePage({ slug: code, center }) { + const hurumapProfile = await fetchProfile(); + + const { locations, preferredChildren, mapType, choropleth } = hurumapProfile; + + const locationCodes = locations.map(({ code: locationCode }) => locationCode); + const geoCodes = code + .split("-vs-") + .map((c) => c.trim()) + .filter((c) => c); + if (!geoCodes.every((gC) => locationCodes.includes(gC))) { + return { + notFound: true, + }; + } + + const [primaryCode, secondaryCode] = geoCodes; + const primaryProfile = await fetchProfileGeography(primaryCode); + const profile = [primaryProfile]; + if (secondaryCode) { + const secondaryProfile = await fetchProfileGeography(secondaryCode); + profile.push(secondaryProfile); + } + + // TODO: Move this to a PayloadCMS + const blocks = { + texts: [], + tutorial: { + items: [ + { + title: "SELECT LOCATION", + description: + "Select the County or Municipality you want to explore, by clicking on the search field and the dropdown menu.

Once you have made your selection, explore the visualisations, change location or pin to compare it to a second location.", + selector: "#location-search", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + width: 694, + height: 572, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGOoqW09f/7Shw8fzp07x8AuoC4qqdXf311YWMTAL6YVE5ve2tpcV18PAHqlETRE6fa/AAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + description: + "Explore the map to confirm or change your selection. You can also pin your location if you want to compare two places.

Once a location is confirmed, click on the “Rich Data” button (on the left hand-side) to display the data visualisations.", + title: "EXPLORE THE MAP", + selector: "#none", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + width: 751, + height: 589, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGP49u3rxEnTDxw4sn//fobCggJeYVU+YaWCvByGzMxMPmElWwfPgvw8AH1vD9GRbZHGAAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + title: "BROWSE THE CHARTS", + description: + "Continue to open the Rich Data dashboard, using the button on the left.

Browse the charts by scrolling the data dashboard. You can share and download the data using the buttons on the side of each chart.", + selector: "#rich-data", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + width: 670, + height: 439, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/ANbW1s3NyVtbWrKyswDOztFdY38JCxe5ubcA3t7ffIKf4uPq////vgcX8ZIA2dgAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + { + title: "PIN AND COMPARE", + description: + "There are two ways to pin and compare a second location:

1) From the data dashboard: look for the “pin” icon and select a second location from the dropdown menu.

2) From the map: pin your selected location by clicking on the ”pin” icon, then select a second location, which will appear in a different colour.", + selector: "#pin", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + width: 675, + height: 491, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/APj491lWYA8QI+zs6wC/wMHXzMmLi5uztLYAu7u7w8XF39/eu7u7x7oYwYnBuWcAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + ], + lazyblock: { + slug: "lazyblock/tutorial", + }, + align: "", + anchor: "", + blockId: "Z1npKaH", + blockUniqueClass: "lazyblock-tutorial-Z1npKaH", + ghostkitSpacings: "", + ghostkitSR: "", + }, + panel: { + panelItems: [ + { + value: "rich-data", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGElEQVR4nGNgQAP/T///f/o/jHMWiQMHACIVCyeABSwfAAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + value: "pin", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + pin: true, + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgQAP/L/z/f/r//4P/wZzT//+fBbOQAQBvnQ3r6iVM4QAAAABJRU5ErkJggg==", + placeholder: "blur", + }, + }, + ], + scrollToTopLabel: "Back To Top", + dataNotAvailable: "— DATA NOT AVAILABLE", + lazyblock: { + slug: "lazyblock/panel", + }, + align: "", + anchor: "", + blockId: "20amuc", + blockUniqueClass: "lazyblock-panel-20amuc", + ghostkitSpacings: "", + ghostkitSR: "", + }, + }; + + const res = { + blockType: "explore-page", + blocks, + center, + choropleth, + locations, + mapType, + profile, + variant: "explore", + preferredChildren, + }; + + return res; +} + +export default explorePage; diff --git a/apps/climatemappedafrica/src/lib/data/blockify/index.js b/apps/climatemappedafrica/src/lib/data/blockify/index.js index 07d61107f..39df28c48 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/index.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/index.js @@ -1,7 +1,9 @@ +import explorePage from "./explore-page"; import pageHero from "./page-hero"; import team from "./team"; const propsifyBlockBySlug = { + "explore-page": explorePage, "page-hero": pageHero, team, }; diff --git a/apps/climatemappedafrica/src/lib/data/common/index.js b/apps/climatemappedafrica/src/lib/data/common/index.js index ab0341049..7afcf048e 100644 --- a/apps/climatemappedafrica/src/lib/data/common/index.js +++ b/apps/climatemappedafrica/src/lib/data/common/index.js @@ -53,6 +53,22 @@ function getNavBar(siteSettings, variant) { }; } +async function processExplorePage(slugs, hurumap) { + const { + initialLocation: { name, center }, + } = hurumap; + const slug = slugs.length ? slugs[0] : name; + const blocks = await blockify([ + { + blockType: "explore-page", + center, + slug: slug.trim().toLowerCase(), + }, + ]); + + return blocks; +} + export async function getPageProps(api, context) { // For now, ClimatemappedAfrica only supports single paths i.e. /, /about, etc., // so params.slug[0] is good enough @@ -74,13 +90,17 @@ export async function getPageProps(api, context) { page: { value: explorePage }, } = hurumap; - const blocks = await blockify(page.blocks, api, context); + let blocks = await blockify(page.blocks, api, context); const variant = page.slug === explorePage.slug ? "explore" : "default"; const siteSettings = await api.findGlobal("settings-site"); const footer = getFooter(siteSettings, variant); const menus = getNavBar(siteSettings, variant); + if (slug === explorePage.slug) { + blocks = await processExplorePage(slugs.slice(1), hurumap); + } + return { blocks, footer, diff --git a/apps/climatemappedafrica/src/pages/[[...slug]].js b/apps/climatemappedafrica/src/pages/[[...slug]].js index d5b79793e..2be1812c3 100644 --- a/apps/climatemappedafrica/src/pages/[[...slug]].js +++ b/apps/climatemappedafrica/src/pages/[[...slug]].js @@ -3,6 +3,7 @@ import React from "react"; import { SWRConfig } from "swr"; import AboutTeam from "@/climatemappedafrica/components/AboutTeam"; +import ExplorePage from "@/climatemappedafrica/components/ExplorePage"; import Footer from "@/climatemappedafrica/components/Footer"; import Navigation from "@/climatemappedafrica/components/Navigation"; import PageHero from "@/climatemappedafrica/components/PageHero"; @@ -10,6 +11,7 @@ import Summary from "@/climatemappedafrica/components/Summary"; import { getPageServerSideProps } from "@/climatemappedafrica/lib/data"; const componentsBySlugs = { + "explore-page": ExplorePage, "page-hero": PageHero, summary: Summary, team: AboutTeam, From acb6cab656e83addbbd4e54469dc846a7d86a697 Mon Sep 17 00:00:00 2001 From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:46:16 +0300 Subject: [PATCH 04/20] Show tutorial --- .../src/components/ExplorePage/index.js | 9 +- .../src/lib/data/blockify/explore-page.js | 160 +++++------------- .../src/lib/data/blockify/index.js | 2 + .../src/lib/data/blockify/tutorial.js | 88 ++++++++++ .../src/lib/data/common/index.js | 3 + .../src/pages/[[...slug]].js | 21 ++- 6 files changed, 156 insertions(+), 127 deletions(-) create mode 100644 apps/climatemappedafrica/src/lib/data/blockify/tutorial.js diff --git a/apps/climatemappedafrica/src/components/ExplorePage/index.js b/apps/climatemappedafrica/src/components/ExplorePage/index.js index 20c977918..792ace1b6 100644 --- a/apps/climatemappedafrica/src/components/ExplorePage/index.js +++ b/apps/climatemappedafrica/src/components/ExplorePage/index.js @@ -21,7 +21,11 @@ function initialState(profiles, onClick) { }; } -function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { +function ExplorePage({ + panel: panelProps = {}, + profile: profileProp, + ...props +}) { const theme = useTheme(); const classes = useStyles(props); // NOTE: This setState and the corresponding useEffect are "hacks" since at @@ -166,8 +170,7 @@ function ExplorePage({ panelProps, profile: profileProp, apiUri, ...props }) { } ExplorePage.propTypes = { - apiUri: PropTypes.string, - panelProps: PropTypes.shape({}), + panel: PropTypes.shape({}), profile: PropTypes.oneOfType([ PropTypes.shape({ geography: PropTypes.shape({}), diff --git a/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js index a3a432129..36a7a17cc 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js @@ -36,140 +36,56 @@ async function explorePage({ slug: code, center }) { } // TODO: Move this to a PayloadCMS - const blocks = { - texts: [], - tutorial: { - items: [ - { - title: "SELECT LOCATION", - description: - "Select the County or Municipality you want to explore, by clicking on the search field and the dropdown menu.

Once you have made your selection, explore the visualisations, change location or pin to compare it to a second location.", - selector: "#location-search", - image: - "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", - imageProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", - width: 694, - height: 572, - type: "png", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGOoqW09f/7Shw8fzp07x8AuoC4qqdXf311YWMTAL6YVE5ve2tpcV18PAHqlETRE6fa/AAAAAElFTkSuQmCC", - placeholder: "blur", - }, + const panel = { + panelItems: [ + { + value: "rich-data", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGElEQVR4nGNgQAP/T///f/o/jHMWiQMHACIVCyeABSwfAAAAAElFTkSuQmCC", + placeholder: "blur", }, - { - description: - "Explore the map to confirm or change your selection. You can also pin your location if you want to compare two places.

Once a location is confirmed, click on the “Rich Data” button (on the left hand-side) to display the data visualisations.", - title: "EXPLORE THE MAP", - selector: "#none", - image: - "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", - imageProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", - width: 751, - height: 589, - type: "png", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGP49u3rxEnTDxw4sn//fobCggJeYVU+YaWCvByGzMxMPmElWwfPgvw8AH1vD9GRbZHGAAAAAElFTkSuQmCC", - placeholder: "blur", - }, - }, - { - title: "BROWSE THE CHARTS", - description: - "Continue to open the Rich Data dashboard, using the button on the left.

Browse the charts by scrolling the data dashboard. You can share and download the data using the buttons on the side of each chart.", - selector: "#rich-data", - image: - "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", - imageProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", - width: 670, - height: 439, - type: "png", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/ANbW1s3NyVtbWrKyswDOztFdY38JCxe5ubcA3t7ffIKf4uPq////vgcX8ZIA2dgAAAAASUVORK5CYII=", - placeholder: "blur", - }, - }, - { - title: "PIN AND COMPARE", - description: - "There are two ways to pin and compare a second location:

1) From the data dashboard: look for the “pin” icon and select a second location from the dropdown menu.

2) From the map: pin your selected location by clicking on the ”pin” icon, then select a second location, which will appear in a different colour.", - selector: "#pin", - image: - "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", - imageProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", - width: 675, - height: 491, - type: "png", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/APj491lWYA8QI+zs6wC/wMHXzMmLi5uztLYAu7u7w8XF39/eu7u7x7oYwYnBuWcAAAAASUVORK5CYII=", - placeholder: "blur", - }, - }, - ], - lazyblock: { - slug: "lazyblock/tutorial", }, - align: "", - anchor: "", - blockId: "Z1npKaH", - blockUniqueClass: "lazyblock-tutorial-Z1npKaH", - ghostkitSpacings: "", - ghostkitSR: "", - }, - panel: { - panelItems: [ - { - value: "rich-data", - icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", - iconProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2021/11/Group-4505.svg", - width: 44, - height: 44, - type: "svg", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGElEQVR4nGNgQAP/T///f/o/jHMWiQMHACIVCyeABSwfAAAAAElFTkSuQmCC", - placeholder: "blur", - }, - }, - { - value: "pin", - icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", - pin: true, - iconProps: { - src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", - width: 44, - height: 44, - type: "svg", - blurDataURL: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgQAP/L/z/f/r//4P/wZzT//+fBbOQAQBvnQ3r6iVM4QAAAABJRU5ErkJggg==", - placeholder: "blur", - }, + { + value: "pin", + icon: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + pin: true, + iconProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/01/Path-210-1-1.svg", + width: 44, + height: 44, + type: "svg", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAH0lEQVR4nGNgQAP/L/z/f/r//4P/wZzT//+fBbOQAQBvnQ3r6iVM4QAAAABJRU5ErkJggg==", + placeholder: "blur", }, - ], - scrollToTopLabel: "Back To Top", - dataNotAvailable: "— DATA NOT AVAILABLE", - lazyblock: { - slug: "lazyblock/panel", }, - align: "", - anchor: "", - blockId: "20amuc", - blockUniqueClass: "lazyblock-panel-20amuc", - ghostkitSpacings: "", - ghostkitSR: "", + ], + scrollToTopLabel: "Back To Top", + dataNotAvailable: "— DATA NOT AVAILABLE", + lazyblock: { + slug: "lazyblock/panel", }, + align: "", + anchor: "", + blockId: "20amuc", + blockUniqueClass: "lazyblock-panel-20amuc", + ghostkitSpacings: "", + ghostkitSR: "", }; - const res = { + id: "explore-page", blockType: "explore-page", - blocks, center, choropleth, locations, mapType, + panel, profile, variant: "explore", preferredChildren, diff --git a/apps/climatemappedafrica/src/lib/data/blockify/index.js b/apps/climatemappedafrica/src/lib/data/blockify/index.js index 39df28c48..9e91332ea 100644 --- a/apps/climatemappedafrica/src/lib/data/blockify/index.js +++ b/apps/climatemappedafrica/src/lib/data/blockify/index.js @@ -1,11 +1,13 @@ import explorePage from "./explore-page"; import pageHero from "./page-hero"; import team from "./team"; +import tutorial from "./tutorial"; const propsifyBlockBySlug = { "explore-page": explorePage, "page-hero": pageHero, team, + tutorial, }; export const blockify = async (blocks, api, context) => { diff --git a/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js new file mode 100644 index 000000000..781934ccc --- /dev/null +++ b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js @@ -0,0 +1,88 @@ +async function tutorial() { + // TODO: Move this to Payload CMS + return { + blockType: "tutorial", + id: "tutorial", + items: [ + { + title: "SELECT LOCATION", + description: + "Select the County or Municipality you want to explore, by clicking on the search field and the dropdown menu.

Once you have made your selection, explore the visualisations, change location or pin to compare it to a second location.", + selector: "#location-search", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-1.png", + width: 694, + height: 572, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGOoqW09f/7Shw8fzp07x8AuoC4qqdXf311YWMTAL6YVE5ve2tpcV18PAHqlETRE6fa/AAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + description: + "Explore the map to confirm or change your selection. You can also pin your location if you want to compare two places.

Once a location is confirmed, click on the “Rich Data” button (on the left hand-side) to display the data visualisations.", + title: "EXPLORE THE MAP", + selector: "#none", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-2.png", + width: 751, + height: 589, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMElEQVR4nGP49u3rxEnTDxw4sn//fobCggJeYVU+YaWCvByGzMxMPmElWwfPgvw8AH1vD9GRbZHGAAAAAElFTkSuQmCC", + placeholder: "blur", + }, + }, + { + title: "BROWSE THE CHARTS", + description: + "Continue to open the Rich Data dashboard, using the button on the left.

Browse the charts by scrolling the data dashboard. You can share and download the data using the buttons on the side of each chart.", + selector: "#rich-data", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-3a.png", + width: 670, + height: 439, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/ANbW1s3NyVtbWrKyswDOztFdY38JCxe5ubcA3t7ffIKf4uPq////vgcX8ZIA2dgAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + { + title: "PIN AND COMPARE", + description: + "There are two ways to pin and compare a second location:

1) From the data dashboard: look for the “pin” icon and select a second location from the dropdown menu.

2) From the map: pin your selected location by clicking on the ”pin” icon, then select a second location, which will appear in a different colour.", + selector: "#pin", + image: + "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + imageProps: { + src: "https://cms.dev.codeforafrica.org/pesayetu/wp-content/uploads/sites/2/2022/04/PesaYetu-Tutorial-4.png", + width: 675, + height: 491, + type: "png", + blurDataURL: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMklEQVR4nAEnANj/APj491lWYA8QI+zs6wC/wMHXzMmLi5uztLYAu7u7w8XF39/eu7u7x7oYwYnBuWcAAAAASUVORK5CYII=", + placeholder: "blur", + }, + }, + ], + lazyblock: { + slug: "lazyblock/tutorial", + }, + align: "", + anchor: "", + blockId: "Z1npKaH", + blockUniqueClass: "lazyblock-tutorial-Z1npKaH", + ghostkitSpacings: "", + ghostkitSR: "", + }; +} + +export default tutorial; diff --git a/apps/climatemappedafrica/src/lib/data/common/index.js b/apps/climatemappedafrica/src/lib/data/common/index.js index 7afcf048e..5c76cd59d 100644 --- a/apps/climatemappedafrica/src/lib/data/common/index.js +++ b/apps/climatemappedafrica/src/lib/data/common/index.js @@ -64,6 +64,9 @@ async function processExplorePage(slugs, hurumap) { center, slug: slug.trim().toLowerCase(), }, + { + blockType: "tutorial", + }, ]); return blocks; diff --git a/apps/climatemappedafrica/src/pages/[[...slug]].js b/apps/climatemappedafrica/src/pages/[[...slug]].js index 2be1812c3..471d852dc 100644 --- a/apps/climatemappedafrica/src/pages/[[...slug]].js +++ b/apps/climatemappedafrica/src/pages/[[...slug]].js @@ -1,3 +1,4 @@ +import { useRouter } from "next/router"; import { NextSeo } from "next-seo"; import React from "react"; import { SWRConfig } from "swr"; @@ -5,6 +6,7 @@ import { SWRConfig } from "swr"; import AboutTeam from "@/climatemappedafrica/components/AboutTeam"; import ExplorePage from "@/climatemappedafrica/components/ExplorePage"; import Footer from "@/climatemappedafrica/components/Footer"; +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"; @@ -18,6 +20,10 @@ const componentsBySlugs = { }; function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { + const { + query: { showTutorial }, + } = useRouter(); + const pageSeo = {}; pageSeo.title = seo?.title || null; pageSeo.description = seo?.metaDesc || null; @@ -37,6 +43,13 @@ function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { } } + const tutorialBlock = blocks.find((block) => block.blockType === "tutorial"); + + let TutorialComponent = React.Fragment; + if (tutorialBlock) { + TutorialComponent = Tutorial; + } + let PageConfig = React.Fragment; let pageConfigProps; if (fallback) { @@ -44,7 +57,11 @@ function Index({ blocks, menus, footer: footerProps, seo = {}, fallback }) { pageConfigProps = { value: { fallback } }; } return ( - <> +