|
1 | 1 | <script> |
2 | | - import { Select, Label, Combobox } from "@budibase/bbui" |
| 2 | + import { Select, Label, Multiselect } from "@budibase/bbui" |
3 | 3 | import { onMount } from "svelte" |
4 | 4 | import DrawerBindableInput from "@/components/common/bindings/DrawerBindableInput.svelte" |
5 | 5 | import { selectedScreen, componentStore } from "@/stores/builder" |
6 | 6 | import { getActionProviders, buildFormSchema } from "@/dataBinding" |
7 | 7 | import { findComponent } from "@/helpers/components" |
8 | 8 |
|
9 | | - export let parameters |
10 | | - export let bindings = [] |
11 | | - export let nested |
| 9 | + let { parameters, bindings = [], nested } = $props() |
12 | 10 |
|
13 | 11 | const typeOptions = [ |
14 | 12 | { |
|
21 | 19 | }, |
22 | 20 | ] |
23 | 21 |
|
24 | | - $: formComponent = getFormComponent( |
25 | | - $selectedScreen.props, |
26 | | - parameters.componentId |
| 22 | + const formComponent = $derived( |
| 23 | + getFormComponent($selectedScreen.props, parameters.componentId) |
27 | 24 | ) |
28 | | - $: formSchema = buildFormSchema(formComponent) |
29 | | - $: fieldOptions = Object.keys(formSchema || {}) |
30 | | - $: actionProviders = getActionProviders( |
31 | | - $selectedScreen, |
32 | | - $componentStore.selectedComponentId, |
33 | | - "ValidateForm", |
34 | | - { includeSelf: nested } |
| 25 | + const formSchema = $derived(buildFormSchema(formComponent)) |
| 26 | + const fieldOptions = $derived(Object.keys(formSchema || {})) |
| 27 | + const actionProviders = $derived( |
| 28 | + getActionProviders( |
| 29 | + $selectedScreen, |
| 30 | + $componentStore.selectedComponentId, |
| 31 | + "ValidateForm", |
| 32 | + { includeSelf: nested } |
| 33 | + ) |
35 | 34 | ) |
36 | 35 |
|
37 | 36 | const getFormComponent = (asset, id) => { |
|
51 | 50 | parameters.type = "set" |
52 | 51 | } |
53 | 52 | }) |
| 53 | +
|
| 54 | + const handleFieldChange = e => { |
| 55 | + // Convert from single field to multi-select format |
| 56 | + parameters.fields = e.detail || [] |
| 57 | + // Initialize fieldValues for new fields |
| 58 | + if (!parameters.fieldValues) { |
| 59 | + parameters.fieldValues = {} |
| 60 | + } |
| 61 | + } |
| 62 | +
|
| 63 | + const handleFieldValueChange = (fieldName, value) => { |
| 64 | + if (!parameters.fieldValues) { |
| 65 | + parameters.fieldValues = {} |
| 66 | + } |
| 67 | + parameters.fieldValues[fieldName] = value |
| 68 | + } |
54 | 69 | </script> |
55 | 70 |
|
56 | 71 | <div class="root"> |
|
67 | 82 | bind:value={parameters.type} |
68 | 83 | options={typeOptions} |
69 | 84 | /> |
70 | | - <Label small>Field</Label> |
71 | | - <Combobox bind:value={parameters.field} options={fieldOptions} /> |
72 | | - {#if parameters.type === "set"} |
73 | | - <Label small>Value</Label> |
74 | | - <DrawerBindableInput |
75 | | - title="Field value" |
76 | | - {bindings} |
77 | | - value={parameters.value} |
78 | | - on:change={e => (parameters.value = e.detail)} |
79 | | - /> |
| 85 | + <Label small>Fields</Label> |
| 86 | + <Multiselect |
| 87 | + value={parameters.fields || []} |
| 88 | + on:change={handleFieldChange} |
| 89 | + options={fieldOptions} |
| 90 | + placeholder={parameters.type === "reset" |
| 91 | + ? "Select fields to reset" |
| 92 | + : "Select fields to set"} |
| 93 | + /> |
| 94 | + {#if parameters.type === "set" && parameters.fields?.length > 0} |
| 95 | + <div class="field-values"> |
| 96 | + {#each parameters.fields as fieldName} |
| 97 | + <div class="field-value-pair"> |
| 98 | + <div class="label-col">{fieldName}</div> |
| 99 | + <div class="input-col"> |
| 100 | + <DrawerBindableInput |
| 101 | + title="Value for {fieldName}" |
| 102 | + {bindings} |
| 103 | + value={parameters.fieldValues?.[fieldName]} |
| 104 | + on:change={e => handleFieldValueChange(fieldName, e.detail)} |
| 105 | + /> |
| 106 | + </div> |
| 107 | + </div> |
| 108 | + {/each} |
| 109 | + </div> |
80 | 110 | {/if} |
81 | 111 | </div> |
82 | 112 |
|
|
85 | 115 | display: grid; |
86 | 116 | column-gap: var(--spacing-l); |
87 | 117 | row-gap: var(--spacing-s); |
88 | | - grid-template-columns: 60px 1fr; |
| 118 | + grid-template-columns: 90px 1fr; |
89 | 119 | align-items: center; |
90 | 120 | max-width: 400px; |
91 | 121 | margin: 0 auto; |
92 | 122 | } |
| 123 | +
|
| 124 | + .field-values { |
| 125 | + grid-column: 1 / -1; |
| 126 | + display: flex; |
| 127 | + flex-direction: column; |
| 128 | + gap: 0; |
| 129 | + overflow: hidden; |
| 130 | + border-top: 1px solid var(--spectrum-global-color-gray-200); |
| 131 | + border-bottom: 1px solid var(--spectrum-global-color-gray-200); |
| 132 | + } |
| 133 | +
|
| 134 | + .field-value-pair { |
| 135 | + display: grid; |
| 136 | + grid-template-columns: 130px 1fr; |
| 137 | + column-gap: var(--spacing-m); |
| 138 | + align-items: center; |
| 139 | + padding: var(--spacing-m) 0; |
| 140 | + border-bottom: 1px solid var(--spectrum-global-color-gray-200); |
| 141 | + } |
| 142 | +
|
| 143 | + .field-value-pair:last-child { |
| 144 | + border-bottom: none; |
| 145 | + } |
| 146 | +
|
| 147 | + .label-col { |
| 148 | + font-size: 13px; |
| 149 | + font-weight: 500; |
| 150 | + color: var(--spectrum-global-color-gray-700); |
| 151 | + padding: 0 var(--spacing-l); |
| 152 | + } |
| 153 | +
|
| 154 | + .input-col { |
| 155 | + padding: 0 var(--spacing-l) 0 0; |
| 156 | + } |
93 | 157 | </style> |
0 commit comments