Automatically determine which state keys are available

This commit is contained in:
Andrew Kingston 2021-08-26 16:46:25 +01:00
parent a7be624d64
commit 21029b80ba
2 changed files with 61 additions and 10 deletions

View File

@ -1,6 +1,10 @@
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { get } from "svelte/store" import { get } from "svelte/store"
import { findComponent, findComponentPath } from "./storeUtils" import {
findComponent,
findComponentPath,
findAllMatchingComponents,
} from "./storeUtils"
import { store } from "builderStore" import { store } from "builderStore"
import { tables as tablesStore, queries as queriesStores } from "stores/backend" import { tables as tablesStore, queries as queriesStores } from "stores/backend"
import { makePropSafe } from "@budibase/string-templates" import { makePropSafe } from "@budibase/string-templates"
@ -262,13 +266,12 @@ const getDeviceBindings = () => {
* Gets all state bindings that are globally available. * Gets all state bindings that are globally available.
*/ */
const getStateBindings = () => { const getStateBindings = () => {
return [ const safeState = makePropSafe("state")
{ return getAllStateVariables().map(key => ({
type: "context", type: "context",
runtimeBinding: makePropSafe("state"), runtimeBinding: `${safeState}.${makePropSafe(key)}`,
readableBinding: `State`, readableBinding: `State.${key}`,
}, }))
]
} }
/** /**
@ -473,3 +476,49 @@ export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
"readableBinding" "readableBinding"
) )
} }
/**
* Returns an array of the keys of any state variables which are set anywhere
* in the app.
*/
export const getAllStateVariables = () => {
let allComponents = []
// Find all onClick settings in all layouts
get(store).layouts.forEach(layout => {
const components = findAllMatchingComponents(
layout.props,
c => c.onClick != null
)
allComponents = allComponents.concat(components || [])
})
// Find all onClick settings in all screens
get(store).screens.forEach(screen => {
const components = findAllMatchingComponents(
screen.props,
c => c.onClick != null
)
allComponents = allComponents.concat(components || [])
})
// Add state bindings for all state actions
let bindingSet = new Set()
allComponents.forEach(component => {
if (!Array.isArray(component.onClick)) {
return
}
component.onClick.forEach(action => {
if (
action["##eventHandlerType"] === "Update State" &&
action.parameters?.type === "set" &&
action.parameters?.key &&
action.parameters?.value
) {
bindingSet.add(action.parameters.key)
}
})
})
return Array.from(bindingSet)
}

View File

@ -1,11 +1,13 @@
<script> <script>
import { Select, Label, Input } from "@budibase/bbui" import { Select, Label, Combobox } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
import { getAllStateVariables } from "builderStore/dataBinding"
export let parameters export let parameters
export let bindings = [] export let bindings = []
const keyOptions = getAllStateVariables()
const typeOptions = [ const typeOptions = [
{ {
label: "Set value", label: "Set value",
@ -32,7 +34,7 @@
options={typeOptions} options={typeOptions}
/> />
<Label small>Key</Label> <Label small>Key</Label>
<Input bind:value={parameters.key} /> <Combobox bind:value={parameters.key} options={keyOptions} />
{#if parameters.type === "set"} {#if parameters.type === "set"}
<Label small>Value</Label> <Label small>Value</Label>
<DrawerBindableInput <DrawerBindableInput