mirror of https://github.com/Budibase/budibase.git
5 changed files with 277 additions and 80 deletions
@ -0,0 +1,38 @@ |
|||
<script> |
|||
import { DetailSummary, ActionButton, Drawer, Button } from "@budibase/bbui" |
|||
// import { store } from "builderStore" |
|||
import ConditionalUIDrawer from "./PropertyControls/ConditionalUIDrawer.svelte" |
|||
|
|||
export let componentInstance |
|||
|
|||
let tempValue |
|||
let drawer |
|||
|
|||
const openDrawer = () => { |
|||
tempValue = componentInstance?._conditions |
|||
drawer.show() |
|||
} |
|||
|
|||
const save = () => { |
|||
// store.actions.components.updateCustomStyle(tempValue) |
|||
drawer.hide() |
|||
} |
|||
</script> |
|||
|
|||
<DetailSummary |
|||
name={`Conditions${componentInstance?._conditions ? " *" : ""}`} |
|||
collapsible={false} |
|||
> |
|||
<div> |
|||
<ActionButton on:click={openDrawer}>Configure conditions</ActionButton> |
|||
</div> |
|||
</DetailSummary> |
|||
{#key componentInstance?._id} |
|||
<Drawer bind:this={drawer} title="Conditions"> |
|||
<svelte:fragment slot="description"> |
|||
Show, hide and update components in response to conditions being met. |
|||
</svelte:fragment> |
|||
<Button cta slot="buttons" on:click={save}>Save</Button> |
|||
<ConditionalUIDrawer slot="body" bind:conditions={tempValue} /> |
|||
</Drawer> |
|||
{/key} |
|||
@ -0,0 +1,156 @@ |
|||
<script> |
|||
import { Button, Icon, DrawerContent, Layout, Select } from "@budibase/bbui" |
|||
import { flip } from "svelte/animate" |
|||
import { dndzone } from "svelte-dnd-action" |
|||
import { generate } from "shortid" |
|||
import DrawerBindableInput from "../../../common/bindings/DrawerBindableInput.svelte" |
|||
import ColorPicker from "./ColorPicker.svelte" |
|||
import { OperatorOptions, getValidOperatorsForType } from "helpers/lucene" |
|||
import { getBindableProperties } from "../../../../builderStore/dataBinding" |
|||
import { currentAsset, store } from "../../../../builderStore" |
|||
|
|||
export let conditions = [] |
|||
|
|||
const flipDurationMs = 150 |
|||
const actionOptions = [ |
|||
{ |
|||
label: "Show component", |
|||
value: "show", |
|||
}, |
|||
{ |
|||
label: "Hide component", |
|||
value: "hide", |
|||
}, |
|||
{ |
|||
label: "Update component setting", |
|||
value: "update", |
|||
}, |
|||
] |
|||
|
|||
$: operatorOptions = getValidOperatorsForType("string") |
|||
$: bindableProperties = getBindableProperties( |
|||
$currentAsset, |
|||
$store.selectedComponentId |
|||
) |
|||
$: conditions.forEach(link => { |
|||
if (!link.id) { |
|||
link.id = generate() |
|||
} |
|||
}) |
|||
|
|||
const addCondition = () => { |
|||
conditions = [ |
|||
...conditions, |
|||
{ |
|||
action: "show", |
|||
operator: OperatorOptions.Equals.value, |
|||
}, |
|||
] |
|||
} |
|||
|
|||
const removeLink = id => { |
|||
conditions = conditions.filter(link => link.id !== id) |
|||
} |
|||
|
|||
const updateLinks = e => { |
|||
conditions = e.detail.items |
|||
} |
|||
</script> |
|||
|
|||
<DrawerContent> |
|||
<div class="container"> |
|||
<Layout noPadding> |
|||
{#if conditions?.length} |
|||
<div |
|||
class="conditions" |
|||
use:dndzone={{ |
|||
items: conditions, |
|||
flipDurationMs, |
|||
dropTargetStyle: { outline: "none" }, |
|||
}} |
|||
on:finalize={updateLinks} |
|||
on:consider={updateLinks} |
|||
> |
|||
{#each conditions as condition (condition.id)} |
|||
<div class="condition" animate:flip={{ duration: flipDurationMs }}> |
|||
<Select |
|||
placeholder={null} |
|||
options={actionOptions} |
|||
bind:value={condition.action} |
|||
/> |
|||
{#if condition.action === "update"} |
|||
<Select options={["Color"]} bind:value={condition.setting} /> |
|||
<div>TO</div> |
|||
<ColorPicker |
|||
on:change={e => (condition.settingValue = e.detail)} |
|||
value={condition.settingValue} |
|||
/> |
|||
{/if} |
|||
<div>IF</div> |
|||
<DrawerBindableInput |
|||
bindings={bindableProperties} |
|||
placeholder="Value" |
|||
value={condition.newValue} |
|||
on:change={e => (condition.newValue = e.detail)} |
|||
/> |
|||
<Select |
|||
placeholder={null} |
|||
options={operatorOptions} |
|||
bind:value={condition.operator} |
|||
/> |
|||
<DrawerBindableInput |
|||
bindings={bindableProperties} |
|||
placeholder="Value" |
|||
value={condition.referenceValue} |
|||
on:change={e => (condition.referenceValue = e.detail)} |
|||
/> |
|||
<Icon |
|||
name="Close" |
|||
hoverable |
|||
size="S" |
|||
on:click={() => removeLink(condition.id)} |
|||
/> |
|||
</div> |
|||
{/each} |
|||
</div> |
|||
{/if} |
|||
<div class="button-container"> |
|||
<Button secondary icon="Add" on:click={addCondition}> |
|||
Add condition |
|||
</Button> |
|||
</div> |
|||
</Layout> |
|||
</div> |
|||
</DrawerContent> |
|||
|
|||
<style> |
|||
.container { |
|||
width: 100%; |
|||
max-width: 1200px; |
|||
} |
|||
.conditions { |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: flex-start; |
|||
align-items: stretch; |
|||
gap: var(--spacing-s); |
|||
} |
|||
.condition { |
|||
gap: var(--spacing-l); |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
border-radius: var(--border-radius-s); |
|||
transition: background-color ease-in-out 130ms; |
|||
} |
|||
.condition:hover { |
|||
background-color: var(--spectrum-global-color-gray-100); |
|||
} |
|||
.condition > :global(.spectrum-Form-item) { |
|||
flex: 1 1 auto; |
|||
width: 0; |
|||
} |
|||
.button-container { |
|||
} |
|||
</style> |
|||
@ -0,0 +1,80 @@ |
|||
export const OperatorOptions = { |
|||
Equals: { |
|||
value: "equal", |
|||
label: "Equals", |
|||
}, |
|||
NotEquals: { |
|||
value: "notEqual", |
|||
label: "Not equals", |
|||
}, |
|||
Empty: { |
|||
value: "empty", |
|||
label: "Is empty", |
|||
}, |
|||
NotEmpty: { |
|||
value: "notEmpty", |
|||
label: "Is not empty", |
|||
}, |
|||
StartsWith: { |
|||
value: "string", |
|||
label: "Starts with", |
|||
}, |
|||
Like: { |
|||
value: "fuzzy", |
|||
label: "Like", |
|||
}, |
|||
MoreThan: { |
|||
value: "rangeLow", |
|||
label: "More than", |
|||
}, |
|||
LessThan: { |
|||
value: "rangeHigh", |
|||
label: "Less than", |
|||
}, |
|||
} |
|||
|
|||
export const getValidOperatorsForType = type => { |
|||
const Op = OperatorOptions |
|||
if (type === "string") { |
|||
return [ |
|||
Op.Equals, |
|||
Op.NotEquals, |
|||
Op.StartsWith, |
|||
Op.Like, |
|||
Op.Empty, |
|||
Op.NotEmpty, |
|||
] |
|||
} else if (type === "number") { |
|||
return [ |
|||
Op.Equals, |
|||
Op.NotEquals, |
|||
Op.MoreThan, |
|||
Op.LessThan, |
|||
Op.Empty, |
|||
Op.NotEmpty, |
|||
] |
|||
} else if (type === "options") { |
|||
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] |
|||
} else if (type === "boolean") { |
|||
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] |
|||
} else if (type === "longform") { |
|||
return [ |
|||
Op.Equals, |
|||
Op.NotEquals, |
|||
Op.StartsWith, |
|||
Op.Like, |
|||
Op.Empty, |
|||
Op.NotEmpty, |
|||
] |
|||
} else if (type === "datetime") { |
|||
return [ |
|||
Op.Equals, |
|||
Op.NotEquals, |
|||
Op.MoreThan, |
|||
Op.LessThan, |
|||
Op.Empty, |
|||
Op.NotEmpty, |
|||
] |
|||
} |
|||
return [] |
|||
} |
|||
Loading…
Reference in new issue