Refactor stores and make state more modular
This commit is contained in:
parent
b82e7582db
commit
37393c4e2a
|
@ -20,10 +20,6 @@
|
||||||
// Deletion callback when confirmed
|
// Deletion callback when confirmed
|
||||||
const performDeletion = async () => {
|
const performDeletion = async () => {
|
||||||
await rows.actions.deleteRows(rowsToDelete)
|
await rows.actions.deleteRows(rowsToDelete)
|
||||||
|
|
||||||
// Refresh state
|
|
||||||
$selectedCellId = null
|
|
||||||
$selectedRows = {}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
import { createRowsStore } from "./stores/rows"
|
import { createRowsStore } from "./stores/rows"
|
||||||
import { createColumnsStores } from "./stores/columns"
|
import { createColumnsStores } from "./stores/columns"
|
||||||
import { createScrollStores } from "./stores/scroll"
|
import { createScrollStores } from "./stores/scroll"
|
||||||
|
import { createBoundsStores } from "./stores/bounds"
|
||||||
|
import { createInterfaceStores } from "./stores/interface"
|
||||||
import DeleteButton from "./DeleteButton.svelte"
|
import DeleteButton from "./DeleteButton.svelte"
|
||||||
import SheetBody from "./SheetBody.svelte"
|
import SheetBody from "./SheetBody.svelte"
|
||||||
import SheetRow from "./SheetRow.svelte"
|
import SheetRow from "./SheetRow.svelte"
|
||||||
|
@ -38,42 +40,23 @@
|
||||||
allowAddColumns,
|
allowAddColumns,
|
||||||
allowSelectRows,
|
allowSelectRows,
|
||||||
})
|
})
|
||||||
const selectedCellId = writable()
|
|
||||||
const selectedRows = writable({})
|
|
||||||
const hoveredRowId = writable()
|
|
||||||
const scroll = writable({
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
})
|
|
||||||
const bounds = writable({
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Build up spreadsheet context and additional stores
|
// Build up spreadsheet context
|
||||||
|
// Stores are listed in order of dependency on each other
|
||||||
let context = {
|
let context = {
|
||||||
API: API || createAPIClient(),
|
API: API || createAPIClient(),
|
||||||
rand,
|
rand,
|
||||||
selectedCellId,
|
|
||||||
selectedRows,
|
|
||||||
cellHeight,
|
cellHeight,
|
||||||
bounds,
|
|
||||||
scroll,
|
|
||||||
hoveredRowId,
|
|
||||||
config,
|
config,
|
||||||
dispatch,
|
dispatch,
|
||||||
}
|
}
|
||||||
const { rows, schema } = createRowsStore(context)
|
context = { ...context, ...createRowsStore(context) }
|
||||||
context = { ...context, rows, schema }
|
context = { ...context, ...createColumnsStores(context) }
|
||||||
const { columns, stickyColumn } = createColumnsStores(context)
|
context = { ...context, ...createBoundsStores(context) }
|
||||||
context = { ...context, columns, stickyColumn }
|
|
||||||
context = { ...context, ...createScrollStores(context) }
|
context = { ...context, ...createScrollStores(context) }
|
||||||
const { visibleRows, visibleColumns } = createViewportStores(context)
|
context = { ...context, ...createViewportStores(context) }
|
||||||
context = { ...context, visibleRows, visibleColumns }
|
context = { ...context, ...createReorderStores(context) }
|
||||||
const { reorder } = createReorderStores(context)
|
context = { ...context, ...createInterfaceStores(context) }
|
||||||
context = { ...context, reorder }
|
|
||||||
|
|
||||||
// Keep config store up to date
|
// Keep config store up to date
|
||||||
$: config.set({
|
$: config.set({
|
||||||
|
@ -94,14 +77,7 @@
|
||||||
<StickyColumn />
|
<StickyColumn />
|
||||||
<div class="sheet-main">
|
<div class="sheet-main">
|
||||||
<HeaderRow />
|
<HeaderRow />
|
||||||
<SheetBody>
|
<SheetBody />
|
||||||
{#each $visibleRows as row}
|
|
||||||
<SheetRow {row} />
|
|
||||||
{/each}
|
|
||||||
{#if allowAddRows}
|
|
||||||
<NewRow />
|
|
||||||
{/if}
|
|
||||||
</SheetBody>
|
|
||||||
</div>
|
</div>
|
||||||
<DeleteButton />
|
<DeleteButton />
|
||||||
<ResizeOverlay />
|
<ResizeOverlay />
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext, onMount } from "svelte"
|
import { getContext, onMount } from "svelte"
|
||||||
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
|
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
|
||||||
|
import NewRow from "./NewRow.svelte"
|
||||||
|
import SheetRow from "./SheetRow.svelte"
|
||||||
|
|
||||||
const { selectedCellId, bounds } = getContext("spreadsheet")
|
const { selectedCellId, bounds, visibleRows, config } =
|
||||||
|
getContext("spreadsheet")
|
||||||
|
|
||||||
let ref
|
let ref
|
||||||
|
|
||||||
|
@ -24,7 +27,12 @@
|
||||||
on:click|self={() => ($selectedCellId = null)}
|
on:click|self={() => ($selectedCellId = null)}
|
||||||
>
|
>
|
||||||
<SheetScrollWrapper>
|
<SheetScrollWrapper>
|
||||||
<slot />
|
{#each $visibleRows as row}
|
||||||
|
<SheetRow {row} />
|
||||||
|
{/each}
|
||||||
|
{#if $config.allowAddRows}
|
||||||
|
<NewRow />
|
||||||
|
{/if}
|
||||||
</SheetScrollWrapper>
|
</SheetScrollWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectRow = id => {
|
const selectRow = id => {
|
||||||
selectedRows.update(state => ({
|
selectedRows.update(state => {
|
||||||
...state,
|
let newState = {
|
||||||
[id]: !state[id],
|
...state,
|
||||||
}))
|
[id]: !state[id],
|
||||||
|
}
|
||||||
|
if (!newState[id]) {
|
||||||
|
delete newState[id]
|
||||||
|
}
|
||||||
|
return newState
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addRow = async field => {
|
const addRow = async field => {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
export const createBoundsStores = () => {
|
||||||
|
const bounds = writable({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
})
|
||||||
|
return { bounds }
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
|
||||||
|
export const createInterfaceStores = context => {
|
||||||
|
const { rows } = context
|
||||||
|
const selectedCellId = writable(null)
|
||||||
|
const selectedRows = writable({})
|
||||||
|
const hoveredRowId = writable(null)
|
||||||
|
|
||||||
|
// Ensure we clear invalid rows from state if they disappear
|
||||||
|
rows.subscribe($rows => {
|
||||||
|
const $selectedCellId = get(selectedCellId)
|
||||||
|
const $selectedRows = get(selectedRows)
|
||||||
|
const $hoveredRowId = get(hoveredRowId)
|
||||||
|
|
||||||
|
// Check selected cell
|
||||||
|
const selectedRowId = $selectedCellId?.split("-")[0]
|
||||||
|
if (selectedRowId && !$rows.find(row => row._id === selectedRowId)) {
|
||||||
|
selectedCellId.set(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check hovered row
|
||||||
|
if ($hoveredRowId && !$rows.find(row => row._id === $hoveredRowId)) {
|
||||||
|
hoveredRowId.set(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check selected rows
|
||||||
|
let newSelectedRows = { ...$selectedRows }
|
||||||
|
let selectedRowsNeedsUpdate = false
|
||||||
|
const selectedIds = Object.keys($selectedRows)
|
||||||
|
for (let i = 0; i < selectedIds.length; i++) {
|
||||||
|
if (!$rows.find(row => row._id === selectedIds[i])) {
|
||||||
|
delete newSelectedRows[selectedIds[i]]
|
||||||
|
selectedRowsNeedsUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedRowsNeedsUpdate) {
|
||||||
|
selectedRows.set(newSelectedRows)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return { selectedCellId, selectedRows, hoveredRowId }
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import { fetchData } from "../../../fetch/fetchData"
|
||||||
import { notifications } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
|
|
||||||
export const createRowsStore = context => {
|
export const createRowsStore = context => {
|
||||||
const { config, API, scroll } = context
|
const { config, API } = context
|
||||||
const tableId = derived(config, $config => $config.tableId)
|
const tableId = derived(config, $config => $config.tableId)
|
||||||
const filter = derived(config, $config => $config.filter)
|
const filter = derived(config, $config => $config.filter)
|
||||||
|
|
||||||
|
@ -64,9 +64,6 @@ export const createRowsStore = context => {
|
||||||
newSchema[primaryDisplay].primaryDisplay = true
|
newSchema[primaryDisplay].primaryDisplay = true
|
||||||
}
|
}
|
||||||
schema.set(newSchema)
|
schema.set(newSchema)
|
||||||
|
|
||||||
// Reset scroll state for fresh dataset
|
|
||||||
scroll.set({ left: 0, top: 0 })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process new rows
|
// Process new rows
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import { derived, get } from "svelte/store"
|
import { derived, get, writable } from "svelte/store"
|
||||||
|
|
||||||
export const createScrollStores = context => {
|
export const createScrollStores = context => {
|
||||||
const { scroll, rows, columns, stickyColumn, bounds, cellHeight } = context
|
const { rows, columns, stickyColumn, bounds, cellHeight } = context
|
||||||
const padding = 180
|
const padding = 180
|
||||||
|
const scroll = writable({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
})
|
||||||
|
|
||||||
// Memoize store primitives
|
// Memoize store primitives
|
||||||
const scrollTop = derived(scroll, $scroll => $scroll.top)
|
const scrollTop = derived(scroll, $scroll => $scroll.top)
|
||||||
|
@ -77,6 +81,7 @@ export const createScrollStores = context => {
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
scroll,
|
||||||
contentHeight,
|
contentHeight,
|
||||||
contentWidth,
|
contentWidth,
|
||||||
maxScrollTop,
|
maxScrollTop,
|
||||||
|
|
Loading…
Reference in New Issue