@kaspernj/api-maker 1.0.236 → 1.0.238
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/.eslintrc.cjs +1 -0
- package/package.json +1 -1
- package/src/bootstrap/sort-link.jsx +13 -5
- package/src/collection-loader.jsx +56 -21
- package/src/serializer.mjs +2 -2
- package/src/table/filters/index.jsx +8 -7
- package/src/table/table-settings.js +36 -12
- package/src/table/table.jsx +6 -3
package/.eslintrc.cjs
CHANGED
|
@@ -100,6 +100,7 @@ module.exports = {
|
|
|
100
100
|
"line-comment-position": "off",
|
|
101
101
|
"lines-around-comment": "error",
|
|
102
102
|
"lines-between-class-members": "off",
|
|
103
|
+
"logical-assignment-operators": "error",
|
|
103
104
|
"max-classes-per-file": "off",
|
|
104
105
|
"max-depth": "error",
|
|
105
106
|
"max-nested-callbacks": "error",
|
package/package.json
CHANGED
|
@@ -26,12 +26,13 @@ class ApiMakerBootstrapSortLink extends PureComponent {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
href () {
|
|
29
|
+
const qParams = this.qParams()
|
|
29
30
|
const {queryParams} = digs(this.props, "queryParams")
|
|
30
31
|
const {searchKey} = digs(this, "searchKey")
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
qParams.s = `${this.attribute()} ${this.sortMode()}` // eslint-disable-line id-length
|
|
33
34
|
|
|
34
|
-
queryParams[searchKey]
|
|
35
|
+
queryParams[searchKey] = JSON.stringify(qParams)
|
|
35
36
|
|
|
36
37
|
const newParams = qs.stringify(queryParams)
|
|
37
38
|
const newPath = `${location.pathname}?${newParams}`
|
|
@@ -40,9 +41,7 @@ class ApiMakerBootstrapSortLink extends PureComponent {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
isSortedByAttribute () {
|
|
43
|
-
const
|
|
44
|
-
const {searchKey} = digs(this, "searchKey")
|
|
45
|
-
const params = queryParams[searchKey] || {}
|
|
44
|
+
const params = this.qParams()
|
|
46
45
|
|
|
47
46
|
if (params.s == this.attribute()) return true
|
|
48
47
|
if (params.s == `${this.attribute()} asc`) return true
|
|
@@ -83,6 +82,15 @@ class ApiMakerBootstrapSortLink extends PureComponent {
|
|
|
83
82
|
return Link
|
|
84
83
|
}
|
|
85
84
|
|
|
85
|
+
qParams() {
|
|
86
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
87
|
+
const {searchKey} = digs(this, "searchKey")
|
|
88
|
+
|
|
89
|
+
if (searchKey in queryParams) return JSON.parse(queryParams[searchKey])
|
|
90
|
+
|
|
91
|
+
return {}
|
|
92
|
+
}
|
|
93
|
+
|
|
86
94
|
sortMode () {
|
|
87
95
|
if (this.isSortedByAttribute()) return "desc"
|
|
88
96
|
|
|
@@ -4,12 +4,11 @@ import {digg, digs} from "diggerize"
|
|
|
4
4
|
import EventCreated from "./event-created"
|
|
5
5
|
import EventDestroyed from "./event-destroyed"
|
|
6
6
|
import EventUpdated from "./event-updated"
|
|
7
|
-
import {LocationChanged} from "on-location-changed/src/location-changed-component"
|
|
8
|
-
import Params from "./params"
|
|
9
7
|
import PropTypes from "prop-types"
|
|
10
8
|
import React from "react"
|
|
9
|
+
import withQueryParams from "on-location-changed/src/with-query-params"
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
class CollectionLoader extends React.PureComponent {
|
|
13
12
|
static defaultProps = {
|
|
14
13
|
destroyEnabled: true,
|
|
15
14
|
groupBy: ["id"],
|
|
@@ -52,6 +51,7 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
52
51
|
overallCount: undefined,
|
|
53
52
|
query: undefined,
|
|
54
53
|
queryName,
|
|
54
|
+
queryPerKey: `${queryName}_per`,
|
|
55
55
|
queryQName: `${queryName}_q`,
|
|
56
56
|
querySName: `${queryName}_s`,
|
|
57
57
|
queryPageName: `${queryName}_page`,
|
|
@@ -72,6 +72,27 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
72
72
|
if (noRecordsAvailableContent) this.loadOverallCount()
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
componentDidUpdate(prevProps) {
|
|
76
|
+
const {queryPageName, queryPerKey, queryQName, querySName} = digs(this.shape, "queryPageName", "queryPerKey", "queryQName", "querySName")
|
|
77
|
+
let changed = false
|
|
78
|
+
|
|
79
|
+
// Only load models again if certain things in the URL changes
|
|
80
|
+
if (prevProps.queryParams[queryQName] != this.props.queryParams[queryQName]) {
|
|
81
|
+
changed = true
|
|
82
|
+
} else if (prevProps.queryParams[queryPageName] != this.props.queryParams[queryPageName]) {
|
|
83
|
+
changed = true
|
|
84
|
+
} else if (prevProps.queryParams[queryPerKey] != this.props.queryParams[queryPerKey]) {
|
|
85
|
+
changed = true
|
|
86
|
+
} else if (prevProps.queryParams[querySName] != this.props.queryParams[querySName]) {
|
|
87
|
+
changed = true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (changed) {
|
|
91
|
+
this.loadQParams()
|
|
92
|
+
this.loadModels()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
75
96
|
async loadOverallCount () {
|
|
76
97
|
const baseQuery = this.props.collection || this.props.modelClass.all()
|
|
77
98
|
const overallCount = await baseQuery.count()
|
|
@@ -83,14 +104,32 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
83
104
|
})
|
|
84
105
|
}
|
|
85
106
|
|
|
107
|
+
hasQParams() {
|
|
108
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
109
|
+
const {queryQName} = digs(this.shape, "queryQName")
|
|
110
|
+
|
|
111
|
+
if (queryQName in queryParams) return true
|
|
112
|
+
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
qParams() {
|
|
117
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
118
|
+
const {queryQName} = digs(this.shape, "queryQName")
|
|
119
|
+
|
|
120
|
+
if (this.hasQParams()) return JSON.parse(digg(queryParams, queryQName))
|
|
121
|
+
|
|
122
|
+
return {}
|
|
123
|
+
}
|
|
124
|
+
|
|
86
125
|
loadQParams () {
|
|
87
|
-
const {
|
|
88
|
-
const
|
|
89
|
-
const qParams = Object.assign({}, this.props.defaultParams
|
|
126
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
127
|
+
const {querySName} = digs(this.shape, "querySName")
|
|
128
|
+
const qParams = this.hasQParams() ? this.qParams() : Object.assign({}, this.props.defaultParams)
|
|
90
129
|
const searchParams = []
|
|
91
130
|
|
|
92
|
-
if (
|
|
93
|
-
for (const rawSearchParam of
|
|
131
|
+
if (queryParams[querySName]) {
|
|
132
|
+
for (const rawSearchParam of queryParams[querySName]) {
|
|
94
133
|
const parsedSearchParam = JSON.parse(rawSearchParam)
|
|
95
134
|
|
|
96
135
|
searchParams.push(parsedSearchParam)
|
|
@@ -101,24 +140,24 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
101
140
|
}
|
|
102
141
|
|
|
103
142
|
loadModels = async () => {
|
|
104
|
-
const
|
|
143
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
105
144
|
const {abilities, collection, groupBy, modelClass, onModelsLoaded, preloads, select, selectColumns} = this.props
|
|
106
145
|
const {
|
|
107
146
|
qParams,
|
|
108
|
-
queryName,
|
|
109
147
|
queryPageName,
|
|
148
|
+
queryPerKey,
|
|
110
149
|
queryQName,
|
|
111
150
|
searchParams
|
|
112
151
|
} = digs(
|
|
113
152
|
this.shape,
|
|
114
153
|
"qParams",
|
|
115
|
-
"queryName",
|
|
116
154
|
"queryPageName",
|
|
155
|
+
"queryPerKey",
|
|
117
156
|
"queryQName",
|
|
118
157
|
"searchParams"
|
|
119
158
|
)
|
|
120
|
-
const
|
|
121
|
-
let per =
|
|
159
|
+
const page = queryParams[queryPageName] || 1
|
|
160
|
+
let per = queryParams[queryPerKey] || 30
|
|
122
161
|
|
|
123
162
|
if (per == "all") {
|
|
124
163
|
per = 999_999_999
|
|
@@ -134,10 +173,10 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
134
173
|
.ransack(qParams)
|
|
135
174
|
.search(searchParams)
|
|
136
175
|
.searchKey(queryQName)
|
|
137
|
-
.page(
|
|
176
|
+
.page(page)
|
|
138
177
|
.pageKey(queryPageName)
|
|
139
178
|
.per(per)
|
|
140
|
-
.perKey(
|
|
179
|
+
.perKey(queryPerKey)
|
|
141
180
|
.preload(preloads)
|
|
142
181
|
.select(select)
|
|
143
182
|
|
|
@@ -184,11 +223,6 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
184
223
|
if (foundModel) this.loadModelsDebounce()
|
|
185
224
|
}
|
|
186
225
|
|
|
187
|
-
onLocationChanged = () => {
|
|
188
|
-
this.loadQParams()
|
|
189
|
-
this.loadModels()
|
|
190
|
-
}
|
|
191
|
-
|
|
192
226
|
showNoRecordsAvailableContent (args) {
|
|
193
227
|
const {noRecordsAvailableContent} = digs(this.props, "noRecordsAvailableContent")
|
|
194
228
|
let models, overallCount
|
|
@@ -239,7 +273,6 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
239
273
|
return (
|
|
240
274
|
<>
|
|
241
275
|
<EventCreated modelClass={modelClass} onCreated={digg(this, "onModelCreated")} />
|
|
242
|
-
<LocationChanged onChanged={digg(this, "onLocationChanged")} />
|
|
243
276
|
{models && models.map((model) =>
|
|
244
277
|
<React.Fragment key={model.id()}>
|
|
245
278
|
<EventDestroyed model={model} onDestroyed={digg(this, "onModelDestroyed")} />
|
|
@@ -250,3 +283,5 @@ export default class CollectionLoader extends React.PureComponent {
|
|
|
250
283
|
)
|
|
251
284
|
}
|
|
252
285
|
}
|
|
286
|
+
|
|
287
|
+
export default withQueryParams(CollectionLoader)
|
package/src/serializer.mjs
CHANGED
|
@@ -16,7 +16,7 @@ export default class Serializer {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
serializeArgument (arg) {
|
|
19
|
-
if (typeof arg == "object" && arg.constructor.apiMakerType == "BaseModel") {
|
|
19
|
+
if (typeof arg == "object" && arg && arg.constructor.apiMakerType == "BaseModel") {
|
|
20
20
|
return {
|
|
21
21
|
api_maker_type: "model",
|
|
22
22
|
model_class_name: digg(arg.modelClassData(), "name"),
|
|
@@ -44,7 +44,7 @@ export default class Serializer {
|
|
|
44
44
|
}
|
|
45
45
|
} else if (Array.isArray(arg)) {
|
|
46
46
|
return this.serializeArray(arg)
|
|
47
|
-
} else if (typeof arg == "object" && arg.constructor && arg.constructor.apiMakerType == "Collection") {
|
|
47
|
+
} else if (typeof arg == "object" && arg && arg.constructor && arg.constructor.apiMakerType == "Collection") {
|
|
48
48
|
return {
|
|
49
49
|
api_maker_type: "collection",
|
|
50
50
|
value: this.serializeObject(arg)
|
|
@@ -57,6 +57,7 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
57
57
|
static propTypes = {
|
|
58
58
|
modelClass: PropTypes.func.isRequired,
|
|
59
59
|
queryName: PropTypes.string.isRequired,
|
|
60
|
+
querySName: PropTypes.string.isRequired,
|
|
60
61
|
queryParams: PropTypes.object.isRequired
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -65,7 +66,7 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
65
66
|
})
|
|
66
67
|
|
|
67
68
|
render() {
|
|
68
|
-
const {modelClass} = this.props
|
|
69
|
+
const {modelClass, querySName} = digs(this.props, "modelClass", "querySName")
|
|
69
70
|
const {filter} = digs(this.shape, "filter")
|
|
70
71
|
const currentFilters = this.currentFilters()
|
|
71
72
|
|
|
@@ -80,7 +81,7 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
80
81
|
key={`filter-${filter.filterIndex}`}
|
|
81
82
|
modelClass={modelClass}
|
|
82
83
|
onApplyClicked={digg(this, "onApplyClicked")}
|
|
83
|
-
querySearchName={
|
|
84
|
+
querySearchName={querySName}
|
|
84
85
|
/>
|
|
85
86
|
}
|
|
86
87
|
{currentFilters?.map((filterData, filterIndex) =>
|
|
@@ -97,8 +98,8 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
currentFilters() {
|
|
100
|
-
const {queryParams} = this.props
|
|
101
|
-
const currentFilters = queryParams[
|
|
101
|
+
const {queryParams, querySName} = digs(this.props, "queryParams", "querySName")
|
|
102
|
+
const currentFilters = queryParams[querySName] || []
|
|
102
103
|
|
|
103
104
|
return currentFilters
|
|
104
105
|
}
|
|
@@ -118,13 +119,14 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
118
119
|
onApplyClicked = () => this.shape.set({filter: undefined})
|
|
119
120
|
|
|
120
121
|
onRemoveClicked = ({filterIndex}) => {
|
|
121
|
-
const
|
|
122
|
+
const {querySName} = digs(this.props, "querySName")
|
|
123
|
+
const searchParams = Params.parse()[querySName] || {}
|
|
122
124
|
|
|
123
125
|
delete searchParams[filterIndex]
|
|
124
126
|
|
|
125
127
|
const newParams = {}
|
|
126
128
|
|
|
127
|
-
newParams[
|
|
129
|
+
newParams[querySName] = searchParams
|
|
128
130
|
|
|
129
131
|
Params.changeParams(newParams)
|
|
130
132
|
|
|
@@ -134,7 +136,6 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
onFilterClicked = (args) => this.shape.set({filter: args})
|
|
137
|
-
querySearchName = () => `${this.props.queryName}_s`
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
export default withQueryParams(ApiMakerTableFilters)
|
|
@@ -4,6 +4,7 @@ import {digg} from "diggerize"
|
|
|
4
4
|
import inflection from "inflection"
|
|
5
5
|
import {serialize as objectToFormData} from "object-to-formdata"
|
|
6
6
|
import {TableSetting} from "../models.mjs.erb"
|
|
7
|
+
import {v4 as uuidv4} from "uuid"
|
|
7
8
|
|
|
8
9
|
export default class ApiMakerTableSettings {
|
|
9
10
|
constructor({table}) {
|
|
@@ -62,13 +63,13 @@ export default class ApiMakerTableSettings {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
loadTableSetting = async () => {
|
|
65
|
-
if (!TableSetting) throw new Error("TableSetting model
|
|
66
|
+
if (!TableSetting) throw new Error("TableSetting model isn't globally available")
|
|
66
67
|
|
|
67
68
|
const tableSetting = await TableSetting
|
|
68
69
|
.ransack({
|
|
69
70
|
identifier_eq: this.identifier(),
|
|
70
|
-
user_id_eq: this.
|
|
71
|
-
user_type_eq:
|
|
71
|
+
user_id_eq: this.currentUserIdOrFallback(),
|
|
72
|
+
user_type_eq: this.currentUserTypeOrFallback()
|
|
72
73
|
})
|
|
73
74
|
.preload("columns")
|
|
74
75
|
.first()
|
|
@@ -76,11 +77,39 @@ export default class ApiMakerTableSettings {
|
|
|
76
77
|
return tableSetting
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
currentUserIdOrFallback() {
|
|
81
|
+
const currentUser = this.currentUser()
|
|
82
|
+
|
|
83
|
+
if (currentUser) return currentUser.id()
|
|
84
|
+
|
|
85
|
+
return this.anonymouseUserId()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
currentUserTypeOrFallback() {
|
|
89
|
+
const currentUser = this.currentUser()
|
|
90
|
+
|
|
91
|
+
if (currentUser) return digg(currentUser.modelClassData(), "name")
|
|
92
|
+
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
anonymouseUserId() {
|
|
97
|
+
const variableName = `ApiMakerTableAnonymousUserId-${this.identifier()}`
|
|
98
|
+
|
|
99
|
+
if (!(variableName in localStorage)) {
|
|
100
|
+
const generatedId = uuidv4()
|
|
101
|
+
|
|
102
|
+
localStorage[variableName] = generatedId
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return digg(localStorage, variableName)
|
|
106
|
+
}
|
|
107
|
+
|
|
79
108
|
createInitialTableSetting = async () => {
|
|
80
109
|
const tableSettingData = {
|
|
81
110
|
identifier: this.identifier(),
|
|
82
|
-
user_id: this.
|
|
83
|
-
user_type:
|
|
111
|
+
user_id: this.currentUserIdOrFallback(),
|
|
112
|
+
user_type: this.currentUserTypeOrFallback(),
|
|
84
113
|
columns_attributes: {}
|
|
85
114
|
}
|
|
86
115
|
|
|
@@ -116,9 +145,6 @@ export default class ApiMakerTableSettings {
|
|
|
116
145
|
}
|
|
117
146
|
|
|
118
147
|
updateTableSetting = async (tableSetting) => {
|
|
119
|
-
// This should remove columns no longer found
|
|
120
|
-
// This should update columns that have changed
|
|
121
|
-
|
|
122
148
|
const columns = this.columns()
|
|
123
149
|
const columnsData = {}
|
|
124
150
|
const tableSettingData = {columns_attributes: columnsData}
|
|
@@ -149,7 +175,7 @@ export default class ApiMakerTableSettings {
|
|
|
149
175
|
const column = columns.find((column) => columnIdentifier(column) == tableSettingColumn.identifier())
|
|
150
176
|
|
|
151
177
|
if (column) {
|
|
152
|
-
// Update column if changed
|
|
178
|
+
// TODO: Update column if changed
|
|
153
179
|
} else {
|
|
154
180
|
// Removed saved columns no longer found
|
|
155
181
|
const columnKey = ++columnsKeyCount
|
|
@@ -158,6 +184,7 @@ export default class ApiMakerTableSettings {
|
|
|
158
184
|
id: tableSettingColumn.id(),
|
|
159
185
|
_destroy: true
|
|
160
186
|
}
|
|
187
|
+
changed = true
|
|
161
188
|
}
|
|
162
189
|
}
|
|
163
190
|
|
|
@@ -165,9 +192,6 @@ export default class ApiMakerTableSettings {
|
|
|
165
192
|
const tableSettingFormData = objectToFormData({table_setting: tableSettingData})
|
|
166
193
|
|
|
167
194
|
await tableSetting.saveRaw(tableSettingFormData)
|
|
168
|
-
|
|
169
|
-
// Maybe not necessary?
|
|
170
|
-
// tableSetting = this.loadTableSetting()
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
return tableSetting
|
package/src/table/table.jsx
CHANGED
|
@@ -96,6 +96,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
96
96
|
queryName,
|
|
97
97
|
queryQName: `${queryName}_q`,
|
|
98
98
|
queryPageName: `${queryName}_page`,
|
|
99
|
+
querySName: `${queryName}_s`,
|
|
99
100
|
qParams: undefined,
|
|
100
101
|
result: undefined,
|
|
101
102
|
showFilters: false,
|
|
@@ -143,6 +144,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
143
144
|
qParams,
|
|
144
145
|
query,
|
|
145
146
|
queryName,
|
|
147
|
+
querySName,
|
|
146
148
|
result,
|
|
147
149
|
models,
|
|
148
150
|
showFilters,
|
|
@@ -155,6 +157,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
155
157
|
"qParams",
|
|
156
158
|
"query",
|
|
157
159
|
"queryName",
|
|
160
|
+
"querySName",
|
|
158
161
|
"result",
|
|
159
162
|
"models",
|
|
160
163
|
"showFilters",
|
|
@@ -189,7 +192,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
189
192
|
</div>
|
|
190
193
|
}
|
|
191
194
|
{showFilters &&
|
|
192
|
-
<Filters modelClass={modelClass} queryName={queryName} />
|
|
195
|
+
<Filters modelClass={modelClass} queryName={queryName} querySName={querySName} />
|
|
193
196
|
}
|
|
194
197
|
{qParams && query && result && models && !showNoRecordsAvailableContent && !showNoRecordsFoundContent &&
|
|
195
198
|
this.cardOrTable()
|
|
@@ -546,10 +549,10 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
546
549
|
const filterForm = digg(filterFormRef, "current")
|
|
547
550
|
const {appHistory} = this.props
|
|
548
551
|
const qParams = Params.serializeForm(filterForm)
|
|
549
|
-
const {queryQName} = this.shape
|
|
552
|
+
const {queryQName} = digs(this.shape, "queryQName")
|
|
550
553
|
const changeParamsParams = {}
|
|
551
554
|
|
|
552
|
-
changeParamsParams[queryQName] = qParams
|
|
555
|
+
changeParamsParams[queryQName] = JSON.stringify(qParams)
|
|
553
556
|
|
|
554
557
|
Params.changeParams(changeParamsParams, {appHistory})
|
|
555
558
|
}
|