gatsby-attainlabs-cms 1.0.27 → 1.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,14 @@ export default function SliceWrapper({ sliceContext, data, }) {
12
12
  console.warn(`Component "${pathFormatted}" not found in CMS_COMPONENTS`);
13
13
  return null;
14
14
  }
15
- return (_jsx(Component, { ...props, trustPilotData: data.allTrustPilotReviews.edges[0].node }));
15
+ return (_jsx(Component, { ...props, trustPilotData: data.allTrustPilotReviews.edges[0].node, blogs: {
16
+ sliderBlogs: {
17
+ ...data.sliderBlogs,
18
+ },
19
+ allBlogs: {
20
+ ...data.allBlogs,
21
+ },
22
+ } }));
16
23
  }
17
24
  export const TrustPilotQuery = graphql `
18
25
  query {
@@ -47,5 +54,68 @@ export const TrustPilotQuery = graphql `
47
54
  }
48
55
  }
49
56
  }
57
+ allBlogs: allBlogs {
58
+ edges {
59
+ node {
60
+ blocks {
61
+ content {
62
+ props {
63
+ content {
64
+ props {
65
+ text
66
+ image {
67
+ desktop {
68
+ url
69
+ }
70
+ }
71
+ }
72
+ # type
73
+ }
74
+ }
75
+ }
76
+ root {
77
+ props {
78
+ author
79
+ datePublished
80
+ pageUrl
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ sliderBlogs: allBlogs(
88
+ limit: 9
89
+ sort: { blocks: { root: { props: { datePublished: DESC } } } }
90
+ ) {
91
+ edges {
92
+ node {
93
+ blocks {
94
+ content {
95
+ props {
96
+ content {
97
+ props {
98
+ text
99
+ image {
100
+ desktop {
101
+ url
102
+ }
103
+ }
104
+ }
105
+ # type
106
+ }
107
+ }
108
+ }
109
+ root {
110
+ props {
111
+ author
112
+ datePublished
113
+ pageUrl
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
50
120
  }
51
121
  `;
package/gatsby-node.js CHANGED
@@ -12,7 +12,7 @@ const brands = {
12
12
  "Attain Finance": "attainfinance",
13
13
  };
14
14
 
15
- const generatePage = async (blocks, layout) => {
15
+ const generatePage = async (blocks, layout, isNested) => {
16
16
  // Validate input parameters
17
17
  if (!Array.isArray(blocks)) {
18
18
  throw new Error("Invalid parameters passed to createPage.");
@@ -27,22 +27,21 @@ const generatePage = async (blocks, layout) => {
27
27
  const pageContent = `
28
28
  /* This is a generated file by the gatsby-attainlabs-cms plugin. Any changes will be overwritten on the next build. */
29
29
  import { Slice } from "gatsby";
30
- import SEO from "../components/SEO";
31
- import Layout from "../layouts/${layout}";
30
+ import SEO from "../${isNested && "../"}components/SEO";
32
31
 
33
32
 
34
33
 
35
34
  export const Head = ({ pageContext }: any) => {
36
35
  const blocks = pageContext.blocks || { root: { props: { meta: {} } } };
37
36
  const { title, description } = blocks.root.props.meta;
38
- return <SEO title={title} description={description} noIndex={true} />;
37
+ return <SEO title={title || ""} description={description || ""} noIndex={true} />;
39
38
  };
40
39
 
41
40
  const Page = ({pageContext}:any ) => {
42
41
  return (
43
- <>
42
+ <div sx={{bg:"white"}}>
44
43
  ${generateSlices(blocks)}
45
- </>
44
+ </div>
46
45
  );
47
46
  };
48
47
 
@@ -301,6 +300,7 @@ exports.sourceNodes = async (
301
300
  );
302
301
  return; // stop execution early
303
302
  }
303
+
304
304
  if (!brand || !businessUnitId) {
305
305
  console.warn(
306
306
  "⚠️ [gatsby-attainlabs-cms] Invalid or missing 'brand' option for Trustpilot integration. " +
@@ -310,6 +310,10 @@ exports.sourceNodes = async (
310
310
  return; // stop execution early
311
311
  }
312
312
 
313
+ console.log(
314
+ `ℹ️ [gatsby-attainlabs-cms] Fetching Firebase Blogs Data brand: ${brand}`
315
+ );
316
+
313
317
  const fetchTrustpilotData = async (endpoint) => {
314
318
  try {
315
319
  const response = await fetch(
@@ -344,7 +348,7 @@ exports.sourceNodes = async (
344
348
  recentReviews: recentReviewsData || {},
345
349
  };
346
350
 
347
- return createNode({
351
+ createNode({
348
352
  ...combinedData,
349
353
  id: createNodeId("trustPilotReviews"),
350
354
  parent: null,
@@ -356,16 +360,31 @@ exports.sourceNodes = async (
356
360
  }
357
361
 
358
362
  // Blogs node creation
359
- const firebaseData = await fetch(
360
- `https://attain-finance-cms-default-rtdb.firebaseio.com/cms/brands/lenddirect/pages.json`
361
- ).then((res) => res.json());
363
+
364
+ const fetchBlogData = async () => {
365
+ try {
366
+ const response = await fetch(
367
+ `https://attain-finance-cms-default-rtdb.firebaseio.com/cms/brands/${brands[brand]}/pages.json`
368
+ );
369
+ if (!response.ok) {
370
+ throw new Error(`HTTP error! status: ${response.status}`);
371
+ }
372
+
373
+ return await response.json();
374
+ } catch (error) {
375
+ console.error(`Failed to fetch data from Firebase`, error.message);
376
+ return null;
377
+ }
378
+ };
379
+
380
+ const firebaseData = await fetchBlogData();
362
381
 
363
382
  const allBlogs = [];
364
383
 
365
384
  for (const [key, value] of Object.entries(firebaseData)) {
366
385
  const category =
367
- value?.draft?.blocks?.root?.props?.category.type ||
368
- value?.blocks?.root?.props?.category.type;
386
+ value?.draft?.blocks?.root?.props?.category ||
387
+ value?.blocks?.root?.props?.category;
369
388
 
370
389
  if (category === "blog") {
371
390
  allBlogs.push(value);
@@ -374,8 +393,8 @@ exports.sourceNodes = async (
374
393
  if (value.hasOwnProperty("children")) {
375
394
  for (const [childKey, childValue] of Object.entries(value["children"])) {
376
395
  const childCategory =
377
- childValue?.draft?.blocks?.root?.props?.category.type ||
378
- childValue?.blocks?.root?.props?.category.type;
396
+ childValue?.draft?.blocks?.root?.props?.category ||
397
+ childValue?.blocks?.root?.props?.category;
379
398
 
380
399
  if (childCategory === "blog") {
381
400
  allBlogs.push(childValue);
@@ -424,8 +443,32 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
424
443
  const firebaseData = await fetch(
425
444
  `https://attain-finance-cms-default-rtdb.firebaseio.com/cms/brands/${brands[brand]}/pages.json`
426
445
  );
446
+
427
447
  const firebaseJson = await firebaseData.json();
428
- for (const page of Object.values(firebaseJson)) {
448
+
449
+ async function processPage(page, parentPath = "") {
450
+ // Check for folderUrl first — handle nested folders immediately
451
+ if (
452
+ page.folderUrl &&
453
+ page.children &&
454
+ Object.keys(page.children).length > 0
455
+ ) {
456
+ // use folderUrl instead of pageUrl for folder structure
457
+ const folderPath = parentPath
458
+ ? path.join(parentPath, page.folderUrl)
459
+ : page.folderUrl;
460
+ const folderFullPath = path.join(siteRoot, "src/cms/pages", folderPath);
461
+
462
+ await fse.ensureDir(folderFullPath);
463
+
464
+ for (const child of Object.values(page.children)) {
465
+ await processPage(child, folderPath);
466
+ }
467
+
468
+ return; // Stop here for folders — no page created for folder node
469
+ }
470
+
471
+ // 🧩 Step 2: Process actual pages (no folderUrl)
429
472
  if (page.template === "visual-editor" && page.published) {
430
473
  const {
431
474
  blocks: {
@@ -437,13 +480,12 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
437
480
  id,
438
481
  } = page;
439
482
 
440
- //Generate page's blocks slices
483
+ // Create slice for each block
441
484
  await Promise.all(
442
485
  content.map(async (b) => {
443
486
  const name = b.props.component.name;
444
487
  const sliceId = `block--${pageUrl}--${name}--${id}--${crypto.randomUUID()}`;
445
- // console.log(`Creating slice: ${sliceId}`);
446
- // here we could await something per slice if needed later
488
+
447
489
  createSlice({
448
490
  id: sliceId,
449
491
  component: path.resolve(
@@ -455,28 +497,30 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
455
497
  ...b.props,
456
498
  },
457
499
  });
458
- b["sliceId"] = sliceId; // attach sliceId to block for later use
500
+
501
+ b["sliceId"] = sliceId;
459
502
  return b;
460
503
  })
461
504
  );
462
505
 
463
- const pageSource = await generatePage(content, layout);
464
- const outPath = path.join(siteRoot, "src/cms/pages", `${pageUrl}.tsx`);
506
+ // Generate page file
507
+ const pageSource = await generatePage(content, layout, parentPath);
508
+ const folderPath = parentPath ? path.join(parentPath, pageUrl) : pageUrl;
509
+ const outPath = path.join(siteRoot, "src/cms/pages", `${folderPath}.tsx`);
465
510
 
466
511
  await fse.outputFile(outPath, pageSource);
512
+
467
513
  await createPage({
468
- path: pageUrl === "index" ? `/` : `/${pageUrl}`,
469
- component: outPath, // ✅ a file path string
470
- context: {
471
- ...page,
472
- },
514
+ path: folderPath.endsWith("/index")
515
+ ? `/${parentPath}`
516
+ : `/${folderPath}`,
517
+ component: outPath,
518
+ context: { ...page },
473
519
  });
474
-
475
- // const pageSource = await generatePage(content, pageUrl);
476
- // const outPath = path.join(siteRoot, "src/pages", `${pageUrl}.tsx`);
477
- // // Generate the page itself
478
- // await fse.outputFile(outPath, pageSource);
479
- // console.log(`✅ Wrote page to ${outPath}`);
480
520
  }
481
521
  }
522
+
523
+ for (const page of Object.values(firebaseJson)) {
524
+ await processPage(page);
525
+ }
482
526
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-attainlabs-cms",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,6 +31,14 @@ export default function SliceWrapper({
31
31
  <Component
32
32
  {...props}
33
33
  trustPilotData={data.allTrustPilotReviews.edges[0].node}
34
+ blogs={{
35
+ sliderBlogs: {
36
+ ...data.sliderBlogs,
37
+ },
38
+ allBlogs: {
39
+ ...data.allBlogs,
40
+ },
41
+ }}
34
42
  />
35
43
  );
36
44
  }
@@ -68,5 +76,68 @@ export const TrustPilotQuery = graphql`
68
76
  }
69
77
  }
70
78
  }
79
+ allBlogs: allBlogs {
80
+ edges {
81
+ node {
82
+ blocks {
83
+ content {
84
+ props {
85
+ content {
86
+ props {
87
+ text
88
+ image {
89
+ desktop {
90
+ url
91
+ }
92
+ }
93
+ }
94
+ # type
95
+ }
96
+ }
97
+ }
98
+ root {
99
+ props {
100
+ author
101
+ datePublished
102
+ pageUrl
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ sliderBlogs: allBlogs(
110
+ limit: 9
111
+ sort: { blocks: { root: { props: { datePublished: DESC } } } }
112
+ ) {
113
+ edges {
114
+ node {
115
+ blocks {
116
+ content {
117
+ props {
118
+ content {
119
+ props {
120
+ text
121
+ image {
122
+ desktop {
123
+ url
124
+ }
125
+ }
126
+ }
127
+ # type
128
+ }
129
+ }
130
+ }
131
+ root {
132
+ props {
133
+ author
134
+ datePublished
135
+ pageUrl
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
71
142
  }
72
143
  `;