Move lucene options into common file and add initial work on conditional UI components
This commit is contained in:
parent
616f4c1e45
commit
0c80e8c5b5
|
@ -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}
|
|
@ -5,6 +5,7 @@
|
|||
import ComponentSettingsSection from "./ComponentSettingsSection.svelte"
|
||||
import DesignSection from "./DesignSection.svelte"
|
||||
import CustomStylesSection from "./CustomStylesSection.svelte"
|
||||
import ConditionalUISection from "./ConditionalUISection.svelte"
|
||||
|
||||
$: componentInstance = $selectedComponent
|
||||
$: componentDefinition = store.actions.components.getDefinition(
|
||||
|
@ -19,6 +20,7 @@
|
|||
<ComponentSettingsSection {componentInstance} {componentDefinition} />
|
||||
<DesignSection {componentInstance} {componentDefinition} />
|
||||
<CustomStylesSection {componentInstance} {componentDefinition} />
|
||||
<ConditionalUISection {componentInstance} {componentDefinition} />
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
|
@ -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>
|
|
@ -11,44 +11,11 @@
|
|||
import { getBindableProperties } from "builderStore/dataBinding"
|
||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
import { generate } from "shortid"
|
||||
import { OperatorOptions, getValidOperatorsForType } from "helpers/lucene"
|
||||
|
||||
export let schemaFields
|
||||
export let value
|
||||
|
||||
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",
|
||||
},
|
||||
}
|
||||
const BannedTypes = ["link", "attachment"]
|
||||
$: bindableProperties = getBindableProperties(
|
||||
$currentAsset,
|
||||
|
@ -75,52 +42,6 @@
|
|||
value = value.filter(field => field.id !== id)
|
||||
}
|
||||
|
||||
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 []
|
||||
}
|
||||
|
||||
const onFieldChange = (expression, field) => {
|
||||
// Update the field type
|
||||
expression.type = schemaFields.find(x => x.name === field)?.type
|
||||
|
|
|
@ -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