mirror of https://github.com/Budibase/budibase.git
4 changed files with 200 additions and 101 deletions
@ -1,5 +1,72 @@ |
|||
<script> |
|||
import { Select, Label } from "@budibase/bbui" |
|||
import { store, backendUiStore } from "builderStore" |
|||
import fetchBindableProperties from "builderStore/fetchBindableProperties" |
|||
import SaveFields from "./SaveFields.svelte" |
|||
|
|||
export let parameters |
|||
|
|||
$: bindableProperties = fetchBindableProperties({ |
|||
componentInstanceId: $store.currentComponentInfo._id, |
|||
components: $store.components, |
|||
screen: $store.currentPreviewItem, |
|||
models: $backendUiStore.models, |
|||
}) |
|||
|
|||
// just wraps binding in {{ ... }} |
|||
const toBindingExpression = bindingPath => `{{ ${bindingPath} }}` |
|||
|
|||
const modelFields = modelId => { |
|||
const model = $backendUiStore.models.find(m => m._id === modelId) |
|||
|
|||
return Object.keys(model.schema) |
|||
} |
|||
|
|||
$: fieldNames = |
|||
parameters && parameters.modelId ? modelFields(parameters.modelId) : [] |
|||
|
|||
const onFieldsChanged = e => { |
|||
parameters.fields = e.detail |
|||
} |
|||
</script> |
|||
|
|||
<div>Create Record</div> |
|||
<div class="root"> |
|||
<Label size="m" color="dark">Table</Label> |
|||
<Select secondary bind:value={parameters.modelId}> |
|||
<option value="" /> |
|||
{#each $backendUiStore.models as model} |
|||
<option value={model._id}>{model.name}</option> |
|||
{/each} |
|||
</Select> |
|||
|
|||
{#if parameters.modelId} |
|||
<SaveFields |
|||
parameterFields={parameters.fields} |
|||
schemaFields={fieldNames} |
|||
on:fieldschanged={onFieldsChanged} /> |
|||
{/if} |
|||
|
|||
</div> |
|||
|
|||
<style> |
|||
.root { |
|||
display: grid; |
|||
column-gap: var(--spacing-s); |
|||
row-gap: var(--spacing-s); |
|||
grid-template-columns: auto 1fr auto 1fr auto; |
|||
align-items: baseline; |
|||
} |
|||
|
|||
.root :global(.relative:nth-child(2)) { |
|||
grid-column-start: 2; |
|||
grid-column-end: 6; |
|||
} |
|||
|
|||
.cannot-use { |
|||
color: var(--red); |
|||
font-size: var(--font-size-s); |
|||
text-align: center; |
|||
width: 70%; |
|||
margin: auto; |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,115 @@ |
|||
<script> |
|||
import { Select, Label, TextButton, Spacer } from "@budibase/bbui" |
|||
import { store, backendUiStore } from "builderStore" |
|||
import fetchBindableProperties from "builderStore/fetchBindableProperties" |
|||
import { CloseCircleIcon, AddIcon } from "components/common/icons" |
|||
import { |
|||
readableToRuntimeBinding, |
|||
runtimeToReadableBinding, |
|||
} from "builderStore/replaceBindings" |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
|
|||
export let parameterFields |
|||
export let schemaFields |
|||
|
|||
const emptyField = () => ({ name: "", value: "" }) |
|||
|
|||
// this statement initialises fields from parameters.fields |
|||
$: fields = |
|||
fields || |
|||
Object.keys(parameterFields || { "": "" }).map(name => ({ |
|||
name, |
|||
value: |
|||
(parameterFields && |
|||
runtimeToReadableBinding( |
|||
bindableProperties, |
|||
parameterFields[name] |
|||
)) || |
|||
"", |
|||
})) |
|||
|
|||
$: bindableProperties = fetchBindableProperties({ |
|||
componentInstanceId: $store.currentComponentInfo._id, |
|||
components: $store.components, |
|||
screen: $store.currentPreviewItem, |
|||
models: $backendUiStore.models, |
|||
}) |
|||
|
|||
const addField = () => { |
|||
const newFields = fields.filter(f => f.name) |
|||
newFields.push(emptyField()) |
|||
fields = newFields |
|||
rebuildParameters() |
|||
} |
|||
|
|||
const removeField = field => () => { |
|||
fields = fields.filter(f => f !== field) |
|||
rebuildParameters() |
|||
} |
|||
|
|||
const rebuildParameters = () => { |
|||
// rebuilds paramters.fields every time a field name or value is added |
|||
const newParameterFields = {} |
|||
for (let field of fields) { |
|||
if (field.name) { |
|||
newParameterFields[field.name] = readableToRuntimeBinding( |
|||
bindableProperties, |
|||
field.value |
|||
) |
|||
} |
|||
} |
|||
dispatch("fieldschanged", newParameterFields) |
|||
} |
|||
|
|||
// just wraps binding in {{ ... }} |
|||
const toBindingExpression = bindingPath => `{{ ${bindingPath} }}` |
|||
</script> |
|||
|
|||
{#if fields} |
|||
{#each fields as field} |
|||
<Label size="m" color="dark">Field</Label> |
|||
<Select secondary bind:value={field.name} on:blur={rebuildParameters}> |
|||
<option value="" /> |
|||
{#each schemaFields as fieldName} |
|||
<option value={fieldName}>{fieldName}</option> |
|||
{/each} |
|||
</Select> |
|||
<Label size="m" color="dark">Value</Label> |
|||
<Select |
|||
editable |
|||
secondary |
|||
bind:value={field.value} |
|||
on:blur={rebuildParameters}> |
|||
<option value="" /> |
|||
{#each bindableProperties as bindableProp} |
|||
<option value={toBindingExpression(bindableProp.readableBinding)}> |
|||
{bindableProp.readableBinding} |
|||
</option> |
|||
{/each} |
|||
</Select> |
|||
<div class="remove-field-container"> |
|||
<TextButton text small on:click={removeField(field)}> |
|||
<CloseCircleIcon /> |
|||
</TextButton> |
|||
</div> |
|||
{/each} |
|||
|
|||
<div> |
|||
<Spacer small /> |
|||
|
|||
<TextButton text small blue on:click={addField}> |
|||
Add Field |
|||
<div style="height: 20px; width: 20px;"> |
|||
<AddIcon /> |
|||
</div> |
|||
</TextButton> |
|||
</div> |
|||
{/if} |
|||
|
|||
<style> |
|||
.remove-field-container :global(button) { |
|||
vertical-align: bottom; |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue