Skip to content

Commit aa5199c

Browse files
Merge pull request #459 from hamiltoes/temp-clone-management
Temp clone management
2 parents 0d50b62 + 013f4fc commit aa5199c

File tree

8 files changed

+253
-73
lines changed

8 files changed

+253
-73
lines changed

src/service-module/make-base-model.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,7 @@ export default function makeBaseModel(options: FeathersVuexOptions) {
185185
}
186186

187187
public static getFromStore(id, params?) {
188-
if (params) {
189-
return this._getters('get', id, params)
190-
} else {
191-
return this._getters('get', id)
192-
}
188+
return this._getters('get', id, params)
193189
}
194190

195191
/**

src/service-module/service-module.actions.ts

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default function makeServiceActions(service: Service<any>) {
5151
return service
5252
.get(id, params)
5353
.then(async function(item) {
54-
await dispatch('addOrUpdate', item)
54+
dispatch('addOrUpdate', item)
5555
commit('unsetPending', 'get')
5656
return state.keyedById[id]
5757
})
@@ -99,7 +99,7 @@ export default function makeServiceActions(service: Service<any>) {
9999
.create(data, params)
100100
.then(async response => {
101101
if (Array.isArray(response)) {
102-
await dispatch('addOrUpdateList', response)
102+
dispatch('addOrUpdateList', response)
103103
response = response.map(item => {
104104
const id = getId(item, idField)
105105

@@ -112,7 +112,7 @@ export default function makeServiceActions(service: Service<any>) {
112112
if (id != null && tempId != null) {
113113
commit('updateTemp', { id, tempId })
114114
}
115-
response = await dispatch('addOrUpdate', response)
115+
response = dispatch('addOrUpdate', response)
116116

117117
// response = state.keyedById[id]
118118
}
@@ -135,7 +135,7 @@ export default function makeServiceActions(service: Service<any>) {
135135
return service
136136
.update(id, data, params)
137137
.then(async function(item) {
138-
await dispatch('addOrUpdate', item)
138+
dispatch('addOrUpdate', item)
139139
commit('unsetPending', 'update')
140140
return state.keyedById[id]
141141
})
@@ -165,7 +165,7 @@ export default function makeServiceActions(service: Service<any>) {
165165
return service
166166
.patch(id, data, params)
167167
.then(async function(item) {
168-
await dispatch('addOrUpdate', item)
168+
dispatch('addOrUpdate', item)
169169
commit('unsetPending', 'patch')
170170
return state.keyedById[id]
171171
})
@@ -223,7 +223,7 @@ export default function makeServiceActions(service: Service<any>) {
223223
const { qid = 'default', query } = params
224224
const { idField } = state
225225

226-
await dispatch('addOrUpdateList', response)
226+
dispatch('addOrUpdateList', response)
227227
commit('unsetPending', 'find')
228228

229229
const mapItemFromState = item => {
@@ -260,7 +260,7 @@ export default function makeServiceActions(service: Service<any>) {
260260
return response
261261
},
262262

263-
async addOrUpdateList({ state, commit }, response) {
263+
addOrUpdateList({ state, commit }, response) {
264264
const list = response.data || response
265265
const isPaginated = response.hasOwnProperty('total')
266266
const toAdd = []
@@ -292,9 +292,7 @@ export default function makeServiceActions(service: Service<any>) {
292292

293293
if (service.FeathersVuexModel) {
294294
toAdd.forEach((item, index) => {
295-
toAdd[index] = new service.FeathersVuexModel(item, {
296-
skipCommit: true
297-
})
295+
toAdd[index] = new service.FeathersVuexModel(item, { commit: false })
298296
})
299297
}
300298

@@ -311,33 +309,27 @@ export default function makeServiceActions(service: Service<any>) {
311309
* the `create` response returns to create the record. The reference to the
312310
* original temporary record must be maintained in order to preserve reactivity.
313311
*/
314-
async addOrUpdate({ state, commit }, item) {
312+
addOrUpdate({ state, commit }, item) {
315313
const { idField } = state
316314
const id = getId(item, idField)
317-
const existingItem = state.keyedById[id]
318315

319316
const isIdOk = id !== null && id !== undefined
320317

321-
if (service.FeathersVuexModel && !item.isFeathersVuexInstance) {
322-
item = new service.FeathersVuexModel(item)
318+
if (
319+
service.FeathersVuexModel &&
320+
!(item instanceof service.FeathersVuexModel)
321+
) {
322+
item = new service.FeathersVuexModel(item, { commit: false })
323323
}
324324

325-
// If the item has a matching temp, update the temp and provide it as the new item.
326-
const temp = state.tempsByNewId[id]
327-
if (temp) {
328-
commit('merge', { dest: temp, source: item })
329-
commit('remove__isTemp', temp)
330-
}
331325
if (isIdOk) {
332-
if (existingItem && temp) {
333-
commit('replaceItemWithTemp', { item, temp })
326+
if (state.keyedById[id]) {
327+
commit('updateItem', item)
334328
} else {
335-
existingItem
336-
? commit('updateItem', temp || item)
337-
: commit('addItem', temp || item)
329+
commit('addItem', item)
338330
}
339331
}
340-
return temp || item
332+
return item
341333
}
342334
}
343335
/**

src/service-module/service-module.getters.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function makeServiceGetters() {
2626
// Set params.temps to true to include the tempsById records
2727
params.temps = params.hasOwnProperty('temps') ? params.temps : false
2828

29-
const { paramsForServer, whitelist } = state
29+
const { paramsForServer, whitelist, keyedById } = state
3030
const q = _omit(params.query || {}, paramsForServer)
3131
const customOperators = Object.keys(q).filter(
3232
k => k[0] === '$' && !defaultOps.includes(k)
@@ -36,7 +36,7 @@ export default function makeServiceGetters() {
3636
const { query, filters } = filterQuery(cleanQuery, {
3737
operators: additionalOperators.concat(whitelist)
3838
})
39-
let values = _.values(state.keyedById)
39+
let values = _.values(keyedById)
4040

4141
if (params.temps) {
4242
values = values.concat(_.values(state.tempsById))

src/service-module/service-module.mutations.ts

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default function makeServiceMutations() {
2121
function addItems(state, items) {
2222
const { serverAlias, idField, tempIdField, modelName } = state
2323
const Model = _get(models, `[${serverAlias}][${modelName}]`)
24-
const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`)
24+
const BaseModel = _get(models, `[${serverAlias}].BaseModel`)
2525

2626
for (let item of items) {
2727
const id = getId(item, idField)
@@ -71,7 +71,7 @@ export default function makeServiceMutations() {
7171
if (state.ids.includes(id)) {
7272
// Completely replace the item
7373
if (replaceItems) {
74-
if (Model && !item.isFeathersVuexInstance) {
74+
if (Model && !(item instanceof Model)) {
7575
item = new Model(item)
7676
}
7777
Vue.set(state.keyedById, id, item)
@@ -90,9 +90,10 @@ export default function makeServiceMutations() {
9090
!(item instanceof Model)
9191
) {
9292
item = new Model(item)
93+
} else {
94+
const original = state.keyedById[id]
95+
updateOriginal(original, item)
9396
}
94-
const original = state.keyedById[id]
95-
updateOriginal(original, item)
9697
}
9798

9899
// if addOnUpsert then add the record into the state, else discard it.
@@ -137,32 +138,31 @@ export default function makeServiceMutations() {
137138
updateItems(state, items)
138139
},
139140

140-
// Adds an _id to a temp record so that that the addOrUpdate action
141-
// can migrate the temp to the keyedById state.
141+
// Promotes temp to "real" item:
142+
// - adds _id to temp
143+
// - removes __isTemp flag
144+
// - migrates temp from tempsById to keyedById
142145
updateTemp(state, { id, tempId }) {
143146
const temp = state.tempsById[tempId]
144-
if (state.tempsById) {
147+
if (temp) {
145148
temp[state.idField] = id
146-
state.tempsByNewId[id] = temp
149+
Vue.delete(temp, '__isTemp')
150+
Vue.delete(state.tempsById, tempId)
151+
// If an item already exists in the store from the `created` event firing
152+
// it will be replaced here
153+
Vue.set(state.keyedById, id, temp)
147154
}
148-
},
149155

150-
/**
151-
* Overwrites the item with matching id with the temp record.
152-
* This is to preserve reactivity for temp records.
153-
*/
154-
replaceItemWithTemp(state, { item, temp }) {
155-
const id = item[state.idField]
156-
if (state.keyedById[id]) {
157-
state.keyedById[id] = temp
158-
Vue.delete(state.keyedById[id], '__isTemp')
156+
// Add _id to temp's clone as well if it exists
157+
const Model = _get(models, `[${state.serverAlias}][${state.modelName}]`)
158+
const tempClone = Model && Model.copiesById && Model.copiesById[tempId]
159+
if (tempClone) {
160+
tempClone[state.idField] = id
161+
Model.copiesById[id] = tempClone
162+
Vue.delete(tempClone, '__isTemp')
159163
}
160164
},
161165

162-
remove__isTemp(state, temp) {
163-
Vue.delete(temp, '__isTemp')
164-
},
165-
166166
removeItem(state, item) {
167167
const { idField } = state
168168
const idToBeRemoved = _isObject(item) ? getId(item, idField) : item
@@ -175,24 +175,18 @@ export default function makeServiceMutations() {
175175
}
176176
},
177177

178-
// Removes temp records. Also cleans up tempsByNewId
178+
// Removes temp records
179179
removeTemps(state, tempIds) {
180-
const ids = tempIds.reduce((ids, id) => {
180+
tempIds.forEach(id => {
181181
const temp = state.tempsById[id]
182182
if (temp) {
183183
if (temp[state.idField]) {
184184
// Removes __isTemp if created
185185
delete temp.__isTemp
186186
Vue.delete(temp, '__isTemp')
187-
ids.push(temp[state.idField])
188-
} else {
189-
// Removes uncreated temp
190-
ids.push(temp[state.tempIdField])
191187
}
192188
}
193-
return ids
194-
}, [])
195-
state.tempsByNewId = _omit(state.tempsByNewId, ids)
189+
})
196190
state.tempsById = _omit(state.tempsById, tempIds)
197191
},
198192

src/service-module/service-module.state.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export interface ServiceStateExclusiveDefaults {
2727

2828
keyedById: {}
2929
tempsById: {}
30-
tempsByNewId: {}
3130
copiesById: {}
3231
namespace?: string
3332
pagination?: {
@@ -57,7 +56,6 @@ export interface ServiceState {
5756
idField: string
5857
keyedById: {}
5958
tempsById: {}
60-
tempsByNewId: {}
6159
copiesById: {}
6260
whitelist: string[]
6361
paramsForServer: string[]
@@ -98,7 +96,6 @@ export default function makeDefaultState(options: MakeServicePluginOptions) {
9896
keyedById: {},
9997
copiesById: {},
10098
tempsById: {}, // Really should be called tempsByTempId
101-
tempsByNewId: {}, // temporary storage for temps while getting transferred from tempsById to keyedById
10299
pagination: {
103100
defaultLimit: null,
104101
defaultSkip: null

test/service-module/make-service-plugin.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ describe('makeServicePlugin', function() {
8787
servicePath: 'todos',
8888
skipRequestIfExists: false,
8989
tempsById: {},
90-
tempsByNewId: {},
9190
whitelist: []
9291
}
9392

0 commit comments

Comments
 (0)