@budibase/frontend-core 3.2.29 → 3.2.30
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 +9 -3
- package/src/api/ai.ts +17 -0
- package/src/api/analytics.ts +39 -0
- package/src/api/{app.js → app.ts} +84 -5
- package/src/api/attachments.ts +121 -0
- package/src/api/auditLogs.ts +35 -0
- package/src/api/{auth.js → auth.ts} +44 -7
- package/src/api/automations.ts +158 -0
- package/src/api/backups.ts +50 -0
- package/src/api/{configs.js → configs.ts} +31 -3
- package/src/api/datasources.ts +132 -0
- package/src/api/environmentVariables.ts +58 -0
- package/src/api/events.ts +21 -0
- package/src/api/flags.ts +48 -0
- package/src/api/{groups.js → groups.ts} +73 -17
- package/src/api/{index.js → index.ts} +89 -102
- package/src/api/layouts.ts +35 -0
- package/src/api/licensing.ts +107 -0
- package/src/api/{logs.js → logs.ts} +7 -1
- package/src/api/migrations.ts +19 -0
- package/src/api/{other.js → other.ts} +19 -12
- package/src/api/{permissions.js → permissions.ts} +31 -5
- package/src/api/{plugins.js → plugins.ts} +18 -1
- package/src/api/{queries.js → queries.ts} +39 -14
- package/src/api/relationships.ts +31 -0
- package/src/api/{roles.js → roles.ts} +22 -5
- package/src/api/routes.ts +30 -0
- package/src/api/{rowActions.js → rowActions.ts} +45 -27
- package/src/api/rows.ts +120 -0
- package/src/api/screens.ts +35 -0
- package/src/api/{self.js → self.ts} +20 -4
- package/src/api/tables.ts +192 -0
- package/src/api/templates.ts +57 -0
- package/src/api/types.ts +136 -0
- package/src/api/{user.js → user.ts} +111 -119
- package/src/api/{views.js → views.ts} +18 -7
- package/src/api/{viewsV2.js → viewsV2.ts} +30 -27
- package/src/components/grid/cells/AICell.svelte +1 -0
- package/src/components/grid/cells/LongFormCell.svelte +1 -0
- package/src/components/grid/cells/RelationshipCell.svelte +1 -2
- package/src/components/grid/cells/TextCell.svelte +3 -0
- package/src/components/grid/controls/MigrationModal.svelte +5 -5
- package/src/components/grid/layout/Grid.svelte +5 -8
- package/src/components/grid/lib/constants.js +1 -1
- package/src/components/grid/lib/{events.js → events.ts} +3 -3
- package/src/components/grid/lib/utils.js +2 -0
- package/src/components/grid/lib/utils.ts +32 -0
- package/src/components/grid/stores/bounds.ts +29 -0
- package/src/components/grid/stores/{cache.js → cache.ts} +21 -6
- package/src/components/grid/stores/{clipboard.js → clipboard.ts} +55 -19
- package/src/components/grid/stores/{columns.js → columns.ts} +47 -19
- package/src/components/grid/stores/{conditions.js → conditions.ts} +32 -12
- package/src/components/grid/stores/{config.js → config.ts} +16 -6
- package/src/components/grid/stores/{datasource.js → datasource.ts} +86 -36
- package/src/components/grid/stores/datasources/index.ts +31 -0
- package/src/components/grid/stores/datasources/{nonPlus.js → nonPlus.ts} +21 -11
- package/src/components/grid/stores/datasources/{table.js → table.ts} +39 -21
- package/src/components/grid/stores/datasources/{viewV2.js → viewV2.ts} +74 -28
- package/src/components/grid/stores/{filter.js → filter.ts} +39 -16
- package/src/components/grid/stores/index.ts +143 -0
- package/src/components/grid/stores/{menu.js → menu.ts} +31 -6
- package/src/components/grid/stores/{notifications.js → notifications.ts} +12 -2
- package/src/components/grid/stores/{pagination.js → pagination.ts} +2 -1
- package/src/components/grid/stores/{reorder.js → reorder.ts} +47 -15
- package/src/components/grid/stores/{resize.js → resize.ts} +28 -10
- package/src/components/grid/stores/{rows.js → rows.ts} +167 -53
- package/src/components/grid/stores/{scroll.js → scroll.ts} +28 -5
- package/src/components/grid/stores/{sort.js → sort.ts} +13 -3
- package/src/components/grid/stores/{ui.js → ui.ts} +77 -20
- package/src/components/grid/stores/{users.js → users.ts} +36 -9
- package/src/components/grid/stores/{validation.js → validation.ts} +35 -12
- package/src/components/grid/stores/{viewport.js → viewport.ts} +14 -3
- package/src/{constants.js → constants.ts} +2 -2
- package/src/fetch/QueryFetch.js +2 -2
- package/src/fetch/RelationshipFetch.js +9 -6
- package/src/fetch/TableFetch.js +1 -2
- package/src/fetch/ViewFetch.js +1 -1
- package/src/fetch/ViewV2Fetch.js +1 -2
- package/src/utils/memo.d.ts +10 -0
- package/src/utils/relatedColumns.ts +126 -0
- package/tsconfig.json +14 -0
- package/src/api/ai.js +0 -11
- package/src/api/analytics.js +0 -17
- package/src/api/attachments.js +0 -78
- package/src/api/auditLogs.js +0 -63
- package/src/api/automations.js +0 -111
- package/src/api/backups.js +0 -46
- package/src/api/datasources.js +0 -92
- package/src/api/environmentVariables.js +0 -36
- package/src/api/events.js +0 -13
- package/src/api/flags.js +0 -34
- package/src/api/hosting.js +0 -19
- package/src/api/layouts.js +0 -23
- package/src/api/licensing.js +0 -75
- package/src/api/migrations.js +0 -10
- package/src/api/relationships.js +0 -21
- package/src/api/routes.js +0 -19
- package/src/api/rows.js +0 -117
- package/src/api/screens.js +0 -23
- package/src/api/tables.js +0 -152
- package/src/api/templates.js +0 -35
- package/src/components/grid/stores/bounds.js +0 -16
- package/src/components/grid/stores/index.js +0 -73
- package/src/utils/relatedColumns.js +0 -103
- /package/src/{index.js → index.ts} +0 -0
- /package/src/utils/{index.js → index.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { writable, get, derived } from "svelte/store"
|
|
1
|
+
import { writable, get, derived, Writable, Readable } from "svelte/store"
|
|
2
2
|
import { tick } from "svelte"
|
|
3
3
|
import {
|
|
4
4
|
DefaultRowHeight,
|
|
@@ -7,8 +7,61 @@ import {
|
|
|
7
7
|
NewRowID,
|
|
8
8
|
} from "../lib/constants"
|
|
9
9
|
import { getCellID, parseCellID } from "../lib/utils"
|
|
10
|
+
import { Store as StoreContext } from "."
|
|
11
|
+
import { Row } from "@budibase/types"
|
|
12
|
+
|
|
13
|
+
export interface UIStore {
|
|
14
|
+
focusedCellId: Writable<string | null>
|
|
15
|
+
focusedCellAPI: Writable<{
|
|
16
|
+
isReadonly: () => boolean
|
|
17
|
+
getValue: () => any
|
|
18
|
+
setValue: (val: any) => void
|
|
19
|
+
} | null>
|
|
20
|
+
selectedRows: Writable<Record<string, boolean>>
|
|
21
|
+
hoveredRowId: Writable<string | null>
|
|
22
|
+
rowHeight: Writable<number>
|
|
23
|
+
previousFocusedRowId: Writable<string | null>
|
|
24
|
+
previousFocusedCellId: Writable<string | null>
|
|
25
|
+
gridFocused: Writable<boolean>
|
|
26
|
+
keyboardBlocked: Writable<boolean>
|
|
27
|
+
isDragging: Writable<boolean>
|
|
28
|
+
buttonColumnWidth: Writable<number>
|
|
29
|
+
cellSelection: Writable<{
|
|
30
|
+
active: boolean
|
|
31
|
+
sourceCellId: string | null
|
|
32
|
+
targetCellId: string | null
|
|
33
|
+
}>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface UIDerivedStore {
|
|
37
|
+
focusedRowId: Readable<string | null>
|
|
38
|
+
focusedRow: Readable<Row | undefined>
|
|
39
|
+
contentLines: Readable<3 | 2 | 1>
|
|
40
|
+
compact: Readable<boolean>
|
|
41
|
+
selectedRowCount: Readable<number>
|
|
42
|
+
isSelectingCells: Readable<boolean>
|
|
43
|
+
selectedCells: Readable<string[][]>
|
|
44
|
+
selectedCellMap: Readable<Record<string, boolean>>
|
|
45
|
+
selectedCellCount: Readable<number>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface UIActionStore {
|
|
49
|
+
selectedCells: UIDerivedStore["selectedCells"] & {
|
|
50
|
+
actions: {
|
|
51
|
+
clear: () => void
|
|
52
|
+
selectRange: (source: string | null, target: string | null) => void
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
ui: {
|
|
56
|
+
actions: {
|
|
57
|
+
blur: () => void
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
10
61
|
|
|
11
|
-
export
|
|
62
|
+
export type Store = UIStore & UIDerivedStore & UIActionStore
|
|
63
|
+
|
|
64
|
+
export const createStores = (context: StoreContext): UIStore => {
|
|
12
65
|
const { props } = context
|
|
13
66
|
const focusedCellId = writable(null)
|
|
14
67
|
const focusedCellAPI = writable(null)
|
|
@@ -43,7 +96,7 @@ export const createStores = context => {
|
|
|
43
96
|
}
|
|
44
97
|
}
|
|
45
98
|
|
|
46
|
-
export const deriveStores = context => {
|
|
99
|
+
export const deriveStores = (context: StoreContext): UIDerivedStore => {
|
|
47
100
|
const {
|
|
48
101
|
focusedCellId,
|
|
49
102
|
rows,
|
|
@@ -58,13 +111,17 @@ export const deriveStores = context => {
|
|
|
58
111
|
|
|
59
112
|
// Derive the current focused row ID
|
|
60
113
|
const focusedRowId = derived(focusedCellId, $focusedCellId => {
|
|
61
|
-
return parseCellID($focusedCellId).rowId
|
|
114
|
+
return parseCellID($focusedCellId).rowId ?? null
|
|
62
115
|
})
|
|
63
116
|
|
|
64
117
|
// Derive the row that contains the selected cell
|
|
65
118
|
const focusedRow = derived(
|
|
66
119
|
[focusedRowId, rowLookupMap],
|
|
67
120
|
([$focusedRowId, $rowLookupMap]) => {
|
|
121
|
+
if ($focusedRowId === null) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
68
125
|
if ($focusedRowId === NewRowID) {
|
|
69
126
|
return { _id: NewRowID }
|
|
70
127
|
}
|
|
@@ -116,8 +173,8 @@ export const deriveStores = context => {
|
|
|
116
173
|
}
|
|
117
174
|
|
|
118
175
|
// Row indices
|
|
119
|
-
const sourceRowIndex = $rowLookupMap[sourceInfo.rowId]?.__idx
|
|
120
|
-
const targetRowIndex = $rowLookupMap[targetInfo.rowId]?.__idx
|
|
176
|
+
const sourceRowIndex = $rowLookupMap[sourceInfo.rowId!]?.__idx
|
|
177
|
+
const targetRowIndex = $rowLookupMap[targetInfo.rowId!]?.__idx
|
|
121
178
|
if (sourceRowIndex == null || targetRowIndex == null) {
|
|
122
179
|
return []
|
|
123
180
|
}
|
|
@@ -128,8 +185,8 @@ export const deriveStores = context => {
|
|
|
128
185
|
upperRowIndex = Math.min(upperRowIndex, lowerRowIndex + 49)
|
|
129
186
|
|
|
130
187
|
// Column indices
|
|
131
|
-
const sourceColIndex = $columnLookupMap[sourceInfo.field].__idx
|
|
132
|
-
const targetColIndex = $columnLookupMap[targetInfo.field].__idx
|
|
188
|
+
const sourceColIndex = $columnLookupMap[sourceInfo.field!].__idx || 0
|
|
189
|
+
const targetColIndex = $columnLookupMap[targetInfo.field!].__idx || 0
|
|
133
190
|
const lowerColIndex = Math.min(sourceColIndex, targetColIndex)
|
|
134
191
|
const upperColIndex = Math.max(sourceColIndex, targetColIndex)
|
|
135
192
|
|
|
@@ -151,7 +208,7 @@ export const deriveStores = context => {
|
|
|
151
208
|
|
|
152
209
|
// Derive a quick lookup map of the selected cells
|
|
153
210
|
const selectedCellMap = derived(selectedCells, $selectedCells => {
|
|
154
|
-
let map = {}
|
|
211
|
+
let map: Record<string, boolean> = {}
|
|
155
212
|
for (let row of $selectedCells) {
|
|
156
213
|
for (let cell of row) {
|
|
157
214
|
map[cell] = true
|
|
@@ -178,7 +235,7 @@ export const deriveStores = context => {
|
|
|
178
235
|
}
|
|
179
236
|
}
|
|
180
237
|
|
|
181
|
-
export const createActions = context => {
|
|
238
|
+
export const createActions = (context: StoreContext) => {
|
|
182
239
|
const {
|
|
183
240
|
focusedCellId,
|
|
184
241
|
hoveredRowId,
|
|
@@ -190,7 +247,7 @@ export const createActions = context => {
|
|
|
190
247
|
selectedCells,
|
|
191
248
|
} = context
|
|
192
249
|
// Keep the last selected index to use with bulk selection
|
|
193
|
-
let lastSelectedIndex = null
|
|
250
|
+
let lastSelectedIndex: number | null = null
|
|
194
251
|
|
|
195
252
|
// Callback when leaving the grid, deselecting all focussed or selected items
|
|
196
253
|
const blur = () => {
|
|
@@ -200,7 +257,7 @@ export const createActions = context => {
|
|
|
200
257
|
}
|
|
201
258
|
|
|
202
259
|
// Toggles whether a certain row ID is selected or not
|
|
203
|
-
const toggleSelectedRow = id => {
|
|
260
|
+
const toggleSelectedRow = (id: string) => {
|
|
204
261
|
selectedRows.update(state => {
|
|
205
262
|
let newState = {
|
|
206
263
|
...state,
|
|
@@ -215,7 +272,7 @@ export const createActions = context => {
|
|
|
215
272
|
})
|
|
216
273
|
}
|
|
217
274
|
|
|
218
|
-
const bulkSelectRows = id => {
|
|
275
|
+
const bulkSelectRows = (id: string) => {
|
|
219
276
|
if (!get(selectedRowCount)) {
|
|
220
277
|
toggleSelectedRow(id)
|
|
221
278
|
return
|
|
@@ -241,7 +298,7 @@ export const createActions = context => {
|
|
|
241
298
|
})
|
|
242
299
|
}
|
|
243
300
|
|
|
244
|
-
const startCellSelection = sourceCellId => {
|
|
301
|
+
const startCellSelection = (sourceCellId: string) => {
|
|
245
302
|
cellSelection.set({
|
|
246
303
|
active: true,
|
|
247
304
|
sourceCellId,
|
|
@@ -249,7 +306,7 @@ export const createActions = context => {
|
|
|
249
306
|
})
|
|
250
307
|
}
|
|
251
308
|
|
|
252
|
-
const updateCellSelection = targetCellId => {
|
|
309
|
+
const updateCellSelection = (targetCellId: string) => {
|
|
253
310
|
cellSelection.update(state => ({
|
|
254
311
|
...state,
|
|
255
312
|
targetCellId,
|
|
@@ -263,7 +320,7 @@ export const createActions = context => {
|
|
|
263
320
|
}))
|
|
264
321
|
}
|
|
265
322
|
|
|
266
|
-
const selectCellRange = (source, target) => {
|
|
323
|
+
const selectCellRange = (source: string, target: string) => {
|
|
267
324
|
cellSelection.set({
|
|
268
325
|
active: false,
|
|
269
326
|
sourceCellId: source,
|
|
@@ -305,7 +362,7 @@ export const createActions = context => {
|
|
|
305
362
|
}
|
|
306
363
|
}
|
|
307
364
|
|
|
308
|
-
export const initialise = context => {
|
|
365
|
+
export const initialise = (context: StoreContext) => {
|
|
309
366
|
const {
|
|
310
367
|
focusedRowId,
|
|
311
368
|
previousFocusedRowId,
|
|
@@ -332,7 +389,7 @@ export const initialise = context => {
|
|
|
332
389
|
const $focusedRowId = get(focusedRowId)
|
|
333
390
|
const $selectedRows = get(selectedRows)
|
|
334
391
|
const $hoveredRowId = get(hoveredRowId)
|
|
335
|
-
const hasRow = id => $rowLookupMap[id] != null
|
|
392
|
+
const hasRow = (id: string) => $rowLookupMap[id] != null
|
|
336
393
|
|
|
337
394
|
// Check focused cell
|
|
338
395
|
if ($focusedRowId && !hasRow($focusedRowId)) {
|
|
@@ -362,13 +419,13 @@ export const initialise = context => {
|
|
|
362
419
|
})
|
|
363
420
|
|
|
364
421
|
// Remember the last focused row ID so that we can store the previous one
|
|
365
|
-
let lastFocusedRowId = null
|
|
422
|
+
let lastFocusedRowId: string | null = null
|
|
366
423
|
focusedRowId.subscribe(id => {
|
|
367
424
|
previousFocusedRowId.set(lastFocusedRowId)
|
|
368
425
|
lastFocusedRowId = id
|
|
369
426
|
})
|
|
370
427
|
|
|
371
|
-
let lastFocusedCellId = null
|
|
428
|
+
let lastFocusedCellId: string | null = null
|
|
372
429
|
focusedCellId.subscribe(id => {
|
|
373
430
|
// Remember the last focused cell ID so that we can store the previous one
|
|
374
431
|
previousFocusedCellId.set(lastFocusedCellId)
|
|
@@ -1,11 +1,38 @@
|
|
|
1
|
-
import { writable, get, derived } from "svelte/store"
|
|
1
|
+
import { writable, get, derived, Writable, Readable } from "svelte/store"
|
|
2
2
|
import { helpers } from "@budibase/shared-core"
|
|
3
|
+
import { Store as StoreContext } from "."
|
|
4
|
+
import { UIUser } from "@budibase/types"
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
interface UIEnrichedUser extends UIUser {
|
|
7
|
+
color: string
|
|
8
|
+
label: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface UsersStore {
|
|
12
|
+
users: Writable<UIUser[]>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface DerivedUsersStore {
|
|
16
|
+
userCellMap: Readable<Record<string, UIUser>>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ActionUserStore {
|
|
20
|
+
users: UsersStore["users"] &
|
|
21
|
+
Readable<UIEnrichedUser[]> & {
|
|
22
|
+
actions: {
|
|
23
|
+
updateUser: (user: UIUser) => void
|
|
24
|
+
removeUser: (sessionId: string) => void
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type Store = DerivedUsersStore & ActionUserStore
|
|
30
|
+
|
|
31
|
+
export const createStores = (): UsersStore => {
|
|
32
|
+
const users = writable<UIUser[]>([])
|
|
6
33
|
|
|
7
34
|
const enrichedUsers = derived(users, $users => {
|
|
8
|
-
return $users.map(user => ({
|
|
35
|
+
return $users.map<UIEnrichedUser>(user => ({
|
|
9
36
|
...user,
|
|
10
37
|
color: helpers.getUserColor(user),
|
|
11
38
|
label: helpers.getUserLabel(user),
|
|
@@ -20,7 +47,7 @@ export const createStores = () => {
|
|
|
20
47
|
}
|
|
21
48
|
}
|
|
22
49
|
|
|
23
|
-
export const deriveStores = context => {
|
|
50
|
+
export const deriveStores = (context: StoreContext): DerivedUsersStore => {
|
|
24
51
|
const { users, focusedCellId } = context
|
|
25
52
|
|
|
26
53
|
// Generate a lookup map of cell ID to the user that has it selected, to make
|
|
@@ -28,7 +55,7 @@ export const deriveStores = context => {
|
|
|
28
55
|
const userCellMap = derived(
|
|
29
56
|
[users, focusedCellId],
|
|
30
57
|
([$users, $focusedCellId]) => {
|
|
31
|
-
let map = {}
|
|
58
|
+
let map: Record<string, UIUser> = {}
|
|
32
59
|
$users.forEach(user => {
|
|
33
60
|
const cellId = user.gridMetadata?.focusedCellId
|
|
34
61
|
if (cellId && cellId !== $focusedCellId) {
|
|
@@ -44,10 +71,10 @@ export const deriveStores = context => {
|
|
|
44
71
|
}
|
|
45
72
|
}
|
|
46
73
|
|
|
47
|
-
export const createActions = context => {
|
|
74
|
+
export const createActions = (context: StoreContext): ActionUserStore => {
|
|
48
75
|
const { users } = context
|
|
49
76
|
|
|
50
|
-
const updateUser = user => {
|
|
77
|
+
const updateUser = (user: UIUser) => {
|
|
51
78
|
const $users = get(users)
|
|
52
79
|
if (!$users.some(x => x.sessionId === user.sessionId)) {
|
|
53
80
|
users.set([...$users, user])
|
|
@@ -60,7 +87,7 @@ export const createActions = context => {
|
|
|
60
87
|
}
|
|
61
88
|
}
|
|
62
89
|
|
|
63
|
-
const removeUser = sessionId => {
|
|
90
|
+
const removeUser = (sessionId: string) => {
|
|
64
91
|
users.update(state => {
|
|
65
92
|
return state.filter(x => x.sessionId !== sessionId)
|
|
66
93
|
})
|
|
@@ -1,10 +1,31 @@
|
|
|
1
|
-
import { writable, get, derived } from "svelte/store"
|
|
1
|
+
import { writable, get, derived, Writable, Readable } from "svelte/store"
|
|
2
|
+
import { Store as StoreContext } from "."
|
|
2
3
|
import { parseCellID } from "../lib/utils"
|
|
3
4
|
|
|
5
|
+
interface ValidationStore {
|
|
6
|
+
validation: Writable<Record<string, string>>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface DerivedValidationStore {
|
|
10
|
+
validationRowLookupMap: Readable<Record<string, string[]>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ValidationActions {
|
|
14
|
+
validation: ValidationStore["validation"] & {
|
|
15
|
+
actions: {
|
|
16
|
+
setError: (cellId: string | undefined, error: string) => void
|
|
17
|
+
rowHasErrors: (rowId: string) => boolean
|
|
18
|
+
focusFirstRowError: (rowId: string) => void
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Store = ValidationStore & DerivedValidationStore & ValidationActions
|
|
24
|
+
|
|
4
25
|
// Normally we would break out actions into the explicit "createActions"
|
|
5
26
|
// function, but for validation all these actions are pure so can go into
|
|
6
27
|
// "createStores" instead to make dependency ordering simpler
|
|
7
|
-
export const createStores = () => {
|
|
28
|
+
export const createStores = (): ValidationStore => {
|
|
8
29
|
const validation = writable({})
|
|
9
30
|
|
|
10
31
|
return {
|
|
@@ -12,20 +33,22 @@ export const createStores = () => {
|
|
|
12
33
|
}
|
|
13
34
|
}
|
|
14
35
|
|
|
15
|
-
export const deriveStores = context => {
|
|
36
|
+
export const deriveStores = (context: StoreContext): DerivedValidationStore => {
|
|
16
37
|
const { validation } = context
|
|
17
38
|
|
|
18
39
|
// Derive which rows have errors so that we can use that info later
|
|
19
40
|
const validationRowLookupMap = derived(validation, $validation => {
|
|
20
|
-
|
|
41
|
+
const map: Record<string, string[]> = {}
|
|
21
42
|
Object.entries($validation).forEach(([key, error]) => {
|
|
22
43
|
// Extract row ID from all errored cell IDs
|
|
23
44
|
if (error) {
|
|
24
45
|
const { rowId } = parseCellID(key)
|
|
25
|
-
if (
|
|
26
|
-
map[rowId]
|
|
46
|
+
if (rowId !== undefined) {
|
|
47
|
+
if (!map[rowId]) {
|
|
48
|
+
map[rowId] = []
|
|
49
|
+
}
|
|
50
|
+
map[rowId].push(key)
|
|
27
51
|
}
|
|
28
|
-
map[rowId].push(key)
|
|
29
52
|
}
|
|
30
53
|
})
|
|
31
54
|
return map
|
|
@@ -36,10 +59,10 @@ export const deriveStores = context => {
|
|
|
36
59
|
}
|
|
37
60
|
}
|
|
38
61
|
|
|
39
|
-
export const createActions = context => {
|
|
62
|
+
export const createActions = (context: StoreContext): ValidationActions => {
|
|
40
63
|
const { validation, focusedCellId, validationRowLookupMap } = context
|
|
41
64
|
|
|
42
|
-
const setError = (cellId, error) => {
|
|
65
|
+
const setError = (cellId: string | undefined, error: string) => {
|
|
43
66
|
if (!cellId) {
|
|
44
67
|
return
|
|
45
68
|
}
|
|
@@ -49,11 +72,11 @@ export const createActions = context => {
|
|
|
49
72
|
}))
|
|
50
73
|
}
|
|
51
74
|
|
|
52
|
-
const rowHasErrors = rowId => {
|
|
75
|
+
const rowHasErrors = (rowId: string) => {
|
|
53
76
|
return get(validationRowLookupMap)[rowId]?.length > 0
|
|
54
77
|
}
|
|
55
78
|
|
|
56
|
-
const focusFirstRowError = rowId => {
|
|
79
|
+
const focusFirstRowError = (rowId: string) => {
|
|
57
80
|
const errorCells = get(validationRowLookupMap)[rowId]
|
|
58
81
|
const cellId = errorCells?.[0]
|
|
59
82
|
if (cellId) {
|
|
@@ -73,7 +96,7 @@ export const createActions = context => {
|
|
|
73
96
|
}
|
|
74
97
|
}
|
|
75
98
|
|
|
76
|
-
export const initialise = context => {
|
|
99
|
+
export const initialise = (context: StoreContext) => {
|
|
77
100
|
const { validation, previousFocusedRowId, validationRowLookupMap } = context
|
|
78
101
|
|
|
79
102
|
// Remove validation errors when changing rows
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import { derived } from "svelte/store"
|
|
1
|
+
import { derived, Readable } from "svelte/store"
|
|
2
2
|
import { MinColumnWidth } from "../lib/constants"
|
|
3
|
+
import { Store as StoreContext } from "."
|
|
4
|
+
import { Row } from "@budibase/types"
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
interface ViewportDerivedStore {
|
|
7
|
+
scrolledRowCount: Readable<number>
|
|
8
|
+
visualRowCapacity: Readable<number>
|
|
9
|
+
renderedRows: Readable<Row>
|
|
10
|
+
columnRenderMap: Readable<Record<string, true>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type Store = ViewportDerivedStore
|
|
14
|
+
|
|
15
|
+
export const deriveStores = (context: StoreContext): ViewportDerivedStore => {
|
|
5
16
|
const {
|
|
6
17
|
rowHeight,
|
|
7
18
|
scrollableColumns,
|
|
@@ -77,7 +88,7 @@ export const deriveStores = context => {
|
|
|
77
88
|
leftEdge += $scrollableColumns[endColIdx].width
|
|
78
89
|
endColIdx++
|
|
79
90
|
}
|
|
80
|
-
let next = {}
|
|
91
|
+
let next: Record<string, true> = {}
|
|
81
92
|
$scrollableColumns
|
|
82
93
|
.slice(Math.max(0, startColIdx), endColIdx)
|
|
83
94
|
.forEach(col => {
|
|
@@ -76,9 +76,9 @@ export const ExtendedBudibaseRoleOptions = [
|
|
|
76
76
|
value: BudibaseRoles.Owner,
|
|
77
77
|
sortOrder: 0,
|
|
78
78
|
},
|
|
79
|
+
...BudibaseRoleOptions,
|
|
80
|
+
...BudibaseRoleOptionsOld,
|
|
79
81
|
]
|
|
80
|
-
.concat(BudibaseRoleOptions)
|
|
81
|
-
.concat(BudibaseRoleOptionsOld)
|
|
82
82
|
|
|
83
83
|
export const PlanType = {
|
|
84
84
|
FREE: "free",
|
package/src/fetch/QueryFetch.js
CHANGED
|
@@ -48,7 +48,7 @@ export default class QueryFetch extends DataFetch {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Add pagination to query if supported
|
|
51
|
-
let queryPayload = {
|
|
51
|
+
let queryPayload = { parameters }
|
|
52
52
|
if (paginate && supportsPagination) {
|
|
53
53
|
const requestCursor = type === "page" ? parseInt(cursor || 1) : cursor
|
|
54
54
|
queryPayload.pagination = { page: requestCursor, limit }
|
|
@@ -56,7 +56,7 @@ export default class QueryFetch extends DataFetch {
|
|
|
56
56
|
|
|
57
57
|
// Execute query
|
|
58
58
|
try {
|
|
59
|
-
const res = await this.API.executeQuery(queryPayload)
|
|
59
|
+
const res = await this.API.executeQuery(datasource?._id, queryPayload)
|
|
60
60
|
const { data, pagination, ...rest } = res
|
|
61
61
|
|
|
62
62
|
// Derive pagination info from response
|
|
@@ -3,13 +3,16 @@ import DataFetch from "./DataFetch.js"
|
|
|
3
3
|
export default class RelationshipFetch extends DataFetch {
|
|
4
4
|
async getData() {
|
|
5
5
|
const { datasource } = this.options
|
|
6
|
+
if (!datasource?.rowId || !datasource?.rowTableId) {
|
|
7
|
+
return { rows: [] }
|
|
8
|
+
}
|
|
6
9
|
try {
|
|
7
|
-
const res = await this.API.fetchRelationshipData(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return { rows: res
|
|
10
|
+
const res = await this.API.fetchRelationshipData(
|
|
11
|
+
datasource.rowTableId,
|
|
12
|
+
datasource.rowId,
|
|
13
|
+
datasource.fieldName
|
|
14
|
+
)
|
|
15
|
+
return { rows: res }
|
|
13
16
|
} catch (error) {
|
|
14
17
|
return { rows: [] }
|
|
15
18
|
}
|
package/src/fetch/TableFetch.js
CHANGED
package/src/fetch/ViewFetch.js
CHANGED
|
@@ -8,7 +8,7 @@ export default class ViewFetch extends DataFetch {
|
|
|
8
8
|
async getData() {
|
|
9
9
|
const { datasource } = this.options
|
|
10
10
|
try {
|
|
11
|
-
const res = await this.API.fetchViewData(datasource)
|
|
11
|
+
const res = await this.API.fetchViewData(datasource.name)
|
|
12
12
|
return { rows: res || [] }
|
|
13
13
|
} catch (error) {
|
|
14
14
|
return { rows: [] }
|
package/src/fetch/ViewV2Fetch.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Readable, Writable } from "svelte/store"
|
|
2
|
+
|
|
3
|
+
declare module "./memo" {
|
|
4
|
+
export function memo<T>(value: T): Writable<T>
|
|
5
|
+
|
|
6
|
+
export function derivedMemo<TStore, TResult>(
|
|
7
|
+
store: Readable<TStore>,
|
|
8
|
+
derivation: (store: TStore) => TResult
|
|
9
|
+
): Readable<TResult>
|
|
10
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Helpers } from "@budibase/bbui"
|
|
2
|
+
import {
|
|
3
|
+
FieldType,
|
|
4
|
+
isRelationshipField,
|
|
5
|
+
RelationshipType,
|
|
6
|
+
Row,
|
|
7
|
+
UIFieldSchema,
|
|
8
|
+
} from "@budibase/types"
|
|
9
|
+
|
|
10
|
+
const columnTypeManyTypeOverrides: Partial<Record<FieldType, FieldType>> = {
|
|
11
|
+
[FieldType.DATETIME]: FieldType.STRING,
|
|
12
|
+
[FieldType.BOOLEAN]: FieldType.STRING,
|
|
13
|
+
[FieldType.SIGNATURE_SINGLE]: FieldType.ATTACHMENTS,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const columnTypeManyParser = {
|
|
17
|
+
[FieldType.DATETIME]: (
|
|
18
|
+
value: any[],
|
|
19
|
+
field: {
|
|
20
|
+
timeOnly?: boolean
|
|
21
|
+
dateOnly?: boolean
|
|
22
|
+
}
|
|
23
|
+
) => {
|
|
24
|
+
function parseDate(value: any) {
|
|
25
|
+
const { timeOnly, dateOnly } = field || {}
|
|
26
|
+
const enableTime = !dateOnly
|
|
27
|
+
const parsedValue = Helpers.parseDate(value, { enableTime })
|
|
28
|
+
const parsed = Helpers.getDateDisplayValue(parsedValue, {
|
|
29
|
+
enableTime,
|
|
30
|
+
timeOnly,
|
|
31
|
+
})
|
|
32
|
+
return parsed
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return value.map(v => parseDate(v))
|
|
36
|
+
},
|
|
37
|
+
[FieldType.BOOLEAN]: (value: any[]) => value.map(v => !!v),
|
|
38
|
+
[FieldType.BB_REFERENCE_SINGLE]: (value: any[]) => [
|
|
39
|
+
...new Map(value.map(i => [i._id, i])).values(),
|
|
40
|
+
],
|
|
41
|
+
[FieldType.BB_REFERENCE]: (value: any[]) => [
|
|
42
|
+
...new Map(value.map(i => [i._id, i])).values(),
|
|
43
|
+
],
|
|
44
|
+
[FieldType.ARRAY]: (value: any[]) => Array.from(new Set(value)),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function enrichSchemaWithRelColumns(
|
|
48
|
+
schema: Record<string, UIFieldSchema>
|
|
49
|
+
): Record<string, UIFieldSchema> {
|
|
50
|
+
const result = Object.keys(schema).reduce<Record<string, UIFieldSchema>>(
|
|
51
|
+
(result, fieldName) => {
|
|
52
|
+
const field = schema[fieldName]
|
|
53
|
+
result[fieldName] = field
|
|
54
|
+
|
|
55
|
+
if (
|
|
56
|
+
field.visible !== false &&
|
|
57
|
+
isRelationshipField(field) &&
|
|
58
|
+
field.columns
|
|
59
|
+
) {
|
|
60
|
+
const fromSingle =
|
|
61
|
+
field?.relationshipType === RelationshipType.ONE_TO_MANY
|
|
62
|
+
|
|
63
|
+
for (const relColumn of Object.keys(field.columns)) {
|
|
64
|
+
const relField = field.columns[relColumn]
|
|
65
|
+
if (!relField.visible) {
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
const name = `${field.name}.${relColumn}`
|
|
69
|
+
result[name] = {
|
|
70
|
+
...relField,
|
|
71
|
+
type: relField.type as any, // TODO
|
|
72
|
+
name,
|
|
73
|
+
related: { field: fieldName, subField: relColumn },
|
|
74
|
+
cellRenderType:
|
|
75
|
+
(!fromSingle && columnTypeManyTypeOverrides[relField.type]) ||
|
|
76
|
+
relField.type,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result
|
|
81
|
+
},
|
|
82
|
+
{}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return result
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function getRelatedTableValues(
|
|
89
|
+
row: Row,
|
|
90
|
+
field: UIFieldSchema & { related: { field: string; subField: string } },
|
|
91
|
+
fromField: UIFieldSchema
|
|
92
|
+
) {
|
|
93
|
+
const fromSingle =
|
|
94
|
+
isRelationshipField(fromField) &&
|
|
95
|
+
fromField?.relationshipType === RelationshipType.ONE_TO_MANY
|
|
96
|
+
|
|
97
|
+
let result = ""
|
|
98
|
+
|
|
99
|
+
if (fromSingle) {
|
|
100
|
+
result = row[field.related.field]?.[0]?.[field.related.subField]
|
|
101
|
+
} else {
|
|
102
|
+
const parser =
|
|
103
|
+
columnTypeManyParser[field.type as keyof typeof columnTypeManyParser] ||
|
|
104
|
+
((value: any) => value)
|
|
105
|
+
const value = row[field.related.field]
|
|
106
|
+
?.flatMap((r: Row) => r[field.related.subField])
|
|
107
|
+
?.filter((i: any) => i !== undefined && i !== null)
|
|
108
|
+
const parsed = parser(value || [], field as any)
|
|
109
|
+
result = parsed as any
|
|
110
|
+
if (
|
|
111
|
+
[
|
|
112
|
+
FieldType.STRING,
|
|
113
|
+
FieldType.NUMBER,
|
|
114
|
+
FieldType.BIGINT,
|
|
115
|
+
FieldType.BOOLEAN,
|
|
116
|
+
FieldType.DATETIME,
|
|
117
|
+
FieldType.LONGFORM,
|
|
118
|
+
FieldType.BARCODEQR,
|
|
119
|
+
].includes(field.type)
|
|
120
|
+
) {
|
|
121
|
+
result = parsed?.join(", ")
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return result
|
|
126
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.build.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"lib": ["ESNext"],
|
|
6
|
+
"module": "preserve",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"allowJs": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"],
|
|
13
|
+
"exclude": ["node_modules", "dist"]
|
|
14
|
+
}
|
package/src/api/ai.js
DELETED