Merge pull request #15464 from Budibase/fix/missing-state-usage
Fixes to address state usage misses
This commit is contained in:
commit
0c496ade8a
|
@ -143,10 +143,10 @@
|
||||||
.property-control.highlighted {
|
.property-control.highlighted {
|
||||||
background: var(--spectrum-global-color-gray-300);
|
background: var(--spectrum-global-color-gray-300);
|
||||||
border-color: var(--spectrum-global-color-static-red-600);
|
border-color: var(--spectrum-global-color-static-red-600);
|
||||||
margin-top: -3.5px;
|
margin-top: -4px;
|
||||||
margin-bottom: -3.5px;
|
margin-bottom: -4px;
|
||||||
padding-bottom: 3.5px;
|
padding-bottom: 4px;
|
||||||
padding-top: 3.5px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.property-control.property-focus :global(input) {
|
.property-control.property-focus :global(input) {
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
section = "conditions"
|
section = "conditions"
|
||||||
} else if (highlightedSetting.key === "_styles") {
|
} else if (highlightedSetting.key === "_styles") {
|
||||||
section = "styles"
|
section = "styles"
|
||||||
} else if (highlightedSetting.key === "_settings") {
|
} else {
|
||||||
section = "settings"
|
section = "settings"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
{#if section == "settings"}
|
{#if section === "settings"}
|
||||||
<TourWrap
|
<TourWrap
|
||||||
stepKeys={[
|
stepKeys={[
|
||||||
BUILDER_FORM_CREATE_STEPS,
|
BUILDER_FORM_CREATE_STEPS,
|
||||||
|
@ -127,7 +127,7 @@
|
||||||
/>
|
/>
|
||||||
</TourWrap>
|
</TourWrap>
|
||||||
{/if}
|
{/if}
|
||||||
{#if section == "styles"}
|
{#if section === "styles"}
|
||||||
<DesignSection
|
<DesignSection
|
||||||
{componentInstance}
|
{componentInstance}
|
||||||
{componentBindings}
|
{componentBindings}
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
componentTitle={title}
|
componentTitle={title}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if section == "conditions"}
|
{#if section === "conditions"}
|
||||||
<ConditionalUISection
|
<ConditionalUISection
|
||||||
{componentInstance}
|
{componentInstance}
|
||||||
{componentDefinition}
|
{componentDefinition}
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
<Icon name="DragHandle" size="XL" />
|
<Icon name="DragHandle" size="XL" />
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
placeholder={null}
|
placeholder={false}
|
||||||
options={actionOptions}
|
options={actionOptions}
|
||||||
bind:value={condition.action}
|
bind:value={condition.action}
|
||||||
/>
|
/>
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
on:change={e => (condition.newValue = e.detail)}
|
on:change={e => (condition.newValue = e.detail)}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
placeholder={null}
|
placeholder={false}
|
||||||
options={getOperatorOptions(condition)}
|
options={getOperatorOptions(condition)}
|
||||||
bind:value={condition.operator}
|
bind:value={condition.operator}
|
||||||
on:change={e => onOperatorChange(condition, e.detail)}
|
on:change={e => onOperatorChange(condition, e.detail)}
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
disabled={condition.noValue || condition.operator === "oneOf"}
|
disabled={condition.noValue || condition.operator === "oneOf"}
|
||||||
options={valueTypeOptions}
|
options={valueTypeOptions}
|
||||||
bind:value={condition.valueType}
|
bind:value={condition.valueType}
|
||||||
placeholder={null}
|
placeholder={false}
|
||||||
on:change={e => onValueTypeChange(condition, e.detail)}
|
on:change={e => onValueTypeChange(condition, e.detail)}
|
||||||
/>
|
/>
|
||||||
{#if ["string", "number"].includes(condition.valueType)}
|
{#if ["string", "number"].includes(condition.valueType)}
|
||||||
|
|
|
@ -72,11 +72,7 @@
|
||||||
background: var(--spectrum-global-color-gray-300);
|
background: var(--spectrum-global-color-gray-300);
|
||||||
border-left: 4px solid var(--spectrum-semantic-informative-color-background);
|
border-left: 4px solid var(--spectrum-semantic-informative-color-background);
|
||||||
transition: background 130ms ease-out, border-color 130ms ease-out;
|
transition: background 130ms ease-out, border-color 130ms ease-out;
|
||||||
margin-top: -3.5px;
|
margin: -4px calc(-1 * var(--spacing-xl));
|
||||||
margin-bottom: -3.5px;
|
padding: 4px var(--spacing-xl) 4px calc(var(--spacing-xl) - 4px);
|
||||||
padding-bottom: 3.5px;
|
|
||||||
padding-top: 3.5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -105,11 +105,7 @@
|
||||||
background: var(--spectrum-global-color-gray-300);
|
background: var(--spectrum-global-color-gray-300);
|
||||||
border-left: 4px solid var(--spectrum-semantic-informative-color-background);
|
border-left: 4px solid var(--spectrum-semantic-informative-color-background);
|
||||||
transition: background 130ms ease-out, border-color 130ms ease-out;
|
transition: background 130ms ease-out, border-color 130ms ease-out;
|
||||||
margin-top: -3.5px;
|
margin: -4px calc(-1 * var(--spacing-xl));
|
||||||
margin-bottom: -3.5px;
|
padding: 4px var(--spacing-xl) 4px calc(var(--spacing-xl) - 4px);
|
||||||
padding-bottom: 3.5px;
|
|
||||||
padding-top: 3.5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Layout gap="XS" paddingX="L" paddingY="XL">
|
<Layout gap="XS" paddingX="XL" paddingY="XL">
|
||||||
{#if activeTab === "theme"}
|
{#if activeTab === "theme"}
|
||||||
<ThemePanel />
|
<ThemePanel />
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
import type { Component } from "@budibase/types"
|
import type {
|
||||||
|
Component,
|
||||||
|
ComponentCondition,
|
||||||
|
EventHandler,
|
||||||
|
Screen,
|
||||||
|
} from "@budibase/types"
|
||||||
import { getAllStateVariables, getBindableProperties } from "@/dataBinding"
|
import { getAllStateVariables, getBindableProperties } from "@/dataBinding"
|
||||||
import {
|
import {
|
||||||
componentStore,
|
componentStore,
|
||||||
|
@ -16,91 +21,191 @@
|
||||||
processStringSync,
|
processStringSync,
|
||||||
} from "@budibase/string-templates"
|
} from "@budibase/string-templates"
|
||||||
import DrawerBindableInput from "@/components/common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "@/components/common/bindings/DrawerBindableInput.svelte"
|
||||||
|
import { type ComponentSetting } from "@/stores/builder/components"
|
||||||
|
|
||||||
interface ComponentUsingState {
|
interface ComponentUsingState {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
settings: string[]
|
setting: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let selectedKey: string | undefined = undefined
|
||||||
|
let componentsUsingState: ComponentUsingState[] = []
|
||||||
|
let componentsUpdatingState: ComponentUsingState[] = []
|
||||||
|
let editorValue: string = ""
|
||||||
|
|
||||||
|
$: selectStateKey($selectedScreen, selectedKey)
|
||||||
$: keyOptions = getAllStateVariables($selectedScreen)
|
$: keyOptions = getAllStateVariables($selectedScreen)
|
||||||
$: bindings = getBindableProperties(
|
$: bindings = getBindableProperties(
|
||||||
$selectedScreen,
|
$selectedScreen,
|
||||||
$componentStore.selectedComponentId
|
$componentStore.selectedComponentId
|
||||||
)
|
)
|
||||||
|
|
||||||
let selectedKey: string | undefined = undefined
|
// Auto-select first valid state key
|
||||||
let componentsUsingState: ComponentUsingState[] = []
|
|
||||||
let componentsUpdatingState: ComponentUsingState[] = []
|
|
||||||
let editorValue: string = ""
|
|
||||||
let previousScreenId: string | undefined = undefined
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
const screenChanged =
|
if (keyOptions.length && !keyOptions.includes(selectedKey)) {
|
||||||
$selectedScreen && $selectedScreen._id !== previousScreenId
|
|
||||||
const previewContext = $previewStore.selectedComponentContext || {}
|
|
||||||
|
|
||||||
if (screenChanged) {
|
|
||||||
selectedKey = keyOptions[0]
|
selectedKey = keyOptions[0]
|
||||||
|
} else if (!keyOptions.length) {
|
||||||
|
selectedKey = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectStateKey = (
|
||||||
|
screen: Screen | undefined,
|
||||||
|
key: string | undefined
|
||||||
|
) => {
|
||||||
|
if (screen && key) {
|
||||||
|
searchComponents(screen, key)
|
||||||
|
editorValue = $previewStore.selectedComponentContext?.state?.[key] ?? ""
|
||||||
|
} else {
|
||||||
|
editorValue = ""
|
||||||
componentsUsingState = []
|
componentsUsingState = []
|
||||||
componentsUpdatingState = []
|
componentsUpdatingState = []
|
||||||
editorValue = ""
|
|
||||||
previousScreenId = $selectedScreen._id
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (keyOptions.length > 0 && !keyOptions.includes(selectedKey)) {
|
const searchComponents = (screen: Screen, stateKey: string) => {
|
||||||
selectedKey = keyOptions[0]
|
const { props, onLoad, _id } = screen
|
||||||
}
|
componentsUsingState = findComponentsUsingState(props, stateKey)
|
||||||
|
componentsUpdatingState = findComponentsUpdatingState(props, stateKey)
|
||||||
|
|
||||||
if (selectedKey) {
|
// Check screen load actions which are outside the component hierarchy
|
||||||
searchComponents(selectedKey)
|
if (eventUpdatesState(onLoad, stateKey)) {
|
||||||
editorValue = previewContext.state?.[selectedKey] ?? ""
|
componentsUpdatingState.push({
|
||||||
|
id: _id!,
|
||||||
|
name: "Screen - On load",
|
||||||
|
setting: "onLoad",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if an event setting updates a certain state key
|
||||||
|
const eventUpdatesState = (
|
||||||
|
handlers: EventHandler[] | undefined,
|
||||||
|
stateKey: string
|
||||||
|
) => {
|
||||||
|
return handlers?.some(handler => {
|
||||||
|
return (
|
||||||
|
handler["##eventHandlerType"] === "Update State" &&
|
||||||
|
handler.parameters?.key === stateKey
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if a setting for the given component updates a certain state key
|
||||||
|
const settingUpdatesState = (
|
||||||
|
component: Record<string, any>,
|
||||||
|
setting: ComponentSetting,
|
||||||
|
stateKey: string
|
||||||
|
) => {
|
||||||
|
if (setting.type === "event") {
|
||||||
|
return eventUpdatesState(component[setting.key], stateKey)
|
||||||
|
} else if (setting.type === "buttonConfiguration") {
|
||||||
|
const buttons = component[setting.key]
|
||||||
|
if (Array.isArray(buttons)) {
|
||||||
|
for (let button of buttons) {
|
||||||
|
if (eventUpdatesState(button.onClick, stateKey)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if a condition updates a certain state key
|
||||||
|
const conditionUpdatesState = (
|
||||||
|
condition: ComponentCondition,
|
||||||
|
settings: ComponentSetting[],
|
||||||
|
stateKey: string
|
||||||
|
) => {
|
||||||
|
const setting = settings.find(s => s.key === condition.setting)
|
||||||
|
if (!setting) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const component = { [setting.key]: condition.settingValue }
|
||||||
|
return settingUpdatesState(component, setting, stateKey)
|
||||||
|
}
|
||||||
|
|
||||||
const findComponentsUpdatingState = (
|
const findComponentsUpdatingState = (
|
||||||
component: Component,
|
component: Component,
|
||||||
stateKey: string
|
stateKey: string,
|
||||||
|
foundComponents: ComponentUsingState[] = []
|
||||||
): ComponentUsingState[] => {
|
): ComponentUsingState[] => {
|
||||||
let foundComponents: ComponentUsingState[] = []
|
const { _children, _conditions, _component, _instanceName, _id } = component
|
||||||
|
const settings = componentStore
|
||||||
|
.getComponentSettings(_component)
|
||||||
|
.filter(s => s.type === "event" || s.type === "buttonConfiguration")
|
||||||
|
|
||||||
const eventHandlerProps = [
|
// Check all settings of this component
|
||||||
"onClick",
|
settings.forEach(setting => {
|
||||||
"onChange",
|
if (settingUpdatesState(component, setting, stateKey)) {
|
||||||
"onRowClick",
|
const label = setting.label || setting.key
|
||||||
"onChange",
|
foundComponents.push({
|
||||||
"buttonOnClick",
|
id: _id!,
|
||||||
]
|
name: `${_instanceName} - ${label}`,
|
||||||
|
setting: setting.key,
|
||||||
eventHandlerProps.forEach(eventType => {
|
|
||||||
const handlers = component[eventType]
|
|
||||||
if (Array.isArray(handlers)) {
|
|
||||||
handlers.forEach(handler => {
|
|
||||||
if (
|
|
||||||
handler["##eventHandlerType"] === "Update State" &&
|
|
||||||
handler.parameters?.key === stateKey
|
|
||||||
) {
|
|
||||||
foundComponents.push({
|
|
||||||
id: component._id!,
|
|
||||||
name: component._instanceName,
|
|
||||||
settings: [eventType],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (component._children) {
|
// Check if conditions update these settings to update this state key
|
||||||
for (let child of component._children) {
|
if (_conditions?.some(c => conditionUpdatesState(c, settings, stateKey))) {
|
||||||
foundComponents = [
|
foundComponents.push({
|
||||||
...foundComponents,
|
id: _id!,
|
||||||
...findComponentsUpdatingState(child, stateKey),
|
name: `${_instanceName} - Conditions`,
|
||||||
]
|
setting: "_conditions",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check children
|
||||||
|
_children?.forEach(child => {
|
||||||
|
findComponentsUpdatingState(child, stateKey, foundComponents)
|
||||||
|
})
|
||||||
return foundComponents
|
return foundComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findComponentsUsingState = (
|
||||||
|
component: Component,
|
||||||
|
stateKey: string,
|
||||||
|
componentsUsingState: ComponentUsingState[] = []
|
||||||
|
): ComponentUsingState[] => {
|
||||||
|
const settings = componentStore.getComponentSettings(component._component)
|
||||||
|
|
||||||
|
// Check all settings of this component
|
||||||
|
const settingsWithState = getSettingsUsingState(component, stateKey)
|
||||||
|
settingsWithState.forEach(setting => {
|
||||||
|
// Get readable label for this setting
|
||||||
|
let label = settings.find(s => s.key === setting)?.label || setting
|
||||||
|
if (setting === "_conditions") {
|
||||||
|
label = "Conditions"
|
||||||
|
} else if (setting === "_styles") {
|
||||||
|
label = "Styles"
|
||||||
|
}
|
||||||
|
componentsUsingState.push({
|
||||||
|
id: component._id!,
|
||||||
|
name: `${component._instanceName} - ${label}`,
|
||||||
|
setting,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check children
|
||||||
|
component._children?.forEach(child => {
|
||||||
|
findComponentsUsingState(child, stateKey, componentsUsingState)
|
||||||
|
})
|
||||||
|
return componentsUsingState
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSettingsUsingState = (
|
||||||
|
component: Component,
|
||||||
|
stateKey: string
|
||||||
|
): string[] => {
|
||||||
|
return Object.entries(component)
|
||||||
|
.filter(([key]) => key !== "_children")
|
||||||
|
.filter(([_, value]) => hasStateBinding(JSON.stringify(value), stateKey))
|
||||||
|
.map(([key]) => key)
|
||||||
|
}
|
||||||
|
|
||||||
const hasStateBinding = (value: string, stateKey: string): boolean => {
|
const hasStateBinding = (value: string, stateKey: string): boolean => {
|
||||||
const bindings = findHBSBlocks(value).map(binding => {
|
const bindings = findHBSBlocks(value).map(binding => {
|
||||||
const sanitizedBinding = binding.replace(/\\"/g, '"')
|
const sanitizedBinding = binding.replace(/\\"/g, '"')
|
||||||
|
@ -111,125 +216,15 @@
|
||||||
return bindings.join(" ").includes(stateKey)
|
return bindings.join(" ").includes(stateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSettingsWithState = (component: any, stateKey: string): string[] => {
|
|
||||||
const settingsWithState: string[] = []
|
|
||||||
for (const [setting, value] of Object.entries(component)) {
|
|
||||||
if (typeof value === "string" && hasStateBinding(value, stateKey)) {
|
|
||||||
settingsWithState.push(setting)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return settingsWithState
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkConditions = (conditions: any[], stateKey: string): boolean => {
|
|
||||||
return conditions.some(condition =>
|
|
||||||
[condition.referenceValue, condition.newValue].some(
|
|
||||||
value => typeof value === "string" && hasStateBinding(value, stateKey)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkStyles = (styles: any, stateKey: string): boolean => {
|
|
||||||
return (
|
|
||||||
typeof styles?.custom === "string" &&
|
|
||||||
hasStateBinding(styles.custom, stateKey)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const findComponentsUsingState = (
|
|
||||||
component: any,
|
|
||||||
stateKey: string
|
|
||||||
): ComponentUsingState[] => {
|
|
||||||
let componentsUsingState: ComponentUsingState[] = []
|
|
||||||
const { _children, _styles, _conditions, ...componentSettings } = component
|
|
||||||
|
|
||||||
const settingsWithState = getSettingsWithState(componentSettings, stateKey)
|
|
||||||
settingsWithState.forEach(setting => {
|
|
||||||
componentsUsingState.push({
|
|
||||||
id: component._id,
|
|
||||||
name: `${component._instanceName} - ${setting}`,
|
|
||||||
settings: [setting],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if (_conditions?.length > 0 && checkConditions(_conditions, stateKey)) {
|
|
||||||
componentsUsingState.push({
|
|
||||||
id: component._id,
|
|
||||||
name: `${component._instanceName} - conditions`,
|
|
||||||
settings: ["_conditions"],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_styles && checkStyles(_styles, stateKey)) {
|
|
||||||
componentsUsingState.push({
|
|
||||||
id: component._id,
|
|
||||||
name: `${component._instanceName} - styles`,
|
|
||||||
settings: ["_styles"],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_children) {
|
|
||||||
for (let child of _children) {
|
|
||||||
componentsUsingState = [
|
|
||||||
...componentsUsingState,
|
|
||||||
...findComponentsUsingState(child, stateKey),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return componentsUsingState
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchComponents = (stateKey: string | undefined) => {
|
|
||||||
if (!stateKey || !$selectedScreen?.props) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const componentStateUpdates = findComponentsUpdatingState(
|
|
||||||
$selectedScreen.props,
|
|
||||||
stateKey
|
|
||||||
)
|
|
||||||
|
|
||||||
componentsUsingState = findComponentsUsingState(
|
|
||||||
$selectedScreen.props,
|
|
||||||
stateKey
|
|
||||||
)
|
|
||||||
|
|
||||||
const screenStateUpdates =
|
|
||||||
$selectedScreen?.onLoad
|
|
||||||
?.filter(
|
|
||||||
(handler: any) =>
|
|
||||||
handler["##eventHandlerType"] === "Update State" &&
|
|
||||||
handler.parameters?.key === stateKey
|
|
||||||
)
|
|
||||||
.map(() => ({
|
|
||||||
id: $selectedScreen._id!,
|
|
||||||
name: "Screen onLoad",
|
|
||||||
settings: ["onLoad"],
|
|
||||||
})) || []
|
|
||||||
|
|
||||||
componentsUpdatingState = [...componentStateUpdates, ...screenStateUpdates]
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleStateKeySelect = (key: CustomEvent) => {
|
|
||||||
if (!key.detail && keyOptions.length > 0) {
|
|
||||||
throw new Error("No state key selected")
|
|
||||||
}
|
|
||||||
searchComponents(key.detail)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onClickComponentLink = (component: ComponentUsingState) => {
|
const onClickComponentLink = (component: ComponentUsingState) => {
|
||||||
componentStore.select(component.id)
|
componentStore.select(component.id)
|
||||||
component.settings.forEach(setting => {
|
builderStore.highlightSetting(component.setting)
|
||||||
builderStore.highlightSetting(setting)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStateInspectorChange = (e: CustomEvent) => {
|
const handleStateInspectorChange = (e: CustomEvent) => {
|
||||||
if (!selectedKey || !$previewStore.selectedComponentContext) {
|
if (!selectedKey || !$previewStore.selectedComponentContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const stateUpdate = {
|
const stateUpdate = {
|
||||||
[selectedKey]: processStringSync(
|
[selectedKey]: processStringSync(
|
||||||
e.detail,
|
e.detail,
|
||||||
|
@ -247,11 +242,10 @@
|
||||||
|
|
||||||
<div class="state-panel">
|
<div class="state-panel">
|
||||||
<Select
|
<Select
|
||||||
label="State variables"
|
label="State variable"
|
||||||
bind:value={selectedKey}
|
bind:value={selectedKey}
|
||||||
placeholder={keyOptions.length > 0 ? false : "No state variables found"}
|
placeholder={keyOptions.length > 0 ? false : "No state variables found"}
|
||||||
options={keyOptions}
|
options={keyOptions}
|
||||||
on:change={handleStateKeySelect}
|
|
||||||
/>
|
/>
|
||||||
{#if selectedKey && keyOptions.length > 0}
|
{#if selectedKey && keyOptions.length > 0}
|
||||||
<DrawerBindableInput
|
<DrawerBindableInput
|
||||||
|
@ -312,7 +306,6 @@
|
||||||
color: var(--spectrum-global-color-gray-700);
|
color: var(--spectrum-global-color-gray-700);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.updates-colour {
|
.updates-colour {
|
||||||
color: var(--bb-indigo-light);
|
color: var(--bb-indigo-light);
|
||||||
}
|
}
|
||||||
|
@ -332,7 +325,6 @@
|
||||||
.component-link:hover {
|
.component-link:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.updates-section {
|
.updates-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { BudiStore } from "../BudiStore"
|
||||||
import { Utils } from "@budibase/frontend-core"
|
import { Utils } from "@budibase/frontend-core"
|
||||||
import {
|
import {
|
||||||
Component as ComponentType,
|
Component as ComponentType,
|
||||||
|
ComponentCondition,
|
||||||
FieldType,
|
FieldType,
|
||||||
Screen,
|
Screen,
|
||||||
Table,
|
Table,
|
||||||
|
@ -69,6 +70,7 @@ export interface ComponentDefinition {
|
||||||
export interface ComponentSetting {
|
export interface ComponentSetting {
|
||||||
key: string
|
key: string
|
||||||
type: string
|
type: string
|
||||||
|
label?: string
|
||||||
section?: string
|
section?: string
|
||||||
name?: string
|
name?: string
|
||||||
defaultValue?: any
|
defaultValue?: any
|
||||||
|
@ -744,10 +746,6 @@ export class ComponentStore extends BudiStore<ComponentState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} componentId
|
|
||||||
*/
|
|
||||||
select(id: string) {
|
select(id: string) {
|
||||||
this.update(state => {
|
this.update(state => {
|
||||||
// Only clear highlights if selecting a different component
|
// Only clear highlights if selecting a different component
|
||||||
|
@ -1139,7 +1137,7 @@ export class ComponentStore extends BudiStore<ComponentState> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateConditions(conditions: Record<string, any>) {
|
async updateConditions(conditions: ComponentCondition[]) {
|
||||||
await this.patch((component: Component) => {
|
await this.patch((component: Component) => {
|
||||||
component._conditions = conditions
|
component._conditions = conditions
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,11 @@ import { userStore, userSelectedResourceMap, isOnlyUser } from "./users.js"
|
||||||
import { deploymentStore } from "./deployments.js"
|
import { deploymentStore } from "./deployments.js"
|
||||||
import { contextMenuStore } from "./contextMenu.js"
|
import { contextMenuStore } from "./contextMenu.js"
|
||||||
import { snippets } from "./snippets"
|
import { snippets } from "./snippets"
|
||||||
import { screenComponents, screenComponentErrors } from "./screenComponent"
|
import {
|
||||||
|
screenComponents,
|
||||||
|
screenComponentErrors,
|
||||||
|
findComponentsBySettingsType,
|
||||||
|
} from "./screenComponent"
|
||||||
|
|
||||||
// Backend
|
// Backend
|
||||||
import { tables } from "./tables"
|
import { tables } from "./tables"
|
||||||
|
@ -70,6 +74,7 @@ export {
|
||||||
appPublished,
|
appPublished,
|
||||||
screenComponents,
|
screenComponents,
|
||||||
screenComponentErrors,
|
screenComponentErrors,
|
||||||
|
findComponentsBySettingsType,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const reset = () => {
|
export const reset = () => {
|
||||||
|
|
|
@ -124,7 +124,7 @@ export const screenComponentErrors = derived(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function findComponentsBySettingsType(
|
export function findComponentsBySettingsType(
|
||||||
screen: Screen,
|
screen: Screen,
|
||||||
type: string | string[],
|
type: string | string[],
|
||||||
definitions: Record<string, ComponentDefinition>
|
definitions: Record<string, ComponentDefinition>
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
import { Document } from "../document"
|
import { Document } from "../document"
|
||||||
|
import { BasicOperator } from "../../sdk"
|
||||||
|
|
||||||
export interface Component extends Document {
|
export interface Component extends Document {
|
||||||
_instanceName: string
|
_instanceName: string
|
||||||
_styles: { [key: string]: any }
|
_styles: { [key: string]: any }
|
||||||
_component: string
|
_component: string
|
||||||
_children?: Component[]
|
_children?: Component[]
|
||||||
|
_conditions?: ComponentCondition[]
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ComponentCondition {
|
||||||
|
id: string
|
||||||
|
operator: BasicOperator
|
||||||
|
action: "update" | "show" | "hide"
|
||||||
|
valueType: "string" | "number" | "datetime" | "boolean"
|
||||||
|
newValue?: any
|
||||||
|
referenceValue?: any
|
||||||
|
setting?: string
|
||||||
|
settingValue?: any
|
||||||
|
}
|
||||||
|
|
|
@ -45,6 +45,6 @@ export interface EventHandler {
|
||||||
value: string
|
value: string
|
||||||
persist: any | null
|
persist: any | null
|
||||||
}
|
}
|
||||||
eventHandlerType: string
|
"##eventHandlerType": string
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue