UNPKG

cspace-ui

Version:
937 lines (924 loc) 34.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateRecordData = exports.validateFieldValue = exports.transitionRecord = exports.sortFieldInstances = exports.setFieldValue = exports.saveRecordWithTransition = exports.saveRecord = exports.revertRecord = exports.readRecord = exports.moveFieldValue = exports.detachSubrecord = exports.deleteRecord = exports.deleteFieldValue = exports.createNewSubrecord = exports.createNewRecord = exports.computeRecordData = exports.computeFieldValue = exports.clearRecord = exports.addFieldInstance = void 0; var _reactIntl = require("react-intl"); var _get = _interopRequireDefault(require("lodash/get")); var _merge = _interopRequireDefault(require("lodash/merge")); var _immutable = _interopRequireDefault(require("immutable")); var _session = _interopRequireDefault(require("../helpers/session")); var _notificationHelpers = _interopRequireDefault(require("../helpers/notificationHelpers")); var _getErrorDescription = _interopRequireDefault(require("../helpers/getErrorDescription")); var _validationHelpers = require("../helpers/validationHelpers"); var _HierarchyReparentNotifier = _interopRequireDefault(require("../components/record/HierarchyReparentNotifier")); var _notification = require("./notification"); var _search = require("./search"); var _reducers = require("../reducers"); var _configHelpers = require("../helpers/configHelpers"); var _recordDataHelpers = require("../helpers/recordDataHelpers"); var _searchHelpers = require("../helpers/searchHelpers"); var _actionCodes = require("../constants/actionCodes"); var _errorCodes = require("../constants/errorCodes"); var _notificationStatusCodes = require("../constants/notificationStatusCodes"); var _prefs = require("./prefs"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* global window */ const deleteMessages = (0, _reactIntl.defineMessages)({ deleting: { "id": "action.record.deleting", "defaultMessage": "{hasTitle, select, yes {Deleting {title}\u2026} other {Deleting record\u2026}}" }, errorDeleting: { "id": "action.record.errorDeleting", "defaultMessage": "{hasTitle, select, yes {Error deleting {title}: {error}} other {Error deleting record: {error}}}" }, deleted: { "id": "action.record.deleted", "defaultMessage": "{hasTitle, select, yes {Deleted {title}} other {Deleted record}}" } }); const saveMessages = (0, _reactIntl.defineMessages)({ saving: { "id": "action.record.saving", "defaultMessage": "{hasTitle, select, yes {Saving {title}\u2026} other {Saving record\u2026}}" }, errorSaving: { "id": "action.record.errorSaving", "defaultMessage": "{hasTitle, select, yes {Error saving {title}: {error}} other {Error saving record: {error}}}" }, saved: { "id": "action.record.saved", "defaultMessage": "{hasTitle, select, yes {Saved {title}} other {Saved record}}" }, errorDupRoleName: { "id": "action.record.errorDupRoleName", "defaultMessage": "Error saving {title}: A role already exists with this name. Please choose a different name." } }); const transitionMessages = { delete: (0, _reactIntl.defineMessages)({ transitioning: { "id": "action.record.transition.delete.transitioning", "defaultMessage": "{hasTitle, select, yes {Deleting {title}\u2026} other {Deleting record\u2026}}" }, errorTransitioning: { "id": "action.record.transition.delete.errorTransitioning", "defaultMessage": "{hasTitle, select, yes {Error deleting {title}: {error}} other {Error deleting record: {error}}}" }, transitioned: { "id": "action.record.transition.delete.transitioned", "defaultMessage": "{hasTitle, select, yes {Deleted {title}} other {Deleted record}}" } }), lock: (0, _reactIntl.defineMessages)({ transitioning: { "id": "action.record.transition.lock.transitioning", "defaultMessage": "{hasTitle, select, yes {Locking {title}\u2026} other {Locking record\u2026}}" }, errorTransitioning: { "id": "action.record.transition.lock.errorTransitioning", "defaultMessage": "{hasTitle, select, yes {Error locking {title}: {error}} other {Error locking record: {error}}}" }, transitioned: { "id": "action.record.transition.lock.transitioned", "defaultMessage": "{hasTitle, select, yes {Locked {title}} other {Locked record}}" } }) }; const getSaveErrorNotificationItem = (error, title) => { const data = (0, _get.default)(error, ['error', 'response', 'data']); if (typeof data === 'string' && data.includes('unique constraint "roles_rolename_tenant_id_key"')) { return { message: saveMessages.errorDupRoleName, values: { title } }; } return { message: saveMessages.errorSaving, values: { title, hasTitle: title ? 'yes' : '', error: (0, _getErrorDescription.default)(error) } }; }; const computeFieldValue = (recordTypeConfig, csid, path, value) => (dispatch, getState) => { const state = getState(); const computeContext = { data: value, path: [], recordData: (0, _reducers.getRecordData)(state, csid), subrecordData: (0, _reducers.getSubrecordData)(state, csid), fieldDescriptor: (0, _get.default)(recordTypeConfig, ['fields', ...(0, _configHelpers.dataPathToFieldDescriptorPath)(path)]), recordType: recordTypeConfig.name, form: (0, _reducers.getForm)(state, recordTypeConfig.name), roleNames: (0, _reducers.getUserRoleNames)(state) }; return (0, _recordDataHelpers.computeField)(computeContext, true).then(computedValue => { if (typeof computedValue !== 'undefined') { dispatch({ type: _actionCodes.FIELD_COMPUTE_FULFILLED, payload: computedValue, meta: { csid, path } }); } }).catch(error => { dispatch({ type: _actionCodes.FIELD_COMPUTE_REJECTED, payload: { code: _errorCodes.ERR_COMPUTE, error }, meta: { csid, path } }); // TODO: Show an error notification? }); }; exports.computeFieldValue = computeFieldValue; const computeRecordData = (recordTypeConfig, csid) => (dispatch, getState) => { const recordData = (0, _reducers.getRecordData)(getState(), csid); return dispatch(computeFieldValue(recordTypeConfig, csid, [], recordData)); }; exports.computeRecordData = computeRecordData; const validateFieldValue = (recordTypeConfig, csid, path, value) => (dispatch, getState) => { const state = getState(); const validationContext = { csid, data: value, path: [], recordData: (0, _reducers.getRecordData)(state, csid), subrecordData: (0, _reducers.getSubrecordData)(state, csid), fieldDescriptor: (0, _get.default)(recordTypeConfig, ['fields', ...(0, _configHelpers.dataPathToFieldDescriptorPath)(path)]), recordType: recordTypeConfig.name, form: (0, _reducers.getForm)(state, recordTypeConfig.name), roleNames: (0, _reducers.getUserRoleNames)(state) }; return (0, _recordDataHelpers.validateField)(validationContext, true).then(errors => { if (errors) { dispatch({ type: _actionCodes.VALIDATION_FAILED, payload: errors, meta: { csid, path } }); dispatch((0, _notification.showValidationNotification)(recordTypeConfig.name, csid)); } else { dispatch({ type: _actionCodes.VALIDATION_PASSED, meta: { csid, path } }); dispatch((0, _notification.removeValidationNotification)()); } }); }; exports.validateFieldValue = validateFieldValue; const validateRecordData = (recordTypeConfig, csid) => (dispatch, getState) => { const recordData = (0, _reducers.getRecordData)(getState(), csid); return dispatch(validateFieldValue(recordTypeConfig, csid, [], recordData)); }; exports.validateRecordData = validateRecordData; const initializeSubrecords = (config, recordTypeConfig, vocabularyConfig, csid) => (dispatch, getState) => { const { subrecords } = recordTypeConfig; if (!subrecords) { return Promise.resolve(); } const data = (0, _reducers.getRecordData)(getState(), csid); return Promise.all(Object.entries(subrecords).map(entry => { const [subrecordName, subrecordConfig] = entry; const { csidField, subresource, recordType: subrecordType, vocabulary: subrecordVocabulary } = subrecordConfig; let subrecordCsidPromise = null; if (csidField) { subrecordCsidPromise = Promise.resolve((0, _recordDataHelpers.deepGet)(data, csidField)); } else if (subresource) { const searchDescriptor = _immutable.default.fromJS({ csid, subresource, recordType: recordTypeConfig.name, vocabulary: vocabularyConfig.name, searchQuery: { // Set page size to 1, and page to 0. This assumes we'll only ever care about the first // result. p: 0, size: 1 } }); const searchName = (0, _searchHelpers.getSubrecordSearchName)(csid, subrecordName); const listType = subresource ? (0, _get.default)(config, ['subresources', subresource, 'listType']) : null; subrecordCsidPromise = dispatch((0, _search.search)(config, searchName, searchDescriptor, listType)).then(() => { const result = (0, _reducers.getSearchResult)(getState(), searchName, searchDescriptor); let subrecordCsid; if (result) { // Read the csid of the first item. const firstItem = (0, _searchHelpers.getFirstItem)(config, result, listType); if (firstItem) { subrecordCsid = firstItem.get('csid'); } } return subrecordCsid; }); } if (subrecordCsidPromise) { return subrecordCsidPromise.then(subrecordCsid => { const subrecordTypeConfig = (0, _get.default)(config, ['recordTypes', subrecordType]); const subrecordVocabularyConfig = (0, _get.default)(subrecordTypeConfig, ['vocabularies', subrecordVocabulary]); if (subrecordCsid) { return ( // eslint-disable-next-line no-use-before-define dispatch(readRecord(config, subrecordTypeConfig, subrecordVocabularyConfig, subrecordCsid)).then(() => dispatch({ type: _actionCodes.SUBRECORD_READ_FULFILLED, meta: { csid, subrecordCsid, subrecordName } })) ); } // No existing subrecord. Create one as a default. // eslint-disable-next-line no-use-before-define return dispatch(createNewSubrecord(config, csid, csidField, subrecordName, subrecordTypeConfig, subrecordVocabularyConfig, undefined, true)); }); } return Promise.resolve(); })); }; const doRead = (recordTypeConfig, vocabularyConfig, csid) => { const { serviceType, servicePath: recordServicePath } = recordTypeConfig.serviceConfig; const vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null; const pathParts = [recordServicePath]; if (vocabularyServicePath) { pathParts.push(vocabularyServicePath); pathParts.push('items'); } pathParts.push(csid); const path = pathParts.join('/'); const requestConfig = { params: { wf_deleted: false } }; if (serviceType === 'authority' || serviceType === 'object') { requestConfig.params.showRelations = true; requestConfig.params.pgSz = 0; } if (recordTypeConfig.requestConfig) { (0, _merge.default)(requestConfig, recordTypeConfig.requestConfig('read')); } return (0, _session.default)().read(path, requestConfig); }; const readRecord = (config, recordTypeConfig, vocabularyConfig, csid, options = {}) => (dispatch, getState) => { const existingData = (0, _reducers.getRecordData)(getState(), csid); if (existingData) { return Promise.resolve(existingData); } if ((0, _reducers.isRecordReadPending)(getState(), csid)) { return Promise.resolve(); } dispatch({ type: _actionCodes.RECORD_READ_STARTED, meta: { recordTypeConfig, csid } }); const { initSubrecords = true } = options; return doRead(recordTypeConfig, vocabularyConfig, csid).then(response => dispatch({ type: _actionCodes.RECORD_READ_FULFILLED, payload: response, meta: { config, recordTypeConfig, csid } })).then(() => initSubrecords ? dispatch(initializeSubrecords(config, recordTypeConfig, vocabularyConfig, csid)) : Promise.resolve()).then(() => (0, _reducers.getRecordData)(getState(), csid)).catch(error => dispatch({ type: _actionCodes.RECORD_READ_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { recordTypeConfig, csid } })); }; exports.readRecord = readRecord; const createNewRecord = (config, recordTypeConfig, vocabularyConfig, cloneCsid) => (dispatch, getState) => { let readClone; if (cloneCsid) { const data = (0, _reducers.getRecordData)(getState(), cloneCsid); if (!data) { // We don't have data for the record to be cloned. Read it first. readClone = dispatch(readRecord(config, recordTypeConfig, vocabularyConfig, cloneCsid)); } } if (!readClone) { // There's nothing to clone, or we already have the record data to be cloned. Perform an // async noop, so this function will be consistently async. readClone = new Promise(resolve => { window.setTimeout(() => { resolve(); }, 0); }); } return readClone.then(() => dispatch({ type: _actionCodes.CREATE_NEW_RECORD, meta: { config, recordTypeConfig, cloneCsid, stickyFields: (0, _reducers.getStickyFields)(getState()) } })); }; exports.createNewRecord = createNewRecord; const createNewSubrecord = (config, csid, csidField, subrecordName, subrecordTypeConfig, subrecordVocabularyConfig, cloneCsid, isDefault) => (dispatch, getState) => { let readClone; if (cloneCsid) { const data = (0, _reducers.getRecordData)(getState(), cloneCsid); if (!data) { // We don't have data for the record to be cloned. Read it first. readClone = dispatch(readRecord(config, subrecordTypeConfig, subrecordVocabularyConfig, cloneCsid)); } } if (!readClone) { // There's nothing to clone, or we already have the record data to be cloned. Perform an // async noop, so this function will be consistently async. readClone = new Promise(resolve => { window.setTimeout(() => { resolve(); }, 0); }); } return readClone.then(() => dispatch({ type: _actionCodes.CREATE_NEW_SUBRECORD, meta: { config, csid, csidField, subrecordName, subrecordTypeConfig, cloneCsid, isDefault, stickyFields: (0, _reducers.getStickyFields)(getState()) } })); }; exports.createNewSubrecord = createNewSubrecord; const saveSubrecords = (config, recordTypeConfig, vocabularyConfig, csid, saveStage) => (dispatch, getState) => { const { subrecords } = recordTypeConfig; if (!subrecords) { return Promise.resolve(); } return Promise.all(Object.entries(subrecords).filter(entry => entry[1].saveStage === saveStage).map(entry => { const [subrecordName, subrecordConfig] = entry; const subrecordCsid = (0, _reducers.getRecordSubrecordCsid)(getState(), csid, subrecordName); if (subrecordCsid) { const { csidField, saveCondition, subresource } = subrecordConfig; if (saveCondition) { const subrecordData = (0, _reducers.getRecordData)(getState(), subrecordCsid); if (!saveCondition(subrecordData)) { return Promise.resolve(); } } if (csidField) { const subrecordTypeConfig = (0, _get.default)(config, ['recordTypes', subrecordConfig.recordType]); const subrecordVocabularyConfig = (0, _get.default)(subrecordTypeConfig, ['vocabularies', subrecordConfig.vocabulary]); // eslint-disable-next-line no-use-before-define return dispatch(saveRecord(config, subrecordTypeConfig, subrecordVocabularyConfig, subrecordCsid, undefined, undefined, undefined, newRecordCsid => { dispatch({ type: _actionCodes.SUBRECORD_CREATED, meta: { csid, csidField, subrecordName, subrecordCsid: newRecordCsid } }); }, false)); } if (subresource) { const searchName = (0, _searchHelpers.getSubrecordSearchName)(csid, subrecordName); const subrecordSubresourceConfig = (0, _get.default)(config, ['subresources', subresource]); if (subrecordSubresourceConfig) { // eslint-disable-next-line no-use-before-define return dispatch(saveRecord(config, recordTypeConfig, vocabularyConfig, csid, subrecordSubresourceConfig, subrecordCsid, undefined, newRecordCsid => { dispatch({ type: _actionCodes.SUBRECORD_CREATED, meta: { csid, searchName, subrecordName, subrecordCsid: newRecordCsid } }); }, false)); } } } return Promise.resolve(); })); }; const saveRecord = (config, recordTypeConfig, vocabularyConfig, csid, subresourceConfig, subresourceCsid, relatedSubjectCsid, onRecordCreated, showNotifications = true) => (dispatch, getState, intl) => { let currentRecordTypeConfig; let currentVocabularyConfig; let currentCsid; if (subresourceConfig) { currentRecordTypeConfig = (0, _get.default)(config, ['recordTypes', subresourceConfig.recordType]); currentVocabularyConfig = (0, _get.default)(currentRecordTypeConfig, ['vocabularies', subresourceConfig.vocabulary]); currentCsid = subresourceCsid; } else { currentRecordTypeConfig = recordTypeConfig; currentVocabularyConfig = vocabularyConfig; currentCsid = csid; } return dispatch(computeRecordData(currentRecordTypeConfig, currentCsid)).then(() => dispatch(validateRecordData(currentRecordTypeConfig, currentCsid))).then(() => { if ((0, _validationHelpers.hasBlockingError)((0, _reducers.getRecordValidationErrors)(getState(), currentCsid))) { return null; } dispatch({ type: _actionCodes.RECORD_SAVE_STARTED, meta: { csid: currentCsid } }); const title = currentRecordTypeConfig.title ? currentRecordTypeConfig.title((0, _reducers.getRecordData)(getState(), currentCsid), { config, intl }) : null; const notificationID = (0, _notificationHelpers.default)(); if (showNotifications) { dispatch((0, _notification.showNotification)({ items: [{ message: saveMessages.saving, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_PENDING }, notificationID)); } return dispatch(saveSubrecords(config, currentRecordTypeConfig, currentVocabularyConfig, currentCsid, 'before')).then(() => dispatch((0, _prefs.setStickyFields)(currentRecordTypeConfig, currentCsid))).then(() => { const data = (0, _reducers.getRecordData)(getState(), currentCsid); const isExisting = (0, _recordDataHelpers.isExistingRecord)(data); const recordServicePath = (0, _get.default)(recordTypeConfig, ['serviceConfig', 'servicePath']); const vocabularyServicePath = (0, _get.default)(vocabularyConfig, ['serviceConfig', 'servicePath']); const pathParts = [recordServicePath]; if (vocabularyServicePath) { pathParts.push(vocabularyServicePath); pathParts.push('items'); } if (subresourceConfig) { if (csid) { pathParts.push(csid); } const subresourceServicePath = (0, _get.default)(subresourceConfig, ['serviceConfig', 'servicePath']); if (subresourceServicePath) { pathParts.push(subresourceServicePath); } } if (isExisting && currentCsid) { pathParts.push(currentCsid); } const path = pathParts.join('/'); const requestConfig = { data: (0, _recordDataHelpers.prepareForSending)(data, currentRecordTypeConfig).toJS() }; if (recordTypeConfig.requestConfig) { (0, _merge.default)(requestConfig, recordTypeConfig.requestConfig('save', data)); } if (isExisting) { return (0, _session.default)().update(path, requestConfig).then(response => currentRecordTypeConfig.refetchAfterUpdate ? doRead(currentRecordTypeConfig, currentVocabularyConfig, currentCsid) : response).then(response => dispatch(saveSubrecords(config, currentRecordTypeConfig, currentVocabularyConfig, currentCsid, 'after')).then(() => { if (showNotifications) { dispatch((0, _notification.showNotification)({ items: [{ message: saveMessages.saved, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_SUCCESS, autoClose: true }, notificationID)); } dispatch({ type: _actionCodes.RECORD_SAVE_FULFILLED, payload: response, meta: { relatedSubjectCsid, recordTypeConfig: currentRecordTypeConfig, csid: currentCsid, recordPagePrimaryCsid: (0, _reducers.getRecordPagePrimaryCsid)(getState()) } }); }).then(() => dispatch(initializeSubrecords(config, currentRecordTypeConfig, currentVocabularyConfig, currentCsid))).then(() => currentCsid).catch(error => { throw error; })).catch(error => { const wrapper = new Error(); wrapper.code = _errorCodes.ERR_API; wrapper.error = error; return Promise.reject(wrapper); }); } return (0, _session.default)().create(path, requestConfig).then(response => { if (response.status === 201 && response.headers.location) { const { location } = response.headers; const newRecordCsid = location.substring(location.lastIndexOf('/') + 1); dispatch({ type: _actionCodes.RECORD_CREATED, meta: { currentCsid, newRecordCsid, recordTypeConfig: currentRecordTypeConfig } }); return dispatch(saveSubrecords(config, currentRecordTypeConfig, currentVocabularyConfig, newRecordCsid, 'after')).then(() => doRead(currentRecordTypeConfig, currentVocabularyConfig, newRecordCsid)).then(readResponse => { if (showNotifications) { dispatch((0, _notification.showNotification)({ items: [{ message: saveMessages.saved, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_SUCCESS, autoClose: true }, notificationID)); } return dispatch({ type: _actionCodes.RECORD_SAVE_FULFILLED, payload: readResponse, meta: { relatedSubjectCsid, recordTypeConfig: currentRecordTypeConfig, csid: newRecordCsid, recordPagePrimaryCsid: (0, _reducers.getRecordPagePrimaryCsid)(getState()) } }); }).then(() => dispatch(initializeSubrecords(config, currentRecordTypeConfig, currentVocabularyConfig, newRecordCsid))).then(() => Promise.resolve(onRecordCreated ? onRecordCreated(newRecordCsid) : null)).then(() => newRecordCsid); } const error = new Error('Expected response with status 201 and a location header'); error.response = response; throw error; }).catch(error => { const wrapper = new Error(); wrapper.code = _errorCodes.ERR_API; wrapper.error = error; return Promise.reject(wrapper); }); }).catch(error => { const notificationItem = getSaveErrorNotificationItem(error, title); if (showNotifications) { dispatch((0, _notification.showNotification)({ items: [notificationItem], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); } dispatch({ type: _actionCodes.RECORD_SAVE_REJECTED, payload: error, meta: { csid: currentCsid } }); throw error; }); }); }; exports.saveRecord = saveRecord; const addFieldInstance = (recordTypeConfig, csid, path, position) => dispatch => { dispatch({ type: _actionCodes.ADD_FIELD_INSTANCE, meta: { csid, path, position, recordTypeConfig } }); return dispatch(computeRecordData(recordTypeConfig, csid)).then(() => dispatch(validateRecordData(recordTypeConfig, csid))); }; exports.addFieldInstance = addFieldInstance; const sortFieldInstances = (config, recordTypeConfig, csid, path, byField) => dispatch => { dispatch({ type: _actionCodes.SORT_FIELD_INSTANCES, meta: { config, csid, path, byField, recordTypeConfig } }); return dispatch(computeRecordData(recordTypeConfig, csid)).then(() => dispatch(validateRecordData(recordTypeConfig, csid))); }; exports.sortFieldInstances = sortFieldInstances; const deleteFieldValue = (recordTypeConfig, csid, path) => dispatch => { dispatch({ type: _actionCodes.DELETE_FIELD_VALUE, meta: { csid, path } }); return dispatch(computeRecordData(recordTypeConfig, csid)).then(() => dispatch(validateRecordData(recordTypeConfig, csid))); }; exports.deleteFieldValue = deleteFieldValue; const moveFieldValue = (recordTypeConfig, csid, path, newPosition) => dispatch => { dispatch({ type: _actionCodes.MOVE_FIELD_VALUE, meta: { csid, path, newPosition } }); return dispatch(computeRecordData(recordTypeConfig, csid)).then(() => dispatch(validateRecordData(recordTypeConfig, csid))); }; exports.moveFieldValue = moveFieldValue; const setFieldValue = (recordTypeConfig, csid, path, value) => dispatch => { dispatch({ type: _actionCodes.SET_FIELD_VALUE, payload: value, meta: { csid, path } }); return dispatch(computeRecordData(recordTypeConfig, csid)).then(() => dispatch(validateRecordData(recordTypeConfig, csid))); }; exports.setFieldValue = setFieldValue; const revertRecord = (recordTypeConfig, csid) => dispatch => { dispatch({ type: _actionCodes.REVERT_RECORD, meta: { recordTypeConfig, csid } }); // Clear validation errors. Could maybe revalidate here, but to be consistent, we should also // validate when a record is first loaded. dispatch({ type: _actionCodes.VALIDATION_PASSED, meta: { csid, path: [] } }); dispatch((0, _notification.removeValidationNotification)()); dispatch((0, _notification.removeNotification)(_HierarchyReparentNotifier.default.notificationID)); }; exports.revertRecord = revertRecord; const deleteRecord = (config, recordTypeConfig, vocabularyConfig, csid, relatedSubjectCsid) => (dispatch, getState, intl) => { const data = (0, _reducers.getRecordData)(getState(), csid); const title = recordTypeConfig.title(data, { config, intl }); const notificationID = (0, _notificationHelpers.default)(); dispatch((0, _notification.showNotification)({ items: [{ message: deleteMessages.deleting, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_PENDING }, notificationID)); dispatch({ type: _actionCodes.RECORD_DELETE_STARTED, meta: { recordTypeConfig, csid } }); const recordServicePath = recordTypeConfig.serviceConfig.servicePath; const vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null; const pathParts = [recordServicePath]; if (vocabularyServicePath) { pathParts.push(vocabularyServicePath); pathParts.push('items'); } if (csid) { pathParts.push(csid); } const path = pathParts.join('/'); return (0, _session.default)().delete(path).then(response => { dispatch((0, _notification.showNotification)({ items: [{ message: deleteMessages.deleted, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_SUCCESS, autoClose: true }, notificationID)); return dispatch({ type: _actionCodes.RECORD_DELETE_FULFILLED, payload: response, meta: { recordTypeConfig, csid, relatedSubjectCsid } }); }).catch(error => { dispatch((0, _notification.showNotification)({ items: [{ message: deleteMessages.errorDeleting, values: { title, hasTitle: title ? 'yes' : '', error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); return dispatch({ type: _actionCodes.RECORD_DELETE_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { recordTypeConfig, csid } }); }); }; exports.deleteRecord = deleteRecord; const transitionRecord = (config, recordTypeConfig, vocabularyConfig, csid, transitionName, relatedSubjectCsid) => (dispatch, getState, intl) => { const data = (0, _reducers.getRecordData)(getState(), csid); const title = recordTypeConfig.title(data, { config, intl }); const notificationID = (0, _notificationHelpers.default)(); const messages = transitionMessages[transitionName]; if (messages) { dispatch((0, _notification.showNotification)({ items: [{ message: messages.transitioning, values: { title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_PENDING }, notificationID)); } dispatch({ type: _actionCodes.RECORD_TRANSITION_STARTED, meta: { recordTypeConfig, csid, transitionName } }); const recordServicePath = recordTypeConfig.serviceConfig.servicePath; const vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null; const pathParts = [recordServicePath]; if (vocabularyServicePath) { pathParts.push(vocabularyServicePath); pathParts.push('items'); } if (csid) { pathParts.push(csid); } pathParts.push('workflow'); pathParts.push(transitionName); const path = pathParts.join('/'); return (0, _session.default)().update(path).then(response => transitionName === 'delete' ? response // For all transitions other than delete, re-read the record to obtain the new workflow // state. : doRead(recordTypeConfig, vocabularyConfig, csid)).then(response => { if (messages) { dispatch((0, _notification.showNotification)({ items: [{ message: messages.transitioned, values: { transitionName, title, hasTitle: title ? 'yes' : '' } }], date: new Date(), status: _notificationStatusCodes.STATUS_SUCCESS, autoClose: true }, notificationID)); } return dispatch({ type: _actionCodes.RECORD_TRANSITION_FULFILLED, payload: response, meta: { recordTypeConfig, csid, transitionName, relatedSubjectCsid, recordPagePrimaryCsid: (0, _reducers.getRecordPagePrimaryCsid)(getState()), // We don't get data back from the transition request. Rather than making a separate // request to get the actual updated time of the record, just make it the current time. updatedTimestamp: new Date().toISOString() } }); }).catch(error => { if (messages) { dispatch((0, _notification.showNotification)({ items: [{ message: messages.errorTransitioning, values: { transitionName, title, hasTitle: title ? 'yes' : '', error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); } return dispatch({ type: _actionCodes.RECORD_TRANSITION_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { recordTypeConfig, csid, transitionName } }); }); }; exports.transitionRecord = transitionRecord; const saveRecordWithTransition = (config, recordTypeConfig, vocabularyConfig, csid, subresourceConfig, subresourceCsid, relatedSubjectCsid, transitionName, onRecordCreated, showNotifications = true) => dispatch => dispatch(saveRecord(config, recordTypeConfig, vocabularyConfig, csid, subresourceConfig, subresourceCsid, relatedSubjectCsid, onRecordCreated, showNotifications)).then(savedCsid => dispatch(transitionRecord(config, recordTypeConfig, vocabularyConfig, savedCsid, transitionName, relatedSubjectCsid))); exports.saveRecordWithTransition = saveRecordWithTransition; const detachSubrecord = (config, csid, csidField, subrecordName, subrecordTypeConfig) => ({ type: _actionCodes.DETACH_SUBRECORD, meta: { config, csid, csidField, subrecordName, subrecordTypeConfig } }); exports.detachSubrecord = detachSubrecord; const clearRecord = (csid, clearSubrecords) => ({ type: _actionCodes.CLEAR_RECORD, meta: { csid, clearSubrecords } }); exports.clearRecord = clearRecord;