cspace-ui
Version:
CollectionSpace user interface for browsers
148 lines (125 loc) • 4.29 kB
JSX
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import Immutable from 'immutable';
import { defineMessages, FormattedMessage } from 'react-intl';
import get from 'lodash/get';
import SearchToRelateModalContainer from '../../containers/search/SearchToRelateModalContainer';
import { canRelate } from '../../helpers/permissionHelpers';
import {
getFirstColumnName,
getRecordTypeNameByServiceObjectName,
getRecordTypeNameByUri,
} from '../../helpers/configHelpers';
import RelateButton from '../record/RelateButton';
const messages = defineMessages({
relate: {
id: 'searchResultPage.relate',
description: 'Label of the relate button on the search result page.',
defaultMessage: 'Relate…',
},
});
const isResultRelatable = (searchDescriptor, config) => {
const recordType = searchDescriptor.get('recordType');
const subresource = searchDescriptor.get('subresource');
const serviceType = get(config, ['recordTypes', recordType, 'serviceConfig', 'serviceType']);
return (
subresource !== 'terms'
&& (
serviceType === 'procedure'
|| serviceType === 'object'
|| recordType === 'procedure'
|| recordType === 'object'
)
);
};
export default function RelateResults({
config,
selectedItems,
searchDescriptor,
perms,
}) {
if (!isResultRelatable(searchDescriptor, config)) {
return null;
}
const [isModalOpen, setIsModalOpen] = useState(false);
const [validationError, setValidationError] = useState(undefined);
const validateSelectedItemsRelatable = () => {
if (selectedItems) {
let err;
selectedItems.valueSeq().find((item) => {
if (item.get('workflowState') === 'locked') {
err = { code: 'locked' };
return true;
}
const recordType = getRecordTypeNameByUri(config, item.get('uri'));
if (!canRelate(recordType, perms, config)) {
const recordMessages = config.recordTypes[recordType]?.messages?.record;
err = {
code: 'notPermitted',
values: {
selectedCount: selectedItems.size,
name: <FormattedMessage {...recordMessages.name} />,
collectionName: <FormattedMessage {...recordMessages.collectionName} />,
},
};
return true;
}
return false;
});
if (err) {
return err;
}
}
return undefined;
};
const handleRelateButtonClick = () => {
setValidationError(validateSelectedItemsRelatable());
setIsModalOpen(true);
};
const handleRelationsCreated = () => {
setIsModalOpen(false);
setValidationError(undefined);
};
const getSearchToRelateSubjects = () => {
if (!selectedItems) {
return null;
}
const recordType = searchDescriptor.get('recordType');
const serviceType = config.recordTypes[recordType]?.serviceConfig?.serviceType;
const itemRecordType = serviceType === 'utility' ? undefined : recordType;
const titleColumnName = getFirstColumnName(config, recordType);
return selectedItems.valueSeq().map((item) => ({
csid: item.get('csid'),
recordType: itemRecordType || getRecordTypeNameByServiceObjectName(config, item.get('docType')),
title: item.get(titleColumnName),
})).toJS();
};
return (
<>
<RelateButton
disabled={!selectedItems || selectedItems.size < 1}
key="relate"
label={<FormattedMessage {...messages.relate} />}
name="relate"
onClick={handleRelateButtonClick}
/>
<SearchToRelateModalContainer
allowedServiceTypes={['object', 'procedure']}
subjects={getSearchToRelateSubjects}
config={config}
isOpen={isModalOpen}
defaultRecordTypeValue="collectionobject"
error={validationError}
onCancelButtonClick={() => setIsModalOpen(false)}
onCloseButtonClick={() => setIsModalOpen(false)}
onRelationsCreated={handleRelationsCreated}
/>
</>
);
}
RelateResults.propTypes = {
config: PropTypes.object.isRequired,
selectedItems: PropTypes.instanceOf(Immutable.Map),
searchDescriptor: PropTypes.instanceOf(Immutable.Map).isRequired,
perms: PropTypes.instanceOf(Immutable.Map).isRequired,
};