UNPKG

design-comuni-plone-theme

Version:
338 lines (322 loc) 10.4 kB
/** * MenuConfigurationForm * @module components/src/widget/MenuConfigurationForm.jsx * Customized via component registry: * - added new select field with lighthouse options */ import React, { useEffect } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { v4 as uuid } from 'uuid'; import { isEmpty } from 'lodash'; import { Form as UIForm, Grid, Button } from 'semantic-ui-react'; import { Form, TextWidget, CheckboxWidget, ObjectBrowserWidget, Sidebar, SelectWidget, } from '@plone/volto/components'; import RadioWidget from 'volto-dropdownmenu/widget/RadioWidget'; /* import SelectWidget from './SelectWidget'; */ import { Portal } from 'react-portal'; import config from '@plone/volto/registry'; const messages = defineMessages({ title: { id: 'dropdownmenu-title', defaultMessage: 'Title', }, visible: { id: 'dropdownmenu-visible', defaultMessage: 'Visible', }, mode: { id: 'dropdownmenu-mode', defaultMessage: 'Mode', }, modeSimpleLink: { id: 'dropdownmenu-mode-simpleLink', defaultMessage: 'Simple link', }, modeDropdown: { id: 'dropdownmenu-mode-dropdown', defaultMessage: 'Dropdown', }, linkUrl: { id: 'dropdownmenu-linkUrl', defaultMessage: 'Link', }, navigationRoot: { id: 'dropdownmenu-navigationRoot', defaultMessage: 'Navigation root', }, showMoreLink: { id: 'dropdownmenu-showMoreLink', defaultMessage: '"Show more" link', }, showMoreText: { id: 'dropdownmenu-showMoreText', defaultMessage: '"Show more" link text', }, additionalClasses: { id: 'dropdownmenu-additionalClasses', defaultMessage: 'Additional classes', }, additionalClassesDescription: { id: 'dropdownmenu-additionalClassesDescription', defaultMessage: 'Additional classes for the item to apply specific styles, accordingly to site layout.', }, blocks: { id: 'dropdownmenu-blocks', defaultMessage: 'Blocks', }, blocks_description: { id: 'dropdownmenu-blocks-description', defaultMessage: 'Add some blocks to show in dropdown menu.', }, deleteMenuItem: { id: 'dropdownmenu-deletemenuitem', defaultMessage: 'Delete menu item', }, deleteButton: { id: 'dropdownmenu-deletemenuitem-button', defaultMessage: 'Delete menu item', }, id_lighthouse: { id: 'ID lighthouse', defaultMessage: 'ID lighthouse', }, id_lighthouse_description: { id: 'ID Lighthouse Help Description', defaultMessage: 'Identificativo di servizio a solo uso interno, utilizzato per le verifiche AgID inerenti al PNRR.', }, }); const MenuConfigurationForm = ({ id, menuItem, onChange, deleteMenuItem }) => { const intl = useIntl(); const defaultBlockId = uuid(); if (!menuItem.blocks_layout || isEmpty(menuItem.blocks_layout.items)) { menuItem.blocks_layout = { items: [defaultBlockId], }; } if (!menuItem.blocks || isEmpty(menuItem.blocks)) { menuItem.blocks = { [defaultBlockId]: { '@type': config.settings.defaultBlockType, }, }; } useEffect(() => { // Get the main Volto HTML form const form = document.querySelector('form.ui.form'); // Handler to block any type of submit const preventSubmit = (e) => { e.preventDefault(); e.stopPropagation(); }; // global handler to stop Enter from submitting inputs // exception: menu-blocks-container (to add slate blocks) const handleEnter = (e) => { if (e.key === 'Enter') { const targetForm = e.target.closest('form.ui.form'); if (targetForm) { const inBlocks = e.target.closest('.menu-blocks-container'); if (inBlocks) { // allow enter to add blocks (React/Volto create new blocks) return; } // block enter everywhere else to prevent unwanted submit e.preventDefault(); e.stopPropagation(); } } }; // prevent native submits (click on buttons that have type submit, etc.) form?.addEventListener('submit', preventSubmit, true); // Block Enter outside blocks document.addEventListener('keydown', handleEnter, true); return () => { // Cleanup all listeners form?.removeEventListener('submit', preventSubmit, true); document.removeEventListener('keydown', handleEnter, true); }; }, []); const onChangeFormData = (id, value) => { onChange({ ...menuItem, [id]: value }); }; const onChangeFormBlocks = (data) => { onChange({ ...menuItem, blocks: data.blocks, blocks_layout: data.blocks_layout, }); }; return ( <> <TextWidget id={`${id}-title`} title={intl.formatMessage(messages.title)} description="" required={true} value={menuItem.title} onChange={(id, value) => onChangeFormData('title', value)} className="menu-item-field-title" /> <SelectWidget id={`${id}-lighthouse`} title={intl.formatMessage(messages.id_lighthouse)} description={intl.formatMessage(messages.id_lighthouse_description)} choices={[ ['all-services', 'all-services'], ['management', 'management'], ['live', 'live'], ['news', 'news'], ['all-topics', 'all-topics'], ['custom-submenu', 'custom-submenu'], ]} value={menuItem.id_lighthouse} onChange={(id, value) => onChangeFormData('id_lighthouse', value)} aria-label="aria-label" className="id_lighthouse" /> <CheckboxWidget id={`${id}-visible`} title={intl.formatMessage(messages.visible)} description="" defaultValue={true} value={!!menuItem.visible} onChange={(id, value) => onChangeFormData('visible', value)} className="menu-item-field-visible" /> <RadioWidget id={`${id}-mode`} title={intl.formatMessage(messages.mode)} description="" required={true} value={menuItem.mode} onChange={(id, value) => onChangeFormData('mode', value)} valueList={[ { value: 'simpleLink', label: intl.formatMessage(messages.modeSimpleLink), }, { value: 'dropdown', label: intl.formatMessage(messages.modeDropdown), }, ]} className="menu-item-field-mode" /> {menuItem.mode === 'simpleLink' && ( <ObjectBrowserWidget id={`${id}-linkUrl`} title={intl.formatMessage(messages.linkUrl)} description="" required={true} mode="link" value={menuItem.linkUrl ?? []} onChange={(id, value) => onChangeFormData('linkUrl', value)} className="menu-item-field-linkUrl" /> )} {menuItem.mode === 'dropdown' && ( <React.Fragment> <div className="menu-item-field-navigationRoot"> <ObjectBrowserWidget id={`${id}-navigationRoot`} title={intl.formatMessage(messages.navigationRoot)} description="" required={true} value={menuItem.navigationRoot ?? []} onChange={(id, value) => onChangeFormData('navigationRoot', value) } /> </div> <div className="menu-item-field-showMoreLink"> <ObjectBrowserWidget id={`${id}-showMoreLink`} title={intl.formatMessage(messages.showMoreLink)} description="" mode="link" value={menuItem.showMoreLink ?? []} onChange={(id, value) => onChangeFormData('showMoreLink', value)} /> </div> <div className="menu-item-field-showMoreText"> <TextWidget id={`${id}-showMoreText`} title={intl.formatMessage(messages.showMoreText)} description="" value={menuItem.showMoreText} onChange={(id, value) => onChangeFormData('showMoreText', value)} /> </div> <div className="menu-item-field-additionalClasses"> <TextWidget id={`${id}-additionalClasses`} title={intl.formatMessage(messages.additionalClasses)} description={intl.formatMessage( messages.additionalClassesDescription, )} value={menuItem.additionalClasses} onChange={(id, value) => onChangeFormData('additionalClasses', value) } /> </div> <UIForm.Field inline className="help wide" id="menu-blocks"> <Grid> <Grid.Row stretched> <Grid.Column width={12}> <div className="wrapper"> <p className="help"> {intl.formatMessage(messages.blocks_description)} </p> </div> </Grid.Column> </Grid.Row> <Grid.Row stretched> <Grid.Column width={12}> <div className="menu-blocks-container"> <Form key={id} formData={menuItem} visual={true} hideActions onChangeFormData={onChangeFormBlocks} /> </div> </Grid.Column> </Grid.Row> </Grid> </UIForm.Field> </React.Fragment> )} <UIForm.Field inline className="delete wide" id="menu-delete"> <Grid> <Grid.Row stretched> <Grid.Column width={4}> <div className="wrapper"></div> </Grid.Column> <Grid.Column width={8}> <Button icon="trash" onClick={deleteMenuItem} id="delete-menuitem" negative content={intl.formatMessage(messages.deleteButton)} /> </Grid.Column> </Grid.Row> </Grid> </UIForm.Field> <Portal node={document.getElementById('sidebar')}> <Sidebar /> </Portal> </> ); }; export default React.memo(MenuConfigurationForm);