Skip to content
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

WIP: Send empty data #84

Draft
wants to merge 48 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
461f1d8
Add UI option to 'attach XML'
JeffersonBledsoe Nov 22, 2022
17cb785
Move the 'send XML' option into a fieldset
JeffersonBledsoe Nov 22, 2022
8e4ba08
Add UI for adding custom IDs for fields
JeffersonBledsoe Nov 23, 2022
76b64f8
Use internal field_id for mapping field names
JeffersonBledsoe Nov 23, 2022
84f5f01
Send the custom_field_id to the backend
JeffersonBledsoe Nov 23, 2022
2873f8c
Fix dataIdMapping accordion key
JeffersonBledsoe Nov 23, 2022
c0a3740
Hidden field
JeffersonBledsoe Nov 28, 2022
87e6814
Change 'Checkbox' to 'Yes/ No' and allow multiple widgets
JeffersonBledsoe Nov 30, 2022
cdbd0b0
Merge branch 'yes-no-field' into deploy
JeffersonBledsoe Nov 30, 2022
8429fe8
Merge branch 'send-xml' into deploy
JeffersonBledsoe Nov 30, 2022
a91d775
Fix hidden fields not being included in form data
JeffersonBledsoe Dec 1, 2022
1f2ba42
Merge branch 'hidden-field-type' into deploy
JeffersonBledsoe Dec 1, 2022
8302596
Fix hidden fields value not being correctly sent to backend
JeffersonBledsoe Dec 1, 2022
72d24be
Merge branch 'hidden-field-type' into deploy
JeffersonBledsoe Dec 1, 2022
1d8c867
Fix crash when creating new form block
JeffersonBledsoe Dec 1, 2022
b2efeed
Add comment
JeffersonBledsoe Dec 1, 2022
0dfbb01
Merge branch 'send-xml' into deploy
JeffersonBledsoe Dec 1, 2022
e85cfe2
Initial UI for setting up acknowledgement sending
JeffersonBledsoe Dec 2, 2022
6b52065
Fix crash creating form
JeffersonBledsoe Dec 6, 2022
362ebda
Fix another crash
JeffersonBledsoe Dec 6, 2022
c7568dc
Merge branch 'main' into deploy
JeffersonBledsoe Dec 12, 2022
9f5907a
Fix crash on block creation
JeffersonBledsoe Dec 12, 2022
9d3ec31
Fix crash on block creation
JeffersonBledsoe Dec 12, 2022
0a0bd66
Merge branch 'send-xml' into deploy
JeffersonBledsoe Dec 12, 2022
327cf08
Merge branch 'send-to' into deploy
JeffersonBledsoe Dec 12, 2022
eb1e547
Fix missing conditional
JeffersonBledsoe Dec 13, 2022
6530103
Fix crash when opening existing forms
JeffersonBledsoe Dec 13, 2022
e65038b
Merge branch 'send-to' into deploy
JeffersonBledsoe Dec 13, 2022
ca857d3
Merge branch 'send-xml' into deploy
JeffersonBledsoe Dec 13, 2022
8396894
Fix crash on block creation
JeffersonBledsoe Feb 5, 2023
a1afd23
Merge branch 'send-xml' into deploy
JeffersonBledsoe Feb 5, 2023
2c065b3
Merge branch 'main' into deploy
JeffersonBledsoe Mar 7, 2023
8f2bdce
Add UI for selecting HTTP headers to forward in email
JeffersonBledsoe Mar 8, 2023
1aa4687
Add description
JeffersonBledsoe Mar 8, 2023
5a55799
Merge branch 'send-header-info' into deploy
JeffersonBledsoe Mar 8, 2023
78f61b6
Add option to change email format
JeffersonBledsoe Apr 25, 2023
ffc5c22
Use string for field_type
JeffersonBledsoe Apr 26, 2023
3a679d2
Merge branch 'fix-field-type' into deploy
JeffersonBledsoe Apr 26, 2023
b36751e
Initial UI & implementation of 'show_when'
JeffersonBledsoe Apr 27, 2023
eb16a64
Return to using only field ID for target field value
JeffersonBledsoe May 3, 2023
8ba4849
Merge branch 'showwhen' into deploy
JeffersonBledsoe May 3, 2023
d5744fc
Merge branch 'email-format' into deploy
JeffersonBledsoe May 3, 2023
aa47bdc
Update UI
JeffersonBledsoe May 17, 2023
a4c116f
Merge branch 'showwhen' into deploy
JeffersonBledsoe May 17, 2023
1b1f807
Fix bad merge
JeffersonBledsoe May 17, 2023
d215ff4
Send all fields and not just ones that haven't been filled out
JeffersonBledsoe May 24, 2023
7b4e04a
Don't attempt to send static text
JeffersonBledsoe Jun 19, 2023
ee21bed
Ensure custom field mappings are used for empty field submissions
JeffersonBledsoe Jun 20, 2023
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
65 changes: 49 additions & 16 deletions src/components/Field.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TextareaWidget,
CheckboxListWidget,
RadioWidget,
HiddenWidget,
} from 'volto-form-block/components/Widget';
import config from '@plone/volto/registry';

Expand All @@ -25,32 +26,61 @@ const messages = defineMessages({
},
});

const widgetMapping = {
single_choice: RadioWidget,
checkbox: CheckboxWidget,
};

/**
* Field class.
* @class View
* @extends Component
*/
const Field = ({
label,
description,
name,
field_type,
required,
input_values,
value,
onChange,
isOnEdit,
valid,
disabled = false,
formHasErrors = false,
id,
}) => {
const Field = (props) => {
const {
label,
description,
name,
field_type,
required,
input_values,
value,
onChange,
isOnEdit,
valid,
disabled = false,
formHasErrors = false,
id,
widget,
} = props;
const intl = useIntl();

const isInvalid = () => {
return !isOnEdit && !valid;
};

if (widget) {
const Widget = widgetMapping[widget];
const valueList =
field_type === 'yes_no'
? [
{ value: true, label: 'Yes' },
{ value: false, label: 'No' },
]
: [...(input_values?.map((v) => ({ value: v, label: v })) ?? [])];

return (
<Widget
{...props}
id={name}
title={label}
valueList={valueList}
invalid={isInvalid().toString()}
{...(isInvalid() ? { className: 'is-invalid' } : {})}
/>
);
}

return (
<div className="field">
{field_type === 'text' && (
Expand Down Expand Up @@ -135,7 +165,7 @@ const Field = ({
{...(isInvalid() ? { className: 'is-invalid' } : {})}
/>
)}
{field_type === 'checkbox' && (
{(field_type === 'yes_no' || field_type === 'checkbox') && (
<CheckboxWidget
id={name}
name={name}
Expand Down Expand Up @@ -195,6 +225,9 @@ const Field = ({
{...(isInvalid() ? { className: 'is-invalid' } : {})}
/>
)}
{field_type === 'hidden' && (
<HiddenWidget id={name} value={value} isOnEdit={isOnEdit} />
)}
{field_type === 'static_text' &&
(isOnEdit ? (
<WysiwygWidget
Expand Down
20 changes: 20 additions & 0 deletions src/components/FieldTypeSchemaExtenders/HiddenSchemaExtender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineMessages } from 'react-intl';
const messages = defineMessages({
field_input_value: {
id: 'form_field_input_value',
defaultMessage: 'Value for field',
},
});

export const HiddenSchemaExtender = (intl) => {
return {
fields: ['value'],
properties: {
value: {
title: intl.formatMessage(messages.field_input_value),
type: 'text',
},
},
required: ['value'],
};
};
25 changes: 25 additions & 0 deletions src/components/FieldTypeSchemaExtenders/YesNoSchemaExtender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineMessages } from 'react-intl';
const messages = defineMessages({
field_widget: {
id: 'form_field_widget',
defaultMessage: 'Widget',
},
});

export const YesNoSchemaExtender = (intl) => {
return {
fields: ['widget'],
properties: {
widget: {
title: intl.formatMessage(messages.field_widget),
type: 'array',
choices: [
['checkbox', 'Checkbox'],
['single_choice', 'Radio'],
],
default: 'checkbox',
},
},
required: ['widget'],
};
};
2 changes: 2 additions & 0 deletions src/components/FieldTypeSchemaExtenders/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { SelectionSchemaExtender } from './SelectionSchemaExtender';
export { FromSchemaExtender } from './FromSchemaExtender';
export { HiddenSchemaExtender } from './HiddenSchemaExtender';
export { YesNoSchemaExtender } from './YesNoSchemaExtender';
31 changes: 26 additions & 5 deletions src/components/FormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from 'semantic-ui-react';
import { getFieldName } from 'volto-form-block/components/utils';
import Field from 'volto-form-block/components/Field';
import { showWhenValidator } from 'volto-form-block/helpers/show_when';
import config from '@plone/volto/registry';

/* Style */
Expand Down Expand Up @@ -134,6 +135,30 @@ const FormView = ({
}),
);

const value =
subblock.field_type === 'static_text'
? subblock.value
: formData[name]?.value;
const { show_when, target_value } = subblock;

const shouldShowValidator = showWhenValidator[show_when];
const shouldShowTargetValue =
formData[subblock.target_field]?.value;

// Only checking for false here to preserve backwards compatibility with blocks that haven't been updated and so have a value of 'undefined' or 'null'
const shouldShow = shouldShowValidator
? shouldShowValidator({
value: shouldShowTargetValue,
target_value: target_value,
}) !== false
: true;

const shouldHide = __CLIENT__ && !shouldShow;

if (shouldHide) {
return <p key={'row' + index}>Empty</p>;
}

return (
<Grid.Row key={'row' + index}>
<Grid.Column>
Expand All @@ -148,11 +173,7 @@ const FormView = ({
fields_to_send_with_value,
)
}
value={
subblock.field_type === 'static_text'
? subblock.value
: formData[name]?.value
}
value={value}
valid={isValidField(name)}
formHasErrors={formErrors?.length > 0}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ const Sidebar = ({
</Accordion.Title>
<Accordion.Content active={selected === index}>
<BlockDataForm
schema={FieldSchema(subblock)}
schema={FieldSchema({ ...subblock, formData: data })}
onChangeField={(name, value) => {
var update_values = {};

Expand Down
64 changes: 53 additions & 11 deletions src/components/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,32 @@ const formStateReducer = (state, action) => {
}
};

const getInitialData = (data) => ({
...data.reduce(
(acc, field) => ({ ...acc, [getFieldName(field.label, field.id)]: field }),
{},
),
});
const getInitialData = (data) => {
const { static_fields = [], subblocks = [] } = data;

return {
...subblocks.reduce(
(acc, field) =>
field.field_type === 'hidden'
? {
...acc,
[getFieldName(field.label, field.id)]: {
...field,
...(data[field.id] && { custom_field_id: data[field.id] }),
},
}
: acc,
{},
),
...static_fields.reduce(
(acc, field) => ({
...acc,
[getFieldName(field.label, field.id)]: field,
}),
{},
),
};
};

/**
* Form view
Expand All @@ -62,26 +82,33 @@ const getInitialData = (data) => ({
const View = ({ data, id, path }) => {
const intl = useIntl();
const dispatch = useDispatch();
const { static_fields = [] } = data;

const [formData, setFormData] = useReducer((state, action) => {
if (action.reset) {
return getInitialData(static_fields);
return getInitialData(data);
}

return {
...state,
[action.field]: action.value,
};
}, getInitialData(static_fields));
}, getInitialData(data));

const [formState, setFormState] = useReducer(formStateReducer, initialState);
const [formErrors, setFormErrors] = useState([]);
const submitResults = useSelector((state) => state.submitForm);
const captchaToken = useRef();

const onChangeFormData = (field_id, field, value, extras) => {
setFormData({ field, value: { field_id, value, ...extras } });
setFormData({
field,
value: {
field_id,
value,
...(data[field_id] && { custom_field_id: data[field_id] }), // Conditionally add the key. Nicer to work with than having a key with a null value
...extras,
},
});
};

useEffect(() => {
Expand Down Expand Up @@ -145,7 +172,22 @@ const View = ({ data, id, path }) => {
captcha.value = formData[data.captcha_props.id]?.value ?? '';
}

let formattedFormData = { ...formData };
let formattedFormData = data.subblocks.reduce(
(returnValue, field) => {
if (field.field_type === 'static_text') {
return returnValue;
}
const fieldName = getFieldName(field.label, field.id);
const dataToAdd = formData[fieldName] ?? {
field_id: field.id,
label: field.label,
value: null,
...(data[field.id] && { custom_field_id: data[field.id] }), // Conditionally add the key. Nicer to work with than having a key with a null value
};
return { ...returnValue, [fieldName]: dataToAdd };
},
{},
);
data.subblocks.forEach((subblock) => {
let name = getFieldName(subblock.label, subblock.id);
if (formattedFormData[name]?.value) {
Expand Down
33 changes: 33 additions & 0 deletions src/components/Widget/HiddenWidget.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import PropTypes from 'prop-types';

/**
* Displays an `<input type="hidden" />`.
*/
export const HiddenWidget = ({ id, title, value, isOnEdit }) => {
const inputId = `field-${id}`;
return (
<>
{isOnEdit ? <label htmlFor={inputId}>Hidden: {title || id}</label> : null}
<input type="hidden" id={inputId} name={id} value={value} />
</>
);
};

HiddenWidget.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onBlur: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
minLength: PropTypes.number,
maxLength: PropTypes.number,
wrapped: PropTypes.bool,
placeholder: PropTypes.string,
};
1 change: 1 addition & 0 deletions src/components/Widget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as EmailWidget } from 'volto-form-block/components/Widget/Email
export { default as FileWidget } from 'volto-form-block/components/Widget/FileWidget';
export { default as GoogleReCaptchaWidget } from 'volto-form-block/components/Widget/GoogleReCaptchaWidget';
export { default as HCaptchaWidget } from 'volto-form-block/components/Widget/HCaptchaWidget';
export { HiddenWidget } from 'volto-form-block/components/Widget/HiddenWidget';
export { default as HoneypotCaptchaWidget } from 'volto-form-block/components/Widget/HoneypotCaptchaWidget';
export { default as NoRobotsCaptchaWidget } from 'volto-form-block/components/Widget/NoRobotsCaptchaWidget';
export { default as RadioWidget } from 'volto-form-block/components/Widget/RadioWidget';
Expand Down
Loading