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.
- package/dist/sliceWrapper.js +71 -1
- package/gatsby-node.js +75 -32
- package/package.json +1 -1
- package/src/sliceWrapper.tsx +71 -0
package/dist/sliceWrapper.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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
|
|
368
|
-
value?.blocks?.root?.props?.category
|
|
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
|
|
378
|
-
childValue?.blocks?.root?.props?.category
|
|
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: "
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
501
|
+
|
|
502
|
+
b["sliceId"] = sliceId;
|
|
459
503
|
return b;
|
|
460
504
|
})
|
|
461
505
|
);
|
|
462
506
|
|
|
463
|
-
|
|
464
|
-
const
|
|
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:
|
|
469
|
-
component: outPath,
|
|
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
package/src/sliceWrapper.tsx
CHANGED
|
@@ -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
|
`;
|