@budibase/frontend-core 2.12.7 → 2.12.9
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/components/grid/cells/RelationshipCell.svelte +29 -46
- package/src/components/grid/stores/cache.js +47 -0
- package/src/components/grid/stores/datasource.js +0 -6
- package/src/components/grid/stores/datasources/nonPlus.js +0 -6
- package/src/components/grid/stores/datasources/table.js +0 -6
- package/src/components/grid/stores/datasources/viewV2.js +0 -6
- package/src/components/grid/stores/index.js +2 -0
- package/src/components/grid/stores/rows.js +5 -5
- package/src/fetch/DataFetch.js +17 -4
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.9",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
7
7
|
"svelte": "src/index.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@budibase/bbui": "2.12.
|
|
10
|
-
"@budibase/shared-core": "2.12.
|
|
9
|
+
"@budibase/bbui": "2.12.9",
|
|
10
|
+
"@budibase/shared-core": "2.12.9",
|
|
11
11
|
"dayjs": "^1.10.8",
|
|
12
12
|
"lodash": "^4.17.21",
|
|
13
13
|
"socket.io-client": "^4.6.1",
|
|
14
14
|
"svelte": "^3.46.2"
|
|
15
15
|
},
|
|
16
|
-
"gitHead": "
|
|
16
|
+
"gitHead": "f12e5aa441469babaaede4b60a7ea7d09e094551"
|
|
17
17
|
}
|
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
<script context="module">
|
|
2
|
-
// We can create a module level cache for all relationship cells to avoid
|
|
3
|
-
// having to fetch the table definition one time for each cell
|
|
4
|
-
let primaryDisplayCache = {}
|
|
5
|
-
|
|
6
|
-
const getPrimaryDisplayForTableId = async (API, tableId) => {
|
|
7
|
-
if (primaryDisplayCache[tableId]) {
|
|
8
|
-
return primaryDisplayCache[tableId]
|
|
9
|
-
}
|
|
10
|
-
const definition = await API.fetchTableDefinition(tableId)
|
|
11
|
-
const primaryDisplay =
|
|
12
|
-
definition?.primaryDisplay || definition?.schema?.[0]?.name
|
|
13
|
-
primaryDisplayCache[tableId] = primaryDisplay
|
|
14
|
-
return primaryDisplay
|
|
15
|
-
}
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
1
|
<script>
|
|
19
2
|
import { getColor } from "../lib/utils"
|
|
20
3
|
import { onMount, getContext } from "svelte"
|
|
21
4
|
import { Icon, Input, ProgressCircle, clickOutside } from "@budibase/bbui"
|
|
22
5
|
import { debounce } from "../../../utils/utils"
|
|
23
6
|
|
|
24
|
-
const { API, dispatch } = getContext("grid")
|
|
7
|
+
const { API, dispatch, cache } = getContext("grid")
|
|
25
8
|
|
|
26
9
|
export let value
|
|
27
10
|
export let api
|
|
@@ -147,7 +130,9 @@
|
|
|
147
130
|
// Find the primary display for the related table
|
|
148
131
|
if (!primaryDisplay) {
|
|
149
132
|
searching = true
|
|
150
|
-
primaryDisplay = await getPrimaryDisplayForTableId(
|
|
133
|
+
primaryDisplay = await cache.actions.getPrimaryDisplayForTableId(
|
|
134
|
+
schema.tableId
|
|
135
|
+
)
|
|
151
136
|
}
|
|
152
137
|
|
|
153
138
|
// Show initial list of results
|
|
@@ -195,7 +180,7 @@
|
|
|
195
180
|
const toggleRow = async row => {
|
|
196
181
|
if (value?.some(x => x._id === row._id)) {
|
|
197
182
|
// If the row is already included, remove it and update the candidate
|
|
198
|
-
// row to be the
|
|
183
|
+
// row to be the same position if possible
|
|
199
184
|
if (oneRowOnly) {
|
|
200
185
|
await onChange([])
|
|
201
186
|
} else {
|
|
@@ -260,31 +245,29 @@
|
|
|
260
245
|
class:wrap={editable || contentLines > 1}
|
|
261
246
|
on:wheel={e => (focused ? e.stopPropagation() : null)}
|
|
262
247
|
>
|
|
263
|
-
{#
|
|
264
|
-
{#
|
|
265
|
-
|
|
266
|
-
<
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
{/each}
|
|
287
|
-
{/if}
|
|
248
|
+
{#each value || [] as relationship}
|
|
249
|
+
{#if relationship[primaryDisplay] || relationship.primaryDisplay}
|
|
250
|
+
<div class="badge">
|
|
251
|
+
<span
|
|
252
|
+
on:click={editable
|
|
253
|
+
? () => showRelationship(relationship._id)
|
|
254
|
+
: null}
|
|
255
|
+
>
|
|
256
|
+
{readable(
|
|
257
|
+
relationship[primaryDisplay] || relationship.primaryDisplay
|
|
258
|
+
)}
|
|
259
|
+
</span>
|
|
260
|
+
{#if editable}
|
|
261
|
+
<Icon
|
|
262
|
+
name="Close"
|
|
263
|
+
size="XS"
|
|
264
|
+
hoverable
|
|
265
|
+
on:click={() => toggleRow(relationship)}
|
|
266
|
+
/>
|
|
267
|
+
{/if}
|
|
268
|
+
</div>
|
|
269
|
+
{/if}
|
|
270
|
+
{/each}
|
|
288
271
|
{#if editable}
|
|
289
272
|
<div class="add" on:click={open}>
|
|
290
273
|
<Icon name="Add" size="S" />
|
|
@@ -320,7 +303,7 @@
|
|
|
320
303
|
<div class="searching">
|
|
321
304
|
<ProgressCircle size="S" />
|
|
322
305
|
</div>
|
|
323
|
-
{:else if
|
|
306
|
+
{:else if searchResults?.length}
|
|
324
307
|
<div class="results">
|
|
325
308
|
{#each searchResults as row, idx}
|
|
326
309
|
<div
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const createActions = context => {
|
|
2
|
+
const { API } = context
|
|
3
|
+
|
|
4
|
+
// Cache for the primary display columns of different tables.
|
|
5
|
+
// If we ever need to cache table definitions for other purposes then we can
|
|
6
|
+
// expand this to be a more generic cache.
|
|
7
|
+
let primaryDisplayCache = {}
|
|
8
|
+
|
|
9
|
+
const resetPrimaryDisplayCache = () => {
|
|
10
|
+
primaryDisplayCache = {}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const getPrimaryDisplayForTableId = async tableId => {
|
|
14
|
+
// If we've never encountered this tableId before then store a promise that
|
|
15
|
+
// resolves to the primary display so that subsequent invocations before the
|
|
16
|
+
// promise completes can reuse this promise
|
|
17
|
+
if (!primaryDisplayCache[tableId]) {
|
|
18
|
+
primaryDisplayCache[tableId] = new Promise(resolve => {
|
|
19
|
+
API.fetchTableDefinition(tableId).then(def => {
|
|
20
|
+
const display = def?.primaryDisplay || def?.schema?.[0]?.name
|
|
21
|
+
primaryDisplayCache[tableId] = display
|
|
22
|
+
resolve(display)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// We await the result so that we account for both promises and primitives
|
|
28
|
+
return await primaryDisplayCache[tableId]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
cache: {
|
|
33
|
+
actions: {
|
|
34
|
+
getPrimaryDisplayForTableId,
|
|
35
|
+
resetPrimaryDisplayCache,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const initialise = context => {
|
|
42
|
+
const { datasource, cache } = context
|
|
43
|
+
|
|
44
|
+
// Wipe the caches whenever the datasource changes to ensure we aren't
|
|
45
|
+
// storing any stale information
|
|
46
|
+
datasource.subscribe(cache.actions.resetPrimaryDisplayCache)
|
|
47
|
+
}
|
|
@@ -160,11 +160,6 @@ export const createActions = context => {
|
|
|
160
160
|
return getAPI()?.actions.canUseColumn(name)
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
// Gets the default number of rows for a single page
|
|
164
|
-
const getFeatures = () => {
|
|
165
|
-
return getAPI()?.actions.getFeatures()
|
|
166
|
-
}
|
|
167
|
-
|
|
168
163
|
return {
|
|
169
164
|
datasource: {
|
|
170
165
|
...datasource,
|
|
@@ -177,7 +172,6 @@ export const createActions = context => {
|
|
|
177
172
|
getRow,
|
|
178
173
|
isDatasourceValid,
|
|
179
174
|
canUseColumn,
|
|
180
|
-
getFeatures,
|
|
181
175
|
},
|
|
182
176
|
},
|
|
183
177
|
}
|
|
@@ -35,11 +35,6 @@ export const createActions = context => {
|
|
|
35
35
|
return $columns.some(col => col.name === name) || $sticky?.name === name
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const getFeatures = () => {
|
|
39
|
-
// We don't support any features
|
|
40
|
-
return {}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
return {
|
|
44
39
|
nonPlus: {
|
|
45
40
|
actions: {
|
|
@@ -50,7 +45,6 @@ export const createActions = context => {
|
|
|
50
45
|
getRow,
|
|
51
46
|
isDatasourceValid,
|
|
52
47
|
canUseColumn,
|
|
53
|
-
getFeatures,
|
|
54
48
|
},
|
|
55
49
|
},
|
|
56
50
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { get } from "svelte/store"
|
|
2
|
-
import TableFetch from "../../../../fetch/TableFetch"
|
|
3
2
|
|
|
4
3
|
const SuppressErrors = true
|
|
5
4
|
|
|
@@ -46,10 +45,6 @@ export const createActions = context => {
|
|
|
46
45
|
return $columns.some(col => col.name === name) || $sticky?.name === name
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
const getFeatures = () => {
|
|
50
|
-
return new TableFetch({ API }).determineFeatureFlags()
|
|
51
|
-
}
|
|
52
|
-
|
|
53
48
|
return {
|
|
54
49
|
table: {
|
|
55
50
|
actions: {
|
|
@@ -60,7 +55,6 @@ export const createActions = context => {
|
|
|
60
55
|
getRow,
|
|
61
56
|
isDatasourceValid,
|
|
62
57
|
canUseColumn,
|
|
63
|
-
getFeatures,
|
|
64
58
|
},
|
|
65
59
|
},
|
|
66
60
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { get } from "svelte/store"
|
|
2
|
-
import ViewV2Fetch from "../../../../fetch/ViewV2Fetch"
|
|
3
2
|
|
|
4
3
|
const SuppressErrors = true
|
|
5
4
|
|
|
@@ -46,10 +45,6 @@ export const createActions = context => {
|
|
|
46
45
|
)
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
const getFeatures = () => {
|
|
50
|
-
return new ViewV2Fetch({ API }).determineFeatureFlags()
|
|
51
|
-
}
|
|
52
|
-
|
|
53
48
|
return {
|
|
54
49
|
viewV2: {
|
|
55
50
|
actions: {
|
|
@@ -60,7 +55,6 @@ export const createActions = context => {
|
|
|
60
55
|
getRow,
|
|
61
56
|
isDatasourceValid,
|
|
62
57
|
canUseColumn,
|
|
63
|
-
getFeatures,
|
|
64
58
|
},
|
|
65
59
|
},
|
|
66
60
|
}
|
|
@@ -19,6 +19,7 @@ import * as Datasource from "./datasource"
|
|
|
19
19
|
import * as Table from "./datasources/table"
|
|
20
20
|
import * as ViewV2 from "./datasources/viewV2"
|
|
21
21
|
import * as NonPlus from "./datasources/nonPlus"
|
|
22
|
+
import * as Cache from "./cache"
|
|
22
23
|
|
|
23
24
|
const DependencyOrderedStores = [
|
|
24
25
|
Sort,
|
|
@@ -42,6 +43,7 @@ const DependencyOrderedStores = [
|
|
|
42
43
|
Clipboard,
|
|
43
44
|
Config,
|
|
44
45
|
Notifications,
|
|
46
|
+
Cache,
|
|
45
47
|
]
|
|
46
48
|
|
|
47
49
|
export const attachStores = context => {
|
|
@@ -114,10 +114,6 @@ export const createActions = context => {
|
|
|
114
114
|
const $allFilters = get(allFilters)
|
|
115
115
|
const $sort = get(sort)
|
|
116
116
|
|
|
117
|
-
// Determine how many rows to fetch per page
|
|
118
|
-
const features = datasource.actions.getFeatures()
|
|
119
|
-
const limit = features?.supportsPagination ? RowPageSize : null
|
|
120
|
-
|
|
121
117
|
// Create new fetch model
|
|
122
118
|
const newFetch = fetchData({
|
|
123
119
|
API,
|
|
@@ -126,8 +122,12 @@ export const createActions = context => {
|
|
|
126
122
|
filter: $allFilters,
|
|
127
123
|
sortColumn: $sort.column,
|
|
128
124
|
sortOrder: $sort.order,
|
|
129
|
-
limit,
|
|
125
|
+
limit: RowPageSize,
|
|
130
126
|
paginate: true,
|
|
127
|
+
|
|
128
|
+
// Disable client side limiting, so that for queries and custom data
|
|
129
|
+
// sources we don't impose fake row limits. We want all the data.
|
|
130
|
+
clientSideLimiting: false,
|
|
131
131
|
},
|
|
132
132
|
})
|
|
133
133
|
|
package/src/fetch/DataFetch.js
CHANGED
|
@@ -43,6 +43,11 @@ export default class DataFetch {
|
|
|
43
43
|
|
|
44
44
|
// Pagination config
|
|
45
45
|
paginate: true,
|
|
46
|
+
|
|
47
|
+
// Client side feature customisation
|
|
48
|
+
clientSideSearching: true,
|
|
49
|
+
clientSideSorting: true,
|
|
50
|
+
clientSideLimiting: true,
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
// State of the fetch
|
|
@@ -208,24 +213,32 @@ export default class DataFetch {
|
|
|
208
213
|
* Fetches some filtered, sorted and paginated data
|
|
209
214
|
*/
|
|
210
215
|
async getPage() {
|
|
211
|
-
const {
|
|
216
|
+
const {
|
|
217
|
+
sortColumn,
|
|
218
|
+
sortOrder,
|
|
219
|
+
sortType,
|
|
220
|
+
limit,
|
|
221
|
+
clientSideSearching,
|
|
222
|
+
clientSideSorting,
|
|
223
|
+
clientSideLimiting,
|
|
224
|
+
} = this.options
|
|
212
225
|
const { query } = get(this.store)
|
|
213
226
|
|
|
214
227
|
// Get the actual data
|
|
215
228
|
let { rows, info, hasNextPage, cursor, error } = await this.getData()
|
|
216
229
|
|
|
217
230
|
// If we don't support searching, do a client search
|
|
218
|
-
if (!this.features.supportsSearch) {
|
|
231
|
+
if (!this.features.supportsSearch && clientSideSearching) {
|
|
219
232
|
rows = runLuceneQuery(rows, query)
|
|
220
233
|
}
|
|
221
234
|
|
|
222
235
|
// If we don't support sorting, do a client-side sort
|
|
223
|
-
if (!this.features.supportsSort) {
|
|
236
|
+
if (!this.features.supportsSort && clientSideSorting) {
|
|
224
237
|
rows = luceneSort(rows, sortColumn, sortOrder, sortType)
|
|
225
238
|
}
|
|
226
239
|
|
|
227
240
|
// If we don't support pagination, do a client-side limit
|
|
228
|
-
if (!this.features.supportsPagination) {
|
|
241
|
+
if (!this.features.supportsPagination && clientSideLimiting) {
|
|
229
242
|
rows = luceneLimit(rows, limit)
|
|
230
243
|
}
|
|
231
244
|
|