@kaspernj/api-maker 1.0.372 → 1.0.374

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaspernj/api-maker",
3
- "version": "1.0.372",
3
+ "version": "1.0.374",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "main": "index.js",
@@ -35,7 +35,7 @@
35
35
  "on-location-changed": ">= 1.0.10",
36
36
  "qs": ">= 6.9.3",
37
37
  "replaceall": ">= 0.1.6",
38
- "set-state-compare": "^1.0.42",
38
+ "set-state-compare": "^1.0.45",
39
39
  "spark-md5": "^3.0.2",
40
40
  "stacktrace-parser": "^0.1.10",
41
41
  "strftime": ">= 0.10.0",
@@ -1,6 +1,7 @@
1
1
  import CableSubscriptionPool from "./cable-subscription-pool.mjs"
2
2
  import CableSubscription from "./cable-subscription.mjs"
3
3
  import {dig} from "diggerize"
4
+ import RunLast from "./run-last.mjs"
4
5
 
5
6
  const shared = {}
6
7
 
@@ -96,7 +97,7 @@ export default class ApiMakerCableConnectionPool {
96
97
  currentSubscription[value].push(subscription)
97
98
  }
98
99
 
99
- this.scheduleConnectUpcoming()
100
+ this.scheduleConnectUpcomingRunLast.queue()
100
101
 
101
102
  return subscription
102
103
  }
@@ -122,10 +123,5 @@ export default class ApiMakerCableConnectionPool {
122
123
  this.cableSubscriptionPools.push(cableSubscriptionPool)
123
124
  }
124
125
 
125
- scheduleConnectUpcoming () {
126
- if (this.scheduleConnectUpcomingTimeout)
127
- clearTimeout(this.scheduleConnectUpcomingTimeout)
128
-
129
- this.scheduleConnectUpcomingTimeout = setTimeout(this.connectUpcoming, 0)
130
- }
126
+ scheduleConnectUpcomingRunLast = new RunLast(this.connectUpcoming)
131
127
  }
@@ -6,6 +6,7 @@ import Deserializer from "./deserializer.mjs"
6
6
  import {dig, digg} from "diggerize"
7
7
  import events from "./events.mjs"
8
8
  import FormDataObjectizer from "form-data-objectizer"
9
+ import RunLast from "./run-last.mjs"
9
10
  import Serializer from "./serializer.mjs"
10
11
  import SessionStatusUpdater from "./session-status-updater.mjs"
11
12
  import ValidationError from "./validation-error.mjs"
@@ -26,9 +27,9 @@ export default class ApiMakerCommandsPool {
26
27
  const promiseResult = pool.addCommand(data)
27
28
 
28
29
  if (args.instant) {
29
- pool.flush()
30
+ pool.flushRunLast.run()
30
31
  } else {
31
- pool.setFlushTimeout()
32
+ pool.flushRunLast.queue()
32
33
  }
33
34
 
34
35
  return promiseResult
@@ -115,13 +116,11 @@ export default class ApiMakerCommandsPool {
115
116
  throw new Error("Couldnt successfully execute request")
116
117
  }
117
118
 
118
- async flush() {
119
+ flush = async () => {
119
120
  if (this.commandsCount() == 0) {
120
121
  return
121
122
  }
122
123
 
123
- this.clearTimeout()
124
-
125
124
  const currentPool = this.pool
126
125
  const currentPoolData = this.poolData
127
126
 
@@ -158,7 +157,8 @@ export default class ApiMakerCommandsPool {
158
157
  } else if (responseType == "error") {
159
158
  const error = new CustomError("Command error", {response: commandResponseData})
160
159
 
161
- error.stack += commandData.stack
160
+ error.stack += "\n"
161
+ error.stack += commandData.stack.split("\n").slice(1).join("\n")
162
162
 
163
163
  commandData.reject(error)
164
164
  } else if (responseType == "failed") {
@@ -196,12 +196,6 @@ export default class ApiMakerCommandsPool {
196
196
  commandData.reject(error)
197
197
  }
198
198
 
199
- clearTimeout() {
200
- if (this.flushTimeout) {
201
- clearTimeout(this.flushTimeout)
202
- }
203
- }
204
-
205
199
  isActive() {
206
200
  if (this.commandsCount() > 0) {
207
201
  return true
@@ -214,24 +208,5 @@ export default class ApiMakerCommandsPool {
214
208
  return false
215
209
  }
216
210
 
217
- // Try to batch calls to backend while waiting for the event-queue-call to clear any other jobs before the request and reset on every flush call
218
- // If only waiting a single time, then other event-queue-jobs might be before us and queue other jobs that might queue calls to the backend
219
- setFlushTimeout() {
220
- this.flushTriggerCount = 0
221
- this.clearTimeout()
222
- this.flushTrigger()
223
- }
224
-
225
- flushTrigger = () => {
226
- if (this.flushTriggerCount >= 10) {
227
- this.flush()
228
- } else {
229
- this.flushTriggerCount++
230
- this.flushTriggerQueue()
231
- }
232
- }
233
-
234
- flushTriggerQueue() {
235
- this.flushTimeout = setTimeout(this.flushTrigger, 0)
236
- }
211
+ flushRunLast = new RunLast(this.flush)
237
212
  }
@@ -0,0 +1,39 @@
1
+ export default class RunLast {
2
+ constructor(callback) {
3
+ if (!callback) throw new Error("Empty callback given")
4
+
5
+ this.callback = callback
6
+ }
7
+
8
+ // Try to batch calls to backend while waiting for the event-queue-call to clear any other jobs before the request and reset on every flush call
9
+ // If only waiting a single time, then other event-queue-jobs might be before us and queue other jobs that might queue calls to the backend
10
+ queue() {
11
+ this.flushTriggerCount = 0
12
+ this.clearTimeout()
13
+ this.flushTrigger()
14
+ }
15
+
16
+ flushTrigger = () => {
17
+ if (this.flushTriggerCount >= 10) {
18
+ this.run()
19
+ } else {
20
+ this.flushTriggerCount++
21
+ this.flushTriggerQueue()
22
+ }
23
+ }
24
+
25
+ flushTriggerQueue() {
26
+ this.flushTimeout = setTimeout(this.flushTrigger, 0)
27
+ }
28
+
29
+ clearTimeout() {
30
+ if (this.flushTimeout) {
31
+ clearTimeout(this.flushTimeout)
32
+ }
33
+ }
34
+
35
+ run() {
36
+ clearTimeout(this.flushTimeout)
37
+ this.callback()
38
+ }
39
+ }
@@ -13,21 +13,21 @@ if (SourceMapConsumer.initialize) {
13
13
  const logger = new Logger({name: "ApiMaker / SourceMapsLoader"})
14
14
 
15
15
  export default class SourceMapsLoader {
16
- constructor () {
16
+ constructor() {
17
17
  this.isLoadingSourceMaps = false
18
18
  this.sourceMaps = []
19
19
  this.srcLoaded = {}
20
20
  }
21
21
 
22
- loadSourceMapsForScriptTags (callback) {
22
+ loadSourceMapsForScriptTags(callback) {
23
23
  this.loadSourceMapsForScriptTagsCallback = callback
24
24
  }
25
25
 
26
- sourceMapForSource (callback) {
26
+ sourceMapForSource(callback) {
27
27
  this.sourceMapForSourceCallback = callback
28
28
  }
29
29
 
30
- async loadSourceMaps (error) {
30
+ async loadSourceMaps(error) {
31
31
  if (!error) throw new Error("No error was given to SourceMapsLoader#loadSourceMaps")
32
32
 
33
33
  this.isLoadingSourceMaps = true
@@ -111,11 +111,9 @@ export default class SourceMapsLoader {
111
111
  }
112
112
  }
113
113
 
114
- includeMapURL(src) {
115
- return src.includes("/packs/")
116
- }
114
+ includeMapURL = (src) => src.includes("/packs/")
117
115
 
118
- async loadSourceMapForSource ({originalUrl, sourceMapUrl}) {
116
+ async loadSourceMapForSource({originalUrl, sourceMapUrl}) {
119
117
  const xhr = new XMLHttpRequest()
120
118
 
121
119
  xhr.open("GET", sourceMapUrl, true)
@@ -127,26 +125,27 @@ export default class SourceMapsLoader {
127
125
  this.sourceMaps.push({consumer, originalUrl})
128
126
  }
129
127
 
130
- loadUrl (url) {
128
+ loadUrl(url) {
131
129
  const parser = document.createElement("a")
130
+
132
131
  parser.href = url
133
132
 
134
133
  return parser
135
134
  }
136
135
 
137
- loadXhr (xhr, postData) {
136
+ loadXhr(xhr, postData) {
138
137
  return new Promise((resolve) => {
139
138
  xhr.onload = () => resolve()
140
139
  xhr.send(postData)
141
140
  })
142
141
  }
143
142
 
144
- parseStackTrace (stackTrace) {
143
+ parseStackTrace(stackTrace) {
145
144
  return this.getStackTraceData(stackTrace)
146
145
  .map((traceData) => `at ${traceData.methodName} (${traceData.fileString})`)
147
146
  }
148
147
 
149
- getStackTraceData (stackTrace) {
148
+ getStackTraceData(stackTrace) {
150
149
  const stack = stackTraceParser.parse(stackTrace)
151
150
  const newSourceMap = []
152
151
 
@@ -0,0 +1,42 @@
1
+ import Attribute from "../../base-model/attribute"
2
+ import {digg, digs} from "diggerize"
3
+ import * as inflection from "inflection"
4
+ import PropTypes from "prop-types"
5
+ import PropTypesExact from "prop-types-exact"
6
+ import {memo} from "react"
7
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component"
8
+
9
+ export default memo(shapeComponent(class AttributeElement extends ShapeComponent {
10
+ static propTypes = PropTypesExact({
11
+ active: PropTypes.bool.isRequired,
12
+ attribute: PropTypes.instanceOf(Attribute).isRequired,
13
+ currentModelClass: PropTypes.func.isRequired,
14
+ fikter: PropTypes.object,
15
+ onClick: PropTypes.func.isRequired
16
+ })
17
+
18
+ render() {
19
+ const {active, attribute, currentModelClass} = digs(this.props, "active", "attribute", "currentModelClass")
20
+ const style = {}
21
+
22
+ if (active) style.fontWeight = "bold"
23
+
24
+ return (
25
+ <div
26
+ className="attribute-element"
27
+ data-attribute-name={attribute.name()}
28
+ data-model-class={currentModelClass.modelClassData().name}
29
+ onClick={digg(this, "onAttributeClicked")}
30
+ style={style}
31
+ >
32
+ {currentModelClass.humanAttributeName(inflection.camelize(attribute.name(), true))}
33
+ </div>
34
+ )
35
+ }
36
+
37
+ onAttributeClicked = (e) => {
38
+ e.preventDefault()
39
+
40
+ this.props.onClick({attribute: digg(this, "props", "attribute")})
41
+ }
42
+ }))
@@ -1,116 +1,17 @@
1
- import Attribute from "../../base-model/attribute"
1
+ import AttributeElement from "./attribute-element"
2
2
  import {digg, digs} from "diggerize"
3
3
  import * as inflection from "inflection"
4
4
  import Input from "../../inputs/input"
5
5
  import PropTypes from "prop-types"
6
6
  import PropTypesExact from "prop-types-exact"
7
- import React from "react"
8
- import Reflection from "../../base-model/reflection"
7
+ import {memo, useMemo, useRef} from "react"
8
+ import ReflectionElement from "./reflection-element"
9
+ import ScopeElement from "./scope-element"
9
10
  import Select from "../../inputs/select"
10
11
  import Services from "../../services.mjs"
11
- import Shape from "set-state-compare/src/shape"
12
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component"
12
13
 
13
- class AttributeElement extends React.PureComponent {
14
- static propTypes = PropTypesExact({
15
- active: PropTypes.bool.isRequired,
16
- attribute: PropTypes.instanceOf(Attribute).isRequired,
17
- currentModelClass: PropTypes.func.isRequired,
18
- fikter: PropTypes.object,
19
- onClick: PropTypes.func.isRequired
20
- })
21
-
22
- render() {
23
- const {active, attribute, currentModelClass} = digs(this.props, "active", "attribute", "currentModelClass")
24
- const style = {}
25
-
26
- if (active) style.fontWeight = "bold"
27
-
28
- return (
29
- <div
30
- className="attribute-element"
31
- data-attribute-name={attribute.name()}
32
- data-model-class={currentModelClass.modelClassData().name}
33
- onClick={digg(this, "onAttributeClicked")}
34
- style={style}
35
- >
36
- {currentModelClass.humanAttributeName(inflection.camelize(attribute.name(), true))}
37
- </div>
38
- )
39
- }
40
-
41
- onAttributeClicked = (e) => {
42
- e.preventDefault()
43
-
44
- this.props.onClick({attribute: digg(this, "props", "attribute")})
45
- }
46
- }
47
-
48
- class ReflectionElement extends React.PureComponent {
49
- static propTypes = PropTypesExact({
50
- currentModelClass: PropTypes.func.isRequired,
51
- onClick: PropTypes.func.isRequired,
52
- reflection: PropTypes.instanceOf(Reflection).isRequired
53
- })
54
-
55
- render() {
56
- const {currentModelClass, reflection} = digs(this.props, "currentModelClass", "reflection")
57
-
58
- return (
59
- <div
60
- className="reflection-element"
61
- data-model-class={currentModelClass.modelClassData().name}
62
- data-reflection-name={reflection.name()}
63
- onClick={digg(this, "onReflectionClicked")}
64
- >
65
- {currentModelClass.humanAttributeName(reflection.name())}
66
- </div>
67
- )
68
- }
69
-
70
- onReflectionClicked = (e) => {
71
- e.preventDefault()
72
-
73
- this.props.onClick({reflection: digg(this, "props", "reflection")})
74
- }
75
- }
76
-
77
- class ScopeElement extends React.PureComponent {
78
- static defaultProps = {
79
- active: false
80
- }
81
-
82
- static propTypes = {
83
- active: PropTypes.bool.isRequired,
84
- scope: PropTypes.object.isRequired
85
- }
86
-
87
- render() {
88
- const {active, scope} = this.props
89
- const style = {}
90
-
91
- if (active) style.fontWeight = "bold"
92
-
93
- return (
94
- <div
95
- className="scope-element"
96
- key={scope.name()}
97
- onClick={digg(this, "onScopeClicked")}
98
- style={style}
99
- >
100
- {scope.name()}
101
- </div>
102
- )
103
- }
104
-
105
- onScopeClicked = (e) => {
106
- e.preventDefault()
107
-
108
- this.props.onScopeClicked({scope: this.props.scope})
109
- }
110
- }
111
-
112
-
113
- export default class ApiMakerTableFiltersFilterForm extends React.PureComponent {
14
+ export default memo(shapeComponent(class ApiMakerTableFiltersFilterForm extends ShapeComponent {
114
15
  static propTypes = PropTypesExact({
115
16
  filter: PropTypes.object,
116
17
  modelClass: PropTypes.func.isRequired,
@@ -118,18 +19,22 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
118
19
  querySearchName: PropTypes.string.isRequired
119
20
  })
120
21
 
121
- shape = new Shape(this, {
122
- attribute: this.currentModelClassFromPath(this.props.filter.p || []).ransackableAttributes().find((attribute) => attribute.name() == this.props.filter.a),
123
- path: this.props.filter.p || [],
124
- predicate: undefined,
125
- predicates: undefined,
126
- scope: this.props.filter.sc,
127
- value: this.props.filter.v
128
- })
129
- valueInputRef = React.createRef()
22
+ setup() {
23
+ this.useStates({
24
+ attribute: () => this.currentModelClassFromPath(this.props.filter.p || [])
25
+ .ransackableAttributes()
26
+ .find((attribute) => attribute.name() == this.props.filter.a),
27
+ path: this.props.filter.p || [],
28
+ predicate: undefined,
29
+ predicates: undefined,
30
+ scope: this.props.filter.sc,
31
+ value: this.props.filter.v
32
+ })
33
+ this.valueInputRef = useRef()
130
34
 
131
- componentDidMount() {
132
- this.loadRansackPredicates()
35
+ useMemo(() => {
36
+ this.loadRansackPredicates()
37
+ }, [])
133
38
  }
134
39
 
135
40
  async loadRansackPredicates() {
@@ -141,7 +46,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
141
46
  currentPredicate = predicates.find((predicate) => predicate.name == this.props.filter.pre)
142
47
  }
143
48
 
144
- this.shape.set({
49
+ this.setState({
145
50
  predicate: currentPredicate,
146
51
  predicates
147
52
  })
@@ -150,7 +55,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
150
55
  render() {
151
56
  const {valueInputRef} = digs(this, "valueInputRef")
152
57
  const currentModelClass = this.currentModelClass()
153
- const {attribute, predicate, predicates, scope, value} = digs(this.shape, "attribute", "predicate", "scope", "predicates", "value")
58
+ const {attribute, predicate, predicates, scope, value} = digs(this.state, "attribute", "predicate", "scope", "predicates", "value")
154
59
  let submitEnabled = false
155
60
 
156
61
  if (attribute && predicate) {
@@ -188,7 +93,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
188
93
  <div>
189
94
  {this.sortedByName(currentModelClass.ransackableAttributes(), currentModelClass).map((attribute) =>
190
95
  <AttributeElement
191
- active={attribute.name() == this.shape.attribute?.name()}
96
+ active={attribute.name() == this.state.attribute?.name()}
192
97
  attribute={attribute}
193
98
  currentModelClass={currentModelClass}
194
99
  key={attribute.name()}
@@ -197,7 +102,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
197
102
  )}
198
103
  {currentModelClass.ransackableScopes().map((scope) =>
199
104
  <ScopeElement
200
- active={scope.name() == this.shape.scope?.name()}
105
+ active={scope.name() == this.state.scope?.name()}
201
106
  key={scope.name()}
202
107
  scope={scope}
203
108
  onScopeClicked={digg(this, "onScopeClicked")}
@@ -205,7 +110,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
205
110
  )}
206
111
  </div>
207
112
  <div>
208
- {predicates && !this.shape.scope &&
113
+ {predicates && !this.state.scope &&
209
114
  <Select
210
115
  className="predicate-select"
211
116
  defaultValue={predicate?.name}
@@ -232,7 +137,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
232
137
  }
233
138
 
234
139
  currentModelClass() {
235
- const {path} = digs(this.shape, "path")
140
+ const {path} = digs(this.state, "path")
236
141
 
237
142
  return this.currentModelClassFromPath(path)
238
143
  }
@@ -259,7 +164,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
259
164
 
260
165
  currentPathParts() {
261
166
  const {modelClass} = digs(this.props, "modelClass")
262
- const {path} = digs(this.shape, "path")
167
+ const {path} = digs(this.state, "path")
263
168
  const result = []
264
169
  let currentModelClass = modelClass
265
170
 
@@ -284,7 +189,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
284
189
  }
285
190
 
286
191
  onAttributeClicked = ({attribute}) => {
287
- this.shape.set({
192
+ this.setState({
288
193
  attribute,
289
194
  predicate: undefined,
290
195
  scope: undefined
@@ -293,15 +198,15 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
293
198
 
294
199
  onPredicateChanged = (e) => {
295
200
  const chosenPredicateName = digg(e, "target", "value")
296
- const predicate = this.shape.predicates.find((predicate) => predicate.name == chosenPredicateName)
201
+ const predicate = this.state.predicates.find((predicate) => predicate.name == chosenPredicateName)
297
202
 
298
- this.shape.set({predicate})
203
+ this.setState({predicate})
299
204
  }
300
205
 
301
206
  onReflectionClicked = ({reflection}) => {
302
- const newPath = this.shape.path.concat([inflection.underscore(reflection.name())])
207
+ const newPath = this.state.path.concat([inflection.underscore(reflection.name())])
303
208
 
304
- this.shape.set({
209
+ this.setState({
305
210
  attribute: undefined,
306
211
  path: newPath,
307
212
  predicate: undefined
@@ -311,7 +216,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
311
216
  }
312
217
 
313
218
  onScopeClicked = ({scope}) => {
314
- this.shape.set({
219
+ this.setState({
315
220
  attribute: undefined,
316
221
  scope
317
222
  })
@@ -321,7 +226,7 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
321
226
  e.preventDefault()
322
227
 
323
228
  const {filter, querySearchName} = digs(this.props, "filter", "querySearchName")
324
- const {attribute, path, predicate, scope} = digs(this.shape, "attribute", "path", "predicate", "scope")
229
+ const {attribute, path, predicate, scope} = digs(this.state, "attribute", "path", "predicate", "scope")
325
230
  const {filterIndex} = digs(filter, "filterIndex")
326
231
  const searchParams = Params.parse()[querySearchName] || {}
327
232
  const value = digg(this, "valueInputRef", "current", "value")
@@ -367,4 +272,4 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
367
272
  currentModelClass.humanAttributeName(a.name()).toLowerCase().localeCompare(currentModelClass.humanAttributeName(b.name()).toLowerCase())
368
273
  )
369
274
  }
370
- }
275
+ }))
@@ -0,0 +1,55 @@
1
+ import {digg, digs} from "diggerize"
2
+ import PropTypes from "prop-types"
3
+ import PropTypesExact from "prop-types-exact"
4
+ import {memo} from "react"
5
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component"
6
+
7
+ export default memo(shapeComponent(class ApiMakerTableFilter extends ShapeComponent {
8
+ static propTypes = PropTypesExact({
9
+ a: PropTypes.string,
10
+ filterIndex: PropTypes.number.isRequired,
11
+ onClick: PropTypes.func.isRequired,
12
+ onRemoveClicked: PropTypes.func.isRequired,
13
+ p: PropTypes.array.isRequired,
14
+ pre: PropTypes.string,
15
+ sc: PropTypes.string,
16
+ v: PropTypes.string.isRequired
17
+ })
18
+
19
+ render() {
20
+ const {p, v} = digs(this.props, "p", "v")
21
+ const {a, pre, sc} = this.props
22
+
23
+ return (
24
+ <div style={{display: "inline-block", backgroundColor: "grey", padding: "10px 6px"}}>
25
+ <span className="filter-label" onClick={digg(this, "onFilterClicked")} style={{cursor: "pointer"}}>
26
+ {p.length > 0 &&
27
+ `${p.join(".")}.`
28
+ }
29
+ {a} {sc} {pre} {v}
30
+ </span>
31
+ <span>
32
+ <a className="remove-filter-button" href="#" onClick={digg(this, "onRemoveFilterClicked")}>
33
+ <i className="fa fa-remove la la-remove" />
34
+ </a>
35
+ </span>
36
+ </div>
37
+ )
38
+ }
39
+
40
+ onFilterClicked = (e) => {
41
+ e.preventDefault()
42
+
43
+ const {a, filterIndex, p, pre, v} = digs(this.props, "a", "filterIndex", "p", "pre", "v")
44
+
45
+ this.props.onClick({a, filterIndex, p, pre, v})
46
+ }
47
+
48
+ onRemoveFilterClicked = (e) => {
49
+ e.preventDefault()
50
+
51
+ const {filterIndex} = digs(this.props, "filterIndex")
52
+
53
+ this.props.onRemoveClicked({filterIndex})
54
+ }
55
+ }))
@@ -1,4 +1,5 @@
1
1
  import {digg, digs} from "diggerize"
2
+ import Filter from "./filter"
2
3
  import FilterForm from "./filter-form"
3
4
  import LoadSearchModal from "./load-search-modal"
4
5
  import SaveSearchModal from "./save-search-modal"
@@ -8,55 +9,6 @@ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-compon
8
9
  import useI18n from "i18n-on-steroids/src/use-i18n.mjs"
9
10
  import useQueryParams from "on-location-changed/src/use-query-params"
10
11
 
11
- const ApiMakerTableFilter = memo(shapeComponent(class ApiMakerTableFilter extends ShapeComponent {
12
- static propTypes = {
13
- a: PropTypes.string.isRequired,
14
- filterIndex: PropTypes.number.isRequired,
15
- onClick: PropTypes.func.isRequired,
16
- onRemoveClicked: PropTypes.func.isRequired,
17
- p: PropTypes.array.isRequired,
18
- pre: PropTypes.string.isRequired,
19
- v: PropTypes.string.isRequired
20
- }
21
-
22
- render() {
23
- const {p, v} = digs(this.props, "p", "v")
24
- const {a, pre, sc} = this.props
25
-
26
- return (
27
- <div style={{display: "inline-block", backgroundColor: "grey", padding: "10px 6px"}}>
28
- <span className="filter-label" onClick={digg(this, "onFilterClicked")} style={{cursor: "pointer"}}>
29
- {p.length > 0 &&
30
- `${p.join(".")}.`
31
- }
32
- {a} {sc} {pre} {v}
33
- </span>
34
- <span>
35
- <a className="remove-filter-button" href="#" onClick={digg(this, "onRemoveFilterClicked")}>
36
- <i className="fa fa-remove la la-remove" />
37
- </a>
38
- </span>
39
- </div>
40
- )
41
- }
42
-
43
- onFilterClicked = (e) => {
44
- e.preventDefault()
45
-
46
- const {a, filterIndex, p, pre, v} = digs(this.props, "a", "filterIndex", "p", "pre", "v")
47
-
48
- this.props.onClick({a, filterIndex, p, pre, v})
49
- }
50
-
51
- onRemoveFilterClicked = (e) => {
52
- e.preventDefault()
53
-
54
- const {filterIndex} = digs(this.props, "filterIndex")
55
-
56
- this.props.onRemoveClicked({filterIndex})
57
- }
58
- }))
59
-
60
12
  export default memo(shapeComponent(class ApiMakerTableFilters extends ShapeComponent {
61
13
  static propTypes = {
62
14
  currentUser: PropTypes.object,
@@ -110,7 +62,7 @@ export default memo(shapeComponent(class ApiMakerTableFilters extends ShapeCompo
110
62
  />
111
63
  }
112
64
  {currentFilters?.map((filterData, filterIndex) =>
113
- <ApiMakerTableFilter
65
+ <Filter
114
66
  key={filterIndex}
115
67
  filterIndex={filterIndex}
116
68
  onClick={digg(this, "onFilterClicked")}
@@ -0,0 +1,35 @@
1
+ import {digg, digs} from "diggerize"
2
+ import PropTypes from "prop-types"
3
+ import PropTypesExact from "prop-types-exact"
4
+ import {memo} from "react"
5
+ import Reflection from "../../base-model/reflection"
6
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component"
7
+
8
+ export default memo(shapeComponent(class ReflectionElement extends ShapeComponent {
9
+ static propTypes = PropTypesExact({
10
+ currentModelClass: PropTypes.func.isRequired,
11
+ onClick: PropTypes.func.isRequired,
12
+ reflection: PropTypes.instanceOf(Reflection).isRequired
13
+ })
14
+
15
+ render() {
16
+ const {currentModelClass, reflection} = digs(this.props, "currentModelClass", "reflection")
17
+
18
+ return (
19
+ <div
20
+ className="reflection-element"
21
+ data-model-class={currentModelClass.modelClassData().name}
22
+ data-reflection-name={reflection.name()}
23
+ onClick={digg(this, "onReflectionClicked")}
24
+ >
25
+ {currentModelClass.humanAttributeName(reflection.name())}
26
+ </div>
27
+ )
28
+ }
29
+
30
+ onReflectionClicked = (e) => {
31
+ e.preventDefault()
32
+
33
+ this.props.onClick({reflection: digg(this, "props", "reflection")})
34
+ }
35
+ }))
@@ -0,0 +1,39 @@
1
+ import {digg} from "diggerize"
2
+ import PropTypes from "prop-types"
3
+ import {memo} from "react"
4
+ import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component"
5
+
6
+ export default memo(shapeComponent(class ScopeElement extends ShapeComponent {
7
+ static defaultProps = {
8
+ active: false
9
+ }
10
+
11
+ static propTypes = {
12
+ active: PropTypes.bool.isRequired,
13
+ scope: PropTypes.object.isRequired
14
+ }
15
+
16
+ render() {
17
+ const {active, scope} = this.props
18
+ const style = {}
19
+
20
+ if (active) style.fontWeight = "bold"
21
+
22
+ return (
23
+ <div
24
+ className="scope-element"
25
+ key={scope.name()}
26
+ onClick={digg(this, "onScopeClicked")}
27
+ style={style}
28
+ >
29
+ {scope.name()}
30
+ </div>
31
+ )
32
+ }
33
+
34
+ onScopeClicked = (e) => {
35
+ e.preventDefault()
36
+
37
+ this.props.onScopeClicked({scope: this.props.scope})
38
+ }
39
+ }))
@@ -22,6 +22,7 @@ import TableSettings from "./table-settings"
22
22
  import uniqunize from "uniqunize"
23
23
  import useBreakpoint from "./use-breakpoint"
24
24
  import useCollection from "../use-collection"
25
+ import useQueryParams from "on-location-changed/src/use-query-params.js"
25
26
 
26
27
  const paginationOptions = [30, 60, 90, ["All", "all"]]
27
28
  const WorkerPluginsCheckAllCheckbox = React.lazy(() => import("./worker-plugins-check-all-checkbox"))
@@ -79,6 +80,7 @@ export default memo(shapeComponent(class ApiMakerTable extends ShapeComponent {
79
80
 
80
81
  setup() {
81
82
  const {breakpoint} = useBreakpoint()
83
+ const queryParams = useQueryParams()
82
84
 
83
85
  this.setInstance({
84
86
  breakpoint,
@@ -91,18 +93,19 @@ export default memo(shapeComponent(class ApiMakerTable extends ShapeComponent {
91
93
  if (!queryName) queryName = collectionKey
92
94
 
93
95
  const columnsAsArray = this.columnsAsArray()
96
+ const querySName = `${queryName}_s`
94
97
 
95
98
  this.useStates({
96
99
  columns: columnsAsArray,
97
100
  currentWorkplace: undefined,
98
- identifier: this.props.identifier || `${collectionKey}-default`,
101
+ identifier: () => this.props.identifier || `${collectionKey}-default`,
99
102
  preload: undefined,
100
103
  preparedColumns: undefined,
101
104
  queryName,
102
- queryQName: `${queryName}_q`,
103
- queryPageName: `${queryName}_page`,
104
- querySName: `${queryName}_s`,
105
- showFilters: false,
105
+ queryQName: () => `${queryName}_q`,
106
+ queryPageName: () => `${queryName}_page`,
107
+ querySName,
108
+ showFilters: () => Boolean(queryParams[querySName]),
106
109
  showSettings: false,
107
110
  tableSetting: undefined,
108
111
  tableSettingFullCacheKey: undefined