Simplify and add new contextAccess manifest key to solve incompatibility with table format and condition settings

This commit is contained in:
Andrew Kingston 2025-02-11 16:14:24 +00:00
parent 83e23ef578
commit 917548bf84
No known key found for this signature in database
10 changed files with 82 additions and 27 deletions

View File

@ -43,7 +43,6 @@
<EditComponentPopover <EditComponentPopover
{anchor} {anchor}
componentInstance={item} componentInstance={item}
{componentBindings}
{bindings} {bindings}
on:change on:change
parseSettings={updatedNestedFlags} parseSettings={updatedNestedFlags}

View File

@ -1,13 +1,13 @@
<script> <script>
import { Icon, Popover, Layout } from "@budibase/bbui" import { Icon, Popover, Layout } from "@budibase/bbui"
import { componentStore } from "@/stores/builder" import { componentStore, selectedScreen } from "@/stores/builder"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { createEventDispatcher, getContext } from "svelte" import { createEventDispatcher, getContext } from "svelte"
import ComponentSettingsSection from "@/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte" import ComponentSettingsSection from "@/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte"
import { getComponentBindableProperties } from "@/dataBinding"
export let anchor export let anchor
export let componentInstance export let componentInstance
export let componentBindings
export let bindings export let bindings
export let parseSettings export let parseSettings
@ -28,6 +28,10 @@
} }
$: componentDef = componentStore.getDefinition(componentInstance._component) $: componentDef = componentStore.getDefinition(componentInstance._component)
$: parsedComponentDef = processComponentDefinitionSettings(componentDef) $: parsedComponentDef = processComponentDefinitionSettings(componentDef)
$: componentBindings = getComponentBindableProperties(
$selectedScreen,
$componentStore.selectedComponentId
)
const open = () => { const open = () => {
isOpen = true isOpen = true

View File

@ -45,7 +45,6 @@
<EditComponentPopover <EditComponentPopover
{anchor} {anchor}
componentInstance={item} componentInstance={item}
{componentBindings}
{bindings} {bindings}
{parseSettings} {parseSettings}
on:change on:change

View File

@ -22,29 +22,59 @@
export let propertyFocus = false export let propertyFocus = false
export let info = null export let info = null
export let disableBindings = false export let disableBindings = false
export let wide export let wide = false
export let isolated = false export let contextAccess = null
let highlightType let highlightType
$: highlightedProp = $builderStore.highlightedSetting $: highlightedProp = $builderStore.highlightedSetting
$: allBindings = getAllBindings(bindings, componentBindings, nested, isolated) $: allBindings = getAllBindings(
bindings,
componentBindings,
nested,
contextAccess
)
$: safeValue = getSafeValue(value, defaultValue, allBindings) $: safeValue = getSafeValue(value, defaultValue, allBindings)
$: replaceBindings = val => readableToRuntimeBinding(allBindings, val) $: replaceBindings = val => readableToRuntimeBinding(allBindings, val)
$: if (value) { $: if (value) {
highlightType = highlightType =
highlightedProp?.key === key ? `highlighted-${highlightedProp?.type}` : "" highlightedProp?.key === key ? `highlighted-${highlightedProp?.type}` : ""
} }
const getAllBindings = (bindings, componentBindings, nested, isolated) => { const getAllBindings = (
if (isolated) { bindings,
bindings = [] componentBindings,
nested,
contextAccess
) => {
// contextAccess is a bit of an escape hatch to get around how we render
// certain settings types by using a pseudo component definition, leading
// to problems with the nested flag
if (contextAccess != null) {
// Optionally include global bindings
let allBindings = contextAccess.global ? bindings : []
// Optionally include or exclude self (component) bindings.
// If this is a nested setting then we will already have our own context
// bindings mixed in, so if we don't want self context we need to filter
// them out.
if (contextAccess.self) {
return [...allBindings, ...componentBindings]
} else {
return allBindings.filter(binding => {
return !componentBindings.some(componentBinding => {
return componentBinding.runtimeBinding === binding.runtimeBinding
})
})
}
} }
if (!nested) {
// Otherwise just honour the normal nested flag
if (nested) {
return [...bindings, ...componentBindings]
} else {
return bindings return bindings
} }
return [...(componentBindings || []), ...(bindings || [])]
} }
// Handle a value change of any type // Handle a value change of any type

View File

@ -151,7 +151,7 @@
propertyFocus={$builderStore.propertyFocus === setting.key} propertyFocus={$builderStore.propertyFocus === setting.key}
info={setting.info} info={setting.info}
disableBindings={setting.disableBindings} disableBindings={setting.disableBindings}
isolated={setting.isolated} contextAccess={setting.contextAccess}
props={{ props={{
// Generic settings // Generic settings
placeholder: setting.placeholder || null, placeholder: setting.placeholder || null,

View File

@ -3088,13 +3088,21 @@
{ {
"type": "tableConditions", "type": "tableConditions",
"label": "Conditions", "label": "Conditions",
"key": "conditions" "key": "conditions",
"contextAccess": {
"global": true,
"self": false
}
}, },
{ {
"type": "text", "type": "text",
"label": "Format", "label": "Format",
"key": "format", "key": "format",
"info": "Changing format will display values as text" "info": "Changing format will display values as text",
"contextAccess": {
"global": false,
"self": true
}
} }
] ]
}, },
@ -7692,8 +7700,7 @@
"type": "columns/grid", "type": "columns/grid",
"key": "columns", "key": "columns",
"resetOn": "table", "resetOn": "table",
"nested": true, "nested": true
"isolated": true
} }
] ]
}, },

View File

@ -47,8 +47,8 @@
$: currentTheme = $context?.device?.theme $: currentTheme = $context?.device?.theme
$: darkMode = !currentTheme?.includes("light") $: darkMode = !currentTheme?.includes("light")
$: parsedColumns = getParsedColumns(columns) $: parsedColumns = getParsedColumns(columns)
$: schemaOverrides = getSchemaOverrides(parsedColumns)
$: enrichedButtons = enrichButtons(buttons) $: enrichedButtons = enrichButtons(buttons)
$: schemaOverrides = getSchemaOverrides(parsedColumns, $context)
$: selectedRows = deriveSelectedRows(gridContext) $: selectedRows = deriveSelectedRows(gridContext)
$: styles = patchStyles($component.styles, minHeight) $: styles = patchStyles($component.styles, minHeight)
$: data = { selectedRows: $selectedRows } $: data = { selectedRows: $selectedRows }
@ -97,18 +97,19 @@
})) }))
} }
const getSchemaOverrides = columns => { const getSchemaOverrides = (columns, context) => {
let overrides = {} let overrides = {}
columns.forEach((column, idx) => { columns.forEach((column, idx) => {
overrides[column.field] = { overrides[column.field] = {
displayName: column.label, displayName: column.label,
order: idx, order: idx,
conditions: column.conditions,
visible: !!column.active, visible: !!column.active,
conditions: enrichConditions(column.conditions, context),
format: createFormatter(column), format: createFormatter(column),
// Small hack to ensure we react to all changes when inside the builder // Small hack to ensure we react to all changes, as our
rand: Math.random(), // memoization cannot compare differences in functions
rand: column.conditions?.length ? Math.random() : null,
} }
if (column.width) { if (column.width) {
overrides[column.field].width = column.width overrides[column.field].width = column.width
@ -117,6 +118,15 @@
return overrides return overrides
} }
const enrichConditions = (conditions, context) => {
return conditions?.map(condition => {
return {
...condition,
referenceValue: processStringSync(condition.referenceValue, context),
}
})
}
const createFormatter = column => { const createFormatter = column => {
if (typeof column.format !== "string" || !column.format.trim().length) { if (typeof column.format !== "string" || !column.format.trim().length) {
return null return null

View File

@ -31,7 +31,7 @@ export const deriveStores = (context: StoreContext): ConditionDerivedStore => {
// Derive and memoize the cell conditions present in our columns so that we // Derive and memoize the cell conditions present in our columns so that we
// only recompute condition metadata when absolutely necessary // only recompute condition metadata when absolutely necessary
const conditions = derivedMemo(columns, $columns => { const conditions = derivedMemo(columns, $columns => {
let newConditions = [] let newConditions: UICondition[] = []
for (let column of $columns) { for (let column of $columns) {
for (let condition of column.conditions || []) { for (let condition of column.conditions || []) {
newConditions.push({ newConditions.push({

View File

@ -1,9 +1,15 @@
import { CalculationType, FieldSchema, FieldType, UIRow } from "@budibase/types" import {
CalculationType,
FieldSchema,
FieldType,
UICondition,
UIRow,
} from "@budibase/types"
export type UIColumn = FieldSchema & { export type UIColumn = FieldSchema & {
label: string label: string
readonly: boolean readonly: boolean
conditions: any conditions?: UICondition[]
format?: (row: UIRow) => any format?: (row: UIRow) => any
related?: { related?: {
field: string field: string

View File

@ -3,7 +3,7 @@ import { FieldType, SearchFilter } from "@budibase/types"
export interface UICondition { export interface UICondition {
column: string column: string
type: FieldType type: FieldType
referenceValue: string referenceValue: any
operator: SearchFilter["operator"] operator: SearchFilter["operator"]
metadataKey: string metadataKey: string
metadataValue: string metadataValue: string