@budibase/frontend-core 3.2.37 → 3.2.39
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 +2 -2
- package/src/api/configs.ts +2 -2
- package/src/api/index.ts +4 -8
- package/src/api/types.ts +2 -3
- package/src/api/views.ts +12 -2
- package/src/api/viewsV2.ts +9 -4
- package/src/components/grid/lib/{renderers.js → renderers.ts} +14 -4
- package/src/components/grid/lib/{websocket.js → websocket.ts} +6 -4
- package/src/components/grid/stores/config.ts +1 -1
- package/src/components/grid/stores/datasource.ts +12 -10
- package/src/components/grid/stores/rows.ts +5 -4
- package/src/constants.ts +2 -2
- package/src/fetch/{CustomFetch.js → CustomFetch.ts} +24 -12
- package/src/fetch/{DataFetch.js → DataFetch.ts} +158 -94
- package/src/fetch/FieldFetch.ts +67 -0
- package/src/fetch/{GroupUserFetch.js → GroupUserFetch.ts} +21 -5
- package/src/fetch/{JSONArrayFetch.js → JSONArrayFetch.ts} +5 -3
- package/src/fetch/NestedProviderFetch.ts +40 -0
- package/src/fetch/{QueryArrayFetch.js → QueryArrayFetch.ts} +12 -6
- package/src/fetch/{QueryFetch.js → QueryFetch.ts} +27 -9
- package/src/fetch/RelationshipFetch.ts +49 -0
- package/src/fetch/{TableFetch.js → TableFetch.ts} +27 -5
- package/src/fetch/{UserFetch.js → UserFetch.ts} +31 -14
- package/src/fetch/ViewFetch.ts +51 -0
- package/src/fetch/{ViewV2Fetch.js → ViewV2Fetch.ts} +46 -24
- package/src/fetch/index.ts +93 -0
- package/src/index.ts +2 -1
- package/src/utils/json.d.ts +23 -0
- package/src/utils/utils.js +3 -0
- package/src/components/grid/lib/utils.js +0 -32
- package/src/fetch/FieldFetch.js +0 -44
- package/src/fetch/NestedProviderFetch.js +0 -21
- package/src/fetch/RelationshipFetch.js +0 -20
- package/src/fetch/ViewFetch.js +0 -23
- package/src/fetch/index.js +0 -57
- /package/src/components/grid/lib/{constants.js → constants.ts} +0 -0
|
@@ -1,25 +1,103 @@
|
|
|
1
|
-
import { writable, derived, get } from "svelte/store"
|
|
1
|
+
import { writable, derived, get, Writable, Readable } from "svelte/store"
|
|
2
2
|
import { cloneDeep } from "lodash/fp"
|
|
3
3
|
import { QueryUtils } from "../utils"
|
|
4
4
|
import { convertJSONSchemaToTableSchema } from "../utils/json"
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
FieldType,
|
|
7
|
+
LegacyFilter,
|
|
8
|
+
Row,
|
|
9
|
+
SearchFilters,
|
|
10
|
+
SortOrder,
|
|
11
|
+
SortType,
|
|
12
|
+
TableSchema,
|
|
13
|
+
UISearchFilter,
|
|
14
|
+
} from "@budibase/types"
|
|
15
|
+
import { APIClient } from "../api/types"
|
|
16
|
+
import { DataFetchType } from "."
|
|
6
17
|
|
|
7
18
|
const { buildQuery, limit: queryLimit, runQuery, sort } = QueryUtils
|
|
8
19
|
|
|
20
|
+
interface DataFetchStore<TDefinition, TQuery> {
|
|
21
|
+
rows: Row[]
|
|
22
|
+
info: any
|
|
23
|
+
schema: TableSchema | null
|
|
24
|
+
loading: boolean
|
|
25
|
+
loaded: boolean
|
|
26
|
+
query: TQuery
|
|
27
|
+
pageNumber: number
|
|
28
|
+
cursor: string | null
|
|
29
|
+
cursors: string[]
|
|
30
|
+
resetKey: string
|
|
31
|
+
error: {
|
|
32
|
+
message: string
|
|
33
|
+
status: number
|
|
34
|
+
} | null
|
|
35
|
+
definition?: TDefinition | null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface DataFetchDerivedStore<TDefinition, TQuery>
|
|
39
|
+
extends DataFetchStore<TDefinition, TQuery> {
|
|
40
|
+
hasNextPage: boolean
|
|
41
|
+
hasPrevPage: boolean
|
|
42
|
+
supportsSearch: boolean
|
|
43
|
+
supportsSort: boolean
|
|
44
|
+
supportsPagination: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface DataFetchParams<
|
|
48
|
+
TDatasource,
|
|
49
|
+
TQuery = SearchFilters | undefined
|
|
50
|
+
> {
|
|
51
|
+
API: APIClient
|
|
52
|
+
datasource: TDatasource
|
|
53
|
+
query: TQuery
|
|
54
|
+
options?: {}
|
|
55
|
+
}
|
|
56
|
+
|
|
9
57
|
/**
|
|
10
58
|
* Parent class which handles the implementation of fetching data from an
|
|
11
59
|
* internal table or datasource plus.
|
|
12
60
|
* For other types of datasource, this class is overridden and extended.
|
|
13
61
|
*/
|
|
14
|
-
export default class DataFetch
|
|
62
|
+
export default abstract class DataFetch<
|
|
63
|
+
TDatasource extends { type: DataFetchType },
|
|
64
|
+
TDefinition extends {
|
|
65
|
+
schema?: Record<string, any> | null
|
|
66
|
+
primaryDisplay?: string
|
|
67
|
+
},
|
|
68
|
+
TQuery extends {} = SearchFilters
|
|
69
|
+
> {
|
|
70
|
+
API: APIClient
|
|
71
|
+
features: {
|
|
72
|
+
supportsSearch: boolean
|
|
73
|
+
supportsSort: boolean
|
|
74
|
+
supportsPagination: boolean
|
|
75
|
+
}
|
|
76
|
+
options: {
|
|
77
|
+
datasource: TDatasource
|
|
78
|
+
limit: number
|
|
79
|
+
// Search config
|
|
80
|
+
filter: UISearchFilter | LegacyFilter[] | null
|
|
81
|
+
query: TQuery
|
|
82
|
+
// Sorting config
|
|
83
|
+
sortColumn: string | null
|
|
84
|
+
sortOrder: SortOrder
|
|
85
|
+
sortType: SortType | null
|
|
86
|
+
// Pagination config
|
|
87
|
+
paginate: boolean
|
|
88
|
+
// Client side feature customisation
|
|
89
|
+
clientSideSearching: boolean
|
|
90
|
+
clientSideSorting: boolean
|
|
91
|
+
clientSideLimiting: boolean
|
|
92
|
+
}
|
|
93
|
+
store: Writable<DataFetchStore<TDefinition, TQuery>>
|
|
94
|
+
derivedStore: Readable<DataFetchDerivedStore<TDefinition, TQuery>>
|
|
95
|
+
|
|
15
96
|
/**
|
|
16
97
|
* Constructs a new DataFetch instance.
|
|
17
98
|
* @param opts the fetch options
|
|
18
99
|
*/
|
|
19
|
-
constructor(opts) {
|
|
20
|
-
// API client
|
|
21
|
-
this.API = null
|
|
22
|
-
|
|
100
|
+
constructor(opts: DataFetchParams<TDatasource, TQuery>) {
|
|
23
101
|
// Feature flags
|
|
24
102
|
this.features = {
|
|
25
103
|
supportsSearch: false,
|
|
@@ -29,12 +107,12 @@ export default class DataFetch {
|
|
|
29
107
|
|
|
30
108
|
// Config
|
|
31
109
|
this.options = {
|
|
32
|
-
datasource:
|
|
110
|
+
datasource: opts.datasource,
|
|
33
111
|
limit: 10,
|
|
34
112
|
|
|
35
113
|
// Search config
|
|
36
114
|
filter: null,
|
|
37
|
-
query:
|
|
115
|
+
query: opts.query,
|
|
38
116
|
|
|
39
117
|
// Sorting config
|
|
40
118
|
sortColumn: null,
|
|
@@ -57,11 +135,11 @@ export default class DataFetch {
|
|
|
57
135
|
schema: null,
|
|
58
136
|
loading: false,
|
|
59
137
|
loaded: false,
|
|
60
|
-
query:
|
|
138
|
+
query: opts.query,
|
|
61
139
|
pageNumber: 0,
|
|
62
140
|
cursor: null,
|
|
63
141
|
cursors: [],
|
|
64
|
-
resetKey: Math.random(),
|
|
142
|
+
resetKey: Math.random().toString(),
|
|
65
143
|
error: null,
|
|
66
144
|
})
|
|
67
145
|
|
|
@@ -102,9 +180,6 @@ export default class DataFetch {
|
|
|
102
180
|
this.store.update($store => ({ ...$store, loaded: true }))
|
|
103
181
|
return
|
|
104
182
|
}
|
|
105
|
-
|
|
106
|
-
// Initially fetch data but don't bother waiting for the result
|
|
107
|
-
this.getInitialData()
|
|
108
183
|
}
|
|
109
184
|
|
|
110
185
|
/**
|
|
@@ -118,7 +193,10 @@ export default class DataFetch {
|
|
|
118
193
|
/**
|
|
119
194
|
* Gets the default sort column for this datasource
|
|
120
195
|
*/
|
|
121
|
-
getDefaultSortColumn(
|
|
196
|
+
getDefaultSortColumn(
|
|
197
|
+
definition: { primaryDisplay?: string } | null,
|
|
198
|
+
schema: Record<string, any>
|
|
199
|
+
): string | null {
|
|
122
200
|
if (definition?.primaryDisplay && schema[definition.primaryDisplay]) {
|
|
123
201
|
return definition.primaryDisplay
|
|
124
202
|
} else {
|
|
@@ -130,13 +208,13 @@ export default class DataFetch {
|
|
|
130
208
|
* Fetches a fresh set of data from the server, resetting pagination
|
|
131
209
|
*/
|
|
132
210
|
async getInitialData() {
|
|
133
|
-
const {
|
|
211
|
+
const { filter, paginate } = this.options
|
|
134
212
|
|
|
135
213
|
// Fetch datasource definition and extract sort properties if configured
|
|
136
|
-
const definition = await this.getDefinition(
|
|
214
|
+
const definition = await this.getDefinition()
|
|
137
215
|
|
|
138
216
|
// Determine feature flags
|
|
139
|
-
const features = this.determineFeatureFlags(
|
|
217
|
+
const features = await this.determineFeatureFlags()
|
|
140
218
|
this.features = {
|
|
141
219
|
supportsSearch: !!features?.supportsSearch,
|
|
142
220
|
supportsSort: !!features?.supportsSort,
|
|
@@ -144,11 +222,11 @@ export default class DataFetch {
|
|
|
144
222
|
}
|
|
145
223
|
|
|
146
224
|
// Fetch and enrich schema
|
|
147
|
-
let schema = this.getSchema(
|
|
148
|
-
schema = this.enrichSchema(schema)
|
|
225
|
+
let schema = this.getSchema(definition)
|
|
149
226
|
if (!schema) {
|
|
150
227
|
return
|
|
151
228
|
}
|
|
229
|
+
schema = this.enrichSchema(schema)
|
|
152
230
|
|
|
153
231
|
// If an invalid sort column is specified, delete it
|
|
154
232
|
if (this.options.sortColumn && !schema[this.options.sortColumn]) {
|
|
@@ -172,20 +250,25 @@ export default class DataFetch {
|
|
|
172
250
|
if (
|
|
173
251
|
fieldSchema?.type === FieldType.NUMBER ||
|
|
174
252
|
fieldSchema?.type === FieldType.BIGINT ||
|
|
175
|
-
fieldSchema?.calculationType
|
|
253
|
+
("calculationType" in fieldSchema && fieldSchema?.calculationType)
|
|
176
254
|
) {
|
|
177
255
|
this.options.sortType = SortType.NUMBER
|
|
178
256
|
}
|
|
257
|
+
|
|
179
258
|
// If no sort order, default to ascending
|
|
180
259
|
if (!this.options.sortOrder) {
|
|
181
260
|
this.options.sortOrder = SortOrder.ASCENDING
|
|
261
|
+
} else {
|
|
262
|
+
// Ensure sortOrder matches the enum
|
|
263
|
+
this.options.sortOrder =
|
|
264
|
+
this.options.sortOrder.toLowerCase() as SortOrder
|
|
182
265
|
}
|
|
183
266
|
}
|
|
184
267
|
|
|
185
268
|
// Build the query
|
|
186
269
|
let query = this.options.query
|
|
187
270
|
if (!query) {
|
|
188
|
-
query = buildQuery(filter)
|
|
271
|
+
query = buildQuery(filter ?? undefined) as TQuery
|
|
189
272
|
}
|
|
190
273
|
|
|
191
274
|
// Update store
|
|
@@ -210,7 +293,7 @@ export default class DataFetch {
|
|
|
210
293
|
info: page.info,
|
|
211
294
|
cursors: paginate && page.hasNextPage ? [null, page.cursor] : [null],
|
|
212
295
|
error: page.error,
|
|
213
|
-
resetKey: Math.random(),
|
|
296
|
+
resetKey: Math.random().toString(),
|
|
214
297
|
}))
|
|
215
298
|
}
|
|
216
299
|
|
|
@@ -238,8 +321,8 @@ export default class DataFetch {
|
|
|
238
321
|
}
|
|
239
322
|
|
|
240
323
|
// If we don't support sorting, do a client-side sort
|
|
241
|
-
if (!this.features.supportsSort && clientSideSorting) {
|
|
242
|
-
rows = sort(rows, sortColumn, sortOrder, sortType)
|
|
324
|
+
if (!this.features.supportsSort && clientSideSorting && sortType) {
|
|
325
|
+
rows = sort(rows, sortColumn as any, sortOrder, sortType)
|
|
243
326
|
}
|
|
244
327
|
|
|
245
328
|
// If we don't support pagination, do a client-side limit
|
|
@@ -256,49 +339,28 @@ export default class DataFetch {
|
|
|
256
339
|
}
|
|
257
340
|
}
|
|
258
341
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
info: null,
|
|
267
|
-
hasNextPage: false,
|
|
268
|
-
cursor: null,
|
|
269
|
-
}
|
|
270
|
-
}
|
|
342
|
+
abstract getData(): Promise<{
|
|
343
|
+
rows: Row[]
|
|
344
|
+
info?: any
|
|
345
|
+
hasNextPage?: boolean
|
|
346
|
+
cursor?: any
|
|
347
|
+
error?: any
|
|
348
|
+
}>
|
|
271
349
|
|
|
272
350
|
/**
|
|
273
351
|
* Gets the definition for this datasource.
|
|
274
|
-
|
|
275
|
-
* @param datasource
|
|
352
|
+
|
|
276
353
|
* @return {object} the definition
|
|
277
354
|
*/
|
|
278
|
-
|
|
279
|
-
if (!datasource?.tableId) {
|
|
280
|
-
return null
|
|
281
|
-
}
|
|
282
|
-
try {
|
|
283
|
-
return await this.API.fetchTableDefinition(datasource.tableId)
|
|
284
|
-
} catch (error) {
|
|
285
|
-
this.store.update(state => ({
|
|
286
|
-
...state,
|
|
287
|
-
error,
|
|
288
|
-
}))
|
|
289
|
-
return null
|
|
290
|
-
}
|
|
291
|
-
}
|
|
355
|
+
abstract getDefinition(): Promise<TDefinition | null>
|
|
292
356
|
|
|
293
357
|
/**
|
|
294
358
|
* Gets the schema definition for a datasource.
|
|
295
|
-
* Defaults to getting the "schema" property of the definition.
|
|
296
|
-
* @param datasource the datasource
|
|
297
359
|
* @param definition the datasource definition
|
|
298
360
|
* @return {object} the schema
|
|
299
361
|
*/
|
|
300
|
-
getSchema(
|
|
301
|
-
return definition?.schema
|
|
362
|
+
getSchema(definition: TDefinition | null): Record<string, any> | undefined {
|
|
363
|
+
return definition?.schema ?? undefined
|
|
302
364
|
}
|
|
303
365
|
|
|
304
366
|
/**
|
|
@@ -307,53 +369,56 @@ export default class DataFetch {
|
|
|
307
369
|
* @param schema the datasource schema
|
|
308
370
|
* @return {object} the enriched datasource schema
|
|
309
371
|
*/
|
|
310
|
-
enrichSchema(schema) {
|
|
311
|
-
if (schema == null) {
|
|
312
|
-
return null
|
|
313
|
-
}
|
|
314
|
-
|
|
372
|
+
enrichSchema(schema: TableSchema): TableSchema {
|
|
315
373
|
// Check for any JSON fields so we can add any top level properties
|
|
316
|
-
let jsonAdditions = {}
|
|
317
|
-
Object.keys(schema)
|
|
374
|
+
let jsonAdditions: Record<string, { type: string; nestedJSON: true }> = {}
|
|
375
|
+
for (const fieldKey of Object.keys(schema)) {
|
|
318
376
|
const fieldSchema = schema[fieldKey]
|
|
319
|
-
if (fieldSchema
|
|
377
|
+
if (fieldSchema.type === FieldType.JSON) {
|
|
320
378
|
const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, {
|
|
321
379
|
squashObjects: true,
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
380
|
+
}) as Record<string, { type: string }> | null // TODO: remove when convertJSONSchemaToTableSchema is typed
|
|
381
|
+
if (jsonSchema) {
|
|
382
|
+
for (const jsonKey of Object.keys(jsonSchema)) {
|
|
383
|
+
jsonAdditions[`${fieldKey}.${jsonKey}`] = {
|
|
384
|
+
type: jsonSchema[jsonKey].type,
|
|
385
|
+
nestedJSON: true,
|
|
386
|
+
}
|
|
327
387
|
}
|
|
328
|
-
}
|
|
388
|
+
}
|
|
329
389
|
}
|
|
330
|
-
}
|
|
331
|
-
schema = { ...schema, ...jsonAdditions }
|
|
390
|
+
}
|
|
332
391
|
|
|
333
392
|
// Ensure schema is in the correct structure
|
|
334
|
-
let enrichedSchema = {}
|
|
335
|
-
Object.entries(schema).forEach(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
393
|
+
let enrichedSchema: TableSchema = {}
|
|
394
|
+
Object.entries({ ...schema, ...jsonAdditions }).forEach(
|
|
395
|
+
([fieldName, fieldSchema]) => {
|
|
396
|
+
if (typeof fieldSchema === "string") {
|
|
397
|
+
enrichedSchema[fieldName] = {
|
|
398
|
+
type: fieldSchema,
|
|
399
|
+
name: fieldName,
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
enrichedSchema[fieldName] = {
|
|
403
|
+
...fieldSchema,
|
|
404
|
+
type: fieldSchema.type as any, // TODO: check type union definition conflicts
|
|
405
|
+
name: fieldName,
|
|
406
|
+
}
|
|
345
407
|
}
|
|
346
408
|
}
|
|
347
|
-
|
|
409
|
+
)
|
|
348
410
|
|
|
349
411
|
return enrichedSchema
|
|
350
412
|
}
|
|
351
413
|
|
|
352
414
|
/**
|
|
353
|
-
* Determine the feature flag for this datasource
|
|
354
|
-
* @param definition
|
|
415
|
+
* Determine the feature flag for this datasource
|
|
355
416
|
*/
|
|
356
|
-
determineFeatureFlags(
|
|
417
|
+
async determineFeatureFlags(): Promise<{
|
|
418
|
+
supportsPagination: boolean
|
|
419
|
+
supportsSearch?: boolean
|
|
420
|
+
supportsSort?: boolean
|
|
421
|
+
}> {
|
|
357
422
|
return {
|
|
358
423
|
supportsSearch: false,
|
|
359
424
|
supportsSort: false,
|
|
@@ -365,12 +430,11 @@ export default class DataFetch {
|
|
|
365
430
|
* Resets the data set and updates options
|
|
366
431
|
* @param newOptions any new options
|
|
367
432
|
*/
|
|
368
|
-
async update(newOptions) {
|
|
433
|
+
async update(newOptions: any) {
|
|
369
434
|
// Check if any settings have actually changed
|
|
370
435
|
let refresh = false
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
const oldVal = this.options[key] == null ? null : this.options[key]
|
|
436
|
+
for (const [key, value] of Object.entries(newOptions || {})) {
|
|
437
|
+
const oldVal = this.options[key as keyof typeof this.options] ?? null
|
|
374
438
|
const newVal = value == null ? null : value
|
|
375
439
|
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
|
376
440
|
refresh = true
|
|
@@ -437,7 +501,7 @@ export default class DataFetch {
|
|
|
437
501
|
* @param state the current store state
|
|
438
502
|
* @return {boolean} whether there is a next page of data or not
|
|
439
503
|
*/
|
|
440
|
-
hasNextPage(state) {
|
|
504
|
+
private hasNextPage(state: DataFetchStore<TDefinition, TQuery>): boolean {
|
|
441
505
|
return state.cursors[state.pageNumber + 1] != null
|
|
442
506
|
}
|
|
443
507
|
|
|
@@ -447,7 +511,7 @@ export default class DataFetch {
|
|
|
447
511
|
* @param state the current store state
|
|
448
512
|
* @return {boolean} whether there is a previous page of data or not
|
|
449
513
|
*/
|
|
450
|
-
hasPrevPage(state) {
|
|
514
|
+
private hasPrevPage(state: { pageNumber: number }): boolean {
|
|
451
515
|
return state.pageNumber > 0
|
|
452
516
|
}
|
|
453
517
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Row } from "@budibase/types"
|
|
2
|
+
import DataFetch from "./DataFetch"
|
|
3
|
+
|
|
4
|
+
type Types = "field" | "queryarray" | "jsonarray"
|
|
5
|
+
|
|
6
|
+
export interface FieldDatasource<TType extends Types> {
|
|
7
|
+
type: TType
|
|
8
|
+
tableId: string
|
|
9
|
+
fieldType: "attachment" | "array"
|
|
10
|
+
value: string[] | Row[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface FieldDefinition {
|
|
14
|
+
schema?: Record<string, { type: string }> | null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isArrayOfStrings(value: string[] | Row[]): value is string[] {
|
|
18
|
+
return Array.isArray(value) && !!value[0] && typeof value[0] !== "object"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default class FieldFetch<TType extends Types> extends DataFetch<
|
|
22
|
+
FieldDatasource<TType>,
|
|
23
|
+
FieldDefinition
|
|
24
|
+
> {
|
|
25
|
+
async getDefinition(): Promise<FieldDefinition | null> {
|
|
26
|
+
const { datasource } = this.options
|
|
27
|
+
|
|
28
|
+
// Field sources have their schema statically defined
|
|
29
|
+
let schema
|
|
30
|
+
if (datasource.fieldType === "attachment") {
|
|
31
|
+
schema = {
|
|
32
|
+
url: {
|
|
33
|
+
type: "string",
|
|
34
|
+
},
|
|
35
|
+
name: {
|
|
36
|
+
type: "string",
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
} else if (datasource.fieldType === "array") {
|
|
40
|
+
schema = {
|
|
41
|
+
value: {
|
|
42
|
+
type: "string",
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { schema }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async getData() {
|
|
50
|
+
const { datasource } = this.options
|
|
51
|
+
|
|
52
|
+
// These sources will be available directly from context
|
|
53
|
+
const data = datasource?.value || []
|
|
54
|
+
let rows: Row[]
|
|
55
|
+
if (isArrayOfStrings(data)) {
|
|
56
|
+
rows = data.map(value => ({ value }))
|
|
57
|
+
} else {
|
|
58
|
+
rows = data
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
rows: rows || [],
|
|
63
|
+
hasNextPage: false,
|
|
64
|
+
cursor: null,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import { get } from "svelte/store"
|
|
2
|
-
import DataFetch from "./DataFetch
|
|
2
|
+
import DataFetch, { DataFetchParams } from "./DataFetch"
|
|
3
3
|
import { TableNames } from "../constants"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
interface GroupUserQuery {
|
|
6
|
+
groupId: string
|
|
7
|
+
emailSearch: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface GroupUserDatasource {
|
|
11
|
+
type: "groupUser"
|
|
12
|
+
tableId: TableNames.USERS
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default class GroupUserFetch extends DataFetch<
|
|
16
|
+
GroupUserDatasource,
|
|
17
|
+
{},
|
|
18
|
+
GroupUserQuery
|
|
19
|
+
> {
|
|
20
|
+
constructor(opts: DataFetchParams<GroupUserDatasource, GroupUserQuery>) {
|
|
7
21
|
super({
|
|
8
22
|
...opts,
|
|
9
23
|
datasource: {
|
|
24
|
+
type: "groupUser",
|
|
10
25
|
tableId: TableNames.USERS,
|
|
11
26
|
},
|
|
12
27
|
})
|
|
13
28
|
}
|
|
14
29
|
|
|
15
|
-
determineFeatureFlags() {
|
|
30
|
+
async determineFeatureFlags() {
|
|
16
31
|
return {
|
|
17
32
|
supportsSearch: true,
|
|
18
33
|
supportsSort: false,
|
|
@@ -28,11 +43,12 @@ export default class GroupUserFetch extends DataFetch {
|
|
|
28
43
|
|
|
29
44
|
async getData() {
|
|
30
45
|
const { query, cursor } = get(this.store)
|
|
46
|
+
|
|
31
47
|
try {
|
|
32
48
|
const res = await this.API.getGroupUsers({
|
|
33
49
|
id: query.groupId,
|
|
34
50
|
emailSearch: query.emailSearch,
|
|
35
|
-
bookmark: cursor,
|
|
51
|
+
bookmark: cursor ?? undefined,
|
|
36
52
|
})
|
|
37
53
|
|
|
38
54
|
return {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import FieldFetch from "./FieldFetch
|
|
1
|
+
import FieldFetch from "./FieldFetch"
|
|
2
2
|
import { getJSONArrayDatasourceSchema } from "../utils/json"
|
|
3
3
|
|
|
4
|
-
export default class JSONArrayFetch extends FieldFetch {
|
|
5
|
-
async getDefinition(
|
|
4
|
+
export default class JSONArrayFetch extends FieldFetch<"jsonarray"> {
|
|
5
|
+
async getDefinition() {
|
|
6
|
+
const { datasource } = this.options
|
|
7
|
+
|
|
6
8
|
// JSON arrays need their table definitions fetched.
|
|
7
9
|
// We can then extract their schema as a subset of the table schema.
|
|
8
10
|
try {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Row, TableSchema } from "@budibase/types"
|
|
2
|
+
import DataFetch from "./DataFetch"
|
|
3
|
+
|
|
4
|
+
interface NestedProviderDatasource {
|
|
5
|
+
type: "provider"
|
|
6
|
+
value?: {
|
|
7
|
+
schema: TableSchema
|
|
8
|
+
primaryDisplay: string
|
|
9
|
+
rows: Row[]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface NestedProviderDefinition {
|
|
14
|
+
schema?: TableSchema
|
|
15
|
+
primaryDisplay?: string
|
|
16
|
+
}
|
|
17
|
+
export default class NestedProviderFetch extends DataFetch<
|
|
18
|
+
NestedProviderDatasource,
|
|
19
|
+
NestedProviderDefinition
|
|
20
|
+
> {
|
|
21
|
+
async getDefinition() {
|
|
22
|
+
const { datasource } = this.options
|
|
23
|
+
|
|
24
|
+
// Nested providers should already have exposed their own schema
|
|
25
|
+
return {
|
|
26
|
+
schema: datasource?.value?.schema,
|
|
27
|
+
primaryDisplay: datasource?.value?.primaryDisplay,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getData() {
|
|
32
|
+
const { datasource } = this.options
|
|
33
|
+
// Pull the rows from the existing data provider
|
|
34
|
+
return {
|
|
35
|
+
rows: datasource?.value?.rows || [],
|
|
36
|
+
hasNextPage: false,
|
|
37
|
+
cursor: null,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import FieldFetch from "./FieldFetch
|
|
1
|
+
import FieldFetch from "./FieldFetch"
|
|
2
2
|
import {
|
|
3
3
|
getJSONArrayDatasourceSchema,
|
|
4
4
|
generateQueryArraySchemas,
|
|
5
5
|
} from "../utils/json"
|
|
6
6
|
|
|
7
|
-
export default class QueryArrayFetch extends FieldFetch {
|
|
8
|
-
async getDefinition(
|
|
7
|
+
export default class QueryArrayFetch extends FieldFetch<"queryarray"> {
|
|
8
|
+
async getDefinition() {
|
|
9
|
+
const { datasource } = this.options
|
|
10
|
+
|
|
9
11
|
if (!datasource?.tableId) {
|
|
10
12
|
return null
|
|
11
13
|
}
|
|
@@ -14,10 +16,14 @@ export default class QueryArrayFetch extends FieldFetch {
|
|
|
14
16
|
try {
|
|
15
17
|
const table = await this.API.fetchQueryDefinition(datasource.tableId)
|
|
16
18
|
const schema = generateQueryArraySchemas(
|
|
17
|
-
table
|
|
18
|
-
table
|
|
19
|
+
table.schema,
|
|
20
|
+
table.nestedSchemaFields
|
|
19
21
|
)
|
|
20
|
-
|
|
22
|
+
const result = {
|
|
23
|
+
schema: getJSONArrayDatasourceSchema(schema, datasource),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return result
|
|
21
27
|
} catch (error) {
|
|
22
28
|
return null
|
|
23
29
|
}
|