Skip to content

Commit 257c41e

Browse files
committed
Cancel Queue and cancel Action should revert origin on a patch
1 parent 4acea85 commit 257c41e

File tree

4 files changed

+54
-41
lines changed

4 files changed

+54
-41
lines changed

lib/ActionQueue.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import some from "lodash-es/some";
22
import has from "lodash-es/has";
33

44
export default class ActionQueue {
5+
[key: string]: any;
56
readonly post: Array<object>;
67
readonly patch: object;
78
readonly delete: object;

lib/ApiState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { IndexedObjectTree, IndexedObject } from "./types";
55

66
export default class ApiState {
77
[key: string]: any;
8-
items?: IndexedObjectTree;
8+
items: IndexedObjectTree;
99
lastLoad: Date;
1010
loaded: boolean;
1111
originItems: IndexedObject;

lib/ApiStore.ts

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import {
2020
} from "./types";
2121
import { applyModifier } from "./utils";
2222

23-
// type RootState<S> = S & { [index: string]: ApiState };
23+
interface StateTree {
24+
[index: string]: ApiState;
25+
}
2426

2527
export default class ApiStore<S> implements StoreOptions<S> {
2628
namespaced: boolean;
@@ -45,31 +47,28 @@ export default class ApiStore<S> implements StoreOptions<S> {
4547

4648
// adding ADD_* mutations
4749
this.mutations[`ADD_${model.name.toUpperCase()}`] = async (
48-
myState: ApiState,
50+
myState: StateTree,
4951
item: IndexedObject | Array<IndexedObject>
5052
) => {
53+
const state = myState[modelIdx];
5154
const res = await this.patchEntity(myState, model, item);
52-
this.storeOriginItem(
53-
get(myState, `${modelIdx}.originItems`),
54-
res,
55-
model.beforeQueue
56-
);
55+
this.storeOriginItem(state.originItems, res, model.beforeQueue);
5756
myState[modelIdx].lastLoad = new Date();
5857
};
5958

6059
// adding DELETE_* mutations
6160
this.mutations[`DELETE_${model.name.toUpperCase()}`] = (
62-
myState: ApiState,
61+
myState: StateTree,
6362
item: string | Array<IndexedObject>
6463
) => {
65-
const store = myState[modelIdx];
64+
const state = myState[modelIdx];
6665
const deleteItem = (i: string | IndexedObject) => {
6766
if (isString(i)) {
68-
Vue.delete(store.originItems, i);
69-
Vue.delete(store.items, i);
67+
Vue.delete(state.originItems, i);
68+
Vue.delete(state.items, i);
7069
} else {
71-
this.removeOriginItem(store.originItems, i);
72-
Vue.delete(store.items, i.id);
70+
this.removeOriginItem(state.originItems, i);
71+
Vue.delete(state.items, i.id);
7372
}
7473
};
7574

@@ -82,38 +81,38 @@ export default class ApiStore<S> implements StoreOptions<S> {
8281

8382
// adding CLEAR_* mutations
8483
this.mutations[`CLEAR_${model.name.toUpperCase()}`] = (
85-
myState: ApiState
84+
myState: StateTree
8685
) => myState[modelIdx].reset();
8786

8887
this.mutations[`QUEUE_ACTION_${model.name.toUpperCase()}`] = (
89-
myState: ApiState,
88+
myState: StateTree,
9089
payload: QueuePayload
9190
) => {
92-
const store = myState[modelIdx];
91+
const state = myState[modelIdx];
9392
const storeAction = async (qp: QueuePayload) => {
9493
const QToStore = omit(qp, "method", "action");
9594
if (qp.action === "post") {
9695
Vue.set(
97-
store.items,
96+
state.items,
9897
qp.data.id,
9998
await applyModifier("afterGet", modelKey, this.models, qp.data)
10099
);
101-
store.actionQueue[qp.action].push(
100+
state.actionQueue[qp.action].push(
102101
await applyModifier("beforeSave", modelKey, this.models, QToStore)
103102
);
104103
} else {
105104
if (qp.action === "delete") {
106-
Vue.delete(store.items, qp.id);
105+
Vue.delete(state.items, qp.id);
107106
}
108107
Vue.set(
109-
store.actionQueue[qp.action],
108+
state.actionQueue[qp.action],
110109
qp.data.id,
111110
await applyModifier("beforeSave", modelKey, this.models, QToStore)
112111
);
113112
}
114113
};
115114

116-
if (has(store.actionQueue, payload.action)) {
115+
if (has(state.actionQueue, payload.action)) {
117116
storeAction(payload);
118117
} else {
119118
// eslint-disable-next-line no-console
@@ -122,20 +121,27 @@ export default class ApiStore<S> implements StoreOptions<S> {
122121
};
123122

124123
this.mutations[`UNQUEUE_ACTION_${model.name.toUpperCase()}`] = (
125-
myState: ApiState,
124+
myState: StateTree,
126125
payload: QueuePayload
127126
) => {
127+
const state = myState[model.plural];
128128
const id = payload.id || payload.data.id;
129-
Vue.delete(myState[model.plural].actionQueue[payload.action], id);
129+
if (payload.action === "patch") {
130+
this.revertOriginItem(state, id);
131+
}
132+
Vue.delete(state.actionQueue[payload.action], id);
130133
};
131134

132135
this.mutations[`RESET_QUEUE_${model.name.toUpperCase()}`] = (
133-
myState: ApiState
136+
myState: StateTree
134137
) => {
135-
forEach(myState[model.plural].actionQueue, (actionList, action) => {
136-
myState[model.plural].actionQueue[action] = isArray(actionList)
137-
? []
138-
: {};
138+
const state = myState[model.plural];
139+
forEach(state.actionQueue, (actionList, action) => {
140+
if (action === "patch") {
141+
forEach(actionList, (item, id) => this.revertOriginItem(state, id));
142+
}
143+
144+
state.actionQueue[action] = isArray(actionList) ? [] : {};
139145
});
140146
};
141147

@@ -166,9 +172,15 @@ export default class ApiStore<S> implements StoreOptions<S> {
166172
Vue.delete(originItems, item.id);
167173
}
168174
}
175+
// Revert to original copy
176+
private revertOriginItem(state: ApiState, id: string) {
177+
if (has(state.originItems, id)) {
178+
state.items[id] = state.originItems[id];
179+
}
180+
}
169181

170182
private async patchEntity(
171-
state: ApiState,
183+
store: StateTree,
172184
model: ModelType,
173185
entity: IndexedObject | Array<IndexedObject>
174186
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -177,15 +189,15 @@ export default class ApiStore<S> implements StoreOptions<S> {
177189
return;
178190
}
179191
if (isArray(entity)) {
180-
return Promise.all(entity.map(e => this.patchEntity(state, model, e)));
192+
return Promise.all(entity.map(e => this.patchEntity(store, model, e)));
181193
}
182194

183195
if (entity.id && model) {
184196
// Patch references
185197
if (model.references) {
186198
forEach(model.references, async (modelName, prop) => {
187199
entity[prop] = await this.patchReference(
188-
state,
200+
store,
189201
entity,
190202
modelName,
191203
prop
@@ -200,10 +212,10 @@ export default class ApiStore<S> implements StoreOptions<S> {
200212
entity
201213
);
202214

203-
const store = state[model.plural];
215+
const state = store[model.plural];
204216

205-
if (has(store.items, entity.id)) {
206-
const storeEntity = store.items[entity.id];
217+
if (has(state.items, entity.id)) {
218+
const storeEntity = state.items[entity.id];
207219
forEach(entityAfter, (value, name: string) => {
208220
if (!isFunction(value) && !has(model.references, name)) {
209221
if (has(entity, name) && !isEqual(value, get(storeEntity, name))) {
@@ -212,24 +224,24 @@ export default class ApiStore<S> implements StoreOptions<S> {
212224
}
213225
});
214226

215-
return store.items[entity.id];
227+
return state.items[entity.id];
216228
} else {
217-
store.items = { ...store.items, [entity.id]: entityAfter };
218-
this.storeOriginItem(store.originItems, entityAfter, model.beforeQueue);
229+
state.items = { ...state.items, [entity.id]: entityAfter };
230+
this.storeOriginItem(state.originItems, entityAfter, model.beforeQueue);
219231

220232
return entityAfter;
221233
}
222234
}
223235
}
224236

225237
private async patchReference(
226-
state: ApiState,
238+
store: StateTree,
227239
entity: IndexedObject,
228240
modelName: string,
229241
prop: string
230242
) {
231243
if (has(this.models, modelName)) {
232-
return this.patchEntity(state, this.models[modelName], entity[prop]);
244+
return this.patchEntity(store, this.models[modelName], entity[prop]);
233245
} else {
234246
// eslint-disable-next-line no-console
235247
console.warn(

tests/unit/apistore.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ describe("ApiStore by default", function() {
338338
store.getters["api/resources"].actionQueue.patch[resource.id]
339339
).toBeUndefined();
340340
// Object should comeback to initial state
341-
expect(store.getters["api/resources"].items[resource.id]).toEqual(resource);
341+
expect(store.getters["api/resources"].items[resource.id]).toEqual(data[0]);
342342
});
343343

344344
it("test cancelAction", async () => {

0 commit comments

Comments
 (0)