|
|
|
@ -1,8 +1,9 @@ |
|
|
|
<script> |
|
|
|
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 { uuid } from "builderStore/uuid" |
|
|
|
import { writable } from "svelte/store" |
|
|
|
|
|
|
|
export let save |
|
|
|
export let datasource |
|
|
|
@ -14,16 +15,57 @@ |
|
|
|
let originalFromName = fromRelationship.name, |
|
|
|
originalToName = toRelationship.name |
|
|
|
|
|
|
|
function isValid(relationship) { |
|
|
|
if ( |
|
|
|
relationship.relationshipType === RelationshipTypes.MANY_TO_MANY && |
|
|
|
!relationship.through |
|
|
|
) { |
|
|
|
function inSchema(table, prop, ogName) { |
|
|
|
if (!table || !prop || prop === ogName) { |
|
|
|
return false |
|
|
|
} |
|
|
|
return ( |
|
|
|
relationship.name && relationship.tableId && relationship.relationshipType |
|
|
|
) |
|
|
|
const keys = Object.keys(table.schema).map(key => key.toLowerCase()) |
|
|
|
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 => ({ |
|
|
|
@ -33,7 +75,8 @@ |
|
|
|
$: fromTable = plusTables.find(table => table._id === toRelationship?.tableId) |
|
|
|
$: toTable = plusTables.find(table => table._id === fromRelationship?.tableId) |
|
|
|
$: 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 |
|
|
|
$: relationshipTypes = [ |
|
|
|
{ |
|
|
|
@ -155,32 +198,44 @@ |
|
|
|
<Select |
|
|
|
label="Select from table" |
|
|
|
options={tableOptions} |
|
|
|
on:change={() => ($touched.from = true)} |
|
|
|
bind:error={errors.from} |
|
|
|
bind:value={toRelationship.tableId} |
|
|
|
/> |
|
|
|
<Select |
|
|
|
label={"Select to table"} |
|
|
|
options={tableOptions} |
|
|
|
on:change={() => ($touched.to = true)} |
|
|
|
bind:error={errors.to} |
|
|
|
bind:value={fromRelationship.tableId} |
|
|
|
/> |
|
|
|
{#if fromRelationship?.relationshipType === RelationshipTypes.MANY_TO_MANY} |
|
|
|
<Select |
|
|
|
label={"Through"} |
|
|
|
options={tableOptions} |
|
|
|
on:change={() => ($touched.through = true)} |
|
|
|
bind:error={errors.through} |
|
|
|
bind:value={fromRelationship.through} |
|
|
|
/> |
|
|
|
{:else if toTable} |
|
|
|
<Select |
|
|
|
label={`Foreign Key (${toTable?.name})`} |
|
|
|
options={Object.keys(toTable?.schema)} |
|
|
|
on:change={() => ($touched.foreign = true)} |
|
|
|
bind:error={errors.foreign} |
|
|
|
bind:value={fromRelationship.fieldName} |
|
|
|
/> |
|
|
|
{/if} |
|
|
|
<div class="headings"> |
|
|
|
<Detail>Column names</Detail> |
|
|
|
</div> |
|
|
|
<Input label="From table column" bind:value={fromRelationship.name} /> |
|
|
|
<Input label="To table column" bind:value={toRelationship.name} /> |
|
|
|
<Body> |
|
|
|
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"> |
|
|
|
|
|
|
|
{#if originalFromName != null} |
|
|
|
<Button warning text on:click={deleteRelationship}>Delete</Button> |
|
|
|
{/if} |
|
|
|
|