Merge pull request #8371 from Budibase/bug/sev3/validate-datasource-config

Validate datasource config
This commit is contained in:
melohagan 2022-10-25 09:24:32 +01:00 committed by GitHub
commit 3ade5b4b65
5 changed files with 60 additions and 4 deletions

View File

@ -10,10 +10,14 @@
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte" import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
import { capitalise } from "helpers" import { capitalise } from "helpers"
import { IntegrationTypes } from "constants/backend" import { IntegrationTypes } from "constants/backend"
import { createValidationStore } from "helpers/validation/yup"
import { createEventDispatcher } from "svelte"
export let datasource export let datasource
export let schema export let schema
export let creating export let creating
const validation = createValidationStore()
const dispatch = createEventDispatcher()
function filter([key, value]) { function filter([key, value]) {
if (!value) { if (!value) {
@ -31,6 +35,17 @@
.filter(el => filter(el)) .filter(el => filter(el))
.map(([key]) => key) .map(([key]) => key)
// setup the validation for each required field
$: configKeys.forEach(key => {
if (schema[key].required) {
validation.addValidatorType(key, schema[key].type, schema[key].required)
}
})
// run the validation whenever the config changes
$: validation.check(config)
// dispatch the validation result
$: dispatch("valid", $validation.valid)
let addButton let addButton
function getDisplayName(key) { function getDisplayName(key) {
@ -79,6 +94,7 @@
type={schema[configKey].type} type={schema[configKey].type}
on:change on:change
bind:value={config[configKey]} bind:value={config[configKey]}
error={$validation.errors[configKey]}
/> />
</div> </div>
{:else} {:else}
@ -88,6 +104,7 @@
type={schema[configKey].type} type={schema[configKey].type}
on:change on:change
bind:value={config[configKey]} bind:value={config[configKey]}
error={$validation.errors[configKey]}
/> />
</div> </div>
{/if} {/if}

View File

@ -13,6 +13,7 @@
// kill the reference so the input isn't saved // kill the reference so the input isn't saved
let datasource = cloneDeep(integration) let datasource = cloneDeep(integration)
let skipFetch = false let skipFetch = false
let isValid = false
$: name = $: name =
IntegrationNames[datasource.type] || datasource.name || datasource.type IntegrationNames[datasource.type] || datasource.name || datasource.type
@ -53,6 +54,7 @@
return true return true
}} }}
size="L" size="L"
disabled={!isValid}
> >
<Layout noPadding> <Layout noPadding>
<Body size="XS" <Body size="XS"
@ -63,5 +65,6 @@
schema={datasource.schema} schema={datasource.schema}
bind:datasource bind:datasource
creating={true} creating={true}
on:valid={e => (isValid = e.detail)}
/> />
</ModalContent> </ModalContent>

View File

@ -17,7 +17,12 @@ export const convertCamel = str => {
export const pipe = (arg, funcs) => flow(funcs)(arg) export const pipe = (arg, funcs) => flow(funcs)(arg)
export const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1) export const capitalise = s => {
if (!s) {
return s
}
return s.substring(0, 1).toUpperCase() + s.substring(1)
}
export const lowercase = s => s.substring(0, 1).toLowerCase() + s.substring(1) export const lowercase = s => s.substring(0, 1).toLowerCase() + s.substring(1)

View File

@ -1,5 +1,5 @@
import { capitalise } from "helpers" import { capitalise } from "helpers"
import { object } from "yup" import { object, string, number } from "yup"
import { writable, get } from "svelte/store" import { writable, get } from "svelte/store"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
@ -20,6 +20,32 @@ export const createValidationStore = () => {
validator[propertyName] = propertyValidator validator[propertyName] = propertyValidator
} }
const addValidatorType = (propertyName, type, required) => {
if (!type || !propertyName) {
return
}
let propertyValidator
switch (type) {
case "number":
propertyValidator = number().transform(value =>
isNaN(value) ? undefined : value
)
break
case "email":
propertyValidator = string().email()
break
default:
propertyValidator = string()
}
if (required) {
propertyValidator = propertyValidator.required()
}
validator[propertyName] = propertyValidator
}
const check = async values => { const check = async values => {
const obj = object().shape(validator) const obj = object().shape(validator)
// clear the previous errors // clear the previous errors
@ -62,5 +88,6 @@ export const createValidationStore = () => {
set: validation.set, set: validation.set,
check, check,
addValidator, addValidator,
addValidatorType,
} }
} }

View File

@ -23,7 +23,8 @@
let importQueriesModal let importQueriesModal
let changed let changed,
isValid = true
let integration, baseDatasource, datasource let integration, baseDatasource, datasource
let queryList let queryList
const querySchema = { const querySchema = {
@ -101,12 +102,15 @@
<Divider /> <Divider />
<div class="config-header"> <div class="config-header">
<Heading size="S">Configuration</Heading> <Heading size="S">Configuration</Heading>
<Button disabled={!changed} cta on:click={saveDatasource}>Save</Button> <Button disabled={!changed || !isValid} cta on:click={saveDatasource}
>Save</Button
>
</div> </div>
<IntegrationConfigForm <IntegrationConfigForm
on:change={hasChanged} on:change={hasChanged}
schema={integration.datasource} schema={integration.datasource}
bind:datasource bind:datasource
on:valid={e => (isValid = e.detail)}
/> />
{#if datasource.plus} {#if datasource.plus}
<PlusConfigForm bind:datasource save={saveDatasource} /> <PlusConfigForm bind:datasource save={saveDatasource} />