Refactor how grid settings are used and add option for row height
This commit is contained in:
parent
3f3e9fca56
commit
d77b2c6ab1
|
@ -5230,9 +5230,7 @@
|
|||
"block": true,
|
||||
"name": "Grid block",
|
||||
"icon": "Table",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 600,
|
||||
"height": 400
|
||||
|
@ -5245,23 +5243,49 @@
|
|||
"key": "table",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "columns",
|
||||
"label": "Columns",
|
||||
"key": "columns",
|
||||
"dependsOn": "table"
|
||||
},
|
||||
{
|
||||
"type": "filter",
|
||||
"label": "Filtering",
|
||||
"key": "filter"
|
||||
"key": "initialFilter"
|
||||
},
|
||||
{
|
||||
"type": "field/sortable",
|
||||
"label": "Sort column",
|
||||
"key": "sortColumn"
|
||||
"key": "initialSortColumn"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Sort order",
|
||||
"key": "sortOrder",
|
||||
"key": "initialSortOrder",
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Ascending"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Row height",
|
||||
"key": "initialRowHeight",
|
||||
"placeholder": "Default",
|
||||
"options": [
|
||||
{
|
||||
"label": "Small",
|
||||
"value": 36
|
||||
},
|
||||
{
|
||||
"label": "Medium",
|
||||
"value": 64
|
||||
},
|
||||
{
|
||||
"label": "Large",
|
||||
"value": 92
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Add rows",
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
export let allowEditRows = true
|
||||
export let allowDeleteRows = true
|
||||
export let stripeRows = false
|
||||
export let filter = null
|
||||
export let sortColumn = null
|
||||
export let sortOrder = null
|
||||
export let initialFilter = null
|
||||
export let initialSortColumn = null
|
||||
export let initialSortOrder = null
|
||||
export let initialRowHeight = null
|
||||
|
||||
const component = getContext("component")
|
||||
const { styleable, API, builderStore } = getContext("sdk")
|
||||
|
@ -28,9 +29,10 @@
|
|||
{allowEditRows}
|
||||
{allowDeleteRows}
|
||||
{stripeRows}
|
||||
{filter}
|
||||
{sortColumn}
|
||||
{sortOrder}
|
||||
{initialFilter}
|
||||
{initialSortColumn}
|
||||
{initialSortOrder}
|
||||
{initialRowHeight}
|
||||
showControls={false}
|
||||
allowExpandRows={false}
|
||||
allowSchemaChanges={false}
|
||||
|
|
|
@ -33,22 +33,6 @@
|
|||
selected: allLarge,
|
||||
},
|
||||
]
|
||||
|
||||
const changeColumnWidth = async width => {
|
||||
columns.update(state => {
|
||||
state.forEach(column => {
|
||||
column.width = width
|
||||
})
|
||||
return state
|
||||
})
|
||||
if ($stickyColumn) {
|
||||
stickyColumn.update(state => ({
|
||||
...state,
|
||||
width,
|
||||
}))
|
||||
}
|
||||
await columns.actions.saveChanges()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div bind:this={anchor}>
|
||||
|
@ -70,7 +54,7 @@
|
|||
{#each sizeOptions as option}
|
||||
<ActionButton
|
||||
quiet
|
||||
on:click={() => changeColumnWidth(option.size)}
|
||||
on:click={() => columns.actions.changeAllColumnWidths(option.size)}
|
||||
selected={option.selected}
|
||||
>
|
||||
{option.label}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
GutterWidth,
|
||||
DefaultRowHeight,
|
||||
} from "../lib/constants"
|
||||
import { memo } from "../../../utils"
|
||||
|
||||
export let API = null
|
||||
export let tableId = null
|
||||
|
@ -43,48 +42,26 @@
|
|||
export let collaboration = true
|
||||
export let showAvatars = true
|
||||
export let showControls = true
|
||||
export let filter = null
|
||||
export let sortColumn = null
|
||||
export let sortOrder = null
|
||||
export let initialFilter = null
|
||||
export let initialSortColumn = null
|
||||
export let initialSortOrder = null
|
||||
export let initialRowHeight = null
|
||||
|
||||
// Unique identifier for DOM nodes inside this instance
|
||||
const rand = Math.random()
|
||||
|
||||
// Stores derived from props.
|
||||
// We use memo here to ensure redundant store reactions don't fire and cause
|
||||
// wasted API calls.
|
||||
const tableIdStore = memo(tableId)
|
||||
const schemaOverridesStore = memo(schemaOverrides)
|
||||
const filterStore = memo(filter)
|
||||
const sortStore = memo({
|
||||
column: sortColumn,
|
||||
order: sortOrder,
|
||||
})
|
||||
const config = memo({
|
||||
allowAddRows,
|
||||
allowExpandRows,
|
||||
allowEditRows,
|
||||
allowDeleteRows,
|
||||
allowSchemaChanges,
|
||||
stripeRows,
|
||||
showControls,
|
||||
})
|
||||
|
||||
// Build up context
|
||||
let context = {
|
||||
API: API || createAPIClient(),
|
||||
rand,
|
||||
config,
|
||||
tableId: tableIdStore,
|
||||
schemaOverrides: schemaOverridesStore,
|
||||
filter: filterStore,
|
||||
sort: sortStore,
|
||||
props: $$props,
|
||||
}
|
||||
context = { ...context, ...createEventManagers() }
|
||||
context = attachStores(context)
|
||||
|
||||
// Reference some stores for local use
|
||||
const {
|
||||
config,
|
||||
isResizing,
|
||||
isReordering,
|
||||
ui,
|
||||
|
@ -95,22 +72,23 @@
|
|||
gridFocused,
|
||||
} = context
|
||||
|
||||
// Keep prop-derived stores up to date
|
||||
$: tableIdStore.set(tableId)
|
||||
$: schemaOverridesStore.set(schemaOverrides)
|
||||
$: filterStore.set(filter)
|
||||
$: sortStore.set({
|
||||
column: sortColumn,
|
||||
order: sortOrder,
|
||||
})
|
||||
// Keep config store up to date with props
|
||||
$: config.set({
|
||||
tableId,
|
||||
schemaOverrides,
|
||||
allowAddRows,
|
||||
allowSchemaChanges,
|
||||
allowExpandRows,
|
||||
allowEditRows,
|
||||
allowDeleteRows,
|
||||
allowSchemaChanges,
|
||||
stripeRows,
|
||||
collaboration,
|
||||
showAvatars,
|
||||
showControls,
|
||||
initialFilter,
|
||||
initialSortColumn,
|
||||
initialSortOrder,
|
||||
initialRowHeight,
|
||||
})
|
||||
|
||||
// Set context for children to consume
|
||||
|
|
|
@ -56,6 +56,23 @@ export const deriveStores = context => {
|
|||
})
|
||||
}
|
||||
|
||||
// Updates the width of all columns
|
||||
const changeAllColumnWidths = async width => {
|
||||
columns.update(state => {
|
||||
return state.map(col => ({
|
||||
...col,
|
||||
width,
|
||||
}))
|
||||
})
|
||||
if (get(stickyColumn)) {
|
||||
stickyColumn.update(state => ({
|
||||
...state,
|
||||
width,
|
||||
}))
|
||||
}
|
||||
await saveChanges()
|
||||
}
|
||||
|
||||
// Persists column changes by saving metadata against table schema
|
||||
const saveChanges = async () => {
|
||||
const $columns = get(columns)
|
||||
|
@ -107,6 +124,7 @@ export const deriveStores = context => {
|
|||
saveChanges,
|
||||
saveTable,
|
||||
changePrimaryDisplay,
|
||||
changeAllColumnWidths,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { derivedMemo } from "../../../utils"
|
||||
|
||||
export const createStores = context => {
|
||||
const config = writable(context.props)
|
||||
const getProp = prop => derivedMemo(config, $config => $config[prop])
|
||||
|
||||
// Derive and memoize some props so that we can react to them in isolation
|
||||
const tableId = getProp("tableId")
|
||||
const initialSortColumn = getProp("initialSortColumn")
|
||||
const initialSortOrder = getProp("initialSortOrder")
|
||||
const initialFilter = getProp("initialFilter")
|
||||
const initialRowHeight = getProp("initialRowHeight")
|
||||
|
||||
return {
|
||||
config,
|
||||
tableId,
|
||||
initialSortColumn,
|
||||
initialSortOrder,
|
||||
initialFilter,
|
||||
initialRowHeight,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { derivedMemo } from "../../../utils"
|
||||
|
||||
export const createStores = context => {
|
||||
const { props } = context
|
||||
|
||||
// Initialise to default props
|
||||
const filter = writable(props.initialFilter)
|
||||
|
||||
return {
|
||||
filter,
|
||||
}
|
||||
}
|
||||
|
||||
export const initialise = context => {
|
||||
const { filter, initialFilter } = context
|
||||
|
||||
// Reset filter when initial filter prop changes
|
||||
initialFilter.subscribe(filter.set)
|
||||
}
|
|
@ -11,8 +11,14 @@ import * as Users from "./users"
|
|||
import * as Validation from "./validation"
|
||||
import * as Viewport from "./viewport"
|
||||
import * as Clipboard from "./clipboard"
|
||||
import * as Config from "./config"
|
||||
import * as Sort from "./sort"
|
||||
import * as Filter from "./filter"
|
||||
|
||||
const DependencyOrderedStores = [
|
||||
Config,
|
||||
Sort,
|
||||
Filter,
|
||||
Bounds,
|
||||
Scroll,
|
||||
Rows,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { writable } from "svelte/store"
|
||||
|
||||
export const createStores = context => {
|
||||
const { props } = context
|
||||
|
||||
// Initialise to default props
|
||||
const sort = writable({
|
||||
column: props.initialSortColumn,
|
||||
order: props.initialSortOrder || "ascending",
|
||||
})
|
||||
|
||||
return {
|
||||
sort,
|
||||
}
|
||||
}
|
||||
|
||||
export const initialise = context => {
|
||||
const { sort, initialSortColumn, initialSortOrder } = context
|
||||
|
||||
// Reset sort when initial sort props change
|
||||
initialSortColumn.subscribe(newSortColumn => {
|
||||
sort.update(state => ({ ...state, column: newSortColumn }))
|
||||
})
|
||||
initialSortOrder.subscribe(newSortOrder => {
|
||||
sort.update(state => ({ ...state, order: newSortOrder }))
|
||||
})
|
||||
}
|
|
@ -8,12 +8,13 @@ import {
|
|||
NewRowID,
|
||||
} from "../lib/constants"
|
||||
|
||||
export const createStores = () => {
|
||||
export const createStores = context => {
|
||||
const { props } = context
|
||||
const focusedCellId = writable(null)
|
||||
const focusedCellAPI = writable(null)
|
||||
const selectedRows = writable({})
|
||||
const hoveredRowId = writable(null)
|
||||
const rowHeight = writable(DefaultRowHeight)
|
||||
const rowHeight = writable(props.initialRowHeight || DefaultRowHeight)
|
||||
const previousFocusedRowId = writable(null)
|
||||
const gridFocused = writable(false)
|
||||
const isDragging = writable(false)
|
||||
|
@ -98,9 +99,9 @@ export const deriveStores = context => {
|
|||
|
||||
// Derive the amount of content lines to show in cells depending on row height
|
||||
const contentLines = derived(rowHeight, $rowHeight => {
|
||||
if ($rowHeight === LargeRowHeight) {
|
||||
if ($rowHeight >= LargeRowHeight) {
|
||||
return 3
|
||||
} else if ($rowHeight === MediumRowHeight) {
|
||||
} else if ($rowHeight >= MediumRowHeight) {
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
|
@ -133,6 +134,7 @@ export const initialise = context => {
|
|||
hoveredRowId,
|
||||
table,
|
||||
rowHeight,
|
||||
initialRowHeight,
|
||||
} = context
|
||||
|
||||
// Ensure we clear invalid rows from state if they disappear
|
||||
|
@ -189,4 +191,7 @@ export const initialise = context => {
|
|||
table.subscribe($table => {
|
||||
rowHeight.set($table?.rowHeight || DefaultRowHeight)
|
||||
})
|
||||
|
||||
// Reset row height when initial row height prop changes
|
||||
initialRowHeight.subscribe(rowHeight.set)
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ export * as JSONUtils from "./json"
|
|||
export * as CookieUtils from "./cookies"
|
||||
export * as RoleUtils from "./roles"
|
||||
export * as Utils from "./utils"
|
||||
export { memo } from "./memo"
|
||||
export { memo, derivedMemo } from "./memo"
|
||||
export { createWebsocket } from "./websocket"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import { writable, get, derived } from "svelte/store"
|
||||
|
||||
// A simple svelte store which deeply compares all changes and ensures that
|
||||
// subscribed children will only fire when a new value is actually set
|
||||
|
@ -33,3 +33,11 @@ export const memo = initialValue => {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Enriched version of svelte's derived store which returns a memo
|
||||
export const derivedMemo = (store, derivation) => {
|
||||
const derivedStore = derived(store, derivation)
|
||||
const memoStore = memo(get(derivedStore))
|
||||
derivedStore.subscribe(memoStore.set)
|
||||
return memoStore
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue