From a50ff96629c2c7d421ae28e158743806e54a6916 Mon Sep 17 00:00:00 2001 From: Indra Date: Mon, 8 Nov 2021 20:46:08 +0530 Subject: [PATCH] Dbz 4146 (#399) * use backend call to get the transform list * update * removed mock data * Adding api error handling * Review fix --- .../src/connector/connector.service.ts | 10 + .../ui/assets/mockResponse/transform.json | 214 ------------------ .../transformHelpers/TransformCard.tsx | 2 + .../transformHelpers/TransformConfig.tsx | 7 +- .../CreateConnectorComponent.tsx | 1 + .../connectorSteps/TransformsStep.tsx | 207 +++++++++-------- ui/packages/ui/src/app/shared/Utils.ts | 14 +- ui/packages/ui/src/locales/en/public.json | 38 ++-- ui/packages/ui/src/locales/it/public.json | 38 ++-- 9 files changed, 176 insertions(+), 355 deletions(-) delete mode 100644 ui/packages/ui/assets/mockResponse/transform.json diff --git a/ui/packages/services/src/connector/connector.service.ts b/ui/packages/services/src/connector/connector.service.ts index ba03c2b7..0ae7eaea 100644 --- a/ui/packages/services/src/connector/connector.service.ts +++ b/ui/packages/services/src/connector/connector.service.ts @@ -189,4 +189,14 @@ export class ConnectorService extends BaseService { return this.httpPost(endpoint, body); } + /** + * Get the transform list and their properties for supplied clusterId + */ + public getTransform(clusterId: number): Promise { + this.logger?.info("[ConnectorService] Getting the list of transform."); + + const endpoint: string = this.endpoint("/:clusterId/transforms.json", { clusterId }); + return this.httpGet(endpoint); + } + } diff --git a/ui/packages/ui/assets/mockResponse/transform.json b/ui/packages/ui/assets/mockResponse/transform.json deleted file mode 100644 index 6b4085c0..00000000 --- a/ui/packages/ui/assets/mockResponse/transform.json +++ /dev/null @@ -1,214 +0,0 @@ -[ - { - "transform": "io.debezium.transforms.Filter", - "enabled": true, - "configurationOptions": [ - { - "description": "An optional regular expression that evaluates the name of the destination topic for an event to determine whether to apply filtering logic.", - "displayName": "Regex", - "isMandatory": false, - "name": "topic.regex", - "type": "STRING" - }, - { - "description": "The language in which the expression is written. Must begin with jsr223., for example, jsr223.groovy, or jsr223.graal.js. Debezium supports bootstrapping through the JSR 223 API ('ScriptingfortheJava™Platform') only.", - "displayName": "Language", - "isMandatory": true, - "name": "language", - "allowedValues": ["jsr223.groovy", "jsr223.graal.js"], - "type": "STRING" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Condition", - "isMandatory": true, - "name": "condition", - "type": "STRING" - }, - { - "description": "Specifies how the transformation handles null (tombstone) messages.", - "displayName": "Null handler", - "isMandatory": true, - "name": "null.handling.mode", - "allowedValues": ["keep", "drop", "evaluate"], - "defaultValue": "keep", - "type": "STRING" - } - ] - }, - { - "transform": "io.debezium.transforms.ContentBasedRouter", - "enabled": true, - "configurationOptions": [ - { - "description": "An optional regular expression that evaluates the name of the destination topic for an event to determine whether to apply filtering logic.", - "displayName": "Regex", - "isMandatory": false, - "name": "topic.regex", - "type": "STRING" - }, - { - "description": "The language in which the expression is written. Must begin with jsr223., for example, jsr223.groovy, or jsr223.graal.js. Debezium supports bootstrapping through the JSR 223 API ('ScriptingfortheJava™Platform') only.", - "displayName": "Language", - "isMandatory": true, - "name": "language", - "allowedValues": ["jsr223.groovy", "jsr223.graal.js"], - "type": "STRING" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Condition", - "isMandatory": true, - "name": "condition", - "type": "STRING" - }, - { - "description": "Specifies how the transformation handles null (tombstone) messages.", - "displayName": "Null handler", - "isMandatory": true, - "name": "null.handling.mode", - "allowedValues": ["keep", "drop", "evaluate"], - "defaultValue": "keep", - "type": "STRING" - } - ] - }, - { - "transform": "io.debezium.transforms.ExtractNewRecordState", - "enabled": true, - "configurationOptions": [ - { - "description": "Debezium generates a change event record for each DELETE operation. The default behavior is that event flattening SMT removes these records from the stream.", - "displayName": "Delete handling", - "isMandatory": true, - "name": "delete.handling​.mode", - "defaultValue": "drop", - "allowedValues": ["drop", "none", "rewrite"], - "type": "STRING" - }, - { - "description": "Debezium generates a tombstone record for each DELETE operation. To keep tombstone records in the stream, specify drop.tombstones=false", - "displayName": "Drop tombstone", - "isMandatory": false, - "defaultValue": true, - "name": "drop.tombstones", - "type": "BOOLEAN" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Fields prefix", - "isMandatory": false, - "defaultValue": "__", - "name": "add.fields.prefix", - "type": "STRING" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Fields", - "isMandatory": false, - "name": "add.fields", - "type": "STRING" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Header prefix", - "isMandatory": false, - "defaultValue": "__", - "name": "add.headers.prefix", - "type": "STRING" - }, - { - "description": "The expression to be evaluated for every message. Must evaluate to a Boolean value where a result of true keeps the message, and a result of false removes it.", - "displayName": "Header", - "isMandatory": false, - "name": "add.headers", - "type": "STRING" - } - ] - }, - { - "transform": "io.debezium.transforms.ByLogicalTableRouter", - "enabled": true, - "configurationOptions": [ - { - "description": "Specifies a regular expression that the transformation applies to each change event record to determine if it should be routed to a particular topic.", - "displayName": "Topic regex", - "isMandatory": true, - "name": "topic.regex", - "type": "STRING" - }, - { - "description": "Specifies a regular expression that represents the destination topic name.", - "displayName": "Topic replacement", - "isMandatory": true, - "name": "topic.replacement", - "type": "STRING" - }, - { - "description": "Indicates whether to add a field to the record’s change event key.", - "displayName": "Enforce key uniqueness", - "isMandatory": false, - "defaultValue": true, - "name": "key.enforce​.uniqueness", - "type": "BOOLEAN" - }, - { - "description": "Name of a field to be added to the change event key", - "displayName": "key field name", - "isMandatory": false, - "defaultValue": "__dbz__physicalTableIdentifier", - "name": "key.field.name", - "type": "STRING" - }, - { - "description": "Specifies a regular expression that the transformation applies to the default destination topic name to capture one or more groups of characters.", - "displayName": "Key fields regex", - "isMandatory": false, - "name": "key.field.regex", - "type": "STRING" - }, - { - "description": "Specifies a regular expression for determining the value of the inserted key field in terms of the groups captured by the expression specified for key.", - "displayName": "key fields replacement", - "isMandatory": false, - "name": "key.field.replacement", - "type": "STRING" - } - ] - }, - { - "transform": "org.apache.kafka.connect.transforms.ValueToKey", - "enabled": true, - "configurationOptions": [ - { - "description": "Replace the record key with a new key formed from a subset of fields in the record value.", - "displayName": "Fields", - "isMandatory": true, - "name": "fields", - "type": "STRING" - } - ] - }, - { - "transform": "org.apache.kafka.connect.transforms.TimestampRoute", - "enabled": true, - "configurationOptions": [ - { - "description": "Format string for the timestamp that is compatible with java.text.SimpleDateFormat. For additional details, see SimpleDateFormat.", - "displayName": "Timestamp format", - "isMandatory": true, - "defaultValue": "yyyyMMdd", - "name": "timestamp.format", - "type": "STRING" - }, - { - "description": "Format string which can contain ${topic} and ${timestamp} as placeholders for the topic and timestamp, respectively.", - "displayName": "Topic format", - "isMandatory": true, - "defaultValue": "${topic}-${timestamp}", - "name": "topic.format", - "type": "STRING" - } - ] - } -] diff --git a/ui/packages/ui/src/app/components/transformHelpers/TransformCard.tsx b/ui/packages/ui/src/app/components/transformHelpers/TransformCard.tsx index d5da511f..90bb49c0 100644 --- a/ui/packages/ui/src/app/components/transformHelpers/TransformCard.tsx +++ b/ui/packages/ui/src/app/components/transformHelpers/TransformCard.tsx @@ -227,7 +227,9 @@ export const TransformCard = React.forwardRef((props, )} + {t('deleteTransform')}}> - - ) : ( - <> - - -

- } - /> - - - {Array.from(transforms.keys()).map((key, index) => { - return ( - - ); - })} - - - - - + } + errorChildren={} + > + {() => ( +
+ {transforms.size === 0 ? ( + + + + {t('noTransformAdded')} + + + + + + + ) : ( + <> + + +

+ } + /> + + + {Array.from(transforms.keys()).map((key, index) => { + return ( + + ); + })} + + + + + + )} + + {t('confirm')} + , + + ]} + > + {t('deleteTransformMsg')} + +
)} - - {t('confirm')} - , - - ]} - > - {t('deleteTransformMsg')} - - +
); }; diff --git a/ui/packages/ui/src/app/shared/Utils.ts b/ui/packages/ui/src/app/shared/Utils.ts index 6c109e2d..9a0e7f08 100644 --- a/ui/packages/ui/src/app/shared/Utils.ts +++ b/ui/packages/ui/src/app/shared/Utils.ts @@ -634,9 +634,15 @@ export function getFormattedProperties (propertyDefns: ConnectorProperty[], conn * @returns the array of altered transform config */ export function getFormattedConfig (transformConfig: any[], transformTypeId: string): any { - const formattedTransformConfig: ConnectorProperty[] = transformTypeId ? _.find([...transformConfig],['transform',transformTypeId])?.configurationOptions : []; - for (const transConfig of formattedTransformConfig) { + const selectedTransformConfig: any = transformTypeId ? _.find([...transformConfig],['transform',transformTypeId])?.properties : {}; + const formattedTransformConfig: any[] = []; + // tslint:disable-next-line: forin + for (const transform in selectedTransformConfig) { + const transConfig = selectedTransformConfig[transform]; transConfig.gridWidthSm = 12; + transConfig.name = transConfig['x-name']; + transConfig.displayName = transConfig.title; + transConfig.allowedValues = transConfig?.enum; const propName = transConfig.name.replace(/\./g, "_"); // Ensure dotted version of name transConfig.name = propName; if (transformTypeId === 'io.debezium.transforms.Filter' || transformTypeId === 'io.debezium.transforms.ContentBasedRouter') { @@ -659,7 +665,7 @@ export function getFormattedProperties (propertyDefns: ConnectorProperty[], conn case 'drop_tombstones': transConfig.type = "BOOLEAN-SWITCH"; break; - case 'delete_handling​_mode': + case 'delete_handling_mode': transConfig.gridWidthLg = 4; break; case 'add_fields_prefix': @@ -686,7 +692,7 @@ export function getFormattedProperties (propertyDefns: ConnectorProperty[], conn break; } } - + formattedTransformConfig.push(transConfig) } return formattedTransformConfig; } diff --git a/ui/packages/ui/src/locales/en/public.json b/ui/packages/ui/src/locales/en/public.json index 98c2b438..a5d88c37 100644 --- a/ui/packages/ui/src/locales/en/public.json +++ b/ui/packages/ui/src/locales/en/public.json @@ -13,37 +13,25 @@ "addDefinition": "+ Add definition", "addDefinitionTooltip": "Add another definition row", "removeDefinitionTooltip": "Remove this definition row", - "topicCreationPageHeadingText": "Define automatic topic creation default properties and groups", - "topicCreation": "Topic creation", - "topicCreationDefaultsTitle": "Topic Creation Defaults", - "topicCreationHeadingText": "Define the topic creation defaults and topic groups", - "topicGroupsTitle": "Topic Groups", - "topicGroupsNoneDefinedText": "No topic groups have been defined. Click 'Add topic group' to add a group.", - "topicGroupOptionsNoneDefinedText": "No topic group options have been defined. Click 'Add option' to add an option.", - "topicGroupOptionsTitle": "Topic Group Options", - "addTopicGroup": "Add topic group", - "addTopicGroupTooltip": "Add another topic group", - "removeTopicGroupTooltip": "Remove this topic group", - "addTopicGroupOption": "Add option", - "topicCreationDisabledAlert": "Kafka automatic topic creation is not enabled.", - "topicCreationSee": "See", - "topicCreationDocumentation": "documentation", - "topicCreationMoreDetailsToEnable": "for details on enabling this feature.", "pageNotFound": "page not found", "pageNotFoundMsg": "This page couldn't be found. If you think this is a bug, please report the issue.", "takeBackToHome": "Take back to home", + "uniqueName": "Name should be unique.", + "nameRequired": "Name is required.", + "topicGroupOptionsTitle": "Topic Group Options", + "topicGroupOptionsNoneDefinedText": "No topic group options have been defined. Click 'Add option' to add an option.", + "addTopicGroupOption": "Add option", "moveTop": "Move top", "moveUp": "Move up", "moveDown": "Move down", "moveBottom": "Move bottom", "reorderTransform": "Reorder transform", "transformNameDescription": "Transformation name (name should ne unique).", - "uniqueName": "Name should be unique.", - "nameRequired": "Name is required.", "transformTypeDescription": "Transform type to be applied.", "typeRequired": "Transform type is required.", "hideConfig": "Hide config", "showConfig": "Show config", + "deleteTransform": "Delete transform", "apiErrorTitle": "Server API problem", "apiErrorMsg": "A problem was encountered interacting with the server. See below for more information (if available). If the problem persists, you may try reloading or report the problem to an admin.", "connectors": "Connectors", @@ -110,12 +98,20 @@ "columnOrFieldFilter": "{{fieldName}}(s) name not available in preview but the {{fieldName}} filter expression will be applied in created connector.", "clear": "Clear", "clearFilterConfMsg": "This operation will clear all filtering expressions. \nAre you sure you want to proceed?", + "topicCreationDisabledAlert": "Kafka automatic topic creation is not enabled.", + "topicCreationSee": "See", + "topicCreationDocumentation": "documentation", + "topicCreationMoreDetailsToEnable": "for details on enabling this feature.", + "topicCreationPageHeadingText": "Define automatic topic creation default properties and groups", + "topicCreationDefaultsTitle": "Topic Creation Defaults", + "topicGroupsTitle": "Topic Groups", + "topicGroupsNoneDefinedText": "No topic groups have been defined. Click 'Add topic group' to add a group.", + "addTopicGroup": "Add topic group", "transformAlert": "Transformations enable single message at a time modification.", "documentation": "documentation", "moreDetails": "for more details.", "noTransformAdded": "No transformations defined", "addTransform": "Add transformation", - "deleteTransform": "Delete transform", "confirm": "Confirm", "deleteTransformMsg": "Click confirm to remove any single message transformation.", "unknownError": "Unknown error - please consult your administrator", @@ -123,6 +119,7 @@ "properties": "Properties", "filterConfiguration": "Filter definition", "transform": "Transformations", + "topicCreation": "Topic creation", "dataOptions": "Data options", "runtimeOptions": "Runtime options", "review": "Review", @@ -153,6 +150,9 @@ "reviewToFinish": "Review and finish", "createConnector": "Create connector", "tryAgain": "Try Again", + "topicCreationHeadingText": "Define the topic creation defaults and topic groups", + "addTopicGroupTooltip": "Add another topic group", + "removeTopicGroupTooltip": "Remove this topic group", "validationSucessMsg": "The validation was successful", "optionalMsg": "This step is optional" } diff --git a/ui/packages/ui/src/locales/it/public.json b/ui/packages/ui/src/locales/it/public.json index 9f5f8b63..48e20b93 100644 --- a/ui/packages/ui/src/locales/it/public.json +++ b/ui/packages/ui/src/locales/it/public.json @@ -13,37 +13,25 @@ "addDefinition": "+ Aggiungi definizione", "addDefinitionTooltip": "Aggiungere un'altra riga definizione", "removeDefinitionTooltip": "Rimuovi questa riga di definizione", - "topicCreationPageHeadingText": "Definire le proprietà e i gruppi predefiniti per la creazione automatica di argomenti", - "topicCreation": "Creazione di argomenti", - "topicCreationDefaultsTitle": "Default creazione argomento", - "topicCreationHeadingText": "Definisci le impostazioni predefinite di creazione degli argomenti e i gruppi di argomenti", - "topicGroupsTitle": "Gruppi di argomenti", - "topicGroupsNoneDefinedText": "Nessun gruppo di argomenti è stato definito. Fare clic su 'Aggiungi gruppo di argomenti' per aggiungere un gruppo.", - "topicGroupOptionsNoneDefinedText": "Non sono state definite opzioni per i gruppi di argomenti. Fare clic su 'Aggiungi opzione' per aggiungere un'opzione.", - "topicGroupOptionsTitle": "Opzioni del gruppo di argomenti", - "addTopicGroup": "Aggiungi gruppo di argomenti", - "addTopicGroupTooltip": "Aggiungi un altro gruppo di argomenti", - "removeTopicGroupTooltip": "Rimuovi questo gruppo di argomenti", - "addTopicGroupOption": "Aggiungi opzione", - "topicCreationDisabledAlert": "Kafka creazione automatica di argomento non è abilitata.", - "topicCreationSee": "Vedere la", - "topicCreationDocumentation": "documentazione", - "topicCreationMoreDetailsToEnable": "per i dettagli sull'abilitazione di questa funzione.", "pageNotFound": "pagina non trovata", "pageNotFoundMsg": "Questa pagina non è stata trovata. Se pensi che si tratti di un bug, segnala il problema.", "takeBackToHome": "Riporta a casa", + "uniqueName": "Il nome dovrebbe essere univoco.", + "nameRequired": "Il nome è obbligatorio.", + "topicGroupOptionsTitle": "Opzioni del gruppo di argomenti", + "topicGroupOptionsNoneDefinedText": "Non sono state definite opzioni per i gruppi di argomenti. Fare clic su 'Aggiungi opzione' per aggiungere un'opzione.", + "addTopicGroupOption": "Aggiungi opzione", "moveTop": "Sposta in alto", "moveUp": "Andare avanti", "moveDown": "Abbassati", "moveBottom": "Sposta in basso", "reorderTransform": "Riordina", "transformNameDescription": "Transformation nome (dovrebbe essere univoco).", - "uniqueName": "Il nome dovrebbe essere univoco.", - "nameRequired": "Il nome è obbligatorio.", "transformTypeDescription": "Transformation tipo da applicare.", "typeRequired": "Il tipo di trasformazione è obbligatorio.", "hideConfig": "Nascondi configurazione", "showConfig": "Mostra configurazione", + "deleteTransform": "Elimina trasformazione", "apiErrorTitle": "Problema dell'API del server", "apiErrorMsg": "Si è verificato un problema durante l'interazione con il server. Vedi sotto per maggiori informazioni (se disponibili). Se il problema persiste, puoi provare a ricaricare o segnalare il problema a un amministratore.", "connectors": "Connettori", @@ -110,12 +98,20 @@ "columnOrFieldFilter": "Il nome {{fieldName}} non è disponibile nell'anteprima ma l'espressione del filtro {{fieldName}} verrà applicata al connettore creato.", "clear": "Chiaro", "clearFilterConfMsg": "Questa operazione cancellerà tutte le espressioni di filtraggio. \n Sei sicuro di voler procedere?", + "topicCreationDisabledAlert": "Kafka creazione automatica di argomento non è abilitata.", + "topicCreationSee": "Vedere la", + "topicCreationDocumentation": "documentazione", + "topicCreationMoreDetailsToEnable": "per i dettagli sull'abilitazione di questa funzione.", + "topicCreationPageHeadingText": "Definire le proprietà e i gruppi predefiniti per la creazione automatica di argomenti", + "topicCreationDefaultsTitle": "Default creazione argomento", + "topicGroupsTitle": "Gruppi di argomenti", + "topicGroupsNoneDefinedText": "Nessun gruppo di argomenti è stato definito. Fare clic su 'Aggiungi gruppo di argomenti' per aggiungere un gruppo.", + "addTopicGroup": "Aggiungi gruppo di argomenti", "transformAlert": "Transformations enable single message at a time modification.", "documentation": "documentation", "moreDetails": "per ulteriori dettagli.", "noTransformAdded": "No transform added", "addTransform": "Aggiungere transform", - "deleteTransform": "Elimina trasformazione", "confirm": "Confermare", "deleteTransformMsg": "Fare clic su Conferma per rimuovere ogni singola trasformazione del messaggio.", "unknownError": "Errore sconosciuto: consulta il tuo amministratore", @@ -123,6 +119,7 @@ "properties": "Proprietà", "filterConfiguration": "Definizione del filtro", "transform": "Transform", + "topicCreation": "Creazione di argomenti", "dataOptions": "Opzioni dati", "runtimeOptions": "Opzioni di runtime", "review": "Revisione", @@ -153,6 +150,9 @@ "reviewToFinish": "Rivedi e concludi", "createConnector": "Crea connettore", "tryAgain": "Riprova", + "topicCreationHeadingText": "Definisci le impostazioni predefinite di creazione degli argomenti e i gruppi di argomenti", + "addTopicGroupTooltip": "Aggiungi un altro gruppo di argomenti", + "removeTopicGroupTooltip": "Rimuovi questo gruppo di argomenti", "resolvePropertySucessMsg": "Tutta la configurazione richiesta è completa. Se lo desideri, puoi procedere a", "validationSucessMsg": "La convalida ha avuto successo", "optionalMsg": "Questo passaggio è facoltativo"