@plone/volto
Version:
Volto
194 lines (184 loc) • 5.83 kB
JSX
import { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import isEmpty from 'lodash/isEmpty';
import map from 'lodash/map';
import { defineMessages, useIntl } from 'react-intl';
import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
import { cloneDeepSchema } from '@plone/volto/helpers/Utils/Utils';
import { updateContent } from '@plone/volto/actions/content/content';
import { ModalForm } from '@plone/volto/components/manage/Form';
import config from '@plone/volto/registry';
const messages = defineMessages({
properties: {
id: 'Properties',
defaultMessage: 'Properties',
},
default: {
id: 'Default',
defaultMessage: 'Default',
},
effectiveTitle: {
id: 'Publishing Date',
defaultMessage: 'Publishing Date',
},
effectiveDescription: {
id: 'If this date is in the future, the content will not show up in listings and searches until this date.',
defaultMessage:
'If this date is in the future, the content will not show up in listings and searches until this date.',
},
expiresTitle: {
id: 'Expiration Date',
defaultMessage: 'Expiration Date',
},
expiresDescription: {
id: 'When this date is reached, the content will nolonger be visible in listings and searches.',
defaultMessage:
'When this date is reached, the content will nolonger be visible in listings and searches.',
},
rightsTitle: {
id: 'Rights',
defaultMessage: 'Rights',
},
rightsDescription: {
id: 'Copyright statement or other rights information on this item.',
defaultMessage:
'Copyright statement or other rights information on this item.',
},
creatorsTitle: {
id: 'Creators',
defaultMessage: 'Creators',
},
creatorsDescription: {
id: 'Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first.',
defaultMessage:
'Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first.',
},
excludeFromNavTitle: {
id: 'Exclude from navigation',
defaultMessage: 'Exclude from navigation',
},
excludeFromNavDescription: {
id: 'If selected, this item will not appear in the navigation tree',
defaultMessage:
'If selected, this item will not appear in the navigation tree',
},
});
const ContentsPropertiesModal = (props) => {
const { onCancel, onOk, open, items, values } = props;
const intl = useIntl();
const dispatch = useDispatch();
const request = useSelector((state) => state.content.update);
const prevrequestloading = usePrevious(request.loading);
const baseSchema = {
fieldsets: [
{
id: 'default',
title: intl.formatMessage(messages.default),
fields: [
'effective',
'expires',
'rights',
'creators',
'exclude_from_nav',
],
},
],
properties: {
effective: {
description: intl.formatMessage(messages.effectiveDescription),
title: intl.formatMessage(messages.effectiveTitle),
type: 'string',
widget: 'datetime',
},
expires: {
description: intl.formatMessage(messages.expiresDescription),
title: intl.formatMessage(messages.expiresTitle),
type: 'string',
widget: 'datetime',
},
rights: {
description: intl.formatMessage(messages.rightsDescription),
title: intl.formatMessage(messages.rightsTitle),
type: 'string',
widget: 'textarea',
},
creators: {
description: intl.formatMessage(messages.creatorsDescription),
title: intl.formatMessage(messages.creatorsTitle),
type: 'array',
},
exclude_from_nav: {
description: intl.formatMessage(messages.excludeFromNavDescription),
title: intl.formatMessage(messages.excludeFromNavTitle),
type: 'boolean',
},
},
required: [],
};
const schemaEnhancer = config.settings.contentPropertiesSchemaEnhancer;
let schema = schemaEnhancer
? schemaEnhancer({
schema: cloneDeepSchema(baseSchema),
intl,
})
: baseSchema;
const initialData = {};
if (values?.length) {
for (const name of Object.keys(schema.properties)) {
const firstValue = values[0][name];
// should not show floor or ceiling dates
if (
(name === 'effective' && firstValue && firstValue <= '1970') ||
(name === 'expires' && firstValue && firstValue >= '2499')
) {
continue;
}
if (values.every((item) => item[name] === firstValue)) {
initialData[name] = firstValue;
}
}
}
useEffect(() => {
if (prevrequestloading && request.loaded) {
onOk();
}
}, [onOk, prevrequestloading, request.loaded]);
const onSubmit = (data) => {
let changes = {};
for (const name of Object.keys(data)) {
if (data[name] !== initialData[name]) {
changes[name] = data[name];
}
}
if (isEmpty(changes)) {
onOk();
} else {
dispatch(
updateContent(
items,
map(items, () => changes),
),
);
}
};
return (
open && (
<ModalForm
open={open}
onSubmit={onSubmit}
onCancel={onCancel}
title={intl.formatMessage(messages.properties)}
schema={schema}
formData={initialData}
/>
)
);
};
ContentsPropertiesModal.propTypes = {
items: PropTypes.arrayOf(PropTypes.string).isRequired,
open: PropTypes.bool.isRequired,
onOk: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
};
export default ContentsPropertiesModal;