Add initial work on evaluation of conditional UI conditions in client library
This commit is contained in:
parent
4bdfb49742
commit
5e5332cd4f
|
@ -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) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { DetailSummary, ActionButton, Drawer, Button } from "@budibase/bbui"
|
||||
// import { store } from "builderStore"
|
||||
import { store } from "builderStore"
|
||||
import ConditionalUIDrawer from "./PropertyControls/ConditionalUIDrawer.svelte"
|
||||
|
||||
export let componentInstance
|
||||
|
@ -9,12 +9,12 @@
|
|||
let drawer
|
||||
|
||||
const openDrawer = () => {
|
||||
tempValue = componentInstance?._conditions
|
||||
tempValue = JSON.parse(JSON.stringify(componentInstance?._conditions ?? []))
|
||||
drawer.show()
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
// store.actions.components.updateCustomStyle(tempValue)
|
||||
store.actions.components.updateConditions(tempValue)
|
||||
drawer.hide()
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={`component ${id}`}
|
||||
data-type={interactive ? "component" : ""}
|
||||
data-id={id}
|
||||
data-name={name}
|
||||
>
|
||||
{#key propsHash}
|
||||
{#if constructor && componentProps}
|
||||
<svelte:component this={constructor} {...componentProps}>
|
||||
{#key propsHash}
|
||||
{#if constructor && componentSettings && visible}
|
||||
<div
|
||||
class={`component ${id}`}
|
||||
data-type={interactive ? "component" : ""}
|
||||
data-id={id}
|
||||
data-name={name}
|
||||
class:hidden={!visible}
|
||||
>
|
||||
<svelte:component this={constructor} {...componentSettings}>
|
||||
{#if children.length}
|
||||
{#each children as child (child._id)}
|
||||
<svelte:self instance={child} />
|
||||
|
@ -159,9 +200,9 @@
|
|||
<Placeholder />
|
||||
{/if}
|
||||
</svelte:component>
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/key}
|
||||
|
||||
<style>
|
||||
.component {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import {
|
||||
buildLuceneQuery,
|
||||
luceneQuery,
|
||||
} from "../../../standard-components/src/lucene"
|
||||
|
||||
export const getActiveConditions = conditions => {
|
||||
if (!conditions?.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const luceneCompatibleConditions = conditions.map(condition => {
|
||||
return {
|
||||
...condition,
|
||||
type: "string",
|
||||
field: "newValue",
|
||||
value: condition.referenceValue,
|
||||
}
|
||||
})
|
||||
|
||||
const query = buildLuceneQuery(luceneCompatibleConditions)
|
||||
console.log(luceneQuery)
|
||||
|
||||
return luceneQuery(luceneCompatibleConditions, query)
|
||||
}
|
||||
|
||||
export const reduceConditionActions = conditions => {
|
||||
let settingUpdates = {}
|
||||
let visible = null
|
||||
|
||||
conditions?.forEach(condition => {
|
||||
if (condition.action === "show") {
|
||||
visible = true
|
||||
} else if (condition.action === "hide") {
|
||||
visible = false
|
||||
} else if (condition.setting) {
|
||||
settingUpdates[condition.setting] = condition.settingValue
|
||||
}
|
||||
})
|
||||
|
||||
return { settingUpdates, visible }
|
||||
}
|
Loading…
Reference in New Issue