@kaspernj/api-maker 1.0.312 → 1.0.313
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.
- package/package.json +2 -2
- package/src/collection-loader.jsx +37 -303
- package/src/use-collection.mjs +277 -0
- package/src/with-collection.jsx +12 -255
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
]
|
|
17
17
|
},
|
|
18
18
|
"name": "@kaspernj/api-maker",
|
|
19
|
-
"version": "1.0.
|
|
19
|
+
"version": "1.0.313",
|
|
20
20
|
"type": "module",
|
|
21
21
|
"description": "",
|
|
22
22
|
"main": "index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"on-location-changed": ">= 1.0.8",
|
|
53
53
|
"qs": ">= 6.9.3",
|
|
54
54
|
"replaceall": ">= 0.1.6",
|
|
55
|
-
"set-state-compare": ">= 1.0.
|
|
55
|
+
"set-state-compare": ">= 1.0.26",
|
|
56
56
|
"spark-md5": "^3.0.2",
|
|
57
57
|
"strftime": ">= 0.10.0",
|
|
58
58
|
"uniqunize": "^1.0.1",
|
|
@@ -1,305 +1,39 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
paginateContent: PropTypes.func,
|
|
38
|
-
preloads: PropTypes.array.isRequired,
|
|
39
|
-
queryMethod: PropTypes.func,
|
|
40
|
-
queryName: PropTypes.string,
|
|
41
|
-
queryParams: PropTypes.object,
|
|
42
|
-
select: PropTypes.object,
|
|
43
|
-
selectColumns: PropTypes.object
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
shape = digg(this, "props", "component", "shape")
|
|
47
|
-
|
|
48
|
-
constructor (props) {
|
|
49
|
-
super(props)
|
|
50
|
-
|
|
51
|
-
let queryName = props.queryName
|
|
52
|
-
|
|
53
|
-
if (!queryName) queryName = digg(props.modelClass.modelClassData(), "collectionKey")
|
|
54
|
-
|
|
55
|
-
this.shape.set({
|
|
56
|
-
models: undefined,
|
|
57
|
-
overallCount: undefined,
|
|
58
|
-
query: undefined,
|
|
59
|
-
queryName,
|
|
60
|
-
queryPerKey: `${queryName}_per`,
|
|
61
|
-
queryQName: `${queryName}_q`,
|
|
62
|
-
querySName: `${queryName}_s`,
|
|
63
|
-
queryPageName: `${queryName}_page`,
|
|
64
|
-
qParams: undefined,
|
|
65
|
-
result: undefined,
|
|
66
|
-
searchParams: undefined,
|
|
67
|
-
showNoRecordsAvailableContent: false,
|
|
68
|
-
showNoRecordsFoundContent: false
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
componentDidMount () {
|
|
73
|
-
this.loadQParams()
|
|
74
|
-
this.loadModels()
|
|
75
|
-
|
|
76
|
-
const {noRecordsAvailableContent} = digs(this.props, "noRecordsAvailableContent")
|
|
77
|
-
|
|
78
|
-
if (noRecordsAvailableContent) this.loadOverallCount()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
componentDidUpdate(prevProps) {
|
|
82
|
-
const {queryPageName, queryPerKey, queryQName, querySName} = digs(this.shape, "queryPageName", "queryPerKey", "queryQName", "querySName")
|
|
83
|
-
let changed = false
|
|
84
|
-
|
|
85
|
-
// Only load models again if certain things in the URL changes
|
|
86
|
-
if (prevProps.queryParams[queryQName] != this.props.queryParams[queryQName]) {
|
|
87
|
-
changed = true
|
|
88
|
-
} else if (prevProps.queryParams[queryPageName] != this.props.queryParams[queryPageName]) {
|
|
89
|
-
changed = true
|
|
90
|
-
} else if (prevProps.queryParams[queryPerKey] != this.props.queryParams[queryPerKey]) {
|
|
91
|
-
changed = true
|
|
92
|
-
} else if (prevProps.queryParams[querySName] != this.props.queryParams[querySName]) {
|
|
93
|
-
changed = true
|
|
94
|
-
} else if (prevProps.collection != this.props.collection) {
|
|
95
|
-
changed = true
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (changed) {
|
|
99
|
-
this.loadQParams()
|
|
100
|
-
this.loadModels()
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async loadOverallCount () {
|
|
105
|
-
const baseQuery = this.props.collection || this.props.modelClass.all()
|
|
106
|
-
const overallCount = await baseQuery.count()
|
|
107
|
-
|
|
108
|
-
this.shape.set({
|
|
109
|
-
overallCount,
|
|
110
|
-
showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({overallCount}),
|
|
111
|
-
showNoRecordsFoundContent: this.showNoRecordsFoundContent({overallCount})
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
hasQParams() {
|
|
116
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
117
|
-
const {queryQName} = digs(this.shape, "queryQName")
|
|
118
|
-
|
|
119
|
-
if (queryQName in queryParams) return true
|
|
120
|
-
|
|
121
|
-
return false
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
qParams() {
|
|
125
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
126
|
-
const {queryQName} = digs(this.shape, "queryQName")
|
|
127
|
-
|
|
128
|
-
if (this.hasQParams()) return JSON.parse(digg(queryParams, queryQName))
|
|
129
|
-
|
|
130
|
-
return {}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
loadQParams () {
|
|
134
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
135
|
-
const {querySName} = digs(this.shape, "querySName")
|
|
136
|
-
const qParams = this.hasQParams() ? this.qParams() : Object.assign({}, this.props.defaultParams)
|
|
137
|
-
const searchParams = []
|
|
138
|
-
|
|
139
|
-
if (queryParams[querySName]) {
|
|
140
|
-
for (const rawSearchParam of queryParams[querySName]) {
|
|
141
|
-
const parsedSearchParam = JSON.parse(rawSearchParam)
|
|
142
|
-
|
|
143
|
-
searchParams.push(parsedSearchParam)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
this.shape.set({qParams, searchParams})
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
loadModels = async () => {
|
|
151
|
-
const {pagination, queryParams} = digs(this.props, "pagination", "queryParams")
|
|
152
|
-
const {abilities, collection, groupBy, modelClass, onModelsLoaded, preloads, queryMethod, select, selectColumns} = this.props
|
|
153
|
-
const {
|
|
154
|
-
qParams,
|
|
155
|
-
queryPageName,
|
|
156
|
-
queryPerKey,
|
|
157
|
-
queryQName,
|
|
158
|
-
searchParams
|
|
159
|
-
} = digs(
|
|
160
|
-
this.shape,
|
|
161
|
-
"qParams",
|
|
162
|
-
"queryPageName",
|
|
163
|
-
"queryPerKey",
|
|
164
|
-
"queryQName",
|
|
165
|
-
"searchParams"
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
let query = collection?.clone() || modelClass.ransack()
|
|
169
|
-
|
|
170
|
-
if (pagination) {
|
|
171
|
-
const page = queryParams[queryPageName] || 1
|
|
172
|
-
let per = queryParams[queryPerKey] || 30
|
|
173
|
-
|
|
174
|
-
if (per == "all") {
|
|
175
|
-
per = 999_999_999
|
|
176
|
-
} else {
|
|
177
|
-
per = Number(per)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
query.page(page).per(per)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (groupBy) query = query.groupBy(...groupBy)
|
|
184
|
-
|
|
185
|
-
query = query
|
|
186
|
-
.ransack(qParams)
|
|
187
|
-
.search(searchParams)
|
|
188
|
-
.searchKey(queryQName)
|
|
189
|
-
.pageKey(queryPageName)
|
|
190
|
-
.perKey(queryPerKey)
|
|
191
|
-
.preload(preloads)
|
|
192
|
-
.select(select)
|
|
193
|
-
|
|
194
|
-
if (abilities) query = query.abilities(abilities)
|
|
195
|
-
if (selectColumns) query = query.selectColumns(selectColumns)
|
|
196
|
-
|
|
197
|
-
let result
|
|
198
|
-
|
|
199
|
-
if (queryMethod) {
|
|
200
|
-
result = await queryMethod({query})
|
|
201
|
-
} else {
|
|
202
|
-
result = await query.result()
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const models = result.models()
|
|
206
|
-
|
|
207
|
-
if (onModelsLoaded) {
|
|
208
|
-
onModelsLoaded({
|
|
209
|
-
models,
|
|
210
|
-
qParams,
|
|
211
|
-
query,
|
|
212
|
-
result
|
|
213
|
-
})
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
this.shape.set({
|
|
217
|
-
query,
|
|
218
|
-
result,
|
|
219
|
-
models: result.models(),
|
|
220
|
-
showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({models}),
|
|
221
|
-
showNoRecordsFoundContent: this.showNoRecordsFoundContent({models})
|
|
222
|
-
})
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
loadModelsDebounce = debounce(digg(this, "loadModels"))
|
|
226
|
-
onModelCreated = digg(this, "loadModels")
|
|
227
|
-
|
|
228
|
-
onModelDestroyed = (args) => {
|
|
229
|
-
const {models} = digs(this.shape, "models")
|
|
230
|
-
|
|
231
|
-
this.shape.set({
|
|
232
|
-
models: models.filter((model) => model.id() != args.model.id())
|
|
233
|
-
})
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
onModelUpdated = (args) => {
|
|
237
|
-
const {models} = digs(this.shape, "models")
|
|
238
|
-
const updatedModel = digg(args, "model")
|
|
239
|
-
const foundModel = models.find((model) => model.id() == updatedModel.id())
|
|
240
|
-
|
|
241
|
-
if (foundModel) this.loadModelsDebounce()
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
showNoRecordsAvailableContent (args) {
|
|
245
|
-
const {noRecordsAvailableContent} = digs(this.props, "noRecordsAvailableContent")
|
|
246
|
-
let models, overallCount
|
|
247
|
-
|
|
248
|
-
if (args.models !== undefined) {
|
|
249
|
-
models = args.models
|
|
250
|
-
} else if (this.shape.models !== undefined) {
|
|
251
|
-
models = this.shape.models
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (args.overallCount !== undefined) {
|
|
255
|
-
overallCount = args.overallCount
|
|
256
|
-
} else if (this.shape.overallCount !== undefined) {
|
|
257
|
-
overallCount = this.shape.overallCount
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (models === undefined || overallCount === undefined || noRecordsAvailableContent === undefined) return false
|
|
261
|
-
if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return true
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
showNoRecordsFoundContent (args) {
|
|
265
|
-
const {noRecordsAvailableContent, noRecordsFoundContent} = digs(this.props, "noRecordsAvailableContent", "noRecordsFoundContent")
|
|
266
|
-
let models, overallCount
|
|
267
|
-
|
|
268
|
-
if (args.models !== undefined) {
|
|
269
|
-
models = args.models
|
|
270
|
-
} else if (this.shape.models !== undefined) {
|
|
271
|
-
models = this.shape.models
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (args.overallCount !== undefined) {
|
|
275
|
-
overallCount = args.overallCount
|
|
276
|
-
} else if (this.shape.overallCount !== undefined) {
|
|
277
|
-
overallCount = this.shape.overallCount
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (models === undefined || noRecordsFoundContent === undefined) return false
|
|
281
|
-
|
|
282
|
-
// Dont show noRecordsAvailableContent together with noRecordsAvailableContent
|
|
283
|
-
if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return false
|
|
284
|
-
if (models.length === 0 && noRecordsFoundContent) return true
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
render() {
|
|
288
|
-
const {modelClass} = digs(this.props, "modelClass")
|
|
289
|
-
const {models} = digs(this.shape, "models")
|
|
290
|
-
|
|
291
|
-
return (
|
|
292
|
-
<>
|
|
293
|
-
<EventCreated modelClass={modelClass} onCreated={digg(this, "onModelCreated")} />
|
|
294
|
-
{models && models.map((model) =>
|
|
295
|
-
<React.Fragment key={model.id()}>
|
|
296
|
-
<EventDestroyed model={model} onDestroyed={digg(this, "onModelDestroyed")} />
|
|
297
|
-
<EventUpdated model={model} onUpdated={digg(this, "onModelUpdated")} />
|
|
298
|
-
</React.Fragment>
|
|
299
|
-
)}
|
|
300
|
-
</>
|
|
301
|
-
)
|
|
302
|
-
}
|
|
1
|
+
import {digg} from "diggerize"
|
|
2
|
+
import {memo, useEffect} from "react"
|
|
3
|
+
import useCollection from "./use-collection"
|
|
4
|
+
import useShape from "set-state-compare/src/use-shape.js"
|
|
5
|
+
|
|
6
|
+
const CollectionLoader = (props) => {
|
|
7
|
+
const s = useShape(props)
|
|
8
|
+
const useCollectionResult = useCollection(props)
|
|
9
|
+
const cachePartsKeys = [
|
|
10
|
+
"modelIdsCacheString",
|
|
11
|
+
"overallCount",
|
|
12
|
+
"qParams",
|
|
13
|
+
"queryName",
|
|
14
|
+
"queryPerKey",
|
|
15
|
+
"queryQName",
|
|
16
|
+
"querySName",
|
|
17
|
+
"queryPageName",
|
|
18
|
+
"searchParams",
|
|
19
|
+
"showNoRecordsAvailableContent",
|
|
20
|
+
"showNoRecordsFoundContent"
|
|
21
|
+
]
|
|
22
|
+
const cacheParts = []
|
|
23
|
+
|
|
24
|
+
for(const cachePartsKey of cachePartsKeys) {
|
|
25
|
+
cacheParts.push(digg(useCollectionResult, cachePartsKey))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
s.updateMeta({useCollectionResult})
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const componentShape = digg(s.p.component, "shape")
|
|
32
|
+
|
|
33
|
+
componentShape.set(s.m.useCollectionResult)
|
|
34
|
+
}, cacheParts)
|
|
35
|
+
|
|
36
|
+
return null
|
|
303
37
|
}
|
|
304
38
|
|
|
305
|
-
export default
|
|
39
|
+
export default memo(CollectionLoader)
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import Collection from "./collection.mjs"
|
|
2
|
+
import debounce from "debounce"
|
|
3
|
+
import {digg} from "diggerize"
|
|
4
|
+
import ModelEvents from "./model-events.mjs"
|
|
5
|
+
import PropTypes from "prop-types"
|
|
6
|
+
import PropTypesExact from "prop-types-exact"
|
|
7
|
+
import {useCallback, useEffect} from "react"
|
|
8
|
+
import useShape from "set-state-compare/src/use-shape.js"
|
|
9
|
+
import useQueryParams from "on-location-changed/src/use-query-params.js"
|
|
10
|
+
|
|
11
|
+
const useCollection = ({
|
|
12
|
+
abilities,
|
|
13
|
+
collection,
|
|
14
|
+
defaultParams,
|
|
15
|
+
groupBy = ["id"],
|
|
16
|
+
modelClass,
|
|
17
|
+
noRecordsAvailableContent = undefined,
|
|
18
|
+
noRecordsFoundContent = undefined,
|
|
19
|
+
onModelsLoaded,
|
|
20
|
+
pagination = false,
|
|
21
|
+
preloads = [],
|
|
22
|
+
queryMethod,
|
|
23
|
+
queryName,
|
|
24
|
+
select = {},
|
|
25
|
+
selectColumns
|
|
26
|
+
}) => {
|
|
27
|
+
const s = useShape({
|
|
28
|
+
abilities,
|
|
29
|
+
collection,
|
|
30
|
+
defaultParams,
|
|
31
|
+
groupBy,
|
|
32
|
+
modelClass,
|
|
33
|
+
noRecordsAvailableContent,
|
|
34
|
+
noRecordsFoundContent,
|
|
35
|
+
onModelsLoaded,
|
|
36
|
+
pagination,
|
|
37
|
+
preloads,
|
|
38
|
+
queryMethod,
|
|
39
|
+
select,
|
|
40
|
+
selectColumns
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (!queryName) queryName = digg(modelClass.modelClassData(), "collectionKey")
|
|
44
|
+
|
|
45
|
+
const setModels = s.useState("models")
|
|
46
|
+
const setOverallCount = s.useState("overallCount")
|
|
47
|
+
const setQuery = s.useState("query")
|
|
48
|
+
const setQueryName = s.useState("queryName", queryName)
|
|
49
|
+
const setQueryPerKey = s.useState("queryPerKey", `${s.s.queryName}_per`)
|
|
50
|
+
const setQueryQName = s.useState("queryQName", `${s.s.queryName}_q`)
|
|
51
|
+
const setQuerySName = s.useState("querySName", `${s.s.queryName}_s`)
|
|
52
|
+
const setQueryPageName = s.useState("queryPageName", `${s.s.queryName}_page`)
|
|
53
|
+
const setQParams = s.useState("qParams")
|
|
54
|
+
const setResult = s.useState("result")
|
|
55
|
+
const setSearchParams = s.useState("searchParams")
|
|
56
|
+
const setShowNoRecordsAvailableContent = s.useState("showNoRecordsAvailableContent", false)
|
|
57
|
+
const setShowNoRecordsFoundContent = s.useState("showNoRecordsFoundContent", false)
|
|
58
|
+
const queryParams = useQueryParams()
|
|
59
|
+
const modelIds = s.s.models?.map((model) => model.id())
|
|
60
|
+
|
|
61
|
+
let modelIdsCacheString
|
|
62
|
+
|
|
63
|
+
if (s.s.models === undefined) {
|
|
64
|
+
modelIdsCacheString = "models-undefined"
|
|
65
|
+
} else if (s.s.models.length === 0) {
|
|
66
|
+
modelIdsCacheString = "no-models"
|
|
67
|
+
} else {
|
|
68
|
+
modelIdsCacheString = modelIds?.join("---")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
s.updateMeta({queryParams})
|
|
72
|
+
|
|
73
|
+
const loadOverallCount = useCallback(async () => {
|
|
74
|
+
const baseQuery = s.p.collection || s.p.modelClass.all()
|
|
75
|
+
const overallCount = await baseQuery.count()
|
|
76
|
+
|
|
77
|
+
setOverallCount(overallCount)
|
|
78
|
+
setShowNoRecordsAvailableContent(showNoRecordsAvailableContent({overallCount}))
|
|
79
|
+
setShowNoRecordsFoundContent(showNoRecordsFoundContent({overallCount}))
|
|
80
|
+
}, [])
|
|
81
|
+
|
|
82
|
+
const hasQParams = useCallback(() => {
|
|
83
|
+
if (s.s.queryQName in s.m.queryParams) return true
|
|
84
|
+
|
|
85
|
+
return false
|
|
86
|
+
}, [])
|
|
87
|
+
|
|
88
|
+
const qParams = useCallback(() => {
|
|
89
|
+
if (hasQParams()) return JSON.parse(digg(s.m.queryParams, s.s.queryQName))
|
|
90
|
+
|
|
91
|
+
return {}
|
|
92
|
+
}, [])
|
|
93
|
+
|
|
94
|
+
const loadQParams = useCallback(() => {
|
|
95
|
+
const qParamsToSet = hasQParams() ? qParams() : Object.assign({}, s.p.defaultParams)
|
|
96
|
+
const searchParams = []
|
|
97
|
+
|
|
98
|
+
if (s.m.queryParams[s.s.querySName]) {
|
|
99
|
+
for (const rawSearchParam of s.m.queryParams[s.s.querySName]) {
|
|
100
|
+
const parsedSearchParam = JSON.parse(rawSearchParam)
|
|
101
|
+
|
|
102
|
+
searchParams.push(parsedSearchParam)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setQParams(qParamsToSet)
|
|
107
|
+
setSearchParams(searchParams)
|
|
108
|
+
}, [])
|
|
109
|
+
|
|
110
|
+
const loadModels = useCallback(async () => {
|
|
111
|
+
let query = s.p.collection?.clone() || s.p.modelClass.ransack()
|
|
112
|
+
|
|
113
|
+
if (s.p.pagination) {
|
|
114
|
+
const page = s.m.queryParams[s.s.queryPageName] || 1
|
|
115
|
+
let per = s.m.queryParams[s.s.queryPerKey] || 30
|
|
116
|
+
|
|
117
|
+
if (per == "all") {
|
|
118
|
+
per = 999_999_999
|
|
119
|
+
} else {
|
|
120
|
+
per = Number(per)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
query.page(page).per(per)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (s.p.groupBy) query = query.groupBy(...s.p.groupBy)
|
|
127
|
+
|
|
128
|
+
query = query
|
|
129
|
+
.ransack(s.s.qParams)
|
|
130
|
+
.search(s.s.searchParams)
|
|
131
|
+
.searchKey(s.s.queryQName)
|
|
132
|
+
.pageKey(s.s.queryPageName)
|
|
133
|
+
.perKey(s.s.queryPerKey)
|
|
134
|
+
.preload(s.p.preloads)
|
|
135
|
+
.select(s.p.select)
|
|
136
|
+
|
|
137
|
+
if (s.p.abilities) query = query.abilities(s.p.abilities)
|
|
138
|
+
if (s.p.selectColumns) query = query.selectColumns(s.p.selectColumns)
|
|
139
|
+
|
|
140
|
+
let result
|
|
141
|
+
|
|
142
|
+
if (s.p.queryMethod) {
|
|
143
|
+
result = await s.p.queryMethod({query})
|
|
144
|
+
} else {
|
|
145
|
+
result = await query.result()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const models = result.models()
|
|
149
|
+
|
|
150
|
+
if (s.p.onModelsLoaded) {
|
|
151
|
+
s.p.onModelsLoaded({
|
|
152
|
+
models,
|
|
153
|
+
qParams: s.s.qParams,
|
|
154
|
+
query,
|
|
155
|
+
result
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
setQuery(query)
|
|
160
|
+
setResult(result)
|
|
161
|
+
setModels(result.models())
|
|
162
|
+
setShowNoRecordsAvailableContent(showNoRecordsAvailableContent({models}))
|
|
163
|
+
setShowNoRecordsFoundContent(showNoRecordsFoundContent({models}))
|
|
164
|
+
}, [])
|
|
165
|
+
|
|
166
|
+
const loadModelsDebounce = useCallback(debounce(loadModels), [])
|
|
167
|
+
const onModelDestroyed = useCallback((args) => {
|
|
168
|
+
setModels(s.s.models.filter((model) => model.id() != args.model.id()))
|
|
169
|
+
}, [])
|
|
170
|
+
|
|
171
|
+
const onModelUpdated = useCallback((args) => {
|
|
172
|
+
const updatedModel = digg(args, "model")
|
|
173
|
+
const foundModel = s.s.models.find((model) => model.id() == updatedModel.id())
|
|
174
|
+
|
|
175
|
+
if (foundModel) loadModelsDebounce()
|
|
176
|
+
}, [])
|
|
177
|
+
|
|
178
|
+
const showNoRecordsAvailableContent = useCallback((args) => {
|
|
179
|
+
let models, overallCount
|
|
180
|
+
|
|
181
|
+
if (args.models !== undefined) {
|
|
182
|
+
models = args.models
|
|
183
|
+
} else if (s.s.models !== undefined) {
|
|
184
|
+
models = s.s.models
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (args.overallCount !== undefined) {
|
|
188
|
+
overallCount = args.overallCount
|
|
189
|
+
} else if (s.s.overallCount !== undefined) {
|
|
190
|
+
overallCount = s.s.overallCount
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (models === undefined || overallCount === undefined || s.p.noRecordsAvailableContent === undefined) return false
|
|
194
|
+
if (models.length === 0 && overallCount === 0 && s.p.noRecordsAvailableContent) return true
|
|
195
|
+
}, [])
|
|
196
|
+
|
|
197
|
+
const showNoRecordsFoundContent = useCallback((args) => {
|
|
198
|
+
let models, overallCount
|
|
199
|
+
|
|
200
|
+
if (args.models !== undefined) {
|
|
201
|
+
models = args.models
|
|
202
|
+
} else if (s.s.models !== undefined) {
|
|
203
|
+
models = s.s.models
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (args.overallCount !== undefined) {
|
|
207
|
+
overallCount = args.overallCount
|
|
208
|
+
} else if (s.s.overallCount !== undefined) {
|
|
209
|
+
overallCount = s.s.overallCount
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (models === undefined || s.p.noRecordsFoundContent === undefined) return false
|
|
213
|
+
|
|
214
|
+
// Dont show noRecordsAvailableContent together with noRecordsAvailableContent
|
|
215
|
+
if (models.length === 0 && overallCount === 0 && s.p.noRecordsAvailableContent) return false
|
|
216
|
+
if (models.length === 0 && s.p.noRecordsFoundContent) return true
|
|
217
|
+
}, [])
|
|
218
|
+
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
loadQParams()
|
|
221
|
+
loadModels()
|
|
222
|
+
}, [queryParams[s.s.queryQName], queryParams[s.s.queryPageName], queryParams[s.s.queryPerKey], queryParams[s.s.querySName], collection])
|
|
223
|
+
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
if (s.p.noRecordsAvailableContent) loadOverallCount()
|
|
226
|
+
}, [])
|
|
227
|
+
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
const connectCreated = ModelEvents.connectCreated(s.p.modelClass, loadModels)
|
|
230
|
+
|
|
231
|
+
return () => {
|
|
232
|
+
connectCreated.unsubscribe()
|
|
233
|
+
}
|
|
234
|
+
}, [])
|
|
235
|
+
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
const connections = []
|
|
238
|
+
|
|
239
|
+
if (s.s.models) {
|
|
240
|
+
for(const model of s.s.models) {
|
|
241
|
+
connections.push(ModelEvents.connectUpdated(model, onModelUpdated))
|
|
242
|
+
connections.push(ModelEvents.connectDestroyed(model, onModelDestroyed))
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return () => {
|
|
247
|
+
for(const connection of connections) {
|
|
248
|
+
connection.unsubscribe()
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}, [modelIdsCacheString])
|
|
252
|
+
|
|
253
|
+
const result = Object.assign({}, s.state)
|
|
254
|
+
|
|
255
|
+
result.modelIdsCacheString = modelIdsCacheString
|
|
256
|
+
|
|
257
|
+
return result
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
useCollection.propTypes = PropTypesExact({
|
|
261
|
+
abilities: PropTypes.object,
|
|
262
|
+
collection: PropTypes.instanceOf(Collection),
|
|
263
|
+
defaultParams: PropTypes.object,
|
|
264
|
+
groupBy: PropTypes.array,
|
|
265
|
+
modelClass: PropTypes.func.isRequired,
|
|
266
|
+
noRecordsAvailableContent: PropTypes.func,
|
|
267
|
+
noRecordsFoundContent: PropTypes.func,
|
|
268
|
+
onModelsLoaded: PropTypes.func,
|
|
269
|
+
pagination: PropTypes.bool.isRequired,
|
|
270
|
+
preloads: PropTypes.array.isRequired,
|
|
271
|
+
queryMethod: PropTypes.func,
|
|
272
|
+
queryName: PropTypes.string,
|
|
273
|
+
select: PropTypes.object,
|
|
274
|
+
selectColumns: PropTypes.object
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
export default useCollection
|
package/src/with-collection.jsx
CHANGED
|
@@ -1,259 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import EventDestroyed from "./event-destroyed"
|
|
5
|
-
import EventUpdated from "./event-updated"
|
|
6
|
-
import React from "react"
|
|
7
|
-
import Shape from "set-state-compare/src/shape"
|
|
8
|
-
import withQueryParams from "on-location-changed/src/with-query-params"
|
|
1
|
+
import {digg} from "diggerize"
|
|
2
|
+
import {memo} from "react"
|
|
3
|
+
import useCollection from "./use-collection"
|
|
9
4
|
|
|
10
|
-
export default (WrappedComponent, withCollectionArgs) =>
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
export default (WrappedComponent, withCollectionArgs) => memo(() => {
|
|
6
|
+
const useCollectionResult = useCollection(withCollectionArgs)
|
|
7
|
+
const models = digg(useCollectionResult, "models")
|
|
8
|
+
const modelsArgName = inflection.camelize(digg(withCollectionArgs.modelClass.modelClassData(), "pluralName"), true)
|
|
9
|
+
const forwardArgs = {}
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
forwardArgs[modelsArgName] = models
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
models: undefined,
|
|
20
|
-
overallCount: undefined,
|
|
21
|
-
query: undefined,
|
|
22
|
-
queryName,
|
|
23
|
-
queryPerKey: `${queryName}_per`,
|
|
24
|
-
queryQName: `${queryName}_q`,
|
|
25
|
-
querySName: `${queryName}_s`,
|
|
26
|
-
queryPageName: `${queryName}_page`,
|
|
27
|
-
qParams: undefined,
|
|
28
|
-
result: undefined,
|
|
29
|
-
searchParams: undefined,
|
|
30
|
-
showNoRecordsAvailableContent: false,
|
|
31
|
-
showNoRecordsFoundContent: false
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
componentDidMount () {
|
|
36
|
-
this.loadQParams()
|
|
37
|
-
this.loadModels()
|
|
38
|
-
|
|
39
|
-
const {noRecordsAvailableContent} = digs(withCollectionArgs)
|
|
40
|
-
|
|
41
|
-
if (noRecordsAvailableContent) this.loadOverallCount()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
componentDidUpdate(prevProps) {
|
|
45
|
-
const {queryPageName, queryPerKey, queryQName, querySName} = digs(this.shape, "queryPageName", "queryPerKey", "queryQName", "querySName")
|
|
46
|
-
let changed = false
|
|
47
|
-
|
|
48
|
-
// Only load models again if certain things in the URL changes
|
|
49
|
-
if (prevProps.queryParams[queryQName] != this.props.queryParams[queryQName]) {
|
|
50
|
-
changed = true
|
|
51
|
-
} else if (prevProps.queryParams[queryPageName] != this.props.queryParams[queryPageName]) {
|
|
52
|
-
changed = true
|
|
53
|
-
} else if (prevProps.queryParams[queryPerKey] != this.props.queryParams[queryPerKey]) {
|
|
54
|
-
changed = true
|
|
55
|
-
} else if (prevProps.queryParams[querySName] != this.props.queryParams[querySName]) {
|
|
56
|
-
changed = true
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (changed) {
|
|
60
|
-
this.loadQParams()
|
|
61
|
-
this.loadModels()
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async loadOverallCount () {
|
|
66
|
-
const baseQuery = withCollectionArgs.collection || withCollectionArgs.modelClass.all()
|
|
67
|
-
const overallCount = await baseQuery.count()
|
|
68
|
-
|
|
69
|
-
this.shape.set({
|
|
70
|
-
overallCount,
|
|
71
|
-
showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({overallCount}),
|
|
72
|
-
showNoRecordsFoundContent: this.showNoRecordsFoundContent({overallCount})
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
hasQParams() {
|
|
77
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
78
|
-
const {queryQName} = digs(this.shape, "queryQName")
|
|
79
|
-
|
|
80
|
-
if (queryQName in queryParams) return true
|
|
81
|
-
|
|
82
|
-
return false
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
qParams() {
|
|
86
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
87
|
-
const {queryQName} = digs(this.shape, "queryQName")
|
|
88
|
-
|
|
89
|
-
if (this.hasQParams()) return JSON.parse(digg(queryParams, queryQName))
|
|
90
|
-
|
|
91
|
-
return {}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
loadQParams () {
|
|
95
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
96
|
-
const {querySName} = digs(this.shape, "querySName")
|
|
97
|
-
const qParams = this.hasQParams() ? this.qParams() : Object.assign({}, withCollectionArgs.defaultParams)
|
|
98
|
-
const searchParams = []
|
|
99
|
-
|
|
100
|
-
if (queryParams[querySName]) {
|
|
101
|
-
for (const rawSearchParam of queryParams[querySName]) {
|
|
102
|
-
const parsedSearchParam = JSON.parse(rawSearchParam)
|
|
103
|
-
|
|
104
|
-
searchParams.push(parsedSearchParam)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.shape.set({qParams, searchParams})
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
loadModels = async () => {
|
|
112
|
-
const {queryParams} = digs(this.props, "queryParams")
|
|
113
|
-
const {abilities, collection, groupBy, modelClass, onModelsLoaded, preloads, select, selectColumns} = withCollectionArgs
|
|
114
|
-
const {
|
|
115
|
-
qParams,
|
|
116
|
-
queryPageName,
|
|
117
|
-
queryPerKey,
|
|
118
|
-
queryQName,
|
|
119
|
-
searchParams
|
|
120
|
-
} = digs(
|
|
121
|
-
this.shape,
|
|
122
|
-
"qParams",
|
|
123
|
-
"queryPageName",
|
|
124
|
-
"queryPerKey",
|
|
125
|
-
"queryQName",
|
|
126
|
-
"searchParams"
|
|
127
|
-
)
|
|
128
|
-
const page = queryParams[queryPageName] || 1
|
|
129
|
-
let per = queryParams[queryPerKey] || 30
|
|
130
|
-
|
|
131
|
-
if (per == "all") {
|
|
132
|
-
per = 999_999_999
|
|
133
|
-
} else {
|
|
134
|
-
per = Number(per)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
let query = collection?.clone() || modelClass.ransack()
|
|
138
|
-
|
|
139
|
-
if (groupBy) query = query.groupBy(...groupBy)
|
|
140
|
-
|
|
141
|
-
query = query
|
|
142
|
-
.ransack(qParams)
|
|
143
|
-
.search(searchParams)
|
|
144
|
-
.searchKey(queryQName)
|
|
145
|
-
.page(page)
|
|
146
|
-
.pageKey(queryPageName)
|
|
147
|
-
.per(per)
|
|
148
|
-
.perKey(queryPerKey)
|
|
149
|
-
.preload(preloads)
|
|
150
|
-
.select(select)
|
|
151
|
-
|
|
152
|
-
if (abilities) query = query.abilities(abilities)
|
|
153
|
-
if (selectColumns) query = query.selectColumns(selectColumns)
|
|
154
|
-
|
|
155
|
-
const result = await query.result()
|
|
156
|
-
const models = result.models()
|
|
157
|
-
|
|
158
|
-
if (onModelsLoaded) {
|
|
159
|
-
onModelsLoaded({
|
|
160
|
-
models,
|
|
161
|
-
qParams,
|
|
162
|
-
query,
|
|
163
|
-
result
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
this.shape.set({
|
|
168
|
-
query,
|
|
169
|
-
result,
|
|
170
|
-
models: result.models(),
|
|
171
|
-
showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({models}),
|
|
172
|
-
showNoRecordsFoundContent: this.showNoRecordsFoundContent({models})
|
|
173
|
-
})
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
loadModelsDebounce = debounce(digg(this, "loadModels"))
|
|
177
|
-
onModelCreated = digg(this, "loadModels")
|
|
178
|
-
|
|
179
|
-
onModelDestroyed = ({destroyedModel}) => {
|
|
180
|
-
const {models} = digs(this.shape, "models")
|
|
181
|
-
|
|
182
|
-
this.shape.set({
|
|
183
|
-
models: models.filter((model) => model.id() != destroyedModel.id())
|
|
184
|
-
})
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
onModelUpdated = ({model: updatedModel}) => {
|
|
188
|
-
const {models} = digs(this.shape, "models")
|
|
189
|
-
const foundModel = models.find((model) => model.id() == updatedModel.id())
|
|
190
|
-
|
|
191
|
-
if (foundModel) this.loadModelsDebounce()
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
showNoRecordsAvailableContent (args) {
|
|
195
|
-
const {noRecordsAvailableContent} = withCollectionArgs
|
|
196
|
-
let models, overallCount
|
|
197
|
-
|
|
198
|
-
if (args.models !== undefined) {
|
|
199
|
-
models = args.models
|
|
200
|
-
} else if (this.shape.models !== undefined) {
|
|
201
|
-
models = this.shape.models
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (args.overallCount !== undefined) {
|
|
205
|
-
overallCount = args.overallCount
|
|
206
|
-
} else if (this.shape.overallCount !== undefined) {
|
|
207
|
-
overallCount = this.shape.overallCount
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (models === undefined || overallCount === undefined || noRecordsAvailableContent === undefined) return false
|
|
211
|
-
if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return true
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
showNoRecordsFoundContent (args) {
|
|
215
|
-
const {noRecordsAvailableContent, noRecordsFoundContent} = withCollectionArgs
|
|
216
|
-
let models, overallCount
|
|
217
|
-
|
|
218
|
-
if (args.models !== undefined) {
|
|
219
|
-
models = args.models
|
|
220
|
-
} else if (this.shape.models !== undefined) {
|
|
221
|
-
models = this.shape.models
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (args.overallCount !== undefined) {
|
|
225
|
-
overallCount = args.overallCount
|
|
226
|
-
} else if (this.shape.overallCount !== undefined) {
|
|
227
|
-
overallCount = this.shape.overallCount
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (models === undefined || noRecordsFoundContent === undefined) return false
|
|
231
|
-
|
|
232
|
-
// Dont show noRecordsAvailableContent together with noRecordsAvailableContent
|
|
233
|
-
if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return false
|
|
234
|
-
if (models.length === 0 && noRecordsFoundContent) return true
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
render() {
|
|
238
|
-
const {modelClass} = digs(withCollectionArgs, "modelClass")
|
|
239
|
-
const {onModelCreated, onModelDestroyed, onModelUpdated} = digs(this, "onModelCreated", "onModelDestroyed", "onModelUpdated")
|
|
240
|
-
const {models} = digs(this.shape, "models")
|
|
241
|
-
const modelsArgName = inflection.camelize(digg(withCollectionArgs.modelClass.modelClassData(), "pluralName"), true)
|
|
242
|
-
const forwardArgs = {}
|
|
243
|
-
|
|
244
|
-
forwardArgs[modelsArgName] = models
|
|
245
|
-
|
|
246
|
-
return (
|
|
247
|
-
<>
|
|
248
|
-
<EventCreated modelClass={modelClass} onCreated={onModelCreated} />
|
|
249
|
-
{models && models.map((model) =>
|
|
250
|
-
<React.Fragment key={model.id()}>
|
|
251
|
-
<EventDestroyed model={model} onDestroyed={onModelDestroyed} />
|
|
252
|
-
<EventUpdated model={model} onUpdated={onModelUpdated} />
|
|
253
|
-
</React.Fragment>
|
|
254
|
-
)}
|
|
255
|
-
<WrappedComponent {...forwardArgs} {...this.props} />
|
|
256
|
-
</>
|
|
257
|
-
)
|
|
258
|
-
}
|
|
13
|
+
return (
|
|
14
|
+
<WrappedComponent {...forwardArgs} {...this.props} />
|
|
15
|
+
)
|
|
259
16
|
})
|