cspace-ui
Version:
CollectionSpace user interface for browsers
226 lines (182 loc) • 5.99 kB
JSX
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Immutable from 'immutable';
import { defineMessages, FormattedMessage } from 'react-intl';
import get from 'lodash/get';
import InvocationDescriptorEditor from './InvocationDescriptorEditor';
import { getRecordTypeNameByServiceObjectName } from '../../helpers/configHelpers';
import { getCommonFieldValue } from '../../helpers/recordDataHelpers';
import RecordFormContainer from '../../containers/record/RecordFormContainer';
import styles from '../../../styles/cspace-ui/InvocationEditor.css';
import messageStyles from '../../../styles/cspace-ui/FormStatusMessage.css';
const messages = defineMessages({
loading: {
id: 'invocationEditor.loading',
description: 'Message displayed when invocable metadata is loading.',
defaultMessage: 'Loading…',
},
noDescription: {
id: 'invocationEditor.noDescription',
description: 'Message displayed when an invocable has no description.',
defaultMessage: 'Description not provided.',
},
});
const renderLoading = () => (
<div className={styles.pending}>
<FormattedMessage {...messages.loading} />
</div>
);
const propTypes = {
allowedModes: PropTypes.func,
config: PropTypes.shape({
recordTypes: PropTypes.object,
}),
invocationDescriptor: PropTypes.instanceOf(Immutable.Map),
modeReadOnly: PropTypes.bool,
invocationTargetReadOnly: PropTypes.bool,
isInvocationTargetModified: PropTypes.bool,
metadata: PropTypes.instanceOf(Immutable.Map),
paramData: PropTypes.instanceOf(Immutable.Map),
recordType: PropTypes.string,
createNewRecord: PropTypes.func,
onInvocationDescriptorCommit: PropTypes.func,
};
export default class InvocationEditor extends Component {
componentDidMount() {
this.init();
}
componentDidUpdate(prevProps) {
const {
metadata: prevMetadata,
} = prevProps;
const {
metadata,
} = this.props;
if (prevMetadata !== metadata) {
this.init();
}
}
getSupportedModes() {
const {
allowedModes,
metadata,
} = this.props;
let modes = [];
if (getCommonFieldValue(metadata, 'supportsNoContext') === 'true') {
modes.push('nocontext');
}
if (getCommonFieldValue(metadata, 'supportsDocList') === 'true') {
modes.push('list');
}
if (getCommonFieldValue(metadata, 'supportsGroup') === 'true') {
modes.push('group');
}
if (getCommonFieldValue(metadata, 'supportsSingleDoc') === 'true') {
modes.push('single');
}
if (allowedModes) {
const supportedRecordTypes = this.getSupportedRecordTypes();
const reportAllowedModes = allowedModes(supportedRecordTypes);
modes = modes.filter((mode) => reportAllowedModes.includes(mode));
}
return modes;
}
getSupportedRecordTypes() {
const {
config,
metadata,
} = this.props;
const forDocTypesContainer = getCommonFieldValue(metadata, 'forDocTypes');
let forDocTypes = forDocTypesContainer && forDocTypesContainer.get('forDocType');
if (forDocTypes) {
if (!Immutable.List.isList(forDocTypes)) {
forDocTypes = Immutable.List.of(forDocTypes);
}
const recordTypes = forDocTypes.map(
(forDocType) => getRecordTypeNameByServiceObjectName(config, forDocType),
).toJS();
return recordTypes;
}
return [];
}
init() {
const {
createNewRecord,
} = this.props;
// Create a params record.
createNewRecord();
}
render() {
const {
config,
invocationDescriptor,
modeReadOnly,
invocationTargetReadOnly,
isInvocationTargetModified,
metadata,
paramData,
recordType,
onInvocationDescriptorCommit,
} = this.props;
if (!metadata) {
return renderLoading();
}
const invocableNameGetter = get(config, ['recordTypes', recordType, 'invocableName']);
const invocableName = invocableNameGetter && invocableNameGetter(metadata);
const paramRecordTypeConfig = get(config, ['invocables', recordType, invocableName]);
const description = getCommonFieldValue(metadata, 'notes')
|| <FormattedMessage {...messages.noDescription} />;
const recordTypeConfig = get(config, ['recordTypes', recordType]);
const recordTypeMessages = get(recordTypeConfig, ['messages', 'record']);
const mode = invocationDescriptor.get('mode');
const items = invocationDescriptor.get('items');
let missingTargetError;
if (mode !== 'nocontext' && (!items || items.isEmpty())) {
missingTargetError = (
<p className={messageStyles.error}>
<FormattedMessage {...recordTypeMessages[`${mode}TargetMissing`]} />
</p>
);
if (modeReadOnly && invocationTargetReadOnly) {
return (
<div className={styles.common}>
<p>{description}</p>
{missingTargetError}
</div>
);
}
}
let unsavedWarning;
if (isInvocationTargetModified) {
unsavedWarning = (
<p className={messageStyles.warning}>
<FormattedMessage {...recordTypeMessages.invokeUnsaved} />
</p>
);
}
return (
<div className={styles.common}>
<p>{description}</p>
<InvocationDescriptorEditor
config={config}
invocationDescriptor={invocationDescriptor}
modes={this.getSupportedModes()}
modeReadOnly={modeReadOnly}
invocationTargetReadOnly={invocationTargetReadOnly}
recordTypes={this.getSupportedRecordTypes()}
onCommit={onInvocationDescriptorCommit}
/>
{missingTargetError}
{unsavedWarning}
<RecordFormContainer
config={config}
csid=""
data={paramData}
recordType="invocable"
recordTypeConfig={paramRecordTypeConfig}
/>
</div>
);
}
}
InvocationEditor.propTypes = propTypes;