@budibase/frontend-core 3.2.28 → 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.
Files changed (106) hide show
  1. package/package.json +9 -3
  2. package/src/api/ai.ts +17 -0
  3. package/src/api/analytics.ts +39 -0
  4. package/src/api/{app.js → app.ts} +84 -5
  5. package/src/api/attachments.ts +121 -0
  6. package/src/api/auditLogs.ts +35 -0
  7. package/src/api/{auth.js → auth.ts} +44 -7
  8. package/src/api/automations.ts +158 -0
  9. package/src/api/backups.ts +50 -0
  10. package/src/api/{configs.js → configs.ts} +31 -3
  11. package/src/api/datasources.ts +132 -0
  12. package/src/api/environmentVariables.ts +58 -0
  13. package/src/api/events.ts +21 -0
  14. package/src/api/flags.ts +48 -0
  15. package/src/api/{groups.js → groups.ts} +73 -17
  16. package/src/api/{index.js → index.ts} +89 -102
  17. package/src/api/layouts.ts +35 -0
  18. package/src/api/licensing.ts +107 -0
  19. package/src/api/{logs.js → logs.ts} +7 -1
  20. package/src/api/migrations.ts +19 -0
  21. package/src/api/{other.js → other.ts} +19 -12
  22. package/src/api/{permissions.js → permissions.ts} +31 -5
  23. package/src/api/{plugins.js → plugins.ts} +18 -1
  24. package/src/api/{queries.js → queries.ts} +39 -14
  25. package/src/api/relationships.ts +31 -0
  26. package/src/api/{roles.js → roles.ts} +22 -5
  27. package/src/api/routes.ts +30 -0
  28. package/src/api/{rowActions.js → rowActions.ts} +45 -27
  29. package/src/api/rows.ts +120 -0
  30. package/src/api/screens.ts +35 -0
  31. package/src/api/{self.js → self.ts} +20 -4
  32. package/src/api/tables.ts +192 -0
  33. package/src/api/templates.ts +57 -0
  34. package/src/api/types.ts +136 -0
  35. package/src/api/{user.js → user.ts} +111 -119
  36. package/src/api/{views.js → views.ts} +18 -7
  37. package/src/api/{viewsV2.js → viewsV2.ts} +30 -27
  38. package/src/components/grid/cells/AICell.svelte +1 -0
  39. package/src/components/grid/cells/LongFormCell.svelte +1 -0
  40. package/src/components/grid/cells/RelationshipCell.svelte +1 -2
  41. package/src/components/grid/cells/TextCell.svelte +3 -0
  42. package/src/components/grid/controls/MigrationModal.svelte +5 -5
  43. package/src/components/grid/layout/Grid.svelte +5 -8
  44. package/src/components/grid/lib/constants.js +1 -1
  45. package/src/components/grid/lib/{events.js → events.ts} +3 -3
  46. package/src/components/grid/lib/utils.js +2 -0
  47. package/src/components/grid/lib/utils.ts +32 -0
  48. package/src/components/grid/stores/bounds.ts +29 -0
  49. package/src/components/grid/stores/{cache.js → cache.ts} +21 -6
  50. package/src/components/grid/stores/{clipboard.js → clipboard.ts} +55 -19
  51. package/src/components/grid/stores/{columns.js → columns.ts} +47 -19
  52. package/src/components/grid/stores/{conditions.js → conditions.ts} +32 -12
  53. package/src/components/grid/stores/{config.js → config.ts} +16 -6
  54. package/src/components/grid/stores/{datasource.js → datasource.ts} +86 -36
  55. package/src/components/grid/stores/datasources/index.ts +31 -0
  56. package/src/components/grid/stores/datasources/{nonPlus.js → nonPlus.ts} +21 -11
  57. package/src/components/grid/stores/datasources/{table.js → table.ts} +39 -21
  58. package/src/components/grid/stores/datasources/{viewV2.js → viewV2.ts} +74 -28
  59. package/src/components/grid/stores/{filter.js → filter.ts} +39 -16
  60. package/src/components/grid/stores/index.ts +143 -0
  61. package/src/components/grid/stores/{menu.js → menu.ts} +31 -6
  62. package/src/components/grid/stores/{notifications.js → notifications.ts} +12 -2
  63. package/src/components/grid/stores/{pagination.js → pagination.ts} +2 -1
  64. package/src/components/grid/stores/{reorder.js → reorder.ts} +47 -15
  65. package/src/components/grid/stores/{resize.js → resize.ts} +28 -10
  66. package/src/components/grid/stores/{rows.js → rows.ts} +167 -53
  67. package/src/components/grid/stores/{scroll.js → scroll.ts} +28 -5
  68. package/src/components/grid/stores/{sort.js → sort.ts} +13 -3
  69. package/src/components/grid/stores/{ui.js → ui.ts} +77 -20
  70. package/src/components/grid/stores/{users.js → users.ts} +36 -9
  71. package/src/components/grid/stores/{validation.js → validation.ts} +35 -12
  72. package/src/components/grid/stores/{viewport.js → viewport.ts} +14 -3
  73. package/src/{constants.js → constants.ts} +2 -2
  74. package/src/fetch/QueryFetch.js +2 -2
  75. package/src/fetch/RelationshipFetch.js +9 -6
  76. package/src/fetch/TableFetch.js +1 -2
  77. package/src/fetch/ViewFetch.js +1 -1
  78. package/src/fetch/ViewV2Fetch.js +1 -2
  79. package/src/utils/memo.d.ts +10 -0
  80. package/src/utils/relatedColumns.ts +126 -0
  81. package/tsconfig.json +14 -0
  82. package/src/api/ai.js +0 -11
  83. package/src/api/analytics.js +0 -17
  84. package/src/api/attachments.js +0 -78
  85. package/src/api/auditLogs.js +0 -63
  86. package/src/api/automations.js +0 -111
  87. package/src/api/backups.js +0 -46
  88. package/src/api/datasources.js +0 -92
  89. package/src/api/environmentVariables.js +0 -36
  90. package/src/api/events.js +0 -13
  91. package/src/api/flags.js +0 -34
  92. package/src/api/hosting.js +0 -19
  93. package/src/api/layouts.js +0 -23
  94. package/src/api/licensing.js +0 -75
  95. package/src/api/migrations.js +0 -10
  96. package/src/api/relationships.js +0 -21
  97. package/src/api/routes.js +0 -19
  98. package/src/api/rows.js +0 -117
  99. package/src/api/screens.js +0 -23
  100. package/src/api/tables.js +0 -152
  101. package/src/api/templates.js +0 -35
  102. package/src/components/grid/stores/bounds.js +0 -16
  103. package/src/components/grid/stores/index.js +0 -73
  104. package/src/utils/relatedColumns.js +0 -103
  105. /package/src/{index.js → index.ts} +0 -0
  106. /package/src/utils/{index.js → index.ts} +0 -0
@@ -74,12 +74,14 @@
74
74
  .value {
75
75
  display: -webkit-box;
76
76
  -webkit-line-clamp: var(--content-lines);
77
+ line-clamp: var(--content-lines);
77
78
  -webkit-box-orient: vertical;
78
79
  overflow: hidden;
79
80
  line-height: 20px;
80
81
  }
81
82
  .number .value {
82
83
  -webkit-line-clamp: 1;
84
+ line-clamp: 1;
83
85
  }
84
86
  input {
85
87
  flex: 1 1 auto;
@@ -110,5 +112,6 @@
110
112
  }
111
113
  input[type="number"] {
112
114
  -moz-appearance: textfield;
115
+ appearance: textfield;
113
116
  }
114
117
  </style>
@@ -29,11 +29,11 @@
29
29
 
30
30
  const migrateUserColumn = async () => {
31
31
  try {
32
- await API.migrateColumn({
33
- tableId: $definition._id,
34
- oldColumn: column.schema.name,
35
- newColumn: newColumnName,
36
- })
32
+ await API.migrateColumn(
33
+ $definition._id,
34
+ column.schema.name,
35
+ newColumnName
36
+ )
37
37
  notifications.success("Column migrated")
38
38
  } catch (e) {
39
39
  notifications.error(`Failed to migrate: ${e.message}`)
@@ -1,4 +1,4 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { setContext, onMount } from "svelte"
3
3
  import { writable, derived } from "svelte/store"
4
4
  import { fade } from "svelte/transition"
@@ -47,24 +47,22 @@
47
47
  export let buttonsCollapsedText = null
48
48
  export let darkMode = false
49
49
  export let isCloud = null
50
- export let rowConditions = null
51
50
  export let aiEnabled = false
52
51
 
53
52
  // Unique identifier for DOM nodes inside this instance
54
53
  const gridID = `grid-${Math.random().toString().slice(2)}`
55
54
 
56
55
  // Store props in a store for reference in other stores
57
- const props = writable($$props)
56
+ const props: any = writable($$props)
58
57
 
59
58
  // Build up context
60
- let context = {
59
+ let context = attachStores({
61
60
  API: API || createAPIClient(),
62
61
  Constants,
63
62
  gridID,
64
63
  props,
65
- }
66
- context = { ...context, ...createEventManagers() }
67
- context = attachStores(context)
64
+ ...createEventManagers(),
65
+ })
68
66
 
69
67
  // Reference some stores for local use
70
68
  const {
@@ -106,7 +104,6 @@
106
104
  darkMode,
107
105
  isCloud,
108
106
  aiEnabled,
109
- rowConditions,
110
107
  })
111
108
 
112
109
  // Derive min height and make available in context
@@ -7,7 +7,7 @@ export const HPadding = 40
7
7
  export const ScrollBarSize = 8
8
8
  export const GutterWidth = 72
9
9
  export const DefaultColumnWidth = 200
10
- export const MinColumnWidth = 80
10
+ export const MinColumnWidth = 56
11
11
  export const NewRowID = "new"
12
12
  export const BlankRowID = "blank"
13
13
  export const GeneratedIDPrefix = "‽‽"
@@ -2,11 +2,11 @@ import { createEventDispatcher } from "svelte"
2
2
 
3
3
  export const createEventManagers = () => {
4
4
  const svelteDispatch = createEventDispatcher()
5
- let subscribers = {}
5
+ let subscribers: Record<string, ((...params: any) => void)[]> = {}
6
6
 
7
7
  // Dispatches an event, notifying subscribers and also emitting a normal
8
8
  // svelte event
9
- const dispatch = (event, payload) => {
9
+ const dispatch = (event: string, payload: any) => {
10
10
  svelteDispatch(event, payload)
11
11
  const subs = subscribers[event] || []
12
12
  for (let i = 0; i < subs.length; i++) {
@@ -15,7 +15,7 @@ export const createEventManagers = () => {
15
15
  }
16
16
 
17
17
  // Subscribes to events
18
- const subscribe = (event, callback) => {
18
+ const subscribe = (event: string, callback: () => void) => {
19
19
  const subs = subscribers[event] || []
20
20
  subscribers[event] = [...subs, callback]
21
21
 
@@ -1,3 +1,5 @@
1
+ // TODO: remove when all stores are typed
2
+
1
3
  import { GeneratedIDPrefix, CellIDSeparator } from "./constants"
2
4
  import { Helpers } from "@budibase/bbui"
3
5
 
@@ -0,0 +1,32 @@
1
+ import { GeneratedIDPrefix, CellIDSeparator } from "./constants"
2
+ import { Helpers } from "@budibase/bbui"
3
+
4
+ export const parseCellID = (cellId: string | null) => {
5
+ if (!cellId) {
6
+ return { rowId: undefined, field: undefined }
7
+ }
8
+ const parts = cellId.split(CellIDSeparator)
9
+ const field = parts.pop()
10
+ return { rowId: parts.join(CellIDSeparator), field }
11
+ }
12
+
13
+ export const getCellID = (rowId: string, fieldName: string) => {
14
+ return `${rowId}${CellIDSeparator}${fieldName}`
15
+ }
16
+
17
+ export const parseEventLocation = (event: MouseEvent | TouchEvent) => {
18
+ const e = event as MouseEvent & TouchEvent
19
+
20
+ return {
21
+ x: e.clientX ?? e.touches?.[0]?.clientX,
22
+ y: e.clientY ?? e.touches?.[0]?.clientY,
23
+ }
24
+ }
25
+
26
+ export const generateRowID = () => {
27
+ return `${GeneratedIDPrefix}${Helpers.uuid()}`
28
+ }
29
+
30
+ export const isGeneratedRowID = (id: string) => {
31
+ return id?.startsWith(GeneratedIDPrefix)
32
+ }
@@ -0,0 +1,29 @@
1
+ import { derived, Readable, Writable, writable } from "svelte/store"
2
+
3
+ interface BoundsStore {
4
+ bounds: Writable<{
5
+ left: number
6
+ top: number
7
+ width: number
8
+ height: number
9
+ }>
10
+ height: Readable<number>
11
+ width: Readable<number>
12
+ }
13
+
14
+ export type Store = BoundsStore
15
+
16
+ export const createStores = (): BoundsStore => {
17
+ const bounds = writable({
18
+ left: 0,
19
+ top: 0,
20
+ width: 0,
21
+ height: 0,
22
+ })
23
+
24
+ // Derive height and width as primitives to avoid wasted computation
25
+ const width = derived(bounds, $bounds => $bounds.width, 0)
26
+ const height = derived(bounds, $bounds => $bounds.height, 0)
27
+
28
+ return { bounds, height, width }
29
+ }
@@ -1,16 +1,31 @@
1
- export const createActions = context => {
1
+ import { FindTableResponse } from "@budibase/types"
2
+ import { Store as StoreContext } from "."
3
+
4
+ interface CacheActionStore {
5
+ cache: {
6
+ actions: {
7
+ getPrimaryDisplayForTableId: (tableId: string) => Promise<string>
8
+ getTable: (tableId: string) => Promise<FindTableResponse>
9
+ resetCache: () => any
10
+ }
11
+ }
12
+ }
13
+
14
+ export type Store = CacheActionStore
15
+
16
+ export const createActions = (context: StoreContext): CacheActionStore => {
2
17
  const { API } = context
3
18
 
4
19
  // Cache for the primary display columns of different tables.
5
20
  // If we ever need to cache table definitions for other purposes then we can
6
21
  // expand this to be a more generic cache.
7
- let tableCache = {}
22
+ let tableCache: Record<string, Promise<FindTableResponse>> = {}
8
23
 
9
24
  const resetCache = () => {
10
25
  tableCache = {}
11
26
  }
12
27
 
13
- const fetchTable = async tableId => {
28
+ const fetchTable = async (tableId: string) => {
14
29
  // If we've never encountered this tableId before then store a promise that
15
30
  // resolves to the primary display so that subsequent invocations before the
16
31
  // promise completes can reuse this promise
@@ -21,13 +36,13 @@ export const createActions = context => {
21
36
  return await tableCache[tableId]
22
37
  }
23
38
 
24
- const getPrimaryDisplayForTableId = async tableId => {
39
+ const getPrimaryDisplayForTableId = async (tableId: string) => {
25
40
  const table = await fetchTable(tableId)
26
41
  const display = table?.primaryDisplay || table?.schema?.[0]?.name
27
42
  return display
28
43
  }
29
44
 
30
- const getTable = async tableId => {
45
+ const getTable = async (tableId: string) => {
31
46
  const table = await fetchTable(tableId)
32
47
  return table
33
48
  }
@@ -43,7 +58,7 @@ export const createActions = context => {
43
58
  }
44
59
  }
45
60
 
46
- export const initialise = context => {
61
+ export const initialise = (context: StoreContext) => {
47
62
  const { datasource, cache } = context
48
63
 
49
64
  // Wipe the caches whenever the datasource changes to ensure we aren't
@@ -1,10 +1,41 @@
1
- import { derived, writable, get } from "svelte/store"
1
+ import { derived, writable, get, Writable, Readable } from "svelte/store"
2
2
  import { Helpers } from "@budibase/bbui"
3
3
  import { parseCellID, getCellID } from "../lib/utils"
4
4
  import { NewRowID } from "../lib/constants"
5
+ import { Store as StoreContext } from "."
5
6
 
6
- export const createStores = () => {
7
- const clipboard = writable({
7
+ type ClipboardStoreData =
8
+ | {
9
+ value: any[][]
10
+ multiCellCopy: true
11
+ }
12
+ | {
13
+ value: any | null | undefined
14
+ multiCellCopy: false
15
+ }
16
+
17
+ interface ClipboardStore {
18
+ clipboard: Writable<ClipboardStoreData>
19
+ }
20
+
21
+ interface ClipboardDerivedStore {
22
+ copyAllowed: Readable<boolean>
23
+ pasteAllowed: Readable<boolean>
24
+ }
25
+
26
+ interface ClipboardActions {
27
+ clipboard: ClipboardStore["clipboard"] & {
28
+ actions: {
29
+ copy: () => void
30
+ paste: (progressCallback: () => void) => Promise<void>
31
+ }
32
+ }
33
+ }
34
+
35
+ export type Store = ClipboardStore & ClipboardDerivedStore & ClipboardActions
36
+
37
+ export const createStores = (): ClipboardStore => {
38
+ const clipboard = writable<ClipboardStoreData>({
8
39
  value: null,
9
40
  multiCellCopy: false,
10
41
  })
@@ -13,7 +44,7 @@ export const createStores = () => {
13
44
  }
14
45
  }
15
46
 
16
- export const deriveStores = context => {
47
+ export const deriveStores = (context: StoreContext): ClipboardDerivedStore => {
17
48
  const { clipboard, focusedCellAPI, selectedCellCount, config, focusedRowId } =
18
49
  context
19
50
 
@@ -60,7 +91,7 @@ export const deriveStores = context => {
60
91
  }
61
92
  }
62
93
 
63
- export const createActions = context => {
94
+ export const createActions = (context: StoreContext): ClipboardActions => {
64
95
  const {
65
96
  clipboard,
66
97
  focusedCellAPI,
@@ -92,11 +123,11 @@ export const createActions = context => {
92
123
  const $rowChangeCache = get(rowChangeCache)
93
124
 
94
125
  // Extract value of each selected cell, accounting for the change cache
95
- let value = []
96
- for (let row of $selectedCells) {
126
+ const value = []
127
+ for (const row of $selectedCells) {
97
128
  const rowValues = []
98
- for (let cellId of row) {
99
- const { rowId, field } = parseCellID(cellId)
129
+ for (const cellId of row) {
130
+ const { rowId = "", field = "" } = parseCellID(cellId)
100
131
  const row = {
101
132
  ...$rowLookupMap[rowId],
102
133
  ...$rowChangeCache[rowId],
@@ -113,7 +144,7 @@ export const createActions = context => {
113
144
  })
114
145
  } else {
115
146
  // Single value to copy
116
- const value = $focusedCellAPI.getValue()
147
+ const value = $focusedCellAPI?.getValue()
117
148
  clipboard.set({
118
149
  value,
119
150
  multiCellCopy,
@@ -130,7 +161,7 @@ export const createActions = context => {
130
161
  }
131
162
 
132
163
  // Pastes the previously copied value(s) into the selected cell(s)
133
- const paste = async progressCallback => {
164
+ const paste = async (progressCallback: () => void) => {
134
165
  if (!get(pasteAllowed)) {
135
166
  return
136
167
  }
@@ -166,8 +197,8 @@ export const createActions = context => {
166
197
  const { rowId, field } = parseCellID($focusedCellId)
167
198
  const $rowLookupMap = get(rowLookupMap)
168
199
  const $columnLookupMap = get(columnLookupMap)
169
- const rowIdx = $rowLookupMap[rowId].__idx
170
- const colIdx = $columnLookupMap[field].__idx
200
+ const rowIdx = $rowLookupMap[rowId!].__idx
201
+ const colIdx = $columnLookupMap[field!].__idx || 0
171
202
 
172
203
  // Get limits of how many rows and columns we're able to paste into
173
204
  const $rows = get(rows)
@@ -187,7 +218,7 @@ export const createActions = context => {
187
218
  // Paste into target cell range
188
219
  if (targetCellId === $focusedCellId) {
189
220
  // Single cell edge case
190
- get(focusedCellAPI).setValue(value[0][0])
221
+ get(focusedCellAPI)?.setValue(value[0][0])
191
222
  } else {
192
223
  // Select the new cells to paste into, then paste
193
224
  selectedCells.actions.selectRange($focusedCellId, targetCellId)
@@ -197,17 +228,20 @@ export const createActions = context => {
197
228
  } else {
198
229
  if (multiCellPaste) {
199
230
  // Single to multi - duplicate value to all selected cells
200
- const newValue = get(selectedCells).map(row => row.map(() => value))
231
+ const newValue = get(selectedCells).map(row => row.map(() => value!))
201
232
  await pasteIntoSelectedCells(newValue, progressCallback)
202
233
  } else {
203
234
  // Single to single - just update the cell's value
204
- get(focusedCellAPI).setValue(value)
235
+ get(focusedCellAPI)?.setValue(value ?? null)
205
236
  }
206
237
  }
207
238
  }
208
239
 
209
240
  // Paste the specified value into the currently selected cells
210
- const pasteIntoSelectedCells = async (value, progressCallback) => {
241
+ const pasteIntoSelectedCells = async (
242
+ value: string[][],
243
+ progressCallback: () => any
244
+ ) => {
211
245
  const $selectedCells = get(selectedCells)
212
246
 
213
247
  // Find the extent at which we can paste
@@ -215,11 +249,13 @@ export const createActions = context => {
215
249
  const colExtent = Math.min(value[0].length, $selectedCells[0].length)
216
250
 
217
251
  // Build change map
218
- let changeMap = {}
252
+ let changeMap: Record<string, Record<string, string>> = {}
219
253
  for (let rowIdx = 0; rowIdx < rowExtent; rowIdx++) {
220
254
  for (let colIdx = 0; colIdx < colExtent; colIdx++) {
221
255
  const cellId = $selectedCells[rowIdx][colIdx]
222
- const { rowId, field } = parseCellID(cellId)
256
+ let { rowId, field } = parseCellID(cellId)
257
+ rowId = rowId!
258
+ field = field!
223
259
  if (!changeMap[rowId]) {
224
260
  changeMap[rowId] = {}
225
261
  }
@@ -1,8 +1,34 @@
1
- import { derived, get, writable } from "svelte/store"
1
+ import { derived, get, Readable, Writable, writable } from "svelte/store"
2
2
  import { DefaultColumnWidth, GutterWidth } from "../lib/constants"
3
+ import { UIColumn } from "@budibase/types"
4
+ import { Store as StoreContext } from "."
3
5
 
4
- export const createStores = () => {
5
- const columns = writable([])
6
+ interface ColumnStore {
7
+ columns: Writable<UIColumn[]>
8
+ }
9
+
10
+ interface DerivedColumnStore {
11
+ tableColumns: Readable<UIColumn[]>
12
+ displayColumn: Readable<UIColumn | undefined>
13
+ columnLookupMap: Readable<Record<string, UIColumn>>
14
+ visibleColumns: Readable<UIColumn[]>
15
+ scrollableColumns: Readable<UIColumn[]>
16
+ hasNonAutoColumn: Readable<boolean>
17
+ }
18
+
19
+ interface ColumnActions {
20
+ columns: ColumnStore["columns"] & {
21
+ actions: {
22
+ changeAllColumnWidths: (width: number) => Promise<void>
23
+ isReadonly: (column: UIColumn) => boolean
24
+ }
25
+ }
26
+ }
27
+
28
+ export type Store = ColumnStore & DerivedColumnStore & ColumnActions
29
+
30
+ export const createStores = (): ColumnStore => {
31
+ const columns = writable<UIColumn[]>([])
6
32
 
7
33
  // Enrich columns with metadata about their display position
8
34
  const enrichedColumns = derived(columns, $columns => {
@@ -16,7 +42,7 @@ export const createStores = () => {
16
42
  }
17
43
  if (col.visible) {
18
44
  idx++
19
- offset += col.width
45
+ offset += col.width ?? 0
20
46
  }
21
47
  return enriched
22
48
  })
@@ -30,12 +56,12 @@ export const createStores = () => {
30
56
  }
31
57
  }
32
58
 
33
- export const deriveStores = context => {
59
+ export const deriveStores = (context: StoreContext): DerivedColumnStore => {
34
60
  const { columns } = context
35
61
 
36
62
  // Derive a lookup map for all columns by name
37
63
  const columnLookupMap = derived(columns, $columns => {
38
- let map = {}
64
+ let map: Record<string, UIColumn> = {}
39
65
  $columns.forEach(column => {
40
66
  map[column.name] = column
41
67
  })
@@ -78,11 +104,11 @@ export const deriveStores = context => {
78
104
  }
79
105
  }
80
106
 
81
- export const createActions = context => {
107
+ export const createActions = (context: StoreContext): ColumnActions => {
82
108
  const { columns, datasource } = context
83
109
 
84
110
  // Updates the width of all columns
85
- const changeAllColumnWidths = async width => {
111
+ const changeAllColumnWidths = async (width: number) => {
86
112
  const $columns = get(columns)
87
113
  $columns.forEach(column => {
88
114
  const { related } = column
@@ -101,7 +127,7 @@ export const createActions = context => {
101
127
  }
102
128
 
103
129
  // Checks if a column is readonly
104
- const isReadonly = column => {
130
+ const isReadonly = (column: UIColumn) => {
105
131
  if (!column?.schema) {
106
132
  return false
107
133
  }
@@ -125,21 +151,21 @@ export const createActions = context => {
125
151
  }
126
152
  }
127
153
 
128
- export const initialise = context => {
154
+ export const initialise = (context: StoreContext) => {
129
155
  const { definition, columns, displayColumn, enrichedSchema } = context
130
156
 
131
157
  // Merge new schema fields with existing schema in order to preserve widths
132
- const processColumns = $enrichedSchema => {
133
- if (!$enrichedSchema) {
158
+ const processColumns = ($enrichedSchema: any) => {
159
+ const $definition = get(definition)
160
+ if (!$enrichedSchema || !$definition) {
134
161
  columns.set([])
135
162
  return
136
163
  }
137
- const $definition = get(definition)
138
- const $columns = get(columns)
164
+
139
165
  const $displayColumn = get(displayColumn)
140
166
 
141
167
  // Find primary display
142
- let primaryDisplay
168
+ let primaryDisplay: string
143
169
  const candidatePD = $definition.primaryDisplay || $displayColumn?.name
144
170
  if (candidatePD && $enrichedSchema[candidatePD]) {
145
171
  primaryDisplay = candidatePD
@@ -150,18 +176,20 @@ export const initialise = context => {
150
176
  Object.keys($enrichedSchema)
151
177
  .map(field => {
152
178
  const fieldSchema = $enrichedSchema[field]
153
- const oldColumn = $columns?.find(col => col.name === field)
154
- const column = {
179
+ const column: UIColumn = {
180
+ type: fieldSchema.type,
155
181
  name: field,
156
182
  label: fieldSchema.displayName || field,
157
183
  schema: fieldSchema,
158
- width: fieldSchema.width || oldColumn?.width || DefaultColumnWidth,
184
+ width: fieldSchema.width || DefaultColumnWidth,
159
185
  visible: fieldSchema.visible ?? true,
160
186
  readonly: fieldSchema.readonly,
161
- order: fieldSchema.order ?? oldColumn?.order,
187
+ order: fieldSchema.order,
162
188
  conditions: fieldSchema.conditions,
163
189
  related: fieldSchema.related,
164
190
  calculationType: fieldSchema.calculationType,
191
+ __left: undefined as any, // TODO
192
+ __idx: undefined as any, // TODO
165
193
  }
166
194
  // Override a few properties for primary display
167
195
  if (field === primaryDisplay) {
@@ -1,15 +1,31 @@
1
- import { writable, get } from "svelte/store"
1
+ import { writable, get, Writable, Readable } from "svelte/store"
2
2
  import { derivedMemo, QueryUtils } from "../../../utils"
3
- import { FieldType, EmptyFilterOption } from "@budibase/types"
3
+ import {
4
+ FieldType,
5
+ EmptyFilterOption,
6
+ UIRow,
7
+ UICondition,
8
+ } from "@budibase/types"
9
+ import { Store as StoreContext } from "."
4
10
 
5
- export const createStores = () => {
11
+ interface ConditionStore {
12
+ metadata: Writable<Record<string, any>>
13
+ }
14
+
15
+ interface ConditionDerivedStore {
16
+ conditions: Readable<UICondition[]>
17
+ }
18
+
19
+ export type Store = ConditionStore & ConditionDerivedStore
20
+
21
+ export const createStores = (): ConditionStore => {
6
22
  const metadata = writable({})
7
23
  return {
8
24
  metadata,
9
25
  }
10
26
  }
11
27
 
12
- export const deriveStores = context => {
28
+ export const deriveStores = (context: StoreContext): ConditionDerivedStore => {
13
29
  const { columns } = context
14
30
 
15
31
  // Derive and memoize the cell conditions present in our columns so that we
@@ -33,12 +49,12 @@ export const deriveStores = context => {
33
49
  }
34
50
  }
35
51
 
36
- export const initialise = context => {
52
+ export const initialise = (context: StoreContext) => {
37
53
  const { metadata, conditions, rows } = context
38
54
 
39
55
  // Recompute all metadata if conditions change
40
56
  conditions.subscribe($conditions => {
41
- let newMetadata = {}
57
+ let newMetadata: Record<string, any> = {}
42
58
  if ($conditions?.length) {
43
59
  for (let row of get(rows)) {
44
60
  newMetadata[row._id] = evaluateConditions(row, $conditions)
@@ -54,7 +70,7 @@ export const initialise = context => {
54
70
  return
55
71
  }
56
72
  const $metadata = get(metadata)
57
- let metadataUpdates = {}
73
+ let metadataUpdates: Record<string, any> = {}
58
74
  for (let row of $rows) {
59
75
  if (!row._rev || $metadata[row._id]?.version !== row._rev) {
60
76
  metadataUpdates[row._id] = evaluateConditions(row, $conditions)
@@ -69,15 +85,15 @@ export const initialise = context => {
69
85
  })
70
86
  }
71
87
 
72
- const TypeCoercionMap = {
88
+ const TypeCoercionMap: Partial<Record<FieldType, (val: string) => any>> = {
73
89
  [FieldType.NUMBER]: parseFloat,
74
- [FieldType.DATETIME]: val => {
90
+ [FieldType.DATETIME]: (val: string) => {
75
91
  if (val) {
76
92
  return new Date(val).toISOString()
77
93
  }
78
94
  return null
79
95
  },
80
- [FieldType.BOOLEAN]: val => {
96
+ [FieldType.BOOLEAN]: (val: string) => {
81
97
  if (`${val}`.toLowerCase().trim() === "true") {
82
98
  return true
83
99
  }
@@ -90,8 +106,12 @@ const TypeCoercionMap = {
90
106
 
91
107
  // Evaluates an array of cell conditions against a certain row and returns the
92
108
  // resultant metadata
93
- const evaluateConditions = (row, conditions) => {
94
- let metadata = {
109
+ const evaluateConditions = (row: UIRow, conditions: UICondition[]) => {
110
+ const metadata: {
111
+ version?: string
112
+ row: Record<string, string>
113
+ cell: Record<string, any>
114
+ } = {
95
115
  version: row._rev,
96
116
  row: {},
97
117
  cell: {},
@@ -1,10 +1,22 @@
1
1
  import { derivedMemo } from "../../../utils"
2
- import { derived } from "svelte/store"
2
+ import { derived, Readable } from "svelte/store"
3
3
  import { ViewV2Type } from "@budibase/types"
4
+ import { BaseStoreProps, Store as StoreContext } from "."
4
5
 
5
- export const createStores = context => {
6
+ type ConfigStore = {
7
+ [key in keyof BaseStoreProps]: Readable<BaseStoreProps[key]>
8
+ }
9
+
10
+ interface ConfigDerivedStore {
11
+ config: Readable<BaseStoreProps>
12
+ }
13
+
14
+ export type Store = ConfigStore & ConfigDerivedStore
15
+
16
+ export const createStores = (context: StoreContext): ConfigStore => {
6
17
  const { props } = context
7
- const getProp = prop => derivedMemo(props, $props => $props[prop])
18
+ const getProp = <T extends keyof BaseStoreProps>(prop: T) =>
19
+ derivedMemo(props, $props => $props[prop])
8
20
 
9
21
  // Derive and memoize some props so that we can react to them in isolation
10
22
  const datasource = getProp("datasource")
@@ -15,7 +27,6 @@ export const createStores = context => {
15
27
  const schemaOverrides = getProp("schemaOverrides")
16
28
  const notifySuccess = getProp("notifySuccess")
17
29
  const notifyError = getProp("notifyError")
18
- const rowConditions = getProp("rowConditions")
19
30
 
20
31
  return {
21
32
  datasource,
@@ -26,11 +37,10 @@ export const createStores = context => {
26
37
  schemaOverrides,
27
38
  notifySuccess,
28
39
  notifyError,
29
- rowConditions,
30
40
  }
31
41
  }
32
42
 
33
- export const deriveStores = context => {
43
+ export const deriveStores = (context: StoreContext): ConfigDerivedStore => {
34
44
  const { props, definition, hasNonAutoColumn } = context
35
45
 
36
46
  // Derive features