Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion blocks/form/_form.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@
"telephone-input",
"text-input",
"tnc",
"wizard"
"wizard",
"review"
]
}
]
Expand Down
140 changes: 140 additions & 0 deletions blocks/form/components/review/_review.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
{
"definitions": [
{
"title": "Review",
"id": "review",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/fd/components/form/panelcontainer/v1/panelcontainer",
"template": {
"jcr:title": "Review",
"fieldType": "panel",
"fd:viewType": "review"
}
}
}
}
}
],
"models": [
{
"id": "review",
"fields": [
{
"component": "container",
"name": "basic",
"label": "Basic",
"collapsible": false,
"fields": [
{
"component": "text",
"name": "name",
"label": "Name",
"valueType": "string",
"required": true,
"valueFormat": "regexp",
"validation": {
"regExp": "^[^$].*",
"customErrorMsg": "Name cannot start with $"
}
},
{
"component": "text",
"name": "jcr:title",
"label": "Title",
"valueType": "string"
},
{
"component": "boolean",
"name": "hideTitle",
"label": "Hide title",
"valueType": "boolean"
},
{
"component": "boolean",
"name": "unboundFormElement",
"label": "Mark as Unbound Form Element",
"valueType": "boolean"
},
{
"component": "boolean",
"name": "visible",
"label": "Show Component",
"valueType": "boolean",
"value": true
},
{
"component": "select",
"name": "colspan",
"label": "Column Span",
"valueType": "string",
"value": "12",
"options": [
{
"name": "1 column",
"value": "1"
},
{
"name": "2 column",
"value": "2"
},
{
"name": "3 column",
"value": "3"
},
{
"name": "4 column",
"value": "4"
},
{
"name": "5 column",
"value": "5"
},
{
"name": "6 column",
"value": "6"
},
{
"name": "7 column",
"value": "7"
},
{
"name": "8 column",
"value": "8"
},
{
"name": "9 column",
"value": "9"
},
{
"name": "10 column",
"value": "10"
},
{
"name": "11 column",
"value": "11"
},
{
"name": "12 column",
"value": "12"
}
]
}
]
},
{
"component": "text",
"name": "panelNames",
"label": "Panel Names",
"valueType": "string",
"multi": true,
"required": true
},
{
"...": "../../models/form-common/_help-container.json"
}
]
}
]
}
41 changes: 41 additions & 0 deletions blocks/form/components/review/review.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:root {
--color-action-border-primary-disabled: #a3baf9;
}

main .form form .review-container {
display: block;
}

main .form .review-container label {
margin:0;
position: relative;
}

main .form form:not(.edit-mode) .review-container .field-wrapper:not(.panel-wrapper, .plain-text-wrapper, .file-wrapper) {
border-left: 3px solid var(--color-action-border-primary-disabled);
padding-left: 1rem;
padding-right: 1rem;

}

main .form .review-panel-wrapper {
display: grid;
}

main .form .review-panel-wrapper .checkbox-wrapper {
margin: 5px;
}

main .form form.edit-mode .review-container .field-wrapper {
display: none;
}

main .form form.edit-mode .review-container::after {
content: 'Review of selected panels will appear here';
font-size: 20px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;

}
111 changes: 111 additions & 0 deletions blocks/form/components/review/review.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { subscribe } from '../../rules/index.js';
import { generateFormRendition } from '../../form.js';

function createReviewFieldElement(item) {
const {
value, name, fieldType, enumNames,
} = item;
const divElement = document.createElement('div');
divElement.className = `review-field-value ${name}`;
if (fieldType === 'radio-group' || fieldType === 'checkbox-group' || fieldType === 'drop-down') {
const index = item?.enum?.indexOf(value);
if (index !== -1) {
divElement.textContent = enumNames[index] || item?.enum?.[index] || value;
}
} else {
divElement.textContent = value || '';
}

return divElement;
}

function replaceInputs(element, model) {
function processItem(item) {
if (item.isContainer) {
item.items?.forEach(processItem);
return;
}
const { fieldType, id } = item;

if (fieldType === 'button') {
element.querySelector(`[data-id="${id}"]`)?.remove();
return;
}

if (!item.value || !item.id) return;
const divElement = createReviewFieldElement(item);

if (fieldType === 'radio-group' || fieldType === 'checkbox-group') {
const group = element.querySelector(`fieldset[data-id="${id}"]`);
if (group) {
group.querySelectorAll('.radio-wrapper, .checkbox-wrapper').forEach((wrapper) => wrapper.remove());
group.appendChild(divElement);
}
} else if (fieldType === 'checkbox') {
const input = element.querySelector(`input[id="${id}"]`);
if (input) {
const label = input.parentNode.querySelector('label');
input.parentNode.insertBefore(divElement, label.nextSibling);
input.remove();
}
} else {
const input = element.querySelector(`input[id="${id}"], select[id="${id}"], textarea[id="${id}"]`);
input?.parentNode.replaceChild(divElement, input);
}
}

model.items?.forEach(processItem);
return element;
}

function render(element, fd, model) {
if (!model) return;

const { form } = model;
const { properties } = fd;

if (!properties?.panelNames) return;

element.innerHTML = '';

const panelModels = [];
form.visit((field) => {
if (properties.panelNames.includes(field.name)) {
panelModels.push(field);
}
});

panelModels.forEach(async (field) => {
if (!field.isContainer) return;

const panelWrapper = document.createElement('div');
panelWrapper.className = `review-panel-wrapper ${field.name}`;

await generateFormRendition(field.getState(), panelWrapper, form.id);
const decoratedPanel = replaceInputs(panelWrapper, field);

if (!decoratedPanel) return;

element.appendChild(panelWrapper);
});
}

export default function decorate(element, fd, container, formId) {
element.classList.add('review-container');
let fieldModel;

subscribe(element, formId, (_element, model) => {
fieldModel = model;
});

const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
render(element, fd, fieldModel);
}
});
}, { threshold: 0.1 });

observer.observe(element);
return element;
}
2 changes: 1 addition & 1 deletion blocks/form/mappings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { loadCSS } from '../../scripts/aem.js';

let customComponents = [];
let customComponents = ['review'];
const OOTBComponentDecorators = ['file-input', 'wizard', 'modal', 'tnc', 'toggleable-link', 'rating', 'datetime', 'list', 'location', 'accordion', 'password'];

export function setCustomComponents(components) {
Expand Down
32 changes: 16 additions & 16 deletions component-definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,22 @@
}
}
},
{
"title": "Review",
"id": "review",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/fd/components/form/panelcontainer/v1/panelcontainer",
"template": {
"jcr:title": "Review",
"fieldType": "panel",
"fd:viewType": "review"
}
}
}
}
},
{
"title": "Terms and conditions",
"id": "tnc",
Expand Down Expand Up @@ -659,22 +675,6 @@
}
}
}
},
{
"title": "Order Accordion",
"id": "order-accordion",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/franklin/components/block/v1/block",
"template": {
"name": "Order Accordion",
"filter": "order-accordion",
"fd:viewType": "order-accordion"
}
}
}
}
}
]
}
Expand Down
6 changes: 3 additions & 3 deletions component-filters.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
"columns",
"fragment",
"form",
"embed-adaptive-form",
"order-accordion"
"embed-adaptive-form"
]
},
{
Expand Down Expand Up @@ -68,7 +67,8 @@
"telephone-input",
"text-input",
"tnc",
"wizard"
"wizard",
"review"
]
}
]
Loading
Loading