Skip to content

Commit

Permalink
Initial Puck and Drupal configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviemirmon committed Apr 12, 2024
1 parent e7dbc68 commit 3a62b55
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 346 deletions.
1 change: 1 addition & 0 deletions .docksal/docksal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ services:
- DRUPAL_CLIENT_SECRET
- DRUPAL_PREVIEW_SECRET
- NEXT_REVALIDATE_SECRET
- VIRTUAL_HOST
working_dir: /var/www/frontend
# Optionally run in debug mode by setting PREVIEW_START_COMMAND to "npm run debug"
command: [ "bash", "-lc", "yarn workspace ${FRONTEND_STARTER} dev" ]
Expand Down
7 changes: 1 addition & 6 deletions .docksal/start/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@
padding: 2rem;
">
<h1>Dashboard</h1>

<p>Welcome to your new DXP!</p>
<p>Click <a href="http://frontend.<?php echo getenv('VIRTUAL_HOST') ?>/admin/login">here</a> to login.</p>

<H2>Services</H2>
<div style="
grid-template-columns: 1fr 1fr;
Expand Down Expand Up @@ -151,7 +147,6 @@
setInterval(function(){
statuses.forEach(function(status) {
fetch(status.dataset.service_url, { method: 'HEAD' } ).then(function(response) {
console.log(response.status); // returns 200
if(response.ok) {
document.getElementById(status.id).innerHTML = " - Up";
} else {
Expand All @@ -161,7 +156,7 @@
document.getElementById(status.id).innerHTML = " - Down";
});
});
}, 5000);
}, 2000);


</script>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export const drupalFieldPrefix = "field_"

export const formatDrupalField = (type) => type.replace(drupalFieldPrefix, "")

export const formatDrupalType = (type) => type.replace("paragraph--", "")

export const snakeToCamel = (text) =>
Expand Down
2 changes: 1 addition & 1 deletion frontend/starters/development/app/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async function getNode(slug: string[]) {
}

if (type === "node--page") {
params.include = "field_page_builder,field_page_builder.field_section_fields,field_page_builder.field_section_fields.field_column_fields,uid"
params.include = "field_page_builder,uid"
}

const resource = await drupal.getResource<DrupalNode>(type, uuid, {
Expand Down
5 changes: 1 addition & 4 deletions frontend/starters/development/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ export default function RootLayout({
</head>
<body>
<DraftAlert />
<div className="max-w-screen-md px-6 mx-auto">
<HeaderNav />
<MantineProvider theme={theme}>{children}</MantineProvider>
</div>
<MantineProvider theme={theme}>{children}</MantineProvider>
</body>
</html>
)
Expand Down
105 changes: 103 additions & 2 deletions frontend/starters/development/app/puck/[...puckPath]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
* NB this route is public, and you will need to add authentication
*/

import { notFound } from "next/navigation"
import { getDraftData } from "next-drupal/draft"
import { drupal } from "@/lib/drupal"
import type { Metadata } from "next"
import type { DrupalNode, JsonApiParams } from "next-drupal"
import "@measured/puck/puck.css";
import { Client } from "./client";
import { Metadata } from "next";
import { getPage } from "../../../lib/get-page";
import { capitalize, formatDrupalType, formatDrupalField, drupalFieldPrefix } from "@powerstack/utils"

export async function generateMetadata({
params: { puckPath = [] },
Expand All @@ -28,13 +33,109 @@ export async function generateMetadata({
};
}


async function getNode(slug: string[]) {
const path = `/${slug.join("/")}`

const params: JsonApiParams = {}

const draftData = getDraftData()

if (draftData.path === path) {
params.resourceVersion = draftData.resourceVersion
}

// Translating the path also allows us to discover the entity type.
const translatedPath = await drupal.translatePath(path)

if (!translatedPath) {
throw new Error("Resource not found", { cause: "NotFound" })
}

const type = translatedPath.jsonapi?.resourceName!
const uuid = translatedPath.entity.uuid

if (type === "node--article") {
params.include = "field_image,uid"
}

if (type === "node--page") {
params.include = "field_page_builder,uid"
}

const resource = await drupal.getResource<DrupalNode>(type, uuid, {
params,
})

if (!resource) {
throw new Error(
`Failed to fetch resource: ${translatedPath?.jsonapi?.individual}`,
{
cause: "DrupalError",
}
)
}

return resource
}


export default async function Page({
params: { puckPath = [] },
}: {
params: { puckPath: string[] };
}) {
const path = `/${puckPath.join("/")}`;
const data = getPage(path);
let data1 = getPage(path);

console.log(data1)

let node
try {
node = await getNode(puckPath)
} catch (error) {
// If getNode throws an error, tell Next.js the path is 404.
notFound()
}


function extractFieldKeys(data) {
const result = {};
for (const key in data) {
if (data.hasOwnProperty(key) && key.startsWith(drupalFieldPrefix)) {
const newKey = formatDrupalField(key); // Remove 'field_' prefix
const fieldData = data[key].hasOwnProperty('value') ? data[key].value : data[key]
result[newKey] = fieldData;
}
}
return result;
}

const content = node?.field_page_builder.map((block) => {

const type = capitalize(formatDrupalType(block.type));
if (type === 'Hero' || 'Text') {
return {
type: type,
props: {
id: `${type}-${block.id}`,
...extractFieldKeys(block)
}
}
}
}

)

const data = {
root: {
props: {
title: node.title
}
},
content: content
}

console.log(data)
return <Client path={path} data={data} />;
}
53 changes: 42 additions & 11 deletions frontend/starters/development/components/drupal/BasicPage.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,55 @@
"use client"

import type { DrupalNode } from "next-drupal"
import config from "../../puck.config";
import { Render } from "@measured/puck";
import { capitalize, formatDrupalType, formatDrupalField, drupalFieldPrefix } from "@powerstack/utils"


interface BasicPageProps {
node: DrupalNode
}

export function BasicPage({ node, ...props }: BasicPageProps) {
console.log(node)

function extractFieldKeys(data) {
const result = {};
for (const key in data) {
if (data.hasOwnProperty(key) && key.startsWith(drupalFieldPrefix)) {
const newKey = formatDrupalField(key); // Remove 'field_' prefix
const fieldData = data[key].hasOwnProperty('value') ? data[key].value : data[key]
result[newKey] = fieldData;
}
}
return result;
}

const content = node?.field_page_builder.map((block) => {

const type = capitalize(formatDrupalType(block.type));
if (type === 'Hero' || 'Text') {

console.log(extractFieldKeys(block))
return {
type: type,
id: `${type}-${block.id}`,
props: extractFieldKeys(block)
}
}
}

)

const data = {
root: {
props: {
title: node.title
}
},
content: content
}

return (
<article {...props}>
<h1 className="mb-4 text-6xl font-black leading-tight">{node.title}</h1>

{node?.field_page_builder[0]?.field_section_fields[0].field_column_fields[0].field_text.processed && (
<div
dangerouslySetInnerHTML={{ __html: node?.field_page_builder[0].field_section_fields[0].field_column_fields[0].field_text.processed}}
className="mt-6 font-serif text-xl leading-loose prose"
/>
)}
</article>
<Render config={config} data={data} />
)
}
71 changes: 70 additions & 1 deletion frontend/starters/development/database.json
Original file line number Diff line number Diff line change
@@ -1 +1,70 @@
{"/":{"content":[{"type":"Hero","props":{"title":"Power Stack","id":"Hero-a8a69850-d5dc-4cf0-8348-15142671a427","subtitle":"Supercharging digital experiences for the modern web.","description":"Build more reliable software with AI companion. AI is also trained to detect lazy developers who do nothing and just complain on Twitter."}},{"type":"Text","props":{"title":"Brilliance is upon us","id":"Text-9abe7f09-4665-462e-935e-2f8cc48665ad","text":"This is sooo good."}},{"type":"Stats","props":{"title":"Heading","id":"Stats-05ac6b81-dcfa-4ebc-9c39-f9d96faa63fa","stats":[{"title":"Page views","subtitle":"test","description":"24% more than in the same month last year, 33% more that two years ago","stats":"456,133"},{"title":"New users","stats":"2,175","description":"13% less compared to last month, new user engagement up by 6%"},{"title":"Completed orders","stats":"1,994","description":"1994 orders were completed this month, 97% satisfaction rate"}]}},{"type":"Text","props":{"title":"Never looking back","id":"Text-0267de45-a97d-45b4-a861-dc50b430bd4e","text":"Good tech stands the test of time"}},{"type":"Text","props":{"title":"Simple. Beautiful. Easy.","id":"Text-b52062cb-fc95-4877-8e33-82d013611ec7","text":"How all editing experiences should be"}}],"root":{"props":{"title":"Home"}},"zones":{}}}
{
"/": {
"content": [
{
"type": "Hero",
"props": {
"title": "Power Stack",
"id": "Hero-a8a69850-d5dc-4cf0-8348-15142671a427",
"subtitle": "Supercharging digital experiences for the modern web.",
"description": "Build more reliable software with AI companion. AI is also trained to detect lazy developers who do nothing and just complain on Twitter."
}
},
{
"type": "Text",
"props": {
"title": "Brilliance is upon us",
"id": "Text-9abe7f09-4665-462e-935e-2f8cc48665ad",
"text": "This is sooo good."
}
},
{
"type": "Stats",
"props": {
"title": "Heading",
"id": "Stats-05ac6b81-dcfa-4ebc-9c39-f9d96faa63fa",
"stats": [
{
"title": "Page views",
"subtitle": "test",
"description": "24% more than in the same month last year, 33% more that two years ago",
"stats": "456,133"
},
{
"title": "New users",
"stats": "2,175",
"description": "13% less compared to last month, new user engagement up by 6%"
},
{
"title": "Completed orders",
"stats": "1,994",
"description": "1994 orders were completed this month, 97% satisfaction rate"
}
]
}
},
{
"type": "Text",
"props": {
"title": "Never looking back",
"id": "Text-0267de45-a97d-45b4-a861-dc50b430bd4e",
"text": "Good tech stands the test of time"
}
},
{
"type": "Text",
"props": {
"title": "Simple. Beautiful. Easy.",
"id": "Text-b52062cb-fc95-4877-8e33-82d013611ec7",
"text": "How all editing experiences should be"
}
}
],
"root": {
"props": {
"title": "Home"
}
},
"zones": {}
}
}
8 changes: 4 additions & 4 deletions frontend/starters/development/lib/drupal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ const clientId = process.env.DRUPAL_CLIENT_ID as string
const clientSecret = process.env.DRUPAL_CLIENT_SECRET as string

export const drupal = new NextDrupal(baseUrl, {
// auth: {
// clientId,
// clientSecret,
// },
auth: {
clientId,
clientSecret,
},
// debug: true,
// useDefaultResourceTypeEntry: true,
})
3 changes: 3 additions & 0 deletions frontend/starters/development/lib/get-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import fs from "fs";

// Replace with call to your database
export const getPage = (path: string) => {

console.log(path)

const allData: Record<string, Data> | null = fs.existsSync("database.json")
? JSON.parse(fs.readFileSync("database.json", "utf-8"))
: null;
Expand Down
13 changes: 13 additions & 0 deletions frontend/starters/development/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ const nextConfig = {
}
return config
},
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "Access-Control-Allow-Origin",
value: `http://${process.env.VIRTUAL_HOST}`, // Set your origin
},
],
},
];
},
}

module.exports = nextConfig
Loading

0 comments on commit 3a62b55

Please sign in to comment.