@kaspernj/api-maker 1.0.291 → 1.0.292
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 +1 -1
- package/src/config.mjs +1 -0
- package/src/inputs/checkbox.jsx +1 -0
- package/src/inputs/input-wrapper.jsx +7 -1
- package/src/table/filters/filter-form.jsx +0 -2
- package/src/table/filters/index.jsx +60 -10
- package/src/table/filters/load-search-modal.jsx +60 -0
- package/src/table/filters/save-search-modal.jsx +51 -0
- package/src/table/settings/index.jsx +1 -1
- package/src/table/table.jsx +2 -2
package/package.json
CHANGED
package/src/config.mjs
CHANGED
package/src/inputs/checkbox.jsx
CHANGED
|
@@ -32,7 +32,13 @@ const inputWrapper = (WrapperComponentClass, wrapperOptions = {}) => {
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
if (this.handleAsCheckbox()) {
|
|
35
|
-
|
|
35
|
+
if ("checked" in this.props) {
|
|
36
|
+
inputProps.checked = this.props.checked
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if ("defaultChecked" in this.props || (this.props.attribute && this.props.model)) {
|
|
40
|
+
inputProps.defaultChecked = this.inputDefaultChecked()
|
|
41
|
+
}
|
|
36
42
|
} else {
|
|
37
43
|
inputProps.defaultValue = this.inputDefaultValue()
|
|
38
44
|
}
|
|
@@ -339,8 +339,6 @@ export default class ApiMakerTableFiltersFilterForm extends React.PureComponent
|
|
|
339
339
|
throw new Error("Dont know if should search for attribute or scope?")
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
console.log({newSearchParams})
|
|
343
|
-
|
|
344
342
|
searchParams[filterIndex] = JSON.stringify(newSearchParams)
|
|
345
343
|
|
|
346
344
|
const newParams = {}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {digg, digs} from "diggerize"
|
|
2
|
+
import FilterForm from "./filter-form"
|
|
3
|
+
import LoadSearchModal from "./load-search-modal"
|
|
4
|
+
import SaveSearchModal from "./save-search-modal"
|
|
2
5
|
import PropTypes from "prop-types"
|
|
3
6
|
import React from "react"
|
|
4
|
-
import FilterForm from "./filter-form"
|
|
5
7
|
import Shape from "set-state-compare/src/shape"
|
|
6
8
|
import withQueryParams from "on-location-changed/src/with-query-params"
|
|
7
9
|
|
|
@@ -56,6 +58,7 @@ class ApiMakerTableFilter extends React.PureComponent {
|
|
|
56
58
|
|
|
57
59
|
class ApiMakerTableFilters extends React.PureComponent {
|
|
58
60
|
static propTypes = {
|
|
61
|
+
currentUser: PropTypes.object,
|
|
59
62
|
modelClass: PropTypes.func.isRequired,
|
|
60
63
|
queryName: PropTypes.string.isRequired,
|
|
61
64
|
querySName: PropTypes.string.isRequired,
|
|
@@ -63,19 +66,19 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
shape = new Shape(this, {
|
|
66
|
-
filter: undefined
|
|
69
|
+
filter: undefined,
|
|
70
|
+
showLoadSearchModal: false,
|
|
71
|
+
showSaveSearchModal: false
|
|
67
72
|
})
|
|
68
73
|
|
|
69
74
|
render() {
|
|
70
75
|
const {modelClass, querySName} = digs(this.props, "modelClass", "querySName")
|
|
71
|
-
const {
|
|
76
|
+
const {currentUser} = this.props
|
|
77
|
+
const {filter, showLoadSearchModal, showSaveSearchModal} = digs(this.shape, "filter", "showLoadSearchModal", "showSaveSearchModal")
|
|
72
78
|
const currentFilters = this.currentFilters()
|
|
73
79
|
|
|
74
80
|
return (
|
|
75
81
|
<div className="api-maker--table--filters">
|
|
76
|
-
<button className="add-new-filter-button" onClick={digg(this, "onAddFilterClicked")}>
|
|
77
|
-
{I18n.t("js.api_maker.table.filters.add_new_filter", {defaultValue: "Add new filter"})}
|
|
78
|
-
</button>
|
|
79
82
|
{filter &&
|
|
80
83
|
<FilterForm
|
|
81
84
|
filter={filter}
|
|
@@ -85,24 +88,50 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
85
88
|
querySearchName={querySName}
|
|
86
89
|
/>
|
|
87
90
|
}
|
|
91
|
+
{showLoadSearchModal &&
|
|
92
|
+
<LoadSearchModal
|
|
93
|
+
currentUser={currentUser}
|
|
94
|
+
modelClass={modelClass}
|
|
95
|
+
onRequestClose={digg(this, "onRequestCloseLoadSearchModal")}
|
|
96
|
+
querySearchName={querySName}
|
|
97
|
+
/>
|
|
98
|
+
}
|
|
99
|
+
{showSaveSearchModal &&
|
|
100
|
+
<SaveSearchModal currentFilters={digg(this, "currentFilters")} currentUser={currentUser} onRequestClose={digg(this, "onRequestCloseSaveSearchModal")} />
|
|
101
|
+
}
|
|
88
102
|
{currentFilters?.map((filterData, filterIndex) =>
|
|
89
103
|
<ApiMakerTableFilter
|
|
90
104
|
key={filterIndex}
|
|
91
105
|
filterIndex={filterIndex}
|
|
92
106
|
onClick={digg(this, "onFilterClicked")}
|
|
93
107
|
onRemoveClicked={digg(this, "onRemoveClicked")}
|
|
94
|
-
{...
|
|
108
|
+
{...filterData}
|
|
95
109
|
/>
|
|
96
110
|
)}
|
|
111
|
+
<div className="filter-actions">
|
|
112
|
+
<button className="add-new-filter-button" onClick={digg(this, "onAddFilterClicked")}>
|
|
113
|
+
{I18n.t("js.api_maker.table.filters.add_new_filter", {defaultValue: "Add new filter"})}
|
|
114
|
+
</button>
|
|
115
|
+
{currentUser &&
|
|
116
|
+
<>
|
|
117
|
+
<button className="save-search-button" onClick={digg(this, "onSaveSearchClicked")}>
|
|
118
|
+
{I18n.t("js.api_maker.table.filters.save_search", {defaultValue: "Save search"})}
|
|
119
|
+
</button>
|
|
120
|
+
<button className="load-search-button" onClick={digg(this, "onLoadSearchClicked")}>
|
|
121
|
+
{I18n.t("js.api_maker.table.filters.load_search", {defaultValue: "Load search"})}
|
|
122
|
+
</button>
|
|
123
|
+
</>
|
|
124
|
+
}
|
|
125
|
+
</div>
|
|
97
126
|
</div>
|
|
98
127
|
)
|
|
99
128
|
}
|
|
100
129
|
|
|
101
|
-
currentFilters() {
|
|
130
|
+
currentFilters = () => {
|
|
102
131
|
const {queryParams, querySName} = digs(this.props, "queryParams", "querySName")
|
|
103
132
|
const currentFilters = queryParams[querySName] || []
|
|
104
133
|
|
|
105
|
-
return currentFilters
|
|
134
|
+
return currentFilters.map((currentFilter) => JSON.parse(currentFilter))
|
|
106
135
|
}
|
|
107
136
|
|
|
108
137
|
onAddFilterClicked = (e) => {
|
|
@@ -118,6 +147,14 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
118
147
|
}
|
|
119
148
|
|
|
120
149
|
onApplyClicked = () => this.shape.set({filter: undefined})
|
|
150
|
+
onFilterClicked = (args) => this.shape.set({filter: args})
|
|
151
|
+
|
|
152
|
+
onLoadSearchClicked = (e) => {
|
|
153
|
+
e.preventDefault()
|
|
154
|
+
this.shape.set({
|
|
155
|
+
showLoadSearchModal: true
|
|
156
|
+
})
|
|
157
|
+
}
|
|
121
158
|
|
|
122
159
|
onRemoveClicked = ({filterIndex}) => {
|
|
123
160
|
const {querySName} = digs(this.props, "querySName")
|
|
@@ -136,7 +173,20 @@ class ApiMakerTableFilters extends React.PureComponent {
|
|
|
136
173
|
})
|
|
137
174
|
}
|
|
138
175
|
|
|
139
|
-
|
|
176
|
+
onRequestCloseLoadSearchModal = () => this.shape.set({showLoadSearchModal: false})
|
|
177
|
+
onRequestCloseSaveSearchModal = () => this.shape.set({showSaveSearchModal: false})
|
|
178
|
+
|
|
179
|
+
onSaveSearchClicked = (e) => {
|
|
180
|
+
e.preventDefault()
|
|
181
|
+
|
|
182
|
+
if (this.hasAnyFilters()) {
|
|
183
|
+
this.shape.set({showSaveSearchModal: true})
|
|
184
|
+
} else {
|
|
185
|
+
FlashMessage.alert(I18n.t("js.api_maker.table.filters.no_filters_has_been_set", {defaultValue: "No filters has been set"}))
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
hasAnyFilters = () => Object.keys(this.currentFilters()).length > 0
|
|
140
190
|
}
|
|
141
191
|
|
|
142
192
|
export default withQueryParams(ApiMakerTableFilters)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import apiMakerConfig from "@kaspernj/api-maker/src/config.mjs"
|
|
2
|
+
import classNames from "classnames"
|
|
3
|
+
import {digg} from "diggerize"
|
|
4
|
+
import {TableSearch} from "../../models.mjs.erb"
|
|
5
|
+
import {useCallback, useEffect, useState} from "react"
|
|
6
|
+
|
|
7
|
+
const SearchLink = (props) => {
|
|
8
|
+
const {onClick, search} = props
|
|
9
|
+
const onSearchClicked = useCallback((e) => {
|
|
10
|
+
e.preventDefault()
|
|
11
|
+
onClick({search})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<a className="load-search-link" href="#" key={search.id()} onClick={onSearchClicked} style={{display: "block"}}>
|
|
16
|
+
{search.name()}
|
|
17
|
+
</a>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ApiMakerTableFiltersLoadSearchModal = (props) => {
|
|
22
|
+
const {className, currentUser, modelClass, onRequestClose, querySearchName, ...restProps} = props
|
|
23
|
+
const Modal = apiMakerConfig.getModal()
|
|
24
|
+
const [searches, setSearches] = useState(undefined)
|
|
25
|
+
|
|
26
|
+
const loadSearches = async () => {
|
|
27
|
+
const userType = digg(currentUser.modelClassData(), "name")
|
|
28
|
+
const searches = await TableSearch
|
|
29
|
+
.ransack({user_id_eq: currentUser.id(), user_type_eq: userType})
|
|
30
|
+
.toArray()
|
|
31
|
+
|
|
32
|
+
setSearches(searches)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const onSearchClicked = useCallback(({search}) => {
|
|
36
|
+
const queryParams = search.queryParams()
|
|
37
|
+
const newParams = {}
|
|
38
|
+
|
|
39
|
+
newParams[querySearchName] = queryParams.map((queryParam) => JSON.stringify(queryParam))
|
|
40
|
+
|
|
41
|
+
Params.changeParams(newParams)
|
|
42
|
+
|
|
43
|
+
onRequestClose()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
useEffect(() => { loadSearches() }, [])
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Modal className={classNames("api-maker--table--filters--load-search-modal", className)} onRequestClose={onRequestClose} {...restProps}>
|
|
50
|
+
<div>
|
|
51
|
+
{I18n.t("js.api_maker.table.filters.load_search_modal.choose_a_search", {defaultValue: "Choose a search"})}
|
|
52
|
+
</div>
|
|
53
|
+
{searches?.map((search) =>
|
|
54
|
+
<SearchLink key={search.id()} onClick={onSearchClicked} search={search} />
|
|
55
|
+
)}
|
|
56
|
+
</Modal>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default ApiMakerTableFiltersLoadSearchModal
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import apiMakerConfig from "@kaspernj/api-maker/src/config.mjs"
|
|
2
|
+
import {digg} from "diggerize"
|
|
3
|
+
import Input from "../../bootstrap/input"
|
|
4
|
+
import {TableSearch} from "../../models.mjs.erb"
|
|
5
|
+
import {useCallback} from "react"
|
|
6
|
+
|
|
7
|
+
const ApiMakerTableFiltersSaveSearchModal = (props) => {
|
|
8
|
+
const {currentFilters, currentUser, onRequestClose, ...restProps} = props
|
|
9
|
+
const Modal = apiMakerConfig.getModal()
|
|
10
|
+
|
|
11
|
+
const onSaveSearchSubmit = useCallback(async (e) => {
|
|
12
|
+
e.preventDefault()
|
|
13
|
+
|
|
14
|
+
const form = digg(e, "target")
|
|
15
|
+
const formData = new FormData(form)
|
|
16
|
+
const tableSearch = new TableSearch()
|
|
17
|
+
|
|
18
|
+
formData.append("table_search[query_params]", JSON.stringify(currentFilters()))
|
|
19
|
+
formData.append("table_search[user_type]", digg(currentUser.modelClassData(), "className"))
|
|
20
|
+
formData.append("table_search[user_id]", currentUser.id())
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await tableSearch.saveRaw(formData, {form})
|
|
24
|
+
onRequestClose()
|
|
25
|
+
} catch (error) {
|
|
26
|
+
FlashMessage.errorResponse(error)
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Modal onRequestClose={onRequestClose} {...restProps}>
|
|
32
|
+
<form onSubmit={onSaveSearchSubmit}>
|
|
33
|
+
<Input
|
|
34
|
+
id="table_search_name"
|
|
35
|
+
label={I18n.t("js.api_maker.table.filters.save_search_modal.search_name", {defaultValue: "Search name"})}
|
|
36
|
+
name="table_search[name]"
|
|
37
|
+
/>
|
|
38
|
+
<Checkbox
|
|
39
|
+
id="table_search_public"
|
|
40
|
+
label={I18n.t("js.api_maker.table.filters.save_search_modal.public", {defaultValue: "Public"})}
|
|
41
|
+
name="table_search[public]"
|
|
42
|
+
/>
|
|
43
|
+
<button className="save-search-submit-button">
|
|
44
|
+
{I18n.t("js.api_maker.table.filters.save_search_modal.save_search", {defaultValue: "Save search"})}
|
|
45
|
+
</button>
|
|
46
|
+
</form>
|
|
47
|
+
</Modal>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default ApiMakerTableFiltersSaveSearchModal
|
|
@@ -34,7 +34,7 @@ class ColumnRow extends React.PureComponent {
|
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<div className="api-maker--table--settings--column-row">
|
|
37
|
-
<label>
|
|
37
|
+
<label style={{whiteSpace: "nowrap"}}>
|
|
38
38
|
<input
|
|
39
39
|
className="api-maker--table--setings--column-checkbox"
|
|
40
40
|
data-identifier={columnIdentifier(column)}
|
package/src/table/table.jsx
CHANGED
|
@@ -157,7 +157,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
157
157
|
|
|
158
158
|
render () {
|
|
159
159
|
const {modelClass, noRecordsAvailableContent, noRecordsFoundContent} = digs(this.props, "modelClass", "noRecordsAvailableContent", "noRecordsFoundContent")
|
|
160
|
-
const {collection, defaultParams, onModelsLoaded, selectColumns} = this.props
|
|
160
|
+
const {collection, currentUser, defaultParams, onModelsLoaded, selectColumns} = this.props
|
|
161
161
|
const {
|
|
162
162
|
overallCount,
|
|
163
163
|
preload,
|
|
@@ -221,7 +221,7 @@ class ApiMakerTable extends React.PureComponent {
|
|
|
221
221
|
</div>
|
|
222
222
|
}
|
|
223
223
|
{showFilters &&
|
|
224
|
-
<Filters modelClass={modelClass} queryName={queryName} querySName={querySName} />
|
|
224
|
+
<Filters currentUser={currentUser} modelClass={modelClass} queryName={queryName} querySName={querySName} />
|
|
225
225
|
}
|
|
226
226
|
{qParams && query && result && models && !showNoRecordsAvailableContent && !showNoRecordsFoundContent &&
|
|
227
227
|
this.cardOrTable()
|