@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
|
@@ -13,22 +13,25 @@
|
|
|
13
13
|
const {
|
|
14
14
|
rows,
|
|
15
15
|
selectedRows,
|
|
16
|
-
|
|
16
|
+
displayColumn,
|
|
17
17
|
renderedRows,
|
|
18
18
|
focusedCellId,
|
|
19
19
|
hoveredRowId,
|
|
20
20
|
config,
|
|
21
21
|
selectedCellMap,
|
|
22
|
+
userCellMap,
|
|
22
23
|
focusedRow,
|
|
23
24
|
scrollLeft,
|
|
24
25
|
dispatch,
|
|
25
26
|
contentLines,
|
|
26
27
|
isDragging,
|
|
28
|
+
isSelectingCells,
|
|
29
|
+
selectedCellCount,
|
|
27
30
|
} = getContext("grid")
|
|
28
31
|
|
|
29
32
|
$: rowCount = $rows.length
|
|
30
33
|
$: selectedRowCount = Object.values($selectedRows).length
|
|
31
|
-
$: width = GutterWidth + ($
|
|
34
|
+
$: width = GutterWidth + ($displayColumn?.width || 0)
|
|
32
35
|
|
|
33
36
|
const selectAll = () => {
|
|
34
37
|
const allSelected = selectedRowCount === rowCount
|
|
@@ -57,8 +60,8 @@
|
|
|
57
60
|
rowSelected={selectedRowCount && selectedRowCount === rowCount}
|
|
58
61
|
disabled={!$renderedRows.length}
|
|
59
62
|
/>
|
|
60
|
-
{#if $
|
|
61
|
-
<HeaderCell column={$
|
|
63
|
+
{#if $displayColumn}
|
|
64
|
+
<HeaderCell column={$displayColumn} orderable={false} idx="sticky">
|
|
62
65
|
<slot name="edit-column" />
|
|
63
66
|
</HeaderCell>
|
|
64
67
|
{/if}
|
|
@@ -69,9 +72,11 @@
|
|
|
69
72
|
<GridScrollWrapper scrollVertically attachHandlers>
|
|
70
73
|
{#each $renderedRows as row, idx}
|
|
71
74
|
{@const rowSelected = !!$selectedRows[row._id]}
|
|
72
|
-
{@const rowHovered =
|
|
75
|
+
{@const rowHovered =
|
|
76
|
+
$hoveredRowId === row._id &&
|
|
77
|
+
(!$selectedCellCount || !$isSelectingCells)}
|
|
73
78
|
{@const rowFocused = $focusedRow?._id === row._id}
|
|
74
|
-
{@const cellId = getCellID(row._id, $
|
|
79
|
+
{@const cellId = getCellID(row._id, $displayColumn?.name)}
|
|
75
80
|
<div
|
|
76
81
|
class="row"
|
|
77
82
|
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
|
@@ -79,20 +84,22 @@
|
|
|
79
84
|
on:click={() => dispatch("rowclick", rows.actions.cleanRow(row))}
|
|
80
85
|
>
|
|
81
86
|
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
|
82
|
-
{#if $
|
|
87
|
+
{#if $displayColumn}
|
|
83
88
|
<DataCell
|
|
84
89
|
{row}
|
|
85
90
|
{cellId}
|
|
86
91
|
{rowFocused}
|
|
87
|
-
|
|
92
|
+
{rowSelected}
|
|
93
|
+
cellSelected={$selectedCellMap[cellId]}
|
|
88
94
|
highlighted={rowHovered || rowFocused}
|
|
89
95
|
rowIdx={row.__idx}
|
|
90
96
|
topRow={idx === 0}
|
|
91
97
|
focused={$focusedCellId === cellId}
|
|
92
|
-
selectedUser={$
|
|
93
|
-
width={$
|
|
94
|
-
column={$
|
|
98
|
+
selectedUser={$userCellMap[cellId]}
|
|
99
|
+
width={$displayColumn.width}
|
|
100
|
+
column={$displayColumn}
|
|
95
101
|
contentLines={$contentLines}
|
|
102
|
+
isSelectingCells={$isSelectingCells}
|
|
96
103
|
/>
|
|
97
104
|
{/if}
|
|
98
105
|
</div>
|
|
@@ -107,9 +114,9 @@
|
|
|
107
114
|
<GutterCell rowHovered={$hoveredRowId === BlankRowID}>
|
|
108
115
|
<Icon name="Add" color="var(--spectrum-global-color-gray-500)" />
|
|
109
116
|
</GutterCell>
|
|
110
|
-
{#if $
|
|
117
|
+
{#if $displayColumn}
|
|
111
118
|
<GridCell
|
|
112
|
-
width={$
|
|
119
|
+
width={$displayColumn.width}
|
|
113
120
|
highlighted={$hoveredRowId === BlankRowID}
|
|
114
121
|
>
|
|
115
122
|
<KeyboardShortcut padded keybind="Ctrl+Enter" />
|
|
@@ -155,7 +162,7 @@
|
|
|
155
162
|
|
|
156
163
|
/* Don't show borders between cells in the sticky column */
|
|
157
164
|
.sticky-column :global(.cell:not(:last-child)) {
|
|
158
|
-
border-right:
|
|
165
|
+
border-right-color: transparent;
|
|
159
166
|
}
|
|
160
167
|
|
|
161
168
|
.header {
|
|
@@ -164,6 +171,9 @@
|
|
|
164
171
|
.header :global(.cell) {
|
|
165
172
|
background: var(--grid-background-alt);
|
|
166
173
|
}
|
|
174
|
+
.header :global(.cell::before) {
|
|
175
|
+
display: none;
|
|
176
|
+
}
|
|
167
177
|
.row {
|
|
168
178
|
display: flex;
|
|
169
179
|
flex-direction: row;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { helpers } from "@budibase/shared-core"
|
|
2
2
|
import { TypeIconMap } from "../../../constants"
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
//
|
|
4
|
+
// We can't use "-" as a separator as this can be present in the ID
|
|
5
|
+
// or column name, so we use something very unusual to avoid this problem
|
|
6
6
|
const JOINING_CHARACTER = "‽‽"
|
|
7
7
|
|
|
8
8
|
export const parseCellID = cellId => {
|
|
9
9
|
if (!cellId) {
|
|
10
|
-
return {
|
|
10
|
+
return { rowId: undefined, field: undefined }
|
|
11
11
|
}
|
|
12
12
|
const parts = cellId.split(JOINING_CHARACTER)
|
|
13
13
|
const field = parts.pop()
|
|
14
|
-
return {
|
|
14
|
+
return { rowId: parts.join(JOINING_CHARACTER), field }
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export const getCellID = (rowId, fieldName) => {
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { getContext, onMount } from "svelte"
|
|
3
3
|
import { debounce } from "../../../utils/utils"
|
|
4
|
-
import { NewRowID } from "../lib/constants"
|
|
5
4
|
import { getCellID, parseCellID } from "../lib/utils"
|
|
5
|
+
import { NewRowID } from "../lib/constants"
|
|
6
6
|
|
|
7
7
|
const {
|
|
8
8
|
rows,
|
|
9
9
|
focusedCellId,
|
|
10
10
|
visibleColumns,
|
|
11
|
-
|
|
12
|
-
stickyColumn,
|
|
11
|
+
rowLookupMap,
|
|
13
12
|
focusedCellAPI,
|
|
14
|
-
clipboard,
|
|
15
13
|
dispatch,
|
|
16
|
-
|
|
14
|
+
selectedRowCount,
|
|
17
15
|
config,
|
|
18
16
|
menu,
|
|
19
17
|
gridFocused,
|
|
20
18
|
keyboardBlocked,
|
|
19
|
+
selectedCellCount,
|
|
20
|
+
selectedCells,
|
|
21
|
+
cellSelection,
|
|
22
|
+
columnLookupMap,
|
|
23
|
+
focusedRowId,
|
|
21
24
|
} = getContext("grid")
|
|
22
25
|
|
|
23
26
|
const ignoredOriginSelectors = [
|
|
@@ -43,23 +46,51 @@
|
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
//
|
|
47
|
-
|
|
49
|
+
// Sugar for preventing default
|
|
50
|
+
const handle = fn => {
|
|
48
51
|
e.preventDefault()
|
|
49
|
-
|
|
50
|
-
return
|
|
52
|
+
fn()
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
//
|
|
55
|
+
// Handle certain key presses regardless of selection state
|
|
56
|
+
if (e.metaKey || e.ctrlKey) {
|
|
57
|
+
switch (e.key) {
|
|
58
|
+
case "c":
|
|
59
|
+
return handle(() => dispatch("copy"))
|
|
60
|
+
case "v":
|
|
61
|
+
return handle(() => dispatch("paste"))
|
|
62
|
+
case "Enter":
|
|
63
|
+
return handle(() => {
|
|
64
|
+
if ($config.canAddRows) {
|
|
65
|
+
dispatch("add-row-inline")
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Handle certain key presses if we have cells selected
|
|
72
|
+
if ($selectedCellCount) {
|
|
73
|
+
switch (e.key) {
|
|
74
|
+
case "Escape":
|
|
75
|
+
return handle(selectedCells.actions.clear)
|
|
76
|
+
case "Delete":
|
|
77
|
+
case "Backspace":
|
|
78
|
+
return handle(() => dispatch("request-bulk-delete"))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Handle certain key presses only if no cell focused
|
|
54
83
|
if (!$focusedCellId) {
|
|
55
84
|
if (e.key === "Tab" || e.key?.startsWith("Arrow")) {
|
|
56
|
-
|
|
57
|
-
focusFirstCell()
|
|
85
|
+
handle(focusFirstCell)
|
|
58
86
|
} else if (e.key === "Delete" || e.key === "Backspace") {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
87
|
+
handle(() => {
|
|
88
|
+
if ($selectedRowCount && $config.canDeleteRows) {
|
|
89
|
+
dispatch("request-bulk-delete")
|
|
90
|
+
}
|
|
91
|
+
})
|
|
62
92
|
}
|
|
93
|
+
// Avoid processing anything else
|
|
63
94
|
return
|
|
64
95
|
}
|
|
65
96
|
|
|
@@ -69,18 +100,19 @@
|
|
|
69
100
|
// By setting a tiny timeout here we can ensure that other listeners
|
|
70
101
|
// which depend on being able to read cell state on an escape keypress
|
|
71
102
|
// get a chance to observe the true state before we blur
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
103
|
+
return handle(() => {
|
|
104
|
+
if (api?.isActive()) {
|
|
105
|
+
setTimeout(api?.blur, 10)
|
|
106
|
+
} else {
|
|
107
|
+
$focusedCellId = null
|
|
108
|
+
}
|
|
109
|
+
menu.actions.close()
|
|
110
|
+
})
|
|
79
111
|
} else if (e.key === "Tab") {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
112
|
+
return handle(() => {
|
|
113
|
+
api?.blur?.()
|
|
114
|
+
changeFocusedColumn(1)
|
|
115
|
+
})
|
|
84
116
|
}
|
|
85
117
|
|
|
86
118
|
// Pass the key event to the selected cell and let it decide whether to
|
|
@@ -91,57 +123,33 @@
|
|
|
91
123
|
return
|
|
92
124
|
}
|
|
93
125
|
}
|
|
94
|
-
e.preventDefault()
|
|
95
126
|
|
|
96
127
|
// Handle the key ourselves
|
|
97
128
|
if (e.metaKey || e.ctrlKey) {
|
|
98
|
-
|
|
99
|
-
case "c":
|
|
100
|
-
clipboard.actions.copy()
|
|
101
|
-
break
|
|
102
|
-
case "v":
|
|
103
|
-
if (!api?.isReadonly()) {
|
|
104
|
-
clipboard.actions.paste()
|
|
105
|
-
}
|
|
106
|
-
break
|
|
107
|
-
case "Enter":
|
|
108
|
-
if ($config.canAddRows) {
|
|
109
|
-
dispatch("add-row-inline")
|
|
110
|
-
}
|
|
111
|
-
}
|
|
129
|
+
//
|
|
112
130
|
} else {
|
|
113
131
|
switch (e.key) {
|
|
114
132
|
case "ArrowLeft":
|
|
115
|
-
changeFocusedColumn(-1)
|
|
116
|
-
break
|
|
133
|
+
return handle(() => changeFocusedColumn(-1, e.shiftKey))
|
|
117
134
|
case "ArrowRight":
|
|
118
|
-
changeFocusedColumn(1)
|
|
119
|
-
break
|
|
135
|
+
return handle(() => changeFocusedColumn(1, e.shiftKey))
|
|
120
136
|
case "ArrowUp":
|
|
121
|
-
changeFocusedRow(-1)
|
|
122
|
-
break
|
|
137
|
+
return handle(() => changeFocusedRow(-1, e.shiftKey))
|
|
123
138
|
case "ArrowDown":
|
|
124
|
-
changeFocusedRow(1)
|
|
125
|
-
break
|
|
139
|
+
return handle(() => changeFocusedRow(1, e.shiftKey))
|
|
126
140
|
case "Delete":
|
|
127
141
|
case "Backspace":
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
return handle(() => {
|
|
143
|
+
if ($selectedRowCount && $config.canDeleteRows) {
|
|
144
|
+
dispatch("request-bulk-delete")
|
|
145
|
+
} else {
|
|
146
|
+
deleteSelectedCell()
|
|
147
|
+
}
|
|
148
|
+
})
|
|
134
149
|
case "Enter":
|
|
135
|
-
focusCell
|
|
136
|
-
break
|
|
137
|
-
case " ":
|
|
138
|
-
case "Space":
|
|
139
|
-
if ($config.canDeleteRows) {
|
|
140
|
-
toggleSelectRow()
|
|
141
|
-
}
|
|
142
|
-
break
|
|
150
|
+
return handle(focusCell)
|
|
143
151
|
default:
|
|
144
|
-
startEnteringValue(e.key, e.which)
|
|
152
|
+
return handle(() => startEnteringValue(e.key, e.which))
|
|
145
153
|
}
|
|
146
154
|
}
|
|
147
155
|
}
|
|
@@ -152,7 +160,7 @@
|
|
|
152
160
|
if (!firstRow) {
|
|
153
161
|
return
|
|
154
162
|
}
|
|
155
|
-
const firstColumn = $
|
|
163
|
+
const firstColumn = $visibleColumns[0]
|
|
156
164
|
if (!firstColumn) {
|
|
157
165
|
return
|
|
158
166
|
}
|
|
@@ -160,38 +168,87 @@
|
|
|
160
168
|
}
|
|
161
169
|
|
|
162
170
|
// Changes the focused cell by moving it left or right to a different column
|
|
163
|
-
const changeFocusedColumn = delta => {
|
|
164
|
-
|
|
171
|
+
const changeFocusedColumn = (delta, shiftKey) => {
|
|
172
|
+
// Determine which cell we are working with
|
|
173
|
+
let sourceCellId = $focusedCellId
|
|
174
|
+
if (shiftKey && $selectedCellCount) {
|
|
175
|
+
sourceCellId = $cellSelection.targetCellId
|
|
176
|
+
}
|
|
177
|
+
if (!sourceCellId) {
|
|
165
178
|
return
|
|
166
179
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
|
|
181
|
+
// Determine the new position for this cell
|
|
182
|
+
const { rowId, field } = parseCellID(sourceCellId)
|
|
183
|
+
const colIdx = $columnLookupMap[field].__idx
|
|
184
|
+
const nextColumn = $visibleColumns[colIdx + delta]
|
|
185
|
+
if (!nextColumn) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
const targetCellId = getCellID(rowId, nextColumn.name)
|
|
189
|
+
|
|
190
|
+
// Apply change
|
|
191
|
+
if (shiftKey) {
|
|
192
|
+
if ($selectedCellCount) {
|
|
193
|
+
// We have selected cells and still are holding shift - update selection
|
|
194
|
+
selectedCells.actions.updateTarget(targetCellId)
|
|
195
|
+
|
|
196
|
+
// Restore focused cell if this removes the selection
|
|
197
|
+
if (!$selectedCellCount) {
|
|
198
|
+
focusedCellId.set(targetCellId)
|
|
199
|
+
}
|
|
177
200
|
} else {
|
|
178
|
-
|
|
201
|
+
// We have no selection but are holding shift - select these cells
|
|
202
|
+
selectedCells.actions.selectRange(sourceCellId, targetCellId)
|
|
179
203
|
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
204
|
+
} else {
|
|
205
|
+
// We aren't holding shift - just focus this cell
|
|
206
|
+
focusedCellId.set(targetCellId)
|
|
183
207
|
}
|
|
184
208
|
}
|
|
185
209
|
|
|
186
210
|
// Changes the focused cell by moving it up or down to a new row
|
|
187
|
-
const changeFocusedRow = delta => {
|
|
188
|
-
|
|
211
|
+
const changeFocusedRow = (delta, shiftKey) => {
|
|
212
|
+
// Ignore for new row component
|
|
213
|
+
if ($focusedRowId === NewRowID) {
|
|
189
214
|
return
|
|
190
215
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
216
|
+
|
|
217
|
+
// Determine which cell we are working with
|
|
218
|
+
let sourceCellId = $focusedCellId
|
|
219
|
+
if (shiftKey && $selectedCellCount) {
|
|
220
|
+
sourceCellId = $cellSelection.targetCellId
|
|
221
|
+
}
|
|
222
|
+
if (!sourceCellId) {
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Determine the new position for this cell
|
|
227
|
+
const { rowId, field } = parseCellID(sourceCellId)
|
|
228
|
+
const rowIdx = $rowLookupMap[rowId].__idx
|
|
229
|
+
const newRow = $rows[rowIdx + delta]
|
|
230
|
+
if (!newRow) {
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
const targetCellId = getCellID(newRow._id, field)
|
|
234
|
+
|
|
235
|
+
// Apply change
|
|
236
|
+
if (shiftKey) {
|
|
237
|
+
if ($selectedCellCount) {
|
|
238
|
+
// We have selected cells and still are holding shift - update selection
|
|
239
|
+
selectedCells.actions.updateTarget(targetCellId)
|
|
240
|
+
|
|
241
|
+
// Restore focused cell if this removes the selection
|
|
242
|
+
if (!$selectedCellCount) {
|
|
243
|
+
focusedCellId.set(targetCellId)
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
// We have no selection but are holding shift - select these cells
|
|
247
|
+
selectedCells.actions.selectRange(sourceCellId, targetCellId)
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
// We aren't holding shift - just focus this cell
|
|
251
|
+
focusedCellId.set(targetCellId)
|
|
195
252
|
}
|
|
196
253
|
}
|
|
197
254
|
|
|
@@ -234,14 +291,6 @@
|
|
|
234
291
|
}
|
|
235
292
|
}
|
|
236
293
|
|
|
237
|
-
const toggleSelectRow = () => {
|
|
238
|
-
const id = $focusedRow?._id
|
|
239
|
-
if (!id || id === NewRowID) {
|
|
240
|
-
return
|
|
241
|
-
}
|
|
242
|
-
selectedRows.actions.toggleRow(id)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
294
|
onMount(() => {
|
|
246
295
|
document.addEventListener("keydown", handleKeyDown)
|
|
247
296
|
return () => {
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
focusedRow,
|
|
10
10
|
menu,
|
|
11
11
|
rows,
|
|
12
|
-
columns,
|
|
13
|
-
focusedCellId,
|
|
14
|
-
stickyColumn,
|
|
15
12
|
config,
|
|
16
|
-
copiedCell,
|
|
17
|
-
clipboard,
|
|
18
13
|
dispatch,
|
|
19
|
-
focusedCellAPI,
|
|
20
14
|
focusedRowId,
|
|
21
15
|
notifications,
|
|
22
16
|
hasBudibaseIdentifiers,
|
|
17
|
+
selectedRowCount,
|
|
18
|
+
copyAllowed,
|
|
19
|
+
pasteAllowed,
|
|
20
|
+
selectedCellCount,
|
|
21
|
+
visibleColumns,
|
|
22
|
+
selectedCells,
|
|
23
23
|
} = getContext("grid")
|
|
24
24
|
|
|
25
25
|
let anchor
|
|
@@ -32,17 +32,20 @@
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const deleteRow = () => {
|
|
35
|
-
rows.actions.deleteRows([$focusedRow])
|
|
36
35
|
menu.actions.close()
|
|
36
|
+
rows.actions.deleteRows([$focusedRow])
|
|
37
37
|
$notifications.success("Deleted 1 row")
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const
|
|
40
|
+
const duplicateRow = async () => {
|
|
41
41
|
menu.actions.close()
|
|
42
42
|
const newRow = await rows.actions.duplicateRow($focusedRow)
|
|
43
43
|
if (newRow) {
|
|
44
|
-
const
|
|
45
|
-
|
|
44
|
+
const firstCol = $visibleColumns[0]
|
|
45
|
+
const lastCol = $visibleColumns[$visibleColumns.length - 1]
|
|
46
|
+
const startCellId = getCellID(newRow._id, firstCol.name)
|
|
47
|
+
const endCellId = getCellID(newRow._id, lastCol.name)
|
|
48
|
+
selectedCells.actions.selectRange(startCellId, endCellId)
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -58,59 +61,107 @@
|
|
|
58
61
|
{#key style}
|
|
59
62
|
<GridPopover {anchor} on:close={menu.actions.close} maxHeight={null}>
|
|
60
63
|
<Menu>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
64
|
+
{#if $menu.multiRowMode}
|
|
65
|
+
<MenuItem
|
|
66
|
+
icon="Duplicate"
|
|
67
|
+
disabled={!$config.canAddRows || $selectedRowCount > 50}
|
|
68
|
+
on:click={() => dispatch("request-bulk-duplicate")}
|
|
69
|
+
on:click={menu.actions.close}
|
|
70
|
+
>
|
|
71
|
+
Duplicate {$selectedRowCount} rows
|
|
72
|
+
</MenuItem>
|
|
73
|
+
<MenuItem
|
|
74
|
+
icon="Delete"
|
|
75
|
+
disabled={!$config.canDeleteRows}
|
|
76
|
+
on:click={() => dispatch("request-bulk-delete")}
|
|
77
|
+
on:click={menu.actions.close}
|
|
78
|
+
>
|
|
79
|
+
Delete {$selectedRowCount} rows
|
|
80
|
+
</MenuItem>
|
|
81
|
+
{:else if $menu.multiCellMode}
|
|
82
|
+
<MenuItem
|
|
83
|
+
icon="Copy"
|
|
84
|
+
disabled={!$copyAllowed}
|
|
85
|
+
on:click={() => dispatch("copy")}
|
|
86
|
+
on:click={menu.actions.close}
|
|
87
|
+
>
|
|
88
|
+
Copy
|
|
89
|
+
</MenuItem>
|
|
90
|
+
<MenuItem
|
|
91
|
+
icon="Paste"
|
|
92
|
+
disabled={!$pasteAllowed}
|
|
93
|
+
on:click={() => dispatch("paste")}
|
|
94
|
+
on:click={menu.actions.close}
|
|
95
|
+
>
|
|
96
|
+
Paste
|
|
97
|
+
</MenuItem>
|
|
98
|
+
<MenuItem
|
|
99
|
+
icon="Delete"
|
|
100
|
+
disabled={!$config.canEditRows}
|
|
101
|
+
on:click={() => dispatch("request-bulk-delete")}
|
|
102
|
+
>
|
|
103
|
+
Delete {$selectedCellCount} cells
|
|
104
|
+
</MenuItem>
|
|
105
|
+
{:else}
|
|
106
|
+
<MenuItem
|
|
107
|
+
icon="Copy"
|
|
108
|
+
disabled={!$copyAllowed}
|
|
109
|
+
on:click={() => dispatch("copy")}
|
|
110
|
+
on:click={menu.actions.close}
|
|
111
|
+
>
|
|
112
|
+
Copy
|
|
113
|
+
</MenuItem>
|
|
114
|
+
<MenuItem
|
|
115
|
+
icon="Paste"
|
|
116
|
+
disabled={!$pasteAllowed}
|
|
117
|
+
on:click={() => dispatch("paste")}
|
|
118
|
+
on:click={menu.actions.close}
|
|
119
|
+
>
|
|
120
|
+
Paste
|
|
121
|
+
</MenuItem>
|
|
122
|
+
<MenuItem
|
|
123
|
+
icon="Maximize"
|
|
124
|
+
disabled={isNewRow ||
|
|
125
|
+
!$config.canEditRows ||
|
|
126
|
+
!$config.canExpandRows}
|
|
127
|
+
on:click={() => dispatch("edit-row", $focusedRow)}
|
|
128
|
+
on:click={menu.actions.close}
|
|
129
|
+
>
|
|
130
|
+
Edit row in modal
|
|
131
|
+
</MenuItem>
|
|
132
|
+
<MenuItem
|
|
133
|
+
icon="Copy"
|
|
134
|
+
disabled={isNewRow || !$focusedRow?._id || !$hasBudibaseIdentifiers}
|
|
135
|
+
on:click={() => copyToClipboard($focusedRow?._id)}
|
|
136
|
+
on:click={menu.actions.close}
|
|
137
|
+
>
|
|
138
|
+
Copy row _id
|
|
139
|
+
</MenuItem>
|
|
140
|
+
<MenuItem
|
|
141
|
+
icon="Copy"
|
|
142
|
+
disabled={isNewRow ||
|
|
143
|
+
!$focusedRow?._rev ||
|
|
144
|
+
!$hasBudibaseIdentifiers}
|
|
145
|
+
on:click={() => copyToClipboard($focusedRow?._rev)}
|
|
146
|
+
on:click={menu.actions.close}
|
|
147
|
+
>
|
|
148
|
+
Copy row _rev
|
|
149
|
+
</MenuItem>
|
|
150
|
+
<MenuItem
|
|
151
|
+
icon="Duplicate"
|
|
152
|
+
disabled={isNewRow || !$config.canAddRows}
|
|
153
|
+
on:click={duplicateRow}
|
|
154
|
+
>
|
|
155
|
+
Duplicate row
|
|
156
|
+
</MenuItem>
|
|
157
|
+
<MenuItem
|
|
158
|
+
icon="Delete"
|
|
159
|
+
disabled={isNewRow || !$config.canDeleteRows}
|
|
160
|
+
on:click={deleteRow}
|
|
161
|
+
>
|
|
162
|
+
Delete row
|
|
163
|
+
</MenuItem>
|
|
164
|
+
{/if}
|
|
114
165
|
</Menu>
|
|
115
166
|
</GridPopover>
|
|
116
167
|
{/key}
|