({
resolver: yupResolver(contactFormSchema),
})
+ const labelProps = {
+ className: classNames(["block", "text-sm", "font-medium", "text-gray-700"]),
+ }
+ const fieldProps = {
+ className: classNames([
+ "relative",
+ "block",
+ "w-full px-3",
+ "py-2 mt-1 text-gray-900",
+ "placeholder-gray-500",
+ "border border-gray-300",
+ "rounded-md appearance-none",
+ "focus:outline-none",
+ "focus:ring-black",
+ "focus:border-black",
+ "focus:z-10",
+ "sm:text-sm",
+ ]),
+ }
+ const wrapperProps = {
+ className: classNames(["space-y-3"]),
+ }
+ const buttonProps = {
+ className: classNames([
+ "flex",
+ "justify-center",
+ "px-4",
+ "py-2",
+ "text-sm font-medium",
+ "text-white",
+ "bg-black",
+ "border border-transparent",
+ "rounded-md",
+ "shadow-sm",
+ "hover:bg-black",
+ ]),
+ }
// This makes a POST to a custom API route.
// The Drupal base URL and the webform_id are NOT exposed.
@@ -58,113 +105,149 @@ export default function WebformPage({ teams }: WebformPageProps) {
This is useful if we need to hide client IDs and secrets or our
Drupal implementation.
-
- {status === "error" ? (
-
- An error occured. Please try again.
-
- ) : null}
- {status === "success" ? (
-
- Your message has been sent. Thank you.
-
- ) : null}
- {Object.values(formState.errors)?.length ? (
-
- {Object.values(formState.errors).map((error, index) => (
-
{error.message}
- ))}
-
- ) : null}
-
-
+
+ {/**/}
+ {/* {status === "error" ? (*/}
+ {/*
*/}
+ {/* An error occured. Please try again.*/}
+ {/*
*/}
+ {/* ) : null}*/}
+ {/* {status === "success" ? (*/}
+ {/*
*/}
+ {/* Your message has been sent. Thank you.*/}
+ {/*
*/}
+ {/* ) : null}*/}
+ {/* {Object.values(formState.errors)?.length ? (*/}
+ {/*
*/}
+ {/* {Object.values(formState.errors).map((error, index) => (*/}
+ {/*
{error.message}
*/}
+ {/* ))}*/}
+ {/*
*/}
+ {/* ) : null}*/}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/* Name*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/* Email*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/* Team*/}
+ {/* */}
+ {/* */}
+ {/* -- Select -- */}
+ {/* {teams.map((team) => (*/}
+ {/* */}
+ {/* {team.name}*/}
+ {/* */}
+ {/* ))}*/}
+ {/* */}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/* Subject*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/* Message*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
+ {/* */}
+ {/* Submit*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
Go back
@@ -183,6 +266,7 @@ export async function getStaticProps(): Promise<
return {
props: {
teams: await getResourceCollection("taxonomy_term--team"),
+ webform: await resolveWebformContent("contact", drupal),
},
}
}
diff --git a/yarn.lock b/yarn.lock
index a6f713f6..dbda8cd8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4623,6 +4623,11 @@ classnames@^2.3.1:
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
+classnames@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924"
+ integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==
+
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
@@ -10084,10 +10089,12 @@ next@^12.2.3:
"@next/swc-win32-ia32-msvc" "12.2.3"
"@next/swc-win32-x64-msvc" "12.2.3"
-nextjs-drupal-webform@^1.0.0-alpha1:
- version "1.0.0-alpha1"
- resolved "https://registry.yarnpkg.com/nextjs-drupal-webform/-/nextjs-drupal-webform-1.0.0-alpha1.tgz#f4106207907c7a001ed8367edebc4c80218dc949"
- integrity sha512-2eyXvp5mavu9QFSmLwWttSuYEon5CcPn3fIxUelVwicgo00OrKZ/9kaCKuEDNeWfYY8HrSQGtal4ANiJ5U908g==
+nextjs-drupal-webform@^1.0.0-alpha2:
+ version "1.0.0-alpha2"
+ resolved "https://registry.yarnpkg.com/nextjs-drupal-webform/-/nextjs-drupal-webform-1.0.0-alpha2.tgz#03f494b2f8a585ecff3c4bc0f55daeba08aedab9"
+ integrity sha512-O+AszzKB1qRT0wFmrqthb1EvCz6rOxE+lbZq1ycj5eW2ftPjWOaui6icKWYVYUH+hkxTD3FYVQbMv7qukpuzEw==
+ dependencies:
+ classnames "^2.3.2"
node-abi@^3.3.0:
version "3.22.0"
From 02445aa6457ac8246815dd78b472154faa5cfc62 Mon Sep 17 00:00:00 2001
From: HARUMI JANG
Date: Thu, 15 Dec 2022 10:53:33 -0500
Subject: [PATCH 4/7] Pass in data-cy to submit button
---
.../example-webform/pages/server-side.tsx | 28 ++++++++++---------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/examples/example-webform/pages/server-side.tsx b/examples/example-webform/pages/server-side.tsx
index a32dd3bf..ff207b3a 100644
--- a/examples/example-webform/pages/server-side.tsx
+++ b/examples/example-webform/pages/server-side.tsx
@@ -66,23 +66,24 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
"shadow-sm",
"hover:bg-black",
]),
+ "data-cy": "btn-submit",
}
// This makes a POST to a custom API route.
// The Drupal base URL and the webform_id are NOT exposed.
- async function onSubmit(data: FormData) {
- const response = await fetch(`/api/contact`, {
- method: "POST",
- body: JSON.stringify(data),
- })
-
- if (response.ok) {
- reset()
- return setStatus("success")
- }
-
- return setStatus("error")
- }
+ // async function onSubmit(data: FormData) {
+ // const response = await fetch(`/api/contact`, {
+ // method: "POST",
+ // body: JSON.stringify(data),
+ // })
+ //
+ // if (response.ok) {
+ // reset()
+ // return setStatus("success")
+ // }
+ //
+ // return setStatus("error")
+ // }
return (
<>
@@ -140,6 +141,7 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
wrapperProps
),
}}
+ // className="space-y-6"
/>
{/**/}
{/* {status === "error" ? (*/}
From 13612b755d936c85302b9d5f723e7f066b2dbf89 Mon Sep 17 00:00:00 2001
From: HARUMI JANG
Date: Wed, 21 Dec 2022 14:16:33 -0500
Subject: [PATCH 5/7] Update example and update text
---
.../components/WebformButton.tsx | 17 ++
examples/example-webform/lib/drupal.ts | 17 ++
examples/example-webform/package.json | 2 +-
examples/example-webform/pages/api/webform.ts | 10 +
examples/example-webform/pages/index.tsx | 15 +-
.../example-webform/pages/server-side.tsx | 232 ++++--------------
yarn.lock | 8 +-
7 files changed, 101 insertions(+), 200 deletions(-)
create mode 100644 examples/example-webform/components/WebformButton.tsx
create mode 100644 examples/example-webform/lib/drupal.ts
create mode 100644 examples/example-webform/pages/api/webform.ts
diff --git a/examples/example-webform/components/WebformButton.tsx b/examples/example-webform/components/WebformButton.tsx
new file mode 100644
index 00000000..cb1050bd
--- /dev/null
+++ b/examples/example-webform/components/WebformButton.tsx
@@ -0,0 +1,17 @@
+import { components } from "nextjs-drupal-webform"
+import classNames from "classnames"
+
+const buttonDecorator = (DecoratedComponent) => {
+ return function WebformCustomTable(props) {
+ const fieldProps = props.fieldProps ?? {}
+ const additionalClasses = []
+ if (props.element["#button_type"] === "primary") {
+ additionalClasses.push("bg-black hover:bg-black text-white")
+ }
+ fieldProps.className = classNames(fieldProps.className, additionalClasses)
+
+ return
+ }
+}
+
+export default buttonDecorator(components.button)
diff --git a/examples/example-webform/lib/drupal.ts b/examples/example-webform/lib/drupal.ts
new file mode 100644
index 00000000..cd653cc6
--- /dev/null
+++ b/examples/example-webform/lib/drupal.ts
@@ -0,0 +1,17 @@
+import { DrupalClient } from "next-drupal"
+
+export const drupal = new DrupalClient(
+ process.env.NEXT_PUBLIC_DRUPAL_BASE_URL,
+ {
+ previewSecret: process.env.DRUPAL_PREVIEW_SECRET,
+ auth: {
+ clientId: process.env.DRUPAL_CLIENT_ID,
+ clientSecret: process.env.DRUPAL_CLIENT_SECRET,
+ scope:
+ "administrator developer site_builder content_administrator content_author content_editor user_administrator headless",
+ },
+ // @see https://github.com/vercel/next.js/discussions/32238
+ // @see https://github.com/vercel/next.js/blob/d895a50abbc8f91726daa2d7ebc22c58f58aabbb/packages/next/server/api-utils/node.ts#L504
+ forceIframeSameSiteCookie: process.env.NODE_ENV === "development",
+ }
+)
diff --git a/examples/example-webform/package.json b/examples/example-webform/package.json
index 97853d73..5cfeecc3 100644
--- a/examples/example-webform/package.json
+++ b/examples/example-webform/package.json
@@ -23,7 +23,7 @@
"react-dom": "^17.0.2",
"react-hook-form": "^7.25.3",
"yup": "^0.32.11",
- "nextjs-drupal-webform": "^1.0.0-alpha2"
+ "nextjs-drupal-webform": "^1.0.0-beta1"
},
"devDependencies": {
"@babel/core": "^7.12.9",
diff --git a/examples/example-webform/pages/api/webform.ts b/examples/example-webform/pages/api/webform.ts
new file mode 100644
index 00000000..60889f25
--- /dev/null
+++ b/examples/example-webform/pages/api/webform.ts
@@ -0,0 +1,10 @@
+import { NextApiRequest, NextApiResponse } from "next"
+import { drupal } from "../../lib/drupal"
+import { WebformDefaultApiRoute } from "nextjs-drupal-webform"
+
+export default async function handler(
+ request: NextApiRequest,
+ response: NextApiResponse
+) {
+ return WebformDefaultApiRoute(request, response, drupal)
+}
diff --git a/examples/example-webform/pages/index.tsx b/examples/example-webform/pages/index.tsx
index 66147367..743c4be7 100644
--- a/examples/example-webform/pages/index.tsx
+++ b/examples/example-webform/pages/index.tsx
@@ -1,5 +1,6 @@
import Head from "next/head"
import Link from "next/link"
+import * as React from "react"
export default function IndexPage() {
return (
@@ -33,19 +34,15 @@ export default function IndexPage() {
See Example
- Server Side (API Route)
+ Server Side
- We submit the form values to a custom API route first. The API route
- then submits the form to Drupal using the{" "}
-
- Webform REST
+ This example uses the{" "}
+
+ Next.js Webform
{" "}
+ library to render and submit forms built using the Drupal Webform
module.
-
- This is useful if we need to hide client IDs and secrets or our
- Drupal implementation.
-
See Example
diff --git a/examples/example-webform/pages/server-side.tsx b/examples/example-webform/pages/server-side.tsx
index ff207b3a..0e318573 100644
--- a/examples/example-webform/pages/server-side.tsx
+++ b/examples/example-webform/pages/server-side.tsx
@@ -2,12 +2,6 @@ import * as React from "react"
import { GetStaticPropsResult } from "next"
import Head from "next/head"
import Link from "next/link"
-import { getResourceCollection, DrupalTaxonomyTerm } from "next-drupal"
-import { useForm } from "react-hook-form"
-import * as yup from "yup"
-import { yupResolver } from "@hookform/resolvers/yup"
-
-import { contactFormSchema } from "../validations/contact"
import withCustomStyles from "../components/withCustomStyles"
import {
resolveWebformContent,
@@ -17,19 +11,13 @@ import {
} from "nextjs-drupal-webform"
import { drupal } from "basic-starter/lib/drupal"
import classNames from "classnames"
-
-type FormData = yup.TypeOf
+import WebformButton from "../components/WebformButton"
interface WebformPageProps {
- teams: DrupalTaxonomyTerm[]
webform: WebformProps
}
-export default function WebformPage({ teams, webform }: WebformPageProps) {
- const [status, setStatus] = React.useState<"error" | "success">()
- const { register, handleSubmit, formState, reset } = useForm({
- resolver: yupResolver(contactFormSchema),
- })
+export default function WebformPage({ webform }: WebformPageProps) {
const labelProps = {
className: classNames(["block", "text-sm", "font-medium", "text-gray-700"]),
}
@@ -54,8 +42,6 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
}
const buttonProps = {
className: classNames([
- "flex",
- "justify-center",
"px-4",
"py-2",
"text-sm font-medium",
@@ -69,22 +55,6 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
"data-cy": "btn-submit",
}
- // This makes a POST to a custom API route.
- // The Drupal base URL and the webform_id are NOT exposed.
- // async function onSubmit(data: FormData) {
- // const response = await fetch(`/api/contact`, {
- // method: "POST",
- // body: JSON.stringify(data),
- // })
- //
- // if (response.ok) {
- // reset()
- // return setStatus("success")
- // }
- //
- // return setStatus("error")
- // }
-
return (
<>
@@ -95,161 +65,53 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
Next.js for Drupal
Webform Example - Server Side
- We submit the form values to a custom API route first. The API route
- then submits the form to Drupal using the{" "}
-
- Webform REST
+ This example uses the{" "}
+
+ Next.js Webform
{" "}
+ library to render and submit forms built using the Drupal Webform
module.
-
- This is useful if we need to hide client IDs and secrets or our
- Drupal implementation.
-
-
- {/**/}
- {/* {status === "error" ? (*/}
- {/*
*/}
- {/* An error occured. Please try again.*/}
- {/*
*/}
- {/* ) : null}*/}
- {/* {status === "success" ? (*/}
- {/*
*/}
- {/* Your message has been sent. Thank you.*/}
- {/*
*/}
- {/* ) : null}*/}
- {/* {Object.values(formState.errors)?.length ? (*/}
- {/*
*/}
- {/* {Object.values(formState.errors).map((error, index) => (*/}
- {/*
{error.message}
*/}
- {/* ))}*/}
- {/*
*/}
- {/* ) : null}*/}
- {/*
*/}
- {/* */}
- {/* */}
- {/* Name*/}
- {/* */}
- {/* */}
- {/*
*/}
- {/* */}
- {/* */}
- {/* Email*/}
- {/* */}
- {/* */}
- {/*
*/}
- {/* */}
- {/* */}
- {/* Team*/}
- {/* */}
- {/* */}
- {/* -- Select -- */}
- {/* {teams.map((team) => (*/}
- {/* */}
- {/* {team.name}*/}
- {/* */}
- {/* ))}*/}
- {/* */}
- {/*
*/}
- {/* */}
- {/* */}
- {/* Subject*/}
- {/* */}
- {/* */}
- {/*
*/}
- {/* */}
- {/* */}
- {/* Message*/}
- {/* */}
- {/* */}
- {/*
*/}
- {/* */}
- {/* Submit*/}
- {/* */}
- {/* */}
- {/*
*/}
+
+
+
Go back
@@ -264,10 +126,8 @@ export default function WebformPage({ teams, webform }: WebformPageProps) {
export async function getStaticProps(): Promise<
GetStaticPropsResult
> {
- // Load terms terms for the contact form.
return {
props: {
- teams: await getResourceCollection("taxonomy_term--team"),
webform: await resolveWebformContent("contact", drupal),
},
}
diff --git a/yarn.lock b/yarn.lock
index dbda8cd8..3610e973 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10089,10 +10089,10 @@ next@^12.2.3:
"@next/swc-win32-ia32-msvc" "12.2.3"
"@next/swc-win32-x64-msvc" "12.2.3"
-nextjs-drupal-webform@^1.0.0-alpha2:
- version "1.0.0-alpha2"
- resolved "https://registry.yarnpkg.com/nextjs-drupal-webform/-/nextjs-drupal-webform-1.0.0-alpha2.tgz#03f494b2f8a585ecff3c4bc0f55daeba08aedab9"
- integrity sha512-O+AszzKB1qRT0wFmrqthb1EvCz6rOxE+lbZq1ycj5eW2ftPjWOaui6icKWYVYUH+hkxTD3FYVQbMv7qukpuzEw==
+nextjs-drupal-webform@^1.0.0-beta1:
+ version "1.0.0-beta1"
+ resolved "https://registry.yarnpkg.com/nextjs-drupal-webform/-/nextjs-drupal-webform-1.0.0-beta1.tgz#fbb7989856fa0f559b599c3859c0922f4c5f7bba"
+ integrity sha512-qdV0LVZvBS9+VEI3IwGp43HkY2z6WuMxRWEuoVC9thqRxTWvspoCGCNYqpdm37IqN9uUgafQyzpQa6eI08ejSA==
dependencies:
classnames "^2.3.2"
From 89afc9562f04070c2a0e1c9ceeabb4f39896793c Mon Sep 17 00:00:00 2001
From: HARUMI JANG
Date: Wed, 21 Dec 2022 14:34:36 -0500
Subject: [PATCH 6/7] Update confirmation msg in test
---
examples/example-webform/cypress/integration/webform.spec.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/example-webform/cypress/integration/webform.spec.tsx b/examples/example-webform/cypress/integration/webform.spec.tsx
index 78b838bf..47f6026c 100644
--- a/examples/example-webform/cypress/integration/webform.spec.tsx
+++ b/examples/example-webform/cypress/integration/webform.spec.tsx
@@ -30,7 +30,7 @@ context("server side webform", () => {
cy.get("[name=message]").type("This is my message.")
cy.get("[data-cy=btn-submit]").click()
- cy.contains("Your message has been sent. Thank you.")
+ cy.contains("New submission added to Contact")
})
})
From da29f76ad035984a7e55c0d69b5a4e736e0be63c Mon Sep 17 00:00:00 2001
From: HARUMI JANG
Date: Wed, 21 Dec 2022 14:46:51 -0500
Subject: [PATCH 7/7] remove option from DrupalClient
---
examples/example-webform/lib/drupal.ts | 3 ---
1 file changed, 3 deletions(-)
diff --git a/examples/example-webform/lib/drupal.ts b/examples/example-webform/lib/drupal.ts
index cd653cc6..a1e60835 100644
--- a/examples/example-webform/lib/drupal.ts
+++ b/examples/example-webform/lib/drupal.ts
@@ -10,8 +10,5 @@ export const drupal = new DrupalClient(
scope:
"administrator developer site_builder content_administrator content_author content_editor user_administrator headless",
},
- // @see https://github.com/vercel/next.js/discussions/32238
- // @see https://github.com/vercel/next.js/blob/d895a50abbc8f91726daa2d7ebc22c58f58aabbb/packages/next/server/api-utils/node.ts#L504
- forceIframeSameSiteCookie: process.env.NODE_ENV === "development",
}
)