@kaspernj/api-maker 1.0.401 → 1.0.403

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.
@@ -1,399 +0,0 @@
1
- import BaseComponent from "../base-component"
2
- import Card from "./card"
3
- import classNames from "classnames"
4
- import Collection from "../collection"
5
- import CollectionLoader from "../collection-loader"
6
- import debounce from "debounce"
7
- import {digg, digs} from "diggerize"
8
- import instanceOfClassName from "../instance-of-class-name"
9
- import ModelRow from "./live-table/model-row"
10
- import Paginate from "./paginate"
11
- import Params from "../params"
12
- import PropTypes from "prop-types"
13
- import {memo} from "react"
14
- import {shapeComponent} from "set-state-compare/src/shape-component.js"
15
- import SortLink from "./sort-link"
16
-
17
- export default memo(shapeComponent(class ApiMakerBootstrapLiveTable extends BaseComponent {
18
- static defaultProps = {
19
- card: true,
20
- destroyEnabled: true,
21
- filterCard: true,
22
- filterSubmitButton: true,
23
- noRecordsAvailableContent: undefined,
24
- noRecordsFoundContent: undefined,
25
- preloads: [],
26
- select: {}
27
- }
28
-
29
- static propTypes = {
30
- abilities: PropTypes.object,
31
- actionsContent: PropTypes.func,
32
- appHistory: PropTypes.object,
33
- card: PropTypes.bool.isRequired,
34
- className: PropTypes.string,
35
- collection: PropTypes.oneOfType([
36
- instanceOfClassName("ApiMakerCollection"),
37
- PropTypes.instanceOf(Collection)
38
- ]),
39
- columns: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
40
- columnsContent: PropTypes.func,
41
- controls: PropTypes.func,
42
- defaultParams: PropTypes.object,
43
- destroyEnabled: PropTypes.bool.isRequired,
44
- destroyMessage: PropTypes.string,
45
- editModelPath: PropTypes.func,
46
- filterCard: PropTypes.bool.isRequired,
47
- filterContent: PropTypes.func,
48
- filterSubmitButton: PropTypes.bool.isRequired,
49
- filterSubmitLabel: PropTypes.node,
50
- headersContent: PropTypes.func,
51
- header: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
52
- groupBy: PropTypes.array,
53
- modelClass: PropTypes.func.isRequired,
54
- noRecordsAvailableContent: PropTypes.func,
55
- noRecordsFoundContent: PropTypes.func,
56
- onModelsLoaded: PropTypes.func,
57
- paginateContent: PropTypes.func,
58
- paginationComponent: PropTypes.func,
59
- preloads: PropTypes.array.isRequired,
60
- queryName: PropTypes.string,
61
- select: PropTypes.object,
62
- selectColumns: PropTypes.object,
63
- viewModelPath: PropTypes.func
64
- }
65
-
66
- setup() {
67
- let queryName = this.props.queryName
68
-
69
- if (!queryName) {
70
- queryName = digg(this.props.modelClass.modelClassData(), "collectionKey")
71
- }
72
-
73
- this.useStates({
74
- columns: () => this.columnsAsArray(),
75
- models: undefined,
76
- overallCount: undefined,
77
- query: undefined,
78
- queryName,
79
- queryQName: `${queryName}_q`,
80
- queryPageName: `${queryName}_page`,
81
- qParams: undefined,
82
- result: undefined,
83
- showNoRecordsAvailableContent: false,
84
- showNoRecordsFoundContent: false
85
- })
86
- }
87
-
88
- columnsAsArray () {
89
- if (typeof this.props.columns == "function") {
90
- return this.props.columns()
91
- }
92
-
93
- return this.props.columns
94
- }
95
-
96
- render () {
97
- const {modelClass, noRecordsAvailableContent, noRecordsFoundContent} = digs(this.props, "modelClass", "noRecordsAvailableContent", "noRecordsFoundContent")
98
- const {collection, defaultParams, onModelsLoaded, preloads, select, selectColumns} = this.props
99
- const {
100
- overallCount,
101
- qParams,
102
- query,
103
- result,
104
- models,
105
- showNoRecordsAvailableContent,
106
- showNoRecordsFoundContent
107
- } = digs(
108
- this.state,
109
- "overallCount",
110
- "qParams",
111
- "query",
112
- "result",
113
- "models",
114
- "showNoRecordsAvailableContent",
115
- "showNoRecordsFoundContent"
116
- )
117
-
118
- return (
119
- <div className={this.className()}>
120
- <CollectionLoader
121
- abilities={this.abilitiesToLoad()}
122
- defaultParams={defaultParams}
123
- collection={collection}
124
- component={this}
125
- modelClass={modelClass}
126
- noRecordsAvailableContent={noRecordsAvailableContent}
127
- noRecordsFoundContent={noRecordsFoundContent}
128
- onModelsLoaded={onModelsLoaded}
129
- pagination
130
- preloads={preloads}
131
- select={select}
132
- selectColumns={selectColumns}
133
- />
134
- {showNoRecordsAvailableContent &&
135
- <div className="live-table--no-records-available-content">
136
- {noRecordsAvailableContent({models, qParams, overallCount})}
137
- </div>
138
- }
139
- {showNoRecordsFoundContent &&
140
- <div className="live-table--no-records-found-content">
141
- {noRecordsFoundContent({models, qParams, overallCount})}
142
- </div>
143
- }
144
- {qParams && query && result && models && !showNoRecordsAvailableContent && !showNoRecordsFoundContent &&
145
- this.cardOrTable()
146
- }
147
- </div>
148
- )
149
- }
150
-
151
- abilitiesToLoad () {
152
- const abilitiesToLoad = {}
153
- const {abilities, modelClass} = this.props
154
- const ownAbilities = []
155
-
156
- if (this.props.destroyEnabled) {
157
- ownAbilities.push("destroy")
158
- }
159
-
160
- if (this.props.editModelPath) {
161
- ownAbilities.push("edit")
162
- }
163
-
164
- if (this.props.viewModelPath) {
165
- ownAbilities.push("show")
166
- }
167
-
168
- if (ownAbilities.length > 0) {
169
- const modelClassName = digg(modelClass.modelClassData(), "name")
170
-
171
- abilitiesToLoad[modelClassName] = ownAbilities
172
- }
173
-
174
- if (abilities) {
175
- for (const modelName in abilities) {
176
- if (!(modelName in abilitiesToLoad)) {
177
- abilitiesToLoad[modelName] = []
178
- }
179
-
180
- for (const ability of abilities[modelName]) {
181
- abilitiesToLoad[modelName].push(ability)
182
- }
183
- }
184
- }
185
-
186
- return abilitiesToLoad
187
- }
188
-
189
- cardOrTable () {
190
- const {
191
- abilities,
192
- actionsContent,
193
- appHistory,
194
- card,
195
- className,
196
- collection,
197
- columns,
198
- columnsContent,
199
- controls,
200
- defaultParams,
201
- destroyEnabled,
202
- destroyMessage,
203
- editModelPath,
204
- filterCard,
205
- filterContent,
206
- filterSubmitButton,
207
- filterSubmitLabel,
208
- headersContent,
209
- header,
210
- groupBy,
211
- modelClass,
212
- noRecordsAvailableContent,
213
- noRecordsFoundContent,
214
- onModelsLoaded,
215
- paginateContent,
216
- paginationComponent,
217
- preloads,
218
- queryName,
219
- select,
220
- selectColumns,
221
- viewModelPath,
222
- ...restProps
223
- } = this.props
224
- const {models, qParams, query, result} = digs(this.state, "models", "qParams", "query", "result")
225
-
226
- let controlsContent, headerContent, PaginationComponent
227
-
228
- if (controls) {
229
- controlsContent = controls({models, qParams, query, result})
230
- }
231
-
232
- if (typeof header == "function") {
233
- headerContent = header({models, qParams, query, result})
234
- } else if (header) {
235
- headerContent = header
236
- }
237
-
238
- if (!paginateContent) {
239
- if (paginationComponent) {
240
- PaginationComponent = paginationComponent
241
- } else {
242
- PaginationComponent = Paginate
243
- }
244
- }
245
-
246
- return (
247
- <>
248
- {filterContent && filterCard &&
249
- <Card className="live-table--filter-card mb-4">
250
- {this.filterForm()}
251
- </Card>
252
- }
253
- {filterContent && !filterCard &&
254
- this.filterForm()
255
- }
256
- {card &&
257
- <Card className={classNames("mb-4", className)} controls={controlsContent} header={headerContent} table {...restProps}>
258
- {this.tableContent()}
259
- </Card>
260
- }
261
- {!card &&
262
- <table className={className} {...restProps}>
263
- {this.tableContent()}
264
- </table>
265
- }
266
- {result && PaginationComponent &&
267
- <PaginationComponent result={result} />
268
- }
269
- {result && paginateContent &&
270
- paginateContent({result})
271
- }
272
- </>
273
- )
274
- }
275
-
276
- filterForm = () => {
277
- const {submitFilterDebounce} = digs(this, "submitFilterDebounce")
278
- const {filterContent, filterSubmitButton} = digs(this.props, "filterContent", "filterSubmitButton")
279
- const {filterSubmitLabel} = this.props
280
- const {qParams} = digs(this.state, "qParams")
281
-
282
- return (
283
- <form className="live-table--filter-form" onSubmit={this.onFilterFormSubmit} ref="filterForm">
284
- {filterContent({
285
- onFilterChanged: this.submitFilter,
286
- onFilterChangedWithDelay: submitFilterDebounce,
287
- qParams
288
- })}
289
- {filterSubmitButton &&
290
- <input
291
- className="btn btn-primary live-table--submit-filter-button"
292
- type="submit"
293
- value={filterSubmitLabel || I18n.t("js.api_maker_bootstrap.live_table.filter")}
294
- />
295
- }
296
- </form>
297
- )
298
- }
299
-
300
- tableContent () {
301
- const {query, models} = this.state
302
-
303
- return (
304
- <>
305
- <thead>
306
- <tr>
307
- {this.state.columns && this.headersContentFromColumns()}
308
- {this.props.headersContent && this.props.headersContent({query})}
309
- <th />
310
- </tr>
311
- </thead>
312
- <tbody>
313
- {models.map((model) =>
314
- <ModelRow key={model.id()} liveTable={this} model={model} />
315
- )}
316
- </tbody>
317
- </>
318
- )
319
- }
320
-
321
- className () {
322
- const classNames = ["component-api-maker-live-table"]
323
-
324
- if (this.props.className)
325
- classNames.push(this.props.className)
326
-
327
- return classNames.join(" ")
328
- }
329
-
330
- headersContentFromColumns () {
331
- const {columns} = digs(this.state, "columns")
332
-
333
- return columns.map((column) =>
334
- <th
335
- className={classNames(...this.headerClassNameForColumn(column))}
336
- data-identifier={this.identifierForColumn(column)}
337
- key={this.identifierForColumn(column)}
338
- >
339
- {column.sortKey && this.state.query &&
340
- <SortLink attribute={column.sortKey} query={this.state.query} title={this.headerLabelForColumn(column)} />
341
- }
342
- {(!column.sortKey || !this.state.query) &&
343
- this.headerLabelForColumn(column)
344
- }
345
- </th>
346
- )
347
- }
348
-
349
- headerClassNameForColumn (column) {
350
- const classNames = ["live-table-header"]
351
-
352
- if (column.commonProps && column.commonProps.className) classNames.push(column.commonProps.className)
353
- if (column.headerProps && column.headerProps.className) classNames.push(column.headerProps.className)
354
- if (column.textCenter) classNames.push("text-center")
355
- if (column.textRight) classNames.push("text-end text-right")
356
-
357
- return classNames
358
- }
359
-
360
- headerLabelForColumn (column) {
361
- if ("label" in column) {
362
- if (typeof column.label == "function") {
363
- return column.label()
364
- } else {
365
- return column.label
366
- }
367
- }
368
-
369
- if (column.attribute) return this.props.modelClass.humanAttributeName(column.attribute)
370
-
371
- throw new Error("No 'label' or 'attribute' was given")
372
- }
373
-
374
- identifierForColumn (column) {
375
- if (column.identifier) return column.identifier
376
- if (column.attribute) return `attribute-${column.attribute}`
377
- if (column.sortKey) return `sort-key-${column.sortKey}`
378
-
379
- throw new Error("No 'attribute', 'identifier' or 'sortKey' was given")
380
- }
381
-
382
- onFilterFormSubmit = (e) => {
383
- e.preventDefault()
384
- this.submitFilter()
385
- }
386
-
387
- submitFilter = () => {
388
- const {appHistory} = this.props
389
- const qParams = Params.serializeForm(this.refs.filterForm)
390
- const {queryQName} = this.state
391
-
392
- const changeParamsParams = {}
393
- changeParamsParams[queryQName] = JSON.stringify(qParams)
394
-
395
- Params.changeParams(changeParamsParams, {appHistory})
396
- }
397
-
398
- submitFilterDebounce = debounce(digg(this, "submitFilter"))
399
- }))