diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelector.js b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelector.js index 084874e4eb..4ec9816566 100644 --- a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelector.js +++ b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelector.js @@ -2,7 +2,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import SelectBox from '@neos-project/react-ui-components/src/SelectBox/'; import style from './style.module.css'; -import {$get, $transform} from 'plow-js'; +import {$transform} from 'plow-js'; import mapValues from 'lodash.mapvalues'; import sortBy from 'lodash.sortby'; import {neos} from '@neos-project/neos-ui-decorators'; @@ -48,9 +48,11 @@ export default class DimensionSelector extends PureComponent { (presetConfiguration, presetName) => { return $transform( { - label: $get('label'), + label: presetConfiguration?.label, value: presetName, - disallowed: $get('disallowed') + disallowed: presetConfiguration?.disallowed, + existing: presetConfiguration?.existing, + url: presetConfiguration?.url }, presetConfiguration ); diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelectorOption.js b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelectorOption.js index e580931b2f..ea8e0402f6 100644 --- a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelectorOption.js +++ b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/DimensionSelectorOption.js @@ -1,25 +1,51 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import style from './style.module.css'; -// eslint-disable-next-line camelcase +import SelectBox_Option_SingleLineLink from '@neos-project/react-ui-components/src/SelectBox_Option_SingleLineLink/index'; import SelectBox_Option_SingleLine from '@neos-project/react-ui-components/src/SelectBox_Option_SingleLine/index'; +import mergeClassNames from 'classnames'; export default class DimensionSelectorOption extends PureComponent { static propTypes = { option: PropTypes.shape({ label: PropTypes.string.isRequired, - disallowed: PropTypes.bool + disallowed: PropTypes.bool, + existing: PropTypes.bool, + url: PropTypes.string }) }; render() { const {option} = this.props; + const className = mergeClassNames({ + [style.lighter]: !option.existing, + [style.strikethrough]: option.disallowed + }); + + if (option.existing) { + const linkOptions = { + className: style.whiteLink, + href: option.url, + target: '_blank', + rel: 'noopener noreferrer', + onClick: (event) => event.preventDefault() + } + + return ( + + ); + } + return ( - // eslint-disable-next-line camelcase ); diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/index.js b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/index.js index 1c71e90942..3ecf7ac612 100644 --- a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/index.js +++ b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/index.js @@ -33,7 +33,9 @@ SelectedPreset.propTypes = { @connect($transform({ contentDimensions: selectors.CR.ContentDimensions.byName, allowedPresets: selectors.CR.ContentDimensions.allowedPresets, - activePresets: selectors.CR.ContentDimensions.activePresets + activePresets: selectors.CR.ContentDimensions.activePresets, + getNodeByContextPath: selectors.CR.Nodes.nodeByContextPath, + documentNode: selectors.CR.Nodes.documentNodeSelector }), { selectPreset: actions.CR.ContentDimensions.selectPreset, setAllowed: actions.CR.ContentDimensions.setAllowed @@ -255,15 +257,58 @@ export default class DimensionSwitcher extends PureComponent { return null; } + getExistingDimensions() { + const allowed = this.props.allowedPresets + const currentDocumentNode = this.props.getNodeByContextPath(this.props.documentNode.contextPath) + const dimensionsWithVariants = currentDocumentNode?.otherNodeVariants; + if (!dimensionsWithVariants) { + return [currentDocumentNode.dimensions] + } + + const existingDimensions = {}; + Object.keys(allowed).forEach((dimensionName) => { + const dimensionValues = allowed[dimensionName]; + + existingDimensions[dimensionName] = []; + Array.from(dimensionValues).forEach((dimensionValue) => { + const result = [...dimensionsWithVariants, currentDocumentNode.dimensions].find((dimension) => { + return dimension[dimensionName] === dimensionValue; + }); + if (result) { + existingDimensions[dimensionName].push(dimensionValue); + } + }); + }); + + return existingDimensions; + } + presetsForDimension(dimensionName) { const {contentDimensions, allowedPresets, i18nRegistry} = this.props; const dimensionConfiguration = $get(dimensionName, contentDimensions); + const existingDimensions = this.getExistingDimensions(); return mapValues(dimensionConfiguration.presets, (presetConfiguration, presetName) => { + // if we do not know which dimensions exist, show all as existing + let existing = existingDimensions.length === 1 && existingDimensions[0] === undefined; + for (const value of presetConfiguration.values) { + if (existingDimensions[dimensionName]?.includes(value)) { + existing = true; + } + } + + const uri = new URL(window.location.href); + const contextPathWithoutDimensions = this.props.documentNode.contextPath.split(';')[0]; + const uriDimension = ';' + dimensionName + '=' + presetConfiguration.values.join(',') + uri.searchParams.set('node', contextPathWithoutDimensions + uriDimension); + const url = uri.toString(); + return Object.assign({}, presetConfiguration, { label: i18nRegistry.translate(presetConfiguration.label), - disallowed: !(allowedPresets[dimensionName] && allowedPresets[dimensionName].includes(presetName)) + disallowed: !(allowedPresets[dimensionName] && allowedPresets[dimensionName].includes(presetName)), + existing, + url }); }); } diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/style.module.css b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/style.module.css index d3a87a2db3..3ca0316d25 100644 --- a/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/style.module.css +++ b/packages/neos-ui/src/Containers/PrimaryToolbar/DimensionSwitcher/style.module.css @@ -60,8 +60,16 @@ } } -.dimmed { - filter: opacity(50%); +.strikethrough { + text-decoration: line-through; +} + +.lighter { + filter: opacity(75%); +} + +.whiteLink { + color: white; } .selectPreset + .selectPreset { diff --git a/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/index.js b/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/index.js new file mode 100644 index 0000000000..555e6811d6 --- /dev/null +++ b/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/index.js @@ -0,0 +1,4 @@ +/* eslint-disable camelcase, react/jsx-pascal-case */ +import SelectBox_Option_SingleLineLink from './selectBox_Option_SingleLineLink'; + +export default SelectBox_Option_SingleLineLink; diff --git a/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/selectBox_Option_SingleLineLink.js b/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/selectBox_Option_SingleLineLink.js new file mode 100644 index 0000000000..e822fa58d3 --- /dev/null +++ b/packages/react-ui-components/src/SelectBox_Option_SingleLineLink/selectBox_Option_SingleLineLink.js @@ -0,0 +1,39 @@ +/* eslint-disable camelcase, react/jsx-pascal-case */ +import React, {PureComponent} from 'react'; +import PropTypes from 'prop-types'; +import ListPreviewElement from '../ListPreviewElement'; +import mergeClassNames from 'classnames'; + +class SelectBox_Option_SingleLineLink extends PureComponent { + static propTypes = { + option: PropTypes.shape({ + label: PropTypes.string.isRequired, + icon: PropTypes.string, + disabled: PropTypes.bool + }).isRequired, + + disabled: PropTypes.bool, + + className: PropTypes.string + } + + render() { + const {option, className, disabled, icon, linkOptions} = this.props; + + const isDisabled = disabled || option.disabled; + + const finalClassNames = mergeClassNames({ + [className]: className + }); + + const previewElementIcon = option.icon ? option.icon : (icon ? icon : null); + + return ( + + {option.label} + + ); + } +} + +export default SelectBox_Option_SingleLineLink;