Skip to content

Commit 542d12a

Browse files
Merge branch 'master' into pullrequests/fratzinger/debounce-events
2 parents c8e9d84 + 4cc137f commit 542d12a

25 files changed

+788
-94
lines changed

docs/mixins.md

Lines changed: 158 additions & 28 deletions
Large diffs are not rendered by default.

docs/model-classes.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,9 @@ const todo = new Todo({ description: 'Do something!' })
339339

340340
The examples above show instantiating a new Model instance without an `id` field. In this case, the record is not added to the Vuex store. If you instantiate a record **with an `id`** field, it **will** get added to the Vuex store. *Note: This field is customizable using the `idField` option for this service.*
341341

342-
Now that we have Model instances, let's take a look at the functionality they provide. Each instance will include the following methods:
342+
Now that we have Model instances, let's take a look at the functionality they provide.
343+
344+
Each instance will include the following methods:
343345

344346
- `.save()`
345347
- `.create()`
@@ -349,6 +351,15 @@ Now that we have Model instances, let's take a look at the functionality they pr
349351
- `.commit()`
350352
- `.reset()`
351353

354+
and the following readonly attributes:
355+
356+
- `isCreatePending` - `create` is currently pending on this model
357+
- `isUpdatePending` - `update` is currently pending on this model
358+
- `isPatchPending` - `patch` is currently pending on this model
359+
- `isRemovePending` - `remove` is currently pending on this model
360+
- `isSavePending` - Any of `create`, `update` or `patch` is currently pending on this model
361+
- `isPending` - Any method is currently pending on this model
362+
352363
*Remember, if a record already has an attribute with any of these method names, it will be overwritten with the method.*
353364

354365
These methods give access to many of the store `actions` and `mutations`. Using Model instances, you no longer have to use `mapActions` for `create`, `patch`, `update`, or `remove`. You also no longer have to use `mapMutations` for `createCopy`, `commitCopy`, or `resetCopy`.

docs/service-plugin.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ Each service comes loaded with the following default state:
156156
errorOnCreate: undefined,
157157
errorOnUpdate: undefined,
158158
errorOnPatch: undefined,
159-
errorOnRemove: undefined
159+
errorOnRemove: undefined,
160+
161+
isIdCreatePending: [],
162+
isIdUpdatePending: [],
163+
isIdPatchPending: [],
164+
isIdRemovePending: [],
160165
}
161166
```
162167

@@ -193,6 +198,13 @@ The following state attribute will be populated with any request error, serializ
193198
- `errorOnPatch {Error}`
194199
- `errorOnRemo {Error}`
195200

201+
The following state attributes allow you to bind to the pending state of requests *per item ID*
202+
203+
- `isIdCreatePending {Array}` - Contains `id` if there's a pending `create` request for `id`.
204+
- `isIdUpdatePending {Array}` -Contains `id` if there's a pending `update` request for `id`.
205+
- `isIdPatchPending {Array}` - Contains `id` if there's a pending `patch` request for `id`.
206+
- `isIdRemovePending {Array}` - Contains `id` if there's a pending `remove` request for `id`.
207+
196208
## Service Getters
197209

198210
Service modules include the following getters:
@@ -206,6 +218,15 @@ Service modules include the following getters:
206218
- `id {Number|String}` - the id of the data to be retrieved by id from the store.
207219
- `params {Object}` - an object containing a Feathers `query` object.
208220

221+
The following getters ease access to per-instance pending status
222+
223+
- `isCreatePendingById(id) {Function}` - Check if `create` is pending for `id`
224+
- `isUpdatePendingById(id) {Function}` - Check if `update` is pending for `id`
225+
- `isPatchPendingById(id) {Function}` - Check if `patch` is pending for `id`
226+
- `isRemovePendingById(id) {Function}` - Check if `remove` is pending for `id`
227+
- `isSavePendingById(id) {Function}` - Check if `create`, `update`, or `patch` is pending for `id`
228+
- `isPendingById(id) {Function}` - Check if `create`, `update`, `patch` or `remove` is pending for `id`
229+
209230
## Service Mutations
210231

211232
The following mutations are included in each service module.
@@ -262,7 +283,9 @@ Clears all data from `ids`, `keyedById`, and `currentId`
262283
The following mutations are called automatically by the service actions, and will rarely, if ever, need to be used manually.
263284

264285
- `setPending(state, method)` - sets the `is${method}Pending` attribute to true
286+
- `setIdPending(state, { method, id })` - adds `id` to `isId${method}Pending` array
265287
- `unsetPending(state, method)` - sets the `is${method}Pending` attribute to false
288+
- `unsetIdPending(state, { method, id })` - removes `id` from `isId${method}Pending` array
266289

267290
### Mutations for Managing Errors
268291

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "feathers-vuex",
33
"description": "FeathersJS, Vue, and Nuxt for the artisan developer",
4-
"version": "3.12.3",
4+
"version": "3.13.0",
55
"homepage": "https:feathers-vuex.feathersjs-ecosystem.com",
66
"main": "dist/",
77
"module": "dist/",

src/FeathersVuexFind.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,14 @@ export default {
7373
}),
7474
computed: {
7575
items() {
76-
const { query, service, $store, temps } = this
76+
let { query, service, $store, temps } = this
7777
let { params } = this
78+
79+
query = query || {}
7880

7981
params = params || { query, temps }
8082

81-
return query ? $store.getters[`${service}/find`](params).data : []
83+
return $store.getters[`${service}/find`](params).data
8284
},
8385
pagination() {
8486
return this.$store.state[this.service].pagination[this.qid]

src/make-find-mixin.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function makeFindMixin(options) {
1818
const {
1919
service,
2020
params,
21-
fetchQuery,
21+
fetchParams,
2222
queryWhen = () => true,
2323
local = false,
2424
qid = 'default',
@@ -224,9 +224,8 @@ export default function makeFindMixin(options) {
224224
getPaginationForQuery(params = {}) {
225225
const pagination = this[PAGINATION]
226226
const { qid, queryId, pageId } = getQueryInfo(params)
227-
const queryInfo = _get(pagination, `[${qid}][${queryId}]`) || {}
228-
const pageInfo =
229-
_get(pagination, `[${qid}][${queryId}][${pageId}]`) || {}
227+
const queryInfo = _get(pagination, [qid, queryId], {})
228+
const pageInfo = _get(pagination, [qid, queryId, pageId], {})
230229

231230
return { queryInfo, pageInfo }
232231
}
@@ -319,7 +318,7 @@ export default function makeFindMixin(options) {
319318

320319
setupAttribute(SERVICE_NAME, service, 'computed', true)
321320
setupAttribute(PARAMS, params)
322-
setupAttribute(FETCH_PARAMS, fetchQuery)
321+
setupAttribute(FETCH_PARAMS, fetchParams)
323322
setupAttribute(QUERY_WHEN, queryWhen, 'computed')
324323
setupAttribute(LOCAL, local)
325324

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import _get from 'lodash/get'
2121
import { EventEmitter } from 'events'
2222
import { ModelSetupContext } from './types'
2323
import { Store } from 'vuex'
24+
import { GetterName } from './service-module.getters'
2425

2526
const defaultOptions = {
2627
clone: false,
@@ -48,7 +49,7 @@ export default function makeBaseModel(options: FeathersVuexOptions) {
4849
const { serverAlias } = options
4950

5051
// If this serverAlias already has a BaseModel, return it
51-
const ExistingBaseModel = _get(globalModels, `[${serverAlias}].BaseModel`)
52+
const ExistingBaseModel = _get(globalModels, [serverAlias, 'BaseModel'])
5253
if (ExistingBaseModel) {
5354
return ExistingBaseModel as ModelStatic
5455
}
@@ -175,6 +176,37 @@ export default function makeBaseModel(options: FeathersVuexOptions) {
175176
return this
176177
}
177178

179+
/**
180+
* Calls `getter`, passing this model's ID as the parameter
181+
* @param getter name of getter to call
182+
*/
183+
private getGetterWithId(getter: GetterName): unknown {
184+
const { _getters, idField, tempIdField } = this
185+
.constructor as typeof BaseModel
186+
const id =
187+
getId(this, idField) != null ? getId(this, idField) : this[tempIdField]
188+
return _getters.call(this.constructor, getter, id)
189+
}
190+
191+
get isCreatePending(): boolean {
192+
return this.getGetterWithId('isCreatePendingById') as boolean
193+
}
194+
get isUpdatePending(): boolean {
195+
return this.getGetterWithId('isUpdatePendingById') as boolean
196+
}
197+
get isPatchPending(): boolean {
198+
return this.getGetterWithId('isPatchPendingById') as boolean
199+
}
200+
get isRemovePending(): boolean {
201+
return this.getGetterWithId('isRemovePendingById') as boolean
202+
}
203+
get isSavePending(): boolean {
204+
return this.getGetterWithId('isSavePendingById') as boolean
205+
}
206+
get isPending(): boolean {
207+
return this.getGetterWithId('isPendingById') as boolean
208+
}
209+
178210
public static getId(record: Record<string, any>): string {
179211
const { idField } = this.constructor as typeof BaseModel
180212
return getId(record, idField)
@@ -214,7 +246,7 @@ export default function makeBaseModel(options: FeathersVuexOptions) {
214246
* @param method the vuex getter name without the namespace
215247
* @param payload if provided, the getter will be called as a function
216248
*/
217-
public static _getters(name: string, idOrParams?: any, params?: any) {
249+
public static _getters(name: GetterName, idOrParams?: any, params?: any) {
218250
const { namespace, store } = this
219251

220252
if (checkNamespace(namespace, this, options.debug)) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default function prepareMakeServicePlugin(
9696
store.registerModule(options.namespace, module, { preserveState: false })
9797

9898
// (2a^) Monkey patch the BaseModel in globalModels
99-
const BaseModel = _get(globalModels, `[${options.serverAlias}].BaseModel`)
99+
const BaseModel = _get(globalModels, [options.serverAlias, 'BaseModel'])
100100
if (BaseModel && !BaseModel.store) {
101101
Object.assign(BaseModel, {
102102
store

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export default function makeServiceActions(service: Service<any>) {
9999
params = params || {}
100100

101101
commit('setPending', 'create')
102+
commit('setIdPending', { method: 'create', id: tempIds })
102103

103104
return service
104105
.create(data, params)
@@ -121,34 +122,39 @@ export default function makeServiceActions(service: Service<any>) {
121122

122123
// response = state.keyedById[id]
123124
}
124-
commit('unsetPending', 'create')
125125
commit('removeTemps', tempIds)
126126
return response
127127
})
128128
.catch(error => {
129129
commit('setError', { method: 'create', error })
130-
commit('unsetPending', 'create')
131130
return Promise.reject(error)
132131
})
132+
.finally(() => {
133+
commit('unsetPending', 'create')
134+
commit('unsetIdPending', { method: 'create', id: tempIds })
135+
})
133136
},
134137

135138
update({ commit, dispatch, state }, [id, data, params]) {
136139
commit('setPending', 'update')
140+
commit('setIdPending', { method: 'update', id })
137141

138142
params = fastCopy(params)
139143

140144
return service
141145
.update(id, data, params)
142146
.then(async function (item) {
143147
dispatch('addOrUpdate', item)
144-
commit('unsetPending', 'update')
145148
return state.keyedById[id]
146149
})
147150
.catch(error => {
148151
commit('setError', { method: 'update', error })
149-
commit('unsetPending', 'update')
150152
return Promise.reject(error)
151153
})
154+
.finally(() => {
155+
commit('unsetPending', 'update')
156+
commit('unsetIdPending', { method: 'update', id })
157+
})
152158
},
153159

154160
/**
@@ -157,6 +163,7 @@ export default function makeServiceActions(service: Service<any>) {
157163
*/
158164
patch({ commit, dispatch, state }, [id, data, params]) {
159165
commit('setPending', 'patch')
166+
commit('setIdPending', { method: 'patch', id })
160167

161168
params = fastCopy(params)
162169

@@ -171,14 +178,16 @@ export default function makeServiceActions(service: Service<any>) {
171178
.patch(id, data, params)
172179
.then(async function (item) {
173180
dispatch('addOrUpdate', item)
174-
commit('unsetPending', 'patch')
175181
return state.keyedById[id]
176182
})
177183
.catch(error => {
178184
commit('setError', { method: 'patch', error })
179-
commit('unsetPending', 'patch')
180185
return Promise.reject(error)
181186
})
187+
.finally(() => {
188+
commit('unsetPending', 'patch')
189+
commit('unsetIdPending', { method: 'patch', id })
190+
})
182191
},
183192

184193
remove({ commit }, idOrArray) {
@@ -196,19 +205,22 @@ export default function makeServiceActions(service: Service<any>) {
196205
params = fastCopy(params)
197206

198207
commit('setPending', 'remove')
208+
commit('setIdPending', { method: 'remove', id })
199209

200210
return service
201211
.remove(id, params)
202212
.then(item => {
203213
commit('removeItem', id)
204-
commit('unsetPending', 'remove')
205214
return item
206215
})
207216
.catch(error => {
208217
commit('setError', { method: 'remove', error })
209-
commit('unsetPending', 'remove')
210218
return Promise.reject(error)
211219
})
220+
.finally(() => {
221+
commit('unsetPending', 'remove')
222+
commit('unsetIdPending', { method: 'remove', id })
223+
})
212224
}
213225
}
214226

0 commit comments

Comments
 (0)