From 5e5332cd4f7f4c788d4e91f151e20f3e076ea424 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 21 Jul 2021 14:03:49 +0100 Subject: [PATCH] Add initial work on evaluation of conditional UI conditions in client library --- .../src/builderStore/store/frontend.js | 5 ++ .../ConditionalUISection.svelte | 6 +- .../client/src/components/Component.svelte | 83 ++++++++++++++----- packages/client/src/utils/conditions.js | 41 +++++++++ 4 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 packages/client/src/utils/conditions.js diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index b9cd134067..f84e1c8735 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -530,6 +530,11 @@ export const getFrontendStore = () => { selected._styles = { normal: {}, hover: {}, active: {} } await store.actions.preview.saveSelected() }, + updateConditions: async conditions => { + const selected = get(selectedComponent) + selected._conditions = conditions + await store.actions.preview.saveSelected() + }, updateProp: async (name, value) => { let component = get(selectedComponent) if (!name || !component) { diff --git a/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte b/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte index 5071354813..63196ab54a 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ConditionalUISection.svelte @@ -1,6 +1,6 @@ diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 4440e83845..b985f064cd 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -8,11 +8,18 @@ import { hashString } from "../utils/hash" import Manifest from "@budibase/standard-components/manifest.json" import { Placeholder } from "@budibase/standard-components" + import { + getActiveConditions, + reduceConditionActions, + } from "../utils/conditions" export let instance = {} - // Props that will be passed to the component instance - let componentProps + // The enriched component settings + let enrichedSettings + + // Any prop overrides that need to be applied due to conditional UI + let conditionalSettings // Props are hashed when inside the builder preview and used as a key, so that // components fully remount whenever any props change @@ -28,6 +35,9 @@ let lastContextKey let lastInstanceKey + // Visibility flag used by conditional UI + let visible = true + // Get contexts const context = getContext("context") const insideScreenslot = !!getContext("screenslot") @@ -54,6 +64,8 @@ $builderStore.inBuilder && $builderStore.selectedComponentId === instance._id $: interactive = $builderStore.previewType === "layout" || insideScreenslot + $: evaluateConditions(enrichedSettings?._conditions) + $: componentSettings = { ...enrichedSettings, ...conditionalSettings } // Update component context $: componentStore.set({ @@ -62,14 +74,14 @@ styles: { ...instance._styles, id, empty, interactive }, empty, selected, - props: componentProps, + props: componentSettings, name, }) const getRawProps = instance => { let validProps = {} Object.entries(instance) - .filter(([name]) => !name.startsWith("_")) + .filter(([name]) => name === "_conditions" || !name.startsWith("_")) .forEach(([key, value]) => { validProps[key] = value }) @@ -123,34 +135,63 @@ return } let propsChanged = false - if (!componentProps) { - componentProps = {} + if (!enrichedSettings) { + enrichedSettings = {} propsChanged = true } Object.keys(enrichedProps).forEach(key => { - if (!propsAreSame(enrichedProps[key], componentProps[key])) { + if (!propsAreSame(enrichedProps[key], enrichedSettings[key])) { propsChanged = true - componentProps[key] = enrichedProps[key] + enrichedSettings[key] = enrichedProps[key] } }) // Update the hash if we're in the builder so we can fully remount this // component if (get(builderStore).inBuilder && propsChanged) { - propsHash = hashString(JSON.stringify(componentProps)) + propsHash = hashString(JSON.stringify(enrichedSettings)) } } + + const evaluateConditions = conditions => { + console.log("evaluating") + console.log(conditions) + + if (!conditions?.length) { + return + } + + // Default visible to false if there is a show condition + let nextVisible = true + for (let condition of conditions) { + if (condition.action === "show") { + nextVisible = false + } + } + + const activeConditions = getActiveConditions(conditions) + console.log(activeConditions) + + const result = reduceConditionActions(activeConditions) + conditionalSettings = result.settingUpdates + if (result.visible != null) { + nextVisible = result.visible + } + + visible = nextVisible + } -
- {#key propsHash} - {#if constructor && componentProps} - +{#key propsHash} + {#if constructor && componentSettings && visible} +
+ {#if children.length} {#each children as child (child._id)} @@ -159,9 +200,9 @@ {/if} - {/if} - {/key} -
+
+ {/if} +{/key}