cspace-ui
Version:
CollectionSpace user interface for browsers
937 lines (924 loc) • 34.3 kB
JavaScript
"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;