Adding validation to the SQL relationship creation modal.

This commit is contained in:
mike12345567 2021-07-06 12:58:36 +01:00
parent 6a8fd12805
commit 478a851956
1 changed files with 67 additions and 12 deletions

View File

@ -1,8 +1,9 @@
<script> <script>
import { RelationshipTypes } from "constants/backend" import { RelationshipTypes } from "constants/backend"
import { Button, Input, ModalContent, Select, Detail } from "@budibase/bbui" import { Button, Input, ModalContent, Select, Detail, Body } from "@budibase/bbui"
import { tables } from "stores/backend" import { tables } from "stores/backend"
import { uuid } from "builderStore/uuid" import { uuid } from "builderStore/uuid"
import { writable } from "svelte/store"
export let save export let save
export let datasource export let datasource
@ -14,16 +15,57 @@
let originalFromName = fromRelationship.name, let originalFromName = fromRelationship.name,
originalToName = toRelationship.name originalToName = toRelationship.name
function isValid(relationship) { function inSchema(table, prop, ogName) {
if ( if (!table || !prop || prop === ogName) {
relationship.relationshipType === RelationshipTypes.MANY_TO_MANY &&
!relationship.through
) {
return false return false
} }
return ( const keys = Object.keys(table.schema).map(key => key.toLowerCase())
relationship.name && relationship.tableId && relationship.relationshipType return keys.indexOf(prop.toLowerCase()) !== -1
) }
const touched = writable({})
function checkForErrors(fromTable, toTable, throughTable, fromRelate, toRelate) {
const isMany = fromRelate.relationshipType === RelationshipTypes.MANY_TO_MANY
const tableNotSet = "Please specify a table"
const errors = {}
if ($touched.from && !fromTable) {
errors.from = tableNotSet
}
if ($touched.to && !toTable) {
errors.to = tableNotSet
}
if ($touched.through && isMany && !fromRelate.through) {
errors.through = tableNotSet
}
if ($touched.foreign && !isMany && !fromRelate.fieldName) {
errors.foreign = "Please pick the foreign key"
}
const colNotSet = "Please specify a column name"
if ($touched.fromCol && !fromRelate.name) {
errors.fromCol = colNotSet
}
if ($touched.toCol && !toRelate.name) {
errors.toCol = colNotSet
}
const tableError = "From/to/through tables must be different"
if (fromTable && (fromTable === toTable || fromTable === throughTable)) {
errors.from = tableError
}
if (toTable && (toTable === fromTable || toTable === throughTable)) {
errors.to = tableError
}
if (throughTable && (throughTable === fromTable || throughTable === toTable)) {
errors.through = tableError
}
const colError = "Column name cannot be an existing column"
if (inSchema(fromTable, fromRelate.name, originalFromName)) {
errors.fromCol = colError
}
if (inSchema(toTable, toRelate.name, originalToName)) {
errors.toCol = colError
}
return errors
} }
$: tableOptions = plusTables.map(table => ({ $: tableOptions = plusTables.map(table => ({
@ -33,7 +75,8 @@
$: fromTable = plusTables.find(table => table._id === toRelationship?.tableId) $: fromTable = plusTables.find(table => table._id === toRelationship?.tableId)
$: toTable = plusTables.find(table => table._id === fromRelationship?.tableId) $: toTable = plusTables.find(table => table._id === fromRelationship?.tableId)
$: through = plusTables.find(table => table._id === fromRelationship?.through) $: through = plusTables.find(table => table._id === fromRelationship?.through)
$: valid = toTable && fromTable && isValid(fromRelationship) $: errors = checkForErrors(fromTable, toTable, through, fromRelationship, toRelationship)
$: valid = Object.keys(errors).length === 0 && Object.keys($touched).length !== 0
$: linkTable = through || toTable $: linkTable = through || toTable
$: relationshipTypes = [ $: relationshipTypes = [
{ {
@ -155,32 +198,44 @@
<Select <Select
label="Select from table" label="Select from table"
options={tableOptions} options={tableOptions}
on:change={() => ($touched.from = true)}
bind:error={errors.from}
bind:value={toRelationship.tableId} bind:value={toRelationship.tableId}
/> />
<Select <Select
label={"Select to table"} label={"Select to table"}
options={tableOptions} options={tableOptions}
on:change={() => ($touched.to = true)}
bind:error={errors.to}
bind:value={fromRelationship.tableId} bind:value={fromRelationship.tableId}
/> />
{#if fromRelationship?.relationshipType === RelationshipTypes.MANY_TO_MANY} {#if fromRelationship?.relationshipType === RelationshipTypes.MANY_TO_MANY}
<Select <Select
label={"Through"} label={"Through"}
options={tableOptions} options={tableOptions}
on:change={() => ($touched.through = true)}
bind:error={errors.through}
bind:value={fromRelationship.through} bind:value={fromRelationship.through}
/> />
{:else if toTable} {:else if toTable}
<Select <Select
label={`Foreign Key (${toTable?.name})`} label={`Foreign Key (${toTable?.name})`}
options={Object.keys(toTable?.schema)} options={Object.keys(toTable?.schema)}
on:change={() => ($touched.foreign = true)}
bind:error={errors.foreign}
bind:value={fromRelationship.fieldName} bind:value={fromRelationship.fieldName}
/> />
{/if} {/if}
<div class="headings"> <div class="headings">
<Detail>Column names</Detail> <Detail>Column names</Detail>
</div> </div>
<Input label="From table column" bind:value={fromRelationship.name} /> <Body>
<Input label="To table column" bind:value={toRelationship.name} /> Budibase manages SQL relationships as a new column in the table, please provide a name for these columns.
</Body>
<Input on:blur={() => ($touched.fromCol = true)} bind:error={errors.fromCol} label="From table column" bind:value={fromRelationship.name} />
<Input on:blur={() => ($touched.toCol = true)} bind:error={errors.toCol} label="To table column" bind:value={toRelationship.name} />
<div slot="footer"> <div slot="footer">
{#if originalFromName != null} {#if originalFromName != null}
<Button warning text on:click={deleteRelationship}>Delete</Button> <Button warning text on:click={deleteRelationship}>Delete</Button>
{/if} {/if}