-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example Webform usage #86
Open
harumijang
wants to merge
48
commits into
acquia:main
Choose a base branch
from
harumijang:webforms
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+122
−5
Open
Changes from 32 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
03a00a2
GET
harumijang 65892b5
added submit method with POST but client not working
harumijang 2427a9e
working submit and removed markdown
harumijang 756c24c
added start of dynamic form element rendering
harumijang 19b5993
support multiple forms on one node
harumijang 62d5a25
dynamically pass in webform_id
harumijang 1c512f4
dynamically build body request
harumijang d508023
started checkboxes/radio for POST
harumijang 45b1c00
Merge branch 'main' into webforms
harumijang 8188daf
Merge branch 'main' into webforms
harumijang 42ef37e
added POST support for checkboxes, radio buttons, single checkbox
harumijang 83399c0
Merge branch 'main' into webforms
harumijang 74f4cf6
Moved webform related functions to lib directory
harumijang 4203766
custom API GET works, moved POST into api/webform
harumijang b5d23e0
added super basic styling
harumijang db7fda1
Move webform rendering to /webform, pass in additionalContent to all …
harumijang c9c684e
Created Webform component and created types.ts file
harumijang f26db83
Use new types
harumijang 46e2521
Started on custom components
harumijang be9f34a
Added example of working example of custom component
harumijang 3486357
Merge branch 'main' into webforms
harumijang 809164e
Merge branch 'main' into webforms
harumijang cabaadc
Added component wrapper for radio buttons and print validation msg
harumijang 44134a4
Render validation error msg for one webform element
harumijang c9e0cf3
Added more wrapper components for webform elements
harumijang 45bcb59
added wrapper for custom component and checkbox
harumijang 07f85c5
prettier
harumijang 1673ff2
add webform debug fallback component and some css for my sanity
harumijang 87c025e
Added error and success form message
harumijang 17451e4
Merge branch 'main' into webforms
harumijang 8b11f33
Moved webforms to different pkg and added README
harumijang bda6dfb
add back line
harumijang 1f1ac35
Updated readme
harumijang 8e8cf49
Removed client from next webform
harumijang f031328
Use backend value for name and add comment about type in custom compo…
harumijang 4191cb7
readme
harumijang 26e6c44
removed webform
harumijang 69d9b0a
Use webform from exports
lauriii db03401
Add second arg to webform method and add condition to node-article
harumijang cfe7e4b
uncomment custom component
harumijang e045044
Pass in client info
harumijang 77ddec6
added submit api to starter and package
harumijang 6ed31cd
Pass url into submit instead of client
harumijang 6dde63c
added get api
harumijang 374d84d
Merge branch 'main' into webforms
harumijang 47664dc
Merge branch 'main' into webforms
harumijang 752c3e8
Remove client as arg from getWebformFields
harumijang 7bddac9
Change custom webform component
harumijang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Next.js Drupal Webform | ||
|
||
Plugin for integrating the [Webform](https://www.drupal.org/project/webform) module with Next.js applications. | ||
|
||
## Setup | ||
1. Install the [Webform](https://www.drupal.org/project/webform) and [Webform REST](https://www.drupal.org/project/webform_rest) modules. | ||
2. Enable REST resources: "Webform Submit", "Webform Elements", "Webform Submission" on /admin/config/services/rest. | ||
3. Set Webform permissions on RESTful Web Services `/admin/people/permissions#module-rest` for Anonymous Users. | ||
4. Create your webform. | ||
5. @todo add how to get the field_webform from entity? | ||
|
||
## Example | ||
``` | ||
<Webform | ||
webformObject={additionalContent.webform} | ||
id={additionalContent.webform.drupal_internal__id} | ||
key={additionalContent.webform.drupal_internal__id} | ||
/> | ||
``` | ||
|
||
|
||
## Using custom components | ||
1. Create your custom component | ||
``` | ||
// Example custom component | ||
export const WebformDate = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
<input type="date" name="date" min="2022-01-01" max="2022-12-31" /> | ||
</WebformElementWrapper> | ||
); | ||
}; | ||
``` | ||
2. Pass in your component(s) to the `customComponents` property. | ||
``` | ||
<Webform | ||
webformObject={additionalContent.webform} | ||
id={additionalContent.webform.drupal_internal__id} | ||
key={additionalContent.webform.drupal_internal__id} | ||
customComponents={{ date: WebformDate }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is unclear based on these docs is that what is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Type |
||
/> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react'; | ||
import WebformElementWrapper from '../src/components/WebformElementWrapper'; | ||
|
||
// Example custom component | ||
export const WebformDate = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
<input type="date" name="date" min="2022-01-01" max="2022-12-31" /> | ||
</WebformElementWrapper> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/basic-features/typescript for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "nextjs-drupal-webform", | ||
"version": "1.0.0", | ||
"private": true, | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "next build", | ||
"dev": "next dev" | ||
}, | ||
"dependencies": { | ||
"@tailwindcss/typography": "^0.5.0", | ||
"classnames": "^2.3.1", | ||
"drupal-jsonapi-params": "^2.1.0", | ||
"html-react-parser": "^1.4.8", | ||
"next": "^12.2.0", | ||
"next-acms": "^1.0.0-beta1", | ||
"next-drupal": "^1.1.1", | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"sharp": "^0.30.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.18.9", | ||
"@types/node": "^18.0.6", | ||
"@types/react": "^17.0.4", | ||
"autoprefixer": "^10.4.2", | ||
"eslint": "^8.20.0", | ||
"eslint-config-next": "^12.2.3", | ||
"postcss": "^8.4.5", | ||
"tailwindcss": "^3.0.15", | ||
"typescript": "^4.6.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next'; | ||
import { drupal } from '../../../src/drupal'; | ||
|
||
export default async function handler( | ||
request: NextApiRequest, | ||
response: NextApiResponse, | ||
) { | ||
try { | ||
const url = drupal.buildUrl( | ||
`/webform_rest/${request.query.id}/fields?_format=json`, | ||
); | ||
const result = await fetch(url.toString()); | ||
const webform = await result.json(); | ||
response.status(200).json(webform); | ||
} catch (e) { | ||
console.log(e.message); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
packages/nextjs-drupal-webform/pages/api/webform/submit.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next'; | ||
import { drupal } from '../../../src/drupal'; | ||
|
||
export default async function handler( | ||
request: NextApiRequest, | ||
response: NextApiResponse, | ||
) { | ||
if (request.method === 'POST') { | ||
const url = drupal.buildUrl('/webform_rest/submit?_format=json'); | ||
// Submit to Drupal. | ||
const result = await fetch(url.toString(), { | ||
method: 'POST', | ||
body: JSON.stringify(request.body), | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
if (!result.ok) { | ||
const message = await result.json(); | ||
// Send error to client. | ||
return response.status(result.status).json({ message }); | ||
} | ||
response.end(JSON.stringify(result)); | ||
response.status(200); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import React, { useState } from 'react'; | ||
import { WebformProps } from './types'; | ||
import { formToJSON, renderWebformElement, styles } from './utils'; | ||
|
||
export class WebformError extends Error { | ||
response: string; | ||
|
||
constructor(response: string) { | ||
super(); | ||
|
||
this.response = response; | ||
} | ||
} | ||
|
||
/** | ||
* Errors returned by Drupal. | ||
*/ | ||
type WebformErrors = { | ||
[name: string]: string; | ||
}; | ||
|
||
export const Webform = ({ | ||
webformObject, | ||
id, | ||
customComponents, | ||
}: WebformProps) => { | ||
const [errors, setErrors] = useState<WebformErrors>({}); | ||
const [status, setStatus] = useState<'error' | 'success'>(); | ||
console.log('webform object', webformObject); | ||
|
||
const submitHandler = async (event) => { | ||
event.preventDefault(); | ||
const data = formToJSON(event.target.elements); | ||
// Post process serialized data: | ||
// Some webform elements require specialized data formatting. | ||
for (const element in webformObject.elements) { | ||
if (data[element]) { | ||
switch (webformObject.elements[element]['#type']) { | ||
case 'checkbox': | ||
data[element] = 1; | ||
break; | ||
} | ||
} | ||
} | ||
const body = { ...(data as object), ...{ webform_id: id } }; | ||
console.log('request body', body); | ||
const response = await fetch('/api/webform/submit', { | ||
method: 'POST', | ||
body: JSON.stringify(body), | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
if (!response.ok) { | ||
setStatus('error'); | ||
const message = await response.json(); | ||
setErrors(message.message.error); | ||
} else { | ||
setStatus('success'); | ||
// Clear webform element errors. | ||
setErrors({}); | ||
} | ||
}; | ||
|
||
return ( | ||
<form style={styles.form} onSubmit={(e) => submitHandler(e)}> | ||
{status === 'error' ? ( | ||
<div style={styles.formError}>An error occurred. Please try again.</div> | ||
) : null} | ||
{status === 'success' ? ( | ||
<div style={styles.formSuccess}> | ||
Your submission has been sent. Thank you. | ||
</div> | ||
) : null} | ||
{Object.values(webformObject.elements).map((el) => | ||
renderWebformElement(el, customComponents, errors[el['#webform_key']]), | ||
)} | ||
</form> | ||
); | ||
}; |
26 changes: 26 additions & 0 deletions
26
packages/nextjs-drupal-webform/src/components/WebformCheckbox.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import WebformElementWrapper from './WebformElementWrapper'; | ||
import { styles } from '../utils'; | ||
import { WebformCustomComponent } from '../types'; | ||
|
||
export const WebformCheckbox: WebformCustomComponent = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
<div> | ||
<input | ||
type={element.type} | ||
id={element['#webform_key']} | ||
name={element['#webform_key']} | ||
style={styles.checkbox} | ||
/> | ||
<label className="form-check-label">{element['#description']}</label> | ||
</div> | ||
</WebformElementWrapper> | ||
); | ||
}; | ||
|
||
export default WebformCheckbox; |
29 changes: 29 additions & 0 deletions
29
packages/nextjs-drupal-webform/src/components/WebformCheckboxGroup.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { styles } from '../utils'; | ||
import WebformElementWrapper from './WebformElementWrapper'; | ||
|
||
export const WebformCheckboxGroup = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
{element['#options'] && | ||
Object.keys(element['#options']).map((option) => ( | ||
<div className="form-check" key={option}> | ||
<input | ||
type={element.type} | ||
name={element['#webform_key']} | ||
id={option} | ||
value={option} | ||
style={styles.checkbox} | ||
/> | ||
<label className="form-check-label">{option}</label> | ||
</div> | ||
))} | ||
</WebformElementWrapper> | ||
); | ||
}; | ||
|
||
export default WebformCheckboxGroup; |
10 changes: 10 additions & 0 deletions
10
packages/nextjs-drupal-webform/src/components/WebformDebug.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export const WebformDebug = ({ element, error }) => { | ||
return ( | ||
<code> | ||
{error} | ||
<pre>{JSON.stringify(element, null, 2)}</pre> | ||
</code> | ||
); | ||
}; | ||
|
||
export default WebformDebug; |
39 changes: 39 additions & 0 deletions
39
packages/nextjs-drupal-webform/src/components/WebformElementWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { styles } from '../utils'; | ||
|
||
export const WebformElementWrapper = ({ | ||
children, | ||
labelFor, | ||
labelClassName, | ||
error, | ||
...props | ||
}) => { | ||
const css = ` | ||
.required-field:after { | ||
content: ' *'; | ||
color: red; | ||
} | ||
.invalid-feedback { | ||
color: red; | ||
} | ||
`; | ||
return ( | ||
<div {...props}> | ||
<style>{css}</style> | ||
<label | ||
style={styles.elementLabel} | ||
htmlFor={labelFor} | ||
className={labelClassName ? 'required-field' : ''} | ||
> | ||
{labelFor} | ||
</label> | ||
{children} | ||
{error && ( | ||
<div className="form-text invalid-feedback" {...props}> | ||
{error} | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default WebformElementWrapper; |
22 changes: 22 additions & 0 deletions
22
packages/nextjs-drupal-webform/src/components/WebformText.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import WebformElementWrapper from './WebformElementWrapper'; | ||
import { styles } from '../utils'; | ||
|
||
export const WebformText = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
<input | ||
placeholder={element['#title']} | ||
id={element['#webform_key']} | ||
name={element['#webform_key']} | ||
style={styles.textArea} | ||
/> | ||
</WebformElementWrapper> | ||
); | ||
}; | ||
|
||
export default WebformText; |
22 changes: 22 additions & 0 deletions
22
packages/nextjs-drupal-webform/src/components/WebformTextArea.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import WebformElementWrapper from './WebformElementWrapper'; | ||
import { styles } from '../utils'; | ||
|
||
export const WebformText = ({ element, error }) => { | ||
return ( | ||
<WebformElementWrapper | ||
labelFor={element['#title']} | ||
labelClassName={element['#required']} | ||
settings={null} | ||
error={error} | ||
> | ||
<textarea | ||
placeholder={element['#title']} | ||
id={element['#webform_key']} | ||
name={element['#webform_key']} | ||
style={styles.textArea} | ||
/> | ||
</WebformElementWrapper> | ||
); | ||
}; | ||
|
||
export default WebformText; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the name should be dynamically coming from the backend?