Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Display document status of other dimensions in dimension dropdown #3680

Open
wants to merge 18 commits into
base: 8.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Resources/Private/Translations/en/Main.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,12 @@
<trans-unit id="copyNodeTypeNameToClipboard" xml:space="preserve">
<source>Copy node type to clipboard</source>
</trans-unit>
<trans-unit id="dimensions.doesNotExistsInDimension" xml:space="preserve">
<source>The current document does not exist in the dimension</source>
</trans-unit>
<trans-unit id="dimensions.combinationNotAllowed" xml:space="preserve">
<source>This combination of dimensions is not allowed</source>
</trans-unit>
</body>
</file>
</xliff>
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export default class DimensionSelector extends PureComponent {
label: presetConfiguration?.label,
value: presetName,
disallowed: presetConfiguration?.disallowed,
group: presetConfiguration?.group
covered: presetConfiguration?.covered,
group: presetConfiguration?.group,
url: presetConfiguration?.url
};
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,57 @@ import PropTypes from 'prop-types';
import style from './style.module.css';
// eslint-disable-next-line camelcase
import SelectBox_Option_SingleLine from '@neos-project/react-ui-components/src/SelectBox_Option_SingleLine/index';
import mergeClassNames from 'classnames';
import {neos} from '@neos-project/neos-ui-decorators';

@neos(globalRegistry => ({
i18nRegistry: globalRegistry.get('i18n')
}))

export default class DimensionSelectorOption extends PureComponent {
static propTypes = {
option: PropTypes.shape({
label: PropTypes.string.isRequired,
disallowed: PropTypes.bool
})
disallowed: PropTypes.bool,
covered: PropTypes.bool,
url: PropTypes.string
}),
i18nRegistry: PropTypes.object.isRequired
};

render() {
const {option} = this.props;
const {option, i18nRegistry} = this.props;
const className = mergeClassNames({
[style.disallowed]: option.disallowed,
[style.notCovered]: !option.covered
});

if (!option.disallowed && option.covered && option.url) {
const linkOptions = {
href: option.url,
target: '_blank',
rel: 'noopener noreferrer',
onClick: (event) => event.preventDefault()
}
return (

// eslint-disable-next-line camelcase
<SelectBox_Option_SingleLine
{...this.props}
className={className}
linkOptions={linkOptions}
/>
);
}
option.title = option.disallowed ?
i18nRegistry.translate('Neos.Neos.Ui:Main:dimensions.combinationNotAllowed') :
i18nRegistry.translate('Neos.Neos.Ui:Main:dimensions.doesNotExistsInDimension')

return (
// eslint-disable-next-line camelcase
<SelectBox_Option_SingleLine
{...this.props}
className={option.disallowed ? style.dimmed : ''}
label={option.label}
className={className}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,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
Expand All @@ -45,6 +47,8 @@ export default class DimensionSwitcher extends PureComponent {
activePresets: PropTypes.object.isRequired,
allowedPresets: PropTypes.object.isRequired,
selectPreset: PropTypes.func.isRequired,
getNodeByContextPath: PropTypes.func.isRequired,
documentNode: PropTypes.object.isRequired,
setAllowed: PropTypes.func.isRequired,

i18nRegistry: PropTypes.object.isRequired
Expand All @@ -62,6 +66,16 @@ export default class DimensionSwitcher extends PureComponent {
loadingPresets: {}
};

componentDidMount() {
const activePresets = mapValues(
this.props.activePresets,
dimensionPreset => dimensionPreset.name
);
this.setState({
transientPresets: activePresets
});
}

getDimensionIcon = (dimensionName, contentDimensionsObject) => {
const dimensionConfiguration = contentDimensionsObject[dimensionName];
return dimensionConfiguration?.icon || null;
Expand Down Expand Up @@ -153,11 +167,21 @@ export default class DimensionSwitcher extends PureComponent {
this.setState({isOpen: false});
}

createDirectDimensionsLink = (dimensionName, presetName) => {
const {documentNode} = this.props;

const nodeContextPath = documentNode.properties._path + ';' + dimensionName + '=' + presetName
const uri = new URL(window.location.href);
uri.searchParams.set('node', nodeContextPath);
return uri.toString();
}

renderSingleDimensionSelector = (dimensionName, contentDimensionsObject) => {
const dimensionConfiguration = contentDimensionsObject[dimensionName];
const icon = this.getDimensionIcon(dimensionName, contentDimensionsObject);
// First look for active preset in transient state, else take it from activePresets prop
const activePreset = this.getEffectivePresets(this.state.transientPresets)[dimensionName];

return (
<DimensionSelector
isLoading={this.state.loadingPresets[dimensionName]}
Expand Down Expand Up @@ -253,15 +277,46 @@ export default class DimensionSwitcher extends PureComponent {
return null;
}

getDocumentDimensions(dimensionName) {
const {getNodeByContextPath, documentNode, allowedPresets, contentDimensions} = this.props;
const currentDocumentNode = getNodeByContextPath(documentNode.contextPath)
if (!currentDocumentNode.dimensions || currentDocumentNode.length === 0) {
return allowedPresets[dimensionName]
}

const variants = [...currentDocumentNode.otherNodeVariants];
variants.push(currentDocumentNode.dimensions)

for (const dimensionKey of Object.keys(contentDimensions)) {
if (dimensionKey === dimensionName || Object.keys(contentDimensions).length === 1) {
break;
}
Object.entries(variants).forEach(entry => {
const [key, value] = entry;
if (value[dimensionKey] !== this.state.transientPresets[dimensionKey]) {
delete variants[key]
}
});
}
const dimensions = []
Object.values(variants).forEach(entry => {
dimensions.push(entry[dimensionName]);
});

return dimensions;
}

presetsForDimension(dimensionName) {
const {contentDimensions, allowedPresets, i18nRegistry} = this.props;
const dimensionConfiguration = $get(dimensionName, contentDimensions);

const documentDimensions = this.getDocumentDimensions(dimensionName);
return mapValues(dimensionConfiguration.presets,
(presetConfiguration, presetName) => {
return Object.assign({}, presetConfiguration, {
label: i18nRegistry.translate(presetConfiguration.label),
disallowed: !(allowedPresets[dimensionName] && allowedPresets[dimensionName].includes(presetName))
disallowed: !(allowedPresets[dimensionName] && allowedPresets[dimensionName].includes(presetName)),
covered: documentDimensions.some(dimension => presetConfiguration.values.includes(dimension)),
url: (Object.keys(contentDimensions).length === 1) ? this.createDirectDimensionsLink(dimensionName, presetName) : null
});
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,31 @@
}
}

.dimmed {
filter: opacity(50%);
.notCovered {
position: relative;
background-image: repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0) 12px, #323232 0, #323232 23px);
}
.notCovered:after {
content: '';
position: absolute;
height: 100%;
width: 3px;
top: 0px;
left: 0px;
background-color: var(--colors-Warn);
}
.disallowed {
position: relative;
background-color: #323232;
}
.disallowed:after {
content: '';
position: absolute;
height: 100%;
width: 3px;
top: 0px;
left: 0px;
background-color: var(--colors-Error);
}

.selectPreset + .selectPreset {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
}
.listPreviewElement--isHighlighted {
background-color: var(--colors-PrimaryBlue) !important;
background-image: none !important;
}

.listPreviewElement--isHighlighted > span {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,57 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import ListPreviewElement from '../ListPreviewElement';
import mergeClassNames from 'classnames';
import style from './style.module.css';

class SelectBox_Option_SingleLine extends PureComponent {
static propTypes = {
option: PropTypes.shape({
label: PropTypes.string.isRequired,
icon: PropTypes.string,
disabled: PropTypes.bool
disabled: PropTypes.bool,
title: PropTypes.string
}).isRequired,

disabled: PropTypes.bool,

className: PropTypes.string
className: PropTypes.string,

icon: PropTypes.string,

linkOptions: PropTypes.shape({
href: PropTypes.string.isRequired,
target: PropTypes.string,
rel: PropTypes.string,
onClick: PropTypes.func
})
}

render() {
const {option, className, disabled, icon} = this.props;
const {option, className, disabled, icon, linkOptions} = this.props;

const isDisabled = disabled || option.disabled;

const finalClassNames = mergeClassNames({
[className]: className
[className]: className,
[style.linkedItem]: linkOptions
});
const linkClassname = mergeClassNames({
[style.dropdownLink]: true,
[style.hasIcon]: (Boolean(option.icon || icon))
});

const previewElementIcon = option.icon ? option.icon : (icon ? icon : null);

return (
<ListPreviewElement {...this.props} icon={previewElementIcon} disabled={isDisabled} className={finalClassNames}>
<span title={option.label}>{option.label}</span>
{linkOptions ? (
<a
{...linkOptions}
className={linkClassname}
title={option.title ? option.title : option.label}>{option.label}</a>
) : (
<span title={option.title ? option.title : option.label}>{option.label}</span>
)}
</ListPreviewElement>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.dropdownLink {
color: white;
padding: 5px 14px;
display: inline-block;
width: 100%;

}
.hasIcon {
width: calc(100% - 2em);
padding: 5px 0px;
}
.linkedItem {
padding: 0px !important;
}
Loading