generated from adobe/aem-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
92ab83e
commit 98d50be
Showing
23 changed files
with
1,372 additions
and
498 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,189 @@ | ||
function createSelect(fd) { | ||
const select = document.createElement('select'); | ||
select.id = fd.Field; | ||
if (fd.Placeholder) { | ||
const ph = document.createElement('option'); | ||
ph.textContent = fd.Placeholder; | ||
ph.setAttribute('selected', ''); | ||
ph.setAttribute('disabled', ''); | ||
select.append(ph); | ||
} | ||
fd.Options.split(',').forEach((o) => { | ||
const option = document.createElement('option'); | ||
option.textContent = o.trim(); | ||
option.value = o.trim(); | ||
select.append(option); | ||
}); | ||
if (fd.Mandatory === 'x') { | ||
select.setAttribute('required', 'required'); | ||
} | ||
return select; | ||
} | ||
function constructPayload(form) { | ||
const payload = {}; | ||
[...form.elements].forEach((fe) => { | ||
if (fe.type === 'checkbox') { | ||
if (fe.checked) | ||
payload[fe.id] = fe.value; | ||
} | ||
else if (fe.id) { | ||
payload[fe.id] = fe.value; | ||
} | ||
}); | ||
return payload; | ||
} | ||
async function submitForm(form) { | ||
const payload = constructPayload(form); | ||
payload.timestamp = new Date().toJSON(); | ||
const resp = await fetch(form.dataset.action, { | ||
method: 'POST', | ||
cache: 'no-cache', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ data: payload }), | ||
}); | ||
await resp.text(); | ||
return payload; | ||
} | ||
function createButton(fd) { | ||
const button = document.createElement('button'); | ||
button.textContent = fd.Label; | ||
button.classList.add('button'); | ||
if (fd.Type === 'submit') { | ||
button.addEventListener('click', async (event) => { | ||
const form = button.closest('form'); | ||
if (fd.Placeholder) | ||
form.dataset.action = fd.Placeholder; | ||
if (form.checkValidity()) { | ||
event.preventDefault(); | ||
button.setAttribute('disabled', ''); | ||
await submitForm(form); | ||
const redirectTo = fd.Extra; | ||
window.location.href = redirectTo; | ||
} | ||
}); | ||
} | ||
return button; | ||
} | ||
function createHeading(fd, el) { | ||
const heading = document.createElement(el); | ||
heading.textContent = fd.Label; | ||
return heading; | ||
} | ||
function createInput(fd) { | ||
const input = document.createElement('input'); | ||
input.type = fd.Type; | ||
input.id = fd.Field; | ||
input.setAttribute('placeholder', fd.Placeholder); | ||
if (fd.Mandatory === 'x') { | ||
input.setAttribute('required', 'required'); | ||
} | ||
return input; | ||
} | ||
function createTextArea(fd) { | ||
const input = document.createElement('textarea'); | ||
input.id = fd.Field; | ||
input.setAttribute('placeholder', fd.Placeholder); | ||
if (fd.Mandatory === 'x') { | ||
input.setAttribute('required', 'required'); | ||
} | ||
return input; | ||
} | ||
function createLabel(fd) { | ||
const label = document.createElement('label'); | ||
label.setAttribute('for', fd.Field); | ||
label.textContent = fd.Label; | ||
if (fd.Mandatory === 'x') { | ||
label.classList.add('required'); | ||
} | ||
return label; | ||
} | ||
function applyRules(form, rules) { | ||
const payload = constructPayload(form); | ||
rules.forEach((field) => { | ||
const { type, condition: { key, operator, value } } = field.rule; | ||
if (type === 'visible') { | ||
if (operator === 'eq') { | ||
if (payload[key] === value) { | ||
form.querySelector(`.${field.fieldId}`).classList.remove('hidden'); | ||
} | ||
else { | ||
form.querySelector(`.${field.fieldId}`).classList.add('hidden'); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
function fill(form) { | ||
const { action } = form.dataset; | ||
if (action === '/tools/bot/register-form') { | ||
const loc = new URL(window.location.href); | ||
form.querySelector('#owner').value = loc.searchParams.get('owner') || ''; | ||
form.querySelector('#installationId').value = loc.searchParams.get('id') || ''; | ||
} | ||
} | ||
async function createForm(formURL) { | ||
console.log('formURL', formURL); // todo: remove before merge! | ||
const { pathname } = new URL(formURL); | ||
const resp = await fetch(pathname); | ||
const json = await resp.json(); | ||
const form = document.createElement('form'); | ||
const rules = []; | ||
// eslint-disable-next-line prefer-destructuring | ||
form.dataset.action = pathname.split('.json')[0]; | ||
json.data.forEach((fd) => { | ||
fd.Type = fd.Type || 'text'; | ||
const fieldWrapper = document.createElement('div'); | ||
const style = fd.Style ? ` form-${fd.Style}` : ''; | ||
const fieldId = `form-${fd.Type}-wrapper${style}`; | ||
fieldWrapper.className = fieldId; | ||
fieldWrapper.classList.add('field-wrapper'); | ||
switch (fd.Type) { | ||
case 'select': | ||
fieldWrapper.append(createLabel(fd)); | ||
fieldWrapper.append(createSelect(fd)); | ||
break; | ||
case 'heading': | ||
fieldWrapper.append(createHeading(fd, 'h3')); | ||
break; | ||
case 'legal': | ||
fieldWrapper.append(createHeading(fd, 'p')); | ||
break; | ||
case 'checkbox': | ||
fieldWrapper.append(createInput(fd)); | ||
fieldWrapper.append(createLabel(fd)); | ||
break; | ||
case 'text-area': | ||
fieldWrapper.append(createLabel(fd)); | ||
fieldWrapper.append(createTextArea(fd)); | ||
break; | ||
case 'submit': | ||
fieldWrapper.append(createButton(fd)); | ||
break; | ||
default: | ||
fieldWrapper.append(createLabel(fd)); | ||
fieldWrapper.append(createInput(fd)); | ||
} | ||
if (fd.Rules) { | ||
try { | ||
rules.push({ fieldId, rule: JSON.parse(fd.Rules) }); | ||
} | ||
catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.warn(`Invalid Rule ${fd.Rules}: ${e}`); | ||
} | ||
} | ||
form.append(fieldWrapper); | ||
}); | ||
form.addEventListener('change', () => applyRules(form, rules)); | ||
applyRules(form, rules); | ||
fill(form); | ||
return (form); | ||
} | ||
export default async function decorate(block) { | ||
const form = block.querySelector('a[href$=".json"]'); | ||
if (form) { | ||
form.replaceWith(await createForm(form.href)); | ||
} | ||
} |
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,122 @@ | ||
main .form { | ||
background-color: var(--color-white); | ||
padding: var(--spacing-s); | ||
border-radius: var(--card-border-radius-l); | ||
filter: var(--image-filter-drop-shadow-small); | ||
border: solid 1px var(--bg-color-grey); | ||
} | ||
|
||
main .form h2 { | ||
padding: var(--spacing-s) 0; | ||
font-size: var(--type-heading-l-lh); | ||
} | ||
|
||
main .form h3 { | ||
padding-top: var(--spacing-s); | ||
font-size: var(--type-heading-m-size); | ||
} | ||
|
||
main .form input, | ||
main .form textarea, | ||
main .form select { | ||
border: solid 1px var(--bg-color-grey); | ||
padding: var(--spacing-xxs) var(--spacing-xs); | ||
width: 100%; | ||
max-width: 50rem; | ||
box-sizing: border-box; | ||
border-radius: var(--input-border-radius); | ||
font-size: var(--type-body-s-size); | ||
line-height: var(--type-body-s-lh); | ||
font-family: var(--body-font-family); | ||
} | ||
|
||
main .form textarea { | ||
min-height: 100px; | ||
} | ||
|
||
main .form input:hover, | ||
main .form select:hover { | ||
border-color: var(--color-font-grey); | ||
} | ||
|
||
main .form label { | ||
display: block; | ||
padding-bottom: var(--spacing-xxs); | ||
box-sizing: border-box; | ||
font-size: var(--type-body-s-size); | ||
line-height: var(--type-body-s-lh); | ||
} | ||
|
||
main .form label.required::after { | ||
content: "*"; | ||
color: var(--color-black); | ||
padding-left: var(--spacing-xxxs); | ||
} | ||
|
||
main .form .field-wrapper { | ||
margin-bottom: var(--spacing-m); | ||
} | ||
|
||
main .form .form-checkbox-wrapper { | ||
display: flex; | ||
align-items: center; | ||
margin: var(--spacing-xs) 0; | ||
} | ||
|
||
main .form .form-checkbox-wrapper input[type='checkbox'] { | ||
appearance: none; | ||
height: 20px; | ||
width: 20px; | ||
position: relative; | ||
border: unset; | ||
padding: unset; | ||
margin-right: var(--spacing-xxs); | ||
margin-left: 0; | ||
} | ||
|
||
main .form .form-checkbox-wrapper input[type='checkbox']::after { | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
height: 20px; | ||
width: 20px; | ||
content: ' '; | ||
background-size: contain; | ||
} | ||
|
||
main .form .form-checkbox-wrapper input[type='checkbox']:checked::after { | ||
background-size: contain; | ||
content: ' '; | ||
} | ||
|
||
main .form .form-checkbox-wrapper label { | ||
display: block; | ||
font-size: var(--type-body-xxs-size); | ||
line-height: var(--type-body-xxs-lh); | ||
padding-bottom: 0; | ||
} | ||
|
||
main .form-legal-wrapper p { | ||
font-size: var(--type-body-xxs-size); | ||
line-height: var(--type-body-xxs-lh); | ||
font-style: italic; | ||
} | ||
|
||
main .form button { | ||
font-family: var(--body-font-family); | ||
} | ||
|
||
@media screen and (min-width: 900px) { | ||
main .form { | ||
padding: var(--spacing-ml); | ||
} | ||
|
||
main .form .field-wrapper { | ||
display: flex; | ||
} | ||
|
||
main .form label { | ||
width: 72%; | ||
} | ||
} |
Oops, something went wrong.