@budibase/frontend-core 3.15.0 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/api/app.ts +0 -12
- package/src/api/backups.ts +11 -0
- package/src/api/workspaceApps.ts +7 -0
- package/src/components/grid/cells/HeaderCell.svelte +48 -37
- package/src/components/grid/layout/Grid.svelte +32 -7
- package/src/components/grid/stores/clipboard.ts +94 -11
- package/src/components/grid/stores/index.ts +5 -1
- package/src/components/grid/stores/rows.ts +12 -0
- package/src/fetch/DataFetch.ts +1 -0
- package/src/stores/gridClipboard.ts +67 -0
- package/src/stores/index.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.16.0",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"shortid": "2.2.15",
|
|
18
18
|
"socket.io-client": "^4.7.5"
|
|
19
19
|
},
|
|
20
|
-
"gitHead": "
|
|
20
|
+
"gitHead": "d20f1f44d10db8eb79d7b7e47c670f3fce502547"
|
|
21
21
|
}
|
package/src/api/app.ts
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
PublishAppResponse,
|
|
21
21
|
RevertAppClientResponse,
|
|
22
22
|
RevertAppResponse,
|
|
23
|
-
SyncAppResponse,
|
|
24
23
|
UnpublishAppResponse,
|
|
25
24
|
UpdateAppClientResponse,
|
|
26
25
|
UpdateAppRequest,
|
|
@@ -54,7 +53,6 @@ export interface AppEndpoints {
|
|
|
54
53
|
body: ImportToUpdateAppRequest
|
|
55
54
|
) => Promise<ImportToUpdateAppResponse>
|
|
56
55
|
fetchSystemDebugInfo: () => Promise<GetDiagnosticsResponse>
|
|
57
|
-
syncApp: (appId: string) => Promise<SyncAppResponse>
|
|
58
56
|
getApps: () => Promise<FetchAppsResponse>
|
|
59
57
|
fetchComponentLibDefinitions: (
|
|
60
58
|
appId: string
|
|
@@ -235,16 +233,6 @@ export const buildAppEndpoints = (API: BaseAPIClient): AppEndpoints => ({
|
|
|
235
233
|
})
|
|
236
234
|
},
|
|
237
235
|
|
|
238
|
-
/**
|
|
239
|
-
* Syncs an app with the production database.
|
|
240
|
-
* @param appId the ID of the app to sync
|
|
241
|
-
*/
|
|
242
|
-
syncApp: async appId => {
|
|
243
|
-
return await API.post({
|
|
244
|
-
url: `/api/applications/${appId}/sync`,
|
|
245
|
-
})
|
|
246
|
-
},
|
|
247
|
-
|
|
248
236
|
/**
|
|
249
237
|
* Gets a list of apps.
|
|
250
238
|
*/
|
package/src/api/backups.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
SearchAppBackupsRequest,
|
|
5
5
|
ClearBackupErrorRequest,
|
|
6
6
|
ClearBackupErrorResponse,
|
|
7
|
+
DeleteAppBackupsResponse,
|
|
7
8
|
} from "@budibase/types"
|
|
8
9
|
import { BaseAPIClient } from "./types"
|
|
9
10
|
|
|
@@ -21,6 +22,10 @@ export interface BackupEndpoints {
|
|
|
21
22
|
appId: string,
|
|
22
23
|
backupId: string
|
|
23
24
|
) => Promise<{ message: string }>
|
|
25
|
+
deleteBackups: (
|
|
26
|
+
appId: string,
|
|
27
|
+
backupIds: string[]
|
|
28
|
+
) => Promise<DeleteAppBackupsResponse>
|
|
24
29
|
clearBackupErrors: (
|
|
25
30
|
appId: string,
|
|
26
31
|
backupId?: string
|
|
@@ -44,6 +49,12 @@ export const buildBackupEndpoints = (API: BaseAPIClient): BackupEndpoints => ({
|
|
|
44
49
|
url: `/api/apps/${appId}/backups/${backupId}`,
|
|
45
50
|
})
|
|
46
51
|
},
|
|
52
|
+
deleteBackups: async (appId, backupIds) => {
|
|
53
|
+
return await API.delete({
|
|
54
|
+
url: `/api/apps/${appId}/backups`,
|
|
55
|
+
body: { backupIds },
|
|
56
|
+
})
|
|
57
|
+
},
|
|
47
58
|
restoreBackup: async (appId, backupId, name) => {
|
|
48
59
|
return await API.post({
|
|
49
60
|
url: `/api/apps/${appId}/backups/${backupId}/import`,
|
package/src/api/workspaceApps.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FetchWorkspaceAppResponse,
|
|
3
|
+
FindWorkspaceAppResponse,
|
|
3
4
|
InsertWorkspaceAppRequest,
|
|
4
5
|
InsertWorkspaceAppResponse,
|
|
5
6
|
UpdateWorkspaceAppRequest,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
import { BaseAPIClient } from "./types"
|
|
9
10
|
|
|
10
11
|
export interface WorkspaceAppEndpoints {
|
|
12
|
+
find: (id: string) => Promise<FindWorkspaceAppResponse>
|
|
11
13
|
fetch: () => Promise<FetchWorkspaceAppResponse>
|
|
12
14
|
create: (
|
|
13
15
|
workspaceApp: InsertWorkspaceAppRequest
|
|
@@ -21,6 +23,11 @@ export interface WorkspaceAppEndpoints {
|
|
|
21
23
|
export const buildWorkspaceAppEndpoints = (
|
|
22
24
|
API: BaseAPIClient
|
|
23
25
|
): WorkspaceAppEndpoints => ({
|
|
26
|
+
find: async id => {
|
|
27
|
+
return await API.get({
|
|
28
|
+
url: `/api/workspaceApp/${id}`,
|
|
29
|
+
})
|
|
30
|
+
},
|
|
24
31
|
fetch: async () => {
|
|
25
32
|
return await API.get({
|
|
26
33
|
url: "/api/workspaceApp",
|
|
@@ -359,23 +359,23 @@
|
|
|
359
359
|
</div>
|
|
360
360
|
{:else}
|
|
361
361
|
<Menu>
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
icon="copy"
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
362
|
+
{#if $config.canEditColumns}
|
|
363
|
+
<MenuItem icon="pencil" on:click={editColumn} disabled={!editable}>
|
|
364
|
+
Edit column
|
|
365
|
+
</MenuItem>
|
|
366
|
+
<MenuItem icon="copy" on:click={duplicateColumn}>
|
|
367
|
+
Duplicate column
|
|
368
|
+
</MenuItem>
|
|
369
|
+
<MenuItem
|
|
370
|
+
icon="tag"
|
|
371
|
+
on:click={makeDisplayColumn}
|
|
372
|
+
disabled={!$config.canEditColumns ||
|
|
373
|
+
column.primaryDisplay ||
|
|
374
|
+
!canBeDisplayColumn(column.schema)}
|
|
375
|
+
>
|
|
376
|
+
Use as display column
|
|
377
|
+
</MenuItem>
|
|
378
|
+
{/if}
|
|
379
379
|
<MenuItem
|
|
380
380
|
icon="sort-ascending"
|
|
381
381
|
on:click={sortAscending}
|
|
@@ -394,27 +394,35 @@
|
|
|
394
394
|
>
|
|
395
395
|
Sort {sortingLabels.descending}
|
|
396
396
|
</MenuItem>
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
>
|
|
412
|
-
Hide column
|
|
413
|
-
</MenuItem>
|
|
414
|
-
{#if $config.canEditColumns && column.schema.type === "link" && column.schema.tableId === TableNames.USERS && !column.schema.autocolumn}
|
|
415
|
-
<MenuItem icon="user" on:click={openMigrationModal}>
|
|
416
|
-
Migrate to user column
|
|
397
|
+
{#if $config.canEditColumns}
|
|
398
|
+
<MenuItem
|
|
399
|
+
disabled={!canMoveLeft}
|
|
400
|
+
icon="caret-left"
|
|
401
|
+
on:click={moveLeft}
|
|
402
|
+
>
|
|
403
|
+
Move left
|
|
404
|
+
</MenuItem>
|
|
405
|
+
<MenuItem
|
|
406
|
+
disabled={!canMoveRight}
|
|
407
|
+
icon="caret-right"
|
|
408
|
+
on:click={moveRight}
|
|
409
|
+
>
|
|
410
|
+
Move right
|
|
417
411
|
</MenuItem>
|
|
412
|
+
<MenuItem
|
|
413
|
+
disabled={!$config.canEditColumns ||
|
|
414
|
+
column.primaryDisplay ||
|
|
415
|
+
!$config.canHideColumns}
|
|
416
|
+
icon="eye-slash"
|
|
417
|
+
on:click={hideColumn}
|
|
418
|
+
>
|
|
419
|
+
Hide column
|
|
420
|
+
</MenuItem>
|
|
421
|
+
{#if $config.canEditColumns && column.schema.type === "link" && column.schema.tableId === TableNames.USERS && !column.schema.autocolumn}
|
|
422
|
+
<MenuItem icon="user" on:click={openMigrationModal}>
|
|
423
|
+
Migrate to user column
|
|
424
|
+
</MenuItem>
|
|
425
|
+
{/if}
|
|
418
426
|
{/if}
|
|
419
427
|
</Menu>
|
|
420
428
|
{/if}
|
|
@@ -455,6 +463,9 @@
|
|
|
455
463
|
display: none;
|
|
456
464
|
width: 18px;
|
|
457
465
|
}
|
|
466
|
+
.clear-icon {
|
|
467
|
+
z-index: 99;
|
|
468
|
+
}
|
|
458
469
|
.header-cell.searchable:not(.open):hover .search-icon,
|
|
459
470
|
.header-cell.searchable.searching .search-icon {
|
|
460
471
|
display: block;
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
import { fade } from "svelte/transition"
|
|
5
5
|
import { clickOutside, ProgressCircle } from "@budibase/bbui"
|
|
6
6
|
import { createEventManagers } from "../lib/events"
|
|
7
|
-
import { createAPIClient } from "../../../api"
|
|
7
|
+
import { type APIClient, createAPIClient } from "../../../api"
|
|
8
8
|
import { attachStores } from "../stores"
|
|
9
9
|
import BulkDeleteHandler from "../controls/BulkDeleteHandler.svelte"
|
|
10
10
|
import BulkDuplicationHandler from "../controls/BulkDuplicationHandler.svelte"
|
|
11
11
|
import ClipboardHandler from "../controls/ClipboardHandler.svelte"
|
|
12
|
+
import { type ExternalClipboardData } from "../../../stores/gridClipboard"
|
|
12
13
|
import GridBody from "./GridBody.svelte"
|
|
13
14
|
import ResizeOverlay from "../overlays/ResizeOverlay.svelte"
|
|
14
15
|
import ReorderOverlay from "../overlays/ReorderOverlay.svelte"
|
|
@@ -23,9 +24,20 @@
|
|
|
23
24
|
import { createGridWebsocket } from "../lib/websocket"
|
|
24
25
|
import * as Constants from "../lib/constants"
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
type SchemaOverride = {
|
|
28
|
+
displayName?: string
|
|
29
|
+
type?: string
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
roles?: any
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export let API: APIClient | null | undefined = null
|
|
35
|
+
// TODO: work out best type to suit datasource
|
|
36
|
+
export let datasource: any = null
|
|
37
|
+
export let schemaOverrides:
|
|
38
|
+
| Record<string, SchemaOverride>
|
|
39
|
+
| null
|
|
40
|
+
| undefined = null
|
|
29
41
|
export let canAddRows = true
|
|
30
42
|
export let canExpandRows = true
|
|
31
43
|
export let canEditRows = true
|
|
@@ -42,13 +54,14 @@
|
|
|
42
54
|
export let fixedRowHeight = null
|
|
43
55
|
export let notifySuccess = null
|
|
44
56
|
export let notifyError = null
|
|
45
|
-
export let buttons = null
|
|
57
|
+
export let buttons: { text: string; onClick: any }[] | null | undefined = null
|
|
46
58
|
export let buttonsCollapsed = false
|
|
47
59
|
export let buttonsCollapsedText = null
|
|
48
60
|
export let darkMode = false
|
|
49
|
-
export let isCloud = null
|
|
61
|
+
export let isCloud: boolean | null | undefined = null
|
|
50
62
|
export let aiEnabled = false
|
|
51
63
|
export let canHideColumns = true
|
|
64
|
+
export let externalClipboard: ExternalClipboardData | undefined = undefined
|
|
52
65
|
|
|
53
66
|
// Unique identifier for DOM nodes inside this instance
|
|
54
67
|
const gridID = `grid-${Math.random().toString().slice(2)}`
|
|
@@ -77,6 +90,8 @@
|
|
|
77
90
|
contentLines,
|
|
78
91
|
gridFocused,
|
|
79
92
|
error,
|
|
93
|
+
definitionMissing,
|
|
94
|
+
dispatch,
|
|
80
95
|
} = context
|
|
81
96
|
|
|
82
97
|
// Keep config store up to date with props
|
|
@@ -106,8 +121,16 @@
|
|
|
106
121
|
isCloud,
|
|
107
122
|
aiEnabled,
|
|
108
123
|
canHideColumns,
|
|
124
|
+
externalClipboard,
|
|
109
125
|
})
|
|
110
126
|
|
|
127
|
+
// missing definition, propagate this
|
|
128
|
+
$: if ($definitionMissing) {
|
|
129
|
+
dispatch("definitionMissing", {
|
|
130
|
+
datasource,
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
111
134
|
// Derive min height and make available in context
|
|
112
135
|
const minHeight = derived(rowHeight, $height => {
|
|
113
136
|
const heightForControls = $$slots.controls ? Constants.ControlsHeight : 0
|
|
@@ -209,7 +232,9 @@
|
|
|
209
232
|
<BulkDeleteHandler />
|
|
210
233
|
<ClipboardHandler />
|
|
211
234
|
<KeyboardManager />
|
|
212
|
-
|
|
235
|
+
{#if $loaded}
|
|
236
|
+
<slot />
|
|
237
|
+
{/if}
|
|
213
238
|
</div>
|
|
214
239
|
|
|
215
240
|
<style>
|
|
@@ -3,6 +3,7 @@ import { Helpers } from "@budibase/bbui"
|
|
|
3
3
|
import { parseCellID, getCellID } from "../lib/utils"
|
|
4
4
|
import { NewRowID } from "../lib/constants"
|
|
5
5
|
import { Store as StoreContext } from "."
|
|
6
|
+
import { ExternalClipboardData } from "../../../stores/gridClipboard"
|
|
6
7
|
|
|
7
8
|
type ClipboardStoreData =
|
|
8
9
|
| {
|
|
@@ -34,19 +35,47 @@ interface ClipboardActions {
|
|
|
34
35
|
|
|
35
36
|
export type Store = ClipboardStore & ClipboardDerivedStore & ClipboardActions
|
|
36
37
|
|
|
37
|
-
export const createStores = (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
export const createStores = (context?: {
|
|
39
|
+
externalClipboard: ExternalClipboardData
|
|
40
|
+
}): ClipboardStore => {
|
|
41
|
+
// Initialize with external clipboard state if provided
|
|
42
|
+
let initialState: ClipboardStoreData
|
|
43
|
+
|
|
44
|
+
if (context?.externalClipboard?.clipboard) {
|
|
45
|
+
const externalState = context.externalClipboard.clipboard.get()
|
|
46
|
+
if (externalState.multiCellCopy) {
|
|
47
|
+
initialState = {
|
|
48
|
+
value: externalState.value,
|
|
49
|
+
multiCellCopy: true,
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
initialState = {
|
|
53
|
+
value: externalState.value,
|
|
54
|
+
multiCellCopy: false,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
initialState = {
|
|
59
|
+
value: undefined,
|
|
60
|
+
multiCellCopy: false,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const clipboard = writable<ClipboardStoreData>(initialState)
|
|
42
65
|
return {
|
|
43
66
|
clipboard,
|
|
44
67
|
}
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
export const deriveStores = (context: StoreContext): ClipboardDerivedStore => {
|
|
48
|
-
const {
|
|
49
|
-
|
|
71
|
+
const {
|
|
72
|
+
clipboard,
|
|
73
|
+
focusedCellAPI,
|
|
74
|
+
selectedCellCount,
|
|
75
|
+
config,
|
|
76
|
+
focusedRowId,
|
|
77
|
+
props,
|
|
78
|
+
} = context
|
|
50
79
|
|
|
51
80
|
// Derive whether or not we're able to copy
|
|
52
81
|
const copyAllowed = derived(focusedCellAPI, $focusedCellAPI => {
|
|
@@ -55,16 +84,24 @@ export const deriveStores = (context: StoreContext): ClipboardDerivedStore => {
|
|
|
55
84
|
|
|
56
85
|
// Derive whether or not we're able to paste
|
|
57
86
|
const pasteAllowed = derived(
|
|
58
|
-
[clipboard, focusedCellAPI, selectedCellCount, config, focusedRowId],
|
|
87
|
+
[clipboard, focusedCellAPI, selectedCellCount, config, focusedRowId, props],
|
|
59
88
|
([
|
|
60
89
|
$clipboard,
|
|
61
90
|
$focusedCellAPI,
|
|
62
91
|
$selectedCellCount,
|
|
63
92
|
$config,
|
|
64
93
|
$focusedRowId,
|
|
94
|
+
$props,
|
|
65
95
|
]) => {
|
|
96
|
+
// Check if we have clipboard data (internal or external)
|
|
97
|
+
let hasClipboardData = $clipboard.value != null
|
|
98
|
+
if (!hasClipboardData && $props.externalClipboard?.clipboard) {
|
|
99
|
+
const externalState = $props.externalClipboard.clipboard.get()
|
|
100
|
+
hasClipboardData = externalState.value != null
|
|
101
|
+
}
|
|
102
|
+
|
|
66
103
|
if (
|
|
67
|
-
|
|
104
|
+
!hasClipboardData ||
|
|
68
105
|
!$config.canEditRows ||
|
|
69
106
|
!$focusedCellAPI ||
|
|
70
107
|
$focusedRowId === NewRowID
|
|
@@ -105,6 +142,7 @@ export const createActions = (context: StoreContext): ClipboardActions => {
|
|
|
105
142
|
focusedCellId,
|
|
106
143
|
columnLookupMap,
|
|
107
144
|
visibleColumns,
|
|
145
|
+
props,
|
|
108
146
|
} = context
|
|
109
147
|
|
|
110
148
|
// Copies the currently selected value (or values)
|
|
@@ -137,11 +175,22 @@ export const createActions = (context: StoreContext): ClipboardActions => {
|
|
|
137
175
|
value.push(rowValues)
|
|
138
176
|
}
|
|
139
177
|
|
|
140
|
-
// Update state
|
|
178
|
+
// Update internal state
|
|
141
179
|
clipboard.set({
|
|
142
180
|
value,
|
|
143
181
|
multiCellCopy: true,
|
|
144
182
|
})
|
|
183
|
+
|
|
184
|
+
const { externalClipboard } = get(props)
|
|
185
|
+
// Sync with external clipboard if provided
|
|
186
|
+
if (externalClipboard?.onCopy) {
|
|
187
|
+
externalClipboard.onCopy({
|
|
188
|
+
value,
|
|
189
|
+
multiCellCopy: true,
|
|
190
|
+
tableId: externalClipboard.tableId,
|
|
191
|
+
viewId: externalClipboard.viewId,
|
|
192
|
+
})
|
|
193
|
+
}
|
|
145
194
|
} else {
|
|
146
195
|
// Single value to copy
|
|
147
196
|
const value = $focusedCellAPI?.getValue()
|
|
@@ -150,6 +199,17 @@ export const createActions = (context: StoreContext): ClipboardActions => {
|
|
|
150
199
|
multiCellCopy,
|
|
151
200
|
})
|
|
152
201
|
|
|
202
|
+
const { externalClipboard } = get(props)
|
|
203
|
+
// Sync with external clipboard if provided
|
|
204
|
+
if (externalClipboard?.onCopy) {
|
|
205
|
+
externalClipboard.onCopy({
|
|
206
|
+
value,
|
|
207
|
+
multiCellCopy: false,
|
|
208
|
+
tableId: externalClipboard.tableId,
|
|
209
|
+
viewId: externalClipboard.viewId,
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
153
213
|
// Also copy a stringified version to the clipboard
|
|
154
214
|
let stringified = ""
|
|
155
215
|
if (value != null && value !== "") {
|
|
@@ -165,7 +225,30 @@ export const createActions = (context: StoreContext): ClipboardActions => {
|
|
|
165
225
|
if (!get(pasteAllowed)) {
|
|
166
226
|
return
|
|
167
227
|
}
|
|
168
|
-
|
|
228
|
+
|
|
229
|
+
// Check for external clipboard data first
|
|
230
|
+
const { externalClipboard } = get(props)
|
|
231
|
+
let clipboardData = get(clipboard)
|
|
232
|
+
|
|
233
|
+
if (externalClipboard?.clipboard) {
|
|
234
|
+
const externalState = externalClipboard.clipboard.get()
|
|
235
|
+
// Use external clipboard data if it has a value
|
|
236
|
+
if (externalState.value !== undefined) {
|
|
237
|
+
if (externalState.multiCellCopy) {
|
|
238
|
+
clipboardData = {
|
|
239
|
+
value: externalState.value as any[][],
|
|
240
|
+
multiCellCopy: true,
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
clipboardData = {
|
|
244
|
+
value: externalState.value,
|
|
245
|
+
multiCellCopy: false,
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const { value, multiCellCopy } = clipboardData
|
|
169
252
|
const multiCellPaste = get(selectedCellCount) > 1
|
|
170
253
|
|
|
171
254
|
// Choose paste strategy
|
|
@@ -26,6 +26,8 @@ import * as Cache from "./cache"
|
|
|
26
26
|
import * as Conditions from "./conditions"
|
|
27
27
|
import { SortOrder, UIDatasource, UISearchFilter } from "@budibase/types"
|
|
28
28
|
import * as Constants from "../lib/constants"
|
|
29
|
+
import * as GridClipboard from "../../../stores/gridClipboard"
|
|
30
|
+
import { ExternalClipboardData } from "../../../stores/gridClipboard"
|
|
29
31
|
|
|
30
32
|
const DependencyOrderedStores = [
|
|
31
33
|
Sort,
|
|
@@ -76,6 +78,7 @@ export interface BaseStoreProps {
|
|
|
76
78
|
canSaveSchema?: boolean
|
|
77
79
|
minHeight?: number
|
|
78
80
|
canHideColumns?: boolean
|
|
81
|
+
externalClipboard?: ExternalClipboardData
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
export interface BaseStore {
|
|
@@ -109,7 +112,8 @@ export type Store = BaseStore &
|
|
|
109
112
|
Viewport.Store &
|
|
110
113
|
Notifications.Store &
|
|
111
114
|
Sort.Store &
|
|
112
|
-
Bounds.Store
|
|
115
|
+
Bounds.Store &
|
|
116
|
+
GridClipboard.Store
|
|
113
117
|
|
|
114
118
|
export const attachStores = (context: BaseStore): Store => {
|
|
115
119
|
// Atomic store creation
|
|
@@ -29,6 +29,7 @@ interface RowStore {
|
|
|
29
29
|
inProgressChanges: Writable<Record<string, number>>
|
|
30
30
|
hasNextPage: Writable<boolean>
|
|
31
31
|
error: Writable<string | null>
|
|
32
|
+
definitionMissing: Writable<boolean>
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
interface RowDerivedStore {
|
|
@@ -87,6 +88,7 @@ export const createStores = (): RowStore => {
|
|
|
87
88
|
const inProgressChanges = writable({})
|
|
88
89
|
const hasNextPage = writable(false)
|
|
89
90
|
const error = writable(null)
|
|
91
|
+
const definitionMissing = writable(false)
|
|
90
92
|
const fetch = writable(null)
|
|
91
93
|
|
|
92
94
|
// Mark loaded as true if we've ever stopped loading
|
|
@@ -109,6 +111,7 @@ export const createStores = (): RowStore => {
|
|
|
109
111
|
inProgressChanges,
|
|
110
112
|
hasNextPage,
|
|
111
113
|
error,
|
|
114
|
+
definitionMissing,
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
|
|
@@ -192,6 +195,7 @@ export const createActions = (context: StoreContext): RowActionStore => {
|
|
|
192
195
|
inProgressChanges,
|
|
193
196
|
hasNextPage,
|
|
194
197
|
error,
|
|
198
|
+
definitionMissing,
|
|
195
199
|
notifications,
|
|
196
200
|
fetch,
|
|
197
201
|
hasBudibaseIdentifiers,
|
|
@@ -250,6 +254,14 @@ export const createActions = (context: StoreContext): RowActionStore => {
|
|
|
250
254
|
let message = "An unknown error occurred"
|
|
251
255
|
if ($fetch.error.status === 403) {
|
|
252
256
|
message = "You don't have access to this data"
|
|
257
|
+
} else if (
|
|
258
|
+
($fetch.error.status === 404 &&
|
|
259
|
+
$fetch.error.url &&
|
|
260
|
+
$fetch.error.url.includes("/api/tables/")) ||
|
|
261
|
+
$fetch.error.url.includes("/api/v2/views/")
|
|
262
|
+
) {
|
|
263
|
+
definitionMissing.set(true)
|
|
264
|
+
message = $fetch.error.message
|
|
253
265
|
} else if ($fetch.error.message) {
|
|
254
266
|
message = $fetch.error.message
|
|
255
267
|
}
|
package/src/fetch/DataFetch.ts
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { writable, get, type Writable } from "svelte/store"
|
|
2
|
+
|
|
3
|
+
export interface GridClipboardState {
|
|
4
|
+
value: any
|
|
5
|
+
multiCellCopy: boolean
|
|
6
|
+
sourceTableId?: string
|
|
7
|
+
sourceViewId?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface GridClipboardStore extends Writable<GridClipboardState> {
|
|
11
|
+
copy: (
|
|
12
|
+
value: any,
|
|
13
|
+
multiCellCopy: boolean,
|
|
14
|
+
tableId?: string,
|
|
15
|
+
viewId?: string
|
|
16
|
+
) => void
|
|
17
|
+
clear: () => void
|
|
18
|
+
get: () => GridClipboardState
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ExternalClipboardData {
|
|
22
|
+
clipboard: GridClipboardStore
|
|
23
|
+
tableId?: string
|
|
24
|
+
viewId?: string
|
|
25
|
+
onCopy: (data: {
|
|
26
|
+
value: any
|
|
27
|
+
multiCellCopy: boolean
|
|
28
|
+
tableId?: string
|
|
29
|
+
viewId?: string
|
|
30
|
+
}) => void
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type Store = GridClipboardStore
|
|
34
|
+
|
|
35
|
+
const createGridClipboard = (): GridClipboardStore => {
|
|
36
|
+
const store = writable<GridClipboardState>({
|
|
37
|
+
value: undefined,
|
|
38
|
+
multiCellCopy: false,
|
|
39
|
+
sourceTableId: undefined,
|
|
40
|
+
sourceViewId: undefined,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
subscribe: store.subscribe,
|
|
45
|
+
set: store.set,
|
|
46
|
+
update: store.update,
|
|
47
|
+
copy: (value, multiCellCopy, tableId, viewId) => {
|
|
48
|
+
store.set({
|
|
49
|
+
value,
|
|
50
|
+
multiCellCopy,
|
|
51
|
+
sourceTableId: tableId,
|
|
52
|
+
sourceViewId: viewId,
|
|
53
|
+
})
|
|
54
|
+
},
|
|
55
|
+
clear: () => {
|
|
56
|
+
store.set({
|
|
57
|
+
value: undefined,
|
|
58
|
+
multiCellCopy: false,
|
|
59
|
+
sourceTableId: undefined,
|
|
60
|
+
sourceViewId: undefined,
|
|
61
|
+
})
|
|
62
|
+
},
|
|
63
|
+
get: () => get(store),
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const gridClipboard = createGridClipboard()
|
package/src/stores/index.js
CHANGED