jason-rails 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +34 -0
- data/README.md +6 -9
- data/app/assets/config/jason_engine_manifest.js +1 -0
- data/app/assets/images/jason/engine/.keep +0 -0
- data/app/assets/stylesheets/jason/engine/application.css +15 -0
- data/app/controllers/jason/api_controller.rb +36 -0
- data/app/helpers/jason/engine/application_helper.rb +6 -0
- data/app/jobs/jason/engine/application_job.rb +6 -0
- data/app/mailers/jason/engine/application_mailer.rb +8 -0
- data/app/models/jason/engine/application_record.rb +7 -0
- data/app/views/layouts/jason/engine/application.html.erb +15 -0
- data/client/babel.config.js +13 -0
- data/client/lib/JasonProvider.d.ts +5 -4
- data/client/lib/JasonProvider.js +30 -3
- data/client/lib/actionFactory.js +1 -1
- data/client/lib/createActions.d.ts +1 -1
- data/client/lib/createActions.js +2 -27
- data/client/lib/createJasonReducers.js +1 -0
- data/client/lib/createOptDis.d.ts +1 -0
- data/client/lib/createOptDis.js +45 -0
- data/client/lib/createPayloadHandler.d.ts +1 -1
- data/client/lib/createPayloadHandler.js +23 -6
- data/client/lib/deepCamelizeKeys.d.ts +1 -0
- data/client/lib/deepCamelizeKeys.js +23 -0
- data/client/lib/deepCamelizeKeys.test.d.ts +1 -0
- data/client/lib/deepCamelizeKeys.test.js +106 -0
- data/client/lib/index.d.ts +4 -4
- data/client/package.json +17 -4
- data/client/src/JasonProvider.tsx +33 -5
- data/client/src/actionFactory.ts +1 -1
- data/client/src/createActions.ts +2 -33
- data/client/src/createJasonReducers.ts +1 -0
- data/client/src/createOptDis.ts +47 -0
- data/client/src/createPayloadHandler.ts +26 -4
- data/client/src/deepCamelizeKeys.test.ts +113 -0
- data/client/src/deepCamelizeKeys.ts +17 -0
- data/client/yarn.lock +4539 -81
- data/config/routes.rb +4 -0
- data/jason-rails.gemspec +5 -0
- data/lib/jason.rb +7 -1
- data/lib/jason/api_model.rb +16 -0
- data/lib/jason/channel.rb +2 -2
- data/lib/jason/engine.rb +5 -0
- data/lib/jason/publisher.rb +38 -6
- data/lib/jason/subscription.rb +21 -24
- data/lib/jason/version.rb +1 -1
- metadata +81 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4231946f3742dee57b9eb0eff4a7367691a1ddff2a2842fbba8ffde0c4f5d460
|
4
|
+
data.tar.gz: c701f79deb2e23b464b4f15f96442084fb4837d429e87715007b6cc41e31ba9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1222df088d647e53b24a735cd9c85b1cf926831171cb21ebd628b67f12fb320003fca93272d94e8173b13d30c21c6ca3cbd55899d604bb2d572196efeb56e8b3
|
7
|
+
data.tar.gz: 34ba69d74e1a6729bd88695ff56d62ea40abf3a804065c9803380bd16c948b9cfea51d33eae986cdc3e240db8f051cda2678a63bebfa87e2c144484f2f0f027b
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jason-rails (0.3.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.4.4)
|
10
|
+
rake (12.3.3)
|
11
|
+
rspec (3.10.0)
|
12
|
+
rspec-core (~> 3.10.0)
|
13
|
+
rspec-expectations (~> 3.10.0)
|
14
|
+
rspec-mocks (~> 3.10.0)
|
15
|
+
rspec-core (3.10.0)
|
16
|
+
rspec-support (~> 3.10.0)
|
17
|
+
rspec-expectations (3.10.0)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.10.0)
|
20
|
+
rspec-mocks (3.10.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.10.0)
|
23
|
+
rspec-support (3.10.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
jason-rails!
|
30
|
+
rake (~> 12.0)
|
31
|
+
rspec (~> 3.0)
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
1.17.3
|
data/README.md
CHANGED
@@ -14,23 +14,20 @@ Jason attempts to minimize this repitition by auto-generating API endpoints, red
|
|
14
14
|
|
15
15
|
## Installation
|
16
16
|
|
17
|
-
Add
|
17
|
+
Add the gem and the NPM package
|
18
18
|
|
19
19
|
```ruby
|
20
20
|
gem 'jason-rails'
|
21
21
|
```
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Or install it yourself as:
|
28
|
-
|
29
|
-
$ gem install jason
|
23
|
+
```bash
|
24
|
+
yarn add @jamesr2323/jason
|
25
|
+
```
|
30
26
|
|
31
27
|
## Usage
|
32
28
|
|
33
|
-
|
29
|
+
### Define your schema
|
30
|
+
|
34
31
|
|
35
32
|
## Development
|
36
33
|
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/jason/engine .css
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Jason::ApiController < ::ApplicationController
|
2
|
+
def schema
|
3
|
+
render json: JASON_API_MODEL.to_json
|
4
|
+
end
|
5
|
+
|
6
|
+
def action
|
7
|
+
type = params[:type]
|
8
|
+
entity = type.split('/')[0].underscore
|
9
|
+
api_model = Jason::ApiModel.new(entity.singularize)
|
10
|
+
model = entity.singularize.camelize.constantize
|
11
|
+
action = type.split('/')[1].underscore
|
12
|
+
|
13
|
+
if action == 'move_priority'
|
14
|
+
id, priority = params[:payload].values_at(:id, :priority)
|
15
|
+
|
16
|
+
instance = model.find(id)
|
17
|
+
priority_filter = instance.as_json.with_indifferent_access.slice(*api_model.priority_scope)
|
18
|
+
|
19
|
+
all_instance_ids = model.send(api_model.scope || :all).where(priority_filter).where.not(id: instance.id).order(:priority).pluck(:id)
|
20
|
+
all_instance_ids.insert(priority.to_i, instance.id)
|
21
|
+
|
22
|
+
all_instance_ids.each_with_index do |id, i|
|
23
|
+
model.find(id).update!(priority: i, skip_publish_json: true)
|
24
|
+
end
|
25
|
+
|
26
|
+
model.publish_all(model.find(all_instance_ids))
|
27
|
+
elsif action == 'upsert' || action == 'add'
|
28
|
+
payload = api_model.permit(params)
|
29
|
+
return render json: model.find_or_create_by_id!(payload).as_json(api_model.as_json_config)
|
30
|
+
elsif action == 'remove'
|
31
|
+
model.find(params[:payload]).destroy!
|
32
|
+
end
|
33
|
+
|
34
|
+
return head :ok
|
35
|
+
end
|
36
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
|
2
|
-
reducers
|
3
|
-
middleware
|
4
|
-
extraActions
|
5
|
-
children
|
3
|
+
reducers?: any;
|
4
|
+
middleware?: any;
|
5
|
+
extraActions?: any;
|
6
|
+
children?: any;
|
6
7
|
}) => any;
|
7
8
|
export default JasonProvider;
|
data/client/lib/JasonProvider.js
CHANGED
@@ -31,22 +31,48 @@ const react_redux_1 = require("react-redux");
|
|
31
31
|
const toolkit_1 = require("@reduxjs/toolkit");
|
32
32
|
const createJasonReducers_1 = __importDefault(require("./createJasonReducers"));
|
33
33
|
const createPayloadHandler_1 = __importDefault(require("./createPayloadHandler"));
|
34
|
+
const createOptDis_1 = __importDefault(require("./createOptDis"));
|
34
35
|
const makeEager_1 = __importDefault(require("./makeEager"));
|
35
36
|
const humps_1 = require("humps");
|
36
37
|
const blueimp_md5_1 = __importDefault(require("blueimp-md5"));
|
37
38
|
const lodash_1 = __importDefault(require("lodash"));
|
38
39
|
const react_1 = __importStar(require("react"));
|
40
|
+
const uuid_1 = require("uuid");
|
39
41
|
const JasonProvider = ({ reducers, middleware, extraActions, children }) => {
|
40
42
|
const [store, setStore] = react_1.useState(null);
|
41
43
|
const [value, setValue] = react_1.useState(null);
|
42
44
|
const [connected, setConnected] = react_1.useState(false);
|
43
45
|
const csrfToken = document.querySelector("meta[name=csrf-token]").content;
|
44
46
|
axios_1.default.defaults.headers.common['X-CSRF-Token'] = csrfToken;
|
45
|
-
const restClient = axios_case_converter_1.default(axios_1.default.create()
|
47
|
+
const restClient = axios_case_converter_1.default(axios_1.default.create(), {
|
48
|
+
preservedKeys: (key) => {
|
49
|
+
return uuid_1.validate(key);
|
50
|
+
}
|
51
|
+
});
|
46
52
|
react_1.useEffect(() => {
|
47
53
|
restClient.get('/jason/api/schema')
|
48
54
|
.then(({ data: snakey_schema }) => {
|
49
55
|
const schema = humps_1.camelizeKeys(snakey_schema);
|
56
|
+
const serverActionQueue = function () {
|
57
|
+
const queue = [];
|
58
|
+
let inFlight = false;
|
59
|
+
return {
|
60
|
+
addItem: (item) => queue.push(item),
|
61
|
+
getItem: () => {
|
62
|
+
if (inFlight)
|
63
|
+
return false;
|
64
|
+
const item = queue.shift();
|
65
|
+
if (item) {
|
66
|
+
inFlight = true;
|
67
|
+
return item;
|
68
|
+
}
|
69
|
+
return false;
|
70
|
+
},
|
71
|
+
itemProcessed: () => inFlight = false,
|
72
|
+
fullySynced: () => queue.length === 0 && !inFlight,
|
73
|
+
getData: () => ({ queue, inFlight })
|
74
|
+
};
|
75
|
+
}();
|
50
76
|
const consumer = actioncable_1.createConsumer();
|
51
77
|
const allReducers = Object.assign(Object.assign({}, reducers), createJasonReducers_1.default(schema));
|
52
78
|
console.log({ schema, allReducers });
|
@@ -78,7 +104,7 @@ const JasonProvider = ({ reducers, middleware, extraActions, children }) => {
|
|
78
104
|
const md5Hash = blueimp_md5_1.default(JSON.stringify(config));
|
79
105
|
console.log('Subscribe with', config, md5Hash);
|
80
106
|
lodash_1.default.map(config, (v, model) => {
|
81
|
-
payloadHandlers[`${model}:${md5Hash}`] = createPayloadHandler_1.default(store.dispatch, subscription, model, schema[model]);
|
107
|
+
payloadHandlers[`${model}:${md5Hash}`] = createPayloadHandler_1.default(store.dispatch, serverActionQueue, subscription, model, schema[model]);
|
82
108
|
});
|
83
109
|
subscription.send({ createSubscription: config });
|
84
110
|
return () => removeSubscription(config);
|
@@ -90,7 +116,8 @@ const JasonProvider = ({ reducers, middleware, extraActions, children }) => {
|
|
90
116
|
delete payloadHandlers[`${model}:${md5Hash}`];
|
91
117
|
});
|
92
118
|
}
|
93
|
-
const
|
119
|
+
const optDis = createOptDis_1.default(schema, store.dispatch, restClient, serverActionQueue);
|
120
|
+
const actions = createActions_1.default(schema, store, restClient, optDis, extraActions);
|
94
121
|
const eager = makeEager_1.default(schema);
|
95
122
|
console.log({ actions });
|
96
123
|
setValue({
|
data/client/lib/actionFactory.js
CHANGED
@@ -23,7 +23,7 @@ exports.default = (dis, store, entity, { extraActions = {}, hasPriority = false
|
|
23
23
|
function remove(id) {
|
24
24
|
return dis({ type: `${pluralize_1.default(entity)}/remove`, payload: id });
|
25
25
|
}
|
26
|
-
const extraActionsResolved = lodash_1.default.mapValues(extraActions, v => v(dis, store, entity));
|
26
|
+
const extraActionsResolved = extraActions ? lodash_1.default.mapValues(extraActions, v => v(dis, store, entity)) : {};
|
27
27
|
if (hasPriority) {
|
28
28
|
return Object.assign({ add, upsert, setAll, remove, movePriority }, extraActionsResolved);
|
29
29
|
}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
declare function createActions(schema: any, store: any, restClient: any, extraActions: any): any;
|
1
|
+
declare function createActions(schema: any, store: any, restClient: any, optDis: any, extraActions: any): any;
|
2
2
|
export default createActions;
|
data/client/lib/createActions.js
CHANGED
@@ -6,32 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const actionFactory_1 = __importDefault(require("./actionFactory"));
|
7
7
|
const pluralize_1 = __importDefault(require("pluralize"));
|
8
8
|
const lodash_1 = __importDefault(require("lodash"));
|
9
|
-
|
10
|
-
function enrich(type, payload) {
|
11
|
-
if (type.split('/')[1] === 'upsert' && !(type.split('/')[0] === 'session')) {
|
12
|
-
if (!payload.id) {
|
13
|
-
return Object.assign(Object.assign({}, payload), { id: uuid_1.v4() });
|
14
|
-
}
|
15
|
-
}
|
16
|
-
return payload;
|
17
|
-
}
|
18
|
-
function makeOptDis(schema, dispatch, restClient) {
|
19
|
-
const plurals = lodash_1.default.keys(schema).map(k => pluralize_1.default(k));
|
20
|
-
return function (action) {
|
21
|
-
const { type, payload } = action;
|
22
|
-
const data = enrich(type, payload);
|
23
|
-
dispatch(action);
|
24
|
-
if (plurals.indexOf(type.split('/')[0]) > -1) {
|
25
|
-
return restClient.post('/jason/api/action', { type, payload: data })
|
26
|
-
.catch(e => {
|
27
|
-
dispatch({ type: 'upsertLocalUi', data: { error: JSON.stringify(e) } });
|
28
|
-
});
|
29
|
-
}
|
30
|
-
};
|
31
|
-
}
|
32
|
-
function createActions(schema, store, restClient, extraActions) {
|
33
|
-
const dis = store.dispatch;
|
34
|
-
const optDis = makeOptDis(schema, dis, restClient);
|
9
|
+
function createActions(schema, store, restClient, optDis, extraActions) {
|
35
10
|
const actions = lodash_1.default.fromPairs(lodash_1.default.map(schema, (config, model) => {
|
36
11
|
if (config.priorityScope) {
|
37
12
|
return [pluralize_1.default(model), actionFactory_1.default(optDis, store, model, { hasPriority: true })];
|
@@ -40,7 +15,7 @@ function createActions(schema, store, restClient, extraActions) {
|
|
40
15
|
return [pluralize_1.default(model), actionFactory_1.default(optDis, store, model)];
|
41
16
|
}
|
42
17
|
}));
|
43
|
-
const extraActionsResolved = extraActions(optDis, store, restClient);
|
18
|
+
const extraActionsResolved = extraActions ? extraActions(optDis, store, restClient, actions) : {};
|
44
19
|
return lodash_1.default.merge(actions, extraActionsResolved);
|
45
20
|
}
|
46
21
|
exports.default = createActions;
|
@@ -19,6 +19,7 @@ function generateSlices(schema) {
|
|
19
19
|
add: adapter.addOne,
|
20
20
|
setAll: adapter.setAll,
|
21
21
|
remove: adapter.removeOne,
|
22
|
+
removeMany: adapter.removeMany,
|
22
23
|
movePriority: (s, { payload: { id, priority, parentFilter } }) => {
|
23
24
|
// Get IDs and insert our item at the new index
|
24
25
|
var affectedIds = lodash_1.default.orderBy(lodash_1.default.filter(lodash_1.default.values(s.entities), parentFilter).filter(e => e.id !== id), 'priority').map(e => e.id);
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function createOptDis(schema: any, dispatch: any, restClient: any, serverActionQueue: any): (action: any) => void;
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const lodash_1 = __importDefault(require("lodash"));
|
7
|
+
const pluralize_1 = __importDefault(require("pluralize"));
|
8
|
+
const uuid_1 = require("uuid");
|
9
|
+
function enrich(type, payload) {
|
10
|
+
if (type.split('/')[1] === 'upsert' && !(type.split('/')[0] === 'session')) {
|
11
|
+
if (!payload.id) {
|
12
|
+
return Object.assign(Object.assign({}, payload), { id: uuid_1.v4() });
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return payload;
|
16
|
+
}
|
17
|
+
function createOptDis(schema, dispatch, restClient, serverActionQueue) {
|
18
|
+
const plurals = lodash_1.default.keys(schema).map(k => pluralize_1.default(k));
|
19
|
+
let inFlight = false;
|
20
|
+
function enqueueServerAction(action) {
|
21
|
+
serverActionQueue.addItem(action);
|
22
|
+
}
|
23
|
+
function dispatchServerAction() {
|
24
|
+
const action = serverActionQueue.getItem();
|
25
|
+
if (!action)
|
26
|
+
return;
|
27
|
+
inFlight = true;
|
28
|
+
restClient.post('/jason/api/action', action)
|
29
|
+
.then(serverActionQueue.itemProcessed)
|
30
|
+
.catch(e => {
|
31
|
+
dispatch({ type: 'upsertLocalUi', data: { error: JSON.stringify(e) } });
|
32
|
+
serverActionQueue.itemProcessed();
|
33
|
+
});
|
34
|
+
}
|
35
|
+
setInterval(dispatchServerAction, 10);
|
36
|
+
return function (action) {
|
37
|
+
const { type, payload } = action;
|
38
|
+
const data = enrich(type, payload);
|
39
|
+
dispatch({ type, payload: data });
|
40
|
+
if (plurals.indexOf(type.split('/')[0]) > -1) {
|
41
|
+
enqueueServerAction({ type, payload: data });
|
42
|
+
}
|
43
|
+
};
|
44
|
+
}
|
45
|
+
exports.default = createOptDis;
|
@@ -1 +1 @@
|
|
1
|
-
export default function createPayloadHandler(dispatch: any, subscription: any, model: any, config: any): (data: any) => null | undefined;
|
1
|
+
export default function createPayloadHandler(dispatch: any, serverActionQueue: any, subscription: any, model: any, config: any): (data: any) => null | undefined;
|
@@ -4,16 +4,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const jsonpatch_1 = require("jsonpatch");
|
7
|
-
const
|
7
|
+
const deepCamelizeKeys_1 = __importDefault(require("./deepCamelizeKeys"));
|
8
8
|
const pluralize_1 = __importDefault(require("pluralize"));
|
9
9
|
const lodash_1 = __importDefault(require("lodash"));
|
10
|
+
const uuid_1 = require("uuid");
|
10
11
|
function diffSeconds(dt2, dt1) {
|
11
12
|
var diff = (dt2.getTime() - dt1.getTime()) / 1000;
|
12
13
|
return Math.abs(Math.round(diff));
|
13
14
|
}
|
14
|
-
function createPayloadHandler(dispatch, subscription, model, config) {
|
15
|
+
function createPayloadHandler(dispatch, serverActionQueue, subscription, model, config) {
|
15
16
|
console.log({ model, config });
|
16
|
-
let payload =
|
17
|
+
let payload = [];
|
18
|
+
let previousPayload = [];
|
17
19
|
let idx = 0;
|
18
20
|
let patchQueue = {};
|
19
21
|
let lastCheckAt = new Date();
|
@@ -23,16 +25,31 @@ function createPayloadHandler(dispatch, subscription, model, config) {
|
|
23
25
|
console.log({ getPayload: model, subscription });
|
24
26
|
subscription.send({ getPayload: { model, config } });
|
25
27
|
}
|
28
|
+
function camelizeKeys(item) {
|
29
|
+
return deepCamelizeKeys_1.default(item, key => uuid_1.validate(key));
|
30
|
+
}
|
26
31
|
const tGetPayload = lodash_1.default.throttle(getPayload, 10000);
|
27
32
|
function dispatchPayload() {
|
33
|
+
// We want to avoid updates from server overwriting changes to local state, so if there is a queue then wait.
|
34
|
+
if (!serverActionQueue.fullySynced()) {
|
35
|
+
console.log(serverActionQueue.getData());
|
36
|
+
setTimeout(dispatchPayload, 100);
|
37
|
+
return;
|
38
|
+
}
|
28
39
|
const includeModels = (config.includeModels || []).map(m => lodash_1.default.camelCase(m));
|
29
40
|
console.log("Dispatching", { payload, includeModels });
|
30
41
|
includeModels.forEach(m => {
|
31
|
-
const subPayload = lodash_1.default.flatten(lodash_1.default.compact(
|
32
|
-
|
42
|
+
const subPayload = lodash_1.default.flatten(lodash_1.default.compact(camelizeKeys(payload).map(instance => instance[m])));
|
43
|
+
const previousSubPayload = lodash_1.default.flatten(lodash_1.default.compact(camelizeKeys(previousPayload).map(instance => instance[m])));
|
44
|
+
// Find IDs that were in the payload but are no longer
|
45
|
+
const idsToRemove = lodash_1.default.difference(previousSubPayload.map(i => i.id), subPayload.map(i => i.id));
|
33
46
|
dispatch({ type: `${pluralize_1.default(m)}/upsertMany`, payload: subPayload });
|
47
|
+
dispatch({ type: `${pluralize_1.default(m)}/removeMany`, payload: idsToRemove });
|
34
48
|
});
|
35
|
-
|
49
|
+
const idsToRemove = lodash_1.default.difference(previousPayload.map(i => i.id), payload.map(i => i.id));
|
50
|
+
dispatch({ type: `${pluralize_1.default(model)}/upsertMany`, payload: camelizeKeys(payload) });
|
51
|
+
dispatch({ type: `${pluralize_1.default(model)}/removeMany`, payload: idsToRemove });
|
52
|
+
previousPayload = payload;
|
36
53
|
}
|
37
54
|
function processQueue() {
|
38
55
|
console.log({ idx, patchQueue });
|