@budibase/frontend-core 2.9.38 → 2.9.39-alpha.0
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 +4 -4
- package/src/api/groups.js +22 -0
- package/src/api/index.js +2 -0
- package/src/api/permissions.js +23 -0
- package/src/api/rows.js +22 -3
- package/src/api/user.js +27 -4
- package/src/api/viewsV2.js +72 -0
- package/src/components/grid/cells/DataCell.svelte +8 -3
- package/src/components/grid/cells/GutterCell.svelte +4 -4
- package/src/components/grid/cells/HeaderCell.svelte +3 -3
- package/src/components/grid/controls/HideColumnsButton.svelte +10 -7
- package/src/components/grid/controls/SizeButton.svelte +10 -4
- package/src/components/grid/controls/SortButton.svelte +12 -34
- package/src/components/grid/layout/Grid.svelte +22 -17
- package/src/components/grid/layout/GridBody.svelte +2 -2
- package/src/components/grid/layout/HeaderRow.svelte +3 -4
- package/src/components/grid/layout/NewColumnButton.svelte +3 -2
- package/src/components/grid/layout/NewRow.svelte +6 -6
- package/src/components/grid/layout/StickyColumn.svelte +2 -2
- package/src/components/grid/lib/websocket.js +18 -12
- package/src/components/grid/overlays/KeyboardManager.svelte +12 -11
- package/src/components/grid/overlays/MenuOverlay.svelte +3 -6
- package/src/components/grid/stores/clipboard.js +1 -1
- package/src/components/grid/stores/columns.js +39 -99
- package/src/components/grid/stores/config.js +33 -6
- package/src/components/grid/stores/datasource.js +131 -0
- package/src/components/grid/stores/filter.js +2 -2
- package/src/components/grid/stores/index.js +14 -3
- package/src/components/grid/stores/menu.js +1 -1
- package/src/components/grid/stores/pagination.js +3 -4
- package/src/components/grid/stores/reorder.js +1 -1
- package/src/components/grid/stores/resize.js +1 -1
- package/src/components/grid/stores/rows.js +61 -101
- package/src/components/grid/stores/sort.js +29 -6
- package/src/components/grid/stores/table.js +129 -0
- package/src/components/grid/stores/ui.js +24 -36
- package/src/components/grid/stores/users.js +8 -1
- package/src/components/grid/stores/viewV2.js +212 -0
- package/src/components/grid/stores/viewport.js +4 -4
- package/src/constants.js +21 -13
- package/src/fetch/DataFetch.js +35 -24
- package/src/fetch/QueryFetch.js +4 -0
- package/src/fetch/ViewV2Fetch.js +65 -0
- package/src/fetch/fetchData.js +2 -0
- package/src/utils/roles.js +5 -3
|
@@ -15,16 +15,20 @@ import * as Config from "./config"
|
|
|
15
15
|
import * as Sort from "./sort"
|
|
16
16
|
import * as Filter from "./filter"
|
|
17
17
|
import * as Notifications from "./notifications"
|
|
18
|
+
import * as Table from "./table"
|
|
19
|
+
import * as ViewV2 from "./viewV2"
|
|
20
|
+
import * as Datasource from "./datasource"
|
|
18
21
|
|
|
19
22
|
const DependencyOrderedStores = [
|
|
20
|
-
Config,
|
|
21
|
-
Notifications,
|
|
22
23
|
Sort,
|
|
23
24
|
Filter,
|
|
24
25
|
Bounds,
|
|
25
26
|
Scroll,
|
|
26
|
-
|
|
27
|
+
Table,
|
|
28
|
+
ViewV2,
|
|
29
|
+
Datasource,
|
|
27
30
|
Columns,
|
|
31
|
+
Rows,
|
|
28
32
|
UI,
|
|
29
33
|
Validation,
|
|
30
34
|
Resize,
|
|
@@ -34,6 +38,8 @@ const DependencyOrderedStores = [
|
|
|
34
38
|
Menu,
|
|
35
39
|
Pagination,
|
|
36
40
|
Clipboard,
|
|
41
|
+
Config,
|
|
42
|
+
Notifications,
|
|
37
43
|
]
|
|
38
44
|
|
|
39
45
|
export const attachStores = context => {
|
|
@@ -47,6 +53,11 @@ export const attachStores = context => {
|
|
|
47
53
|
context = { ...context, ...store.deriveStores?.(context) }
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
// Action creation
|
|
57
|
+
for (let store of DependencyOrderedStores) {
|
|
58
|
+
context = { ...context, ...store.createActions?.(context) }
|
|
59
|
+
}
|
|
60
|
+
|
|
50
61
|
// Initialise any store logic
|
|
51
62
|
for (let store of DependencyOrderedStores) {
|
|
52
63
|
store.initialise?.(context)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { derived } from "svelte/store"
|
|
1
|
+
import { derived, get } from "svelte/store"
|
|
2
2
|
|
|
3
3
|
export const initialise = context => {
|
|
4
4
|
const { scrolledRowCount, rows, visualRowCapacity } = context
|
|
@@ -11,13 +11,12 @@ export const initialise = context => {
|
|
|
11
11
|
[scrolledRowCount, rowCount, visualRowCapacity],
|
|
12
12
|
([$scrolledRowCount, $rowCount, $visualRowCapacity]) => {
|
|
13
13
|
return Math.max(0, $rowCount - $scrolledRowCount - $visualRowCapacity)
|
|
14
|
-
}
|
|
15
|
-
100
|
|
14
|
+
}
|
|
16
15
|
)
|
|
17
16
|
|
|
18
17
|
// Fetch next page when fewer than 25 remaining rows to scroll
|
|
19
18
|
remainingRows.subscribe(remaining => {
|
|
20
|
-
if (remaining < 25) {
|
|
19
|
+
if (remaining < 25 && get(rowCount)) {
|
|
21
20
|
rows.actions.loadNextPage()
|
|
22
21
|
}
|
|
23
22
|
})
|
|
@@ -3,30 +3,24 @@ import { fetchData } from "../../../fetch/fetchData"
|
|
|
3
3
|
import { NewRowID, RowPageSize } from "../lib/constants"
|
|
4
4
|
import { tick } from "svelte"
|
|
5
5
|
|
|
6
|
-
const SuppressErrors = true
|
|
7
|
-
|
|
8
6
|
export const createStores = () => {
|
|
9
7
|
const rows = writable([])
|
|
10
|
-
const table = writable(null)
|
|
11
8
|
const loading = writable(false)
|
|
12
9
|
const loaded = writable(false)
|
|
13
10
|
const rowChangeCache = writable({})
|
|
14
11
|
const inProgressChanges = writable({})
|
|
15
12
|
const hasNextPage = writable(false)
|
|
16
13
|
const error = writable(null)
|
|
14
|
+
const fetch = writable(null)
|
|
17
15
|
|
|
18
16
|
// Generate a lookup map to quick find a row by ID
|
|
19
|
-
const rowLookupMap = derived(
|
|
20
|
-
|
|
21
|
-
$rows
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return map
|
|
27
|
-
},
|
|
28
|
-
{}
|
|
29
|
-
)
|
|
17
|
+
const rowLookupMap = derived(rows, $rows => {
|
|
18
|
+
let map = {}
|
|
19
|
+
for (let i = 0; i < $rows.length; i++) {
|
|
20
|
+
map[$rows[i]._id] = i
|
|
21
|
+
}
|
|
22
|
+
return map
|
|
23
|
+
})
|
|
30
24
|
|
|
31
25
|
// Mark loaded as true if we've ever stopped loading
|
|
32
26
|
let hasStartedLoading = false
|
|
@@ -38,10 +32,25 @@ export const createStores = () => {
|
|
|
38
32
|
}
|
|
39
33
|
})
|
|
40
34
|
|
|
35
|
+
// Enrich rows with an index property and any pending changes
|
|
36
|
+
const enrichedRows = derived(
|
|
37
|
+
[rows, rowChangeCache],
|
|
38
|
+
([$rows, $rowChangeCache]) => {
|
|
39
|
+
return $rows.map((row, idx) => ({
|
|
40
|
+
...row,
|
|
41
|
+
...$rowChangeCache[row._id],
|
|
42
|
+
__idx: idx,
|
|
43
|
+
}))
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
|
|
41
47
|
return {
|
|
42
|
-
rows
|
|
48
|
+
rows: {
|
|
49
|
+
...rows,
|
|
50
|
+
subscribe: enrichedRows.subscribe,
|
|
51
|
+
},
|
|
52
|
+
fetch,
|
|
43
53
|
rowLookupMap,
|
|
44
|
-
table,
|
|
45
54
|
loaded,
|
|
46
55
|
loading,
|
|
47
56
|
rowChangeCache,
|
|
@@ -51,15 +60,15 @@ export const createStores = () => {
|
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
export const
|
|
63
|
+
export const createActions = context => {
|
|
55
64
|
const {
|
|
56
65
|
rows,
|
|
57
66
|
rowLookupMap,
|
|
58
|
-
|
|
67
|
+
definition,
|
|
59
68
|
filter,
|
|
60
69
|
loading,
|
|
61
70
|
sort,
|
|
62
|
-
|
|
71
|
+
datasource,
|
|
63
72
|
API,
|
|
64
73
|
scroll,
|
|
65
74
|
validation,
|
|
@@ -71,37 +80,29 @@ export const deriveStores = context => {
|
|
|
71
80
|
hasNextPage,
|
|
72
81
|
error,
|
|
73
82
|
notifications,
|
|
83
|
+
fetch,
|
|
74
84
|
} = context
|
|
75
85
|
const instanceLoaded = writable(false)
|
|
76
|
-
const fetch = writable(null)
|
|
77
86
|
|
|
78
87
|
// Local cache of row IDs to speed up checking if a row exists
|
|
79
88
|
let rowCacheMap = {}
|
|
80
89
|
|
|
81
|
-
//
|
|
82
|
-
const enrichedRows = derived(
|
|
83
|
-
[rows, rowChangeCache],
|
|
84
|
-
([$rows, $rowChangeCache]) => {
|
|
85
|
-
return $rows.map((row, idx) => ({
|
|
86
|
-
...row,
|
|
87
|
-
...$rowChangeCache[row._id],
|
|
88
|
-
__idx: idx,
|
|
89
|
-
}))
|
|
90
|
-
},
|
|
91
|
-
[]
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
// Reset everything when table ID changes
|
|
90
|
+
// Reset everything when datasource changes
|
|
95
91
|
let unsubscribe = null
|
|
96
92
|
let lastResetKey = null
|
|
97
|
-
|
|
93
|
+
datasource.subscribe(async $datasource => {
|
|
98
94
|
// Unsub from previous fetch if one exists
|
|
99
95
|
unsubscribe?.()
|
|
100
96
|
fetch.set(null)
|
|
101
97
|
instanceLoaded.set(false)
|
|
102
98
|
loading.set(true)
|
|
103
99
|
|
|
104
|
-
//
|
|
100
|
+
// Abandon if we don't have a valid datasource
|
|
101
|
+
if (!datasource.actions.isDatasourceValid($datasource)) {
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Tick to allow other reactive logic to update stores when datasource changes
|
|
105
106
|
// before proceeding. This allows us to wipe filters etc if needed.
|
|
106
107
|
await tick()
|
|
107
108
|
const $filter = get(filter)
|
|
@@ -110,10 +111,7 @@ export const deriveStores = context => {
|
|
|
110
111
|
// Create new fetch model
|
|
111
112
|
const newFetch = fetchData({
|
|
112
113
|
API,
|
|
113
|
-
datasource:
|
|
114
|
-
type: "table",
|
|
115
|
-
tableId: $tableId,
|
|
116
|
-
},
|
|
114
|
+
datasource: $datasource,
|
|
117
115
|
options: {
|
|
118
116
|
filter: $filter,
|
|
119
117
|
sortColumn: $sort.column,
|
|
@@ -142,7 +140,7 @@ export const deriveStores = context => {
|
|
|
142
140
|
const previousResetKey = lastResetKey
|
|
143
141
|
lastResetKey = $fetch.resetKey
|
|
144
142
|
|
|
145
|
-
// If resetting rows due to a
|
|
143
|
+
// If resetting rows due to a datasource change, wipe data and wait for
|
|
146
144
|
// derived stores to compute. This prevents stale data being passed
|
|
147
145
|
// to cells when we save the new schema.
|
|
148
146
|
if (!$instanceLoaded && previousResetKey) {
|
|
@@ -152,16 +150,12 @@ export const deriveStores = context => {
|
|
|
152
150
|
|
|
153
151
|
// Reset state properties when dataset changes
|
|
154
152
|
if (!$instanceLoaded || resetRows) {
|
|
155
|
-
|
|
156
|
-
sort.set({
|
|
157
|
-
column: $fetch.sortColumn,
|
|
158
|
-
order: $fetch.sortOrder,
|
|
159
|
-
})
|
|
153
|
+
definition.set($fetch.definition)
|
|
160
154
|
}
|
|
161
155
|
|
|
162
156
|
// Reset scroll state when data changes
|
|
163
157
|
if (!$instanceLoaded) {
|
|
164
|
-
// Reset both top and left for a new
|
|
158
|
+
// Reset both top and left for a new datasource ID
|
|
165
159
|
instanceLoaded.set(true)
|
|
166
160
|
scroll.set({ top: 0, left: 0 })
|
|
167
161
|
} else if (resetRows) {
|
|
@@ -180,19 +174,6 @@ export const deriveStores = context => {
|
|
|
180
174
|
fetch.set(newFetch)
|
|
181
175
|
})
|
|
182
176
|
|
|
183
|
-
// Update fetch when filter or sort config changes
|
|
184
|
-
filter.subscribe($filter => {
|
|
185
|
-
get(fetch)?.update({
|
|
186
|
-
filter: $filter,
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
sort.subscribe($sort => {
|
|
190
|
-
get(fetch)?.update({
|
|
191
|
-
sortOrder: $sort.order,
|
|
192
|
-
sortColumn: $sort.column,
|
|
193
|
-
})
|
|
194
|
-
})
|
|
195
|
-
|
|
196
177
|
// Gets a row by ID
|
|
197
178
|
const getRow = id => {
|
|
198
179
|
const index = get(rowLookupMap)[id]
|
|
@@ -211,7 +192,7 @@ export const deriveStores = context => {
|
|
|
211
192
|
let erroredColumns = []
|
|
212
193
|
let missingColumns = []
|
|
213
194
|
for (let column of keys) {
|
|
214
|
-
if (
|
|
195
|
+
if (datasource.actions.canUseColumn(column)) {
|
|
215
196
|
erroredColumns.push(column)
|
|
216
197
|
} else {
|
|
217
198
|
missingColumns.push(column)
|
|
@@ -252,11 +233,9 @@ export const deriveStores = context => {
|
|
|
252
233
|
// Adds a new row
|
|
253
234
|
const addRow = async (row, idx, bubble = false) => {
|
|
254
235
|
try {
|
|
255
|
-
// Create row
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
SuppressErrors
|
|
259
|
-
)
|
|
236
|
+
// Create row. Spread row so we can mutate and enrich safely.
|
|
237
|
+
let newRow = { ...row }
|
|
238
|
+
newRow = await datasource.actions.addRow(newRow)
|
|
260
239
|
|
|
261
240
|
// Update state
|
|
262
241
|
if (idx != null) {
|
|
@@ -294,21 +273,6 @@ export const deriveStores = context => {
|
|
|
294
273
|
}
|
|
295
274
|
}
|
|
296
275
|
|
|
297
|
-
// Fetches a row by ID using the search endpoint
|
|
298
|
-
const fetchRow = async id => {
|
|
299
|
-
const res = await API.searchTable({
|
|
300
|
-
tableId: get(tableId),
|
|
301
|
-
limit: 1,
|
|
302
|
-
query: {
|
|
303
|
-
equal: {
|
|
304
|
-
_id: id,
|
|
305
|
-
},
|
|
306
|
-
},
|
|
307
|
-
paginate: false,
|
|
308
|
-
})
|
|
309
|
-
return res?.rows?.[0]
|
|
310
|
-
}
|
|
311
|
-
|
|
312
276
|
// Replaces a row in state with the newly defined row, handling updates,
|
|
313
277
|
// addition and deletion
|
|
314
278
|
const replaceRow = (id, row) => {
|
|
@@ -337,7 +301,7 @@ export const deriveStores = context => {
|
|
|
337
301
|
|
|
338
302
|
// Refreshes a specific row
|
|
339
303
|
const refreshRow = async id => {
|
|
340
|
-
const row = await
|
|
304
|
+
const row = await datasource.actions.getRow(id)
|
|
341
305
|
replaceRow(id, row)
|
|
342
306
|
}
|
|
343
307
|
|
|
@@ -347,7 +311,7 @@ export const deriveStores = context => {
|
|
|
347
311
|
}
|
|
348
312
|
|
|
349
313
|
// Patches a row with some changes
|
|
350
|
-
const updateRow = async (rowId, changes) => {
|
|
314
|
+
const updateRow = async (rowId, changes, options = { save: true }) => {
|
|
351
315
|
const $rows = get(rows)
|
|
352
316
|
const $rowLookupMap = get(rowLookupMap)
|
|
353
317
|
const index = $rowLookupMap[rowId]
|
|
@@ -377,16 +341,23 @@ export const deriveStores = context => {
|
|
|
377
341
|
},
|
|
378
342
|
}))
|
|
379
343
|
|
|
344
|
+
// Stop here if we don't want to persist the change
|
|
345
|
+
if (!options?.save) {
|
|
346
|
+
return
|
|
347
|
+
}
|
|
348
|
+
|
|
380
349
|
// Save change
|
|
381
350
|
try {
|
|
382
351
|
inProgressChanges.update(state => ({
|
|
383
352
|
...state,
|
|
384
353
|
[rowId]: true,
|
|
385
354
|
}))
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
355
|
+
|
|
356
|
+
// Update row
|
|
357
|
+
const saved = await datasource.actions.updateRow({
|
|
358
|
+
...row,
|
|
359
|
+
...get(rowChangeCache)[rowId],
|
|
360
|
+
})
|
|
390
361
|
|
|
391
362
|
// Update state after a successful change
|
|
392
363
|
if (saved?._id) {
|
|
@@ -412,8 +383,8 @@ export const deriveStores = context => {
|
|
|
412
383
|
}
|
|
413
384
|
|
|
414
385
|
// Updates a value of a row
|
|
415
|
-
const updateValue = async (rowId, column, value) => {
|
|
416
|
-
return await updateRow(rowId, { [column]: value })
|
|
386
|
+
const updateValue = async ({ rowId, column, value, save = true }) => {
|
|
387
|
+
return await updateRow(rowId, { [column]: value }, { save })
|
|
417
388
|
}
|
|
418
389
|
|
|
419
390
|
// Deletes an array of rows
|
|
@@ -426,10 +397,7 @@ export const deriveStores = context => {
|
|
|
426
397
|
rowsToDelete.forEach(row => {
|
|
427
398
|
delete row.__idx
|
|
428
399
|
})
|
|
429
|
-
await
|
|
430
|
-
tableId: get(tableId),
|
|
431
|
-
rows: rowsToDelete,
|
|
432
|
-
})
|
|
400
|
+
await datasource.actions.deleteRows(rowsToDelete)
|
|
433
401
|
|
|
434
402
|
// Update state
|
|
435
403
|
handleRemoveRows(rowsToDelete)
|
|
@@ -473,12 +441,6 @@ export const deriveStores = context => {
|
|
|
473
441
|
get(fetch)?.nextPage()
|
|
474
442
|
}
|
|
475
443
|
|
|
476
|
-
// Refreshes the schema of the data fetch subscription
|
|
477
|
-
const refreshTableDefinition = async () => {
|
|
478
|
-
const definition = await API.fetchTableDefinition(get(tableId))
|
|
479
|
-
table.set(definition)
|
|
480
|
-
}
|
|
481
|
-
|
|
482
444
|
// Checks if we have a row with a certain ID
|
|
483
445
|
const hasRow = id => {
|
|
484
446
|
if (id === NewRowID) {
|
|
@@ -498,7 +460,6 @@ export const deriveStores = context => {
|
|
|
498
460
|
})
|
|
499
461
|
|
|
500
462
|
return {
|
|
501
|
-
enrichedRows,
|
|
502
463
|
rows: {
|
|
503
464
|
...rows,
|
|
504
465
|
actions: {
|
|
@@ -513,7 +474,6 @@ export const deriveStores = context => {
|
|
|
513
474
|
refreshRow,
|
|
514
475
|
replaceRow,
|
|
515
476
|
refreshData,
|
|
516
|
-
refreshTableDefinition,
|
|
517
477
|
},
|
|
518
478
|
},
|
|
519
479
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { derived, get } from "svelte/store"
|
|
2
|
+
import { memo } from "../../../utils"
|
|
2
3
|
|
|
3
4
|
export const createStores = context => {
|
|
4
5
|
const { props } = context
|
|
6
|
+
const $props = get(props)
|
|
5
7
|
|
|
6
8
|
// Initialise to default props
|
|
7
|
-
const sort =
|
|
8
|
-
column: props.initialSortColumn,
|
|
9
|
-
order: props.initialSortOrder || "ascending",
|
|
9
|
+
const sort = memo({
|
|
10
|
+
column: $props.initialSortColumn,
|
|
11
|
+
order: $props.initialSortOrder || "ascending",
|
|
10
12
|
})
|
|
11
13
|
|
|
12
14
|
return {
|
|
@@ -15,13 +17,34 @@ export const createStores = context => {
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export const initialise = context => {
|
|
18
|
-
const { sort, initialSortColumn, initialSortOrder } = context
|
|
20
|
+
const { sort, initialSortColumn, initialSortOrder, definition } = context
|
|
19
21
|
|
|
20
22
|
// Reset sort when initial sort props change
|
|
21
23
|
initialSortColumn.subscribe(newSortColumn => {
|
|
22
24
|
sort.update(state => ({ ...state, column: newSortColumn }))
|
|
23
25
|
})
|
|
24
26
|
initialSortOrder.subscribe(newSortOrder => {
|
|
25
|
-
sort.update(state => ({ ...state, order: newSortOrder }))
|
|
27
|
+
sort.update(state => ({ ...state, order: newSortOrder || "ascending" }))
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// Derive if the current sort column exists in the schema
|
|
31
|
+
const sortColumnExists = derived(
|
|
32
|
+
[sort, definition],
|
|
33
|
+
([$sort, $definition]) => {
|
|
34
|
+
if (!$sort?.column || !$definition) {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
return $definition.schema?.[$sort.column] != null
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Clear sort state if our sort column does not exist
|
|
42
|
+
sortColumnExists.subscribe(exists => {
|
|
43
|
+
if (!exists) {
|
|
44
|
+
sort.set({
|
|
45
|
+
column: null,
|
|
46
|
+
order: "ascending",
|
|
47
|
+
})
|
|
48
|
+
}
|
|
26
49
|
})
|
|
27
50
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { get } from "svelte/store"
|
|
2
|
+
|
|
3
|
+
const SuppressErrors = true
|
|
4
|
+
|
|
5
|
+
export const createActions = context => {
|
|
6
|
+
const { definition, API, datasource, columns, stickyColumn } = context
|
|
7
|
+
|
|
8
|
+
const refreshDefinition = async () => {
|
|
9
|
+
definition.set(await API.fetchTableDefinition(get(datasource).tableId))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const saveDefinition = async newDefinition => {
|
|
13
|
+
await API.saveTable(newDefinition)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const saveRow = async row => {
|
|
17
|
+
row.tableId = get(datasource)?.tableId
|
|
18
|
+
return await API.saveRow(row, SuppressErrors)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const deleteRows = async rows => {
|
|
22
|
+
await API.deleteRows({
|
|
23
|
+
tableId: get(datasource).tableId,
|
|
24
|
+
rows,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const isDatasourceValid = datasource => {
|
|
29
|
+
return datasource?.type === "table" && datasource?.tableId
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getRow = async id => {
|
|
33
|
+
const res = await API.searchTable({
|
|
34
|
+
tableId: get(datasource).tableId,
|
|
35
|
+
limit: 1,
|
|
36
|
+
query: {
|
|
37
|
+
equal: {
|
|
38
|
+
_id: id,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
paginate: false,
|
|
42
|
+
})
|
|
43
|
+
return res?.rows?.[0]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const canUseColumn = name => {
|
|
47
|
+
const $columns = get(columns)
|
|
48
|
+
const $sticky = get(stickyColumn)
|
|
49
|
+
return $columns.some(col => col.name === name) || $sticky?.name === name
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
table: {
|
|
54
|
+
actions: {
|
|
55
|
+
refreshDefinition,
|
|
56
|
+
saveDefinition,
|
|
57
|
+
addRow: saveRow,
|
|
58
|
+
updateRow: saveRow,
|
|
59
|
+
deleteRows,
|
|
60
|
+
getRow,
|
|
61
|
+
isDatasourceValid,
|
|
62
|
+
canUseColumn,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const initialise = context => {
|
|
69
|
+
const {
|
|
70
|
+
datasource,
|
|
71
|
+
fetch,
|
|
72
|
+
filter,
|
|
73
|
+
sort,
|
|
74
|
+
table,
|
|
75
|
+
initialFilter,
|
|
76
|
+
initialSortColumn,
|
|
77
|
+
initialSortOrder,
|
|
78
|
+
} = context
|
|
79
|
+
|
|
80
|
+
// Keep a list of subscriptions so that we can clear them when the datasource
|
|
81
|
+
// config changes
|
|
82
|
+
let unsubscribers = []
|
|
83
|
+
|
|
84
|
+
// Observe datasource changes and apply logic for table datasources
|
|
85
|
+
datasource.subscribe($datasource => {
|
|
86
|
+
// Clear previous subscriptions
|
|
87
|
+
unsubscribers?.forEach(unsubscribe => unsubscribe())
|
|
88
|
+
unsubscribers = []
|
|
89
|
+
if (!table.actions.isDatasourceValid($datasource)) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Wipe state
|
|
94
|
+
filter.set(get(initialFilter))
|
|
95
|
+
sort.set({
|
|
96
|
+
column: get(initialSortColumn),
|
|
97
|
+
order: get(initialSortOrder) || "ascending",
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// Update fetch when filter changes
|
|
101
|
+
unsubscribers.push(
|
|
102
|
+
filter.subscribe($filter => {
|
|
103
|
+
// Ensure we're updating the correct fetch
|
|
104
|
+
const $fetch = get(fetch)
|
|
105
|
+
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
$fetch.update({
|
|
109
|
+
filter: $filter,
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
// Update fetch when sorting changes
|
|
115
|
+
unsubscribers.push(
|
|
116
|
+
sort.subscribe($sort => {
|
|
117
|
+
// Ensure we're updating the correct fetch
|
|
118
|
+
const $fetch = get(fetch)
|
|
119
|
+
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
$fetch.update({
|
|
123
|
+
sortOrder: $sort.order || "ascending",
|
|
124
|
+
sortColumn: $sort.column,
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
)
|
|
128
|
+
})
|
|
129
|
+
}
|