1
0
Fork 0
mirror of synced 2024-06-13 16:05:06 +12:00
budibase/packages/builder/src/components/backend/DataTable/modals/JSONSchemaModal.svelte

153 lines
3.7 KiB
Svelte

<script>
import Editor from "components/integration/QueryEditor.svelte"
import {
ModalContent,
Tabs,
Tab,
Button,
Input,
Select,
Body,
Layout,
ActionButton,
} from "@budibase/bbui"
import { onMount, createEventDispatcher } from "svelte"
import { FIELDS } from "constants/backend"
import { generate } from "builderStore/schemaGenerator"
export let schema = {}
export let json
let dispatcher = createEventDispatcher()
let mode = "Form"
let fieldCount = 0
let fieldKeys = [],
fieldTypes = []
let keyValueOptions = [
{ label: "String", value: FIELDS.STRING.type },
{ label: "Number", value: FIELDS.NUMBER.type },
{ label: "Boolean", value: FIELDS.BOOLEAN.type },
{ label: "Object", value: FIELDS.JSON.type },
{ label: "Array", value: FIELDS.ARRAY.type },
]
let invalid = false
async function onJsonUpdate({ detail }) {
const input = detail.value
json = input
try {
// check json valid first
let inputJson = JSON.parse(input)
schema = generate(inputJson)
updateCounts()
invalid = false
} catch (err) {
// json not currently valid
invalid = true
}
}
function updateCounts() {
if (!schema) {
schema = {}
}
// find the entries which aren't in the list
const schemaEntries = Object.entries(schema).filter(
([key]) => !fieldKeys.includes(key)
)
for (let [key, value] of schemaEntries) {
fieldKeys.push(key)
fieldTypes.push(value.type)
}
fieldCount = fieldKeys.length
}
function saveSchema() {
const newSchema = {}
for (let [index, key] of fieldKeys.entries()) {
// they were added to schema, rather than generated
newSchema[key] = {
...schema[key],
type: fieldTypes[index],
}
}
dispatcher("save", { schema: newSchema, json })
schema = newSchema
}
function removeKey(index) {
const keyToRemove = fieldKeys[index]
if (fieldKeys[index + 1] != null) {
fieldKeys[index] = fieldKeys[index + 1]
fieldTypes[index] = fieldTypes[index + 1]
}
fieldKeys.splice(index, 1)
fieldTypes.splice(index, 1)
fieldCount--
if (json) {
try {
const parsed = JSON.parse(json)
delete parsed[keyToRemove]
json = JSON.stringify(parsed, null, 2)
} catch (err) {
// json not valid, ignore
}
}
}
onMount(() => {
updateCounts()
})
</script>
<ModalContent
title={"JSON Schema Editor"}
confirmText="Save Column"
onConfirm={saveSchema}
bind:disabled={invalid}
size="L"
>
<Tabs selected={mode} noPadding>
<Tab title="Form">
{#each Array(fieldCount) as _, i}
<div class="horizontal">
<Input outline label="Key" bind:value={fieldKeys[i]} />
<Select
label="Type"
options={keyValueOptions}
bind:value={fieldTypes[i]}
getOptionValue={field => field.value}
getOptionLabel={field => field.label}
/>
<ActionButton icon="Close" quiet on:click={() => removeKey(i)} />
</div>
{/each}
<div class:add-field-btn={fieldCount !== 0}>
<Button primary text on:click={() => fieldCount++}>Add Field</Button>
</div>
</Tab>
<Tab title="JSON">
<Layout noPadding gap="XS">
<Body size="S">
Provide a sample JSON blob here to automatically determine your
schema.
</Body>
<Editor mode="json" on:change={onJsonUpdate} value={json} />
</Layout>
</Tab>
</Tabs>
</ModalContent>
<style>
.horizontal {
display: grid;
grid-template-columns: 30% 1fr 40px;
grid-gap: var(--spacing-s);
align-items: end;
}
.add-field-btn {
margin-top: var(--spacing-xl);
}
</style>