From 63b1aeca2b860f8d7e1fe374fdc68f6c6cab6e2e Mon Sep 17 00:00:00 2001 From: "rich.jdev00" Date: Thu, 3 Jul 2025 03:08:36 +0400 Subject: [PATCH 1/4] Add support for special projects --- src/components/SectionRecentArticles.js | 63 +++---- .../SpecialProjects/MoreArticles.js | 155 ++++++++++++++++++ src/layouts/advanced.js | 38 ++++- src/pages/[...slug].js | 8 +- studio/schemas/advanced.js | 57 +++++-- 5 files changed, 278 insertions(+), 43 deletions(-) create mode 100644 src/components/SpecialProjects/MoreArticles.js diff --git a/src/components/SectionRecentArticles.js b/src/components/SectionRecentArticles.js index 8f74dfb6..df6f0ec8 100644 --- a/src/components/SectionRecentArticles.js +++ b/src/components/SectionRecentArticles.js @@ -77,7 +77,7 @@ const useStyles = makeStyles(() => ({ })); const SectionRecentArticles = (props) => { - const { articles } = props; + const { articles, viewMore } = props; const classes = useStyles(); return ( @@ -93,40 +93,42 @@ const SectionRecentArticles = (props) => { Latest - - - + - View more - - - + + View more + + + + )} @@ -184,6 +186,7 @@ const SectionRecentArticles = (props) => { SectionRecentArticles.propTypes = { articles: PropTypes.array, + viewMore: PropTypes.boolean, }; export default SectionRecentArticles; diff --git a/src/components/SpecialProjects/MoreArticles.js b/src/components/SpecialProjects/MoreArticles.js new file mode 100644 index 00000000..b49a6c01 --- /dev/null +++ b/src/components/SpecialProjects/MoreArticles.js @@ -0,0 +1,155 @@ +// base imports +import React from "react"; +import PropTypes from "prop-types"; +import { DateTime } from "luxon"; + +// Material UI imports +import { makeStyles } from "@mui/styles"; +import Grid from "@mui/material/Grid"; +import Link from "@mui/material/Link"; +import Typography from "@mui/material/Typography"; +import Badge from "../Badge"; + +const useStyles = makeStyles((theme) => ({ + article: { + marginBottom: 20, + }, + lastArticle: { + marginBottom: 20, + }, + articleTitle: { + color: "#000 !important", + fontSize: "1em", + fontWeight: "700", + "&:hover": { + color: "#225C9D !important", + textDecoration: "none", + }, + }, + articlePublication: { + color: "rgba(0, 0, 0, 0.6)", + marginTop: 25, + marginBottom: 8, + position: "relative", + }, + articleGrid: { + borderBottom: "1px solid", + borderBottomColor: "#DCDCDC", + paddingBottom: 20, + flexDirection: "column", + flexWrap: "nowrap", + columnGap: "16px", + rowGap: "8px", + [theme.breakpoints.down("md")]: { + flexDirection: "column", + }, + }, + em: { + fontSize: "0.81em", + fontStyle: "italic", + }, + authors: { + color: "rgba(0, 0, 0, 0.6)", + fontFamily: "Lexend", + fontSize: "10px", + fontWeight: "700", + textTransform: "uppercase", + }, + grid: { + marginTop: 20, + }, + gridTitle: { + borderBottom: "1px solid #000", + marginBottom: 32, + width: "100%", + }, + link: { + textDecoration: "none !important", + }, + more: { + textDecoration: "none", + width: 200, + "&:active, & :focus, &:hover": { + color: "#FF0033", + textDecoration: "underline", + }, + }, + moreText: { + backgroundColor: "#FFE5EA", + borderRadius: 2, + color: "#FF0033", + fontWeight: 500, + padding: 6, + }, +})); + +function MoreArticles({ articles }) { + const classes = useStyles(); + + return ( + + + + More + + + + {articles && articles.length + ? articles.map((article) => ( + + + + {article.badge && ( + + )} + + + {article.title} + + + + {DateTime.fromISO(article.date) + .setZone("America/New_York") + .setLocale("en-us") + .toLocaleString(DateTime.DATE_FULL)} + + + + + )) + : null} + + + ); +} + +MoreArticles.propTypes = { + articles: PropTypes.array, +}; + +export default MoreArticles; diff --git a/src/layouts/advanced.js b/src/layouts/advanced.js index c4033162..b35671ec 100644 --- a/src/layouts/advanced.js +++ b/src/layouts/advanced.js @@ -7,6 +7,7 @@ import PropTypes from "prop-types"; import Box from "@mui/material/Box"; import Container from "@mui/material/Container"; import Grid from "@mui/material/Grid"; +import Typography from "@mui/material/Typography"; // components import components, { Layout } from "../components/index"; @@ -24,12 +25,13 @@ import SpotlightArticles from "../components/Homepage/SpotlightArticles"; import AroundGlobe from "../components/Homepage/AroundGlobe"; import PolicyTracker from "../components/Homepage/PolicyTracker"; import Announcements from "../components/Homepage/Announcements"; +import MoreArticles from "../components/SpecialProjects/MoreArticles"; const Advanced = (props) => { const { path, page, featured, articles } = props; const latest = - path === "/" + (path === "/" || (page && page.layout === "project")) && articles ? articles.filter( (article) => featured.find((a) => a._id === article._id) == null ) @@ -193,6 +195,40 @@ const Advanced = (props) => { + ) : page && page.layout === "project" ? ( + <> + + + {page.title} + + + {featured && ( + + + + + )} + + + + + + + + + ) : ( <> {path === "/tracker" ? ( diff --git a/src/pages/[...slug].js b/src/pages/[...slug].js index a412aa37..58280895 100644 --- a/src/pages/[...slug].js +++ b/src/pages/[...slug].js @@ -51,7 +51,7 @@ export async function getStaticProps(props) { ); let [page] = await client.fetch( - `*[!(_id in path("drafts.**")) && _type in ["advanced", "page", "post"] && (slug.current == "${slug}" || stackbit_url_path == "/${slug}")]{_id, _type, stackbit_url_path, trackerText, _createdAt, _updatedAt, badge, date, slug, title, body, toc, tocTitle, featuredImage, seo, disableNewsletterSignup, authors[]->{slug, name, photo, bio}, heroContent, layout, sections, sidebar_content[type == "sidebar_about"]{staff[]->, board[]->, masthead[]->}, relatedTopics[]->{displayName, name, type, slug, stackbit_model_type}, relatedArticles[]->{date,badge,title,slug,authors[]->{firstName, lastName}},relatedCommentary[]->}` + `*[!(_id in path("drafts.**")) && _type in ["advanced", "page", "post"] && (slug.current == "${slug}" || stackbit_url_path == "/${slug}")]{_id, _type, stackbit_url_path, trackerText, _createdAt, _updatedAt, badge, date, slug, title, body, toc, tocTitle, featuredImage, seo, disableNewsletterSignup, authors[]->{slug, name, photo, bio}, heroContent, layout, sections, sidebar_content[type == "sidebar_about"]{staff[]->, board[]->, masthead[]->}, relatedTopics[]->{displayName, name, type, slug, stackbit_model_type}, relatedArticles[]->{date,badge,title,slug,authors[]->{firstName, lastName}},relatedCommentary[]->,featuredPosts[]->{_id, title, author, badge, date, featuredImage, category, date, type, slug, stackbit_model_type},projectTopics[]->{_id}}` ); let path; @@ -83,6 +83,11 @@ export async function getStaticProps(props) { const articlesQuery = `*[!(_id in path("drafts.**")) && _type == "post"]{ title, date, slug, badge, 'key': slug } | order(date desc)`; articles = await client.fetch(articlesQuery); + } else if (page && page.layout === "project") { + const refs = page.projectTopics.map((ref) => `references("${ref._id}")`).join(" || "); + articles = await client.fetch( + `*[!(_id in path("drafts.**")) && (${refs}) && _type=="post"]{ _id, title, slug, featuredImage, date, badge } | order(date desc)[0...20]` + ) } return { @@ -91,6 +96,7 @@ export async function getStaticProps(props) { articles: articles.length ? articles : null, _type: page ? page._type : null, authors: authors.length ? authors : null, + featured: page ? page.featuredPosts : null, path: path, data: { config, topics }, }, diff --git a/studio/schemas/advanced.js b/studio/schemas/advanced.js index bfd31170..bfda2be2 100644 --- a/studio/schemas/advanced.js +++ b/studio/schemas/advanced.js @@ -10,29 +10,43 @@ export default { description: 'The title of the page.', validation: (Rule) => Rule.required(), }, + { + type: 'string', + name: 'layout', + title: 'Layout', + hidden: false, + validation: (Rule) => Rule.required(), + options: { + list: [{ title: 'Advanced', value: 'advanced' }, { title: 'Special Project', value: 'project' }], + }, + }, { type: 'string', name: 'heroContent', title: 'Hero Content', description: 'The text in the page hero.', + hidden: ({document}) => document?.layout !== 'advanced', }, { type: 'string', name: 'heroLinkText', title: 'Hero Link Text', description: 'The text displayed on the hero link.', + hidden: ({document}) => document?.layout !== 'advanced', }, { type: 'string', name: 'heroLinkUrl', title: 'Hero Link URL', description: 'The URL for the hero link.', + hidden: ({document}) => document?.layout !== 'advanced', }, { type: 'text', name: 'trackerText', title: 'Policy tracker intro text', - description: 'Add the introduction text for the Policy Tracker for the homepage' + description: 'Add the introduction text for the Policy Tracker for the homepage', + hidden: ({document}) => document?.layout !== 'advanced', }, // { // name: "featuredTopics", @@ -87,6 +101,37 @@ export default { type: 'section_podcast', }, ], + hidden: ({document}) => document?.layout !== 'advanced', + }, + { + title: 'Project topics', + name: 'projectTopics', + type: 'array', + of: [ + { + type: 'reference', + to: [{ type: 'topic' }], + options: { + disableNew: true, + }, + }, + ], + hidden: ({document}) => document?.layout !== 'project', + }, + { + type: 'array', + name: 'featuredPosts', + of: [ + { + title: 'Posts', + type: 'reference', + to: [{type: 'post'}], + options: { + disableNew: true, + }, + }, + ], + hidden: ({document}) => document?.layout !== 'project', }, { type: 'string', @@ -101,16 +146,6 @@ export default { title: 'Seo', validation: null, }, - { - type: 'string', - name: 'layout', - title: 'Layout', - hidden: false, - validation: (Rule) => Rule.required(), - options: { - list: ['advanced'], - }, - }, { type: 'string', name: 'stackbit_url_path', From 4c2556e634925703e76b805c198923e07fcfffca Mon Sep 17 00:00:00 2001 From: "rich.jdev00" Date: Fri, 18 Jul 2025 23:15:28 +0400 Subject: [PATCH 2/4] Update for Special Page posts and 'More' link --- .../SpecialProjects/MoreArticles.js | 42 ++++++++++++++++++- src/layouts/advanced.js | 5 ++- src/pages/[...slug].js | 2 +- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/components/SpecialProjects/MoreArticles.js b/src/components/SpecialProjects/MoreArticles.js index b49a6c01..f1594e94 100644 --- a/src/components/SpecialProjects/MoreArticles.js +++ b/src/components/SpecialProjects/MoreArticles.js @@ -57,6 +57,7 @@ const useStyles = makeStyles((theme) => ({ }, grid: { marginTop: 20, + marginBottom: 60, }, gridTitle: { borderBottom: "1px solid #000", @@ -83,9 +84,11 @@ const useStyles = makeStyles((theme) => ({ }, })); -function MoreArticles({ articles }) { +function MoreArticles({ articles, topics }) { const classes = useStyles(); + console.log(topics); + return ( @@ -144,12 +147,49 @@ function MoreArticles({ articles }) { )) : null} + {topics && topics.length > 0 && ( + + + + View more + + + + )} ); } MoreArticles.propTypes = { articles: PropTypes.array, + topics: PropTypes.array, }; export default MoreArticles; diff --git a/src/layouts/advanced.js b/src/layouts/advanced.js index b35671ec..e4dff6f6 100644 --- a/src/layouts/advanced.js +++ b/src/layouts/advanced.js @@ -226,7 +226,10 @@ const Advanced = (props) => { - + ) : ( diff --git a/src/pages/[...slug].js b/src/pages/[...slug].js index 58280895..743544dd 100644 --- a/src/pages/[...slug].js +++ b/src/pages/[...slug].js @@ -86,7 +86,7 @@ export async function getStaticProps(props) { } else if (page && page.layout === "project") { const refs = page.projectTopics.map((ref) => `references("${ref._id}")`).join(" || "); articles = await client.fetch( - `*[!(_id in path("drafts.**")) && (${refs}) && _type=="post"]{ _id, title, slug, featuredImage, date, badge } | order(date desc)[0...20]` + `*[!(_id in path("drafts.**")) && (${refs}) && _type=="post"]{ _id, title, slug, featuredImage, date, badge } | order(date desc)[0...29]` ) } From fce2de228faab7167a7e5932c1a9e62ec90ba39c Mon Sep 17 00:00:00 2001 From: "rich.jdev00" Date: Fri, 18 Jul 2025 23:16:39 +0400 Subject: [PATCH 3/4] Remove console debug --- src/components/SpecialProjects/MoreArticles.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/SpecialProjects/MoreArticles.js b/src/components/SpecialProjects/MoreArticles.js index f1594e94..607e5ef6 100644 --- a/src/components/SpecialProjects/MoreArticles.js +++ b/src/components/SpecialProjects/MoreArticles.js @@ -87,8 +87,6 @@ const useStyles = makeStyles((theme) => ({ function MoreArticles({ articles, topics }) { const classes = useStyles(); - console.log(topics); - return ( From 8ff1943932be8b2ee8caf4c63e4ed842e348f33a Mon Sep 17 00:00:00 2001 From: "rich.jdev00" Date: Fri, 25 Jul 2025 21:24:38 +0400 Subject: [PATCH 4/4] Update More articles grid --- .../SpecialProjects/MoreArticles.js | 104 +++++++++--------- 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/src/components/SpecialProjects/MoreArticles.js b/src/components/SpecialProjects/MoreArticles.js index 607e5ef6..22b4470d 100644 --- a/src/components/SpecialProjects/MoreArticles.js +++ b/src/components/SpecialProjects/MoreArticles.js @@ -12,6 +12,7 @@ import Badge from "../Badge"; const useStyles = makeStyles((theme) => ({ article: { + paddingTop: "0!important", marginBottom: 20, }, lastArticle: { @@ -87,6 +88,51 @@ const useStyles = makeStyles((theme) => ({ function MoreArticles({ articles, topics }) { const classes = useStyles(); + const drawArticle = (article) => { + return ( + + + + {article.badge && } + + + {article.title} + + + + {DateTime.fromISO(article.date) + .setZone("America/New_York") + .setLocale("en-us") + .toLocaleString(DateTime.DATE_FULL)} + + + + + ); + }; + + const columns = [[], [], []]; + + articles.forEach((article, index) => { + columns[index % 3].push(article); + }); + return ( @@ -94,56 +140,14 @@ function MoreArticles({ articles, topics }) { More - - {articles && articles.length - ? articles.map((article) => ( - - - - {article.badge && ( - - )} - - - {article.title} - - - - {DateTime.fromISO(article.date) - .setZone("America/New_York") - .setLocale("en-us") - .toLocaleString(DateTime.DATE_FULL)} - - - - - )) - : null} + + {columns.map((col, colIndex) => ( + + + {col.map((article) => drawArticle(article))} + + + ))} {topics && topics.length > 0 && (