UNPKG

design-comuni-plone-theme

Version:
453 lines (437 loc) • 13.7 kB
/** * Field * @module components/manage/Blocks/IconsBlocks/View * * CUSTOMIZATIONS: * - customized to use design-react-kit elements instead semantic-ui elements */ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { useIntl, defineMessages } from 'react-intl'; import { Input, FormGroup, Label } from 'design-react-kit'; import { Icon } from 'design-comuni-plone-theme/components/ItaliaTheme'; import FileWidget from 'design-comuni-plone-theme/components/ItaliaTheme/manage/Widgets/FileWidget'; import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable'; import { TextBlockView } from '@plone/volto-slate/blocks/Text'; import { TextEditorWidget } from 'design-comuni-plone-theme/components/ItaliaTheme'; import config from '@plone/volto/registry'; import { fromHtml } from 'design-comuni-plone-theme/config/Slate/utils'; const messages = defineMessages({ select_a_value: { id: 'form_select_a_value', defaultMessage: 'Seleziona un valore', }, static_field_placeholder: { id: 'form_static_field_placeholder', defaultMessage: 'Inserisci qui il testo statico da mostrare.', }, open_menu: { id: 'open_menu', defaultMessage: 'Apri il menu', }, }); const DropdownIndicator = injectLazyLibs('reactSelect')((props) => { const intl = useIntl(); const components = props.reactSelect.components; return ( <components.DropdownIndicator {...props}> <Icon icon="chevron-down" style={{ ariaHidden: true }} title={intl.formatMessage(messages.open_menu)} /> </components.DropdownIndicator> ); }); /** * Field class. * @class View * @extends Component */ const Field = ({ label, description, name, required, field_type, field_id, input_values, value, onChange, isOnEdit, valid, disabled = false, formHasErrors = false, errorMessage, id, reactSelect, autocomplete, }) => { const intl = useIntl(); const Select = reactSelect.default; const [selected, setSelected] = useState(false); const getLabel = () => { return required ? label + ' *' : label; }; const isInvalid = () => { return !isOnEdit && !valid; }; const infoText = errorMessage ? ( <> <div className="form-text">{description}</div> {errorMessage} </> ) : ( description ); let static_text_value = value; if (field_type === 'static_text') { if (value?.data) { static_text_value = fromHtml(value); } //per retrocompatibilità con il vecchio widget che usava draftjs } return ( <div className="field"> {field_type === 'text' && ( <Input id={name} name={name} label={getLabel()} type="text" required={required} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} onChange={(e) => { onChange(name, e.target.value); }} value={value ?? ''} autoComplete={autocomplete} /> )} {field_type === 'textarea' && ( <Input id={name} name={name} label={getLabel()} tag="textarea" rows={10} required={required} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} onChange={(e) => { onChange(name, e.target.value); }} value={value ?? undefined} autoComplete={autocomplete} /> )} {field_type === 'number' && ( <Input id={name} name={name} label={getLabel()} type="number" required={required} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} onChange={(e) => { onChange(name, e.target.value); }} onKeyDown={(e) => { if ( !/[0-9eE+\-.,]/.test(e.key) && e.key !== 'Backspace' && e.key !== 'Tab' && e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' && e.key !== 'Delete' ) { e.preventDefault(); } }} value={value ?? ''} autoComplete={autocomplete} /> )} {field_type === 'select' && ( <div className="form-group"> <div className={`bootstrap-select-wrapper ${isInvalid() ? 'is-invalid' : '' }`} > <label id={`${name}-label`} htmlFor={name}> {getLabel()} </label> <Select components={{ IndicatorSeparator: null, DropdownIndicator, }} inputId={name} isSearchable={true} onChange={(v) => { onChange(name, v.value); }} options={[ ...(input_values?.map((v) => ({ value: v, label: v })) ?? []), ]} aria-live="polite" isDisabled={disabled} placeholder={intl.formatMessage(messages.select_a_value)} aria-labelledby={`${name}-label`} classNamePrefix="react-select" className={isInvalid() ? 'is-invalid' : ''} value={value ? [{ value: value, label: value }] : []} autoComplete={autocomplete} /> {description && <small className="form-text">{description}</small>} {errorMessage && ( <div className="invalid-feedback form-feedback just-validate-error-label form-text form-feedback just-validate-error-label"> {errorMessage} </div> )} </div> </div> )} {field_type === 'single_choice' && ( <div className="form-group"> <div className={`bootstrap-checkbox-radio-wrapper ${isInvalid() ? 'is-invalid' : '' }`} > <fieldset className="radio-group"> <legend>{getLabel()}</legend> {input_values?.map((v, index) => ( <FormGroup check key={v + name + index}> <Input id={v + name} name={name} type="radio" disabled={disabled} readOnly={disabled} onChange={(e) => { onChange(name, v); }} addon // Needed to avoid application of form-control class as of kit v4.0.2 checked={value === v} /> <Label for={v + name} check> {v} </Label> </FormGroup> ))} {description && ( <small className="form-text">{description}</small> )} {errorMessage && ( <div className="invalid-feedback form-feedback just-validate-error-label form-text form-feedback just-validate-error-label"> {errorMessage} </div> )} </fieldset> </div> </div> )} {field_type === 'multiple_choice' && ( <div className="form-group"> <div className={`bootstrap-checkbox-radio-wrapper ${isInvalid() ? 'is-invalid' : '' }`} > <fieldset className="checkbox-group"> <legend>{getLabel()}</legend> {input_values?.map((v, index) => ( <FormGroup check key={v + name + index}> <Input id={v + name} name={name} type="checkbox" checked={value?.indexOf(v) > -1} onChange={(e) => { let values = JSON.parse(JSON.stringify(value ?? [])); if (e.target.checked) { values.push(v); } else { values.splice(values.indexOf(v), 1); } onChange(name, values); }} invalid={isInvalid() ? 'true' : null} addon // Needed to avoid application of form-control class as of kit v4.0.2 /> <Label for={v + name} check> {v} </Label> </FormGroup> ))} {description && ( <small className="form-text">{description}</small> )} {errorMessage && ( <div className="invalid-feedback form-feedback just-validate-error-label form-text form-feedback just-validate-error-label"> {errorMessage} </div> )} </fieldset> </div> </div> )} {field_type === 'checkbox' && ( <div className="form-group"> <div className={`bootstrap-checkbox-radio-wrapper ${isInvalid() ? 'is-invalid' : '' }`} > <FormGroup check key={name}> <Input id={name} name={name} type="checkbox" checked={!!value} onChange={(e) => { onChange(name, e.target.checked); }} invalid={isInvalid() ? 'true' : null} required={required} addon // Needed to avoid application of form-control class as of kit v4.0.2 /> <Label for={name} check> {getLabel()} </Label> </FormGroup> {description && <small className="form-text">{description}</small>} {errorMessage && ( <div className="invalid-feedback form-feedback just-validate-error-label form-text form-feedback just-validate-error-label"> {errorMessage} </div> )} </div> </div> )} {field_type === 'date' && ( <Input id={name} name={name} label={getLabel()} type="date" required={required} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} onChange={(e) => { onChange(name, e.target.value); }} value={value ?? ''} autoComplete={autocomplete} /> )} {field_type === 'attachment' && ( <FileWidget id={name} name={name} label={getLabel()} type="file" required={required} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} onChange={onChange} onEdit={isOnEdit} value={value} /> )} {(field_type === 'from' || field_type === 'email') && ( <Input id={name} name={name} label={getLabel()} type="email" required={true} infoText={infoText} disabled={disabled} readOnly={disabled} invalid={isInvalid() ? 'true' : null} validationText={errorMessage} onChange={(e) => { onChange(name, e.target.value); }} value={value ?? ''} autoComplete={autocomplete} /> )} {field_type === 'static_text' && ( <> {isOnEdit ? ( <div className="mb-2"> <TextEditorWidget value={static_text_value} selected={selected} setSelected={setSelected} placeholder={intl.formatMessage( messages.static_field_placeholder, )} showToolbar={true} onChangeBlock={(block, data) => { onChange(name, data.value); }} /> </div> ) : value ? ( <div className="static-text"> <TextBlockView id={name} data={{ value: static_text_value }} /> </div> ) : ( <br /> )} </> )} {config.blocks.blocksConfig.form.additionalFields?.reduce((acc, val) => { if (val.id === field_type) return [ ...acc, <val.component id={name} name={name} title={label} description={description} infoText={infoText} required={required} onChange={onChange} value={value} isDisabled={disabled} formHasErrors={formHasErrors} invalid={isInvalid().toString()} {...(isInvalid() ? { className: 'is-invalid' } : {})} />, ]; return acc; }, []) ?? []} </div> ); }; /** * Property types. * @property {Object} propTypes Property types. * @static */ Field.propTypes = { label: PropTypes.string, name: PropTypes.string, description: PropTypes.string, required: PropTypes.bool, field_type: PropTypes.string, input_values: PropTypes.any, value: PropTypes.any, formHasErrors: PropTypes.bool, onChange: PropTypes.func, autoComplete: PropTypes.string, }; export default injectLazyLibs('reactSelect')(Field);