@kaspernj/api-maker 1.0.417 → 1.0.419
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/bootstrap/attribute-row/index.jsx +6 -2
- package/src/table/header-column.jsx +11 -5
- package/src/table/model-column.jsx +64 -0
- package/src/table/model-row.jsx +12 -31
- package/src/table/settings/column-row.jsx +4 -2
- package/src/table/settings/index.jsx +0 -4
- package/src/table/table.jsx +117 -34
- package/src/table/widths.mjs +20 -19
- package/src/table/worker-plugins-checkbox.jsx +17 -21
- package/src/use-model-event.js +60 -0
- package/src/table/style.scss +0 -76
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import PropTypes from "prop-types"
|
|
|
6
6
|
import {memo, useMemo} from "react"
|
|
7
7
|
import {shapeComponent, ShapeComponent} from "set-state-compare/src/shape-component.js"
|
|
8
8
|
import strftime from "strftime"
|
|
9
|
+
import useI18n from "i18n-on-steroids/src/use-i18n.mjs"
|
|
9
10
|
|
|
10
11
|
export default memo(shapeComponent(class ApiMakerBootstrapAttributeRow extends ShapeComponent {
|
|
11
12
|
static defaultProps = {
|
|
@@ -23,6 +24,9 @@ export default memo(shapeComponent(class ApiMakerBootstrapAttributeRow extends S
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
setup() {
|
|
27
|
+
const {t} = useI18n({namespace: "js.api_maker.attribute_row"})
|
|
28
|
+
|
|
29
|
+
this.t = t
|
|
26
30
|
this.attribute = useMemo(
|
|
27
31
|
() => {
|
|
28
32
|
if (this.props.attribute) {
|
|
@@ -88,9 +92,9 @@ export default memo(shapeComponent(class ApiMakerBootstrapAttributeRow extends S
|
|
|
88
92
|
} else if (value instanceof Date) {
|
|
89
93
|
return strftime("%Y-%m-%d %H:%M", value)
|
|
90
94
|
} else if (typeof value === "boolean") {
|
|
91
|
-
if (value) return
|
|
95
|
+
if (value) return this.t("js.shared.yes", {defaultValue: "Yes"})
|
|
92
96
|
|
|
93
|
-
return
|
|
97
|
+
return this.t("js.shared.no", {defaultValue: "No"})
|
|
94
98
|
} else if (MoneyFormatter.isMoney(value)) {
|
|
95
99
|
return MoneyFormatter.format(value)
|
|
96
100
|
} else {
|
|
@@ -37,6 +37,15 @@ export default memo(shapeComponent(class ApiMakerTableHeaderColumn extends BaseC
|
|
|
37
37
|
const {defaultParams} = table.props
|
|
38
38
|
const {styleForHeader, styleForHeaderText} = table.tt
|
|
39
39
|
const {query} = digs(table.collection, "query")
|
|
40
|
+
const columnProps = table.columnProps(column)
|
|
41
|
+
const {style, ...restColumnProps} = columnProps
|
|
42
|
+
const actualStyle = Object.assign(
|
|
43
|
+
{
|
|
44
|
+
cursor: resizing ? "col-resize" : undefined,
|
|
45
|
+
width
|
|
46
|
+
},
|
|
47
|
+
style
|
|
48
|
+
)
|
|
40
49
|
|
|
41
50
|
return (
|
|
42
51
|
<Header
|
|
@@ -45,11 +54,8 @@ export default memo(shapeComponent(class ApiMakerTableHeaderColumn extends BaseC
|
|
|
45
54
|
identifier: tableSettingColumn.identifier()
|
|
46
55
|
}}
|
|
47
56
|
onLayout={this.tt.onLayout}
|
|
48
|
-
style={styleForHeader({style:
|
|
49
|
-
|
|
50
|
-
width: `${width}%`
|
|
51
|
-
}})}
|
|
52
|
-
{...table.columnProps(column)}
|
|
57
|
+
style={styleForHeader({style: actualStyle})}
|
|
58
|
+
{...restColumnProps}
|
|
53
59
|
>
|
|
54
60
|
<View style={{display: "flex", flexDirection: "row", alignItems: "center"}}>
|
|
55
61
|
{tableSettingColumn.hasSortKey() && query &&
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {Text, View} from "react-native"
|
|
2
|
+
import BaseComponent from "../base-component"
|
|
3
|
+
import classNames from "classnames"
|
|
4
|
+
import Column from "./components/column"
|
|
5
|
+
import ColumnContent from "./column-content"
|
|
6
|
+
import columnIdentifier from "./column-identifier.mjs"
|
|
7
|
+
import PropTypes from "prop-types"
|
|
8
|
+
import propTypesExact from "prop-types-exact"
|
|
9
|
+
import {memo} from "react"
|
|
10
|
+
import {shapeComponent} from "set-state-compare/src/shape-component"
|
|
11
|
+
|
|
12
|
+
export default memo(shapeComponent(class ApiMakerTableModelColumn extends BaseComponent {
|
|
13
|
+
static propTypes = propTypesExact({
|
|
14
|
+
column: PropTypes.object.isRequired,
|
|
15
|
+
columnIndex: PropTypes.number.isRequired,
|
|
16
|
+
even: PropTypes.bool.isRequired,
|
|
17
|
+
isSmallScreen: PropTypes.bool.isRequired,
|
|
18
|
+
model: PropTypes.object.isRequired,
|
|
19
|
+
table: PropTypes.object.isRequired,
|
|
20
|
+
tableSettingColumn: PropTypes.object.isRequired,
|
|
21
|
+
width: PropTypes.number.isRequired
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
render() {
|
|
25
|
+
const {column, columnIndex, even, isSmallScreen, model, table, width} = this.props
|
|
26
|
+
const columnProps = table.columnProps(column)
|
|
27
|
+
const {style, ...restColumnProps} = columnProps
|
|
28
|
+
const actualStyle = Object.assign(
|
|
29
|
+
table.styleForColumn({column, columnIndex, even, style: {width}}),
|
|
30
|
+
style
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Column
|
|
35
|
+
dataSet={{
|
|
36
|
+
class: classNames(this.columnClassNamesForColumn(column)),
|
|
37
|
+
identifier: columnIdentifier(column)
|
|
38
|
+
}}
|
|
39
|
+
style={actualStyle}
|
|
40
|
+
{...restColumnProps}
|
|
41
|
+
>
|
|
42
|
+
{isSmallScreen &&
|
|
43
|
+
<View dataSet={{class: "table--column-label"}}>
|
|
44
|
+
<Text>
|
|
45
|
+
{table.headerLabelForColumn(column)}
|
|
46
|
+
</Text>
|
|
47
|
+
</View>
|
|
48
|
+
}
|
|
49
|
+
<View dataSet={{class: "table--column-value"}}>
|
|
50
|
+
{new ColumnContent({column, model, table}).content()}
|
|
51
|
+
</View>
|
|
52
|
+
</Column>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
columnClassNamesForColumn(column) {
|
|
57
|
+
const classNames = ["table--column"]
|
|
58
|
+
|
|
59
|
+
if (column.commonProps && column.commonProps.className) classNames.push(column.commonProps.className)
|
|
60
|
+
if (column.columnProps && column.columnProps.className) classNames.push(column.columnProps.className)
|
|
61
|
+
|
|
62
|
+
return classNames
|
|
63
|
+
}
|
|
64
|
+
}))
|
package/src/table/model-row.jsx
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {Pressable
|
|
1
|
+
import {Pressable} from "react-native"
|
|
2
2
|
import BaseComponent from "../base-component"
|
|
3
|
-
import classNames from "classnames"
|
|
4
3
|
import Column from "./components/column"
|
|
5
|
-
import ColumnContent from "./column-content"
|
|
6
4
|
import columnIdentifier from "./column-identifier.mjs"
|
|
7
5
|
import columnVisible from "./column-visible.mjs"
|
|
8
6
|
import FontAwesomeIcon from "react-native-vector-icons/FontAwesome"
|
|
9
7
|
import * as inflection from "inflection"
|
|
10
8
|
import modelCallbackArgs from "./model-callback-args.mjs"
|
|
11
9
|
import Link from "../link"
|
|
10
|
+
import ModelColumn from "./model-column"
|
|
12
11
|
import PropTypes from "prop-types"
|
|
13
12
|
import propTypesExact from "prop-types-exact"
|
|
14
13
|
import Row from "./components/row"
|
|
@@ -86,39 +85,21 @@ export default memo(shapeComponent(class ApiMakerBootStrapLiveTableModelRow exte
|
|
|
86
85
|
)
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
columnClassNamesForColumn(column) {
|
|
90
|
-
const classNames = ["table--column"]
|
|
91
|
-
|
|
92
|
-
if (column.commonProps && column.commonProps.className) classNames.push(column.commonProps.className)
|
|
93
|
-
if (column.columnProps && column.columnProps.className) classNames.push(column.columnProps.className)
|
|
94
|
-
|
|
95
|
-
return classNames
|
|
96
|
-
}
|
|
97
|
-
|
|
98
88
|
columnsContentFromColumns(model, even) {
|
|
99
89
|
const {isSmallScreen, table, preparedColumns} = this.p
|
|
100
90
|
|
|
101
91
|
return preparedColumns?.map(({column, tableSettingColumn, width}, columnIndex) => columnVisible(column, tableSettingColumn) &&
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
92
|
+
<ModelColumn
|
|
93
|
+
column={column}
|
|
94
|
+
columnIndex={columnIndex}
|
|
95
|
+
even={even}
|
|
96
|
+
isSmallScreen={isSmallScreen}
|
|
107
97
|
key={columnIdentifier(column)}
|
|
108
|
-
|
|
109
|
-
{
|
|
110
|
-
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
<Text>
|
|
114
|
-
{table.headerLabelForColumn(column)}
|
|
115
|
-
</Text>
|
|
116
|
-
</View>
|
|
117
|
-
}
|
|
118
|
-
<View dataSet={{class: "table--column-value"}}>
|
|
119
|
-
{new ColumnContent({column, model, table}).content()}
|
|
120
|
-
</View>
|
|
121
|
-
</Column>
|
|
98
|
+
model={model}
|
|
99
|
+
table={table}
|
|
100
|
+
tableSettingColumn={tableSettingColumn}
|
|
101
|
+
width={width}
|
|
102
|
+
/>
|
|
122
103
|
)
|
|
123
104
|
}
|
|
124
105
|
|
|
@@ -4,7 +4,7 @@ import PropTypes from "prop-types"
|
|
|
4
4
|
import propTypesExact from "prop-types-exact"
|
|
5
5
|
import {memo, useEffect, useRef} from "react"
|
|
6
6
|
import {shapeComponent} from "set-state-compare/src/shape-component.js"
|
|
7
|
-
import {View} from "react-native"
|
|
7
|
+
import {Text, View} from "react-native"
|
|
8
8
|
|
|
9
9
|
export default memo(shapeComponent(class ColumnRow extends BaseComponent {
|
|
10
10
|
static propTypes = propTypesExact({
|
|
@@ -43,7 +43,9 @@ export default memo(shapeComponent(class ColumnRow extends BaseComponent {
|
|
|
43
43
|
type="checkbox"
|
|
44
44
|
{...checkboxProps}
|
|
45
45
|
/>
|
|
46
|
-
|
|
46
|
+
<Text>
|
|
47
|
+
{table.headerLabelForColumn(column)}
|
|
48
|
+
</Text>
|
|
47
49
|
</label>
|
|
48
50
|
</View>
|
|
49
51
|
)
|
|
@@ -16,10 +16,6 @@ export default memo(shapeComponent(class ApiMakerTableSettings extends BaseCompo
|
|
|
16
16
|
|
|
17
17
|
setup() {
|
|
18
18
|
this.rootRef = useRef()
|
|
19
|
-
|
|
20
|
-
this.useStates({
|
|
21
|
-
fixedTableLayout: this.tableSetting().fixedTableLayout()
|
|
22
|
-
})
|
|
23
19
|
}
|
|
24
20
|
|
|
25
21
|
tableSetting = () => this.p.table.s.tableSetting
|
package/src/table/table.jsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import "./style"
|
|
2
1
|
import {digg, digs} from "diggerize"
|
|
3
|
-
import {Pressable, View} from "react-native"
|
|
2
|
+
import {Pressable, StyleSheet, Text, View} from "react-native"
|
|
4
3
|
import BaseComponent from "../base-component"
|
|
5
4
|
import Card from "../bootstrap/card"
|
|
6
5
|
import classNames from "classnames"
|
|
@@ -28,15 +27,25 @@ import TableSettings from "./table-settings"
|
|
|
28
27
|
import uniqunize from "uniqunize"
|
|
29
28
|
import useBreakpoint from "../use-breakpoint"
|
|
30
29
|
import useCollection from "../use-collection"
|
|
30
|
+
import useI18n from "i18n-on-steroids/src/use-i18n.mjs"
|
|
31
|
+
import useModelEvent from "../use-model-event.js"
|
|
31
32
|
import useQueryParams from "on-location-changed/src/use-query-params.js"
|
|
32
33
|
import Widths from "./widths"
|
|
33
34
|
|
|
34
35
|
const paginationOptions = [30, 60, 90, ["All", "all"]]
|
|
35
36
|
const WorkerPluginsCheckAllCheckbox = React.lazy(() => import("./worker-plugins-check-all-checkbox"))
|
|
37
|
+
const styleSheet = StyleSheet.create({
|
|
38
|
+
flatList: {
|
|
39
|
+
border: "1px solid #dbdbdb",
|
|
40
|
+
borderRadius: 5,
|
|
41
|
+
overflowX: "auto"
|
|
42
|
+
}
|
|
43
|
+
})
|
|
36
44
|
|
|
37
45
|
export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
38
46
|
static defaultProps = {
|
|
39
47
|
card: true,
|
|
48
|
+
currentUser: null,
|
|
40
49
|
destroyEnabled: true,
|
|
41
50
|
filterCard: true,
|
|
42
51
|
filterSubmitButton: true,
|
|
@@ -85,14 +94,18 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
85
94
|
workplace: PropTypes.bool.isRequired
|
|
86
95
|
}
|
|
87
96
|
|
|
97
|
+
tableSetting = null
|
|
98
|
+
|
|
88
99
|
setup() {
|
|
100
|
+
const {t} = useI18n({namespace: "js.api_maker.table"})
|
|
89
101
|
const {breakpoint} = useBreakpoint()
|
|
90
102
|
const queryParams = useQueryParams()
|
|
91
103
|
|
|
92
104
|
this.setInstance({
|
|
93
105
|
breakpoint,
|
|
94
106
|
filterFormRef: useRef(),
|
|
95
|
-
isSmallScreen: breakpoint == "xs" || breakpoint == "sm"
|
|
107
|
+
isSmallScreen: breakpoint == "xs" || breakpoint == "sm",
|
|
108
|
+
t
|
|
96
109
|
})
|
|
97
110
|
|
|
98
111
|
const collectionKey = digg(this.p.modelClass.modelClassData(), "collectionKey")
|
|
@@ -106,7 +119,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
106
119
|
this.useStates({
|
|
107
120
|
columns: columnsAsArray,
|
|
108
121
|
currentWorkplace: undefined,
|
|
109
|
-
|
|
122
|
+
currentWorkplaceCount: null,
|
|
110
123
|
identifier: () => this.props.identifier || `${collectionKey}-default`,
|
|
111
124
|
lastUpdate: () => new Date(),
|
|
112
125
|
preload: undefined,
|
|
@@ -119,17 +132,28 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
119
132
|
showFilters: () => Boolean(queryParams[querySName]),
|
|
120
133
|
showSettings: false,
|
|
121
134
|
tableSetting: undefined,
|
|
135
|
+
tableSettingLoaded: false,
|
|
122
136
|
tableSettingFullCacheKey: undefined,
|
|
137
|
+
width: undefined,
|
|
123
138
|
widths: null
|
|
124
139
|
})
|
|
125
140
|
|
|
126
141
|
useMemo(() => {
|
|
127
|
-
this.loadTableSetting()
|
|
128
|
-
|
|
129
142
|
if (this.props.workplace) {
|
|
130
|
-
this.loadCurrentWorkplace()
|
|
143
|
+
this.loadCurrentWorkplace().then(() => {
|
|
144
|
+
this.loadCurrentWorkplaceCount()
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
}, [this.p.currentUser?.id()])
|
|
148
|
+
|
|
149
|
+
useMemo(() => {
|
|
150
|
+
if (!this.tt.tableSetting && this.s.width) {
|
|
151
|
+
this.loadTableSetting()
|
|
131
152
|
}
|
|
132
|
-
}, [])
|
|
153
|
+
}, [this.p.currentUser?.id(), this.s.width])
|
|
154
|
+
|
|
155
|
+
useModelEvent(this.s.currentWorkplace, "workplace_links_created", this.tt.onLinksCreated)
|
|
156
|
+
useModelEvent(this.s.currentWorkplace, "workplace_links_destroyed", this.tt.onLinksDestroyed)
|
|
133
157
|
|
|
134
158
|
let collectionReady = true
|
|
135
159
|
let select
|
|
@@ -169,18 +193,31 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
169
193
|
this.setState({currentWorkplace})
|
|
170
194
|
}
|
|
171
195
|
|
|
196
|
+
async loadCurrentWorkplaceCount() {
|
|
197
|
+
const WorkplaceLink = modelClassRequire("WorkplaceLink")
|
|
198
|
+
const currentWorkplaceCount = await WorkplaceLink
|
|
199
|
+
.ransack({
|
|
200
|
+
resource_type_eq: this.p.modelClass.modelClassData().name,
|
|
201
|
+
workplace_id_eq: this.s.currentWorkplace.id()
|
|
202
|
+
})
|
|
203
|
+
.count()
|
|
204
|
+
|
|
205
|
+
this.setState({currentWorkplaceCount})
|
|
206
|
+
}
|
|
207
|
+
|
|
172
208
|
async loadTableSetting() {
|
|
173
209
|
this.tableSettings = new TableSettings({table: this})
|
|
174
210
|
|
|
175
211
|
const tableSetting = await this.tableSettings.loadExistingOrCreateTableSettings()
|
|
176
212
|
const {columns, preload} = this.tableSettings.preparedColumns(tableSetting)
|
|
177
|
-
const {
|
|
178
|
-
const widths = new Widths({columns,
|
|
213
|
+
const {width} = this.s
|
|
214
|
+
const widths = new Widths({columns, table: this, width})
|
|
179
215
|
|
|
180
216
|
this.setState({
|
|
181
217
|
preparedColumns: columns,
|
|
182
218
|
preload: this.mergedPreloads(preload),
|
|
183
219
|
tableSetting,
|
|
220
|
+
tableSettingLoaded: true,
|
|
184
221
|
tableSettingFullCacheKey: tableSetting.fullCacheKey(),
|
|
185
222
|
widths
|
|
186
223
|
})
|
|
@@ -237,7 +274,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
237
274
|
}
|
|
238
275
|
|
|
239
276
|
return (
|
|
240
|
-
<
|
|
277
|
+
<View dataSet={{class: this.className()}} onLayout={this.tt.onContainerLayout} style={this.props.styles?.container}>
|
|
241
278
|
{showNoRecordsAvailableContent &&
|
|
242
279
|
<div className="live-table--no-records-available-content">
|
|
243
280
|
{noRecordsAvailableContent({models, qParams, overallCount})}
|
|
@@ -254,7 +291,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
254
291
|
{qParams && query && result && models && !showNoRecordsAvailableContent && !showNoRecordsFoundContent &&
|
|
255
292
|
this.cardOrTable()
|
|
256
293
|
}
|
|
257
|
-
</
|
|
294
|
+
</View>
|
|
258
295
|
)
|
|
259
296
|
}
|
|
260
297
|
|
|
@@ -354,10 +391,9 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
354
391
|
extraData={this.s.lastUpdate}
|
|
355
392
|
keyExtractor={this.tt.keyExtrator}
|
|
356
393
|
ListHeaderComponent={this.tt.listHeaderComponent}
|
|
357
|
-
onLayout={this.tt.onFlatListLayout}
|
|
358
394
|
renderItem={this.tt.renderItem}
|
|
359
395
|
showsHorizontalScrollIndicator
|
|
360
|
-
style={
|
|
396
|
+
style={styleSheet.flatList}
|
|
361
397
|
{...restProps}
|
|
362
398
|
/>
|
|
363
399
|
)
|
|
@@ -394,12 +430,36 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
394
430
|
)
|
|
395
431
|
}
|
|
396
432
|
|
|
397
|
-
|
|
433
|
+
onContainerLayout = (e) => {
|
|
398
434
|
const {width} = e.nativeEvent.layout
|
|
399
435
|
const {widths} = this.s
|
|
400
436
|
|
|
401
|
-
this.setState({
|
|
402
|
-
widths.
|
|
437
|
+
this.setState({width})
|
|
438
|
+
if (widths) widths.tableWidth = width
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
onLinksCreated = ({args}) => {
|
|
442
|
+
const modelClassName = this.p.modelClass.modelClassData().name
|
|
443
|
+
|
|
444
|
+
if (args.created[modelClassName]) {
|
|
445
|
+
const amountCreated = args.created[modelClassName].length
|
|
446
|
+
|
|
447
|
+
this.setState((prevState) => ({
|
|
448
|
+
currentWorkplaceCount: prevState.currentWorkplaceCount + amountCreated
|
|
449
|
+
}))
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
onLinksDestroyed = ({args}) => {
|
|
454
|
+
const modelClassName = this.p.modelClass.modelClassData().name
|
|
455
|
+
|
|
456
|
+
if (args.destroyed[modelClassName]) {
|
|
457
|
+
const amountDestroyed = args.destroyed[modelClassName].length
|
|
458
|
+
|
|
459
|
+
this.setState((prevState) => ({
|
|
460
|
+
currentWorkplaceCount: prevState.currentWorkplaceCount - amountDestroyed
|
|
461
|
+
}))
|
|
462
|
+
}
|
|
403
463
|
}
|
|
404
464
|
|
|
405
465
|
keyExtrator = (model) => model.id()
|
|
@@ -425,7 +485,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
425
485
|
className="btn btn-primary live-table--submit-filter-button"
|
|
426
486
|
type="submit"
|
|
427
487
|
style={{marginTop: "8px"}}
|
|
428
|
-
value={filterSubmitLabel ||
|
|
488
|
+
value={filterSubmitLabel || this.t(".filter", {defaultValue: "Filter"})}
|
|
429
489
|
/>
|
|
430
490
|
}
|
|
431
491
|
</form>
|
|
@@ -449,16 +509,14 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
449
509
|
}
|
|
450
510
|
|
|
451
511
|
listHeaderComponent = () => {
|
|
452
|
-
const {workplace} = this.p
|
|
453
|
-
const {currentWorkplace} = this.s
|
|
454
512
|
const {query} = digs(this.collection, "query")
|
|
455
513
|
|
|
456
514
|
return (
|
|
457
515
|
<Row dataSet={{class: "live-table-header-row"}} style={this.styleForRow()}>
|
|
458
|
-
{workplace && currentWorkplace &&
|
|
516
|
+
{this.p.workplace && this.s.currentWorkplace &&
|
|
459
517
|
<Header style={this.styleForHeader({style: {width: 41}})}>
|
|
460
518
|
<WorkerPluginsCheckAllCheckbox
|
|
461
|
-
currentWorkplace={currentWorkplace}
|
|
519
|
+
currentWorkplace={this.s.currentWorkplace}
|
|
462
520
|
query={query}
|
|
463
521
|
style={{marginHorizontal: "auto"}}
|
|
464
522
|
/>
|
|
@@ -473,6 +531,16 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
473
531
|
renderItem = ({index, item: model}) => {
|
|
474
532
|
const {preparedColumns, tableSettingFullCacheKey} = this.s
|
|
475
533
|
|
|
534
|
+
if (!this.s.tableSettingLoaded) {
|
|
535
|
+
return (
|
|
536
|
+
<View>
|
|
537
|
+
<Text>
|
|
538
|
+
Loading...
|
|
539
|
+
</Text>
|
|
540
|
+
</View>
|
|
541
|
+
)
|
|
542
|
+
}
|
|
543
|
+
|
|
476
544
|
return (
|
|
477
545
|
<ModelRow
|
|
478
546
|
cacheKey={model.cacheKey()}
|
|
@@ -492,7 +560,8 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
492
560
|
const defaultStyle = {
|
|
493
561
|
justifyContent: "center",
|
|
494
562
|
padding: 8,
|
|
495
|
-
backgroundColor: even ? "#f5f5f5" : undefined
|
|
563
|
+
backgroundColor: even ? "#f5f5f5" : undefined,
|
|
564
|
+
overflow: "hidden"
|
|
496
565
|
}
|
|
497
566
|
|
|
498
567
|
if (type == "actions") {
|
|
@@ -576,24 +645,31 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
576
645
|
const totalCount = result.totalCount()
|
|
577
646
|
const perPage = result.perPage()
|
|
578
647
|
const to = Math.min(currentPage * perPage, totalCount)
|
|
579
|
-
const defaultValue = "Showing %{from} to %{to} out of %{total_count} total"
|
|
648
|
+
const defaultValue = "Showing %{from} to %{to} out of %{total_count} total."
|
|
580
649
|
let from = ((currentPage - 1) * perPage) + 1
|
|
581
650
|
|
|
582
651
|
if (to === 0) from = 0
|
|
583
652
|
|
|
584
653
|
return (
|
|
585
|
-
<View style={{flexDirection: "row", justifyContent: "space-between", marginTop:
|
|
586
|
-
<
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
654
|
+
<View style={{flexDirection: "row", justifyContent: "space-between", marginTop: 10}}>
|
|
655
|
+
<View dataSet={{class: "showing-counts"}} style={{flexDirection: "row"}}>
|
|
656
|
+
<Text>
|
|
657
|
+
{this.t(".showing_from_to_out_of_total", {defaultValue, from, to, total_count: totalCount})}
|
|
658
|
+
</Text>
|
|
659
|
+
{this.p.workplace && this.s.currentWorkplaceCount !== null &&
|
|
660
|
+
<Text style={{marginLeft: 3}}>
|
|
661
|
+
{this.t(".x_selected", {defaultValue: "%{selected} selected.", selected: this.s.currentWorkplaceCount})}
|
|
662
|
+
</Text>
|
|
663
|
+
}
|
|
664
|
+
</View>
|
|
665
|
+
<View>
|
|
590
666
|
<Select
|
|
591
667
|
className="per-page-select"
|
|
592
668
|
defaultValue={perPage}
|
|
593
669
|
onChange={this.tt.onPerPageChanged}
|
|
594
670
|
options={paginationOptions}
|
|
595
671
|
/>
|
|
596
|
-
</
|
|
672
|
+
</View>
|
|
597
673
|
</View>
|
|
598
674
|
)
|
|
599
675
|
}
|
|
@@ -611,8 +687,15 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
611
687
|
columnProps(column) {
|
|
612
688
|
const props = {}
|
|
613
689
|
|
|
614
|
-
if (column.textCenter)
|
|
615
|
-
|
|
690
|
+
if (column.textCenter) {
|
|
691
|
+
props.style ||= {}
|
|
692
|
+
props.style.textAlign = "center"
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (column.textRight) {
|
|
696
|
+
props.style ||= {}
|
|
697
|
+
props.style.textAlign = "right"
|
|
698
|
+
}
|
|
616
699
|
|
|
617
700
|
return props
|
|
618
701
|
}
|
|
@@ -639,7 +722,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
639
722
|
/>
|
|
640
723
|
)
|
|
641
724
|
|
|
642
|
-
headerClassNameForColumn
|
|
725
|
+
headerClassNameForColumn(column) {
|
|
643
726
|
const classNames = ["live-table-header"]
|
|
644
727
|
|
|
645
728
|
if (column.commonProps && column.commonProps.className) classNames.push(column.commonProps.className)
|
|
@@ -648,7 +731,7 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
648
731
|
return classNames
|
|
649
732
|
}
|
|
650
733
|
|
|
651
|
-
headerLabelForColumn
|
|
734
|
+
headerLabelForColumn(column) {
|
|
652
735
|
const {modelClass} = this.p
|
|
653
736
|
|
|
654
737
|
if ("label" in column) {
|
package/src/table/widths.mjs
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import {digg} from "diggerize"
|
|
2
2
|
|
|
3
3
|
export default class TableWidths {
|
|
4
|
-
constructor({columns,
|
|
4
|
+
constructor({columns, table, width}) {
|
|
5
5
|
this.columns = columns
|
|
6
|
-
this.
|
|
6
|
+
this.tableWidth = width
|
|
7
7
|
this.table = table
|
|
8
8
|
this.setWidths()
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
setWidths() {
|
|
12
|
-
let widthLeft = 100.0
|
|
13
|
-
|
|
14
12
|
this.columnsWidths = {}
|
|
15
13
|
|
|
14
|
+
let widthLeft = this.tableWidth
|
|
16
15
|
const updateData = []
|
|
17
16
|
|
|
18
17
|
// Set widths that are defined
|
|
19
18
|
for (const columnIndex in this.columns) {
|
|
20
|
-
const column = this.columns[columnIndex]
|
|
19
|
+
const column = this.columns[columnIndex]
|
|
20
|
+
const tableSettingColumn = column.tableSettingColumn
|
|
21
21
|
|
|
22
|
-
if (
|
|
23
|
-
|
|
22
|
+
if (tableSettingColumn.hasWidth()) {
|
|
23
|
+
column.width = tableSettingColumn.width()
|
|
24
24
|
|
|
25
|
-
widthLeft -=
|
|
25
|
+
widthLeft -= tableSettingColumn.width()
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -36,21 +36,26 @@ export default class TableWidths {
|
|
|
36
36
|
|
|
37
37
|
// Set widths of columns without
|
|
38
38
|
for (const columnIndex in this.columns) {
|
|
39
|
-
const column = this.columns[columnIndex]
|
|
39
|
+
const column = this.columns[columnIndex]
|
|
40
|
+
const tableSettingColumn = column.tableSettingColumn
|
|
41
|
+
|
|
42
|
+
if (!tableSettingColumn.hasWidth()) {
|
|
43
|
+
let newWidth = widthLeft / amountOfColumns
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
const newWidth = widthLeft / amountOfColumns
|
|
45
|
+
if (newWidth < 200) newWidth = 200
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
column.width = newWidth
|
|
45
48
|
|
|
46
49
|
updateData << {
|
|
47
|
-
id:
|
|
50
|
+
id: tableSettingColumn.id(),
|
|
48
51
|
width: newWidth
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
if (updateData.length > 0) {
|
|
57
|
+
// FIXME: Should update the columns on the backend if anything changed
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
getWidthOfColumn(identifier) {
|
|
@@ -66,12 +71,8 @@ export default class TableWidths {
|
|
|
66
71
|
|
|
67
72
|
if (!column) throw new Error(`No such column: ${identifier}`)
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
column.width = widthPercent
|
|
74
|
+
column.width = width
|
|
72
75
|
|
|
73
76
|
this.table.setState({lastUpdate: new Date()})
|
|
74
|
-
|
|
75
|
-
// FIXME: Should reduce / enlarge sibling columns to keep a 100% fit
|
|
76
77
|
}
|
|
77
78
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import BaseComponent from "../base-component"
|
|
1
2
|
import classNames from "classnames"
|
|
2
3
|
import {digg} from "diggerize"
|
|
3
|
-
import EventConnection from "../event-connection"
|
|
4
4
|
import modelClassRequire from "../model-class-require.mjs"
|
|
5
5
|
import PropTypes from "prop-types"
|
|
6
6
|
import PropTypesExact from "prop-types-exact"
|
|
7
7
|
import {memo, useMemo} from "react"
|
|
8
|
-
import {shapeComponent
|
|
8
|
+
import {shapeComponent} from "set-state-compare/src/shape-component"
|
|
9
|
+
import useModelEvent from "../use-model-event.js"
|
|
9
10
|
|
|
10
11
|
const Workplace = modelClassRequire("Workplace")
|
|
11
12
|
|
|
12
|
-
export default memo(shapeComponent(class ApiMakerTableWorkerPluginsCheckbox extends
|
|
13
|
+
export default memo(shapeComponent(class ApiMakerTableWorkerPluginsCheckbox extends BaseComponent {
|
|
13
14
|
static propTypes = PropTypesExact({
|
|
14
15
|
currentWorkplace: PropTypes.object,
|
|
15
16
|
model: PropTypes.object.isRequired,
|
|
@@ -25,6 +26,9 @@ export default memo(shapeComponent(class ApiMakerTableWorkerPluginsCheckbox exte
|
|
|
25
26
|
useMemo(() => {
|
|
26
27
|
this.loadCurrentLink()
|
|
27
28
|
}, [])
|
|
29
|
+
|
|
30
|
+
useModelEvent(this.p.currentWorkplace, "workplace_links_created", this.tt.onLinksCreated)
|
|
31
|
+
useModelEvent(this.p.currentWorkplace, "workplace_links_destroyed", this.tt.onLinksDestroyed)
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async loadCurrentLink() {
|
|
@@ -39,7 +43,7 @@ export default memo(shapeComponent(class ApiMakerTableWorkerPluginsCheckbox exte
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
render() {
|
|
42
|
-
const {className,
|
|
46
|
+
const {className, model, style} = this.props
|
|
43
47
|
const {checked, linkLoaded} = this.state
|
|
44
48
|
|
|
45
49
|
if (!linkLoaded) {
|
|
@@ -47,23 +51,15 @@ export default memo(shapeComponent(class ApiMakerTableWorkerPluginsCheckbox exte
|
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
return (
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
className={classNames("api-maker--table--worker-plugins-checkbox", className)}
|
|
60
|
-
data-checked={checked}
|
|
61
|
-
data-model-id={model.id()}
|
|
62
|
-
onChange={this.tt.onCheckedChanged}
|
|
63
|
-
style={style}
|
|
64
|
-
type="checkbox"
|
|
65
|
-
/>
|
|
66
|
-
</>
|
|
54
|
+
<input
|
|
55
|
+
checked={checked}
|
|
56
|
+
className={classNames("api-maker--table--worker-plugins-checkbox", className)}
|
|
57
|
+
data-checked={checked}
|
|
58
|
+
data-model-id={model.id()}
|
|
59
|
+
onChange={this.tt.onCheckedChanged}
|
|
60
|
+
style={style}
|
|
61
|
+
type="checkbox"
|
|
62
|
+
/>
|
|
67
63
|
)
|
|
68
64
|
}
|
|
69
65
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {useCallback, useLayoutEffect, useMemo} from "react"
|
|
2
|
+
import debounceFunction from "debounce"
|
|
3
|
+
import ModelEvents from "./model-events.mjs"
|
|
4
|
+
import useShape from "set-state-compare/src/use-shape.js"
|
|
5
|
+
|
|
6
|
+
const apiMakerUseModelEvent = (model, event, onCallback, props) => {
|
|
7
|
+
const {active = true, debounce, onConnected, ...restProps} = props || {}
|
|
8
|
+
|
|
9
|
+
if (Object.keys(restProps).length > 0) {
|
|
10
|
+
throw new Error(`Unknown props given to apiMakerUseModelEvent: ${Object.keys(restProps).join(", ")}`)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const s = useShape({active, debounce, model, onCallback})
|
|
14
|
+
|
|
15
|
+
const debounceCallback = useMemo(() => {
|
|
16
|
+
if (typeof debounce == "number") {
|
|
17
|
+
return debounceFunction(s.p.onCallback, debounce)
|
|
18
|
+
} else {
|
|
19
|
+
return debounceFunction(s.p.onCallback)
|
|
20
|
+
}
|
|
21
|
+
}, [debounce])
|
|
22
|
+
|
|
23
|
+
s.updateMeta({debounceCallback})
|
|
24
|
+
|
|
25
|
+
const onCallbackCallback = useCallback((...args) => {
|
|
26
|
+
if (!s.p.active) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (s.p.debounce) {
|
|
31
|
+
s.m.debounceCallback(...args)
|
|
32
|
+
} else {
|
|
33
|
+
s.p.onCallback(...args)
|
|
34
|
+
}
|
|
35
|
+
}, [])
|
|
36
|
+
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
let connectEvent, onConnectedListener
|
|
39
|
+
|
|
40
|
+
if (model) {
|
|
41
|
+
connectEvent = ModelEvents.connect(model, event, onCallbackCallback)
|
|
42
|
+
|
|
43
|
+
if (onConnected) {
|
|
44
|
+
onConnectedListener = connectEvent.events.addListener("connected", onConnected)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return () => {
|
|
49
|
+
if (onConnectedListener) {
|
|
50
|
+
connectEvent.events.removeListener("connected", onConnected)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (connectEvent) {
|
|
54
|
+
connectEvent.unsubscribe()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}, [model?.id()])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default apiMakerUseModelEvent
|
package/src/table/style.scss
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
@import "./variables";
|
|
2
|
-
|
|
3
|
-
.api-maker--table {
|
|
4
|
-
&[data-fixed-table-layout="true"] {
|
|
5
|
-
table {
|
|
6
|
-
table-layout: fixed;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.live-table-header {
|
|
11
|
-
text-align: left;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@media (max-width: $sm-to) {
|
|
15
|
-
.live-table-column {
|
|
16
|
-
display: flex;
|
|
17
|
-
justify-content: space-between;
|
|
18
|
-
|
|
19
|
-
.live-table-column-value {
|
|
20
|
-
text-align: right;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.live-table-header-row {
|
|
25
|
-
margin-bottom: 15px;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.live-table-row {
|
|
29
|
-
+ .live-table-row {
|
|
30
|
-
margin-top: 15px;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@media (min-width: $md-from) {
|
|
36
|
-
.actions-column {
|
|
37
|
-
display: flex;
|
|
38
|
-
align-items: center;
|
|
39
|
-
justify-content: end;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.live-table-header:not(:first-child),
|
|
43
|
-
.live-table-column:not(:first-child) {
|
|
44
|
-
padding-left: 10px;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.live-table-header:not(:last-child),
|
|
48
|
-
.live-table-column:not(:last-child) {
|
|
49
|
-
padding-right: 10px;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.live-table-column {
|
|
53
|
-
&[data-text-align="center"] {
|
|
54
|
-
.live-table-column-value {
|
|
55
|
-
text-align: center;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
&[data-text-align="right"] {
|
|
60
|
-
.live-table-column-value {
|
|
61
|
-
text-align: right;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.live-table-header {
|
|
67
|
-
&[data-text-align="center"] {
|
|
68
|
-
text-align: center;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
&[data-text-align="right"] {
|
|
72
|
-
text-align: right;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|