UNPKG

cspace-ui

Version:
370 lines (364 loc) 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unrelateBidirectional = exports.unrelate = exports.showRelationNotification = exports.find = exports.deleteRelation = exports.createBidirectional = exports.create = exports.clearState = exports.checkForRelations = exports.batchUnrelateBidirectional = exports.batchUnrelate = exports.batchCreateBidirectional = exports.batchCreate = void 0; var _immutable = _interopRequireDefault(require("immutable")); var _reactIntl = require("react-intl"); var _get = _interopRequireDefault(require("lodash/get")); var _session = _interopRequireDefault(require("../helpers/session")); var _notification = require("./notification"); var _getErrorDescription = _interopRequireDefault(require("../helpers/getErrorDescription")); var _reducers = require("../reducers"); var _errorCodes = require("../constants/errorCodes"); var _notificationStatusCodes = require("../constants/notificationStatusCodes"); var _actionCodes = require("../constants/actionCodes"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const clearState = () => ({ type: _actionCodes.CLEAR_RELATION_STATE }); exports.clearState = clearState; const messages = (0, _reactIntl.defineMessages)({ related: { "id": "action.relation.related", "defaultMessage": "{objectCount, plural, =0 {No records} one {# record} other {# records}} related to {subjectTitle}." }, batchCreateError: { "id": "action.relation.batchCreateError", "defaultMessage": "Some records could not be related: {error}" }, batchUnrelateError: { "id": "action.relation.batchUnrelateError", "defaultMessage": "Some records could not be unrelated: {error}" } }); const notificationID = 'action.relation'; const showRelationNotification = (message, values) => (0, _notification.showNotification)({ items: [{ message, values }], date: new Date(), status: _notificationStatusCodes.STATUS_SUCCESS, autoClose: true }, notificationID); /* * Find a relation, given at least the subject csid and object csid, and optionally the subject * record type, object record type, and predicate. This function assumes that there will be very * few (typically zero or one) results, and retrieves them all without paginating. */ exports.showRelationNotification = showRelationNotification; const find = (config, subject, object, predicate) => (dispatch, getState) => { if (!(subject.csid || object.csid)) { throw new Error('subject csid or object csid must be supplied'); } if ((0, _reducers.getRelationFindResult)(getState(), subject, object, predicate)) { // Already have a result for this descriptor. Do nothing. // TODO: Also check for a pending find request. return null; } dispatch({ type: _actionCodes.RELATION_FIND_STARTED, meta: { subject, object, predicate } }); const params = { prd: predicate, wf_deleted: 'false', pgSz: '0' }; if (subject) { const { csid, recordType } = subject; params.sbj = csid; if (recordType) { params.sbjType = (0, _get.default)(config, ['recordTypes', recordType, 'serviceConfig', 'objectName']); } } if (object) { const { csid, recordType } = object; params.obj = csid; if (recordType) { params.objType = (0, _get.default)(config, ['recordTypes', recordType, 'serviceConfig', 'objectName']); } } const requestConfig = { params }; return (0, _session.default)().read('/relations', requestConfig).then(response => dispatch({ type: _actionCodes.RELATION_FIND_FULFILLED, payload: response, meta: { subject, object, predicate } })).catch(error => dispatch({ type: _actionCodes.RELATION_FIND_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { subject, object, predicate } })); }; /** * Check if any relations exist for a given record csid and predicate, and optionally, a related * csid. Resolves to true or false. */ exports.find = find; const checkForRelations = (csid1, predicate, csid2) => () => { const params = { prd: predicate, sbj: csid1, andReciprocal: 'true', wf_deleted: 'false', pgSz: '1' }; if (typeof csid2 !== 'undefined') { params.obj = csid2; } const requestConfig = { params }; return (0, _session.default)().read('/relations', requestConfig).then(response => { const totalItems = (0, _get.default)(response, ['data', 'rel:relations-common-list', 'totalItems']); return totalItems && parseInt(totalItems, 10) > 0; }); }; exports.checkForRelations = checkForRelations; const deleteRelation = csid => dispatch => { if (!csid) { throw new Error('csid must be supplied'); } // return Promise.resolve(); dispatch({ type: _actionCodes.RELATION_DELETE_STARTED, meta: { csid } }); return (0, _session.default)().delete(`/relations/${csid}`).then(response => dispatch({ type: _actionCodes.RELATION_DELETE_FULFILLED, payload: response, meta: { csid } })).catch(error => { dispatch({ type: _actionCodes.RELATION_DELETE_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { csid } }); return Promise.reject(error); }); }; exports.deleteRelation = deleteRelation; const doUnrelate = (config, subject, object, predicate) => (dispatch, getState) => { if (!(subject.csid && object.csid)) { throw new Error('subject csid and object csid must be supplied'); } const existingResult = (0, _reducers.getRelationFindResult)(getState(), subject, object, predicate); let promise; if (existingResult) { promise = Promise.resolve(existingResult); } else { promise = dispatch(find(config, subject, object, predicate)).then(() => (0, _reducers.getRelationFindResult)(getState(), subject, object, predicate)); } return promise.then(findResult => { const list = findResult.get('rel:relations-common-list'); let items = list.get('relation-list-item'); if (!_immutable.default.List.isList(items)) { items = _immutable.default.List.of(items); } return Promise.all(items.map(item => dispatch(deleteRelation(item.get('csid'))))); }); }; const unrelate = (config, subject, object, predicate) => dispatch => dispatch(doUnrelate(config, subject, object, predicate)).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(() => {}); exports.unrelate = unrelate; const unrelateBidirectional = (config, subject, object, predicate) => dispatch => dispatch(unrelate(config, subject, object, predicate)).then(() => dispatch(unrelate(config, object, subject, predicate))).catch(() => {}); exports.unrelateBidirectional = unrelateBidirectional; const batchUnrelate = (config, subject, objects, predicate) => dispatch => objects.reduce((promise, object) => promise.then(() => dispatch(doUnrelate(config, subject, object, predicate))), Promise.resolve()).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(error => { dispatch((0, _notification.showNotification)({ items: [{ message: messages.batchUnrelateError, values: { error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); }); exports.batchUnrelate = batchUnrelate; const batchUnrelateBidirectional = (config, subject, objects, predicate) => dispatch => // For the passed subject, we only want to dispatch SUBJECT_RELATIONS_UPDATED once at the end, so // doUnrelate is used. The passed objects should be unique; for the reverse relations (where the // object becomes the subject), SUBJECT_RELATIONS_UPDATED may be dispatched immediately, so // unrelate is used. // Send these requests one at a time, to avoid DOSing the server. objects.reduce((promise, object) => promise.then(() => dispatch(doUnrelate(config, subject, object, predicate))).then(() => dispatch(unrelate(config, object, subject, predicate))), Promise.resolve()).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(error => { dispatch((0, _notification.showNotification)({ items: [{ message: messages.batchUnrelateError, values: { error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); }); exports.batchUnrelateBidirectional = batchUnrelateBidirectional; const doCreate = (subject, object, predicate) => dispatch => { dispatch({ type: _actionCodes.RELATION_SAVE_STARTED, meta: { subject, object, predicate } }); const config = { data: { document: { 'rel:relations_common': { '@xmlns:rel': 'http://collectionspace.org/services/relation', subjectCsid: subject.csid, objectCsid: object.csid, relationshipType: predicate } } } }; return (0, _session.default)().create('/relations', config).then(response => dispatch({ type: _actionCodes.RELATION_SAVE_FULFILLED, payload: response, meta: { subject, object, predicate } })).catch(error => { dispatch({ type: _actionCodes.RELATION_SAVE_REJECTED, payload: { code: _errorCodes.ERR_API, error }, meta: { subject, object, predicate } }); return Promise.reject(error); }); }; const batchCreate = (subject, objects, predicate) => dispatch => objects.reduce((promise, object) => promise.then(() => dispatch(checkForRelations(subject.csid, predicate, object.csid))).then(relationExists => { if (relationExists) { return Promise.resolve(); } return dispatch(doCreate(subject, object, predicate)); }), Promise.resolve()).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(error => { dispatch((0, _notification.showNotification)({ items: [{ message: messages.batchCreateError, values: { error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); }); exports.batchCreate = batchCreate; const batchCreateBidirectional = (subject, objects, predicate) => dispatch => // Send these requests one at a time, to avoid DOSing the server. objects.reduce((promise, object) => promise.then(() => dispatch(checkForRelations(subject.csid, predicate, object.csid))).then(relationExists => { if (relationExists) { return Promise.resolve(); } return dispatch(doCreate(subject, object, predicate)).then(() => dispatch(doCreate(object, subject, predicate))); }), Promise.resolve()).then(() => { dispatch(showRelationNotification(messages.related, { objectCount: objects.length, subjectTitle: subject.title })); dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } }); }).catch(error => { dispatch((0, _notification.showNotification)({ items: [{ message: messages.batchCreateError, values: { error: (0, _getErrorDescription.default)(error) } }], date: new Date(), status: _notificationStatusCodes.STATUS_ERROR }, notificationID)); }); exports.batchCreateBidirectional = batchCreateBidirectional; const create = (subject, object, predicate) => dispatch => dispatch(doCreate(subject, object, predicate)).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(() => {}); exports.create = create; const createBidirectional = (subject, object, predicate) => dispatch => dispatch(doCreate(subject, object, predicate)).then(() => dispatch(doCreate(object, subject, predicate))).then(() => dispatch({ type: _actionCodes.SUBJECT_RELATIONS_UPDATED, meta: { subject, updatedTime: new Date().toISOString() } })).catch(() => {}); exports.createBidirectional = createBidirectional;