budibase/packages/builder/src/components/userInterface/PropertyControl.svelte

156 lines
3.8 KiB
Svelte
Raw Normal View History

2020-05-07 15:30:04 +02:00
<script>
import { Icon } from "@budibase/bbui"
2020-08-26 09:11:16 +02:00
import Input from "./PropertyPanelControls/Input.svelte"
import { store, backendUiStore } from "builderStore"
import fetchBindableProperties from "builderStore/fetchBindableProperties"
2020-09-09 22:16:26 +02:00
import {
readableToRuntimeBinding,
runtimeToReadableBinding,
CAPTURE_VAR_INSIDE_MUSTACHE,
} from "builderStore/replaceBindings"
2020-08-12 17:30:20 +02:00
import { DropdownMenu } from "@budibase/bbui"
import BindingDropdown from "components/userInterface/BindingDropdown.svelte"
2020-05-18 17:32:00 +02:00
import { onMount, getContext } from "svelte"
2020-05-07 15:30:04 +02:00
export let label = ""
export let componentInstance = {}
2020-05-07 15:30:04 +02:00
export let control = null
export let key = ""
2020-05-21 15:28:32 +02:00
export let value
2020-05-07 15:30:04 +02:00
export let props = {}
export let onChange = () => {}
let temporaryBindableValue = value
function handleClose() {
handleChange(key, temporaryBindableValue)
}
2020-09-03 09:45:58 +02:00
let bindableProperties = []
2020-08-12 17:30:20 +02:00
let anchor
let dropdown
2020-09-03 09:45:58 +02:00
function getBindableProperties() {
// Get all bindableProperties
bindableProperties = fetchBindableProperties({
componentInstanceId: $store.currentComponentInfo._id,
components: $store.components,
screen: $store.currentPreviewItem,
models: $backendUiStore.models,
})
}
2020-09-03 09:45:58 +02:00
function replaceBindings(textWithBindings) {
getBindableProperties()
2020-09-09 22:16:26 +02:00
textWithBindings = readableToRuntimeBinding(
bindableProperties,
textWithBindings
)
2020-08-27 11:00:36 +02:00
onChange(key, textWithBindings)
}
function handleChange(key, v) {
2020-07-26 12:54:55 +02:00
let innerVal = v
if (typeof v === "object") {
if ("detail" in v) {
innerVal = v.detail
} else if ("target" in v) {
innerVal = props.valueKey ? v.target[props.valueKey] : v.target.value
}
2020-05-20 12:55:25 +02:00
}
if (typeof innerVal === "string") {
replaceBindings(innerVal)
} else {
onChange(key, innerVal)
}
}
2020-05-25 16:23:56 +02:00
const safeValue = () => {
getBindableProperties()
2020-09-09 22:16:26 +02:00
let temp = runtimeToReadableBinding(bindableProperties, value)
2020-05-25 16:23:56 +02:00
return value === undefined && props.defaultValue !== undefined
? props.defaultValue
: temp
2020-05-25 16:23:56 +02:00
}
2020-05-21 15:28:32 +02:00
//Incase the component has a different value key name
const handlevalueKey = value =>
2020-05-25 16:23:56 +02:00
props.valueKey ? { [props.valueKey]: safeValue() } : { value: safeValue() }
2020-05-07 15:30:04 +02:00
</script>
<div class="property-control" bind:this={anchor}>
2020-05-07 15:30:04 +02:00
<div class="label">{label}</div>
<div data-cy={`${key}-prop-control`} class="control">
2020-05-07 15:30:04 +02:00
<svelte:component
this={control}
{componentInstance}
2020-05-21 15:28:32 +02:00
{...handlevalueKey(value)}
on:change={val => handleChange(key, val)}
onChange={val => handleChange(key, val)}
{...props}
name={key} />
2020-05-07 15:30:04 +02:00
</div>
2020-09-14 13:07:08 +02:00
{#if control === Input && !key.startsWith("_")}
<button data-cy={`${key}-binding-button`} on:click={dropdown.show}>
<Icon name="edit" />
</button>
{/if}
2020-05-07 15:30:04 +02:00
</div>
{#if control == Input}
<DropdownMenu
on:close={handleClose}
bind:this={dropdown}
{anchor}
align="right">
<BindingDropdown
{...handlevalueKey(value)}
close={dropdown.hide}
on:update={e => (temporaryBindableValue = e.detail)}
{bindableProperties} />
</DropdownMenu>
{/if}
2020-05-07 15:30:04 +02:00
<style>
.property-control {
position: relative;
2020-05-07 15:30:04 +02:00
display: flex;
flex-flow: row;
2020-08-05 15:19:56 +02:00
width: 260px;
2020-05-07 15:30:04 +02:00
margin: 8px 0px;
align-items: center;
2020-05-07 15:30:04 +02:00
}
.label {
2020-05-28 17:24:53 +02:00
display: flex;
align-items: center;
2020-05-07 15:30:04 +02:00
font-size: 12px;
font-weight: 400;
2020-08-05 15:19:56 +02:00
width: 100px;
2020-05-07 15:30:04 +02:00
text-align: left;
color: var(--ink);
margin-right: auto;
text-transform: capitalize;
2020-05-07 15:30:04 +02:00
}
.control {
flex: 1;
display: flex;
padding-left: 2px;
max-width: 164px;
2020-05-07 15:30:04 +02:00
}
button {
position: absolute;
background: none;
border: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: rgb(224, 224, 224);
right: 5px;
--spacing-s: 0;
}
2020-05-07 15:30:04 +02:00
</style>