Merge pull request #3309 from Budibase/quick-bindings

Quick bindings
This commit is contained in:
Andrew Kingston 2021-11-10 12:18:52 +00:00 committed by GitHub
commit d47bf555c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 49 additions and 105 deletions

View File

@ -36,5 +36,7 @@
{getOptionLabel} {getOptionLabel}
{getOptionValue} {getOptionValue}
on:change={onChange} on:change={onChange}
on:pick
on:type
/> />
</Field> </Field>

View File

@ -40,8 +40,15 @@
open = false open = false
} }
const onChange = e => { const onType = e => {
selectOption(e.target.value) const value = e.target.value
dispatch("type", value)
selectOption(value)
}
const onPick = value => {
dispatch("pick", value)
selectOption(value)
} }
</script> </script>
@ -62,7 +69,7 @@
type="text" type="text"
on:focus={() => (focus = true)} on:focus={() => (focus = true)}
on:blur={() => (focus = false)} on:blur={() => (focus = false)}
on:change={onChange} on:change={onType}
value={value || ""} value={value || ""}
placeholder={placeholder || ""} placeholder={placeholder || ""}
{disabled} {disabled}
@ -99,7 +106,7 @@
role="option" role="option"
aria-selected="true" aria-selected="true"
tabindex="0" tabindex="0"
on:click={() => selectOption(getOptionValue(option))} on:click={() => onPick(getOptionValue(option))}
> >
<span class="spectrum-Menu-itemLabel" <span class="spectrum-Menu-itemLabel"
>{getOptionLabel(option)}</span >{getOptionLabel(option)}</span

View File

@ -17,6 +17,7 @@
export let disabled = false export let disabled = false
export let options export let options
export let allowJS = true export let allowJS = true
export let appendBindingsAsOptions = true
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
let bindingDrawer let bindingDrawer
@ -24,15 +25,30 @@
$: readableValue = runtimeToReadableBinding(bindings, value) $: readableValue = runtimeToReadableBinding(bindings, value)
$: tempValue = readableValue $: tempValue = readableValue
$: isJS = isJSBinding(value) $: isJS = isJSBinding(value)
$: allOptions = buildOptions(options, bindings, appendBindingsAsOptions)
const handleClose = () => { const handleClose = () => {
onChange(tempValue) onChange(tempValue)
bindingDrawer.hide() bindingDrawer.hide()
} }
const onChange = value => { const onChange = (value, optionPicked) => {
// Add HBS braces if picking binding
if (optionPicked && !options?.includes(value)) {
value = `{{ ${value} }}`
}
dispatch("change", readableToRuntimeBinding(bindings, value)) dispatch("change", readableToRuntimeBinding(bindings, value))
} }
const buildOptions = (options, bindings, appendBindingsAsOptions) => {
if (!appendBindingsAsOptions) {
return options
}
return []
.concat(options || [])
.concat(bindings?.map(binding => binding.readableBinding) || [])
}
</script> </script>
<div class="control"> <div class="control">
@ -40,12 +56,17 @@
{label} {label}
{disabled} {disabled}
value={isJS ? "(JavaScript function)" : readableValue} value={isJS ? "(JavaScript function)" : readableValue}
on:change={event => onChange(event.detail)} on:type={e => onChange(e.detail, false)}
on:pick={e => onChange(e.detail, true)}
{placeholder} {placeholder}
{options} options={allOptions}
/> />
{#if !disabled} {#if !disabled}
<div class="icon" on:click={bindingDrawer.show}> <div
class="icon"
on:click={bindingDrawer.show}
data-cy="text-binding-button"
>
<Icon size="S" name="FlashOn" /> <Icon size="S" name="FlashOn" />
</div> </div>
{/if} {/if}

View File

@ -78,7 +78,6 @@
<DetailSummary name={section.name} collapsible={false}> <DetailSummary name={section.name} collapsible={false}>
{#if idx === 0 && !componentInstance._component.endsWith("/layout")} {#if idx === 0 && !componentInstance._component.endsWith("/layout")}
<PropertyControl <PropertyControl
bindable={false}
control={Input} control={Input}
label="Name" label="Name"
key="_instanceName" key="_instanceName"

View File

@ -1,15 +0,0 @@
<script>
import { Input } from "@budibase/bbui"
import { isJSBinding } from "@budibase/string-templates"
export let value
$: isJS = isJSBinding(value)
</script>
<Input
{...$$props}
value={isJS ? "(JavaScript function)" : value}
readonly={isJS}
on:change
/>

View File

@ -1,11 +1,9 @@
<script> <script>
import { Button, Icon, Drawer, Label } from "@budibase/bbui" import { Label } from "@budibase/bbui"
import { import {
readableToRuntimeBinding, readableToRuntimeBinding,
runtimeToReadableBinding, runtimeToReadableBinding,
} from "builderStore/dataBinding" } from "builderStore/dataBinding"
import BindingPanel from "components/common/bindings/BindingPanel.svelte"
import { capitalise } from "helpers"
export let label = "" export let label = ""
export let bindable = true export let bindable = true
@ -20,10 +18,6 @@
export let componentBindings = [] export let componentBindings = []
export let nested = false export let nested = false
let bindingDrawer
let anchor
let valid
$: allBindings = getAllBindings(bindings, componentBindings, nested) $: allBindings = getAllBindings(bindings, componentBindings, nested)
$: safeValue = getSafeValue(value, props.defaultValue, allBindings) $: safeValue = getSafeValue(value, props.defaultValue, allBindings)
$: tempValue = safeValue $: tempValue = safeValue
@ -36,11 +30,6 @@
return [...(bindings || []), ...(componentBindings || [])] return [...(bindings || []), ...(componentBindings || [])]
} }
const handleClose = () => {
handleChange(tempValue)
bindingDrawer.hide()
}
// Handle a value change of any type // Handle a value change of any type
// String values have any bindings handled // String values have any bindings handled
const handleChange = value => { const handleChange = value => {
@ -74,7 +63,7 @@
} }
</script> </script>
<div class="property-control" bind:this={anchor} data-cy={`setting-${key}`}> <div class="property-control" data-cy={`setting-${key}`}>
{#if type !== "boolean" && label} {#if type !== "boolean" && label}
<div class="label"> <div class="label">
<Label>{label}</Label> <Label>{label}</Label>
@ -94,31 +83,6 @@
{type} {type}
{...props} {...props}
/> />
{#if bindable && !key.startsWith("_") && type === "text"}
<div
class="icon"
data-cy={`${key}-binding-button`}
on:click={bindingDrawer.show}
>
<Icon size="S" name="FlashOn" />
</div>
<Drawer bind:this={bindingDrawer} title={capitalise(key)}>
<svelte:fragment slot="description">
Add the objects on the left to enrich your text.
</svelte:fragment>
<Button cta slot="buttons" disabled={!valid} on:click={handleClose}>
Save
</Button>
<BindingPanel
slot="body"
bind:valid
value={safeValue}
on:change={e => (tempValue = e.detail)}
bindableProperties={allBindings}
allowJS
/>
</Drawer>
{/if}
</div> </div>
</div> </div>
@ -130,40 +94,10 @@
justify-content: flex-start; justify-content: flex-start;
align-items: stretch; align-items: stretch;
} }
.label { .label {
padding-bottom: var(--spectrum-global-dimension-size-65); padding-bottom: var(--spectrum-global-dimension-size-65);
} }
.control { .control {
position: relative; position: relative;
} }
.icon {
right: 1px;
top: 1px;
bottom: 1px;
position: absolute;
justify-content: center;
align-items: center;
display: flex;
flex-direction: row;
box-sizing: border-box;
border-left: 1px solid var(--spectrum-alias-border-color);
border-top-right-radius: var(--spectrum-alias-border-radius-regular);
border-bottom-right-radius: var(--spectrum-alias-border-radius-regular);
width: 31px;
color: var(--spectrum-alias-text-color);
background-color: var(--spectrum-global-color-gray-75);
transition: background-color
var(--spectrum-global-animation-duration-100, 130ms),
box-shadow var(--spectrum-global-animation-duration-100, 130ms),
border-color var(--spectrum-global-animation-duration-100, 130ms);
}
.icon:hover {
cursor: pointer;
color: var(--spectrum-alias-text-color-hover);
background-color: var(--spectrum-global-color-gray-50);
border-color: var(--spectrum-alias-border-color-hover);
}
</style> </style>

View File

@ -10,4 +10,10 @@
.filter(x => x != null) .filter(x => x != null)
</script> </script>
<DrawerBindableCombobox {value} {bindings} on:change options={urlOptions} /> <DrawerBindableCombobox
{value}
{bindings}
on:change
options={urlOptions}
appendBindingsAsOptions={false}
/>

View File

@ -15,10 +15,10 @@ import URLSelect from "./URLSelect.svelte"
import OptionsEditor from "./OptionsEditor/OptionsEditor.svelte" import OptionsEditor from "./OptionsEditor/OptionsEditor.svelte"
import FormFieldSelect from "./FormFieldSelect.svelte" import FormFieldSelect from "./FormFieldSelect.svelte"
import ValidationEditor from "./ValidationEditor/ValidationEditor.svelte" import ValidationEditor from "./ValidationEditor/ValidationEditor.svelte"
import Input from "./Input.svelte" import DrawerBindableCombobox from "components/common/bindings/DrawerBindableCombobox.svelte"
const componentMap = { const componentMap = {
text: Input, text: DrawerBindableCombobox,
select: Select, select: Select,
dataSource: DataSourceSelect, dataSource: DataSourceSelect,
dataProvider: DataProviderSelect, dataProvider: DataProviderSelect,

View File

@ -54,7 +54,6 @@
<DetailSummary name="Screen" collapsible={false}> <DetailSummary name="Screen" collapsible={false}>
{#each screenSettings as def (`${componentInstance._id}-${def.key}`)} {#each screenSettings as def (`${componentInstance._id}-${def.key}`)}
<PropertyControl <PropertyControl
bindable={false}
control={def.control} control={def.control}
label={def.label} label={def.label}
key={def.key} key={def.key}

View File

@ -30,7 +30,6 @@
{#each properties as prop (`${componentInstance._id}-${prop.key}-${prop.label}`)} {#each properties as prop (`${componentInstance._id}-${prop.key}-${prop.label}`)}
<div style="grid-column: {prop.column || 'auto'}"> <div style="grid-column: {prop.column || 'auto'}">
<PropertyControl <PropertyControl
bindable={false}
label={`${prop.label}${hasPropChanged(style, prop) ? " *" : ""}`} label={`${prop.label}${hasPropChanged(style, prop) ? " *" : ""}`}
control={prop.control} control={prop.control}
key={prop.key} key={prop.key}

View File

@ -9,7 +9,6 @@ export const margin = {
label: "Top", label: "Top",
key: "margin-top", key: "margin-top",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -30,7 +29,6 @@ export const margin = {
label: "Right", label: "Right",
key: "margin-right", key: "margin-right",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -51,7 +49,6 @@ export const margin = {
label: "Bottom", label: "Bottom",
key: "margin-bottom", key: "margin-bottom",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -72,7 +69,6 @@ export const margin = {
label: "Left", label: "Left",
key: "margin-left", key: "margin-left",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -100,7 +96,6 @@ export const padding = {
label: "Top", label: "Top",
key: "padding-top", key: "padding-top",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -121,7 +116,6 @@ export const padding = {
label: "Right", label: "Right",
key: "padding-right", key: "padding-right",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -142,7 +136,6 @@ export const padding = {
label: "Bottom", label: "Bottom",
key: "padding-bottom", key: "padding-bottom",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },
@ -163,7 +156,6 @@ export const padding = {
label: "Left", label: "Left",
key: "padding-left", key: "padding-left",
control: Select, control: Select,
bindable: false,
placeholder: "None", placeholder: "None",
options: [ options: [
{ label: "4px", value: "4px" }, { label: "4px", value: "4px" },