Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 85 additions & 51 deletions gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,18 @@ const slugify = require("./src/utils/slugify");
const { paginate } = require("gatsby-awesome-pagination");
const { createFilePath } = require("gatsby-source-filesystem");
const config = require("./gatsby-config");
const {
componentsData,
} = require("./src/sections/Projects/Sistent/components/content");

const HEAVY_COLLECTIONS = new Set(["members", "integrations"]);
const isFullSiteBuild = process.env.BUILD_FULL_SITE !== "false";
const shouldIncludeCollection = (collection) => isFullSiteBuild || !HEAVY_COLLECTIONS.has(collection);
const shouldIncludeCollection = (collection) =>
isFullSiteBuild || !HEAVY_COLLECTIONS.has(collection);

const { loadRedirects } = require("./src/utils/redirects.js");

exports.createPages = async ({ actions, graphql, reporter }) => {
const { createRedirect } = actions;
const redirects = loadRedirects();
redirects.forEach(redirect => createRedirect(redirect)); // Handles all hardcoded ones dynamically
redirects.forEach((redirect) => createRedirect(redirect)); // Handles all hardcoded ones dynamically
// Create Pages
const { createPage } = actions;

Expand All @@ -49,7 +47,7 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

const blogPostTemplate = path.resolve("src/templates/blog-single.js");
const blogCategoryListTemplate = path.resolve(
"src/templates/blog-category-list.js"
"src/templates/blog-category-list.js",
);
const blogTagListTemplate = path.resolve("src/templates/blog-tag-list.js");

Expand All @@ -64,7 +62,7 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
const ProgramPostTemplate = path.resolve("src/templates/program-single.js");

const MultiProgramPostTemplate = path.resolve(
"src/templates/program-multiple.js"
"src/templates/program-multiple.js",
);

const CareerPostTemplate = path.resolve("src/templates/career-single.js");
Expand All @@ -79,7 +77,9 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

const resourcePostTemplate = path.resolve("src/templates/resource-single.js");
const integrationTemplate = path.resolve("src/templates/integrations.js");
const LitePlaceholderTemplate = path.resolve("src/templates/lite-placeholder.js");
const LitePlaceholderTemplate = path.resolve(
"src/templates/lite-placeholder.js",
);

const memberBioQuery = isFullSiteBuild
? `
Expand Down Expand Up @@ -108,7 +108,6 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

const HandbookTemplate = path.resolve("src/templates/handbook-template.js");


const res = await graphql(`
{
allPosts: allMdx(filter: { frontmatter: { published: { eq: true } } }) {
Expand Down Expand Up @@ -210,6 +209,25 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
}
}
}
sistentComponents: allMdx(
filter: {
fields: { collection: { eq: "sistent" } }
}
) {
group(field: { fields: { componentName: SELECT } }) {
fieldValue
nodes {
fields {
slug
componentName
pageType
}
internal {
contentFilePath
}
}
}
}
}
`);

Expand Down Expand Up @@ -241,7 +259,6 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

const handbook = res.data.handbookPages.nodes;


const singleWorkshop = res.data.singleWorkshop.nodes;
const labs = res.data.labs.nodes;

Expand Down Expand Up @@ -413,7 +430,6 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
});
});


programs.forEach((program) => {
envCreatePage({
path: `/programs/${program.frontmatter.programSlug}`,
Expand Down Expand Up @@ -452,7 +468,7 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
envCreatePage({
...page,
component: LitePlaceholderTemplate,
})
}),
);

const graphqlPlaceholderPages = [
Expand Down Expand Up @@ -511,35 +527,29 @@ exports.createPages = async ({ actions, graphql, reporter }) => {
}
});

const components = componentsData.map((component) => component.src.replace("/", ""));
const createComponentPages = (createPage, components) => {
const pageTypes = [
{ suffix: "", file: "index.js" },
{ suffix: "/guidance", file: "guidance.js" },
{ suffix: "/code", file: "code.js" },
];
// Create Sistent component pages dynamically from MDX
// Use grouping to identify which sub-pages (Tabs) exist for each component
const sistentGroups = res.data.sistentComponents.group;
const sistentTemplate = path.resolve("src/templates/sistent-component.js");

components.forEach((name) => {
pageTypes.forEach(({ suffix, file }) => {
const pagePath = `/projects/sistent/components/${name}${suffix}`;
const componentPath = `./src/sections/Projects/Sistent/components/${name}/${file}`;
if (fs.existsSync(path.resolve(componentPath))) {
try {
createPage({
path: pagePath,
component: require.resolve(componentPath),
});
} catch (error) {
console.error(`Error creating page for "${pagePath}":`, error);
}
} else {
console.info(`Skipping creating page "${pagePath}" - file not found: "${componentPath}"`);
}
sistentGroups.forEach((group) => {
const componentName = group.fieldValue;
// content-learn uses different fields, sistent uses componentName.

const availablePages = group.nodes.map((node) => node.fields.pageType);

group.nodes.forEach((node) => {
createPage({
path: node.fields.slug,
component: `${sistentTemplate}?__contentFilePath=${node.internal.contentFilePath}`,
context: {
slug: node.fields.slug,
componentName: componentName,
availablePages: availablePages,
},
});
});
};

createComponentPages(createPage, components);
});
};

// slug starts and ends with '/' so parts[0] and parts[-1] will be empty
Expand Down Expand Up @@ -626,13 +636,11 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
const parent = getNode(node.parent);
let collection = parent.sourceInstanceName;

// --- CHANGED: Consolidated Source Logic ---
// If the source is "collections", we determine the actual collection
// from the parent directory name (e.g., "blog", "news", etc.)
if (collection === "collections") {
collection = parent.relativeDirectory.split("/")[0];
}
// ------------------------------------------

createNodeField({
name: "collection",
Expand All @@ -649,7 +657,7 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
case "blog":
if (node.frontmatter.published)
slug = `/${collection}/${slugify(
node.frontmatter.category
node.frontmatter.category,
)}/${slugify(node.frontmatter.title)}`;
break;
case "news":
Expand All @@ -660,11 +668,11 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
case "kanvas-labs":
slug = `/learn/${collection}/${slugify(node.frontmatter.title)}`;
break;
case "resources":
if (node.frontmatter.published)
slug = `/${collection}/${slugify(
node.frontmatter.category
)}/${slugify(node.frontmatter.title)}`;
case "resources":
if (node.frontmatter.published)
slug = `/${collection}/${slugify(
node.frontmatter.category,
)}/${slugify(node.frontmatter.title)}`;
break;
case "members":
if (node.frontmatter.published)
Expand All @@ -677,6 +685,29 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
if (node.frontmatter.title)
slug = `/community/events/${slugify(node.frontmatter.title)}`;
break;
case "sistent": {
// For sistent components, create slug from directory structure
const componentSlug = parent.relativeDirectory.split("/").pop();
const fileName = parent.name;
const suffix = fileName === "index" ? "" : `/${fileName}`;

slug = `/projects/sistent/components/${componentSlug}${suffix}`;

createNodeField({
name: "componentName",
node,
value: componentSlug,
});

// "index" -> "overview", others match filename
const pageType = fileName === "index" ? "overview" : fileName;
createNodeField({
name: "pageType",
node,
value: pageType,
});
break;
}
default:
slug = `/${collection}/${slugify(node.frontmatter.title)}`;
}
Expand Down Expand Up @@ -800,11 +831,16 @@ exports.onCreateWebpackConfig = ({ actions, stage, getConfig }) => {
});

// Reduce memory pressure by disabling sourcemaps in dev and build
if (stage === "develop" || stage === "develop-html" || stage === "build-javascript" || stage === "build-html") {
if (
stage === "develop" ||
stage === "develop-html" ||
stage === "build-javascript" ||
stage === "build-html"
) {
const config = getConfig();
config.devtool = false;
const miniCssExtractPlugin = config.plugins.find(
(plugin) => plugin.constructor.name === "MiniCssExtractPlugin"
(plugin) => plugin.constructor.name === "MiniCssExtractPlugin",
);

if (miniCssExtractPlugin) {
Expand Down Expand Up @@ -881,8 +917,6 @@ exports.createSchemaCustomization = ({ actions }) => {
createTypes(typeDefs);
};



exports.onPostBuild = async ({ graphql, reporter }) => {
const result = await graphql(`
{
Expand Down Expand Up @@ -911,4 +945,4 @@ exports.onPostBuild = async ({ graphql, reporter }) => {
// Optionally, write the result to a file for easier inspection
const outputPath = path.resolve(__dirname, "public", "query-result.json");
fs.writeFileSync(outputPath, JSON.stringify(result, null, 2));
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState } from "react";
import { Accordion, AccordionSummary, AccordionDetails, Typography } from "@sistent/sistent";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";

const ControlledAccordion = () => {
const [expanded, setExpanded] = useState("panel1");

const handleChange = (panel) => (event, isExpanded) => {
setExpanded(isExpanded ? panel : false);
};

return (
<div style={{ width: "100%" }}>
<Accordion expanded={expanded === "panel1"} onChange={handleChange("panel1")}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1bh-content"
id="panel1bh-header"
>
<Typography>
General settings
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Controlled accordions manage their expanded state through React, allowing only one panel to be open at a time. This creates a cleaner, more focused user experience by preventing multiple sections from being visible simultaneously.
</Typography>
</AccordionDetails>
</Accordion>
<Accordion expanded={expanded === "panel2"} onChange={handleChange("panel2")}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2bh-content"
id="panel2bh-header"
>
<Typography>Users</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
When expanding this panel, the previously opened panel automatically collapses. This behavior is ideal for settings pages, configuration panels, and any interface where you want users to focus on one section at a time.
</Typography>
</AccordionDetails>
</Accordion>
<Accordion expanded={expanded === "panel3"} onChange={handleChange("panel3")}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel3bh-content"
id="panel3bh-header"
>
<Typography>
Advanced settings
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
Accordions help organize complex information into digestible sections. They reduce cognitive load by hiding content until users actively choose to reveal it, making interfaces feel less overwhelming and more navigable.
</Typography>
</AccordionDetails>
</Accordion>
</div>
);
};

export default ControlledAccordion;
Loading