From 40ecae145e7219ed4e7a5257b9383f5448a05dd5 Mon Sep 17 00:00:00 2001 From: Xavier Damman Date: Tue, 15 Feb 2022 11:18:32 +0100 Subject: [PATCH] Added /collectives/ayowecca, + fixes for /collectives --- components/CollectiveCard.js | 26 +++-- components/Footer.js | 7 +- next.config.js | 12 ++ pages/collectives/[googleDocId].js | 182 +++++++++++++++++++++++++++++ pages/collectives/index.js | 139 +++++++--------------- pages/collectives/list.js | 2 +- pages/collectives/mosaic.js | 107 +++++++++++++++++ pages/collectives/updates.js | 2 +- sitemap.json | 9 ++ 9 files changed, 378 insertions(+), 108 deletions(-) create mode 100644 pages/collectives/[googleDocId].js create mode 100644 pages/collectives/mosaic.js diff --git a/components/CollectiveCard.js b/components/CollectiveCard.js index 54f237c..96f5741 100644 --- a/components/CollectiveCard.js +++ b/components/CollectiveCard.js @@ -1,6 +1,6 @@ -import styled from 'styled-components'; -import { Flex, Box } from 'rebass'; -import numeral from '../lib/numeral'; +import styled from "styled-components"; +import { Flex, Box } from "rebass"; +import numeral from "../lib/numeral"; const Collective = styled.div` width: 150px; @@ -8,7 +8,7 @@ const Collective = styled.div` float: left; padding: 10px; border: 1px solid #eee; - border-radius: 3px; + border-radius: 10px; overflow: hidden; margin: 5px; `; @@ -20,13 +20,15 @@ const H1 = styled.h1` display: flex; align-items: center; justify-content: center; + line-height: 1; `; const Description = styled.p` - font-size: 12px; + font-size: 11.5px; overflow: hidden; color: #222; height: 45px; + font-weight: 500; line-height: 1.3; `; @@ -50,7 +52,7 @@ const Number = styled.div` `; const Label = styled.label` -font-size: 10px; + font-size: 10px; `; export default ({ data }) => { @@ -67,16 +69,20 @@ export default ({ data }) => { - {numeral(data.stats.balance / 100).format('$0,0')} + + {numeral(data.stats.balance / 100).format("$0,0")} + - {numeral(data.stats.monthlySpending / 100).format('$0,0')} + + {numeral(data.stats.monthlySpending / 100).format("$0,0")} + - ) -} \ No newline at end of file + ); +}; diff --git a/components/Footer.js b/components/Footer.js index 0957866..e378a04 100644 --- a/components/Footer.js +++ b/components/Footer.js @@ -1,7 +1,10 @@ const Footer = ({ googleDocId }) => ( -
+
- + All for Climate Logo { + if (!key.match(/^collectives\//)) return; + console.log(">>> key", key); + paths.push({ + params: { + googleDocId: sitemap[key].googleDocId, + }, + }); + paths.push({ + params: { + googleDocId: key.replace("collectives/", ""), + }, + }); + }); + console.log(paths); + return { + paths, + fallback: true, + }; +} + +export async function getStaticProps({ params }) { + const pageInfo = getPageMetadata(`collectives/${params.googleDocId}`); + const googleDocId = pageInfo.googleDocId || params.googleDocId; + let doc = {}, + error = null; + try { + doc = await getHTMLFromGoogleDocId(googleDocId); + } catch (e) { + error = e.message; + } + + const page = { + title: pageInfo.title || doc.title || null, + description: pageInfo.description || doc.description || null, + image: pageInfo.image || null, + body: doc.body || null, + outline: doc.outline || null, + googleDocId, + error, + }; + + return { + props: { page }, + // we will attempt to re-generate the page: + // - when a request comes in + // - at most once every 180 seconds + revalidate: 180, + }; +} + +export default function Home({ page }) { + if (!page) return
; + const { title, description, outline, body, image, googleDocId, error } = page; + const [currentSection, setCurrentSection] = useState(); + const [currentDocWidth, setCurrentDocWidth] = useState(0); + + function changeCurrentSection(section) { + setCurrentSection(section); + document.querySelectorAll("#outline a").forEach((el) => { + const href = el.getAttribute("href"); + if (href === `#${section}`) { + el.classList.add("bg-gray-300"); + console.log(">>> adding active to", el); + } else { + el.classList.remove("bg-gray-300"); + } + }); + console.log(">>> current section", section); + history.replaceState( + null, + null, + document.location.pathname + (section ? "#" + section : "") + ); + } + + function logit() { + const y = window.pageYOffset; + if (y % 5 !== 0) return false; + + let section = null, + index = 0; + outline.forEach((item, i) => { + if (y >= item.offsetTop - 60) { + section = item.slug; + index = i; + } + }); + if (section !== currentSection) { + changeCurrentSection(section); + } + } + + function computeOffset() { + const docEl = document.querySelector("#document"); + if (!docEl) return; + if (Math.abs(docEl.offsetWidth - currentDocWidth) < 50) { + return; + } + console.log( + "computeOffset", + currentDocWidth, + Math.abs(docEl.offsetWidth - currentDocWidth) + ); + setCurrentDocWidth(Number(docEl.offsetWidth) || 120); + docEl.querySelectorAll("h1,h2,h3,h4,h5,h6").forEach((el) => { + const slug = el.getAttribute("id"); + const item = outline.find((o) => o.slug === slug); + if (!item) return; + item.offsetTop = el.offsetTop; + item.el = el; + }); + } + + useEffect(() => { + // we only highlight the current section on large screens + // where the outline is visible side by side + if (window.innerWidth < 768) return false; + + function addListeners() { + window.addEventListener("scroll", logit); + window.addEventListener("resize", computeOffset); + } + computeOffset(); + addListeners(); + return () => { + window.removeEventListener("scroll", logit); + window.removeEventListener("resize", computeOffset); + }; + }); + + return ( +
+ + {title || defaultValues.title} + + + + + +
+ {outline && ( + computeOffset()} /> + )} +
+ {!body && !error &&

Loading...

} + {error === "not_published" && ( + + )} + {error === "invalid_googledocid" && ( + + )} + {body && ( +
+ +
+
+ )} +
+
+
+ ); +} diff --git a/pages/collectives/index.js b/pages/collectives/index.js index 80b0955..8e68798 100644 --- a/pages/collectives/index.js +++ b/pages/collectives/index.js @@ -1,5 +1,9 @@ import styled from "styled-components"; import Link from "next/link"; +import sitemap from "../../sitemap.json"; +import { getHTMLFromGoogleDocId } from "../../lib/googledoc"; +import RenderGoogleDoc from "../../components/RenderGoogleDoc"; +import Footer from "../../components/Footer"; const Body = styled.div``; @@ -23,101 +27,48 @@ const StyledLink = styled.a` } `; -const About = styled.div` - margin: 50px 0; -`; - -const Footer = styled.div``; - -const FooterLink = styled.a` - text-decoration: none; - margin-right: 20px; -`; - -const Label = styled.span` - color: #555; - margin-right: 20px; -`; - -const H2 = styled.h2` - font-size: 24px; - font-weight: 700; - margin: 40px 0 10px; -`; +export async function getStaticProps(context, params) { + const googleDocId = sitemap.collectives.googleDocId; + const page = await getHTMLFromGoogleDocId(googleDocId); -export default () => ( - -
-
- - - - List of collectives we are hosting - - - Latest updates from our collectives - - - Apply to host your collective - - - 📕 Documentation - - - 💶 Donate - - + return { + props: { page, googleDocId }, + // we will attempt to re-generate the page: + // - when a request comes in + // - at most once every 180 seconds + revalidate: 180, + }; +} - -

A fiscal sponsor for your local climate justice group

-

- As a local group you probably don't have the resources to create - your own non profit with your own bank account. You also probably - don't want to use your personal bank account to receive donations - and manage the expenses for your group. We have created a non profit - based in Brussels that can act as a fiscal sponsor for you (in the - eurozone), think of it as your financial back office.
-
- More info - -

+export default function CollectivesPage({ page, googleDocId }) { + return ( + +
+
+ + + + 🔅 List of collectives we are hosting + + + 📰 Latest updates from our collectives + + + 🙋‍♀️ Apply to host your collective + + + 📕 Documentation + + + 💶 Donate + + -

- An easy way for foundations to support local climate justice groups -

-

- Local groups don't usually have a bank account where you can wire - money to, nor do they have the administrative resources to do - accounting and to write the necessary reports you need. All for - Climate is set up as a proper non profit entity based in Brussels - that you can trust. We act as a shared administrative back office so - that local groups can focus on their actions. -
- Contact us -

- + {page.body && } -
- - Discord - - - Open Collective - - - GitHub - - - Facebook - - - Google Drive - - Email -
- -
-
-
- -); +
+
+
+ + ); +} diff --git a/pages/collectives/list.js b/pages/collectives/list.js index 37fd4d9..bbf18a9 100644 --- a/pages/collectives/list.js +++ b/pages/collectives/list.js @@ -58,7 +58,7 @@ export default ({ collectives }) => {

We are hosting {collectives.length} collectives

diff --git a/pages/collectives/mosaic.js b/pages/collectives/mosaic.js new file mode 100644 index 0000000..56845bd --- /dev/null +++ b/pages/collectives/mosaic.js @@ -0,0 +1,107 @@ +import styled from "styled-components"; +import { Flex } from "rebass"; + +const Body = styled.div` + max-width: 900px; + margin: 0 auto; + font-family: Content-font, Roboto, sans-serif; + font-weight: 400; + line-height: 1.625; + font-size: 16px; +`; + +const CollectiveLogo = styled.img` + height: 64px; + margin: 0 0 0 0; + flex: 0 0 auto; +`; + +const H2 = styled.h2` + font-size: 24px; + font-weight: 700; + margin: 40px 0 10px; +`; + +export default ({ collectives }) => { + const images = {}; + collectives.map((node) => { + images[node.collective.image] = true; + }); + const imagesArray = Object.keys(images); + return ( + +
+ + + {imagesArray.map((image) => ( + + ))} + +
+ + ); +}; + +async function getData() { + console.log( + ">>> fetching collectives data from OC graphql API", + process.env.OC_GRAPHQL_API + ); + const query = ` + query collective($slug: String) { + Collective (slug: $slug) { + name, + description + memberOf(role: "HOST") { + collective { + slug + name + description + image + stats { + balance + monthlySpending + backers { + all + } + } + updates { + createdAt + title + } + } + } + } + } + `; + + const res = await fetch(process.env.OC_GRAPHQL_API, { + method: "post", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query, variables: { slug: "allforclimate" } }), + }); + const json = await res.json(); + let collectives = json.data.Collective.memberOf; + collectives.sort((a, b) => { + if (a.collective.stats.backers.all > b.collective.stats.backers.all) + return -1; + if (a.collective.stats.backers.all < b.collective.stats.backers.all) + return 1; + return a.collective.stats.balance > b.collective.stats.balance ? -1 : 1; + }); + + return { collectives }; +} + +export async function getStaticProps() { + return { + props: await getData(), + // we will attempt to re-generate the page: + // - when a request comes in + // - at most once every 180 seconds + revalidate: 180, + }; +} diff --git a/pages/collectives/updates.js b/pages/collectives/updates.js index ccc03fc..6ce6970 100644 --- a/pages/collectives/updates.js +++ b/pages/collectives/updates.js @@ -60,7 +60,7 @@ export default ({ updates }) => {

Latest updates from our collectives

diff --git a/sitemap.json b/sitemap.json index d90585b..5cf4952 100644 --- a/sitemap.json +++ b/sitemap.json @@ -23,6 +23,15 @@ "title": "All for Climate DAO - projects", "googleDocId": "1d2qyyfXs_tSjn7K3CWb5cRiaNHmPoEWZv-QZIOKOW8k" }, + "collectives": { + "title": "All for Climate DAO - collectives", + "googleDocId": "1xhZCvzf5lF3pjAWE3Ru9gCqwR5Wdwwpw2buMviC-GPY" + }, + "collectives/ayowecca": { + "title": "Ayowecca - Uganda", + "description": "Protecting Natural Resources, Adaptation to #ClimateChange, Conservations, SRHR, Skills Development & Empowering Women & Children.", + "googleDocId": "17nHfcbkIliEpm3dJgGRHx8an-rMAO5LUu4FsRbaud0A" + }, "gitcoinclimate": { "title": "All for Climate DAO - Gitcoin Climate", "description": "Raise funds for your project with Gitcoin",