From ec77c7780915fb3aa03f6b9bdfe0bcb5c2b7d327 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 20:58:39 -0500 Subject: [PATCH 01/18] Use a selector to have only a single Session instance per state update --- src/app/reducers/entitiesReducer.js | 2 +- src/features/entities/entitySelectors.js | 10 ++++++++++ src/features/mechs/MechDetails.jsx | 4 ++-- src/features/mechs/MechsList/MechsList.jsx | 4 ++-- src/features/mechs/MechsList/MechsListRow.jsx | 4 ++-- src/features/pilots/PilotDetails.jsx | 4 ++-- src/features/pilots/PilotsList/PilotsList.jsx | 4 ++-- src/features/pilots/PilotsList/PilotsListRow.jsx | 4 ++-- 8 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 src/features/entities/entitySelectors.js diff --git a/src/app/reducers/entitiesReducer.js b/src/app/reducers/entitiesReducer.js index ef6d703..14b182d 100644 --- a/src/app/reducers/entitiesReducer.js +++ b/src/app/reducers/entitiesReducer.js @@ -1,6 +1,6 @@ import {createReducer} from "common/utils/reducerUtils"; -import orm from "app/orm" +import orm from "app/orm"; import {DATA_LOADED} from "features/tools/toolConstants"; diff --git a/src/features/entities/entitySelectors.js b/src/features/entities/entitySelectors.js new file mode 100644 index 0000000..030b59a --- /dev/null +++ b/src/features/entities/entitySelectors.js @@ -0,0 +1,10 @@ +import {createSelector} from "reselect"; + +import orm from "app/orm"; + +export const selectEntities = state => state.entities; + +export const getEntitiesSession = createSelector( + selectEntities, + entities => orm.session(entities) +); diff --git a/src/features/mechs/MechDetails.jsx b/src/features/mechs/MechDetails.jsx index bd2aea9..9f3019c 100644 --- a/src/features/mechs/MechDetails.jsx +++ b/src/features/mechs/MechDetails.jsx @@ -2,7 +2,7 @@ import React from "react"; import {connect} from "react-redux"; import {Form} from "semantic-ui-react"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; import {getWeightClass, selectCurrentMech} from "./mechsSelectors"; @@ -12,7 +12,7 @@ const mapState = (state) => { const currentMech = selectCurrentMech(state); - const session = orm.session(state.entities); + const session = getEntitiesSession(state); const {Mech} = session; if(Mech.hasId(currentMech)) { diff --git a/src/features/mechs/MechsList/MechsList.jsx b/src/features/mechs/MechsList/MechsList.jsx index 94db6d7..89f6df6 100644 --- a/src/features/mechs/MechsList/MechsList.jsx +++ b/src/features/mechs/MechsList/MechsList.jsx @@ -5,14 +5,14 @@ import {Table} from "semantic-ui-react"; import MechsListHeader from "./MechsListHeader"; import MechsListRow from "./MechsListRow"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; import {selectMech} from "../mechsActions"; import {selectCurrentMech} from "../mechsSelectors"; const mapState = (state) => { - const session = orm.session(state.entities); + const session = getEntitiesSession(state); const {Mech} = session; const mechs = Mech.all().toModelArray().map(mechModel => mechModel.getId()); diff --git a/src/features/mechs/MechsList/MechsListRow.jsx b/src/features/mechs/MechsList/MechsListRow.jsx index 6b4623d..ebdeb5f 100644 --- a/src/features/mechs/MechsList/MechsListRow.jsx +++ b/src/features/mechs/MechsList/MechsListRow.jsx @@ -2,12 +2,12 @@ import React from "react"; import {connect} from "react-redux"; import {Table} from "semantic-ui-react"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; import {getWeightClass} from "../mechsSelectors"; const mapState = (state, ownProps) => { - const session = orm.session(state.entities); + const session = getEntitiesSession(state); const {Mech} = session; let mech; diff --git a/src/features/pilots/PilotDetails.jsx b/src/features/pilots/PilotDetails.jsx index 1fe50a4..e3f851b 100644 --- a/src/features/pilots/PilotDetails.jsx +++ b/src/features/pilots/PilotDetails.jsx @@ -4,7 +4,7 @@ import {Form, Dropdown, Grid, Button} from "semantic-ui-react"; import FormEditWrapper from "common/components/FormEditWrapper"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; import { selectCurrentPilot, @@ -53,7 +53,7 @@ const mapState = (state) => { const currentPilot = selectCurrentPilot(state); - const session = orm.session(state.entities); + const session = getEntitiesSession(state); const {Pilot} = session; if(Pilot.hasId(currentPilot)) { diff --git a/src/features/pilots/PilotsList/PilotsList.jsx b/src/features/pilots/PilotsList/PilotsList.jsx index fc87610..c1ffa6c 100644 --- a/src/features/pilots/PilotsList/PilotsList.jsx +++ b/src/features/pilots/PilotsList/PilotsList.jsx @@ -5,7 +5,7 @@ import {Table} from "semantic-ui-react"; import PilotsListHeader from "./PilotsListHeader"; import PilotsListRow from "./PilotsListRow"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; import {selectPilot} from "../pilotsActions"; import {selectCurrentPilot} from "../pilotsSelectors"; @@ -14,7 +14,7 @@ import {selectCurrentPilot} from "../pilotsSelectors"; const mapState = (state) => { // Create a Redux-ORM Session from our "entities" slice, which // contains the "tables" for each model type - const session = orm.session(state.entities); + const session = getEntitiesSession(state); // Retrieve the model class that we need. Each Session // specifically "binds" model classes to itself, so that diff --git a/src/features/pilots/PilotsList/PilotsListRow.jsx b/src/features/pilots/PilotsList/PilotsListRow.jsx index 585c9be..8f07b0f 100644 --- a/src/features/pilots/PilotsList/PilotsListRow.jsx +++ b/src/features/pilots/PilotsList/PilotsListRow.jsx @@ -3,10 +3,10 @@ import {connect} from "react-redux"; import {Table} from "semantic-ui-react"; import _ from "lodash"; -import orm from "app/orm"; +import {getEntitiesSession} from "features/entities/entitySelectors"; const mapState = (state, ownProps) => { - const session = orm.session(state.entities); + const session = getEntitiesSession(state); const {Pilot} = session; let pilot; From 779dbdc65caa7187391ba7da1f688b2fabe33b7a Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:07:17 -0500 Subject: [PATCH 02/18] Add generic entity creation and deletion handling --- src/features/entities/entityActions.js | 23 +++++++++++++- src/features/entities/entityConstants.js | 2 ++ src/features/entities/entityReducer.js | 39 +++++++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/features/entities/entityActions.js b/src/features/entities/entityActions.js index 2d68843..8e1ded1 100644 --- a/src/features/entities/entityActions.js +++ b/src/features/entities/entityActions.js @@ -1,4 +1,8 @@ -import {ENTITY_UPDATE} from "./entityConstants"; +import { + ENTITY_UPDATE, + ENTITY_DELETE, + ENTITY_CREATE, +} from "./entityConstants"; export function updateEntity(itemType, itemID, newItemAttributes) { return { @@ -10,3 +14,20 @@ export function updateEntity(itemType, itemID, newItemAttributes) { }, }; } + +export function deleteEntity(itemType, itemID) { + return { + type : ENTITY_DELETE, + payload : {itemType, itemID} + }; +} + +export function createEntity(itemType, newItemAttributes) { + return { + type : ENTITY_CREATE, + payload : { + itemType, + newItemAttributes, + }, + }; +} \ No newline at end of file diff --git a/src/features/entities/entityConstants.js b/src/features/entities/entityConstants.js index 97c659f..12408d8 100644 --- a/src/features/entities/entityConstants.js +++ b/src/features/entities/entityConstants.js @@ -1 +1,3 @@ export const ENTITY_UPDATE = "ENTITY_UPDATE"; +export const ENTITY_CREATE = "ENTITY_CREATE"; +export const ENTITY_DELETE = "ENTITY_DELETE"; diff --git a/src/features/entities/entityReducer.js b/src/features/entities/entityReducer.js index c43d972..9a2cd94 100644 --- a/src/features/entities/entityReducer.js +++ b/src/features/entities/entityReducer.js @@ -1,4 +1,8 @@ -import {ENTITY_UPDATE} from "./entityConstants"; +import { + ENTITY_UPDATE, + ENTITY_DELETE, + ENTITY_CREATE, +} from "./entityConstants"; import {createConditionalSliceReducer} from "common/utils/reducerUtils"; @@ -23,8 +27,41 @@ export function updateEntity(state, payload) { return newState; } +export function deleteEntity(state, payload) { + const {itemID, itemType} = payload; + + const session = orm.session(state); + const ModelClass = session[itemType]; + + let newState = state; + + if(ModelClass.hasId(itemID)) { + const modelInstance = ModelClass.withId(itemID); + + modelInstance.delete(); + + newState = session.state + } + + return newState; +} + +export function createEntity(state, payload) { + const {itemType, newItemAttributes} = payload; + + const session = orm.session(state); + const ModelClass = session[itemType]; + + ModelClass.parse(newItemAttributes); + + return session.state; +} + + const entityHandlers = { [ENTITY_UPDATE] : updateEntity, + [ENTITY_CREATE] : createEntity, + [ENTITY_DELETE] : deleteEntity, }; const entityCrudFeatureReducer = createConditionalSliceReducer("entities", entityHandlers); From 128b2acda07e02329ad3a4dfcf74be8a031af07f Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:33:52 -0500 Subject: [PATCH 03/18] Add the ability to delete individual Pilot entries --- .../pilots/PilotsList/PilotsListHeader.jsx | 3 +- .../pilots/PilotsList/PilotsListRow.jsx | 29 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/features/pilots/PilotsList/PilotsListHeader.jsx b/src/features/pilots/PilotsList/PilotsListHeader.jsx index e1a040e..e0fd0e3 100644 --- a/src/features/pilots/PilotsList/PilotsListHeader.jsx +++ b/src/features/pilots/PilotsList/PilotsListHeader.jsx @@ -16,9 +16,10 @@ const PilotsListHeader = () => ( Skills - + Mech + diff --git a/src/features/pilots/PilotsList/PilotsListRow.jsx b/src/features/pilots/PilotsList/PilotsListRow.jsx index 8f07b0f..7956190 100644 --- a/src/features/pilots/PilotsList/PilotsListRow.jsx +++ b/src/features/pilots/PilotsList/PilotsListRow.jsx @@ -1,9 +1,14 @@ import React from "react"; import {connect} from "react-redux"; -import {Table} from "semantic-ui-react"; +import { + Table, + Button, + Icon, +} from "semantic-ui-react"; import _ from "lodash"; import {getEntitiesSession} from "features/entities/entitySelectors"; +import {deleteEntity} from "features/entities/entityActions"; const mapState = (state, ownProps) => { const session = getEntitiesSession(state); @@ -37,7 +42,11 @@ const mapState = (state, ownProps) => { return {pilot}; } -const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected}) => { +const actions = { + deleteEntity, +}; + +const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected, deleteEntity}) => { const { id = null, name = "", @@ -48,6 +57,8 @@ const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected}) => { mechType = "", } = pilot; + const onDeleteClicked = () => deleteEntity("Pilot", id); + return ( onPilotClicked(id)} active={selected}> @@ -65,8 +76,20 @@ const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected}) => { {mechType} + + + ); } -export default connect(mapState)(PilotsListRow); +export default connect(mapState, actions)(PilotsListRow); From 2ca4d620ef7500a3907b31f127b979d97e1eb860 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:40:16 -0500 Subject: [PATCH 04/18] Clear selection and stop editing if the current pilot is deleted --- .../pilots/PilotsList/PilotsListRow.jsx | 11 ++++++++-- src/features/pilots/pilotsReducer.js | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/features/pilots/PilotsList/PilotsListRow.jsx b/src/features/pilots/PilotsList/PilotsListRow.jsx index 7956190..b7cdb75 100644 --- a/src/features/pilots/PilotsList/PilotsListRow.jsx +++ b/src/features/pilots/PilotsList/PilotsListRow.jsx @@ -57,10 +57,17 @@ const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected, deleteEntity} mechType = "", } = pilot; - const onDeleteClicked = () => deleteEntity("Pilot", id); + const onDeleteClicked = (e) => { + e.stopPropagation(); + e.preventDefault(); + deleteEntity("Pilot", id); + } + + const onRowClicked = () => onPilotClicked(id); + return ( - onPilotClicked(id)} active={selected}> + {name} diff --git a/src/features/pilots/pilotsReducer.js b/src/features/pilots/pilotsReducer.js index d233fdb..a1957b8 100644 --- a/src/features/pilots/pilotsReducer.js +++ b/src/features/pilots/pilotsReducer.js @@ -1,5 +1,9 @@ import {createReducer} from "common/utils/reducerUtils"; +import { + ENTITY_DELETE, +} from "features/entities/entityConstants"; + import { PILOT_SELECT, PILOT_EDIT_START, @@ -40,9 +44,25 @@ export function stopEditingPilot(state, payload) { }; } +export function stopEditingIfDeleted(state, payload) { + const {itemType, itemID} = payload; + const {isEditing, currentPilot} = state; + + if(itemType === "Pilot" && itemID === currentPilot) { + return { + ...state, + isEditing : false, + currentPilot : null, + }; + } + + return state; +} + export default createReducer(initialState, { [PILOT_SELECT] : selectPilot, [PILOT_EDIT_START] : startEditingPilot, [PILOT_EDIT_STOP] : stopEditingPilot, + [ENTITY_DELETE] : stopEditingIfDeleted, }); \ No newline at end of file From d93f3a0d4deead216ff6a3be27bd117b3153cfc6 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:55:54 -0500 Subject: [PATCH 05/18] Add an "editingEntities" state slice to store draft data --- src/app/reducers/editingEntitiesReducer.js | 7 +++++++ src/app/reducers/rootReducer.js | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 src/app/reducers/editingEntitiesReducer.js diff --git a/src/app/reducers/editingEntitiesReducer.js b/src/app/reducers/editingEntitiesReducer.js new file mode 100644 index 0000000..695ddd1 --- /dev/null +++ b/src/app/reducers/editingEntitiesReducer.js @@ -0,0 +1,7 @@ +import {createReducer} from "common/utils/reducerUtils"; + +import orm from "app/orm"; +const defaultEditingEntities = orm.getEmptyState(); + +export default createReducer(defaultEditingEntities, { +}); diff --git a/src/app/reducers/rootReducer.js b/src/app/reducers/rootReducer.js index 97d1d9c..fa63590 100644 --- a/src/app/reducers/rootReducer.js +++ b/src/app/reducers/rootReducer.js @@ -3,6 +3,7 @@ import {combineReducers} from "redux"; import {reduceReducers} from "common/utils/reducerUtils"; import entitiesReducer from "./entitiesReducer"; +import editingEntitiesReducer from "./editingEntitiesReducer"; import pilotsReducer from "features/pilots/pilotsReducer"; import mechsReducer from "features/mechs/mechsReducer"; import tabReducer from "features/tabs/tabsReducer"; @@ -13,6 +14,7 @@ import entityCrudReducer from "features/entities/entityReducer"; const combinedReducer = combineReducers({ entities : entitiesReducer, + editingEntities : editingEntitiesReducer, pilots : pilotsReducer, mechs : mechsReducer, unitInfo : unitInfoReducer, From cbf7fc3961031408129e6a84eb1971e40f411d40 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:56:12 -0500 Subject: [PATCH 06/18] Add a utility function to look up a model by type and ID --- src/common/utils/modelUtils.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/common/utils/modelUtils.js diff --git a/src/common/utils/modelUtils.js b/src/common/utils/modelUtils.js new file mode 100644 index 0000000..face63b --- /dev/null +++ b/src/common/utils/modelUtils.js @@ -0,0 +1,5 @@ +export function getModelByType(session, itemType, itemID) { + const modelClass = session[itemType]; + const model = modelClass.withId(itemID); + return model; +} From 6a29f3ba81ab237103727203f675f4b01abf9352 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 21:57:31 -0500 Subject: [PATCH 07/18] Create an empty editing feature reducer --- src/app/reducers/rootReducer.js | 2 ++ src/features/editing/editingReducer.js | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 src/features/editing/editingReducer.js diff --git a/src/app/reducers/rootReducer.js b/src/app/reducers/rootReducer.js index fa63590..963d40f 100644 --- a/src/app/reducers/rootReducer.js +++ b/src/app/reducers/rootReducer.js @@ -10,6 +10,7 @@ import tabReducer from "features/tabs/tabsReducer"; import unitInfoReducer from "features/unitInfo/unitInfoReducer"; import entityCrudReducer from "features/entities/entityReducer"; +import editingFeatureReducer from "features/editing/editingReducer"; const combinedReducer = combineReducers({ @@ -24,6 +25,7 @@ const combinedReducer = combineReducers({ const rootReducer = reduceReducers( combinedReducer, entityCrudReducer, + editingFeatureReducer, ); export default rootReducer; \ No newline at end of file diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js new file mode 100644 index 0000000..1ceebd9 --- /dev/null +++ b/src/features/editing/editingReducer.js @@ -0,0 +1,7 @@ +import {createReducer} from "common/utils/reducerUtils"; + + +const editingFeatureReducer = createReducer({}, { +}); + +export default editingFeatureReducer; From 17d04efc51163f5aa52bd4d3a8c207fa2b292171 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 23:07:47 -0500 Subject: [PATCH 08/18] Add editing utility functions --- src/features/editing/editingUtils.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/features/editing/editingUtils.js diff --git a/src/features/editing/editingUtils.js b/src/features/editing/editingUtils.js new file mode 100644 index 0000000..b6c601c --- /dev/null +++ b/src/features/editing/editingUtils.js @@ -0,0 +1,27 @@ +import orm from "app/orm"; +import {getModelByType} from "common/utils/modelUtils"; + +export function updateEditingEntitiesState(state, updatedEditingEntities) { + return { + ...state, + editingEntities : updatedEditingEntities, + }; +} + +export function updateEntitiesState(state, updatedEntities) { + return { + ...state, + entities : updatedEntities, + }; +} + +export function readEntityData(entities, itemType, itemID) { + const readSession = orm.session(entities); + + // Look up the model instance for the requested item + const model = getModelByType(readSession, itemType, itemID); + const data = model.toJSON(); + + return data; +} + From f0cca7b59519e663a6c62087ed7029631c5ebc69 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 23:07:55 -0500 Subject: [PATCH 09/18] Add toJSON() methods to Redux-ORM model classes --- src/features/mechs/Mech.js | 5 +++++ src/features/mechs/MechDesign.js | 5 +++++ src/features/pilots/Pilot.js | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/features/mechs/Mech.js b/src/features/mechs/Mech.js index f885b4f..3968a64 100644 --- a/src/features/mechs/Mech.js +++ b/src/features/mechs/Mech.js @@ -12,5 +12,10 @@ export default class Mech extends Model { static parse(mechData) { return this.create(mechData); } + + toJSON() { + return {...this.ref}; + } + } diff --git a/src/features/mechs/MechDesign.js b/src/features/mechs/MechDesign.js index 9e11f69..ea95f0e 100644 --- a/src/features/mechs/MechDesign.js +++ b/src/features/mechs/MechDesign.js @@ -12,4 +12,9 @@ export default class MechDesign extends Model { static parse(designData) { return this.create(designData); } + + toJSON() { + return {...this.ref}; + } + } diff --git a/src/features/pilots/Pilot.js b/src/features/pilots/Pilot.js index b6f8f4a..d208324 100644 --- a/src/features/pilots/Pilot.js +++ b/src/features/pilots/Pilot.js @@ -23,4 +23,9 @@ export default class Pilot extends Model { // class itself, not an instance return this.create(pilotData); } + + toJSON() { + return {...this.ref}; + } + } From f12a784237eae333b8d3c9459f048181de399471 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Tue, 7 Nov 2017 23:20:27 -0500 Subject: [PATCH 10/18] Add generic reducer logic for editing an entity --- src/features/editing/editingActions.js | 37 ++++++++++++++ src/features/editing/editingConstants.js | 3 ++ src/features/editing/editingReducer.js | 65 +++++++++++++++++++++++- src/features/editing/editingSelectors.js | 1 + 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/features/editing/editingActions.js create mode 100644 src/features/editing/editingConstants.js create mode 100644 src/features/editing/editingSelectors.js diff --git a/src/features/editing/editingActions.js b/src/features/editing/editingActions.js new file mode 100644 index 0000000..c986423 --- /dev/null +++ b/src/features/editing/editingActions.js @@ -0,0 +1,37 @@ +import { + EDIT_ITEM_EXISTING, + EDIT_ITEM_UPDATE, + EDIT_ITEM_STOP +} from "./editingConstants"; + + +export function editExistingItem(itemType, itemID) { + return { + type : EDIT_ITEM_EXISTING, + payload : { + itemType, + itemID + }, + }; +} + +export function editItemAttributes(itemType, itemID, newItemAttributes) { + return { + type : EDIT_ITEM_UPDATE, + payload : { + itemType, + itemID, + newItemAttributes, + }, + }; +} + +export function stopEditingItem(itemType, itemID) { + return { + type : EDIT_ITEM_STOP, + payload : { + itemType, + itemID + }, + }; +} \ No newline at end of file diff --git a/src/features/editing/editingConstants.js b/src/features/editing/editingConstants.js new file mode 100644 index 0000000..0504d53 --- /dev/null +++ b/src/features/editing/editingConstants.js @@ -0,0 +1,3 @@ +export const EDIT_ITEM_EXISTING = "EDIT_ITEM_EXISTING"; +export const EDIT_ITEM_UPDATE = "EDIT_ITEM_UPDATE"; +export const EDIT_ITEM_STOP = "EDIT_ITEM_STOP"; diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js index 1ceebd9..a567593 100644 --- a/src/features/editing/editingReducer.js +++ b/src/features/editing/editingReducer.js @@ -1,7 +1,70 @@ import {createReducer} from "common/utils/reducerUtils"; +import { + createEntity, + updateEntity, + deleteEntity +} from "features/entities/entityReducer"; + +import { + EDIT_ITEM_EXISTING, + EDIT_ITEM_UPDATE, + EDIT_ITEM_STOP +} from "./editingConstants"; + + +import {selectEntities} from "features/entities/entitySelectors"; +import {selectEditingEntities} from "./editingSelectors"; +import { + readEntityData, + updateEditingEntitiesState, +} from "./editingUtils"; + + + +export function copyEntity(sourceEntities, destinationEntities, payload) { + const {itemID, itemType} = payload; + + const newItemAttributes = readEntityData(sourceEntities, itemType, itemID); + const creationPayload = {itemType, itemID, newItemAttributes} + + const updatedEntities = createEntity(destinationEntities, creationPayload); + return updatedEntities; +} + + + + +export function editItemExisting(state, payload) { + const entities = selectEntities(state); + const editingEntities = selectEditingEntities(state); + + const updatedEditingEntities = copyEntity(entities, editingEntities, payload); + + return updateEditingEntitiesState(state, updatedEditingEntities); +} + +export function editItemUpdate(state, payload) { + const editingEntities = selectEditingEntities(state); + + const updatedEditingEntities = updateEntity(editingEntities, payload); + return updateEditingEntitiesState(state, updatedEditingEntities); +} + +export function editItemStop(state, payload) { + const editingEntities = selectEditingEntities(state); + + const updatedEditingEntities = deleteEntity(editingEntities, payload); + return updateEditingEntitiesState(state, updatedEditingEntities); +} + + + const editingFeatureReducer = createReducer({}, { + [EDIT_ITEM_EXISTING] : editItemExisting, + [EDIT_ITEM_UPDATE] : editItemUpdate, + [EDIT_ITEM_STOP] : editItemStop, }); -export default editingFeatureReducer; +export default editingFeatureReducer; \ No newline at end of file diff --git a/src/features/editing/editingSelectors.js b/src/features/editing/editingSelectors.js new file mode 100644 index 0000000..0e0ae9d --- /dev/null +++ b/src/features/editing/editingSelectors.js @@ -0,0 +1 @@ +export const selectEditingEntities = state => state.editingEntities; From db9b7f7dd08c3ba0e7464f14bc91cdf0eb00d1e3 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:08:51 -0500 Subject: [PATCH 11/18] Add ability to display pilot entry from "draft" editingEntities slice --- src/features/editing/editingReducer.js | 3 +++ src/features/editing/editingSelectors.js | 10 +++++++ src/features/pilots/PilotDetails.jsx | 33 +++++++++++++++++------- src/features/pilots/pilotsActions.js | 23 +++++++++++------ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js index a567593..411b573 100644 --- a/src/features/editing/editingReducer.js +++ b/src/features/editing/editingReducer.js @@ -26,6 +26,9 @@ export function copyEntity(sourceEntities, destinationEntities, payload) { const {itemID, itemType} = payload; const newItemAttributes = readEntityData(sourceEntities, itemType, itemID); + if(newItemAttributes.name) { + newItemAttributes.name += " (copied)"; + } const creationPayload = {itemType, itemID, newItemAttributes} const updatedEntities = createEntity(destinationEntities, creationPayload); diff --git a/src/features/editing/editingSelectors.js b/src/features/editing/editingSelectors.js index 0e0ae9d..06fe3dc 100644 --- a/src/features/editing/editingSelectors.js +++ b/src/features/editing/editingSelectors.js @@ -1 +1,11 @@ +import {createSelector} from "reselect"; + +import orm from "app/orm"; + + export const selectEditingEntities = state => state.editingEntities; + +export const getEditingEntitiesSession = createSelector( + selectEditingEntities, + editingEntities => orm.session(editingEntities) +); \ No newline at end of file diff --git a/src/features/pilots/PilotDetails.jsx b/src/features/pilots/PilotDetails.jsx index e3f851b..bad918d 100644 --- a/src/features/pilots/PilotDetails.jsx +++ b/src/features/pilots/PilotDetails.jsx @@ -5,6 +5,7 @@ import {Form, Dropdown, Grid, Button} from "semantic-ui-react"; import FormEditWrapper from "common/components/FormEditWrapper"; import {getEntitiesSession} from "features/entities/entitySelectors"; +import {getEditingEntitiesSession} from "features/editing/editingSelectors"; import { selectCurrentPilot, @@ -53,16 +54,20 @@ const mapState = (state) => { const currentPilot = selectCurrentPilot(state); - const session = getEntitiesSession(state); - const {Pilot} = session; - - if(Pilot.hasId(currentPilot)) { - pilot = Pilot.withId(currentPilot).ref; - } - const pilotIsSelected = Boolean(currentPilot); const isEditingPilot = selectIsEditingPilot(state); + if(pilotIsSelected) { + const session = isEditingPilot ? + getEditingEntitiesSession(state) : + getEntitiesSession(state); + + const {Pilot} = session; + + if(Pilot.hasId(currentPilot)) { + pilot = Pilot.withId(currentPilot).ref; + } + } return {pilot, pilotIsSelected, isEditingPilot} } @@ -90,6 +95,16 @@ export class PilotDetails extends Component { this.props.updateEntity("Pilot", id, newValues); } + onStartEditingClicked = () => { + const {id} = this.props.pilot; + this.props.startEditingPilot(id); + } + + onStopEditingClicked = () => { + const {id} = this.props.pilot; + this.props.stopEditingPilot(id); + } + render() { const {pilot={}, pilotIsSelected = false, isEditingPilot = false } = this.props; const {startEditingPilot, stopEditingPilot} = this.props; @@ -190,7 +205,7 @@ export class PilotDetails extends Component { primary disabled={!canStartEditing} type="button" - onClick={startEditingPilot} + onClick={this.onStartEditingClicked} > Start Editing @@ -198,7 +213,7 @@ export class PilotDetails extends Component { secondary disabled={!canStopEditing} type="button" - onClick={stopEditingPilot} + onClick={this.onStopEditingClicked} > Stop Editing diff --git a/src/features/pilots/pilotsActions.js b/src/features/pilots/pilotsActions.js index 20fc6d9..a6380c1 100644 --- a/src/features/pilots/pilotsActions.js +++ b/src/features/pilots/pilotsActions.js @@ -1,3 +1,8 @@ +import { + editExistingItem, + stopEditingItem +} from "features/editing/editingActions"; + import { PILOT_SELECT, PILOT_EDIT_START, @@ -11,14 +16,16 @@ export function selectPilot(pilotID) { }; } -export function startEditingPilot() { - return { - type : PILOT_EDIT_START, - }; +export function startEditingPilot(pilotID) { + return (dispatch, getState) => { + dispatch(editExistingItem("Pilot", pilotID)); + dispatch({type : PILOT_EDIT_START}); + } } -export function stopEditingPilot() { - return { - type : PILOT_EDIT_STOP, - }; +export function stopEditingPilot(pilotID) { + return (dispatch, getState) => { + dispatch({type : PILOT_EDIT_STOP}); + dispatch(stopEditingItem("Pilot", pilotID)); + } } \ No newline at end of file From b90405e0e2fa9e67f1c1f0eb3dd3aab07d92efe2 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:09:12 -0500 Subject: [PATCH 12/18] Update pilot editing logic to apply to draft entry --- src/features/editing/editingReducer.js | 3 --- src/features/pilots/PilotDetails.jsx | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js index 411b573..a567593 100644 --- a/src/features/editing/editingReducer.js +++ b/src/features/editing/editingReducer.js @@ -26,9 +26,6 @@ export function copyEntity(sourceEntities, destinationEntities, payload) { const {itemID, itemType} = payload; const newItemAttributes = readEntityData(sourceEntities, itemType, itemID); - if(newItemAttributes.name) { - newItemAttributes.name += " (copied)"; - } const creationPayload = {itemType, itemID, newItemAttributes} const updatedEntities = createEntity(destinationEntities, creationPayload); diff --git a/src/features/pilots/PilotDetails.jsx b/src/features/pilots/PilotDetails.jsx index bad918d..8b370b4 100644 --- a/src/features/pilots/PilotDetails.jsx +++ b/src/features/pilots/PilotDetails.jsx @@ -12,7 +12,7 @@ import { selectIsEditingPilot } from "./pilotsSelectors"; -import {updateEntity} from "features/entities/entityActions"; +import {editItemAttributes} from "features/editing/editingActions"; import {getValueFromEvent} from "common/utils/clientUtils"; @@ -75,7 +75,7 @@ const mapState = (state) => { const actions = { startEditingPilot, stopEditingPilot, - updateEntity, + editItemAttributes, } export class PilotDetails extends Component { @@ -84,7 +84,7 @@ export class PilotDetails extends Component { const newValues = getValueFromEvent(e); const {id} = this.props.pilot; - this.props.updateEntity("Pilot", id, newValues); + this.props.editItemAttributes("Pilot", id, newValues); } onDropdownChanged = (e, result) => { @@ -92,7 +92,7 @@ export class PilotDetails extends Component { const newValues = { [name] : value}; const {id} = this.props.pilot; - this.props.updateEntity("Pilot", id, newValues); + this.props.editItemAttributes("Pilot", id, newValues); } onStartEditingClicked = () => { From b31b7b442ace8bf0321a05603221095fa429044d Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:16:52 -0500 Subject: [PATCH 13/18] Add updateFrom methods to models --- src/features/mechs/Mech.js | 4 ++++ src/features/mechs/MechDesign.js | 4 ++++ src/features/pilots/Pilot.js | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/features/mechs/Mech.js b/src/features/mechs/Mech.js index 3968a64..dfb5173 100644 --- a/src/features/mechs/Mech.js +++ b/src/features/mechs/Mech.js @@ -17,5 +17,9 @@ export default class Mech extends Model { return {...this.ref}; } + updateFrom(otherMech) { + this.update(otherMech.ref); + } + } diff --git a/src/features/mechs/MechDesign.js b/src/features/mechs/MechDesign.js index ea95f0e..3456bb8 100644 --- a/src/features/mechs/MechDesign.js +++ b/src/features/mechs/MechDesign.js @@ -17,4 +17,8 @@ export default class MechDesign extends Model { return {...this.ref}; } + updateFrom(otherDesign) { + this.update(otherDesign.ref); + } + } diff --git a/src/features/pilots/Pilot.js b/src/features/pilots/Pilot.js index d208324..86d8e06 100644 --- a/src/features/pilots/Pilot.js +++ b/src/features/pilots/Pilot.js @@ -28,4 +28,8 @@ export default class Pilot extends Model { return {...this.ref}; } + updateFrom(otherPilot) { + this.update(otherPilot.ref); + } + } From fd80c8101517d43b1d9a3d151aa7399d1f683037 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:27:53 -0500 Subject: [PATCH 14/18] Add logic to apply item edits to the "current data" slice --- src/features/editing/editingActions.js | 13 ++++++- src/features/editing/editingConstants.js | 1 + src/features/editing/editingReducer.js | 46 ++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/features/editing/editingActions.js b/src/features/editing/editingActions.js index c986423..60de4b8 100644 --- a/src/features/editing/editingActions.js +++ b/src/features/editing/editingActions.js @@ -1,7 +1,8 @@ import { EDIT_ITEM_EXISTING, EDIT_ITEM_UPDATE, - EDIT_ITEM_STOP + EDIT_ITEM_APPLY, + EDIT_ITEM_STOP, } from "./editingConstants"; @@ -15,6 +16,16 @@ export function editExistingItem(itemType, itemID) { }; } +export function applyItemEdits(itemType, itemID) { + return { + type : EDIT_ITEM_APPLY, + payload : { + itemType, + itemID + }, + }; +} + export function editItemAttributes(itemType, itemID, newItemAttributes) { return { type : EDIT_ITEM_UPDATE, diff --git a/src/features/editing/editingConstants.js b/src/features/editing/editingConstants.js index 0504d53..afc01c9 100644 --- a/src/features/editing/editingConstants.js +++ b/src/features/editing/editingConstants.js @@ -1,3 +1,4 @@ export const EDIT_ITEM_EXISTING = "EDIT_ITEM_EXISTING"; export const EDIT_ITEM_UPDATE = "EDIT_ITEM_UPDATE"; +export const EDIT_ITEM_APPLY = "EDIT_ITEM_APPLY"; export const EDIT_ITEM_STOP = "EDIT_ITEM_STOP"; diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js index a567593..dcb279e 100644 --- a/src/features/editing/editingReducer.js +++ b/src/features/editing/editingReducer.js @@ -1,5 +1,7 @@ import {createReducer} from "common/utils/reducerUtils"; +import orm from "app/orm"; + import { createEntity, updateEntity, @@ -9,14 +11,17 @@ import { import { EDIT_ITEM_EXISTING, EDIT_ITEM_UPDATE, + EDIT_ITEM_APPLY, EDIT_ITEM_STOP } from "./editingConstants"; +import {getModelByType} from "common/utils/modelUtils"; import {selectEntities} from "features/entities/entitySelectors"; import {selectEditingEntities} from "./editingSelectors"; import { readEntityData, + updateEntitiesState, updateEditingEntitiesState, } from "./editingUtils"; @@ -33,6 +38,38 @@ export function copyEntity(sourceEntities, destinationEntities, payload) { } +export function updateEditedEntity(sourceEntities, destinationEntities, payload) { + // Start by reading our "work-in-progress" data + const readSession = orm.session(sourceEntities); + + const {itemType, itemID} = payload; + + // Look up the model instance for the requested item + const model = getModelByType(readSession, itemType, itemID); + + + // We of course will be updating our "current" relational data + let writeSession = orm.session(destinationEntities); + + const ModelClass = writeSession[itemType]; + + if(ModelClass.hasId(itemID)) { + // Look up the original Model instance for the top item + const existingItem = ModelClass.withId(itemID); + + if(existingItem.updateFrom) { + // Each model class should know how to properly update itself and its + // relations from another model of the same type. Ask the original model to + // update itself based on the "work-in-progress" model, which queues up a + // series of immutable add/update/delete actions internally + existingItem.updateFrom(model); + } + } + + // The session contains our new "current" relational data + const updatedEntities = writeSession.state; + return updatedEntities; +} export function editItemExisting(state, payload) { @@ -59,11 +96,20 @@ export function editItemStop(state, payload) { } +export function editItemApply(state, payload) { + const entities = selectEntities(state); + const editingEntities = selectEditingEntities(state); + + const updatedEntities = updateEditedEntity(editingEntities, entities, payload); + return updateEntitiesState(state, updatedEntities); +} + const editingFeatureReducer = createReducer({}, { [EDIT_ITEM_EXISTING] : editItemExisting, [EDIT_ITEM_UPDATE] : editItemUpdate, + [EDIT_ITEM_APPLY] : editItemApply, [EDIT_ITEM_STOP] : editItemStop, }); From d425bc839fa23341e9e22f69d83778b390707b8d Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:42:20 -0500 Subject: [PATCH 15/18] Rework pilot logic to explicitly stop editing on selection --- src/features/pilots/PilotDetails.jsx | 6 ++---- src/features/pilots/pilotsActions.js | 31 +++++++++++++++++++++------- src/features/pilots/pilotsReducer.js | 2 -- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/features/pilots/PilotDetails.jsx b/src/features/pilots/PilotDetails.jsx index 8b370b4..7b76839 100644 --- a/src/features/pilots/PilotDetails.jsx +++ b/src/features/pilots/PilotDetails.jsx @@ -96,13 +96,11 @@ export class PilotDetails extends Component { } onStartEditingClicked = () => { - const {id} = this.props.pilot; - this.props.startEditingPilot(id); + this.props.startEditingPilot(); } onStopEditingClicked = () => { - const {id} = this.props.pilot; - this.props.stopEditingPilot(id); + this.props.stopEditingPilot(); } render() { diff --git a/src/features/pilots/pilotsActions.js b/src/features/pilots/pilotsActions.js index a6380c1..8c398b3 100644 --- a/src/features/pilots/pilotsActions.js +++ b/src/features/pilots/pilotsActions.js @@ -9,23 +9,38 @@ import { PILOT_EDIT_STOP, } from "./pilotsConstants"; +import {selectCurrentPilot, selectIsEditingPilot} from "./pilotsSelectors"; + export function selectPilot(pilotID) { - return { - type : PILOT_SELECT, - payload : {currentPilot : pilotID}, - }; + return (dispatch, getState) => { + const state = getState(); + const isEditing = selectIsEditingPilot(state); + + if(isEditing) { + dispatch(stopEditingPilot()) + } + + dispatch({ + type : PILOT_SELECT, + payload : {currentPilot : pilotID}, + }); + } } -export function startEditingPilot(pilotID) { +export function startEditingPilot() { return (dispatch, getState) => { - dispatch(editExistingItem("Pilot", pilotID)); + const currentPilot = selectCurrentPilot(getState()); + + dispatch(editExistingItem("Pilot", currentPilot)); dispatch({type : PILOT_EDIT_START}); } } -export function stopEditingPilot(pilotID) { +export function stopEditingPilot() { return (dispatch, getState) => { + const currentPilot = selectCurrentPilot(getState()); + dispatch({type : PILOT_EDIT_STOP}); - dispatch(stopEditingItem("Pilot", pilotID)); + dispatch(stopEditingItem("Pilot", currentPilot)); } } \ No newline at end of file diff --git a/src/features/pilots/pilotsReducer.js b/src/features/pilots/pilotsReducer.js index a1957b8..e16c7dc 100644 --- a/src/features/pilots/pilotsReducer.js +++ b/src/features/pilots/pilotsReducer.js @@ -25,8 +25,6 @@ export function selectPilot(state, payload) { // Deselect entirely if it's a second click on the same pilot, // otherwise go ahead and select the one that was clicked currentPilot : isSamePilot ? null : newSelectedPilot, - // Any time we select a different pilot, we stop editing - isEditing : false, }; } From 6b13991b86a20ca85d8e28f5c386264dfff2bf9f Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:50:09 -0500 Subject: [PATCH 16/18] Save changes to pilot entries when editing is stopped --- src/features/pilots/pilotsActions.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/features/pilots/pilotsActions.js b/src/features/pilots/pilotsActions.js index 8c398b3..c11ee3d 100644 --- a/src/features/pilots/pilotsActions.js +++ b/src/features/pilots/pilotsActions.js @@ -1,5 +1,6 @@ import { editExistingItem, + applyItemEdits, stopEditingItem } from "features/editing/editingActions"; @@ -41,6 +42,7 @@ export function stopEditingPilot() { const currentPilot = selectCurrentPilot(getState()); dispatch({type : PILOT_EDIT_STOP}); + dispatch(applyItemEdits("Pilot", currentPilot)); dispatch(stopEditingItem("Pilot", currentPilot)); } } \ No newline at end of file From c19cd773bb3ce332fab3560867bd685b137c29a1 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 22:59:27 -0500 Subject: [PATCH 17/18] Add logic to reset a currently edited item --- src/features/editing/editingActions.js | 11 +++++++++++ src/features/editing/editingConstants.js | 1 + src/features/editing/editingReducer.js | 12 +++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/features/editing/editingActions.js b/src/features/editing/editingActions.js index 60de4b8..2e0dd8e 100644 --- a/src/features/editing/editingActions.js +++ b/src/features/editing/editingActions.js @@ -3,6 +3,7 @@ import { EDIT_ITEM_UPDATE, EDIT_ITEM_APPLY, EDIT_ITEM_STOP, + EDIT_ITEM_RESET, } from "./editingConstants"; @@ -45,4 +46,14 @@ export function stopEditingItem(itemType, itemID) { itemID }, }; +} + +export function resetEditedItem(itemType, itemID) { + return { + type : EDIT_ITEM_RESET, + payload : { + itemType, + itemID, + }, + }; } \ No newline at end of file diff --git a/src/features/editing/editingConstants.js b/src/features/editing/editingConstants.js index afc01c9..0fbb83b 100644 --- a/src/features/editing/editingConstants.js +++ b/src/features/editing/editingConstants.js @@ -2,3 +2,4 @@ export const EDIT_ITEM_EXISTING = "EDIT_ITEM_EXISTING"; export const EDIT_ITEM_UPDATE = "EDIT_ITEM_UPDATE"; export const EDIT_ITEM_APPLY = "EDIT_ITEM_APPLY"; export const EDIT_ITEM_STOP = "EDIT_ITEM_STOP"; +export const EDIT_ITEM_RESET = "EDIT_ITEM_RESET"; diff --git a/src/features/editing/editingReducer.js b/src/features/editing/editingReducer.js index dcb279e..862a27b 100644 --- a/src/features/editing/editingReducer.js +++ b/src/features/editing/editingReducer.js @@ -12,7 +12,8 @@ import { EDIT_ITEM_EXISTING, EDIT_ITEM_UPDATE, EDIT_ITEM_APPLY, - EDIT_ITEM_STOP + EDIT_ITEM_STOP, + EDIT_ITEM_RESET, } from "./editingConstants"; import {getModelByType} from "common/utils/modelUtils"; @@ -105,12 +106,21 @@ export function editItemApply(state, payload) { } +export function editItemReset(state, payload) { + const stateWithoutItem = editItemStop(state, payload); + const stateWithCurrentItem = editItemExisting(stateWithoutItem, payload); + + return stateWithCurrentItem; +} + + const editingFeatureReducer = createReducer({}, { [EDIT_ITEM_EXISTING] : editItemExisting, [EDIT_ITEM_UPDATE] : editItemUpdate, [EDIT_ITEM_APPLY] : editItemApply, [EDIT_ITEM_STOP] : editItemStop, + [EDIT_ITEM_RESET] : editItemReset, }); export default editingFeatureReducer; \ No newline at end of file From de269edf679fe9c771bafd4f8b0fa4dd6f9f4a57 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Wed, 8 Nov 2017 23:10:15 -0500 Subject: [PATCH 18/18] Add the ability to reset and cancel editing a pilot --- src/features/pilots/PilotDetails.jsx | 37 +++++++++++++++++++++++++++- src/features/pilots/pilotsActions.js | 11 ++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/features/pilots/PilotDetails.jsx b/src/features/pilots/PilotDetails.jsx index 7b76839..925969d 100644 --- a/src/features/pilots/PilotDetails.jsx +++ b/src/features/pilots/PilotDetails.jsx @@ -20,8 +20,13 @@ import {getValueFromEvent} from "common/utils/clientUtils"; import { startEditingPilot, stopEditingPilot, + cancelEditingPilot, } from "./pilotsActions"; +import { + resetEditedItem, +} from "features/editing/editingActions"; + const RANKS = [ {value: "Private", text : "Private"}, @@ -76,6 +81,8 @@ const actions = { startEditingPilot, stopEditingPilot, editItemAttributes, + resetEditedItem, + cancelEditingPilot, } export class PilotDetails extends Component { @@ -103,6 +110,11 @@ export class PilotDetails extends Component { this.props.stopEditingPilot(); } + onResetClicked = () => { + const {id} = this.props.pilot; + this.props.resetEditedItem("Pilot", id); + } + render() { const {pilot={}, pilotIsSelected = false, isEditingPilot = false } = this.props; const {startEditingPilot, stopEditingPilot} = this.props; @@ -119,6 +131,8 @@ export class PilotDetails extends Component { const canStartEditing = pilotIsSelected && !isEditingPilot; const canStopEditing = pilotIsSelected && isEditingPilot; + const buttonWidth = 140; + return (
Start Editing @@ -211,9 +226,29 @@ export class PilotDetails extends Component { secondary disabled={!canStopEditing} type="button" + style={{width : buttonWidth}} onClick={this.onStopEditingClicked} > - Stop Editing + Save Edits + + + + + diff --git a/src/features/pilots/pilotsActions.js b/src/features/pilots/pilotsActions.js index c11ee3d..d322997 100644 --- a/src/features/pilots/pilotsActions.js +++ b/src/features/pilots/pilotsActions.js @@ -18,7 +18,7 @@ export function selectPilot(pilotID) { const isEditing = selectIsEditingPilot(state); if(isEditing) { - dispatch(stopEditingPilot()) + dispatch(cancelEditingPilot()); } dispatch({ @@ -45,4 +45,13 @@ export function stopEditingPilot() { dispatch(applyItemEdits("Pilot", currentPilot)); dispatch(stopEditingItem("Pilot", currentPilot)); } +} + +export function cancelEditingPilot() { + return (dispatch, getState) => { + const currentPilot = selectCurrentPilot(getState()); + + dispatch({type : PILOT_EDIT_STOP}); + dispatch(stopEditingItem("Pilot", currentPilot)); + } } \ No newline at end of file