@budibase/frontend-core 2.8.31-alpha.0 → 2.8.31
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 +0 -9
- package/src/api/index.js +0 -2
- package/src/components/UserAvatar.svelte +44 -9
- package/src/components/grid/cells/HeaderCell.svelte +49 -83
- package/src/components/grid/cells/OptionsCell.svelte +2 -3
- package/src/components/grid/cells/RelationshipCell.svelte +1 -1
- package/src/components/grid/controls/AddColumnButton.svelte +16 -0
- package/src/components/grid/controls/AddRowButton.svelte +18 -0
- package/src/components/grid/layout/Grid.svelte +3 -15
- package/src/components/grid/layout/GridBody.svelte +2 -2
- package/src/components/grid/layout/HeaderRow.svelte +41 -19
- package/src/components/grid/layout/NewRow.svelte +12 -20
- package/src/components/grid/layout/StickyColumn.svelte +4 -5
- package/src/components/grid/overlays/KeyboardManager.svelte +2 -3
- package/src/components/grid/overlays/MenuOverlay.svelte +1 -2
- package/src/components/grid/overlays/ResizeOverlay.svelte +9 -2
- package/src/components/grid/stores/columns.js +0 -16
- package/src/components/grid/stores/ui.js +0 -11
- package/src/components/grid/stores/users.js +2 -3
- package/src/components/index.js +0 -1
- package/src/utils/download.js +0 -23
- package/src/utils/index.js +1 -1
- package/src/api/logs.js +0 -14
- package/src/components/UserAvatars.svelte +0 -67
- package/src/components/grid/layout/NewColumnButton.svelte +0 -79
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.8.31
|
|
3
|
+
"version": "2.8.31",
|
|
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.31
|
|
10
|
-
"@budibase/shared-core": "2.8.31
|
|
9
|
+
"@budibase/bbui": "2.8.31",
|
|
10
|
+
"@budibase/shared-core": "2.8.31",
|
|
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": "4613b17c1e76328bf279998c821a17195fbaab37"
|
|
17
17
|
}
|
package/src/api/app.js
CHANGED
|
@@ -123,15 +123,6 @@ 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
|
-
|
|
135
126
|
/**
|
|
136
127
|
* Syncs an app with the production database.
|
|
137
128
|
* @param appId the ID of the app to sync
|
package/src/api/index.js
CHANGED
|
@@ -30,7 +30,6 @@ 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"
|
|
34
33
|
|
|
35
34
|
/**
|
|
36
35
|
* Random identifier to uniquely identify a session in a tab. This is
|
|
@@ -278,6 +277,5 @@ export const createAPIClient = config => {
|
|
|
278
277
|
...buildEnvironmentVariableEndpoints(API),
|
|
279
278
|
...buildEventEndpoints(API),
|
|
280
279
|
...buildAuditLogsEndpoints(API),
|
|
281
|
-
...buildLogsEndpoints(API),
|
|
282
280
|
}
|
|
283
281
|
}
|
|
@@ -1,23 +1,58 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { Avatar,
|
|
2
|
+
import { Avatar, Tooltip } 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
|
|
7
|
+
export let tooltipDirection = "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
|
+
}
|
|
9
22
|
</script>
|
|
10
23
|
|
|
11
24
|
{#if user}
|
|
12
|
-
<
|
|
13
|
-
text={showTooltip ? helpers.getUserLabel(user) : null}
|
|
14
|
-
position={tooltipPosition}
|
|
15
|
-
color={helpers.getUserColor(user)}
|
|
16
|
-
>
|
|
25
|
+
<div class="user-avatar">
|
|
17
26
|
<Avatar
|
|
18
27
|
{size}
|
|
19
28
|
initials={helpers.getUserInitials(user)}
|
|
20
29
|
color={helpers.getUserColor(user)}
|
|
21
30
|
/>
|
|
22
|
-
|
|
31
|
+
{#if showTooltip}
|
|
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>
|
|
23
42
|
{/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>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { getContext
|
|
2
|
+
import { getContext } from "svelte"
|
|
3
3
|
import GridCell from "./GridCell.svelte"
|
|
4
|
-
import { Icon, Popover, Menu, MenuItem
|
|
4
|
+
import { Icon, Popover, Menu, MenuItem } from "@budibase/bbui"
|
|
5
5
|
import { getColumnIcon } from "../lib/utils"
|
|
6
6
|
|
|
7
7
|
export let column
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
sort,
|
|
17
17
|
renderedColumns,
|
|
18
18
|
dispatch,
|
|
19
|
-
subscribe,
|
|
20
19
|
config,
|
|
21
20
|
ui,
|
|
22
21
|
columns,
|
|
@@ -27,14 +26,13 @@
|
|
|
27
26
|
"array",
|
|
28
27
|
"attachment",
|
|
29
28
|
"boolean",
|
|
29
|
+
"formula",
|
|
30
30
|
"json",
|
|
31
31
|
]
|
|
32
32
|
|
|
33
33
|
let anchor
|
|
34
34
|
let open = false
|
|
35
|
-
let editIsOpen = false
|
|
36
35
|
let timeout
|
|
37
|
-
let popover
|
|
38
36
|
|
|
39
37
|
$: sortedBy = column.name === $sort.column
|
|
40
38
|
$: canMoveLeft = orderable && idx > 0
|
|
@@ -46,16 +44,11 @@
|
|
|
46
44
|
? "high-low"
|
|
47
45
|
: "Z-A"
|
|
48
46
|
|
|
49
|
-
const editColumn =
|
|
50
|
-
editIsOpen = true
|
|
51
|
-
await tick()
|
|
47
|
+
const editColumn = () => {
|
|
52
48
|
dispatch("edit-column", column.schema)
|
|
49
|
+
open = false
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
const cancelEdit = () => {
|
|
56
|
-
popover.hide()
|
|
57
|
-
editIsOpen = false
|
|
58
|
-
}
|
|
59
52
|
const onMouseDown = e => {
|
|
60
53
|
if (e.button === 0 && orderable) {
|
|
61
54
|
timeout = setTimeout(() => {
|
|
@@ -116,7 +109,6 @@
|
|
|
116
109
|
columns.actions.saveChanges()
|
|
117
110
|
open = false
|
|
118
111
|
}
|
|
119
|
-
onMount(() => subscribe("close-edit-column", cancelEdit))
|
|
120
112
|
</script>
|
|
121
113
|
|
|
122
114
|
<div
|
|
@@ -165,74 +157,57 @@
|
|
|
165
157
|
|
|
166
158
|
<Popover
|
|
167
159
|
bind:open
|
|
168
|
-
bind:this={popover}
|
|
169
160
|
{anchor}
|
|
170
161
|
align="right"
|
|
171
162
|
offset={0}
|
|
172
163
|
popoverTarget={document.getElementById(`grid-${rand}`)}
|
|
173
164
|
animate={false}
|
|
174
|
-
customZindex={100}
|
|
175
165
|
>
|
|
176
|
-
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
class="content"
|
|
166
|
+
<Menu>
|
|
167
|
+
<MenuItem
|
|
168
|
+
icon="Edit"
|
|
169
|
+
on:click={editColumn}
|
|
170
|
+
disabled={!$config.allowSchemaChanges || column.schema.disabled}
|
|
182
171
|
>
|
|
183
|
-
|
|
184
|
-
</
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
icon="ChevronRight"
|
|
223
|
-
on:click={moveRight}
|
|
224
|
-
>
|
|
225
|
-
Move right
|
|
226
|
-
</MenuItem>
|
|
227
|
-
<MenuItem
|
|
228
|
-
disabled={idx === "sticky" || !$config.showControls}
|
|
229
|
-
icon="VisibilityOff"
|
|
230
|
-
on:click={hideColumn}
|
|
231
|
-
>
|
|
232
|
-
Hide column
|
|
233
|
-
</MenuItem>
|
|
234
|
-
</Menu>
|
|
235
|
-
{/if}
|
|
172
|
+
Edit column
|
|
173
|
+
</MenuItem>
|
|
174
|
+
<MenuItem
|
|
175
|
+
icon="Label"
|
|
176
|
+
on:click={makeDisplayColumn}
|
|
177
|
+
disabled={idx === "sticky" ||
|
|
178
|
+
!$config.allowSchemaChanges ||
|
|
179
|
+
bannedDisplayColumnTypes.includes(column.schema.type)}
|
|
180
|
+
>
|
|
181
|
+
Use as display column
|
|
182
|
+
</MenuItem>
|
|
183
|
+
<MenuItem
|
|
184
|
+
icon="SortOrderUp"
|
|
185
|
+
on:click={sortAscending}
|
|
186
|
+
disabled={column.name === $sort.column && $sort.order === "ascending"}
|
|
187
|
+
>
|
|
188
|
+
Sort {ascendingLabel}
|
|
189
|
+
</MenuItem>
|
|
190
|
+
<MenuItem
|
|
191
|
+
icon="SortOrderDown"
|
|
192
|
+
on:click={sortDescending}
|
|
193
|
+
disabled={column.name === $sort.column && $sort.order === "descending"}
|
|
194
|
+
>
|
|
195
|
+
Sort {descendingLabel}
|
|
196
|
+
</MenuItem>
|
|
197
|
+
<MenuItem disabled={!canMoveLeft} icon="ChevronLeft" on:click={moveLeft}>
|
|
198
|
+
Move left
|
|
199
|
+
</MenuItem>
|
|
200
|
+
<MenuItem disabled={!canMoveRight} icon="ChevronRight" on:click={moveRight}>
|
|
201
|
+
Move right
|
|
202
|
+
</MenuItem>
|
|
203
|
+
<MenuItem
|
|
204
|
+
disabled={idx === "sticky" || !$config.showControls}
|
|
205
|
+
icon="VisibilityOff"
|
|
206
|
+
on:click={hideColumn}
|
|
207
|
+
>
|
|
208
|
+
Hide column
|
|
209
|
+
</MenuItem>
|
|
210
|
+
</Menu>
|
|
236
211
|
</Popover>
|
|
237
212
|
|
|
238
213
|
<style>
|
|
@@ -280,13 +255,4 @@
|
|
|
280
255
|
.header-cell:hover .sort-indicator {
|
|
281
256
|
display: none;
|
|
282
257
|
}
|
|
283
|
-
|
|
284
|
-
.content {
|
|
285
|
-
width: 300px;
|
|
286
|
-
padding: 20px;
|
|
287
|
-
display: flex;
|
|
288
|
-
flex-direction: column;
|
|
289
|
-
gap: 20px;
|
|
290
|
-
background: var(--spectrum-alias-background-color-secondary);
|
|
291
|
-
}
|
|
292
258
|
</style>
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
let focusedOptionIdx = null
|
|
19
19
|
|
|
20
20
|
$: options = schema?.constraints?.inclusion || []
|
|
21
|
-
$: optionColors = schema?.optionColors || {}
|
|
22
21
|
$: editable = focused && !readonly
|
|
23
22
|
$: values = Array.isArray(value) ? value : [value].filter(x => x != null)
|
|
24
23
|
$: {
|
|
@@ -94,7 +93,7 @@
|
|
|
94
93
|
on:click={editable ? open : null}
|
|
95
94
|
>
|
|
96
95
|
{#each values as val}
|
|
97
|
-
{@const color =
|
|
96
|
+
{@const color = getOptionColor(val)}
|
|
98
97
|
{#if color}
|
|
99
98
|
<div class="badge text" style="--color: {color}">
|
|
100
99
|
<span>
|
|
@@ -122,7 +121,7 @@
|
|
|
122
121
|
use:clickOutside={close}
|
|
123
122
|
>
|
|
124
123
|
{#each options as option, idx}
|
|
125
|
-
{@const color =
|
|
124
|
+
{@const color = getOptionColor(option)}
|
|
126
125
|
<div
|
|
127
126
|
class="option"
|
|
128
127
|
on:click={() => toggleOption(option)}
|
|
@@ -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, idx}
|
|
262
262
|
{#if relationship.primaryDisplay}
|
|
263
263
|
<div class="badge">
|
|
264
264
|
<span
|
|
@@ -0,0 +1,16 @@
|
|
|
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>
|
|
@@ -0,0 +1,18 @@
|
|
|
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>
|
|
@@ -71,7 +71,6 @@
|
|
|
71
71
|
contentLines,
|
|
72
72
|
gridFocused,
|
|
73
73
|
error,
|
|
74
|
-
canAddRows,
|
|
75
74
|
} = context
|
|
76
75
|
|
|
77
76
|
// Keep config store up to date with props
|
|
@@ -139,23 +138,12 @@
|
|
|
139
138
|
{#if $loaded}
|
|
140
139
|
<div class="grid-data-outer" use:clickOutside={ui.actions.blur}>
|
|
141
140
|
<div class="grid-data-inner">
|
|
142
|
-
<StickyColumn
|
|
143
|
-
<svelte:fragment slot="edit-column">
|
|
144
|
-
<slot name="edit-column" />
|
|
145
|
-
</svelte:fragment>
|
|
146
|
-
</StickyColumn>
|
|
141
|
+
<StickyColumn />
|
|
147
142
|
<div class="grid-data-content">
|
|
148
|
-
<HeaderRow
|
|
149
|
-
<svelte:fragment slot="add-column">
|
|
150
|
-
<slot name="add-column" />
|
|
151
|
-
</svelte:fragment>
|
|
152
|
-
<svelte:fragment slot="edit-column">
|
|
153
|
-
<slot name="edit-column" />
|
|
154
|
-
</svelte:fragment>
|
|
155
|
-
</HeaderRow>
|
|
143
|
+
<HeaderRow />
|
|
156
144
|
<GridBody />
|
|
157
145
|
</div>
|
|
158
|
-
{#if
|
|
146
|
+
{#if allowAddRows}
|
|
159
147
|
<NewRow />
|
|
160
148
|
{/if}
|
|
161
149
|
<div class="overlays">
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
renderedRows,
|
|
10
10
|
renderedColumns,
|
|
11
11
|
rowVerticalInversionIndex,
|
|
12
|
-
|
|
12
|
+
config,
|
|
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 $config.allowAddRows && $renderedColumns.length}
|
|
47
47
|
<div
|
|
48
48
|
class="blank"
|
|
49
49
|
class:highlighted={$hoveredRowId === BlankRowID}
|
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import NewColumnButton from "./NewColumnButton.svelte"
|
|
3
|
-
|
|
4
2
|
import { getContext } from "svelte"
|
|
5
3
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
6
4
|
import HeaderCell from "../cells/HeaderCell.svelte"
|
|
7
|
-
import {
|
|
5
|
+
import { Icon } from "@budibase/bbui"
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
renderedColumns,
|
|
9
|
+
dispatch,
|
|
10
|
+
scroll,
|
|
11
|
+
hiddenColumnsWidth,
|
|
12
|
+
width,
|
|
13
|
+
config,
|
|
14
|
+
} = getContext("grid")
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
$: columnsWidth = $renderedColumns.reduce(
|
|
17
|
+
(total, col) => (total += col.width),
|
|
18
|
+
0
|
|
19
|
+
)
|
|
20
|
+
$: end = $hiddenColumnsWidth + columnsWidth - 1 - $scroll.left
|
|
21
|
+
$: left = Math.min($width - 40, end)
|
|
11
22
|
</script>
|
|
12
23
|
|
|
13
24
|
<div class="header">
|
|
14
25
|
<GridScrollWrapper scrollHorizontally>
|
|
15
26
|
<div class="row">
|
|
16
27
|
{#each $renderedColumns as column, idx}
|
|
17
|
-
<HeaderCell {column} {idx}
|
|
18
|
-
<slot name="edit-column" />
|
|
19
|
-
</HeaderCell>
|
|
28
|
+
<HeaderCell {column} {idx} />
|
|
20
29
|
{/each}
|
|
21
30
|
</div>
|
|
22
31
|
</GridScrollWrapper>
|
|
23
32
|
{#if $config.allowSchemaChanges}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<slot name="add-column" />
|
|
32
|
-
</NewColumnButton>
|
|
33
|
-
</TempTooltip>
|
|
34
|
-
{/key}
|
|
33
|
+
<div
|
|
34
|
+
class="add"
|
|
35
|
+
style="left:{left}px"
|
|
36
|
+
on:click={() => dispatch("add-column")}
|
|
37
|
+
>
|
|
38
|
+
<Icon name="Add" />
|
|
39
|
+
</div>
|
|
35
40
|
{/if}
|
|
36
41
|
</div>
|
|
37
42
|
|
|
@@ -45,4 +50,21 @@
|
|
|
45
50
|
.row {
|
|
46
51
|
display: flex;
|
|
47
52
|
}
|
|
53
|
+
.add {
|
|
54
|
+
height: var(--default-row-height);
|
|
55
|
+
display: grid;
|
|
56
|
+
place-items: center;
|
|
57
|
+
width: 40px;
|
|
58
|
+
position: absolute;
|
|
59
|
+
top: 0;
|
|
60
|
+
border-left: var(--cell-border);
|
|
61
|
+
border-right: var(--cell-border);
|
|
62
|
+
border-bottom: var(--cell-border);
|
|
63
|
+
background: var(--grid-background-alt);
|
|
64
|
+
z-index: 1;
|
|
65
|
+
}
|
|
66
|
+
.add:hover {
|
|
67
|
+
background: var(--spectrum-global-color-gray-200);
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
}
|
|
48
70
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { getContext, onDestroy, onMount, tick } from "svelte"
|
|
3
|
-
import { Icon, Button
|
|
3
|
+
import { Icon, Button } 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,8 +27,7 @@
|
|
|
27
27
|
rowVerticalInversionIndex,
|
|
28
28
|
columnHorizontalInversionIndex,
|
|
29
29
|
selectedRows,
|
|
30
|
-
|
|
31
|
-
canAddRows,
|
|
30
|
+
config,
|
|
32
31
|
} = getContext("grid")
|
|
33
32
|
|
|
34
33
|
let visible = false
|
|
@@ -41,7 +40,6 @@
|
|
|
41
40
|
$: $tableId, (visible = false)
|
|
42
41
|
$: invertY = shouldInvertY(offset, $rowVerticalInversionIndex, $renderedRows)
|
|
43
42
|
$: selectedRowCount = Object.values($selectedRows).length
|
|
44
|
-
$: hasNoRows = !$rows.length
|
|
45
43
|
|
|
46
44
|
const shouldInvertY = (offset, inversionIndex, rows) => {
|
|
47
45
|
if (offset === 0) {
|
|
@@ -149,22 +147,16 @@
|
|
|
149
147
|
</script>
|
|
150
148
|
|
|
151
149
|
<!-- New row FAB -->
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
class:offset={!$stickyColumn}
|
|
163
|
-
>
|
|
164
|
-
<Icon name="Add" size="S" />
|
|
165
|
-
</div>
|
|
166
|
-
{/if}
|
|
167
|
-
</TempTooltip>
|
|
150
|
+
{#if !visible && !selectedRowCount && $config.allowAddRows && firstColumn}
|
|
151
|
+
<div
|
|
152
|
+
class="new-row-fab"
|
|
153
|
+
on:click={() => dispatch("add-row-inline")}
|
|
154
|
+
transition:fade|local={{ duration: 130 }}
|
|
155
|
+
class:offset={!$stickyColumn}
|
|
156
|
+
>
|
|
157
|
+
<Icon name="Add" size="S" />
|
|
158
|
+
</div>
|
|
159
|
+
{/if}
|
|
168
160
|
|
|
169
161
|
<!-- Only show new row functionality if we have any columns -->
|
|
170
162
|
{#if visible}
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
rows,
|
|
14
14
|
selectedRows,
|
|
15
15
|
stickyColumn,
|
|
16
|
+
renderedColumns,
|
|
16
17
|
renderedRows,
|
|
17
18
|
focusedCellId,
|
|
18
19
|
hoveredRowId,
|
|
19
|
-
|
|
20
|
+
config,
|
|
20
21
|
selectedCellMap,
|
|
21
22
|
focusedRow,
|
|
22
23
|
scrollLeft,
|
|
@@ -57,9 +58,7 @@
|
|
|
57
58
|
disabled={!$renderedRows.length}
|
|
58
59
|
/>
|
|
59
60
|
{#if $stickyColumn}
|
|
60
|
-
<HeaderCell column={$stickyColumn} orderable={false} idx="sticky"
|
|
61
|
-
<slot name="edit-column" />
|
|
62
|
-
</HeaderCell>
|
|
61
|
+
<HeaderCell column={$stickyColumn} orderable={false} idx="sticky" />
|
|
63
62
|
{/if}
|
|
64
63
|
</div>
|
|
65
64
|
|
|
@@ -94,7 +93,7 @@
|
|
|
94
93
|
{/if}
|
|
95
94
|
</div>
|
|
96
95
|
{/each}
|
|
97
|
-
{#if $
|
|
96
|
+
{#if $config.allowAddRows && ($renderedColumns.length || $stickyColumn)}
|
|
98
97
|
<div
|
|
99
98
|
class="row new"
|
|
100
99
|
on:mouseenter={$isDragging
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
config,
|
|
17
17
|
menu,
|
|
18
18
|
gridFocused,
|
|
19
|
-
canAddRows,
|
|
20
19
|
} = getContext("grid")
|
|
21
20
|
|
|
22
21
|
const ignoredOriginSelectors = [
|
|
@@ -46,7 +45,7 @@
|
|
|
46
45
|
e.preventDefault()
|
|
47
46
|
focusFirstCell()
|
|
48
47
|
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
|
49
|
-
if ($
|
|
48
|
+
if ($config.allowAddRows) {
|
|
50
49
|
e.preventDefault()
|
|
51
50
|
dispatch("add-row-inline")
|
|
52
51
|
}
|
|
@@ -100,7 +99,7 @@
|
|
|
100
99
|
}
|
|
101
100
|
break
|
|
102
101
|
case "Enter":
|
|
103
|
-
if ($
|
|
102
|
+
if ($config.allowAddRows) {
|
|
104
103
|
dispatch("add-row-inline")
|
|
105
104
|
}
|
|
106
105
|
}
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
focusedCellAPI,
|
|
18
18
|
focusedRowId,
|
|
19
19
|
notifications,
|
|
20
|
-
canAddRows,
|
|
21
20
|
} = getContext("grid")
|
|
22
21
|
|
|
23
22
|
$: style = makeStyle($menu)
|
|
@@ -94,7 +93,7 @@
|
|
|
94
93
|
</MenuItem>
|
|
95
94
|
<MenuItem
|
|
96
95
|
icon="Duplicate"
|
|
97
|
-
disabled={isNewRow || !$
|
|
96
|
+
disabled={isNewRow || !$config.allowAddRows}
|
|
98
97
|
on:click={duplicate}
|
|
99
98
|
>
|
|
100
99
|
Duplicate row
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
import { getContext } from "svelte"
|
|
3
3
|
import { GutterWidth } from "../lib/constants"
|
|
4
4
|
|
|
5
|
-
const {
|
|
6
|
-
|
|
5
|
+
const {
|
|
6
|
+
columns,
|
|
7
|
+
resize,
|
|
8
|
+
renderedColumns,
|
|
9
|
+
stickyColumn,
|
|
10
|
+
isReordering,
|
|
11
|
+
scrollLeft,
|
|
12
|
+
} = getContext("grid")
|
|
7
13
|
|
|
14
|
+
$: cutoff = $scrollLeft + GutterWidth + ($columns[0]?.width || 0)
|
|
8
15
|
$: offset = GutterWidth + ($stickyColumn?.width || 0)
|
|
9
16
|
$: activeColumn = $resize.column
|
|
10
17
|
|
|
@@ -83,21 +83,6 @@ 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
|
-
|
|
101
86
|
// Persists column changes by saving metadata against table schema
|
|
102
87
|
const saveChanges = async () => {
|
|
103
88
|
const $columns = get(columns)
|
|
@@ -143,7 +128,6 @@ export const deriveStores = context => {
|
|
|
143
128
|
}
|
|
144
129
|
|
|
145
130
|
return {
|
|
146
|
-
hasNonAutoColumn,
|
|
147
131
|
columns: {
|
|
148
132
|
...columns,
|
|
149
133
|
actions: {
|
|
@@ -70,8 +70,6 @@ export const deriveStores = context => {
|
|
|
70
70
|
rowHeight,
|
|
71
71
|
stickyColumn,
|
|
72
72
|
width,
|
|
73
|
-
hasNonAutoColumn,
|
|
74
|
-
config,
|
|
75
73
|
} = context
|
|
76
74
|
|
|
77
75
|
// Derive the row that contains the selected cell
|
|
@@ -114,16 +112,7 @@ export const deriveStores = context => {
|
|
|
114
112
|
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
|
|
115
113
|
})
|
|
116
114
|
|
|
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
|
-
|
|
125
115
|
return {
|
|
126
|
-
canAddRows,
|
|
127
116
|
focusedRow,
|
|
128
117
|
contentLines,
|
|
129
118
|
compact,
|
|
@@ -30,9 +30,8 @@ export const deriveStores = context => {
|
|
|
30
30
|
([$users, $focusedCellId]) => {
|
|
31
31
|
let map = {}
|
|
32
32
|
$users.forEach(user => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
map[cellId] = user
|
|
33
|
+
if (user.focusedCellId && user.focusedCellId !== $focusedCellId) {
|
|
34
|
+
map[user.focusedCellId] = user
|
|
36
35
|
}
|
|
37
36
|
})
|
|
38
37
|
return map
|
package/src/components/index.js
CHANGED
|
@@ -2,5 +2,4 @@ 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"
|
|
6
5
|
export { Grid } from "./grid"
|
package/src/utils/download.js
CHANGED
|
@@ -11,26 +11,3 @@ 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
package/src/api/logs.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
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,67 +0,0 @@
|
|
|
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>
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { getContext, onMount } from "svelte"
|
|
3
|
-
import { Icon, Popover, clickOutside } from "@budibase/bbui"
|
|
4
|
-
|
|
5
|
-
const { renderedColumns, scroll, hiddenColumnsWidth, width, subscribe } =
|
|
6
|
-
getContext("grid")
|
|
7
|
-
|
|
8
|
-
let anchor
|
|
9
|
-
let open = false
|
|
10
|
-
$: columnsWidth = $renderedColumns.reduce(
|
|
11
|
-
(total, col) => (total += col.width),
|
|
12
|
-
0
|
|
13
|
-
)
|
|
14
|
-
$: end = $hiddenColumnsWidth + columnsWidth - 1 - $scroll.left
|
|
15
|
-
$: left = Math.min($width - 40, end)
|
|
16
|
-
|
|
17
|
-
const close = () => {
|
|
18
|
-
open = false
|
|
19
|
-
}
|
|
20
|
-
onMount(() => subscribe("close-edit-column", close))
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<div
|
|
24
|
-
id="add-column-button"
|
|
25
|
-
bind:this={anchor}
|
|
26
|
-
class="add"
|
|
27
|
-
style="left:{left}px"
|
|
28
|
-
on:click={() => (open = true)}
|
|
29
|
-
>
|
|
30
|
-
<Icon name="Add" />
|
|
31
|
-
</div>
|
|
32
|
-
<Popover
|
|
33
|
-
bind:open
|
|
34
|
-
{anchor}
|
|
35
|
-
align="right"
|
|
36
|
-
offset={0}
|
|
37
|
-
popoverTarget={document.getElementById(`add-column-button`)}
|
|
38
|
-
animate={false}
|
|
39
|
-
customZindex={100}
|
|
40
|
-
>
|
|
41
|
-
<div
|
|
42
|
-
use:clickOutside={() => {
|
|
43
|
-
open = false
|
|
44
|
-
}}
|
|
45
|
-
class="content"
|
|
46
|
-
>
|
|
47
|
-
<slot />
|
|
48
|
-
</div>
|
|
49
|
-
</Popover>
|
|
50
|
-
|
|
51
|
-
<style>
|
|
52
|
-
.add {
|
|
53
|
-
height: var(--default-row-height);
|
|
54
|
-
display: grid;
|
|
55
|
-
place-items: center;
|
|
56
|
-
width: 40px;
|
|
57
|
-
position: absolute;
|
|
58
|
-
top: 0;
|
|
59
|
-
border-left: var(--cell-border);
|
|
60
|
-
border-right: var(--cell-border);
|
|
61
|
-
border-bottom: var(--cell-border);
|
|
62
|
-
background: var(--grid-background-alt);
|
|
63
|
-
z-index: 1;
|
|
64
|
-
}
|
|
65
|
-
.add:hover {
|
|
66
|
-
background: var(--spectrum-global-color-gray-200);
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.content {
|
|
71
|
-
width: 300px;
|
|
72
|
-
padding: 20px;
|
|
73
|
-
display: flex;
|
|
74
|
-
flex-direction: column;
|
|
75
|
-
gap: 20px;
|
|
76
|
-
z-index: 2;
|
|
77
|
-
background: var(--spectrum-alias-background-color-secondary);
|
|
78
|
-
}
|
|
79
|
-
</style>
|