diff --git a/frontend/src/lib/components/triggers/CaptureWrapper.svelte b/frontend/src/lib/components/triggers/CaptureWrapper.svelte index 5e42bac89c201..a9cf007f6f2e9 100644 --- a/frontend/src/lib/components/triggers/CaptureWrapper.svelte +++ b/frontend/src/lib/components/triggers/CaptureWrapper.svelte @@ -35,7 +35,7 @@ return false } - if (invalidRelations(args.publication.table_to_track, true) === true) { + if (invalidRelations(args.publication.table_to_track, true, true) === true) { return false } } diff --git a/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte index ca7e5071e5404..c4bc9abaae371 100644 --- a/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte +++ b/frontend/src/lib/components/triggers/postgres/PostgresTriggerEditorInner.svelte @@ -184,7 +184,7 @@ } async function updateTrigger(): Promise { - if (selectedTable === 'specific' && invalidRelations(relations, true) === true) { + if (selectedTable === 'specific' && invalidRelations(relations, true, true) === true) { return } if (edit) { @@ -333,12 +333,47 @@ disabled={!can_write} /> +
+

+ Pick a script or flow to be triggered +

+
+ + {#if script_path === undefined && is_flow === false} +
+ +
+ {/if} +
+
-

+

Pick a database to connect to

-
-
-

- Pick a script or flow to be triggered -

-
- - - {#if script_path === undefined && is_flow === false} -
- -
- {/if} -
-
{/if} diff --git a/frontend/src/lib/components/triggers/postgres/RelationPicker.svelte b/frontend/src/lib/components/triggers/postgres/RelationPicker.svelte index 5cd23d0d17876..ac76948b43c92 100644 --- a/frontend/src/lib/components/triggers/postgres/RelationPicker.svelte +++ b/frontend/src/lib/components/triggers/postgres/RelationPicker.svelte @@ -9,6 +9,7 @@ import { invalidRelations } from './utils' import AddPropertyFormV2 from '$lib/components/schema/AddPropertyFormV2.svelte' import Label from '$lib/components/Label.svelte' + import { emptyStringTrimmed, sendUserToast } from '$lib/utils' export let relations: Relations[] = [] export let selectedTable: 'all' | 'specific' @@ -49,46 +50,6 @@ - {#if selectedTable !== 'all'} -
- { - if (relations == undefined || !Array.isArray(relations)) { - relations = [] - relations = relations.concat({ - schema_name: 'public', - table_to_track: [] - }) - } else if (relations.length === 0) { - relations = relations.concat({ - schema_name: 'public', - table_to_track: [] - }) - } else if (invalidRelations(relations, true) === false) { - relations = relations.concat({ - schema_name: detail.name, - table_to_track: [] - }) - } - }} - > - - - - -
- {/if} {#if selectedTable !== 'all'} {#if relations && relations.length > 0} @@ -249,5 +210,43 @@ {/each} {/if} +
+ { + if (relations == undefined || !Array.isArray(relations)) { + relations = [] + relations = relations.concat({ + schema_name: 'public', + table_to_track: [] + }) + } else if (emptyStringTrimmed(detail.name)) { + sendUserToast('Schema name must not be empty', true) + } else { + const appendedRelations = relations.concat({ + schema_name: detail.name, + table_to_track: [] + }) + if (invalidRelations(appendedRelations, false, true) === false) { + relations = appendedRelations + } + } + }} + > + + + + +
{/if} diff --git a/frontend/src/lib/components/triggers/postgres/utils.ts b/frontend/src/lib/components/triggers/postgres/utils.ts index cffb0988848d8..7e9629a6b8ada 100644 --- a/frontend/src/lib/components/triggers/postgres/utils.ts +++ b/frontend/src/lib/components/triggers/postgres/utils.ts @@ -10,73 +10,90 @@ type RelationError = { schemaName?: string trackAllTablesInSchema: boolean trackSpecificColumnsInTable: boolean + duplicateSchemaName: boolean | undefined } -export function invalidRelations(relations: Relations[], showError?: boolean): boolean { - let result: RelationError = { +export function invalidRelations( + relations: Relations[], + trackSchemaTableError: boolean, + showError?: boolean +): boolean { + let error: RelationError = { schemaIndex: -1, tableIndex: -1, schemaError: false, tableError: false, trackAllTablesInSchema: false, - trackSpecificColumnsInTable: false + trackSpecificColumnsInTable: false, + duplicateSchemaName: undefined } + + const duplicateName: Set = new Set() + console.log(relations.length) for (const [schemaIndex, relation] of relations.entries()) { + error.schemaIndex = schemaIndex + 1 + error.schemaName = relation.schema_name if (emptyString(relation.schema_name)) { - result.schemaError = true - result.schemaIndex = schemaIndex + 1 + error.schemaError = true break } else { + if (duplicateName.has(relation.schema_name)) { + error.duplicateSchemaName = true + break + } + duplicateName.add(relation.schema_name) const tableToTrack = relation.table_to_track if (tableToTrack.length > 0) { for (const [tableIndex, table] of tableToTrack.entries()) { if (emptyString(table.table_name)) { - result.tableError = true - result.tableIndex = tableIndex + 1 - result.schemaName = relation.schema_name - result.schemaIndex = schemaIndex + 1 + error.tableError = true + error.tableIndex = tableIndex + 1 break } if ( - !result.trackSpecificColumnsInTable && + !error.trackSpecificColumnsInTable && table.columns_name && table.columns_name.length > 0 ) { - result.trackSpecificColumnsInTable = true + error.trackSpecificColumnsInTable = true } } - if (result.tableError) { + if (error.tableError) { break } - } else if (!result.trackAllTablesInSchema) { - result.trackAllTablesInSchema = true + } else if (!error.trackAllTablesInSchema) { + error.trackAllTablesInSchema = true } - if (result.trackAllTablesInSchema && result.trackSpecificColumnsInTable) { + if ( + trackSchemaTableError && + error.trackAllTablesInSchema && + error.trackSpecificColumnsInTable + ) { break } } } + const errorFound = + error.tableError || + error.schemaError || + error.duplicateSchemaName || + (trackSchemaTableError && error.trackAllTablesInSchema && error.trackSpecificColumnsInTable) + if (showError && errorFound) { + let errorMessage: string = '' - const error = - result.tableError || - result.schemaError || - (result.trackAllTablesInSchema && result.trackSpecificColumnsInTable) - if (showError) { - if (error === true) { - let errorMessage: string = '' - - if (result.schemaError) { - errorMessage = `Schema Error: Please enter a name for schema number ${result.schemaIndex}` - } else if (result.tableError) { - errorMessage = `Table Error: Please enter a name for table number ${result.tableIndex} inside schema number ${result.schemaIndex}` - errorMessage += emptyString(result.schemaName) ? '' : ` named: ${result.schemaName}` - } else { - errorMessage = - 'Configuration Error: Schema-level tracking and specific table tracking with column selection cannot be used together. Refer to the documentation for valid configurations.' - } - sendUserToast(errorMessage, true) + if (error.schemaError) { + errorMessage = `Schema Error: Please enter a name for schema number ${error.schemaIndex}` + } else if (error.tableError) { + errorMessage = `Table Error: Please enter a name for table number ${error.tableIndex} inside schema number ${error.schemaIndex}` + errorMessage += emptyString(error.schemaName) ? '' : ` named: ${error.schemaName}` + } else if (error.duplicateSchemaName) { + errorMessage = `Schema Error: schema name '${error.schemaName}' is already taken` + } else { + errorMessage = + 'Configuration Error: Schema-level tracking and specific table tracking with column selection cannot be used together. Refer to the documentation for valid configurations.' } + sendUserToast(errorMessage, true) } - return error + return errorFound }