UNPKG

cspace-ui

Version:
645 lines (638 loc) 22.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.searchName = exports.default = exports.BaseSearchToSelectModal = void 0; var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactIntl = require("react-intl"); var _immutable = _interopRequireDefault(require("immutable")); var _get = _interopRequireDefault(require("lodash/get")); var _isEqual = _interopRequireDefault(require("lodash/isEqual")); var _cspaceLayout = require("cspace-layout"); var _CheckboxInput = _interopRequireDefault(require("cspace-input/lib/components/CheckboxInput")); var _SearchForm = _interopRequireDefault(require("./SearchForm")); var _Pager = _interopRequireDefault(require("./Pager")); var _AcceptSelectionButton = _interopRequireDefault(require("./AcceptSelectionButton")); var _BackButton = _interopRequireDefault(require("../navigation/BackButton")); var _CancelButton = _interopRequireDefault(require("../navigation/CancelButton")); var _SearchButton = _interopRequireDefault(require("./SearchButton")); var _SearchClearButton = _interopRequireDefault(require("./SearchClearButton")); var _SearchResultSummary = _interopRequireDefault(require("./SearchResultSummary")); var _SearchToSelectTitleBar = _interopRequireDefault(require("./SearchToSelectTitleBar")); var _SelectBar = _interopRequireDefault(require("./SelectBar")); var _SearchResultTableContainer = _interopRequireDefault(require("../../containers/search/SearchResultTableContainer")); var _searchHelpers = require("../../helpers/searchHelpers"); var _SearchToSelectModal = _interopRequireDefault(require("../../../styles/cspace-ui/SearchToSelectModal.css")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const searchName = exports.searchName = 'searchToSelect'; const messages = (0, _reactIntl.defineMessages)({ editSearch: { "id": "searchToSelectModal.editSearch", "defaultMessage": "Revise search" }, label: { "id": "searchToSelectModal.label", "defaultMessage": "Select records" } }); const listType = 'common'; // FIXME: Make default page size configurable const defaultPageSize = 20; const stopPropagation = event => { event.stopPropagation(); }; const propTypes = { acceptButtonClassName: _propTypes.default.string, acceptButtonLabel: _propTypes.default.node, allowedRecordTypes: _propTypes.default.arrayOf(_propTypes.default.string), allowedServiceTypes: _propTypes.default.arrayOf(_propTypes.default.string), config: _propTypes.default.shape({ listTypes: _propTypes.default.object, recordTypes: _propTypes.default.object }), intl: _reactIntl.intlShape, isOpen: _propTypes.default.bool, keywordValue: _propTypes.default.string, defaultRecordTypeValue: _propTypes.default.string, defaultVocabularyValue: _propTypes.default.string, recordTypeValue: _propTypes.default.string, vocabularyValue: _propTypes.default.string, advancedSearchCondition: _propTypes.default.instanceOf(_immutable.default.Map), preferredAdvancedSearchBooleanOp: _propTypes.default.string, preferredPageSize: _propTypes.default.number, perms: _propTypes.default.instanceOf(_immutable.default.Map), selectedItems: _propTypes.default.instanceOf(_immutable.default.Map), singleSelect: _propTypes.default.bool, titleMessage: _propTypes.default.objectOf(_propTypes.default.string), getAuthorityVocabCsid: _propTypes.default.func, buildRecordFieldOptionLists: _propTypes.default.func, deleteOptionList: _propTypes.default.func, onAdvancedSearchConditionCommit: _propTypes.default.func, onKeywordCommit: _propTypes.default.func, onRecordTypeCommit: _propTypes.default.func, onVocabularyCommit: _propTypes.default.func, onAccept: _propTypes.default.func, onCloseButtonClick: _propTypes.default.func, onCancelButtonClick: _propTypes.default.func, onClearButtonClick: _propTypes.default.func, onItemSelectChange: _propTypes.default.func, customizeSearchDescriptor: _propTypes.default.func, clearSearchResults: _propTypes.default.func, parentSelector: _propTypes.default.func, renderAcceptPending: _propTypes.default.func, search: _propTypes.default.func, setAllItemsSelected: _propTypes.default.func, setPreferredPageSize: _propTypes.default.func, shouldShowCheckbox: _propTypes.default.func }; const defaultProps = { defaultVocabularyValue: 'all', selectedItems: _immutable.default.Map(), renderAcceptPending: () => /*#__PURE__*/_react.default.createElement("p", null), shouldShowCheckbox: () => true }; class BaseSearchToSelectModal extends _react.Component { constructor() { super(); this.handleAcceptButtonClick = this.handleAcceptButtonClick.bind(this); this.handleCancelButtonClick = this.handleCancelButtonClick.bind(this); this.handleCheckboxCommit = this.handleCheckboxCommit.bind(this); this.handleCloseButtonClick = this.handleCloseButtonClick.bind(this); this.handleEditSearchLinkClick = this.handleEditSearchLinkClick.bind(this); this.handleFormSearch = this.handleFormSearch.bind(this); this.handleItemClick = this.handleItemClick.bind(this); this.handlePageChange = this.handlePageChange.bind(this); this.handlePageSizeChange = this.handlePageSizeChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this); this.renderCheckbox = this.renderCheckbox.bind(this); this.renderEditSearchLink = this.renderEditSearchLink.bind(this); this.renderModalButtonBar = this.renderModalButtonBar.bind(this); this.renderSearchResultTableHeader = this.renderSearchResultTableHeader.bind(this); this.renderSearchResultTableFooter = this.renderSearchResultTableFooter.bind(this); this.state = { isSearchInitiated: false, pageNum: 0, sort: null }; } // eslint-disable-next-line camelcase UNSAFE_componentWillReceiveProps(nextProps) { const { isOpen } = this.props; const { isOpen: nextIsOpen } = nextProps; if (isOpen && !nextIsOpen) { // Closing. this.setState({ isAcceptHandlerPending: false, isSearchInitiated: false, pageNum: 0, sort: null }); } } componentDidUpdate(prevProps, prevState) { const { isOpen } = this.props; const { isOpen: prevIsOpen } = prevProps; if (prevIsOpen && !isOpen) { // Closed. const { clearSearchResults, onRecordTypeCommit } = this.props; if (clearSearchResults) { clearSearchResults(searchName); } if (onRecordTypeCommit) { onRecordTypeCommit(''); } } else if (!prevIsOpen && isOpen) { // Opened. const { config, defaultRecordTypeValue, defaultVocabularyValue, onRecordTypeCommit, onVocabularyCommit } = this.props; if (onRecordTypeCommit) { onRecordTypeCommit(defaultRecordTypeValue); if (onVocabularyCommit) { const serviceType = (0, _get.default)(config, ['recordTypes', defaultRecordTypeValue, 'serviceConfig', 'serviceType']); if (serviceType === 'authority') { onVocabularyCommit(defaultVocabularyValue); } } } } const { isSearchInitiated, pageNum, sort } = this.state; const { config, defaultVocabularyValue, recordTypeValue, vocabularyValue, advancedSearchCondition, preferredPageSize, onVocabularyCommit } = this.props; const { recordTypeValue: prevRecordTypeValue, vocabularyValue: prevVocabularyValue, advancedSearchCondition: prevAdvancedSearchCondition, preferredPageSize: prevPreferredPageSize } = prevProps; if (isSearchInitiated) { const { pageNum: prevPageNum, sort: prevSort } = prevState; if (recordTypeValue !== prevRecordTypeValue || vocabularyValue !== prevVocabularyValue || !(0, _isEqual.default)(advancedSearchCondition, prevAdvancedSearchCondition) || preferredPageSize !== prevPreferredPageSize || pageNum !== prevPageNum || sort !== prevSort) { this.search(); } } else if (recordTypeValue !== prevRecordTypeValue) { const serviceType = (0, _get.default)(config, ['recordTypes', recordTypeValue, 'serviceConfig', 'serviceType']); if (serviceType === 'authority') { onVocabularyCommit(defaultVocabularyValue); } } } handleAcceptButtonClick() { const { isSearchInitiated } = this.state; if (isSearchInitiated) { const { onAccept, selectedItems } = this.props; if (onAccept) { this.setState({ isAcceptHandlerPending: true, isSearchInitiated: false }); Promise.resolve(onAccept(selectedItems, this.getSearchDescriptor())); } } else { this.search(); } } handleCancelButtonClick(event) { const { onCancelButtonClick } = this.props; if (onCancelButtonClick) { onCancelButtonClick(event); } } handleCloseButtonClick(event) { const { onCloseButtonClick } = this.props; if (onCloseButtonClick) { onCloseButtonClick(event); } } handleEditSearchLinkClick() { const { clearSearchResults } = this.props; if (clearSearchResults) { clearSearchResults(searchName); } this.setState({ isSearchInitiated: false }); } handleFormSearch() { this.search(); } handleCheckboxCommit(path, value) { const index = parseInt(path[0], 10); this.setItemSelected(index, value); } handleItemClick(item, index) { const { selectedItems, shouldShowCheckbox } = this.props; if (shouldShowCheckbox(item)) { const itemCsid = item.get('csid'); const selected = selectedItems ? selectedItems.has(itemCsid) : false; this.setItemSelected(index, !selected); } } handlePageChange(pageNum) { this.setState({ pageNum }); } handlePageSizeChange(pageSize) { const { setPreferredPageSize } = this.props; let normalizedPageSize; if (Number.isNaN(pageSize) || pageSize < 1) { normalizedPageSize = 0; } else if (pageSize > 2500) { normalizedPageSize = 2500; } else { normalizedPageSize = pageSize; } if (setPreferredPageSize) { this.setState({ pageNum: 0 }); setPreferredPageSize(normalizedPageSize); } } handleSortChange(sort) { this.setState({ sort }); } getSearchDescriptor() { const { config, recordTypeValue: recordType, vocabularyValue: vocabulary, keywordValue: keyword, advancedSearchCondition, preferredPageSize, customizeSearchDescriptor } = this.props; const { pageNum, sort } = this.state; const pageSize = preferredPageSize || defaultPageSize; const searchQuery = { p: pageNum, size: pageSize }; if (sort) { searchQuery.sort = sort; } const kw = keyword ? keyword.trim() : ''; if (kw) { searchQuery.kw = kw; } const fields = (0, _get.default)(config, ['recordTypes', recordType, 'fields']); const condition = (0, _searchHelpers.normalizeCondition)(fields, advancedSearchCondition); if (condition) { searchQuery.as = condition; } const searchDescriptor = _immutable.default.fromJS({ recordType, vocabulary, searchQuery }); if (customizeSearchDescriptor) { return customizeSearchDescriptor(searchDescriptor); } return searchDescriptor; } setItemSelected(index, selected) { const { config, singleSelect, setAllItemsSelected, onItemSelectChange } = this.props; if (onItemSelectChange) { const searchDescriptor = this.getSearchDescriptor(); if (singleSelect && selected) { setAllItemsSelected(config, searchName, searchDescriptor, listType, false); } onItemSelectChange(config, searchName, searchDescriptor, listType, index, selected); } } search() { const { config, search } = this.props; if (search) { const searchDescriptor = this.getSearchDescriptor(); search(config, searchName, searchDescriptor); this.setState({ isSearchInitiated: true }); } } renderCheckbox({ rowData, rowIndex }) { const { shouldShowCheckbox } = this.props; if (shouldShowCheckbox(rowData)) { const { selectedItems } = this.props; const itemCsid = rowData.get('csid'); const selected = selectedItems ? selectedItems.has(itemCsid) : false; return /*#__PURE__*/_react.default.createElement(_CheckboxInput.default, { embedded: true, name: `${rowIndex}`, value: selected, onCommit: this.handleCheckboxCommit // Prevent click on the checkbox from propagating to the row, which would cause // double-toggling of the selected state. , onClick: stopPropagation }); } return null; } renderSearchForm() { const { allowedRecordTypes, allowedServiceTypes, config, intl, keywordValue, recordTypeValue, vocabularyValue, perms, preferredAdvancedSearchBooleanOp, advancedSearchCondition, getAuthorityVocabCsid, buildRecordFieldOptionLists, deleteOptionList, onAdvancedSearchConditionCommit, onKeywordCommit, onRecordTypeCommit, onVocabularyCommit } = this.props; let recordTypeInputReadOnly = true; let recordTypeInputRootType; if (allowedServiceTypes) { // Allow the record type to be changed. recordTypeInputReadOnly = false; // Don't show the All Records option. recordTypeInputRootType = ''; } else if (allowedRecordTypes) { recordTypeInputReadOnly = allowedRecordTypes.length < 2; } return /*#__PURE__*/_react.default.createElement(_SearchForm.default, { config: config, intl: intl, recordTypeValue: recordTypeValue, vocabularyValue: vocabularyValue, keywordValue: keywordValue, advancedSearchCondition: advancedSearchCondition, perms: perms, preferredAdvancedSearchBooleanOp: preferredAdvancedSearchBooleanOp, recordTypeInputReadOnly: recordTypeInputReadOnly, recordTypeInputRootType: recordTypeInputRootType, recordTypeInputRecordTypes: allowedRecordTypes, recordTypeInputServiceTypes: allowedServiceTypes, getAuthorityVocabCsid: getAuthorityVocabCsid, buildRecordFieldOptionLists: buildRecordFieldOptionLists, deleteOptionList: deleteOptionList, onAdvancedSearchConditionCommit: onAdvancedSearchConditionCommit, onKeywordCommit: onKeywordCommit, onRecordTypeCommit: onRecordTypeCommit, onVocabularyCommit: onVocabularyCommit, onSearch: this.handleFormSearch }); } renderEditSearchLink() { return /*#__PURE__*/_react.default.createElement("button", { type: "button", onClick: this.handleEditSearchLinkClick }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.editSearch)); } renderSearchResultTableHeader({ searchError, searchResult }) { const { config, selectedItems, setAllItemsSelected, shouldShowCheckbox, singleSelect } = this.props; if (searchError) { return null; } const searchDescriptor = this.getSearchDescriptor(); let selectBar; if (!singleSelect) { // If only a single selection is allowed, there's no need to show a count of selected records // or a select all checkbox. selectBar = /*#__PURE__*/_react.default.createElement(_SelectBar.default, { config: config, listType: listType, searchDescriptor: searchDescriptor, searchName: searchName, searchResult: searchResult, selectedItems: selectedItems, setAllItemsSelected: setAllItemsSelected, showCheckboxFilter: shouldShowCheckbox }); } return /*#__PURE__*/_react.default.createElement("header", null, /*#__PURE__*/_react.default.createElement(_SearchResultSummary.default, { config: config, listType: listType, searchDescriptor: searchDescriptor, searchError: searchError, searchResult: searchResult, renderEditLink: this.renderEditSearchLink, onPageSizeChange: this.handlePageSizeChange }), selectBar); } renderSearchResultTableFooter({ searchResult }) { const { config } = this.props; if (searchResult) { const listTypeConfig = config.listTypes[listType]; const list = searchResult.get(listTypeConfig.listNodeName); const totalItems = parseInt(list.get('totalItems'), 10); const pageSize = parseInt(list.get('pageSize'), 10); const pageNum = parseInt(list.get('pageNum'), 10); const lastPage = Math.max(0, Number.isNaN(totalItems) ? 0 : Math.ceil(totalItems / pageSize) - 1); return /*#__PURE__*/_react.default.createElement("footer", null, /*#__PURE__*/_react.default.createElement(_Pager.default, { currentPage: pageNum, lastPage: lastPage, pageSize: pageSize, onPageChange: this.handlePageChange, onPageSizeChange: this.handlePageSizeChange })); } return null; } renderSearchResultTable() { const { config, recordTypeValue } = this.props; const searchDescriptor = this.getSearchDescriptor(); return /*#__PURE__*/_react.default.createElement(_SearchResultTableContainer.default, { config: config, linkItems: false, listType: listType, recordType: recordTypeValue, searchName: searchName, searchDescriptor: searchDescriptor, showCheckboxColumn: true, renderCheckbox: this.renderCheckbox, renderHeader: this.renderSearchResultTableHeader, renderFooter: this.renderSearchResultTableFooter, onItemClick: this.handleItemClick, onSortChange: this.handleSortChange }); } renderModalButtonBar() { const { acceptButtonClassName, acceptButtonLabel, selectedItems, onClearButtonClick } = this.props; const { isAcceptHandlerPending, isSearchInitiated } = this.state; const cancelButton = /*#__PURE__*/_react.default.createElement(_CancelButton.default, { disabled: isAcceptHandlerPending, onClick: this.handleCancelButtonClick }); let acceptButton; let backButton; let clearButton; if (isSearchInitiated) { acceptButton = /*#__PURE__*/_react.default.createElement(_AcceptSelectionButton.default, { className: acceptButtonClassName, disabled: isAcceptHandlerPending || !selectedItems || selectedItems.size < 1, label: acceptButtonLabel, onClick: this.handleAcceptButtonClick }); backButton = /*#__PURE__*/_react.default.createElement(_BackButton.default, { disabled: isAcceptHandlerPending, label: /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.editSearch), onClick: this.handleEditSearchLinkClick }); } else { acceptButton = /*#__PURE__*/_react.default.createElement(_SearchButton.default, { disabled: isAcceptHandlerPending, type: "button", onClick: this.handleAcceptButtonClick }); clearButton = /*#__PURE__*/_react.default.createElement(_SearchClearButton.default, { onClick: onClearButtonClick }); } return /*#__PURE__*/_react.default.createElement("div", null, clearButton, backButton, cancelButton, acceptButton); } render() { const { config, intl, isOpen, recordTypeValue, parentSelector, singleSelect, titleMessage, renderAcceptPending } = this.props; const { isAcceptHandlerPending, isSearchInitiated } = this.state; let content; let title; if (isOpen) { if (isAcceptHandlerPending) { content = renderAcceptPending(); } else if (isSearchInitiated) { content = this.renderSearchResultTable(); } else { content = this.renderSearchForm(); } const searchDescriptor = this.getSearchDescriptor(); title = /*#__PURE__*/_react.default.createElement(_SearchToSelectTitleBar.default, { config: config, isSearchInitiated: isSearchInitiated, recordType: recordTypeValue, searchDescriptor: searchDescriptor, singleSelect: singleSelect, titleMessage: titleMessage }); } return /*#__PURE__*/_react.default.createElement(_cspaceLayout.Modal, { className: _SearchToSelectModal.default.common, contentLabel: intl.formatMessage(messages.label), title: title, isOpen: isOpen, showCloseButton: !isAcceptHandlerPending, closeButtonClassName: "material-icons", closeButtonLabel: "close", parentSelector: parentSelector, renderButtonBar: this.renderModalButtonBar, onCloseButtonClick: this.handleCloseButtonClick }, content); } } exports.BaseSearchToSelectModal = BaseSearchToSelectModal; BaseSearchToSelectModal.propTypes = propTypes; BaseSearchToSelectModal.defaultProps = defaultProps; var _default = exports.default = (0, _reactIntl.injectIntl)(BaseSearchToSelectModal);