@budibase/frontend-core 2.8.21 → 2.8.22-alpha.1
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/api/app.js +9 -0
- package/src/api/index.js +2 -0
- package/src/api/logs.js +14 -0
- package/src/components/UserAvatar.svelte +9 -44
- package/src/components/UserAvatars.svelte +67 -0
- package/src/components/grid/cells/RelationshipCell.svelte +1 -1
- package/src/components/grid/layout/Grid.svelte +2 -1
- package/src/components/grid/layout/GridBody.svelte +2 -2
- package/src/components/grid/layout/HeaderRow.svelte +20 -9
- package/src/components/grid/layout/NewRow.svelte +20 -12
- package/src/components/grid/layout/StickyColumn.svelte +2 -3
- package/src/components/grid/overlays/KeyboardManager.svelte +3 -2
- package/src/components/grid/overlays/MenuOverlay.svelte +2 -1
- package/src/components/grid/overlays/ResizeOverlay.svelte +2 -9
- package/src/components/grid/stores/columns.js +16 -0
- package/src/components/grid/stores/ui.js +11 -0
- package/src/components/grid/stores/users.js +3 -2
- package/src/components/index.js +1 -0
- package/src/utils/download.js +23 -0
- package/src/utils/index.js +1 -1
- package/src/components/grid/controls/AddColumnButton.svelte +0 -16
- package/src/components/grid/controls/AddRowButton.svelte +0 -18
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.22-alpha.1",
|
|
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.8.
|
|
10
|
-
"@budibase/shared-core": "2.8.
|
|
9
|
+
"@budibase/bbui": "2.8.22-alpha.1",
|
|
10
|
+
"@budibase/shared-core": "2.8.22-alpha.1",
|
|
11
11
|
"dayjs": "^1.11.7",
|
|
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": "efcef8d6f8ce0744d1f80f8161a41f55ef6c8ea4"
|
|
17
17
|
}
|
package/src/api/app.js
CHANGED
|
@@ -123,6 +123,15 @@ export const buildAppEndpoints = API => ({
|
|
|
123
123
|
})
|
|
124
124
|
},
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Gets budibase platform debug information.
|
|
128
|
+
*/
|
|
129
|
+
fetchSystemDebugInfo: async () => {
|
|
130
|
+
return await API.get({
|
|
131
|
+
url: `/api/debug/diagnostics`,
|
|
132
|
+
})
|
|
133
|
+
},
|
|
134
|
+
|
|
126
135
|
/**
|
|
127
136
|
* Syncs an app with the production database.
|
|
128
137
|
* @param appId the ID of the app to sync
|
package/src/api/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import { buildBackupsEndpoints } from "./backups"
|
|
|
30
30
|
import { buildEnvironmentVariableEndpoints } from "./environmentVariables"
|
|
31
31
|
import { buildEventEndpoints } from "./events"
|
|
32
32
|
import { buildAuditLogsEndpoints } from "./auditLogs"
|
|
33
|
+
import { buildLogsEndpoints } from "./logs"
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Random identifier to uniquely identify a session in a tab. This is
|
|
@@ -277,5 +278,6 @@ export const createAPIClient = config => {
|
|
|
277
278
|
...buildEnvironmentVariableEndpoints(API),
|
|
278
279
|
...buildEventEndpoints(API),
|
|
279
280
|
...buildAuditLogsEndpoints(API),
|
|
281
|
+
...buildLogsEndpoints(API),
|
|
280
282
|
}
|
|
281
283
|
}
|
package/src/api/logs.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const buildLogsEndpoints = API => ({
|
|
2
|
+
/**
|
|
3
|
+
* Gets a stream for the system logs.
|
|
4
|
+
*/
|
|
5
|
+
getSystemLogs: async () => {
|
|
6
|
+
return await API.get({
|
|
7
|
+
url: "/api/system/logs",
|
|
8
|
+
json: false,
|
|
9
|
+
parseResponse: async response => {
|
|
10
|
+
return response
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
},
|
|
14
|
+
})
|
|
@@ -1,58 +1,23 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { Avatar,
|
|
2
|
+
import { Avatar, AbsTooltip, TooltipPosition } from "@budibase/bbui"
|
|
3
3
|
import { helpers } from "@budibase/shared-core"
|
|
4
4
|
|
|
5
5
|
export let user
|
|
6
|
-
export let size
|
|
7
|
-
export let
|
|
6
|
+
export let size = "S"
|
|
7
|
+
export let tooltipPosition = TooltipPosition.Top
|
|
8
8
|
export let showTooltip = true
|
|
9
|
-
|
|
10
|
-
$: tooltipStyle = getTooltipStyle(tooltipDirection)
|
|
11
|
-
|
|
12
|
-
const getTooltipStyle = direction => {
|
|
13
|
-
if (!direction) {
|
|
14
|
-
return ""
|
|
15
|
-
}
|
|
16
|
-
if (direction === "top") {
|
|
17
|
-
return "transform: translateX(-50%) translateY(-100%);"
|
|
18
|
-
} else if (direction === "bottom") {
|
|
19
|
-
return "transform: translateX(-50%) translateY(100%);"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
9
|
</script>
|
|
23
10
|
|
|
24
11
|
{#if user}
|
|
25
|
-
<
|
|
12
|
+
<AbsTooltip
|
|
13
|
+
text={showTooltip ? helpers.getUserLabel(user) : null}
|
|
14
|
+
position={tooltipPosition}
|
|
15
|
+
color={helpers.getUserColor(user)}
|
|
16
|
+
>
|
|
26
17
|
<Avatar
|
|
27
18
|
{size}
|
|
28
19
|
initials={helpers.getUserInitials(user)}
|
|
29
20
|
color={helpers.getUserColor(user)}
|
|
30
21
|
/>
|
|
31
|
-
|
|
32
|
-
<div class="tooltip" style={tooltipStyle}>
|
|
33
|
-
<Tooltip
|
|
34
|
-
direction={tooltipDirection}
|
|
35
|
-
textWrapping
|
|
36
|
-
text={user.email}
|
|
37
|
-
size="S"
|
|
38
|
-
/>
|
|
39
|
-
</div>
|
|
40
|
-
{/if}
|
|
41
|
-
</div>
|
|
22
|
+
</AbsTooltip>
|
|
42
23
|
{/if}
|
|
43
|
-
|
|
44
|
-
<style>
|
|
45
|
-
.user-avatar {
|
|
46
|
-
position: relative;
|
|
47
|
-
}
|
|
48
|
-
.tooltip {
|
|
49
|
-
display: none;
|
|
50
|
-
position: absolute;
|
|
51
|
-
top: 0;
|
|
52
|
-
left: 50%;
|
|
53
|
-
white-space: nowrap;
|
|
54
|
-
}
|
|
55
|
-
.user-avatar:hover .tooltip {
|
|
56
|
-
display: block;
|
|
57
|
-
}
|
|
58
|
-
</style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { UserAvatar } from "@budibase/frontend-core"
|
|
3
|
+
import { TooltipPosition, Avatar } from "@budibase/bbui"
|
|
4
|
+
|
|
5
|
+
export let users = []
|
|
6
|
+
export let order = "ltr"
|
|
7
|
+
export let size = "S"
|
|
8
|
+
export let tooltipPosition = TooltipPosition.Top
|
|
9
|
+
|
|
10
|
+
$: uniqueUsers = unique(users, order)
|
|
11
|
+
$: avatars = getAvatars(uniqueUsers, order)
|
|
12
|
+
|
|
13
|
+
const unique = users => {
|
|
14
|
+
let uniqueUsers = {}
|
|
15
|
+
users?.forEach(user => {
|
|
16
|
+
uniqueUsers[user.email] = user
|
|
17
|
+
})
|
|
18
|
+
return Object.values(uniqueUsers)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const getAvatars = (users, order) => {
|
|
22
|
+
const avatars = users.slice(0, 3)
|
|
23
|
+
if (users.length > 3) {
|
|
24
|
+
const overflow = {
|
|
25
|
+
_id: "overflow",
|
|
26
|
+
label: `+${users.length - 3}`,
|
|
27
|
+
}
|
|
28
|
+
if (order === "ltr") {
|
|
29
|
+
avatars.push(overflow)
|
|
30
|
+
} else {
|
|
31
|
+
avatars.unshift(overflow)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return avatars.map((user, idx) => ({
|
|
35
|
+
...user,
|
|
36
|
+
zIndex: order === "ltr" ? idx : uniqueUsers.length - idx,
|
|
37
|
+
}))
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<div class="avatars">
|
|
42
|
+
{#each avatars as user}
|
|
43
|
+
<span style="z-index:{user.zIndex};">
|
|
44
|
+
{#if user._id === "overflow"}
|
|
45
|
+
<Avatar
|
|
46
|
+
{size}
|
|
47
|
+
initials={user.label}
|
|
48
|
+
color="var(--spectrum-global-color-gray-500)"
|
|
49
|
+
/>
|
|
50
|
+
{:else}
|
|
51
|
+
<UserAvatar {size} {user} {tooltipPosition} />
|
|
52
|
+
{/if}
|
|
53
|
+
</span>
|
|
54
|
+
{/each}
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<style>
|
|
58
|
+
.avatars {
|
|
59
|
+
display: flex;
|
|
60
|
+
}
|
|
61
|
+
span:not(:first-of-type) {
|
|
62
|
+
margin-left: -6px;
|
|
63
|
+
}
|
|
64
|
+
.avatars :global(.spectrum-Avatar) {
|
|
65
|
+
border: 2px solid var(--avatars-background, var(--background));
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
class:wrap={editable || contentLines > 1}
|
|
259
259
|
on:wheel={e => (focused ? e.stopPropagation() : null)}
|
|
260
260
|
>
|
|
261
|
-
{#each value || [] as relationship
|
|
261
|
+
{#each value || [] as relationship}
|
|
262
262
|
{#if relationship.primaryDisplay}
|
|
263
263
|
<div class="badge">
|
|
264
264
|
<span
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
contentLines,
|
|
72
72
|
gridFocused,
|
|
73
73
|
error,
|
|
74
|
+
canAddRows,
|
|
74
75
|
} = context
|
|
75
76
|
|
|
76
77
|
// Keep config store up to date with props
|
|
@@ -143,7 +144,7 @@
|
|
|
143
144
|
<HeaderRow />
|
|
144
145
|
<GridBody />
|
|
145
146
|
</div>
|
|
146
|
-
{#if
|
|
147
|
+
{#if $canAddRows}
|
|
147
148
|
<NewRow />
|
|
148
149
|
{/if}
|
|
149
150
|
<div class="overlays">
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
renderedRows,
|
|
10
10
|
renderedColumns,
|
|
11
11
|
rowVerticalInversionIndex,
|
|
12
|
-
|
|
12
|
+
canAddRows,
|
|
13
13
|
hoveredRowId,
|
|
14
14
|
dispatch,
|
|
15
15
|
isDragging,
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
invertY={idx >= $rowVerticalInversionIndex}
|
|
44
44
|
/>
|
|
45
45
|
{/each}
|
|
46
|
-
{#if $
|
|
46
|
+
{#if $canAddRows}
|
|
47
47
|
<div
|
|
48
48
|
class="blank"
|
|
49
49
|
class:highlighted={$hoveredRowId === BlankRowID}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { getContext } from "svelte"
|
|
3
3
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
4
4
|
import HeaderCell from "../cells/HeaderCell.svelte"
|
|
5
|
-
import { Icon } from "@budibase/bbui"
|
|
5
|
+
import { Icon, TempTooltip, TooltipType } from "@budibase/bbui"
|
|
6
6
|
|
|
7
7
|
const {
|
|
8
8
|
renderedColumns,
|
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
hiddenColumnsWidth,
|
|
12
12
|
width,
|
|
13
13
|
config,
|
|
14
|
+
hasNonAutoColumn,
|
|
15
|
+
tableId,
|
|
16
|
+
loading,
|
|
14
17
|
} = getContext("grid")
|
|
15
18
|
|
|
16
19
|
$: columnsWidth = $renderedColumns.reduce(
|
|
17
|
-
(total, col) =>
|
|
20
|
+
(total, col) => total + col.width,
|
|
18
21
|
0
|
|
19
22
|
)
|
|
20
23
|
$: end = $hiddenColumnsWidth + columnsWidth - 1 - $scroll.left
|
|
@@ -30,13 +33,21 @@
|
|
|
30
33
|
</div>
|
|
31
34
|
</GridScrollWrapper>
|
|
32
35
|
{#if $config.allowSchemaChanges}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
{#key $tableId}
|
|
37
|
+
<TempTooltip
|
|
38
|
+
text="Click here to create your first column"
|
|
39
|
+
type={TooltipType.Info}
|
|
40
|
+
condition={!$hasNonAutoColumn && !$loading}
|
|
41
|
+
>
|
|
42
|
+
<div
|
|
43
|
+
class="add"
|
|
44
|
+
style="left:{left}px;"
|
|
45
|
+
on:click={() => dispatch("add-column")}
|
|
46
|
+
>
|
|
47
|
+
<Icon name="Add" />
|
|
48
|
+
</div>
|
|
49
|
+
</TempTooltip>
|
|
50
|
+
{/key}
|
|
40
51
|
{/if}
|
|
41
52
|
</div>
|
|
42
53
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { getContext, onDestroy, onMount, tick } from "svelte"
|
|
3
|
-
import { Icon, Button } from "@budibase/bbui"
|
|
3
|
+
import { Icon, Button, TempTooltip, TooltipType } from "@budibase/bbui"
|
|
4
4
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
5
5
|
import DataCell from "../cells/DataCell.svelte"
|
|
6
6
|
import { fade } from "svelte/transition"
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
rowVerticalInversionIndex,
|
|
28
28
|
columnHorizontalInversionIndex,
|
|
29
29
|
selectedRows,
|
|
30
|
-
|
|
30
|
+
loading,
|
|
31
|
+
canAddRows,
|
|
31
32
|
} = getContext("grid")
|
|
32
33
|
|
|
33
34
|
let visible = false
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
$: $tableId, (visible = false)
|
|
41
42
|
$: invertY = shouldInvertY(offset, $rowVerticalInversionIndex, $renderedRows)
|
|
42
43
|
$: selectedRowCount = Object.values($selectedRows).length
|
|
44
|
+
$: hasNoRows = !$rows.length
|
|
43
45
|
|
|
44
46
|
const shouldInvertY = (offset, inversionIndex, rows) => {
|
|
45
47
|
if (offset === 0) {
|
|
@@ -147,16 +149,22 @@
|
|
|
147
149
|
</script>
|
|
148
150
|
|
|
149
151
|
<!-- New row FAB -->
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
{
|
|
152
|
+
<TempTooltip
|
|
153
|
+
text="Click here to create your first row"
|
|
154
|
+
condition={hasNoRows && !$loading}
|
|
155
|
+
type={TooltipType.Info}
|
|
156
|
+
>
|
|
157
|
+
{#if !visible && !selectedRowCount && $canAddRows}
|
|
158
|
+
<div
|
|
159
|
+
class="new-row-fab"
|
|
160
|
+
on:click={() => dispatch("add-row-inline")}
|
|
161
|
+
transition:fade|local={{ duration: 130 }}
|
|
162
|
+
class:offset={!$stickyColumn}
|
|
163
|
+
>
|
|
164
|
+
<Icon name="Add" size="S" />
|
|
165
|
+
</div>
|
|
166
|
+
{/if}
|
|
167
|
+
</TempTooltip>
|
|
160
168
|
|
|
161
169
|
<!-- Only show new row functionality if we have any columns -->
|
|
162
170
|
{#if visible}
|
|
@@ -13,11 +13,10 @@
|
|
|
13
13
|
rows,
|
|
14
14
|
selectedRows,
|
|
15
15
|
stickyColumn,
|
|
16
|
-
renderedColumns,
|
|
17
16
|
renderedRows,
|
|
18
17
|
focusedCellId,
|
|
19
18
|
hoveredRowId,
|
|
20
|
-
|
|
19
|
+
canAddRows,
|
|
21
20
|
selectedCellMap,
|
|
22
21
|
focusedRow,
|
|
23
22
|
scrollLeft,
|
|
@@ -93,7 +92,7 @@
|
|
|
93
92
|
{/if}
|
|
94
93
|
</div>
|
|
95
94
|
{/each}
|
|
96
|
-
{#if $
|
|
95
|
+
{#if $canAddRows}
|
|
97
96
|
<div
|
|
98
97
|
class="row new"
|
|
99
98
|
on:mouseenter={$isDragging
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
config,
|
|
17
17
|
menu,
|
|
18
18
|
gridFocused,
|
|
19
|
+
canAddRows,
|
|
19
20
|
} = getContext("grid")
|
|
20
21
|
|
|
21
22
|
const ignoredOriginSelectors = [
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
e.preventDefault()
|
|
46
47
|
focusFirstCell()
|
|
47
48
|
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
|
48
|
-
if ($
|
|
49
|
+
if ($canAddRows) {
|
|
49
50
|
e.preventDefault()
|
|
50
51
|
dispatch("add-row-inline")
|
|
51
52
|
}
|
|
@@ -99,7 +100,7 @@
|
|
|
99
100
|
}
|
|
100
101
|
break
|
|
101
102
|
case "Enter":
|
|
102
|
-
if ($
|
|
103
|
+
if ($canAddRows) {
|
|
103
104
|
dispatch("add-row-inline")
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
focusedCellAPI,
|
|
18
18
|
focusedRowId,
|
|
19
19
|
notifications,
|
|
20
|
+
canAddRows,
|
|
20
21
|
} = getContext("grid")
|
|
21
22
|
|
|
22
23
|
$: style = makeStyle($menu)
|
|
@@ -93,7 +94,7 @@
|
|
|
93
94
|
</MenuItem>
|
|
94
95
|
<MenuItem
|
|
95
96
|
icon="Duplicate"
|
|
96
|
-
disabled={isNewRow || !$
|
|
97
|
+
disabled={isNewRow || !$canAddRows}
|
|
97
98
|
on:click={duplicate}
|
|
98
99
|
>
|
|
99
100
|
Duplicate row
|
|
@@ -2,16 +2,9 @@
|
|
|
2
2
|
import { getContext } from "svelte"
|
|
3
3
|
import { GutterWidth } from "../lib/constants"
|
|
4
4
|
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
resize,
|
|
8
|
-
renderedColumns,
|
|
9
|
-
stickyColumn,
|
|
10
|
-
isReordering,
|
|
11
|
-
scrollLeft,
|
|
12
|
-
} = getContext("grid")
|
|
5
|
+
const { resize, renderedColumns, stickyColumn, isReordering, scrollLeft } =
|
|
6
|
+
getContext("grid")
|
|
13
7
|
|
|
14
|
-
$: cutoff = $scrollLeft + GutterWidth + ($columns[0]?.width || 0)
|
|
15
8
|
$: offset = GutterWidth + ($stickyColumn?.width || 0)
|
|
16
9
|
$: activeColumn = $resize.column
|
|
17
10
|
|
|
@@ -83,6 +83,21 @@ export const deriveStores = context => {
|
|
|
83
83
|
await saveChanges()
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// Derive if we have any normal columns
|
|
87
|
+
const hasNonAutoColumn = derived(
|
|
88
|
+
[columns, stickyColumn],
|
|
89
|
+
([$columns, $stickyColumn]) => {
|
|
90
|
+
let allCols = $columns || []
|
|
91
|
+
if ($stickyColumn) {
|
|
92
|
+
allCols = [...allCols, $stickyColumn]
|
|
93
|
+
}
|
|
94
|
+
const normalCols = allCols.filter(column => {
|
|
95
|
+
return !column.schema?.autocolumn
|
|
96
|
+
})
|
|
97
|
+
return normalCols.length > 0
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
86
101
|
// Persists column changes by saving metadata against table schema
|
|
87
102
|
const saveChanges = async () => {
|
|
88
103
|
const $columns = get(columns)
|
|
@@ -128,6 +143,7 @@ export const deriveStores = context => {
|
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
return {
|
|
146
|
+
hasNonAutoColumn,
|
|
131
147
|
columns: {
|
|
132
148
|
...columns,
|
|
133
149
|
actions: {
|
|
@@ -70,6 +70,8 @@ export const deriveStores = context => {
|
|
|
70
70
|
rowHeight,
|
|
71
71
|
stickyColumn,
|
|
72
72
|
width,
|
|
73
|
+
hasNonAutoColumn,
|
|
74
|
+
config,
|
|
73
75
|
} = context
|
|
74
76
|
|
|
75
77
|
// Derive the row that contains the selected cell
|
|
@@ -112,7 +114,16 @@ export const deriveStores = context => {
|
|
|
112
114
|
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
|
|
113
115
|
})
|
|
114
116
|
|
|
117
|
+
// Derive if we're able to add rows
|
|
118
|
+
const canAddRows = derived(
|
|
119
|
+
[config, hasNonAutoColumn],
|
|
120
|
+
([$config, $hasNonAutoColumn]) => {
|
|
121
|
+
return $config.allowAddRows && $hasNonAutoColumn
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
|
|
115
125
|
return {
|
|
126
|
+
canAddRows,
|
|
116
127
|
focusedRow,
|
|
117
128
|
contentLines,
|
|
118
129
|
compact,
|
|
@@ -30,8 +30,9 @@ export const deriveStores = context => {
|
|
|
30
30
|
([$users, $focusedCellId]) => {
|
|
31
31
|
let map = {}
|
|
32
32
|
$users.forEach(user => {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const cellId = user.gridMetadata?.focusedCellId
|
|
34
|
+
if (cellId && cellId !== $focusedCellId) {
|
|
35
|
+
map[cellId] = user
|
|
35
36
|
}
|
|
36
37
|
})
|
|
37
38
|
return map
|
package/src/components/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export { default as SplitPage } from "./SplitPage.svelte"
|
|
|
2
2
|
export { default as TestimonialPage } from "./TestimonialPage.svelte"
|
|
3
3
|
export { default as Testimonial } from "./Testimonial.svelte"
|
|
4
4
|
export { default as UserAvatar } from "./UserAvatar.svelte"
|
|
5
|
+
export { default as UserAvatars } from "./UserAvatars.svelte"
|
|
5
6
|
export { Grid } from "./grid"
|
package/src/utils/download.js
CHANGED
|
@@ -11,3 +11,26 @@ export function downloadText(filename, text) {
|
|
|
11
11
|
|
|
12
12
|
URL.revokeObjectURL(url)
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
export async function downloadStream(streamResponse) {
|
|
16
|
+
const blob = await streamResponse.blob()
|
|
17
|
+
|
|
18
|
+
const contentDisposition = streamResponse.headers.get("Content-Disposition")
|
|
19
|
+
|
|
20
|
+
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(
|
|
21
|
+
contentDisposition
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const filename = matches[1].replace(/['"]/g, "")
|
|
25
|
+
|
|
26
|
+
const resBlob = new Blob([blob])
|
|
27
|
+
|
|
28
|
+
const blobUrl = URL.createObjectURL(resBlob)
|
|
29
|
+
|
|
30
|
+
const link = document.createElement("a")
|
|
31
|
+
link.href = blobUrl
|
|
32
|
+
link.download = filename
|
|
33
|
+
link.click()
|
|
34
|
+
|
|
35
|
+
URL.revokeObjectURL(blobUrl)
|
|
36
|
+
}
|
package/src/utils/index.js
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { ActionButton } from "@budibase/bbui"
|
|
3
|
-
import { getContext } from "svelte"
|
|
4
|
-
|
|
5
|
-
const { config, dispatch } = getContext("grid")
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<ActionButton
|
|
9
|
-
icon="TableColumnAddRight"
|
|
10
|
-
quiet
|
|
11
|
-
size="M"
|
|
12
|
-
on:click={() => dispatch("add-column")}
|
|
13
|
-
disabled={!$config.allowSchemaChanges}
|
|
14
|
-
>
|
|
15
|
-
Add column
|
|
16
|
-
</ActionButton>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { ActionButton } from "@budibase/bbui"
|
|
3
|
-
import { getContext } from "svelte"
|
|
4
|
-
|
|
5
|
-
const { dispatch, columns, stickyColumn, config, loaded } = getContext("grid")
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<ActionButton
|
|
9
|
-
icon="TableRowAddBottom"
|
|
10
|
-
quiet
|
|
11
|
-
size="M"
|
|
12
|
-
on:click={() => dispatch("add-row-inline")}
|
|
13
|
-
disabled={!loaded ||
|
|
14
|
-
!$config.allowAddRows ||
|
|
15
|
-
(!$columns.length && !$stickyColumn)}
|
|
16
|
-
>
|
|
17
|
-
Add row
|
|
18
|
-
</ActionButton>
|