Skip to content

Commit

Permalink
Add wrappers for custom forms.
Browse files Browse the repository at this point in the history
  • Loading branch information
robgietema committed Nov 18, 2024
1 parent 7982b4f commit 6cd40a3
Show file tree
Hide file tree
Showing 16 changed files with 656 additions and 1 deletion.
2 changes: 2 additions & 0 deletions frontend/packages/volto-form-block/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const applyConfig = (config) => {
edit: schemaFormBlockEdit,
formSchema: FormSchema,
widgets: null,
component: null,
buttonComponent: null,
blockSchema: schemaFormBlockSchema,
fieldSchema: FieldSchema,
disableEnter: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class Edit extends Component {
title: 'Form',
type: 'object',
}}
component={config.blocks.blocksConfig.schemaForm.component}
buttonComponent={
config.blocks.blocksConfig.schemaForm.buttonComponent
}
formData={
isEmpty(data.schema)
? { schema: defaultEmptyData }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ const FormBlockView = ({ data, id, properties, metadata, path }) => {
}}
formData={initialData}
widgets={config.blocks.blocksConfig.schemaForm.widgets}
component={config.blocks.blocksConfig.schemaForm.component}
buttonComponent={
config.blocks.blocksConfig.schemaForm.buttonComponent
}
onSubmit={onSubmit}
resetOnCancel={true}
onCancel={data.show_cancel ? onCancel : null}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useRef } from 'react';
import PropTypes from 'prop-types';
import config from '@plone/volto/registry';

import FormFieldWrapper from './FormFieldWrapper';

const CheckboxGroupWrapper = (props) => {
const {
id,
value,
choices,
onChange,
onClick,
isDisabled,
title,
description,
} = props;

const ref = useRef();
const Widget =
config.blocks.blocksConfig.schemaForm.innerWidgets.checkboxGroup;
const OptionWidget =
config.blocks.blocksConfig.schemaForm.innerWidgets.checkboxGroupOption;

const options = choices || [];

return (
<FormFieldWrapper {...props} className="text">
<Widget
id={`field-${id}`}
name={id}
value={value || ''}
label={title}
description={description}
disabled={isDisabled}
onChange={(value) => onChange(id, value === '' ? undefined : value)}
ref={ref}
onClick={() => onClick()}
>
{options.map((option) => (
<OptionWidget value={option[0]}>{option[1]}</OptionWidget>
))}
</Widget>
</FormFieldWrapper>
);
};

export default CheckboxGroupWrapper;

CheckboxGroupWrapper.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useRef } from 'react';
import PropTypes from 'prop-types';
import config from '@plone/volto/registry';

import FormFieldWrapper from './FormFieldWrapper';

const CheckboxWrapper = (props) => {
const { id, value, onChange, onClick, isDisabled, title, description } =
props;

const ref = useRef();
const Widget = config.blocks.blocksConfig.schemaForm.innerWidgets.checkbox;

return (
<FormFieldWrapper {...props} className="text">
<Widget
id={`field-${id}`}
name={id}
value={value || ''}
label={title}
description={description}
disabled={isDisabled}
onChange={(value) => onChange(id, value === '' ? undefined : value)}
ref={ref}
onClick={() => onClick()}
/>
</FormFieldWrapper>
);
};

export default CheckboxWrapper;

CheckboxWrapper.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useRef } from 'react';
import PropTypes from 'prop-types';
import config from '@plone/volto/registry';

import FormFieldWrapper from './FormFieldWrapper';

const DatetimeWrapper = (props) => {
const { id, value, onChange, onClick, isDisabled, title, description } =
props;

const ref = useRef();
const Widget = config.blocks.blocksConfig.schemaForm.innerWidgets.datetime;

return (
<FormFieldWrapper {...props} className="text">
<Widget
id={`field-${id}`}
name={id}
value={value || null}
label={title}
description={description}
disabled={isDisabled}
onChange={(value) => onChange(id, value === '' ? undefined : value)}
ref={ref}
onClick={() => onClick()}
/>
</FormFieldWrapper>
);
};

export default DatetimeWrapper;

DatetimeWrapper.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useRef } from 'react';
import PropTypes from 'prop-types';
import config from '@plone/volto/registry';

import FormFieldWrapper from './FormFieldWrapper';

const EmailWrapper = (props) => {
const {
id,
value,
onChange,
onClick,
minLength,
maxLength,
isDisabled,
title,
description,
} = props;

const ref = useRef();
const Widget = config.blocks.blocksConfig.schemaForm.innerWidgets.email;

return (
<FormFieldWrapper {...props} className="text">
<Widget
id={`field-${id}`}
name={id}
value={value || ''}
label={title}
description={description}
disabled={isDisabled}
onChange={(value) => onChange(id, value === '' ? undefined : value)}
ref={ref}
onClick={() => onClick()}
minLength={minLength || null}
maxLength={maxLength || null}
/>
</FormFieldWrapper>
);
};

export default EmailWrapper;

EmailWrapper.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
minLength: null,
maxLength: null,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useRef } from 'react';
import PropTypes from 'prop-types';
import config from '@plone/volto/registry';
import { readAsDataURL } from 'promise-file-reader';

import FormFieldWrapper from './FormFieldWrapper';

const FileWrapper = (props) => {
const { id, value, onChange, isDisabled, title, description, accept, size } =
props;

const ref = useRef();
const Widget = config.blocks.blocksConfig.schemaForm.innerWidgets.file;

console.log(value);

return (
<FormFieldWrapper {...props} className="text">
<Widget
id={`field-${id}`}
name={id}
labelFile={value?.filename || ''}
label={title}
description={description}
disabled={isDisabled}
accept={accept}
size={size}
onSelect={(files) => {
if (files.length < 1) return;
const file = files[0];
readAsDataURL(file).then((data) => {
const fields = data.match(/^data:(.*);(.*),(.*)$/);
onChange(id, {
data: fields[3],
encoding: fields[2],
'content-type': fields[1],
filename: file.name,
});
});
}}
deleteFilesCallback={() => {
onChange(id, null);
}}
ref={ref}
/>
</FormFieldWrapper>
);
};

export default FileWrapper;

FileWrapper.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.object,
focus: PropTypes.bool,
onChange: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
accept: PropTypes.string,
size: PropTypes.number,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import PropTypes from 'prop-types';
import _ from 'lodash';

const FormComponent = (props) => {
const { children, onSubmit, error } = props;

const handleSubmit = (e, ...args) => {
if (typeof action !== 'string') _.invoke(e, 'preventDefault');
_.invoke(props, 'onSubmit', e, props, ...args);
};

return (
<form onSubmit={handleSubmit} className={error ? 'error' : ''}>
{children}
</form>
);
};

export default FormComponent;

FormComponent.propTypes = {
children: PropTypes.node,
onSubmit: PropTypes.func,
error: PropTypes.bool,
};
Loading

0 comments on commit 6cd40a3

Please sign in to comment.