Refactor grid stores and how config is handled

This commit is contained in:
Andrew Kingston 2023-07-27 14:17:26 +01:00
parent c4e4b5c979
commit deb4092cd3
25 changed files with 193 additions and 136 deletions

View File

@ -26,16 +26,14 @@
$: id = $tables.selected?._id $: id = $tables.selected?._id
$: isUsersTable = id === TableNames.USERS $: isUsersTable = id === TableNames.USERS
$: isInternal = $tables.selected?.type !== "external" $: isInternal = $tables.selected?.type !== "external"
$: datasource = { $: gridDatasource = {
type: "table", type: "table",
tableId: id, tableId: id,
} }
$: tableDatasource = $datasources.list.find(datasource => {
$: datasource = $datasources.list.find(datasource => {
return datasource._id === $tables.selected?.sourceId return datasource._id === $tables.selected?.sourceId
}) })
$: relationshipsEnabled = relationshipSupport(tableDatasource)
$: relationshipsEnabled = relationshipSupport(datasource)
const relationshipSupport = datasource => { const relationshipSupport = datasource => {
const integration = $integrations[datasource?.source] const integration = $integrations[datasource?.source]
@ -58,7 +56,7 @@
<div class="wrapper"> <div class="wrapper">
<Grid <Grid
{API} {API}
{datasource} datasource={gridDatasource}
allowAddRows={!isUsersTable} allowAddRows={!isUsersTable}
allowDeleteRows={!isUsersTable} allowDeleteRows={!isUsersTable}
schemaOverrides={isUsersTable ? userSchemaOverrides : null} schemaOverrides={isUsersTable ? userSchemaOverrides : null}

View File

@ -1,7 +1,6 @@
export const buildViewV2Endpoints = API => ({ export const buildViewV2Endpoints = API => ({
/** /**
* Create a new view * Create a new view
* @param tableId the id of the table where the view will be created
* @param view the view object * @param view the view object
*/ */
create: async view => { create: async view => {
@ -10,9 +9,18 @@ export const buildViewV2Endpoints = API => ({
body: view, body: view,
}) })
}, },
/**
* Updates a view
* @param view the view object
*/
update: async view => {
return await API.put({
url: `/api/v2/views/${view.id}`,
body: view,
})
},
/** /**
* Fetches all rows in a view * Fetches all rows in a view
* @param tableId the id of the table
* @param viewId the id of the view * @param viewId the id of the view
*/ */
fetch: async viewId => { fetch: async viewId => {
@ -20,7 +28,6 @@ export const buildViewV2Endpoints = API => ({
}, },
/** /**
* Delete a view * Delete a view
* @param tableId the id of the table
* @param viewId the id of the view * @param viewId the id of the view
*/ */
delete: async viewId => { delete: async viewId => {

View File

@ -34,7 +34,7 @@
column.schema.autocolumn || column.schema.autocolumn ||
column.schema.disabled || column.schema.disabled ||
column.schema.type === "formula" || column.schema.type === "formula" ||
(!$config.allowEditRows && row._id) (!$config.canEditRows && row._id)
// Register this cell API if the row is focused // Register this cell API if the row is focused
$: { $: {

View File

@ -40,7 +40,7 @@
<div <div
on:click={select} on:click={select}
class="checkbox" class="checkbox"
class:visible={$config.allowDeleteRows && class:visible={$config.canDeleteRows &&
(disableNumber || rowSelected || rowHovered || rowFocused)} (disableNumber || rowSelected || rowHovered || rowFocused)}
> >
<Checkbox value={rowSelected} {disabled} /> <Checkbox value={rowSelected} {disabled} />
@ -48,14 +48,14 @@
{#if !disableNumber} {#if !disableNumber}
<div <div
class="number" class="number"
class:visible={!$config.allowDeleteRows || class:visible={!$config.canDeleteRows ||
!(rowSelected || rowHovered || rowFocused)} !(rowSelected || rowHovered || rowFocused)}
> >
{row.__idx + 1} {row.__idx + 1}
</div> </div>
{/if} {/if}
{/if} {/if}
{#if rowSelected && $config.allowDeleteRows} {#if rowSelected && $config.canDeleteRows}
<div class="delete" on:click={() => dispatch("request-bulk-delete")}> <div class="delete" on:click={() => dispatch("request-bulk-delete")}>
<Icon <Icon
name="Delete" name="Delete"
@ -64,7 +64,7 @@
/> />
</div> </div>
{:else} {:else}
<div class="expand" class:visible={$config.allowExpandRows && expandable}> <div class="expand" class:visible={$config.canExpandRows && expandable}>
<Icon <Icon
size="S" size="S"
name="Maximize" name="Maximize"

View File

@ -167,7 +167,7 @@
<MenuItem <MenuItem
icon="Edit" icon="Edit"
on:click={editColumn} on:click={editColumn}
disabled={!$config.allowSchemaChanges || column.schema.disabled} disabled={!$config.canEditColumns || column.schema.disabled}
> >
Edit column Edit column
</MenuItem> </MenuItem>
@ -175,7 +175,7 @@
icon="Label" icon="Label"
on:click={makeDisplayColumn} on:click={makeDisplayColumn}
disabled={idx === "sticky" || disabled={idx === "sticky" ||
!$config.allowSchemaChanges || !$config.canEditPrimaryDisplay ||
bannedDisplayColumnTypes.includes(column.schema.type)} bannedDisplayColumnTypes.includes(column.schema.type)}
> >
Use as display column Use as display column

View File

@ -1,5 +1,6 @@
<script> <script>
import { setContext, onMount } from "svelte" import { setContext, onMount } from "svelte"
import { writable } from "svelte/store"
import { fade } from "svelte/transition" import { fade } from "svelte/transition"
import { clickOutside, ProgressCircle } from "@budibase/bbui" import { clickOutside, ProgressCircle } from "@budibase/bbui"
import { createEventManagers } from "../lib/events" import { createEventManagers } from "../lib/events"
@ -35,6 +36,7 @@
export let allowExpandRows = true export let allowExpandRows = true
export let allowEditRows = true export let allowEditRows = true
export let allowDeleteRows = true export let allowDeleteRows = true
export let allowEditColumns = true
export let allowSchemaChanges = true export let allowSchemaChanges = true
export let stripeRows = false export let stripeRows = false
export let collaboration = true export let collaboration = true
@ -50,11 +52,14 @@
// Unique identifier for DOM nodes inside this instance // Unique identifier for DOM nodes inside this instance
const rand = Math.random() const rand = Math.random()
// Store props in a store for reference in other stores
const props = writable($$props)
// Build up context // Build up context
let context = { let context = {
API: API || createAPIClient(), API: API || createAPIClient(),
rand, rand,
props: $$props, props,
} }
context = { ...context, ...createEventManagers() } context = { ...context, ...createEventManagers() }
context = attachStores(context) context = attachStores(context)
@ -71,11 +76,10 @@
contentLines, contentLines,
gridFocused, gridFocused,
error, error,
canAddRows,
} = context } = context
// Keep config store up to date with props // Keep config store up to date with props
$: config.set({ $: props.set({
datasource, datasource,
schemaOverrides, schemaOverrides,
columnWhitelist, columnWhitelist,
@ -83,6 +87,7 @@
allowExpandRows, allowExpandRows,
allowEditRows, allowEditRows,
allowDeleteRows, allowDeleteRows,
allowEditColumns,
allowSchemaChanges, allowSchemaChanges,
stripeRows, stripeRows,
collaboration, collaboration,
@ -144,7 +149,7 @@
<HeaderRow /> <HeaderRow />
<GridBody /> <GridBody />
</div> </div>
{#if $canAddRows} {#if $config.canAddRows}
<NewRow /> <NewRow />
{/if} {/if}
<div class="overlays"> <div class="overlays">
@ -168,7 +173,7 @@
<ProgressCircle /> <ProgressCircle />
</div> </div>
{/if} {/if}
{#if allowDeleteRows} {#if $config.canDeleteRows}
<BulkDeleteHandler /> <BulkDeleteHandler />
{/if} {/if}
<KeyboardManager /> <KeyboardManager />

View File

@ -9,10 +9,10 @@
renderedRows, renderedRows,
renderedColumns, renderedColumns,
rowVerticalInversionIndex, rowVerticalInversionIndex,
canAddRows,
hoveredRowId, hoveredRowId,
dispatch, dispatch,
isDragging, isDragging,
config,
} = getContext("grid") } = getContext("grid")
let body let body
@ -43,7 +43,7 @@
invertY={idx >= $rowVerticalInversionIndex} invertY={idx >= $rowVerticalInversionIndex}
/> />
{/each} {/each}
{#if $canAddRows} {#if $config.canAddRows}
<div <div
class="blank" class="blank"
class:highlighted={$hoveredRowId === BlankRowID} class:highlighted={$hoveredRowId === BlankRowID}

View File

@ -32,7 +32,7 @@
{/each} {/each}
</div> </div>
</GridScrollWrapper> </GridScrollWrapper>
{#if $config.allowSchemaChanges} {#if $config.canEditColumns}
{#key $datasource} {#key $datasource}
<TempTooltip <TempTooltip
text="Click here to create your first column" text="Click here to create your first column"

View File

@ -28,7 +28,7 @@
columnHorizontalInversionIndex, columnHorizontalInversionIndex,
selectedRows, selectedRows,
loading, loading,
canAddRows, config,
} = getContext("grid") } = getContext("grid")
let visible = false let visible = false
@ -154,7 +154,7 @@
condition={hasNoRows && !$loading} condition={hasNoRows && !$loading}
type={TooltipType.Info} type={TooltipType.Info}
> >
{#if !visible && !selectedRowCount && $canAddRows} {#if !visible && !selectedRowCount && $config.canAddRows}
<div <div
class="new-row-fab" class="new-row-fab"
on:click={() => dispatch("add-row-inline")} on:click={() => dispatch("add-row-inline")}

View File

@ -16,7 +16,7 @@
renderedRows, renderedRows,
focusedCellId, focusedCellId,
hoveredRowId, hoveredRowId,
canAddRows, config,
selectedCellMap, selectedCellMap,
focusedRow, focusedRow,
scrollLeft, scrollLeft,
@ -92,7 +92,7 @@
{/if} {/if}
</div> </div>
{/each} {/each}
{#if $canAddRows} {#if $config.canAddRows}
<div <div
class="row new" class="row new"
on:mouseenter={$isDragging on:mouseenter={$isDragging

View File

@ -16,7 +16,6 @@
config, config,
menu, menu,
gridFocused, gridFocused,
canAddRows,
} = getContext("grid") } = getContext("grid")
const ignoredOriginSelectors = [ const ignoredOriginSelectors = [
@ -46,12 +45,12 @@
e.preventDefault() e.preventDefault()
focusFirstCell() focusFirstCell()
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { } else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
if ($canAddRows) { if ($config.canAddRows) {
e.preventDefault() e.preventDefault()
dispatch("add-row-inline") dispatch("add-row-inline")
} }
} else if (e.key === "Delete" || e.key === "Backspace") { } else if (e.key === "Delete" || e.key === "Backspace") {
if (Object.keys($selectedRows).length && $config.allowDeleteRows) { if (Object.keys($selectedRows).length && $config.canDeleteRows) {
dispatch("request-bulk-delete") dispatch("request-bulk-delete")
} }
} }
@ -100,7 +99,7 @@
} }
break break
case "Enter": case "Enter":
if ($canAddRows) { if ($config.canAddRows) {
dispatch("add-row-inline") dispatch("add-row-inline")
} }
} }
@ -120,7 +119,7 @@
break break
case "Delete": case "Delete":
case "Backspace": case "Backspace":
if (Object.keys($selectedRows).length && $config.allowDeleteRows) { if (Object.keys($selectedRows).length && $config.canDeleteRows) {
dispatch("request-bulk-delete") dispatch("request-bulk-delete")
} else { } else {
deleteSelectedCell() deleteSelectedCell()
@ -131,7 +130,7 @@
break break
case " ": case " ":
case "Space": case "Space":
if ($config.allowDeleteRows) { if ($config.canDeleteRows) {
toggleSelectRow() toggleSelectRow()
} }
break break

View File

@ -17,7 +17,6 @@
focusedCellAPI, focusedCellAPI,
focusedRowId, focusedRowId,
notifications, notifications,
canAddRows,
} = getContext("grid") } = getContext("grid")
$: style = makeStyle($menu) $: style = makeStyle($menu)
@ -68,9 +67,7 @@
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon="Maximize" icon="Maximize"
disabled={isNewRow || disabled={isNewRow || !$config.canEditRows || !$config.canExpandRows}
!$config.allowEditRows ||
!$config.allowExpandRows}
on:click={() => dispatch("edit-row", $focusedRow)} on:click={() => dispatch("edit-row", $focusedRow)}
on:click={menu.actions.close} on:click={menu.actions.close}
> >
@ -94,14 +91,14 @@
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon="Duplicate" icon="Duplicate"
disabled={isNewRow || !$canAddRows} disabled={isNewRow || !$config.canAddRows}
on:click={duplicate} on:click={duplicate}
> >
Duplicate row Duplicate row
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon="Delete" icon="Delete"
disabled={isNewRow || !$config.allowDeleteRows} disabled={isNewRow || !$config.canDeleteRows}
on:click={deleteRow} on:click={deleteRow}
> >
Delete row Delete row

View File

@ -8,7 +8,7 @@ export const createStores = () => {
} }
} }
export const deriveStores = context => { export const createActions = context => {
const { copiedCell, focusedCellAPI } = context const { copiedCell, focusedCellAPI } = context
const copy = () => { const copy = () => {

View File

@ -35,20 +35,10 @@ export const createStores = () => {
[] []
) )
// Checks if we have a certain column by name
const hasColumn = column => {
const $columns = get(columns)
const $sticky = get(stickyColumn)
return $columns.some(col => col.name === column) || $sticky?.name === column
}
return { return {
columns: { columns: {
...columns, ...columns,
subscribe: enrichedColumns.subscribe, subscribe: enrichedColumns.subscribe,
actions: {
hasColumn,
},
}, },
stickyColumn, stickyColumn,
visibleColumns, visibleColumns,
@ -56,10 +46,43 @@ export const createStores = () => {
} }
export const deriveStores = context => { export const deriveStores = context => {
const { columns, stickyColumn } = context
// Derive if we have any normal columns
const hasNonAutoColumn = derived(
[columns, stickyColumn],
([$columns, $stickyColumn]) => {
let allCols = $columns || []
if ($stickyColumn) {
allCols = [...allCols, $stickyColumn]
}
const normalCols = allCols.filter(column => {
return !column.schema?.autocolumn
})
return normalCols.length > 0
}
)
return {
hasNonAutoColumn,
}
}
export const createActions = context => {
const { table, columns, stickyColumn, API, dispatch, config } = context const { table, columns, stickyColumn, API, dispatch, config } = context
// Checks if we have a certain column by name
const hasColumn = column => {
const $columns = get(columns)
const $sticky = get(stickyColumn)
return $columns.some(col => col.name === column) || $sticky?.name === column
}
// Updates the tables primary display column // Updates the tables primary display column
const changePrimaryDisplay = async column => { const changePrimaryDisplay = async column => {
if (!get(config).canEditPrimaryDisplay) {
return
}
return await saveTable({ return await saveTable({
...get(table), ...get(table),
primaryDisplay: column, primaryDisplay: column,
@ -83,21 +106,6 @@ export const deriveStores = context => {
await saveChanges() await saveChanges()
} }
// Derive if we have any normal columns
const hasNonAutoColumn = derived(
[columns, stickyColumn],
([$columns, $stickyColumn]) => {
let allCols = $columns || []
if ($stickyColumn) {
allCols = [...allCols, $stickyColumn]
}
const normalCols = allCols.filter(column => {
return !column.schema?.autocolumn
})
return normalCols.length > 0
}
)
// Persists column changes by saving metadata against table schema // Persists column changes by saving metadata against table schema
const saveChanges = async () => { const saveChanges = async () => {
const $columns = get(columns) const $columns = get(columns)
@ -133,7 +141,7 @@ export const deriveStores = context => {
table.set(newTable) table.set(newTable)
// Update server // Update server
if (get(config).allowSchemaChanges) { if (get(config).canSaveSchema) {
await API.saveTable(newTable) await API.saveTable(newTable)
} }
@ -143,11 +151,10 @@ export const deriveStores = context => {
} }
return { return {
hasNonAutoColumn,
columns: { columns: {
...columns, ...columns,
actions: { actions: {
...columns.actions, hasColumn,
saveChanges, saveChanges,
saveTable, saveTable,
changePrimaryDisplay, changePrimaryDisplay,

View File

@ -1,9 +1,9 @@
import { writable } from "svelte/store"
import { derivedMemo } from "../../../utils" import { derivedMemo } from "../../../utils"
import { derived } from "svelte/store"
export const createStores = context => { export const deriveStores = context => {
const config = writable(context.props) const { props, hasNonAutoColumn } = context
const getProp = prop => derivedMemo(config, $config => $config[prop]) const getProp = prop => derivedMemo(props, $props => $props[prop])
// Derive and memoize some props so that we can react to them in isolation // Derive and memoize some props so that we can react to them in isolation
const datasource = getProp("datasource") const datasource = getProp("datasource")
@ -16,6 +16,45 @@ export const createStores = context => {
const notifySuccess = getProp("notifySuccess") const notifySuccess = getProp("notifySuccess")
const notifyError = getProp("notifyError") const notifyError = getProp("notifyError")
// Derive features
const config = derived(
[props, hasNonAutoColumn],
([$props, $hasNonAutoColumn]) => {
let config = {
// Row features
canAddRows: $props.allowAddRows,
canExpandRows: $props.allowExpandRows,
canEditRows: $props.allowEditRows,
canDeleteRows: $props.allowDeleteRows,
// Column features
canEditColumns: $props.allowEditColumns,
canEditPrimaryDisplay: $props.allowEditColumns,
canSaveSchema: $props.allowSchemaChanges,
}
// Disable some features if we're editing a view
if ($props.datasource?.type === "viewV2") {
config.canEditPrimaryDisplay = false
config.canEditColumns = false
config.canEditRows = false
config.canDeleteRows = false
config.canAddRows = false
}
console.log($hasNonAutoColumn)
// Disable adding rows if we don't have any valid columns
if (!$hasNonAutoColumn) {
config.canAddRows = false
}
console.log(config)
return config
}
)
return { return {
config, config,
datasource, datasource,

View File

@ -1,10 +1,10 @@
import { writable } from "svelte/store" import { writable, get } from "svelte/store"
export const createStores = context => { export const createStores = context => {
const { props } = context const { props } = context
// Initialise to default props // Initialise to default props
const filter = writable(props.initialFilter) const filter = writable(get(props).initialFilter)
return { return {
filter, filter,

View File

@ -17,7 +17,6 @@ import * as Filter from "./filter"
import * as Notifications from "./notifications" import * as Notifications from "./notifications"
const DependencyOrderedStores = [ const DependencyOrderedStores = [
Config,
Notifications, Notifications,
Sort, Sort,
Filter, Filter,
@ -34,6 +33,7 @@ const DependencyOrderedStores = [
Menu, Menu,
Pagination, Pagination,
Clipboard, Clipboard,
Config,
] ]
export const attachStores = context => { export const attachStores = context => {
@ -47,6 +47,11 @@ export const attachStores = context => {
context = { ...context, ...store.deriveStores?.(context) } context = { ...context, ...store.deriveStores?.(context) }
} }
// Action creation
for (let store of DependencyOrderedStores) {
context = { ...context, ...store.createActions?.(context) }
}
// Initialise any store logic // Initialise any store logic
for (let store of DependencyOrderedStores) { for (let store of DependencyOrderedStores) {
store.initialise?.(context) store.initialise?.(context)

View File

@ -12,7 +12,7 @@ export const createStores = () => {
} }
} }
export const deriveStores = context => { export const createActions = context => {
const { menu, focusedCellId, rand } = context const { menu, focusedCellId, rand } = context
const open = (cellId, e) => { const open = (cellId, e) => {

View File

@ -23,7 +23,7 @@ export const createStores = () => {
} }
} }
export const deriveStores = context => { export const createActions = context => {
const { const {
reorder, reorder,
columns, columns,

View File

@ -19,7 +19,7 @@ export const createStores = () => {
} }
} }
export const deriveStores = context => { export const createActions = context => {
const { resize, columns, stickyColumn, ui } = context const { resize, columns, stickyColumn, ui } = context
// Starts resizing a certain column // Starts resizing a certain column

View File

@ -38,8 +38,24 @@ export const createStores = () => {
} }
}) })
// Enrich rows with an index property and any pending changes
const enrichedRows = derived(
[rows, rowChangeCache],
([$rows, $rowChangeCache]) => {
return $rows.map((row, idx) => ({
...row,
...$rowChangeCache[row._id],
__idx: idx,
}))
},
[]
)
return { return {
rows, rows: {
...rows,
subscribe: enrichedRows.subscribe,
},
rowLookupMap, rowLookupMap,
table, table,
loaded, loaded,
@ -51,7 +67,7 @@ export const createStores = () => {
} }
} }
export const deriveStores = context => { export const createActions = context => {
const { const {
rows, rows,
rowLookupMap, rowLookupMap,
@ -71,27 +87,14 @@ export const deriveStores = context => {
hasNextPage, hasNextPage,
error, error,
notifications, notifications,
config,
} = context } = context
const instanceLoaded = writable(false) const instanceLoaded = writable(false)
const fetch = writable(null) const fetch = writable(null)
const tableId = writable(null)
// Local cache of row IDs to speed up checking if a row exists // Local cache of row IDs to speed up checking if a row exists
let rowCacheMap = {} let rowCacheMap = {}
// Enrich rows with an index property and any pending changes
const enrichedRows = derived(
[rows, rowChangeCache],
([$rows, $rowChangeCache]) => {
return $rows.map((row, idx) => ({
...row,
...$rowChangeCache[row._id],
__idx: idx,
}))
},
[]
)
// Reset everything when table ID changes // Reset everything when table ID changes
let unsubscribe = null let unsubscribe = null
let lastResetKey = null let lastResetKey = null
@ -102,6 +105,8 @@ export const deriveStores = context => {
instanceLoaded.set(false) instanceLoaded.set(false)
loading.set(true) loading.set(true)
console.log($datasource)
// Abandon if we don't have a valid datasource // Abandon if we don't have a valid datasource
if (!$datasource?.tableId) { if (!$datasource?.tableId) {
return return
@ -501,7 +506,6 @@ export const deriveStores = context => {
}) })
return { return {
enrichedRows,
rows: { rows: {
...rows, ...rows,
actions: { actions: {

View File

@ -1,12 +1,13 @@
import { writable } from "svelte/store" import { writable, get } from "svelte/store"
export const createStores = context => { export const createStores = context => {
const { props } = context const { props } = context
const $props = get(props)
// Initialise to default props // Initialise to default props
const sort = writable({ const sort = writable({
column: props.initialSortColumn, column: $props.initialSortColumn,
order: props.initialSortOrder || "ascending", order: $props.initialSortOrder || "ascending",
}) })
return { return {

View File

@ -14,7 +14,7 @@ export const createStores = context => {
const focusedCellAPI = writable(null) const focusedCellAPI = writable(null)
const selectedRows = writable({}) const selectedRows = writable({})
const hoveredRowId = writable(null) const hoveredRowId = writable(null)
const rowHeight = writable(props.fixedRowHeight || DefaultRowHeight) const rowHeight = writable(get(props).fixedRowHeight || DefaultRowHeight)
const previousFocusedRowId = writable(null) const previousFocusedRowId = writable(null)
const gridFocused = writable(false) const gridFocused = writable(false)
const isDragging = writable(false) const isDragging = writable(false)
@ -61,23 +61,13 @@ export const createStores = context => {
} }
export const deriveStores = context => { export const deriveStores = context => {
const { const { focusedCellId, rows, rowLookupMap, rowHeight, stickyColumn, width } =
focusedCellId, context
selectedRows,
hoveredRowId,
enrichedRows,
rowLookupMap,
rowHeight,
stickyColumn,
width,
hasNonAutoColumn,
config,
} = context
// Derive the row that contains the selected cell // Derive the row that contains the selected cell
const focusedRow = derived( const focusedRow = derived(
[focusedCellId, rowLookupMap, enrichedRows], [focusedCellId, rowLookupMap, rows],
([$focusedCellId, $rowLookupMap, $enrichedRows]) => { ([$focusedCellId, $rowLookupMap, $rows]) => {
const rowId = $focusedCellId?.split("-")[0] const rowId = $focusedCellId?.split("-")[0]
// Edge case for new rows // Edge case for new rows
@ -87,18 +77,11 @@ export const deriveStores = context => {
// All normal rows // All normal rows
const index = $rowLookupMap[rowId] const index = $rowLookupMap[rowId]
return $enrichedRows[index] return $rows[index]
}, },
null null
) )
// Callback when leaving the grid, deselecting all focussed or selected items
const blur = () => {
focusedCellId.set(null)
selectedRows.set({})
hoveredRowId.set(null)
}
// Derive the amount of content lines to show in cells depending on row height // Derive the amount of content lines to show in cells depending on row height
const contentLines = derived(rowHeight, $rowHeight => { const contentLines = derived(rowHeight, $rowHeight => {
if ($rowHeight >= LargeRowHeight) { if ($rowHeight >= LargeRowHeight) {
@ -114,19 +97,24 @@ export const deriveStores = context => {
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100 return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
}) })
// Derive if we're able to add rows
const canAddRows = derived(
[config, hasNonAutoColumn],
([$config, $hasNonAutoColumn]) => {
return $config.allowAddRows && $hasNonAutoColumn
}
)
return { return {
canAddRows,
focusedRow, focusedRow,
contentLines, contentLines,
compact, compact,
}
}
export const createActions = context => {
const { focusedCellId, selectedRows, hoveredRowId } = context
// Callback when leaving the grid, deselecting all focussed or selected items
const blur = () => {
focusedCellId.set(null)
selectedRows.set({})
hoveredRowId.set(null)
}
return {
ui: { ui: {
actions: { actions: {
blur, blur,

View File

@ -39,6 +39,14 @@ export const deriveStores = context => {
} }
) )
return {
selectedCellMap,
}
}
export const createActions = context => {
const { users } = context
const updateUser = user => { const updateUser = user => {
const $users = get(users) const $users = get(users)
if (!$users.some(x => x.sessionId === user.sessionId)) { if (!$users.some(x => x.sessionId === user.sessionId)) {
@ -66,6 +74,5 @@ export const deriveStores = context => {
removeUser, removeUser,
}, },
}, },
selectedCellMap,
} }
} }

View File

@ -10,7 +10,7 @@ export const deriveStores = context => {
const { const {
rowHeight, rowHeight,
visibleColumns, visibleColumns,
enrichedRows, rows,
scrollTop, scrollTop,
scrollLeft, scrollLeft,
width, width,
@ -35,9 +35,9 @@ export const deriveStores = context => {
0 0
) )
const renderedRows = derived( const renderedRows = derived(
[enrichedRows, scrolledRowCount, visualRowCapacity], [rows, scrolledRowCount, visualRowCapacity],
([$enrichedRows, $scrolledRowCount, $visualRowCapacity]) => { ([$rows, $scrolledRowCount, $visualRowCapacity]) => {
return $enrichedRows.slice( return $rows.slice(
$scrolledRowCount, $scrolledRowCount,
$scrolledRowCount + $visualRowCapacity $scrolledRowCount + $visualRowCapacity
) )