Add row conditions
This commit is contained in:
parent
cf12c8246b
commit
06e7517529
|
@ -5,6 +5,7 @@
|
|||
|
||||
export let bindings = []
|
||||
export let value = ""
|
||||
export let allowHBS = true
|
||||
export let allowJS = false
|
||||
export let allowHelpers = true
|
||||
export let autofocusEditor = false
|
||||
|
@ -31,6 +32,7 @@
|
|||
context={{ ...$previewStore.selectedComponentContext, ...context }}
|
||||
snippets={$snippets}
|
||||
{value}
|
||||
{allowHBS}
|
||||
{allowJS}
|
||||
{allowHelpers}
|
||||
{autofocusEditor}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
export let placeholder
|
||||
export let label
|
||||
export let disabled = false
|
||||
export let allowHBS = true
|
||||
export let allowJS = true
|
||||
export let allowHelpers = true
|
||||
export let updateOnChange = true
|
||||
|
@ -98,6 +99,7 @@
|
|||
value={readableValue}
|
||||
on:change={event => (tempValue = event.detail)}
|
||||
{bindings}
|
||||
{allowHBS}
|
||||
{allowJS}
|
||||
{allowHelpers}
|
||||
{context}
|
||||
|
|
|
@ -31,6 +31,7 @@ import FormStepConfiguration from "./controls/FormStepConfiguration.svelte"
|
|||
import FormStepControls from "./controls/FormStepControls.svelte"
|
||||
import PaywalledSetting from "./controls/PaywalledSetting.svelte"
|
||||
import CellConditionEditor from "./controls/CellConditionEditor.svelte"
|
||||
import RowConditionEditor from "./controls/RowConditionEditor.svelte"
|
||||
|
||||
const componentMap = {
|
||||
text: DrawerBindableInput,
|
||||
|
@ -63,6 +64,7 @@ const componentMap = {
|
|||
"columns/basic": BasicColumnEditor,
|
||||
"columns/grid": GridColumnEditor,
|
||||
cellConditions: CellConditionEditor,
|
||||
rowConditions: RowConditionEditor,
|
||||
"field/sortable": SortableFieldSelect,
|
||||
"field/string": FormFieldSelect,
|
||||
"field/number": FormFieldSelect,
|
||||
|
|
|
@ -113,11 +113,17 @@
|
|||
<ActionButton on:click={openDrawer}>{conditionText}</ActionButton>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<Drawer bind:this={drawer} title="Conditions" on:drawerShow on:drawerHide>
|
||||
<Drawer
|
||||
bind:this={drawer}
|
||||
title="{componentInstance.field} conditions"
|
||||
on:drawerShow
|
||||
on:drawerHide
|
||||
>
|
||||
<Button cta slot="buttons" on:click={save}>Save</Button>
|
||||
<DrawerContent slot="body">
|
||||
<div class="container">
|
||||
<Layout noPadding>
|
||||
Update the appearance of cells based on their value.
|
||||
{#if tempValue.length}
|
||||
<div
|
||||
class="conditions"
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<script>
|
||||
import {
|
||||
ActionButton,
|
||||
Drawer,
|
||||
Button,
|
||||
DrawerContent,
|
||||
Layout,
|
||||
Select,
|
||||
Icon,
|
||||
} from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { cloneDeep } from "lodash"
|
||||
import ColorPicker from "./ColorPicker.svelte"
|
||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
import { Constants } from "@budibase/frontend-core"
|
||||
import { generate } from "shortid"
|
||||
import { dndzone } from "svelte-dnd-action"
|
||||
import { flip } from "svelte/animate"
|
||||
import { getDatasourceForProvider, getSchemaForDatasource } from "dataBinding"
|
||||
import { selectedScreen, selectedComponent } from "stores/builder"
|
||||
import { makePropSafe } from "@budibase/string-templates"
|
||||
|
||||
export let value
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const flipDuration = 130
|
||||
const conditionOptions = [
|
||||
{
|
||||
label: "Update background color",
|
||||
value: "backgroundColor",
|
||||
},
|
||||
{
|
||||
label: "Update text color",
|
||||
value: "textColor",
|
||||
},
|
||||
]
|
||||
|
||||
let tempValue = []
|
||||
let drawer
|
||||
let dragDisabled = true
|
||||
|
||||
$: count = value?.length
|
||||
$: conditionText = `${count || "No"} condition${count !== 1 ? "s" : ""} set`
|
||||
$: datasource = getDatasourceForProvider($selectedScreen, $selectedComponent)
|
||||
$: schema = getSchemaForDatasource($selectedScreen, datasource)?.schema
|
||||
$: rowBindings = generateRowBindings(schema)
|
||||
|
||||
const generateRowBindings = schema => {
|
||||
let bindings = []
|
||||
for (let key of Object.keys(schema || {})) {
|
||||
bindings.push({
|
||||
type: "context",
|
||||
runtimeBinding: `${makePropSafe("row")}.${makePropSafe(key)}`,
|
||||
readableBinding: `Row.${key}`,
|
||||
category: "Row",
|
||||
icon: "RailTop",
|
||||
display: { name: key },
|
||||
})
|
||||
}
|
||||
|
||||
return bindings
|
||||
}
|
||||
|
||||
const openDrawer = () => {
|
||||
tempValue = cloneDeep(value || [])
|
||||
drawer.show()
|
||||
}
|
||||
|
||||
const save = async () => {
|
||||
dispatch("change", tempValue)
|
||||
drawer.hide()
|
||||
}
|
||||
|
||||
const addCondition = () => {
|
||||
const condition = {
|
||||
id: generate(),
|
||||
metadataKey: conditionOptions[0].value,
|
||||
operator: Constants.OperatorOptions.Equals.value,
|
||||
referenceValue: true,
|
||||
}
|
||||
tempValue = [...tempValue, condition]
|
||||
}
|
||||
|
||||
const duplicateCondition = condition => {
|
||||
const dupe = { ...condition, id: generate() }
|
||||
tempValue = [...tempValue, dupe]
|
||||
}
|
||||
|
||||
const removeCondition = condition => {
|
||||
tempValue = tempValue.filter(c => c.id !== condition.id)
|
||||
}
|
||||
|
||||
const updateConditions = e => {
|
||||
tempValue = e.detail.items
|
||||
}
|
||||
|
||||
const handleFinalize = e => {
|
||||
updateConditions(e)
|
||||
dragDisabled = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<ActionButton on:click={openDrawer}>{conditionText}</ActionButton>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<Drawer bind:this={drawer} title="Row conditions" on:drawerShow on:drawerHide>
|
||||
<Button cta slot="buttons" on:click={save}>Save</Button>
|
||||
<DrawerContent slot="body">
|
||||
<div class="container">
|
||||
<Layout noPadding>
|
||||
Update the appearance of rows based on the entire row value.
|
||||
{#if tempValue.length}
|
||||
<div
|
||||
class="conditions"
|
||||
use:dndzone={{
|
||||
items: tempValue,
|
||||
flipDurationMs: flipDuration,
|
||||
dropTargetStyle: { outline: "none" },
|
||||
dragDisabled,
|
||||
}}
|
||||
on:consider={updateConditions}
|
||||
on:finalize={handleFinalize}
|
||||
>
|
||||
{#each tempValue as condition (condition.id)}
|
||||
<div
|
||||
class="condition"
|
||||
class:update={condition.action === "update"}
|
||||
animate:flip={{ duration: flipDuration }}
|
||||
>
|
||||
<div
|
||||
class="handle"
|
||||
aria-label="drag-handle"
|
||||
style={dragDisabled ? "cursor: grab" : "cursor: grabbing"}
|
||||
on:mousedown={() => (dragDisabled = false)}
|
||||
>
|
||||
<Icon name="DragHandle" size="XL" />
|
||||
</div>
|
||||
<Select
|
||||
placeholder={null}
|
||||
options={conditionOptions}
|
||||
bind:value={condition.metadataKey}
|
||||
/>
|
||||
<span>to</span>
|
||||
<ColorPicker
|
||||
value={condition.metadataValue}
|
||||
on:change={e => (condition.metadataValue = e.detail)}
|
||||
/>
|
||||
<span>if</span>
|
||||
<DrawerBindableInput
|
||||
bindings={rowBindings}
|
||||
allowHBS={false}
|
||||
placeholder="Expression"
|
||||
value={condition.value}
|
||||
on:change={e => (condition.value = e.detail)}
|
||||
/>
|
||||
<span>returns true</span>
|
||||
<Icon
|
||||
name="Duplicate"
|
||||
hoverable
|
||||
size="S"
|
||||
on:click={() => duplicateCondition(condition)}
|
||||
/>
|
||||
<Icon
|
||||
name="Close"
|
||||
hoverable
|
||||
size="S"
|
||||
on:click={() => removeCondition(condition)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<div>
|
||||
<Button secondary icon="Add" on:click={addCondition}>
|
||||
Add condition
|
||||
</Button>
|
||||
</div>
|
||||
</Layout>
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.conditions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
.condition {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto auto auto 1fr auto auto auto;
|
||||
align-items: center;
|
||||
grid-column-gap: var(--spacing-l);
|
||||
}
|
||||
</style>
|
|
@ -8,8 +8,11 @@
|
|||
} from "@budibase/bbui"
|
||||
import { componentStore } from "stores/builder"
|
||||
import ConditionalUIDrawer from "./ConditionalUIDrawer.svelte"
|
||||
import ComponentSettingsSection from "./ComponentSettingsSection.svelte"
|
||||
|
||||
export let componentInstance
|
||||
export let componentDefinition
|
||||
export let componentBindings
|
||||
export let bindings
|
||||
|
||||
let tempValue
|
||||
|
@ -35,6 +38,19 @@
|
|||
} set`
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Load any general settings or sections tagged as "condition"
|
||||
-->
|
||||
<ComponentSettingsSection
|
||||
{componentInstance}
|
||||
{componentDefinition}
|
||||
isScreen={false}
|
||||
showInstanceName={false}
|
||||
{bindings}
|
||||
{componentBindings}
|
||||
tag="condition"
|
||||
/>
|
||||
|
||||
<DetailSummary name={"Conditions"} collapsible={false}>
|
||||
<ActionButton on:click={openDrawer}>{conditionText}</ActionButton>
|
||||
</DetailSummary>
|
||||
|
|
|
@ -7329,6 +7329,18 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"tag": "condition",
|
||||
"name": "Row conditions",
|
||||
"settings": [
|
||||
{
|
||||
"type": "rowConditions",
|
||||
"key": "rowConditions",
|
||||
"nested": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"context": [
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
export let columns = null
|
||||
export let onRowClick = null
|
||||
export let buttons = null
|
||||
export let rowConditions = null
|
||||
|
||||
const context = getContext("context")
|
||||
const component = getContext("component")
|
||||
|
@ -62,7 +63,13 @@
|
|||
const goldenRow = generateGoldenSample(rows)
|
||||
const id = get(component).id
|
||||
return {
|
||||
// Not sure what this one is for...
|
||||
[id]: goldenRow,
|
||||
|
||||
// For row conditions context
|
||||
row: goldenRow,
|
||||
|
||||
// For button action context
|
||||
eventContext: {
|
||||
row: goldenRow,
|
||||
},
|
||||
|
@ -166,6 +173,7 @@
|
|||
{fixedRowHeight}
|
||||
{columnWhitelist}
|
||||
{schemaOverrides}
|
||||
{rowConditions}
|
||||
canAddRows={allowAddRows}
|
||||
canEditRows={allowEditRows}
|
||||
canDeleteRows={allowDeleteRows}
|
||||
|
|
|
@ -130,7 +130,10 @@
|
|||
on:mouseup={stopSelectionCallback}
|
||||
on:click={handleClick}
|
||||
width={column.width}
|
||||
metadata={row.__metadata?.[column.name]}
|
||||
metadata={{
|
||||
...row.__metadata,
|
||||
...row.__cellMetadata?.[column.name],
|
||||
}}
|
||||
>
|
||||
<svelte:component
|
||||
this={getCellRenderer(column)}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
selected={rowSelected}
|
||||
{defaultHeight}
|
||||
rowIdx={row?.__idx}
|
||||
metadata={row?.__metadata}
|
||||
>
|
||||
<div class="gutter">
|
||||
{#if $$slots.default}
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
rowIdx={row.__idx}
|
||||
selected={rowSelected}
|
||||
highlighted={rowHovered || rowFocused}
|
||||
metadata={row.__metadata}
|
||||
>
|
||||
<div class="buttons" class:offset={$showVScrollbar}>
|
||||
{#each buttons as button}
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
export let darkMode
|
||||
export let isCloud = null
|
||||
export let allowViewReadonlyColumns = false
|
||||
export let rowConditions = null
|
||||
|
||||
// Unique identifier for DOM nodes inside this instance
|
||||
const gridID = `grid-${Math.random().toString().slice(2)}`
|
||||
|
@ -114,6 +115,8 @@
|
|||
buttons,
|
||||
darkMode,
|
||||
isCloud,
|
||||
allowViewReadonlyColumns,
|
||||
rowConditions,
|
||||
})
|
||||
|
||||
// Derive min height and make available in context
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import { derivedMemo, QueryUtils } from "../../../utils"
|
||||
import { OperatorOptions } from "@budibase/shared-core"
|
||||
import { FieldType } from "@budibase/types"
|
||||
import { processString, processStringSync } from "@budibase/string-templates"
|
||||
|
||||
export const createStores = () => {
|
||||
const conditionMetadata = writable({})
|
||||
const cellMetadata = writable({})
|
||||
const rowMetadata = writable({})
|
||||
return {
|
||||
conditionMetadata,
|
||||
cellMetadata,
|
||||
rowMetadata,
|
||||
}
|
||||
}
|
||||
|
||||
export const deriveStores = context => {
|
||||
const { columns } = context
|
||||
|
||||
// Derive and memoize the conditions present in our columns so that we only
|
||||
// recompute condition metdata when absolutely necessary
|
||||
const conditions = derivedMemo(columns, $columns => {
|
||||
// Derive and memoize the cell conditions present in our columns so that we
|
||||
// only recompute condition metadata when absolutely necessary
|
||||
const cellConditions = derivedMemo(columns, $columns => {
|
||||
let newConditions = []
|
||||
for (let column of $columns) {
|
||||
for (let condition of column.conditions || []) {
|
||||
|
@ -28,96 +33,147 @@ export const deriveStores = context => {
|
|||
})
|
||||
|
||||
return {
|
||||
conditions,
|
||||
cellConditions,
|
||||
}
|
||||
}
|
||||
|
||||
export const initialise = context => {
|
||||
const { conditionMetadata, conditions, rows } = context
|
||||
const { cellMetadata, cellConditions, rowConditions, rowMetadata, rows } =
|
||||
context
|
||||
|
||||
// Evaluates an array of conditions against a certain row and returns the
|
||||
// resultant metadata
|
||||
const evaluateConditions = (row, conditions) => {
|
||||
let metadata = { version: row._rev }
|
||||
for (let condition of conditions) {
|
||||
try {
|
||||
let {
|
||||
column,
|
||||
type,
|
||||
referenceValue,
|
||||
operator,
|
||||
metadataKey,
|
||||
metadataValue,
|
||||
} = condition
|
||||
let value = row[column]
|
||||
|
||||
// Coerce values into correct types for primitives
|
||||
if (type === "number") {
|
||||
referenceValue = parseFloat(referenceValue)
|
||||
value = parseFloat(value)
|
||||
} else if (type === "datetime") {
|
||||
if (referenceValue) {
|
||||
referenceValue = new Date(referenceValue).toISOString()
|
||||
}
|
||||
if (value) {
|
||||
value = new Date(value).toISOString()
|
||||
}
|
||||
} else if (type === "boolean") {
|
||||
referenceValue = `${referenceValue}`.toLowerCase() === "true"
|
||||
value = `${value}`.toLowerCase() === "true"
|
||||
}
|
||||
|
||||
// Build lucene compatible condition expression
|
||||
const luceneFilter = {
|
||||
operator,
|
||||
type,
|
||||
field: "value",
|
||||
value: referenceValue,
|
||||
}
|
||||
const query = QueryUtils.buildQuery([luceneFilter])
|
||||
const result = QueryUtils.runQuery([{ value }], query)
|
||||
if (result.length > 0) {
|
||||
if (!metadata[column]) {
|
||||
metadata[column] = {}
|
||||
}
|
||||
metadata[column][metadataKey] = metadataValue
|
||||
}
|
||||
} catch {
|
||||
// Swallow
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
// Recompute all metadata if conditions change
|
||||
conditions.subscribe($conditions => {
|
||||
// Recompute all cell metadata if cell conditions change
|
||||
cellConditions.subscribe($conditions => {
|
||||
let metadata = {}
|
||||
if ($conditions.length) {
|
||||
if ($conditions?.length) {
|
||||
for (let row of get(rows)) {
|
||||
metadata[row._id] = evaluateConditions(row, $conditions)
|
||||
metadata[row._id] = evaluateCellConditions(row, $conditions)
|
||||
}
|
||||
}
|
||||
conditionMetadata.set(metadata)
|
||||
cellMetadata.set(metadata)
|
||||
})
|
||||
|
||||
// Recompute specific rows when they change
|
||||
rows.subscribe($rows => {
|
||||
const $conditions = get(conditions)
|
||||
if (!$conditions.length) {
|
||||
return
|
||||
}
|
||||
const metadata = get(conditionMetadata)
|
||||
let updates = {}
|
||||
for (let row of $rows) {
|
||||
if (!row._rev || metadata[row._id]?.version !== row._rev) {
|
||||
updates[row._id] = evaluateConditions(row, $conditions)
|
||||
// Recompute all row metadata if row conditions change
|
||||
rowConditions.subscribe($conditions => {
|
||||
let metadata = {}
|
||||
if ($conditions?.length) {
|
||||
for (let row of get(rows)) {
|
||||
metadata[row._id] = evaluateRowConditions(row, $conditions)
|
||||
}
|
||||
}
|
||||
if (Object.keys(updates).length) {
|
||||
conditionMetadata.update(state => ({
|
||||
rowMetadata.set(metadata)
|
||||
})
|
||||
|
||||
// Recompute metadata for specific rows when they change
|
||||
rows.subscribe($rows => {
|
||||
const $cellConditions = get(cellConditions)
|
||||
const $rowConditions = get(rowConditions)
|
||||
const processCells = $cellConditions?.length > 0
|
||||
const processRows = $rowConditions?.length > 0
|
||||
if (!processCells && !processRows) {
|
||||
return
|
||||
}
|
||||
const $cellMetadata = get(cellMetadata)
|
||||
const $rowMetadata = get(rowMetadata)
|
||||
let cellUpdates = {}
|
||||
let rowUpdates = {}
|
||||
for (let row of $rows) {
|
||||
// Process cell metadata
|
||||
if (processCells) {
|
||||
if (!row._rev || $cellMetadata[row._id]?.version !== row._rev) {
|
||||
cellUpdates[row._id] = evaluateCellConditions(row, $cellConditions)
|
||||
}
|
||||
}
|
||||
// Process row metadata
|
||||
if (processRows) {
|
||||
if (!row._rev || $rowMetadata[row._id]?.version !== row._rev) {
|
||||
rowUpdates[row._id] = evaluateRowConditions(row, $rowConditions)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(cellUpdates).length) {
|
||||
cellMetadata.update(state => ({
|
||||
...state,
|
||||
...updates,
|
||||
...cellUpdates,
|
||||
}))
|
||||
}
|
||||
if (Object.keys(rowUpdates).length) {
|
||||
rowMetadata.update(state => ({
|
||||
...state,
|
||||
...rowUpdates,
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Evaluates an array of cell conditions against a certain row and returns the
|
||||
// resultant metadata
|
||||
const evaluateCellConditions = (row, conditions) => {
|
||||
let metadata = { version: row._rev }
|
||||
for (let condition of conditions) {
|
||||
try {
|
||||
let {
|
||||
column,
|
||||
type,
|
||||
referenceValue,
|
||||
operator,
|
||||
metadataKey,
|
||||
metadataValue,
|
||||
} = condition
|
||||
let value = row[column]
|
||||
|
||||
// Coerce values into correct types for primitives
|
||||
if (type === "number") {
|
||||
referenceValue = parseFloat(referenceValue)
|
||||
value = parseFloat(value)
|
||||
} else if (type === "datetime") {
|
||||
if (referenceValue) {
|
||||
referenceValue = new Date(referenceValue).toISOString()
|
||||
}
|
||||
if (value) {
|
||||
value = new Date(value).toISOString()
|
||||
}
|
||||
} else if (type === "boolean") {
|
||||
referenceValue = `${referenceValue}`.toLowerCase() === "true"
|
||||
value = `${value}`.toLowerCase() === "true"
|
||||
}
|
||||
|
||||
// Build lucene compatible condition expression
|
||||
const luceneFilter = {
|
||||
operator,
|
||||
type,
|
||||
field: "value",
|
||||
value: referenceValue,
|
||||
}
|
||||
const query = QueryUtils.buildQuery([luceneFilter])
|
||||
const result = QueryUtils.runQuery([{ value }], query)
|
||||
if (result.length > 0) {
|
||||
if (!metadata[column]) {
|
||||
metadata[column] = {}
|
||||
}
|
||||
metadata[column][metadataKey] = metadataValue
|
||||
}
|
||||
} catch {
|
||||
// Swallow
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
// Evaluates an array of row conditions against a certain row and returns the
|
||||
// resultant metadata
|
||||
const evaluateRowConditions = (row, conditions) => {
|
||||
let metadata = { version: row._rev }
|
||||
for (let condition of conditions) {
|
||||
try {
|
||||
const { metadataKey, metadataValue, value } = condition
|
||||
console.log("JS")
|
||||
const result = processStringSync(value, { row })
|
||||
if (result === true) {
|
||||
metadata[metadataKey] = metadataValue
|
||||
}
|
||||
} catch {
|
||||
// Swallow
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ export const createStores = context => {
|
|||
const columnWhitelist = getProp("columnWhitelist")
|
||||
const notifySuccess = getProp("notifySuccess")
|
||||
const notifyError = getProp("notifyError")
|
||||
const rowConditions = getProp("rowConditions")
|
||||
|
||||
return {
|
||||
datasource,
|
||||
|
@ -26,6 +27,7 @@ export const createStores = context => {
|
|||
columnWhitelist,
|
||||
notifySuccess,
|
||||
notifyError,
|
||||
rowConditions,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ export const deriveStores = context => {
|
|||
width,
|
||||
height,
|
||||
rowChangeCache,
|
||||
conditionMetadata,
|
||||
cellMetadata,
|
||||
rowMetadata,
|
||||
} = context
|
||||
|
||||
// Derive visible rows
|
||||
|
@ -35,21 +36,24 @@ export const deriveStores = context => {
|
|||
scrolledRowCount,
|
||||
visualRowCapacity,
|
||||
rowChangeCache,
|
||||
conditionMetadata,
|
||||
cellMetadata,
|
||||
rowMetadata,
|
||||
],
|
||||
([
|
||||
$rows,
|
||||
$scrolledRowCount,
|
||||
$visualRowCapacity,
|
||||
$rowChangeCache,
|
||||
$conditionMetadata,
|
||||
$cellMetadata,
|
||||
$rowMetadata,
|
||||
]) => {
|
||||
return $rows
|
||||
.slice($scrolledRowCount, $scrolledRowCount + $visualRowCapacity)
|
||||
.map(row => ({
|
||||
...row,
|
||||
...$rowChangeCache[row._id],
|
||||
__metadata: $conditionMetadata[row._id],
|
||||
__metadata: $rowMetadata[row._id],
|
||||
__cellMetadata: $cellMetadata[row._id],
|
||||
}))
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue