Merge pull request #8371 from Budibase/bug/sev3/validate-datasource-config
Validate datasource config
This commit is contained in:
commit
3ade5b4b65
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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} />
|
||||||
|
|
Loading…
Reference in New Issue