UNPKG

@plone/volto

Version:
213 lines (197 loc) 5.74 kB
import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { compose } from 'redux'; import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable'; import { getSchema } from '@plone/volto/actions/schema/schema'; import { updateContent, getContent, } from '@plone/volto/actions/content/content'; import { getLayoutFieldname } from '@plone/volto/helpers/Content/Content'; import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious'; import { FormFieldWrapper } from '@plone/volto/components/manage/Widgets'; import Icon from '@plone/volto/components/theme/Icon/Icon'; import { defineMessages, useIntl } from 'react-intl'; import config from '@plone/volto/registry'; import downSVG from '@plone/volto/icons/down-key.svg'; import upSVG from '@plone/volto/icons/up-key.svg'; import checkSVG from '@plone/volto/icons/check.svg'; const messages = defineMessages({ Viewmode: { id: 'Viewmode', defaultMessage: 'View', }, }); const Option = injectLazyLibs('reactSelect')((props) => { const { Option } = props.reactSelect.components; return ( <Option {...props}> <div>{props.label}</div> {props.isFocused && !props.isSelected && ( <Icon name={checkSVG} size="18px" color="#b8c6c8" /> )} {props.isSelected && <Icon name={checkSVG} size="18px" color="#007bc1" />} </Option> ); }); const DropdownIndicator = injectLazyLibs('reactSelect')((props) => { const { DropdownIndicator } = props.reactSelect.components; return ( <DropdownIndicator {...props}> {props.selectProps.menuIsOpen ? ( <Icon name={upSVG} size="24px" color="#007bc1" /> ) : ( <Icon name={downSVG} size="24px" color="#007bc1" /> )} </DropdownIndicator> ); }); const selectTheme = (theme) => ({ ...theme, borderRadius: 0, colors: { ...theme.colors, primary25: 'hotpink', primary: '#b8c6c8', }, }); const customSelectStyles = { control: (styles, state) => ({ ...styles, border: 'none', borderBottom: '2px solid #b8c6c8', boxShadow: 'none', borderBottomStyle: state.menuIsOpen ? 'dotted' : 'solid', }), menu: (styles, state) => ({ ...styles, top: null, marginTop: 0, boxShadow: 'none', borderBottom: '2px solid #b8c6c8', }), menuList: (styles, state) => ({ ...styles, maxHeight: '400px', }), indicatorSeparator: (styles) => ({ ...styles, width: null, }), valueContainer: (styles) => ({ ...styles, padding: 0, }), option: (styles, state) => ({ ...styles, backgroundColor: null, minHeight: '50px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 12px', color: state.isSelected ? '#007bc1' : state.isFocused ? '#4a4a4a' : 'inherit', ':active': { backgroundColor: null, }, span: { flex: '0 0 auto', }, svg: { flex: '0 0 auto', }, }), }; const DisplaySelect = (props) => { const { pathname } = props; const intl = useIntl(); const dispatch = useDispatch(); const loaded = useSelector((state) => state.content.update.loaded); const layouts = useSelector((state) => state.schema.schema ? state.schema.schema.layouts : [], ); const layout = useSelector((state) => state.content.data ? state.content.data[getLayoutFieldname(state.content.data)] : '', ); const layoutMappingId = config.views.layoutViewsNamesMapping?.[layout]; const [selectedOption, setselectedOption] = useState({ value: layout, label: layoutMappingId ? intl.formatMessage({ id: layoutMappingId, defaultMessage: layoutMappingId, }) : layout, }); const type = useSelector((state) => state.content.data ? state.content.data['@type'] : '', ); const prevloaded = usePrevious(loaded); const prevpathname = usePrevious(pathname); useEffect(() => { dispatch(getSchema(type)); }, [dispatch, type]); useEffect(() => { if (pathname !== prevpathname) { dispatch(getSchema(type)); } if (!prevloaded && loaded) { dispatch(getContent(pathname)); } }, [dispatch, type, pathname, prevpathname, prevloaded, loaded]); const setLayout = (selectedOption) => { dispatch( updateContent(pathname, { layout: selectedOption.value, }), ); setselectedOption(selectedOption); }; const Select = props.reactSelect.default; const layoutsNames = config.views.layoutViewsNamesMapping; const layoutOptions = layouts .filter( (layout) => Object.keys(config.views.contentTypesViews).includes(layout) || Object.keys(config.views.layoutViews).includes(layout), ) .map((item) => ({ value: item, label: intl.formatMessage({ id: layoutsNames[item], defaultMessage: layoutsNames[item], }) || item, })); return layoutOptions?.length > 1 ? ( <FormFieldWrapper id="display-select" title={intl.formatMessage(messages.Viewmode)} {...props} > <Select name="display-select" className="react-select-container" classNamePrefix="react-select" options={layoutOptions} styles={customSelectStyles} theme={selectTheme} components={{ DropdownIndicator, Option }} onChange={setLayout} defaultValue={selectedOption} isSearchable={false} /> </FormFieldWrapper> ) : null; }; DisplaySelect.propTypes = { pathname: PropTypes.string.isRequired, }; export default compose(injectLazyLibs('reactSelect'))(DisplaySelect);