Remove copy/paste rows, remove move to start/end, improve copy/paste for cell values
This commit is contained in:
parent
ddc11ab88c
commit
b1d227b65f
|
@ -16,7 +16,7 @@
|
||||||
export let column
|
export let column
|
||||||
export let row
|
export let row
|
||||||
export let cellId
|
export let cellId
|
||||||
export let updateRow = rows.actions.updateRow
|
export let updateValue = rows.actions.updateValue
|
||||||
export let invertX = false
|
export let invertX = false
|
||||||
export let invertY = false
|
export let invertY = false
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
getValue: () => row[column.name],
|
getValue: () => row[column.name],
|
||||||
setValue: value => {
|
setValue: value => {
|
||||||
validation.actions.setError(cellId, null)
|
validation.actions.setError(cellId, null)
|
||||||
updateRow(row._id, column.name, value)
|
updateValue(row._id, column.name, value)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -177,26 +177,12 @@
|
||||||
>
|
>
|
||||||
Sort Z-A
|
Sort Z-A
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
|
||||||
disabled={!canMoveLeft}
|
|
||||||
icon="ChevronDoubleLeft"
|
|
||||||
on:click={moveStart}
|
|
||||||
>
|
|
||||||
Move to start
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem disabled={!canMoveLeft} icon="ChevronLeft" on:click={moveLeft}>
|
<MenuItem disabled={!canMoveLeft} icon="ChevronLeft" on:click={moveLeft}>
|
||||||
Move left
|
Move left
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem disabled={!canMoveRight} icon="ChevronRight" on:click={moveRight}>
|
<MenuItem disabled={!canMoveRight} icon="ChevronRight" on:click={moveRight}>
|
||||||
Move right
|
Move right
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
|
||||||
disabled={!canMoveRight}
|
|
||||||
icon="ChevronDoubleRight"
|
|
||||||
on:click={moveEnd}
|
|
||||||
>
|
|
||||||
Move to end
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateRow = (rowId, columnName, val) => {
|
const updateValue = (rowId, columnName, val) => {
|
||||||
touched = true
|
touched = true
|
||||||
newRow[columnName] = val
|
newRow[columnName] = val
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
focused={$focusedCellId === cellId}
|
focused={$focusedCellId === cellId}
|
||||||
{rowFocused}
|
{rowFocused}
|
||||||
width={$stickyColumn.width}
|
width={$stickyColumn.width}
|
||||||
{updateRow}
|
{updateValue}
|
||||||
rowIdx={0}
|
rowIdx={0}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
focused={$focusedCellId === cellId}
|
focused={$focusedCellId === cellId}
|
||||||
{rowFocused}
|
{rowFocused}
|
||||||
width={column.width}
|
width={column.width}
|
||||||
{updateRow}
|
{updateValue}
|
||||||
rowIdx={0}
|
rowIdx={0}
|
||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
|
|
|
@ -9,15 +9,15 @@
|
||||||
focusedRow,
|
focusedRow,
|
||||||
stickyColumn,
|
stickyColumn,
|
||||||
focusedCellAPI,
|
focusedCellAPI,
|
||||||
|
clipboard,
|
||||||
} = getContext("sheet")
|
} = getContext("sheet")
|
||||||
|
|
||||||
let copiedValue
|
|
||||||
|
|
||||||
// Global key listener which intercepts all key events
|
// Global key listener which intercepts all key events
|
||||||
const handleKeyDown = e => {
|
const handleKeyDown = e => {
|
||||||
// If nothing selected avoid processing further key presses
|
// If nothing selected avoid processing further key presses
|
||||||
if (!$focusedCellId) {
|
if (!$focusedCellId) {
|
||||||
if (e.key === "Tab") {
|
if (e.key === "Tab") {
|
||||||
|
e.preventDefault()
|
||||||
focusFirstCell()
|
focusFirstCell()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -46,10 +46,10 @@
|
||||||
if (e.metaKey || e.ctrlKey) {
|
if (e.metaKey || e.ctrlKey) {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case "c":
|
case "c":
|
||||||
copy()
|
clipboard.actions.copy()
|
||||||
break
|
break
|
||||||
case "v":
|
case "v":
|
||||||
paste()
|
clipboard.actions.paste()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -144,18 +144,6 @@
|
||||||
$focusedCellAPI?.focus?.()
|
$focusedCellAPI?.focus?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the value from the current cell
|
|
||||||
const copy = () => {
|
|
||||||
copiedValue = $focusedCellAPI?.getValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pastes the copied value
|
|
||||||
const paste = () => {
|
|
||||||
if (copiedValue != null) {
|
|
||||||
$focusedCellAPI?.setValue(copiedValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utils to identify a key code
|
// Utils to identify a key code
|
||||||
const keyCodeIsNumber = keyCode => keyCode >= 48 && keyCode <= 57
|
const keyCodeIsNumber = keyCode => keyCode >= 48 && keyCode <= 57
|
||||||
const keyCodeIsLetter = keyCode => keyCode >= 65 && keyCode <= 90
|
const keyCodeIsLetter = keyCode => keyCode >= 65 && keyCode <= 90
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
focusedCellId,
|
focusedCellId,
|
||||||
stickyColumn,
|
stickyColumn,
|
||||||
config,
|
config,
|
||||||
|
copiedCell,
|
||||||
|
clipboard,
|
||||||
} = getContext("sheet")
|
} = getContext("sheet")
|
||||||
|
|
||||||
$: style = makeStyle($menu)
|
$: style = makeStyle($menu)
|
||||||
|
@ -37,16 +39,35 @@
|
||||||
{#if $menu.visible}
|
{#if $menu.visible}
|
||||||
<div class="menu" {style} use:clickOutside={() => menu.actions.close()}>
|
<div class="menu" {style} use:clickOutside={() => menu.actions.close()}>
|
||||||
<Menu>
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
icon="Copy"
|
||||||
|
on:click={clipboard.actions.copyCell}
|
||||||
|
on:click={menu.actions.close}
|
||||||
|
>
|
||||||
|
Copy
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
icon="Paste"
|
||||||
|
disabled={$copiedCell == null}
|
||||||
|
on:click={clipboard.actions.pasteCell}
|
||||||
|
on:click={menu.actions.close}
|
||||||
|
>
|
||||||
|
Paste
|
||||||
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon="Delete"
|
icon="Delete"
|
||||||
disabled={!$config.allowDeleteRows}
|
disabled={!$config.allowDeleteRows}
|
||||||
on:click={deleteRow}>Delete row</MenuItem
|
on:click={deleteRow}
|
||||||
>
|
>
|
||||||
|
Delete row
|
||||||
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon="Duplicate"
|
icon="Duplicate"
|
||||||
disabled={!$config.allowAddRows}
|
disabled={!$config.allowAddRows}
|
||||||
on:click={duplicate}>Duplicate row</MenuItem
|
on:click={duplicate}
|
||||||
>
|
>
|
||||||
|
Duplicate row
|
||||||
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
|
||||||
|
export const createStores = () => {
|
||||||
|
const copiedCell = writable(null)
|
||||||
|
const copiedRow = writable(null)
|
||||||
|
|
||||||
|
return {
|
||||||
|
copiedCell,
|
||||||
|
copiedRow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deriveStores = context => {
|
||||||
|
const { copiedCell, copiedRow, focusedCellAPI } = context
|
||||||
|
|
||||||
|
const copy = () => {
|
||||||
|
copiedCell.set(get(focusedCellAPI)?.getValue())
|
||||||
|
copiedRow.set(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const paste = () => {
|
||||||
|
const $copiedCell = get(copiedCell)
|
||||||
|
const $focusedCellAPI = get(focusedCellAPI)
|
||||||
|
if ($copiedCell != null && $focusedCellAPI) {
|
||||||
|
$focusedCellAPI.setValue($copiedCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
clipboard: {
|
||||||
|
actions: {
|
||||||
|
copy,
|
||||||
|
paste,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import * as UI from "./ui"
|
||||||
import * as Users from "./users"
|
import * as Users from "./users"
|
||||||
import * as Validation from "./validation"
|
import * as Validation from "./validation"
|
||||||
import * as Viewport from "./viewport"
|
import * as Viewport from "./viewport"
|
||||||
|
import * as Clipboard from "./clipboard"
|
||||||
|
|
||||||
const DependencyOrderedStores = [
|
const DependencyOrderedStores = [
|
||||||
Bounds,
|
Bounds,
|
||||||
|
@ -24,6 +25,7 @@ const DependencyOrderedStores = [
|
||||||
Users,
|
Users,
|
||||||
Menu,
|
Menu,
|
||||||
Pagination,
|
Pagination,
|
||||||
|
Clipboard,
|
||||||
]
|
]
|
||||||
|
|
||||||
export const attachStores = context => {
|
export const attachStores = context => {
|
||||||
|
|
|
@ -122,17 +122,6 @@ export const deriveStores = context => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const moveColumnToStart = async column => {
|
|
||||||
moveColumn(column, null)
|
|
||||||
await columns.actions.saveChanges()
|
|
||||||
}
|
|
||||||
|
|
||||||
const moveColumnToEnd = async column => {
|
|
||||||
const $visibleColumns = get(visibleColumns)
|
|
||||||
moveColumn(column, $visibleColumns[$visibleColumns.length - 1]?.name)
|
|
||||||
await columns.actions.saveChanges()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moves a column one place left (as appears visually)
|
// Moves a column one place left (as appears visually)
|
||||||
const moveColumnLeft = async column => {
|
const moveColumnLeft = async column => {
|
||||||
const $visibleColumns = get(visibleColumns)
|
const $visibleColumns = get(visibleColumns)
|
||||||
|
@ -160,8 +149,6 @@ export const deriveStores = context => {
|
||||||
stopReordering,
|
stopReordering,
|
||||||
moveColumnLeft,
|
moveColumnLeft,
|
||||||
moveColumnRight,
|
moveColumnRight,
|
||||||
moveColumnToStart,
|
|
||||||
moveColumnToEnd,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,13 +283,25 @@ export const deriveStores = context => {
|
||||||
get(fetch)?.getInitialData()
|
get(fetch)?.getInitialData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates a value of a row
|
// Patches a row with some changes
|
||||||
const updateRow = async (rowId, column, value) => {
|
const updateRow = async (rowId, changes) => {
|
||||||
const $rows = get(rows)
|
const $rows = get(rows)
|
||||||
const $rowLookupMap = get(rowLookupMap)
|
const $rowLookupMap = get(rowLookupMap)
|
||||||
const index = $rowLookupMap[rowId]
|
const index = $rowLookupMap[rowId]
|
||||||
const row = $rows[index]
|
const row = $rows[index]
|
||||||
if (index == null || row?.[column] === value) {
|
if (index == null || !Object.keys(changes || {}).length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abandon if no changes
|
||||||
|
let same = true
|
||||||
|
for (let column of Object.keys(changes)) {
|
||||||
|
if (row[column] !== changes[column]) {
|
||||||
|
same = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (same) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +310,7 @@ export const deriveStores = context => {
|
||||||
...state,
|
...state,
|
||||||
[rowId]: {
|
[rowId]: {
|
||||||
...state[rowId],
|
...state[rowId],
|
||||||
[column]: value,
|
...changes,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -332,6 +344,11 @@ export const deriveStores = context => {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates a value of a row
|
||||||
|
const updateValue = async (rowId, column, value) => {
|
||||||
|
return await updateRow(rowId, { [column]: value })
|
||||||
|
}
|
||||||
|
|
||||||
// Deletes an array of rows
|
// Deletes an array of rows
|
||||||
const deleteRows = async rowsToDelete => {
|
const deleteRows = async rowsToDelete => {
|
||||||
if (!rowsToDelete?.length) {
|
if (!rowsToDelete?.length) {
|
||||||
|
@ -418,6 +435,7 @@ export const deriveStores = context => {
|
||||||
addRow,
|
addRow,
|
||||||
duplicateRow,
|
duplicateRow,
|
||||||
getRow,
|
getRow,
|
||||||
|
updateValue,
|
||||||
updateRow,
|
updateRow,
|
||||||
deleteRows,
|
deleteRows,
|
||||||
hasRow,
|
hasRow,
|
||||||
|
|
Loading…
Reference in New Issue