gatsby-attainlabs-cms 1.0.26 → 1.0.28

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,8 +27,8 @@ 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";
31
+ import Layout from "../${isNested && "../"}layouts/${layout}";
32
32
 
33
33
 
34
34
 
@@ -40,9 +40,9 @@ const generatePage = async (blocks, layout) => {
40
40
 
41
41
  const Page = ({pageContext}:any ) => {
42
42
  return (
43
- <>
43
+ <div sx={{bg:"white"}}>
44
44
  ${generateSlices(blocks)}
45
- </>
45
+ </div>
46
46
  );
47
47
  };
48
48
 
@@ -301,6 +301,7 @@ exports.sourceNodes = async (
301
301
  );
302
302
  return; // stop execution early
303
303
  }
304
+
304
305
  if (!brand || !businessUnitId) {
305
306
  console.warn(
306
307
  "⚠️ [gatsby-attainlabs-cms] Invalid or missing 'brand' option for Trustpilot integration. " +
@@ -310,6 +311,10 @@ exports.sourceNodes = async (
310
311
  return; // stop execution early
311
312
  }
312
313
 
314
+ console.log(
315
+ `ℹ️ [gatsby-attainlabs-cms] Fetching Firebase Blogs Data brand: ${brand}`
316
+ );
317
+
313
318
  const fetchTrustpilotData = async (endpoint) => {
314
319
  try {
315
320
  const response = await fetch(
@@ -344,7 +349,7 @@ exports.sourceNodes = async (
344
349
  recentReviews: recentReviewsData || {},
345
350
  };
346
351
 
347
- return createNode({
352
+ createNode({
348
353
  ...combinedData,
349
354
  id: createNodeId("trustPilotReviews"),
350
355
  parent: null,
@@ -356,16 +361,31 @@ exports.sourceNodes = async (
356
361
  }
357
362
 
358
363
  // 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());
364
+
365
+ const fetchBlogData = async () => {
366
+ try {
367
+ const response = await fetch(
368
+ `https://attain-finance-cms-default-rtdb.firebaseio.com/cms/brands/${brands[brand]}/pages.json`
369
+ );
370
+ if (!response.ok) {
371
+ throw new Error(`HTTP error! status: ${response.status}`);
372
+ }
373
+
374
+ return await response.json();
375
+ } catch (error) {
376
+ console.error(`Failed to fetch data from Firebase`, error.message);
377
+ return null;
378
+ }
379
+ };
380
+
381
+ const firebaseData = await fetchBlogData();
362
382
 
363
383
  const allBlogs = [];
364
384
 
365
385
  for (const [key, value] of Object.entries(firebaseData)) {
366
386
  const category =
367
- value?.draft?.blocks?.root?.props?.category.type ||
368
- value?.blocks?.root?.props?.category.type;
387
+ value?.draft?.blocks?.root?.props?.category ||
388
+ value?.blocks?.root?.props?.category;
369
389
 
370
390
  if (category === "blog") {
371
391
  allBlogs.push(value);
@@ -374,8 +394,8 @@ exports.sourceNodes = async (
374
394
  if (value.hasOwnProperty("children")) {
375
395
  for (const [childKey, childValue] of Object.entries(value["children"])) {
376
396
  const childCategory =
377
- childValue?.draft?.blocks?.root?.props?.category.type ||
378
- childValue?.blocks?.root?.props?.category.type;
397
+ childValue?.draft?.blocks?.root?.props?.category ||
398
+ childValue?.blocks?.root?.props?.category;
379
399
 
380
400
  if (childCategory === "blog") {
381
401
  allBlogs.push(childValue);
@@ -392,7 +412,7 @@ exports.sourceNodes = async (
392
412
  parent: null,
393
413
  children: [],
394
414
  internal: {
395
- type: "Blog",
415
+ type: "Blogs",
396
416
  contentDigest: createContentDigest(blog),
397
417
  },
398
418
  };
@@ -424,8 +444,32 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
424
444
  const firebaseData = await fetch(
425
445
  `https://attain-finance-cms-default-rtdb.firebaseio.com/cms/brands/${brands[brand]}/pages.json`
426
446
  );
447
+
427
448
  const firebaseJson = await firebaseData.json();
428
- for (const page of Object.values(firebaseJson)) {
449
+
450
+ async function processPage(page, parentPath = "") {
451
+ // Check for folderUrl first — handle nested folders immediately
452
+ if (
453
+ page.folderUrl &&
454
+ page.children &&
455
+ Object.keys(page.children).length > 0
456
+ ) {
457
+ // use folderUrl instead of pageUrl for folder structure
458
+ const folderPath = parentPath
459
+ ? path.join(parentPath, page.folderUrl)
460
+ : page.folderUrl;
461
+ const folderFullPath = path.join(siteRoot, "src/cms/pages", folderPath);
462
+
463
+ await fse.ensureDir(folderFullPath);
464
+
465
+ for (const child of Object.values(page.children)) {
466
+ await processPage(child, folderPath);
467
+ }
468
+
469
+ return; // Stop here for folders — no page created for folder node
470
+ }
471
+
472
+ // 🧩 Step 2: Process actual pages (no folderUrl)
429
473
  if (page.template === "visual-editor" && page.published) {
430
474
  const {
431
475
  blocks: {
@@ -437,13 +481,12 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
437
481
  id,
438
482
  } = page;
439
483
 
440
- //Generate page's blocks slices
484
+ // Create slice for each block
441
485
  await Promise.all(
442
486
  content.map(async (b) => {
443
487
  const name = b.props.component.name;
444
488
  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
489
+
447
490
  createSlice({
448
491
  id: sliceId,
449
492
  component: path.resolve(
@@ -455,28 +498,28 @@ exports.createPages = async ({ actions, store }, pluginOptions) => {
455
498
  ...b.props,
456
499
  },
457
500
  });
458
- b["sliceId"] = sliceId; // attach sliceId to block for later use
501
+
502
+ b["sliceId"] = sliceId;
459
503
  return b;
460
504
  })
461
505
  );
462
506
 
463
- const pageSource = await generatePage(content, layout);
464
- const outPath = path.join(siteRoot, "src/cms/pages", `${pageUrl}.tsx`);
507
+ // Generate page file
508
+ const pageSource = await generatePage(content, layout, parentPath);
509
+ const folderPath = parentPath ? path.join(parentPath, pageUrl) : pageUrl;
510
+ const outPath = path.join(siteRoot, "src/cms/pages", `${folderPath}.tsx`);
465
511
 
466
512
  await fse.outputFile(outPath, pageSource);
513
+
467
514
  await createPage({
468
- path: pageUrl === "index" ? `/` : `/${pageUrl}`,
469
- component: outPath, // ✅ a file path string
470
- context: {
471
- ...page,
472
- },
515
+ path: folderPath === "index" ? `/` : `/${folderPath}`,
516
+ component: outPath,
517
+ context: { ...page },
473
518
  });
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
519
  }
481
520
  }
521
+
522
+ for (const page of Object.values(firebaseJson)) {
523
+ await processPage(page);
524
+ }
482
525
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-attainlabs-cms",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
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
  `;