@budibase/frontend-core 2.29.21 → 2.29.23
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 +5 -5
- package/src/components/FilterBuilder.svelte +1 -5
- package/src/components/grid/cells/DataCell.svelte +63 -12
- package/src/components/grid/cells/GridCell.svelte +36 -16
- package/src/components/grid/cells/GutterCell.svelte +15 -8
- package/src/components/grid/cells/HeaderCell.svelte +3 -3
- package/src/components/grid/cells/RelationshipCell.svelte +16 -8
- package/src/components/grid/controls/BulkDeleteHandler.svelte +98 -13
- package/src/components/grid/controls/BulkDuplicationHandler.svelte +79 -0
- package/src/components/grid/controls/ClipboardHandler.svelte +67 -0
- package/src/components/grid/controls/ColumnsSettingButton.svelte +5 -10
- package/src/components/grid/controls/SizeButton.svelte +6 -13
- package/src/components/grid/controls/SortButton.svelte +8 -22
- package/src/components/grid/layout/ButtonColumn.svelte +12 -6
- package/src/components/grid/layout/Grid.svelte +11 -7
- package/src/components/grid/layout/GridBody.svelte +2 -2
- package/src/components/grid/layout/GridRow.svelte +12 -6
- package/src/components/grid/layout/GridScrollWrapper.svelte +9 -7
- package/src/components/grid/layout/HeaderRow.svelte +2 -2
- package/src/components/grid/layout/NewColumnButton.svelte +11 -5
- package/src/components/grid/layout/NewRow.svelte +16 -12
- package/src/components/grid/layout/StickyColumn.svelte +24 -14
- package/src/components/grid/lib/utils.js +4 -4
- package/src/components/grid/overlays/KeyboardManager.svelte +144 -95
- package/src/components/grid/overlays/MenuOverlay.svelte +114 -63
- package/src/components/grid/overlays/ReorderOverlay.svelte +14 -18
- package/src/components/grid/overlays/ResizeOverlay.svelte +8 -21
- package/src/components/grid/stores/clipboard.js +215 -18
- package/src/components/grid/stores/columns.js +78 -97
- package/src/components/grid/stores/conditions.js +157 -0
- package/src/components/grid/stores/config.js +2 -2
- package/src/components/grid/stores/datasource.js +4 -14
- package/src/components/grid/stores/datasources/nonPlus.js +2 -4
- package/src/components/grid/stores/datasources/table.js +6 -5
- package/src/components/grid/stores/datasources/viewV2.js +7 -9
- package/src/components/grid/stores/index.js +5 -3
- package/src/components/grid/stores/menu.js +40 -6
- package/src/components/grid/stores/pagination.js +9 -3
- package/src/components/grid/stores/reorder.js +67 -42
- package/src/components/grid/stores/resize.js +1 -1
- package/src/components/grid/stores/rows.js +220 -85
- package/src/components/grid/stores/scroll.js +31 -28
- package/src/components/grid/stores/ui.js +295 -70
- package/src/components/grid/stores/users.js +2 -2
- package/src/components/grid/stores/validation.js +43 -16
- package/src/components/grid/stores/viewport.js +30 -24
- package/src/components/index.js +1 -0
- package/src/constants.js +3 -0
- package/src/themes/midnight.css +18 -17
- package/src/themes/nord.css +2 -1
- package/src/utils/utils.js +2 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Modal, ModalContent, ProgressBar } from "@budibase/bbui"
|
|
3
|
+
import { getContext, onMount } from "svelte"
|
|
4
|
+
import { sleep } from "../../../utils/utils"
|
|
5
|
+
|
|
6
|
+
const { clipboard, subscribe, copyAllowed, pasteAllowed, selectedCellCount } =
|
|
7
|
+
getContext("grid")
|
|
8
|
+
const duration = 260
|
|
9
|
+
|
|
10
|
+
let modal
|
|
11
|
+
let progressPercentage = 0
|
|
12
|
+
let processing = false
|
|
13
|
+
|
|
14
|
+
const handleCopyRequest = () => {
|
|
15
|
+
if (!$copyAllowed) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
clipboard.actions.copy()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const handlePasteRequest = async () => {
|
|
22
|
+
progressPercentage = 0
|
|
23
|
+
if (!$pasteAllowed) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
// Prompt if paste will update multiple cells
|
|
27
|
+
const multiCellPaste = $selectedCellCount > 1
|
|
28
|
+
const prompt = $clipboard.multiCellCopy || multiCellPaste
|
|
29
|
+
if (prompt) {
|
|
30
|
+
modal?.show()
|
|
31
|
+
} else {
|
|
32
|
+
clipboard.actions.paste()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const performBulkPaste = async () => {
|
|
37
|
+
processing = true
|
|
38
|
+
await clipboard.actions.paste(progress => {
|
|
39
|
+
progressPercentage = progress * 100
|
|
40
|
+
})
|
|
41
|
+
await sleep(duration)
|
|
42
|
+
processing = false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
onMount(() => subscribe("copy", handleCopyRequest))
|
|
46
|
+
onMount(() => subscribe("paste", handlePasteRequest))
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<Modal bind:this={modal}>
|
|
50
|
+
<ModalContent
|
|
51
|
+
title="Confirm paste"
|
|
52
|
+
confirmText="Continue"
|
|
53
|
+
cancelText="Cancel"
|
|
54
|
+
onConfirm={performBulkPaste}
|
|
55
|
+
size="M"
|
|
56
|
+
>
|
|
57
|
+
Are you sure you want to paste? This will update multiple values.
|
|
58
|
+
{#if processing}
|
|
59
|
+
<ProgressBar
|
|
60
|
+
size="L"
|
|
61
|
+
value={progressPercentage}
|
|
62
|
+
{duration}
|
|
63
|
+
width="100%"
|
|
64
|
+
/>
|
|
65
|
+
{/if}
|
|
66
|
+
</ModalContent>
|
|
67
|
+
</Modal>
|
|
@@ -7,14 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
export let allowViewReadonlyColumns = false
|
|
9
9
|
|
|
10
|
-
const { columns, datasource,
|
|
10
|
+
const { columns, datasource, dispatch } = getContext("grid")
|
|
11
11
|
|
|
12
12
|
let open = false
|
|
13
13
|
let anchor
|
|
14
14
|
|
|
15
|
-
$:
|
|
16
|
-
|
|
17
|
-
$: restrictedColumns = allColumns.filter(col => !col.visible || col.readonly)
|
|
15
|
+
$: restrictedColumns = $columns.filter(col => !col.visible || col.readonly)
|
|
18
16
|
$: anyRestricted = restrictedColumns.length
|
|
19
17
|
$: text = anyRestricted ? `Columns (${anyRestricted} restricted)` : "Columns"
|
|
20
18
|
|
|
@@ -43,12 +41,9 @@
|
|
|
43
41
|
HIDDEN: "hidden",
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
$: displayColumns =
|
|
44
|
+
$: displayColumns = $columns.map(c => {
|
|
47
45
|
const isRequired = helpers.schema.isRequired(c.schema.constraints)
|
|
48
|
-
const isDisplayColumn = $stickyColumn === c
|
|
49
|
-
|
|
50
46
|
const requiredTooltip = isRequired && "Required columns must be writable"
|
|
51
|
-
|
|
52
47
|
const editEnabled =
|
|
53
48
|
!isRequired ||
|
|
54
49
|
columnToPermissionOptions(c) !== PERMISSION_OPTIONS.WRITABLE
|
|
@@ -74,9 +69,9 @@
|
|
|
74
69
|
options.push({
|
|
75
70
|
icon: "VisibilityOff",
|
|
76
71
|
value: PERMISSION_OPTIONS.HIDDEN,
|
|
77
|
-
disabled:
|
|
72
|
+
disabled: c.primaryDisplay || isRequired,
|
|
78
73
|
tooltip:
|
|
79
|
-
(
|
|
74
|
+
(c.primaryDisplay && "Display column cannot be hidden") ||
|
|
80
75
|
requiredTooltip ||
|
|
81
76
|
"Hidden",
|
|
82
77
|
})
|
|
@@ -8,14 +8,8 @@
|
|
|
8
8
|
SmallRowHeight,
|
|
9
9
|
} from "../lib/constants"
|
|
10
10
|
|
|
11
|
-
const {
|
|
12
|
-
|
|
13
|
-
columns,
|
|
14
|
-
rowHeight,
|
|
15
|
-
definition,
|
|
16
|
-
fixedRowHeight,
|
|
17
|
-
datasource,
|
|
18
|
-
} = getContext("grid")
|
|
11
|
+
const { columns, rowHeight, definition, fixedRowHeight, datasource } =
|
|
12
|
+
getContext("grid")
|
|
19
13
|
|
|
20
14
|
// Some constants for column width options
|
|
21
15
|
const smallColSize = 120
|
|
@@ -42,10 +36,9 @@
|
|
|
42
36
|
let anchor
|
|
43
37
|
|
|
44
38
|
// Column width sizes
|
|
45
|
-
$:
|
|
46
|
-
$:
|
|
47
|
-
$:
|
|
48
|
-
$: allLarge = allCols.every(col => col.width === largeColSize)
|
|
39
|
+
$: allSmall = $columns.every(col => col.width === smallColSize)
|
|
40
|
+
$: allMedium = $columns.every(col => col.width === mediumColSize)
|
|
41
|
+
$: allLarge = $columns.every(col => col.width === largeColSize)
|
|
49
42
|
$: custom = !allSmall && !allMedium && !allLarge
|
|
50
43
|
$: columnSizeOptions = [
|
|
51
44
|
{
|
|
@@ -80,7 +73,7 @@
|
|
|
80
73
|
size="M"
|
|
81
74
|
on:click={() => (open = !open)}
|
|
82
75
|
selected={open}
|
|
83
|
-
disabled={
|
|
76
|
+
disabled={!$columns.length}
|
|
84
77
|
>
|
|
85
78
|
Size
|
|
86
79
|
</ActionButton>
|
|
@@ -3,34 +3,20 @@
|
|
|
3
3
|
import { ActionButton, Popover, Select } from "@budibase/bbui"
|
|
4
4
|
import { canBeSortColumn } from "@budibase/shared-core"
|
|
5
5
|
|
|
6
|
-
const { sort, columns
|
|
6
|
+
const { sort, columns } = getContext("grid")
|
|
7
7
|
|
|
8
8
|
let open = false
|
|
9
9
|
let anchor
|
|
10
10
|
|
|
11
|
-
$: columnOptions =
|
|
11
|
+
$: columnOptions = $columns
|
|
12
|
+
.map(col => ({
|
|
13
|
+
label: col.label || col.name,
|
|
14
|
+
value: col.name,
|
|
15
|
+
type: col.schema?.type,
|
|
16
|
+
}))
|
|
17
|
+
.filter(col => canBeSortColumn(col.type))
|
|
12
18
|
$: orderOptions = getOrderOptions($sort.column, columnOptions)
|
|
13
19
|
|
|
14
|
-
const getColumnOptions = (stickyColumn, columns) => {
|
|
15
|
-
let options = []
|
|
16
|
-
if (stickyColumn) {
|
|
17
|
-
options.push({
|
|
18
|
-
label: stickyColumn.label || stickyColumn.name,
|
|
19
|
-
value: stickyColumn.name,
|
|
20
|
-
type: stickyColumn.schema?.type,
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
options = [
|
|
24
|
-
...options,
|
|
25
|
-
...columns.map(col => ({
|
|
26
|
-
label: col.label || col.name,
|
|
27
|
-
value: col.name,
|
|
28
|
-
type: col.schema?.type,
|
|
29
|
-
})),
|
|
30
|
-
]
|
|
31
|
-
return options.filter(col => canBeSortColumn(col.type))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
20
|
const getOrderOptions = (column, columnOptions) => {
|
|
35
21
|
const type = columnOptions.find(col => col.value === column)?.type
|
|
36
22
|
return [
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
rows,
|
|
14
14
|
focusedRow,
|
|
15
15
|
selectedRows,
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
scrollableColumns,
|
|
17
|
+
scrollLeft,
|
|
18
18
|
isDragging,
|
|
19
19
|
buttonColumnWidth,
|
|
20
20
|
showVScrollbar,
|
|
@@ -24,12 +24,13 @@
|
|
|
24
24
|
let container
|
|
25
25
|
|
|
26
26
|
$: buttons = $props.buttons?.slice(0, 3) || []
|
|
27
|
-
$: columnsWidth = $
|
|
27
|
+
$: columnsWidth = $scrollableColumns.reduce(
|
|
28
28
|
(total, col) => (total += col.width),
|
|
29
29
|
0
|
|
30
30
|
)
|
|
31
|
-
$:
|
|
32
|
-
$:
|
|
31
|
+
$: columnEnd = columnsWidth - $scrollLeft - 1
|
|
32
|
+
$: gridEnd = $width - $buttonColumnWidth - 1
|
|
33
|
+
$: left = Math.min(columnEnd, gridEnd)
|
|
33
34
|
|
|
34
35
|
const handleClick = async (button, row) => {
|
|
35
36
|
await button.onClick?.(rows.actions.cleanRow(row))
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
onMount(() => {
|
|
41
42
|
const observer = new ResizeObserver(entries => {
|
|
42
43
|
const width = entries?.[0]?.contentRect?.width ?? 0
|
|
43
|
-
buttonColumnWidth.set(width)
|
|
44
|
+
buttonColumnWidth.set(Math.floor(width) - 1)
|
|
44
45
|
})
|
|
45
46
|
observer.observe(container)
|
|
46
47
|
})
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
class="button-column"
|
|
52
53
|
style="left:{left}px"
|
|
53
54
|
class:hidden={$buttonColumnWidth === 0}
|
|
55
|
+
class:right-border={left !== gridEnd}
|
|
54
56
|
>
|
|
55
57
|
<div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
|
|
56
58
|
<GridScrollWrapper scrollVertically attachHandlers bind:ref={container}>
|
|
@@ -68,6 +70,7 @@
|
|
|
68
70
|
rowIdx={row.__idx}
|
|
69
71
|
selected={rowSelected}
|
|
70
72
|
highlighted={rowHovered || rowFocused}
|
|
73
|
+
metadata={row.__metadata?.row}
|
|
71
74
|
>
|
|
72
75
|
<div class="buttons" class:offset={$showVScrollbar}>
|
|
73
76
|
{#each buttons as button}
|
|
@@ -150,4 +153,7 @@
|
|
|
150
153
|
.button-column :global(.cell) {
|
|
151
154
|
border-left: var(--cell-border);
|
|
152
155
|
}
|
|
156
|
+
.button-column:not(.right-border) :global(.cell) {
|
|
157
|
+
border-right-color: transparent;
|
|
158
|
+
}
|
|
153
159
|
</style>
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import { createAPIClient } from "../../../api"
|
|
8
8
|
import { attachStores } from "../stores"
|
|
9
9
|
import BulkDeleteHandler from "../controls/BulkDeleteHandler.svelte"
|
|
10
|
+
import BulkDuplicationHandler from "../controls/BulkDuplicationHandler.svelte"
|
|
11
|
+
import ClipboardHandler from "../controls/ClipboardHandler.svelte"
|
|
10
12
|
import GridBody from "./GridBody.svelte"
|
|
11
13
|
import ResizeOverlay from "../overlays/ResizeOverlay.svelte"
|
|
12
14
|
import ReorderOverlay from "../overlays/ReorderOverlay.svelte"
|
|
@@ -35,14 +37,12 @@
|
|
|
35
37
|
export let API = null
|
|
36
38
|
export let datasource = null
|
|
37
39
|
export let schemaOverrides = null
|
|
38
|
-
export let columnWhitelist = null
|
|
39
40
|
export let canAddRows = true
|
|
40
41
|
export let canExpandRows = true
|
|
41
42
|
export let canEditRows = true
|
|
42
43
|
export let canDeleteRows = true
|
|
43
44
|
export let canEditColumns = true
|
|
44
45
|
export let canSaveSchema = true
|
|
45
|
-
export let canSelectRows = false
|
|
46
46
|
export let stripeRows = false
|
|
47
47
|
export let quiet = false
|
|
48
48
|
export let collaboration = true
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
export let darkMode
|
|
59
59
|
export let isCloud = null
|
|
60
60
|
export let allowViewReadonlyColumns = false
|
|
61
|
+
export let rowConditions = null
|
|
61
62
|
|
|
62
63
|
// Unique identifier for DOM nodes inside this instance
|
|
63
64
|
const gridID = `grid-${Math.random().toString().slice(2)}`
|
|
@@ -92,14 +93,12 @@
|
|
|
92
93
|
$: props.set({
|
|
93
94
|
datasource,
|
|
94
95
|
schemaOverrides,
|
|
95
|
-
columnWhitelist,
|
|
96
96
|
canAddRows,
|
|
97
97
|
canExpandRows,
|
|
98
98
|
canEditRows,
|
|
99
99
|
canDeleteRows,
|
|
100
100
|
canEditColumns,
|
|
101
101
|
canSaveSchema,
|
|
102
|
-
canSelectRows,
|
|
103
102
|
stripeRows,
|
|
104
103
|
quiet,
|
|
105
104
|
collaboration,
|
|
@@ -114,6 +113,8 @@
|
|
|
114
113
|
buttons,
|
|
115
114
|
darkMode,
|
|
116
115
|
isCloud,
|
|
116
|
+
allowViewReadonlyColumns,
|
|
117
|
+
rowConditions,
|
|
117
118
|
})
|
|
118
119
|
|
|
119
120
|
// Derive min height and make available in context
|
|
@@ -209,9 +210,11 @@
|
|
|
209
210
|
<ProgressCircle />
|
|
210
211
|
</div>
|
|
211
212
|
{/if}
|
|
212
|
-
{#if $config.
|
|
213
|
-
<
|
|
213
|
+
{#if $config.canAddRows}
|
|
214
|
+
<BulkDuplicationHandler />
|
|
214
215
|
{/if}
|
|
216
|
+
<BulkDeleteHandler />
|
|
217
|
+
<ClipboardHandler />
|
|
215
218
|
<KeyboardManager />
|
|
216
219
|
</div>
|
|
217
220
|
|
|
@@ -229,6 +232,7 @@
|
|
|
229
232
|
--cell-spacing: 4px;
|
|
230
233
|
--cell-border: 1px solid var(--spectrum-global-color-gray-200);
|
|
231
234
|
--cell-font-size: 14px;
|
|
235
|
+
--cell-font-color: var(--spectrum-global-color-gray-800);
|
|
232
236
|
flex: 1 1 auto;
|
|
233
237
|
display: flex;
|
|
234
238
|
flex-direction: column;
|
|
@@ -284,7 +288,7 @@
|
|
|
284
288
|
flex-direction: row;
|
|
285
289
|
justify-content: space-between;
|
|
286
290
|
align-items: center;
|
|
287
|
-
border-bottom:
|
|
291
|
+
border-bottom: var(--cell-border);
|
|
288
292
|
padding: var(--cell-padding);
|
|
289
293
|
gap: var(--cell-spacing);
|
|
290
294
|
background: var(--grid-background-alt);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
const {
|
|
10
10
|
bounds,
|
|
11
11
|
renderedRows,
|
|
12
|
-
|
|
12
|
+
scrollableColumns,
|
|
13
13
|
hoveredRowId,
|
|
14
14
|
dispatch,
|
|
15
15
|
isDragging,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
let body
|
|
21
21
|
|
|
22
|
-
$: columnsWidth = $
|
|
22
|
+
$: columnsWidth = $scrollableColumns.reduce(
|
|
23
23
|
(total, col) => (total += col.width),
|
|
24
24
|
0
|
|
25
25
|
)
|
|
@@ -10,19 +10,23 @@
|
|
|
10
10
|
focusedCellId,
|
|
11
11
|
reorder,
|
|
12
12
|
selectedRows,
|
|
13
|
-
|
|
13
|
+
scrollableColumns,
|
|
14
14
|
hoveredRowId,
|
|
15
|
-
selectedCellMap,
|
|
16
15
|
focusedRow,
|
|
17
16
|
contentLines,
|
|
18
17
|
isDragging,
|
|
19
18
|
dispatch,
|
|
20
19
|
rows,
|
|
21
20
|
columnRenderMap,
|
|
21
|
+
userCellMap,
|
|
22
|
+
isSelectingCells,
|
|
23
|
+
selectedCellMap,
|
|
24
|
+
selectedCellCount,
|
|
22
25
|
} = getContext("grid")
|
|
23
26
|
|
|
24
27
|
$: rowSelected = !!$selectedRows[row._id]
|
|
25
|
-
$: rowHovered =
|
|
28
|
+
$: rowHovered =
|
|
29
|
+
$hoveredRowId === row._id && (!$selectedCellCount || !$isSelectingCells)
|
|
26
30
|
$: rowFocused = $focusedRow?._id === row._id
|
|
27
31
|
$: reorderSource = $reorder.sourceColumn
|
|
28
32
|
</script>
|
|
@@ -36,22 +40,24 @@
|
|
|
36
40
|
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
|
37
41
|
on:click={() => dispatch("rowclick", rows.actions.cleanRow(row))}
|
|
38
42
|
>
|
|
39
|
-
{#each $
|
|
43
|
+
{#each $scrollableColumns as column}
|
|
40
44
|
{@const cellId = getCellID(row._id, column.name)}
|
|
41
45
|
<DataCell
|
|
42
46
|
{cellId}
|
|
43
47
|
{column}
|
|
44
48
|
{row}
|
|
45
49
|
{rowFocused}
|
|
50
|
+
{rowSelected}
|
|
51
|
+
cellSelected={$selectedCellMap[cellId]}
|
|
46
52
|
highlighted={rowHovered || rowFocused || reorderSource === column.name}
|
|
47
|
-
selected={rowSelected}
|
|
48
53
|
rowIdx={row.__idx}
|
|
49
54
|
topRow={top}
|
|
50
55
|
focused={$focusedCellId === cellId}
|
|
51
|
-
selectedUser={$
|
|
56
|
+
selectedUser={$userCellMap[cellId]}
|
|
52
57
|
width={column.width}
|
|
53
58
|
contentLines={$contentLines}
|
|
54
59
|
hidden={!$columnRenderMap[column.name]}
|
|
60
|
+
isSelectingCells={$isSelectingCells}
|
|
55
61
|
/>
|
|
56
62
|
{/each}
|
|
57
63
|
</div>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const {
|
|
6
6
|
rowHeight,
|
|
7
7
|
scroll,
|
|
8
|
-
|
|
8
|
+
ui,
|
|
9
9
|
renderedRows,
|
|
10
10
|
maxScrollTop,
|
|
11
11
|
maxScrollLeft,
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
hoveredRowId,
|
|
14
14
|
menu,
|
|
15
15
|
focusedCellAPI,
|
|
16
|
+
scrollTop,
|
|
17
|
+
scrollLeft,
|
|
16
18
|
} = getContext("grid")
|
|
17
19
|
|
|
18
20
|
export let scrollVertically = false
|
|
@@ -24,12 +26,12 @@
|
|
|
24
26
|
let initialTouchX
|
|
25
27
|
let initialTouchY
|
|
26
28
|
|
|
27
|
-
$: style = generateStyle($
|
|
29
|
+
$: style = generateStyle($scrollLeft, $scrollTop, $rowHeight)
|
|
28
30
|
|
|
29
|
-
const generateStyle = (
|
|
30
|
-
const offsetX = scrollHorizontally ? -1 *
|
|
31
|
-
const offsetY = scrollVertically ? -1 * (
|
|
32
|
-
return `transform:
|
|
31
|
+
const generateStyle = (scrollLeft, scrollTop, rowHeight) => {
|
|
32
|
+
const offsetX = scrollHorizontally ? -1 * scrollLeft : 0
|
|
33
|
+
const offsetY = scrollVertically ? -1 * (scrollTop % rowHeight) : 0
|
|
34
|
+
return `transform: translate(${offsetX}px, ${offsetY}px);`
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
// Handles a mouse wheel event and updates scroll state
|
|
@@ -108,7 +110,7 @@
|
|
|
108
110
|
on:wheel={attachHandlers ? handleWheel : null}
|
|
109
111
|
on:touchstart={attachHandlers ? handleTouchStart : null}
|
|
110
112
|
on:touchmove={attachHandlers ? handleTouchMove : null}
|
|
111
|
-
on:click|self={
|
|
113
|
+
on:click|self={ui.actions.blur}
|
|
112
114
|
>
|
|
113
115
|
<div {style} class="inner" bind:this={ref}>
|
|
114
116
|
<slot />
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
import HeaderCell from "../cells/HeaderCell.svelte"
|
|
6
6
|
import { TempTooltip, TooltipType } from "@budibase/bbui"
|
|
7
7
|
|
|
8
|
-
const {
|
|
8
|
+
const { scrollableColumns, config, hasNonAutoColumn, datasource, loading } =
|
|
9
9
|
getContext("grid")
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<div class="header">
|
|
13
13
|
<GridScrollWrapper scrollHorizontally>
|
|
14
14
|
<div class="row">
|
|
15
|
-
{#each $
|
|
15
|
+
{#each $scrollableColumns as column, idx}
|
|
16
16
|
<HeaderCell {column} {idx}>
|
|
17
17
|
<slot name="edit-column" />
|
|
18
18
|
</HeaderCell>
|
|
@@ -3,17 +3,23 @@
|
|
|
3
3
|
import { Icon } from "@budibase/bbui"
|
|
4
4
|
import GridPopover from "../overlays/GridPopover.svelte"
|
|
5
5
|
|
|
6
|
-
const {
|
|
7
|
-
|
|
6
|
+
const {
|
|
7
|
+
scrollableColumns,
|
|
8
|
+
scrollLeft,
|
|
9
|
+
width,
|
|
10
|
+
subscribe,
|
|
11
|
+
ui,
|
|
12
|
+
keyboardBlocked,
|
|
13
|
+
} = getContext("grid")
|
|
8
14
|
|
|
9
15
|
let anchor
|
|
10
16
|
let isOpen = false
|
|
11
17
|
|
|
12
|
-
$: columnsWidth = $
|
|
18
|
+
$: columnsWidth = $scrollableColumns.reduce(
|
|
13
19
|
(total, col) => (total += col.width),
|
|
14
20
|
0
|
|
15
21
|
)
|
|
16
|
-
$: end = columnsWidth - 1 - $
|
|
22
|
+
$: end = columnsWidth - 1 - $scrollLeft
|
|
17
23
|
$: left = Math.min($width - 40, end)
|
|
18
24
|
$: keyboardBlocked.set(isOpen)
|
|
19
25
|
|
|
@@ -43,7 +49,7 @@
|
|
|
43
49
|
{#if isOpen}
|
|
44
50
|
<GridPopover
|
|
45
51
|
{anchor}
|
|
46
|
-
align={$
|
|
52
|
+
align={$scrollableColumns.length ? "right" : "left"}
|
|
47
53
|
on:close={close}
|
|
48
54
|
maxHeight={null}
|
|
49
55
|
resizable
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const {
|
|
13
13
|
hoveredRowId,
|
|
14
14
|
focusedCellId,
|
|
15
|
-
|
|
15
|
+
displayColumn,
|
|
16
16
|
scroll,
|
|
17
17
|
dispatch,
|
|
18
18
|
rows,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
datasource,
|
|
21
21
|
subscribe,
|
|
22
22
|
renderedRows,
|
|
23
|
-
|
|
23
|
+
scrollableColumns,
|
|
24
24
|
rowHeight,
|
|
25
25
|
hasNextPage,
|
|
26
26
|
maxScrollTop,
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
filter,
|
|
32
32
|
inlineFilters,
|
|
33
33
|
columnRenderMap,
|
|
34
|
+
visibleColumns,
|
|
34
35
|
scrollTop,
|
|
35
36
|
} = getContext("grid")
|
|
36
37
|
|
|
@@ -39,8 +40,8 @@
|
|
|
39
40
|
let newRow
|
|
40
41
|
let offset = 0
|
|
41
42
|
|
|
42
|
-
$: firstColumn = $
|
|
43
|
-
$: width = GutterWidth + ($
|
|
43
|
+
$: firstColumn = $visibleColumns[0]
|
|
44
|
+
$: width = GutterWidth + ($displayColumn?.width || 0)
|
|
44
45
|
$: $datasource, (visible = false)
|
|
45
46
|
$: selectedRowCount = Object.values($selectedRows).length
|
|
46
47
|
$: hasNoRows = !$rows.length
|
|
@@ -70,7 +71,10 @@
|
|
|
70
71
|
const newRowIndex = offset ? undefined : 0
|
|
71
72
|
let rowToCreate = { ...newRow }
|
|
72
73
|
delete rowToCreate._isNewRow
|
|
73
|
-
const savedRow = await rows.actions.addRow(
|
|
74
|
+
const savedRow = await rows.actions.addRow({
|
|
75
|
+
row: rowToCreate,
|
|
76
|
+
idx: newRowIndex,
|
|
77
|
+
})
|
|
74
78
|
if (savedRow) {
|
|
75
79
|
// Reset state
|
|
76
80
|
clear()
|
|
@@ -167,7 +171,7 @@
|
|
|
167
171
|
class="new-row-fab"
|
|
168
172
|
on:click={() => dispatch("add-row-inline")}
|
|
169
173
|
transition:fade|local={{ duration: 130 }}
|
|
170
|
-
class:offset={!$
|
|
174
|
+
class:offset={!$displayColumn}
|
|
171
175
|
>
|
|
172
176
|
<Icon name="Add" size="S" />
|
|
173
177
|
</div>
|
|
@@ -191,19 +195,19 @@
|
|
|
191
195
|
<div in:fade={{ duration: 130 }} class="loading-overlay" />
|
|
192
196
|
{/if}
|
|
193
197
|
</GutterCell>
|
|
194
|
-
{#if $
|
|
195
|
-
{@const cellId = getCellID(NewRowID, $
|
|
198
|
+
{#if $displayColumn}
|
|
199
|
+
{@const cellId = getCellID(NewRowID, $displayColumn.name)}
|
|
196
200
|
<DataCell
|
|
197
201
|
{cellId}
|
|
198
202
|
rowFocused
|
|
199
|
-
column={$
|
|
203
|
+
column={$displayColumn}
|
|
200
204
|
row={newRow}
|
|
201
205
|
focused={$focusedCellId === cellId}
|
|
202
|
-
width={$
|
|
206
|
+
width={$displayColumn.width}
|
|
203
207
|
{updateValue}
|
|
204
208
|
topRow={offset === 0}
|
|
205
209
|
>
|
|
206
|
-
{#if $
|
|
210
|
+
{#if $displayColumn?.schema?.autocolumn}
|
|
207
211
|
<div class="readonly-overlay">Can't edit auto column</div>
|
|
208
212
|
{/if}
|
|
209
213
|
{#if isAdding}
|
|
@@ -216,7 +220,7 @@
|
|
|
216
220
|
<div class="normal-columns" transition:fade|local={{ duration: 130 }}>
|
|
217
221
|
<GridScrollWrapper scrollHorizontally attachHandlers>
|
|
218
222
|
<div class="row">
|
|
219
|
-
{#each $
|
|
223
|
+
{#each $scrollableColumns as column}
|
|
220
224
|
{@const cellId = getCellID(NewRowID, column.name)}
|
|
221
225
|
<DataCell
|
|
222
226
|
{cellId}
|