cspace-ui
Version:
CollectionSpace user interface for browsers
298 lines (249 loc) • 7.51 kB
JSX
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage } from 'react-intl';
import Immutable from 'immutable';
import get from 'lodash/get';
import { Modal } from 'cspace-layout';
import InvokeButton from './InvokeButton';
import InvocationEditorContainer from '../../containers/invocable/InvocationEditorContainer';
import CancelButton from '../navigation/CancelButton';
import styles from '../../../styles/cspace-ui/InvocationModal.css';
const messages = defineMessages({
cancel: {
id: 'invocationModal.cancel',
description: 'Label of the cancel button in the invocation modal.',
defaultMessage: 'Cancel',
},
invoke: {
id: 'invocationModal.run',
description: 'Label of the invoke button in the invocation modal.',
defaultMessage: 'Run',
},
});
const propTypes = {
allowedModes: PropTypes.arrayOf(PropTypes.string),
config: PropTypes.object.isRequired,
csid: PropTypes.string,
data: PropTypes.instanceOf(Immutable.Map),
initialInvocationDescriptor: PropTypes.instanceOf(Immutable.Map),
modeReadOnly: PropTypes.bool,
invocationTargetReadOnly: PropTypes.bool,
isOpen: PropTypes.bool,
isRecordModified: PropTypes.bool,
isRunning: PropTypes.bool,
recordType: PropTypes.oneOf(['report', 'batch']),
readRecord: PropTypes.func,
searchCsid: PropTypes.func,
onCancelButtonClick: PropTypes.func,
onCloseButtonClick: PropTypes.func,
onInvokeButtonClick: PropTypes.func,
};
export default class InvocationModal extends Component {
constructor(props) {
super(props);
this.handleInvocationDescriptorCommit = this.handleInvocationDescriptorCommit.bind(this);
this.handleInvokeButtonClick = this.handleInvokeButtonClick.bind(this);
this.renderButtonBar = this.renderButtonBar.bind(this);
this.state = {
invocationDescriptor: props.initialInvocationDescriptor,
};
}
componentWillReceiveProps(nextProps) {
const {
isOpen,
} = this.props;
const {
isOpen: nextIsOpen,
} = nextProps;
if (!isOpen && nextIsOpen) {
this.setState({
invocationDescriptor: nextProps.initialInvocationDescriptor,
});
}
}
componentDidUpdate(prevProps) {
const {
csid,
isOpen,
readRecord,
} = this.props;
const {
isOpen: prevIsOpen,
} = prevProps;
if (csid && !prevIsOpen && isOpen) {
if (readRecord) {
readRecord();
}
this.readInvocationItem();
}
}
handleInvocationDescriptorCommit(invocationDescriptor) {
this.setState({
invocationDescriptor,
});
}
handleInvokeButtonClick() {
const {
data,
onInvokeButtonClick,
} = this.props;
const {
invocationDescriptor,
} = this.state;
const mode = invocationDescriptor.get('mode');
// Translate the items map to csids.
const items = invocationDescriptor.get('items') || Immutable.Map();
let csid = items.keySeq().toJS();
if (mode === 'single' || mode === 'group') {
csid = csid[0];
}
if (onInvokeButtonClick) {
onInvokeButtonClick(data, invocationDescriptor.set('csid', csid));
}
}
readInvocationItem() {
const {
config,
searchCsid,
} = this.props;
const {
invocationDescriptor,
} = this.state;
if (invocationDescriptor) {
const invocationCsid = invocationDescriptor.get('csid');
if (
invocationCsid
&& typeof invocationCsid === 'string'
&& !invocationDescriptor.get('items')
) {
searchCsid(config, invocationDescriptor.get('recordType'), invocationCsid)
.then((response) => {
let item = get(response, ['data', 'ns2:abstract-common-list', 'list-item']);
if (item) {
item = Immutable.fromJS(item);
} else {
item = Immutable.Map({
csid: invocationCsid,
});
}
const nextInvocationDescriptor = this.state.invocationDescriptor.set(
'items', Immutable.Map({ [invocationCsid]: item })
);
this.setState({
invocationDescriptor: nextInvocationDescriptor,
});
})
.catch(() => {
const item = Immutable.Map({
csid: invocationCsid,
});
const nextInvocationDescriptor = this.state.invocationDescriptor.set(
'items', Immutable.Map({ [invocationCsid]: item })
);
this.setState({
invocationDescriptor: nextInvocationDescriptor,
});
});
}
}
}
renderButtonBar() {
const {
isRunning,
onCancelButtonClick,
recordType,
} = this.props;
const {
invocationDescriptor,
} = this.state;
const mode = invocationDescriptor.get('mode');
const items = invocationDescriptor.get('items');
return (
<div>
<CancelButton
disabled={isRunning}
label={<FormattedMessage {...messages.cancel} />}
onClick={onCancelButtonClick}
/>
<InvokeButton
disabled={
isRunning
|| (mode !== 'nocontext' && (!items || items.isEmpty()))
}
label={<FormattedMessage {...messages.invoke} />}
recordType={recordType}
onClick={this.handleInvokeButtonClick}
/>
</div>
);
}
renderTitle() {
const {
config,
data,
recordType,
} = this.props;
if (!data) {
return ' ';
}
const recordTypeConfig = get(config, ['recordTypes', recordType]);
const titleGetter = get(recordTypeConfig, 'title');
let title = (titleGetter && titleGetter(data));
if (!title) {
const recordTypeMessages = get(recordTypeConfig, ['messages', 'record']);
title = <FormattedMessage {...recordTypeMessages.name} />;
}
return (
<h1>{title}</h1>
);
}
render() {
const {
allowedModes,
config,
csid,
data,
modeReadOnly,
invocationTargetReadOnly,
isOpen,
isRecordModified,
recordType,
onCloseButtonClick,
} = this.props;
const {
invocationDescriptor,
} = this.state;
if (!isOpen || !csid) {
return null;
}
const recordTypeConfig = get(config, ['recordTypes', recordType]);
const invocableNameGetter = get(recordTypeConfig, 'invocableName');
const invocableName = invocableNameGetter && invocableNameGetter(data);
return (
<Modal
className={styles.common}
isOpen={isOpen}
title={this.renderTitle()}
closeButtonClassName="material-icons"
closeButtonLabel="close"
renderButtonBar={this.renderButtonBar}
onCloseButtonClick={onCloseButtonClick}
>
<InvocationEditorContainer
allowedModes={allowedModes}
config={config}
metadata={data}
invocationDescriptor={invocationDescriptor}
modeReadOnly={modeReadOnly}
invocationTargetReadOnly={invocationTargetReadOnly}
invocableName={invocableName}
isInvocationTargetModified={isRecordModified}
recordType={recordType}
onInvocationDescriptorCommit={this.handleInvocationDescriptorCommit}
/>
</Modal>
);
}
}
InvocationModal.modalName = 'InvocationModal';
InvocationModal.propTypes = propTypes;