diff --git a/client/actions/events/api.js b/client/actions/events/api.js index c018032f2..20ac0c909 100644 --- a/client/actions/events/api.js +++ b/client/actions/events/api.js @@ -6,7 +6,7 @@ import { TO_BE_CONFIRMED_FIELD, } from '../../constants'; import {EventUpdateMethods} from '../../components/Events'; -import {get, isEqual, cloneDeep, pickBy, isNil, has, find, every} from 'lodash'; +import {get, isEqual, cloneDeep, pickBy, has, find, every} from 'lodash'; import * as selectors from '../../selectors'; import { eventUtils, @@ -26,7 +26,6 @@ import moment from 'moment'; import planningApi from '../planning/api'; import eventsUi from './ui'; -import locationApi from '../locations'; import main from '../main'; /** @@ -1264,59 +1263,15 @@ const uploadFiles = (event) => ( } ); -/** - * Action Dispatcher for saving the location for an event - * @param {object} event - The event the location is associated with - * @return arrow function - */ -const _saveLocation = (event, original) => ( - (dispatch) => { - const location = get(event, 'location'); - - if (!location || !location.name) { - if (!get(original, 'location')) { - delete event.location; - } else if (get(original, 'lock_action') === EVENTS.ITEM_ACTIONS.EDIT_EVENT.lock_action) { - // only if event was edited - event.location = null; - } - - return Promise.resolve(event); - } else if (location.existingLocation) { - event.location = { - name: location.name, - qcode: location.guid, - address: location.address, - }; - - // external address might not be there. - if (get(location, 'address.external')) { - delete location.address.external; - } - - return Promise.resolve(event); - } else if (isNil(location.qcode)) { - // the location is set, but doesn't have a qcode (not registered in the location collection) - return dispatch(locationApi.saveLocation(location)) - .then((savedLocation) => { - event.location = savedLocation; - return Promise.resolve(event); - }); - } else { - return Promise.resolve(event); - } - } -); - -const _save = (original, eventUpdates) => ( +const save = (original, updates) => ( (dispatch, getState, {api}) => { let promise; if (original) { promise = Promise.resolve(original); - } else if (isExistingItem(eventUpdates)) { + } else if (isExistingItem(updates)) { promise = dispatch( - self.fetchById(eventUpdates._id, {saveToStore: false, loadPlanning: false}) + self.fetchById(updates._id, {saveToStore: false, loadPlanning: false}) ); } else { promise = Promise.resolve({}); @@ -1326,8 +1281,8 @@ const _save = (original, eventUpdates) => ( const originalItem = eventUtils.modifyForServer(cloneDeep(originalEvent), true); // clone the updates as we're going to modify it - let updates = eventUtils.modifyForServer( - cloneDeep(eventUpdates), + let eventUpdates = eventUtils.modifyForServer( + cloneDeep(updates), true ); @@ -1335,20 +1290,20 @@ const _save = (original, eventUpdates) => ( // remove all properties starting with _ // and updates that are the same as original - updates = pickBy(updates, (v, k) => ( + eventUpdates = pickBy(eventUpdates, (v, k) => ( (k === TO_BE_CONFIRMED_FIELD || k === '_planning_item' || !k.startsWith('_')) && - !isEqual(updates[k], originalItem[k]) + !isEqual(eventUpdates[k], originalItem[k]) )); if (get(originalItem, 'lock_action') === EVENTS.ITEM_ACTIONS.EDIT_EVENT.lock_action && !isTemporaryId(originalItem._id) ) { - delete updates.dates; + delete eventUpdates.dates; } - updates.update_method = get(updates, 'update_method.value') || + eventUpdates.update_method = get(eventUpdates, 'update_method.value') || EventUpdateMethods[0].value; - return api('events').save(originalItem, updates); + return api('events').save(originalItem, eventUpdates); }) .then( (data) => Promise.resolve(get(data, '_items') || [data]), @@ -1357,14 +1312,6 @@ const _save = (original, eventUpdates) => ( } ); -const save = (original, updates) => ( - (dispatch) => ( - // Returns the modified unsaved event with the locations changes - dispatch(self._saveLocation(updates, original)) - .then((modifiedUpdates) => dispatch(self._save(original, modifiedUpdates))) - ) -); - const updateRepetitions = (original, updates) => ( (dispatch, getState, {api}) => ( api.update( @@ -1511,9 +1458,7 @@ const self = { fetchEventHistory, unpost, uploadFiles, - _save, save, - _saveLocation, getCriteria, fetchById, updateRepetitions, diff --git a/client/actions/events/tests/api_test.js b/client/actions/events/tests/api_test.js index 5f7819202..318debcb0 100644 --- a/client/actions/events/tests/api_test.js +++ b/client/actions/events/tests/api_test.js @@ -1089,78 +1089,11 @@ describe('actions.events.api', () => { afterEach(() => { restoreSinonStub(eventsApi.fetchById); - restoreSinonStub(eventsApi._saveLocation); restoreSinonStub(eventsApi._save); }); - it('returns Promise.reject is _saveLocation fails', (done) => { - sinon.stub(eventsApi, '_saveLocation').callsFake(() => Promise.reject('Save Location Failed')); - sinon.stub(eventsApi, '_save').callsFake(() => Promise.resolve()); - store.test(done, eventsApi.save(data.events[0])) - .then(null, (error) => { - expect(error).toEqual('Save Location Failed'); - - expect(eventsApi._saveLocation.callCount).toBe(1); - expect(eventsApi._save.callCount).toBe(0); - - done(); - }) - .catch(done.fail); - }); - - it('runs _save with location information', (done) => { - sinon.stub(eventsApi, '_saveLocation').callsFake((item) => Promise.resolve(item)); - sinon.stub(eventsApi, '_save').callsFake((item) => Promise.resolve(item)); - store.test(done, eventsApi.save(data.events[0], {name: 'New Event'})) - .then((item) => { - expect(item).toEqual(data.events[0]); - expect(eventsApi._saveLocation.callCount).toBe(1); - expect(eventsApi._save.callCount).toBe(1); - expect(eventsApi._save.args[0]).toEqual([ - data.events[0], - {name: 'New Event'}, - ]); - - done(); - }) - .catch(done.fail); - }); - - it('_save calls api.save', (done) => ( - store.test(done, eventsApi._save(null, { - _id: data.events[0]._id, - name: 'New Name', - slugline: 'New Slugline', - })) - .then((item) => { - expect(item).toEqual([data.events[0]]); - - expect(eventsApi.fetchById.callCount).toBe(1); - expect(eventsApi.fetchById.args[0]).toEqual([ - data.events[0]._id, - {saveToStore: false, loadPlanning: false}, - ]); - - expect(services.api('events').save.callCount).toBe(1); - expect(services.api('events').save.args[0]).toEqual([ - { - ...data.events[0], - location: null, - }, - { - name: 'New Name', - slugline: 'New Slugline', - update_method: 'single', - }, - ]); - - done(); - }) - .catch(done.fail) - )); - it('doesnt call event.api.fetchById if it is a new Event', (done) => ( - store.test(done, eventsApi._save(null, {name: 'New Event', slugline: 'New Slugline'})) + store.test(done, eventsApi.save(null, {name: 'New Event', slugline: 'New Slugline'})) .then(() => { expect(eventsApi.fetchById.callCount).toBe(0); diff --git a/client/actions/locations.js b/client/actions/locations.js index 6bcf22430..8c5090a21 100644 --- a/client/actions/locations.js +++ b/client/actions/locations.js @@ -171,28 +171,6 @@ const saveLocation = (newLocation) => ( (result) => Promise.resolve(result), () => Promise.reject('Failed to save location.!') ); - }) - .then((data) => { - const eventData = { - name: data.name, - qcode: data.guid, - }; - - if (data.position) { - eventData.location = { - lat: data.position.latitude, - lon: data.position.longitude, - }; - } - - if (get(data, 'address')) { - eventData.address = data.address; - if (eventData.address.external) { - delete eventData.address.external; - } - } - - return eventData; }); } ); diff --git a/client/components/GeoLookupInput/AddGeoLookupInput.jsx b/client/components/GeoLookupInput/AddGeoLookupInput.jsx index 129e26843..3874327c4 100644 --- a/client/components/GeoLookupInput/AddGeoLookupInput.jsx +++ b/client/components/GeoLookupInput/AddGeoLookupInput.jsx @@ -79,12 +79,19 @@ export class GeoLookupInputComponent extends React.Component { } saveNewLocation(value) { - this.props.onChange(this.props.field, value); - this.setState({ - unsavedInput: '', - searching: false, - searchLocalAlways: true, - }); + this.props.saveLocation(value) + .then((newLocation) => { + this.onSuggestSelect({ + ...newLocation, + existingLocation: true, + }); + + this.setState({ + unsavedInput: '', + searching: false, + searchLocalAlways: true, + }); + }); } removeLocation() { @@ -184,8 +191,34 @@ export class GeoLookupInputComponent extends React.Component { * @param {Object} suggest The suggest */ onSuggestSelect(suggest) { - this.props.onChange(this.props.field, this.onGeocodeSuggest(suggest)); - this.resetSearchResults(); + const location = this.onGeocodeSuggest(suggest); + let promise = get(location, 'existingLocation') ? Promise.resolve(location) : + this.props.saveLocation(location); + + promise.then((newLocation) => { + let value = { + name: newLocation.name, + qcode: newLocation.guid, + address: newLocation.address, + }; + + // external address might not be there. + if (get(value, 'address.external')) { + delete value.address.external; + } + + if (newLocation.position) { + value = { + ...value, + location: { + lat: get(newLocation, 'position.latitude'), + lon: get(newLocation, 'position.longitude'), + }, + }; + } + + this.props.onChange(this.props.field, value); + }).finally(() => this.resetSearchResults()); } onSuggestsLookup(userInput) { @@ -332,6 +365,7 @@ GeoLookupInputComponent.propTypes = { onPopupOpen: PropTypes.func, onPopupClose: PropTypes.func, allowFreeTextLocation: PropTypes.bool, + saveLocation: PropTypes.func, }; const mapStateToProps = (state, ownProps) => ({ @@ -346,6 +380,7 @@ const mapStateToProps = (state, ownProps) => ({ const mapDispatchToProps = (dispatch) => ({ searchLocalLocations: (text) => dispatch(actions.locations.getLocation(text)), + saveLocation: (newLocation) => dispatch(actions.locations.saveLocation(newLocation)), }); export const AddGeoLookupInput = connect(