From 351d4cd9e5b3d5f2e095f7c98bd7365f4c70167c Mon Sep 17 00:00:00 2001 From: nicolaferraro Date: Tue, 10 Dec 2024 22:56:28 +0100 Subject: [PATCH 01/60] rpcn: fix display of validation errors --- .../components/pages/rp-connect/errors.tsx | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/pages/rp-connect/errors.tsx b/frontend/src/components/pages/rp-connect/errors.tsx index d7813f485..ef6ca5656 100644 --- a/frontend/src/components/pages/rp-connect/errors.tsx +++ b/frontend/src/components/pages/rp-connect/errors.tsx @@ -9,8 +9,16 @@ export function formatPipelineError(err: any): any { genDesc = err.message; for (const detail of err.details) { if (isLintHint(detail)) { - const hint = LintHint.fromJsonString(JSON.stringify(detail.debug)); - details.push(`Line ${hint.line}, Col ${hint.column}: ${hint.hint}`); + const hint = detail.debug; + if (hint.line > 0) { + details.push(`Line ${hint.line}, Col ${hint.column}: ${hint.hint}`); + } else { + details.push(hint.hint); + } + } else if (isBadRequest(detail)) { + for (const v of detail.debug.fieldViolations) { + details.push(`${v.field}: ${v.description}`); + } } } } @@ -32,6 +40,19 @@ export function formatPipelineError(err: any): any { return desc; } -function isLintHint(obj: any): obj is { type: string; debug: any } { +type BadRequest = { + fieldViolations: FieldViolation[]; +}; + +type FieldViolation = { + field: string; + description: string; +}; + +function isLintHint(obj: any): obj is { type: string; debug: LintHint } { return obj && obj.type === LintHint.typeName; } + +function isBadRequest(obj: any): obj is { type: string; debug: BadRequest } { + return obj && obj.type === 'google.rpc.BadRequest'; +} From 177ba02cab2496f0ab9e5bcb5c76eb35ce3e504b Mon Sep 17 00:00:00 2001 From: Andres Aristizabal Date: Tue, 17 Dec 2024 16:17:34 -0500 Subject: [PATCH 02/60] rpcn: add pipelines column to secret list page --- .../pages/rp-connect/secrets/Secrets.List.tsx | 30 ++++++++++++++----- frontend/src/config.ts | 4 +++ frontend/src/state/backendApi.ts | 23 +++++++++++++- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx b/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx index e07e2b3bb..299364234 100644 --- a/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx +++ b/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx @@ -1,3 +1,4 @@ +import { Link as ChakraLink } from '@chakra-ui/react'; import { PencilIcon, TrashIcon } from '@heroicons/react/outline'; import { Box, @@ -151,14 +152,27 @@ class RpConnectSecretsList extends PageComponent { ), size: 400, }, - // let use this on next phase - // { - // header: 'Pipelines', - // cell: (_) => ( - // TODO - // ), - // size: 400, - // }, + { + header: 'Pipelines', + cell: ({ row: { original } }) => ( + + {rpcnSecretManagerApi.secretsByPipeline + ?.find((x) => x.secretId === original.id) + ?.pipelines?.map(({ id, displayName }, index, array) => ( + + {displayName} {index !== array.length - 1 ? ', ' : ''} + + ))} + + ), + size: 400, + }, { header: '', id: 'actions', diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 65cb39a75..a11061a2d 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -32,6 +32,7 @@ import { LicenseService } from './protogen/redpanda/api/console/v1alpha1/license import { PipelineService } from './protogen/redpanda/api/console/v1alpha1/pipeline_connect'; import { SecurityService } from './protogen/redpanda/api/console/v1alpha1/security_connect'; import { TransformService } from './protogen/redpanda/api/console/v1alpha1/transform_connect'; +import { PipelineService as PipelineServiceV2 } from './protogen/redpanda/api/dataplane/v1alpha2/pipeline_connect'; import { SecretService as RPCNSecretService } from './protogen/redpanda/api/dataplane/v1alpha2/secret_connect'; import { appGlobal } from './state/appGlobal'; import { api } from './state/backendApi'; @@ -118,6 +119,7 @@ interface Config { debugBundleClient?: PromiseClient; securityClient?: PromiseClient; pipelinesClient?: PromiseClient; + pipelinesClientV2?: PromiseClient; rpcnSecretsClient?: PromiseClient; transformsClient?: PromiseClient; fetch: WindowOrWorkerGlobalScope['fetch']; @@ -157,6 +159,7 @@ const setConfig = ({ fetch, urlOverride, jwt, isServerless, ...args }: SetConfig const debugBundleGrpcClient = createPromiseClient(DebugBundleService, transport); const securityGrpcClient = createPromiseClient(SecurityService, transport); const pipelinesGrpcClient = createPromiseClient(PipelineService, transport); + const pipelinesV2GrpcClient = createPromiseClient(PipelineServiceV2, transport); const secretGrpcClient = createPromiseClient(RPCNSecretService, transport); const transformClient = createPromiseClient(TransformService, transport); Object.assign(config, { @@ -170,6 +173,7 @@ const setConfig = ({ fetch, urlOverride, jwt, isServerless, ...args }: SetConfig debugBundleClient: debugBundleGrpcClient, securityClient: securityGrpcClient, pipelinesClient: pipelinesGrpcClient, + pipelinesClientV2: pipelinesV2GrpcClient, transformsClient: transformClient, rpcnSecretsClient: secretGrpcClient, ...args, diff --git a/frontend/src/state/backendApi.ts b/frontend/src/state/backendApi.ts index 8dfdd0bfb..28fd7d55d 100644 --- a/frontend/src/state/backendApi.ts +++ b/frontend/src/state/backendApi.ts @@ -136,7 +136,12 @@ import type { PublishMessageResponse, } from '../protogen/redpanda/api/console/v1alpha1/publish_messages_pb'; import type { TransformMetadata } from '../protogen/redpanda/api/dataplane/v1alpha1/transform_pb'; -import type { Pipeline, PipelineCreate, PipelineUpdate } from '../protogen/redpanda/api/dataplane/v1alpha2/pipeline_pb'; +import { + GetPipelinesBySecretsRequest, + Pipeline, + PipelineCreate, + PipelineUpdate, +} from '../protogen/redpanda/api/dataplane/v1alpha2/pipeline_pb'; import { type CreateSecretRequest, type DeleteSecretRequest, @@ -2069,12 +2074,16 @@ export const pipelinesApi = observable({ export const rpcnSecretManagerApi = observable({ secrets: undefined as undefined | Secret[], + secretsByPipeline: undefined as { secretId: string; pipelines: Pipeline[] }[] | undefined, isEnable: true, async refreshSecrets(_force: boolean): Promise { const client = appConfig.rpcnSecretsClient; if (!client) throw new Error('redpanda connect secret client is not initialized'); + // handle error in order to avoid crash app for this request + this.secretsByPipeline = await this.getPipelinesBySecret().catch(() => []); + const secrets = []; let nextPageToken = ''; @@ -2125,6 +2134,18 @@ export const rpcnSecretManagerApi = observable({ this.isEnable = isEnable; return isEnable; }, + async getPipelinesBySecret() { + const client = appConfig.pipelinesClientV2; + if (!client) throw new Error('redpanda connect dataplane pipeline is not initialized'); + + const pipelinesBySecrets = await client.getPipelinesBySecrets(new GetPipelinesBySecretsRequest()); + return pipelinesBySecrets.pipelinesForSecret.map(({ secretId, pipelines }) => { + return { + secretId: secretId, + pipelines: pipelines, + }; + }); + }, }); export const transformsApi = observable({ From 01652815ab6815bf15e4ee3277301b1c874ab1a4 Mon Sep 17 00:00:00 2001 From: Andres Aristizabal Date: Wed, 11 Dec 2024 15:59:12 -0500 Subject: [PATCH 03/60] rpcn: add task description --- .../src/components/pages/rp-connect/Pipelines.Create.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx b/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx index 7dcfa90f7..5e6d8308d 100644 --- a/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx +++ b/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx @@ -103,7 +103,7 @@ class RpConnectPipelinesCreate extends PageComponent<{}> { . - + { width={500} /> - + (this.tasks = Number(e ?? MIN_TASKS))} From d72f43ffc67a8d91d057c42daa9188346c073d2f Mon Sep 17 00:00:00 2001 From: Jake Cahill <45230295+JakeSCahill@users.noreply.github.com> Date: Thu, 19 Dec 2024 10:31:09 +0000 Subject: [PATCH 04/60] Replace Kowl with Redpanda Console (#1565) --- .../src/components/pages/reassign-partitions/Step2.Brokers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx b/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx index 72361dc10..38e582c1d 100644 --- a/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx +++ b/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx @@ -45,7 +45,7 @@ export class StepSelectBrokers extends Component<{

Target Brokers

- Choose the target brokers to move the selected partitions to. Kowl will consider them as desired targets and + Choose the target brokers to move the selected partitions to. Redpanda Console will distribute partitions across the available racks of the selected target brokers.

From aeeb5b08a679098d2faa284f6b7bd725cb3dd664 Mon Sep 17 00:00:00 2001 From: Jake Cahill <45230295+JakeSCahill@users.noreply.github.com> Date: Thu, 19 Dec 2024 11:04:22 +0000 Subject: [PATCH 05/60] Fix doc links (#1567) * Fix doc links Data transforms is no longer in beta. Although we have redirects, it's best to use the GA URL. * Update Transforms.List.tsx --- frontend/src/components/pages/transforms/Transforms.List.tsx | 2 +- frontend/src/components/pages/transforms/Transforms.Setup.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/pages/transforms/Transforms.List.tsx b/frontend/src/components/pages/transforms/Transforms.List.tsx index 008d7462f..6c032a181 100644 --- a/frontend/src/components/pages/transforms/Transforms.List.tsx +++ b/frontend/src/components/pages/transforms/Transforms.List.tsx @@ -110,7 +110,7 @@ class TransformsList extends PageComponent<{}> { Redpanda.{' '} Learn more diff --git a/frontend/src/components/pages/transforms/Transforms.Setup.tsx b/frontend/src/components/pages/transforms/Transforms.Setup.tsx index 38da44c2c..68b449fee 100644 --- a/frontend/src/components/pages/transforms/Transforms.Setup.tsx +++ b/frontend/src/components/pages/transforms/Transforms.Setup.tsx @@ -36,7 +36,7 @@ export class TransformsSetup extends PageComponent<{}> { within Redpanda.{' '} Date: Fri, 20 Dec 2024 13:16:14 +0100 Subject: [PATCH 07/60] frontend: fix typo causing syntax error (#1568) --- frontend/src/components/pages/transforms/Transforms.Setup.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/pages/transforms/Transforms.Setup.tsx b/frontend/src/components/pages/transforms/Transforms.Setup.tsx index 68b449fee..4ba07ad5e 100644 --- a/frontend/src/components/pages/transforms/Transforms.Setup.tsx +++ b/frontend/src/components/pages/transforms/Transforms.Setup.tsx @@ -36,7 +36,7 @@ export class TransformsSetup extends PageComponent<{}> { within Redpanda.{' '} Learn more From 74ca55a6134ec1ab00237cd282ace02ba22785b0 Mon Sep 17 00:00:00 2001 From: Andres Aristizabal Date: Fri, 20 Dec 2024 10:33:02 -0500 Subject: [PATCH 08/60] fix: lint --- frontend/src/components/pages/acls/Acl.List.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/pages/acls/Acl.List.tsx b/frontend/src/components/pages/acls/Acl.List.tsx index b358196d9..c0cc967bd 100644 --- a/frontend/src/components/pages/acls/Acl.List.tsx +++ b/frontend/src/components/pages/acls/Acl.List.tsx @@ -101,7 +101,7 @@ class AclList extends PageComponent<{ tab: AclListTab }> { } async refreshData(force: boolean) { - if (api.userData != null && !api.userData.canListAcls) return; + if (api.userData !== undefined && api.userData !== null && !api.userData.canListAcls) return; await Promise.allSettled([ api.refreshAcls(AclRequestDefault, force), From 33d7d8ffd13812c72e541fe942c02a4297468603 Mon Sep 17 00:00:00 2001 From: Andres Aristizabal Date: Fri, 20 Dec 2024 10:34:48 -0500 Subject: [PATCH 09/60] fix: lint --- frontend/src/components/pages/acls/Acl.List.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/pages/acls/Acl.List.tsx b/frontend/src/components/pages/acls/Acl.List.tsx index c0cc967bd..b358196d9 100644 --- a/frontend/src/components/pages/acls/Acl.List.tsx +++ b/frontend/src/components/pages/acls/Acl.List.tsx @@ -101,7 +101,7 @@ class AclList extends PageComponent<{ tab: AclListTab }> { } async refreshData(force: boolean) { - if (api.userData !== undefined && api.userData !== null && !api.userData.canListAcls) return; + if (api.userData != null && !api.userData.canListAcls) return; await Promise.allSettled([ api.refreshAcls(AclRequestDefault, force), From 245239044e9405e240f1e410582313870383387f Mon Sep 17 00:00:00 2001 From: Jan Vorcak Date: Fri, 3 Jan 2025 13:02:26 +0100 Subject: [PATCH 10/60] Topic config modal uses react-hook-form --- .../pages/topics/TopicConfiguration.tsx | 479 +++++++++--------- 1 file changed, 229 insertions(+), 250 deletions(-) diff --git a/frontend/src/components/pages/topics/TopicConfiguration.tsx b/frontend/src/components/pages/topics/TopicConfiguration.tsx index 845e4cff2..8d49a2350 100644 --- a/frontend/src/components/pages/topics/TopicConfiguration.tsx +++ b/frontend/src/components/pages/topics/TopicConfiguration.tsx @@ -1,12 +1,11 @@ -import { AdjustmentsIcon } from '@heroicons/react/outline'; import { PencilIcon } from '@heroicons/react/solid'; import { Alert, - AlertDescription, AlertIcon, Box, Button, Flex, + FormField, Icon, Input, Modal, @@ -25,6 +24,8 @@ import { } from '@redpanda-data/ui'; import { Observer, observer, useLocalObservable } from 'mobx-react'; import type { FC } from 'react'; +import { useState } from 'react'; +import { Controller, type SubmitHandler, useForm } from 'react-hook-form'; import type { ConfigEntryExtended } from '../../../state/restInterfaces'; import { formatConfigValue } from '../../../utils/formatters/ConfigValueFormatter'; import { DataSizeSelect, DurationSelect, NumInput, RatioInput } from './CreateTopicModal/CreateTopicModal'; @@ -32,7 +33,6 @@ import './TopicConfiguration.scss'; import { MdInfoOutline } from 'react-icons/md'; import { isServerless } from '../../../config'; import { api } from '../../../state/backendApi'; -import { Label } from '../../../utils/tsxUtils'; import { SingleSelect } from '../../misc/Select'; type ConfigurationEditorProps = { @@ -41,27 +41,165 @@ type ConfigurationEditorProps = { onForceRefresh: () => void; }; -const ConfigurationEditor: FC = observer((props) => { +type Inputs = { + valueType: 'default' | 'infinite' | 'custom'; + customValue: string | number | undefined | null; +}; + +const ConfigEditorForm: FC<{ + editedEntry: ConfigEntryExtended; + onClose: () => void; + onSuccess: () => void; + targetTopic: string; +}> = ({ editedEntry, onClose, targetTopic, onSuccess, onError }) => { const toast = useToast(); + const [globalError, setGlobalError] = useState(null); + + const { + control, + handleSubmit, + formState: { isSubmitting }, + watch, + } = useForm({ + defaultValues: { + valueType: editedEntry.isExplicitlySet ? (editedEntry.value === '-1' ? 'infinite' : 'custom') : 'default', + customValue: editedEntry.isExplicitlySet && editedEntry.value !== '-1' ? editedEntry.value : undefined, + }, + }); + + const hasInfiniteValue = ['BYTE_SIZE', 'DURATION'].includes(editedEntry.frontendFormat); + const valueTypeOptions = []; + valueTypeOptions.push({ + label: 'Default', + value: 'default', + }); + if (hasInfiniteValue) { + valueTypeOptions.push({ + label: 'Infinite', + value: 'infinite', + }); + } + valueTypeOptions.push({ + label: 'Custom', + value: 'custom', + }); + + const onSubmit: SubmitHandler = async ({ valueType, customValue }) => { + const operation = valueType === 'infinite' || valueType === 'custom' ? 'SET' : 'DELETE'; + + let value: number | string = undefined; + if (valueType === 'infinite') { + value = -1; + } else if (valueType === 'custom') { + value = customValue; + } + + try { + await api.changeTopicConfig(targetTopic, [ + { + key: editedEntry.name, + op: operation, + value: operation === 'SET' ? String(value) : undefined, + }, + ]); + toast({ + status: 'success', + description: ( + + Successfully updated config {editedEntry.name} + + ), + }); + onSuccess(); + onClose(); + } catch (err) { + console.error('error while applying config change', { err, configEntry: editedEntry }); + setGlobalError(err instanceof Error ? err.message : String(err)); + } + }; + + const valueType = watch('valueType'); + + return ( + +
+ + + {`Edit ${editedEntry.name}`} + + {editedEntry.documentation} + + + + ( + options={valueTypeOptions} value={value} onChange={onChange} /> + )} + /> + + {valueType === 'custom' && ( + + + ( + + )} + /> + + + )} + {/*It's not possible to show default value until we get it always from the BE.*/} + {/*Currently we only retrieve the current value and not default if it's set to custom/infinite*/} + {/*{valueType === 'default' && (*/} + {/* */} + {/* The default value is{' '}*/} + {/* */} + {/* {formatConfigValue(editedEntry.name, editedEntry.value, 'friendly')}*/} + {/* */} + {/* . This is inherited from {editedEntry.source}.*/} + {/* */} + {/*)}*/} + + {globalError && ( + + + {globalError} + + )} + + + + + + + +
+ ); +}; + +const ConfigurationEditor: FC = observer((props) => { const $state = useLocalObservable<{ - isEditing: boolean; filter?: string; - initialValueType?: 'default' | 'custom'; - modalValueType: 'default' | 'custom'; - modalError: string | null; editedEntry: ConfigEntryExtended | null; }>(() => ({ - isEditing: false, - modalValueType: 'default', - modalError: null, + filter: '', editedEntry: null, })); const editConfig = (configEntry: ConfigEntryExtended) => { - configEntry.currentValue = configEntry.value; - $state.initialValueType = configEntry.isExplicitlySet ? 'custom' : 'default'; - - $state.modalValueType = $state.initialValueType; $state.editedEntry = configEntry; }; @@ -90,158 +228,16 @@ const ConfigurationEditor: FC = observer((props) => { return ( - ($state.editedEntry = null)}> - - {$state.editedEntry !== null && ( - - - {`Edit ${$state.editedEntry.name}`} - - - - {() => { - const isCustom = $state.modalValueType === 'custom'; - - if ($state.editedEntry === null) { - return null; - } - - const configEntry = $state.editedEntry; - const defaultEntry = $state.editedEntry.synonyms?.last(); - const defaultValue = defaultEntry?.value ?? $state.editedEntry.value; - const defaultSource = defaultEntry?.source ?? $state.editedEntry.source; - const friendlyDefault = formatConfigValue($state.editedEntry.name, defaultValue, 'friendly'); - - return ( -
-

- Edit {configEntry.name} configuration for topic {props.targetTopic}. -

- - - {configEntry.documentation} - - - - - - {$state.modalValueType === 'default' && ( - <> - {friendlyDefault} - Inherited from {defaultSource} - - )} - - {$state.modalValueType === 'custom' && ( - <> - Set at topic configuration - - - - - )} - - {$state.modalError && ( - - - {$state.modalError} - - )} - -
- ); - }} -
-
- - - - -
- )} -
+ {$state.editedEntry !== null && ( + ($state.editedEntry = null)} + onSuccess={() => { + props.onForceRefresh(); + }} + /> + )}
{ - const entry = p.entry; - switch (entry.frontendFormat) { - case 'BOOLEAN': - return ( - (entry.currentValue = c)} - /> - ); - - case 'SELECT': - return ( - (entry.currentValue = e)} - className={p.className} - options={ - entry.enumValues?.map((value) => ({ - value, - label: value, - })) ?? [] - } - /> - ); - - case 'BYTE_SIZE': - return ( - (entry.currentValue = Math.round(e))} - className={p.className} - /> - ); - case 'DURATION': - return ( - (entry.currentValue = Math.round(e))} - className={p.className} - /> - ); - - case 'PASSWORD': - return ( - (entry.currentValue = x.target.value)} /> - ); - - case 'RATIO': - return (entry.currentValue = x)} />; - - case 'INTEGER': - return ( - (entry.currentValue = Math.round(e ?? 0))} - className={p.className} - /> - ); - - case 'DECIMAL': - return ( - (entry.currentValue = e)} - className={p.className} - /> - ); - default: - return (entry.currentValue = e.target.value)} />; - } - }, -); +export const ConfigEntryEditorController = (p: { + entry: ConfigEntryExtended; + value: T; + onChange: (e: T) => void; +}) => { + const { entry, value, onChange } = p; + switch (entry.frontendFormat) { + case 'BOOLEAN': + return ( + + ); + + case 'SELECT': + return ( + ({ + value, + label: value, + })) ?? [] + } + /> + ); + + case 'BYTE_SIZE': + return ( + onChange(Math.round(e))} + /> + ); + case 'DURATION': + return ( + onChange(Math.round(e))} + /> + ); + + case 'PASSWORD': + return onChange(x.target.value)} />; + + case 'RATIO': + return onChange(x)} />; + + case 'INTEGER': + return onChange(Math.round(e ?? 0))} />; + + case 'DECIMAL': + return onChange(e)} />; + default: + return onChange(e.target.value)} />; + } +}; function getConfigDescription(source: string): string { switch (source) { From 0c3063b7c142619c426c16d1a946cb1040150811 Mon Sep 17 00:00:00 2001 From: Jan Vorcak Date: Fri, 3 Jan 2025 13:08:18 +0100 Subject: [PATCH 11/60] Fixes lint issues --- .../components/pages/reassign-partitions/Step2.Brokers.tsx | 4 ++-- .../src/components/pages/rp-connect/Pipelines.Create.tsx | 2 +- frontend/src/state/backendApi.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx b/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx index 38e582c1d..672a99968 100644 --- a/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx +++ b/frontend/src/components/pages/reassign-partitions/Step2.Brokers.tsx @@ -45,8 +45,8 @@ export class StepSelectBrokers extends Component<{

Target Brokers

- Choose the target brokers to move the selected partitions to. Redpanda Console will - distribute partitions across the available racks of the selected target brokers. + Choose the target brokers to move the selected partitions to. Redpanda Console will distribute partitions + across the available racks of the selected target brokers.

diff --git a/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx b/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx index 5e6d8308d..4e658e962 100644 --- a/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx +++ b/frontend/src/components/pages/rp-connect/Pipelines.Create.tsx @@ -26,7 +26,7 @@ import { } from '@redpanda-data/ui'; import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; -import { editor } from 'monaco-editor'; +import type { editor } from 'monaco-editor'; import React, { useState } from 'react'; import { Link } from 'react-router-dom'; import { PipelineCreate } from '../../../protogen/redpanda/api/dataplane/v1alpha2/pipeline_pb'; diff --git a/frontend/src/state/backendApi.ts b/frontend/src/state/backendApi.ts index 28fd7d55d..2a77c1f71 100644 --- a/frontend/src/state/backendApi.ts +++ b/frontend/src/state/backendApi.ts @@ -138,9 +138,9 @@ import type { import type { TransformMetadata } from '../protogen/redpanda/api/dataplane/v1alpha1/transform_pb'; import { GetPipelinesBySecretsRequest, - Pipeline, - PipelineCreate, - PipelineUpdate, + type Pipeline, + type PipelineCreate, + type PipelineUpdate, } from '../protogen/redpanda/api/dataplane/v1alpha2/pipeline_pb'; import { type CreateSecretRequest, From 119de69bf4e7562b082de7bc13be1ef48f340c39 Mon Sep 17 00:00:00 2001 From: Jan Vorcak Date: Mon, 6 Jan 2025 10:20:40 +0100 Subject: [PATCH 12/60] Fixes tslint --- .../pages/topics/TopicConfiguration.tsx | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/frontend/src/components/pages/topics/TopicConfiguration.tsx b/frontend/src/components/pages/topics/TopicConfiguration.tsx index 8d49a2350..c81de1938 100644 --- a/frontend/src/components/pages/topics/TopicConfiguration.tsx +++ b/frontend/src/components/pages/topics/TopicConfiguration.tsx @@ -22,7 +22,7 @@ import { Tooltip, useToast, } from '@redpanda-data/ui'; -import { Observer, observer, useLocalObservable } from 'mobx-react'; +import { observer, useLocalObservable } from 'mobx-react'; import type { FC } from 'react'; import { useState } from 'react'; import { Controller, type SubmitHandler, useForm } from 'react-hook-form'; @@ -36,7 +36,7 @@ import { api } from '../../../state/backendApi'; import { SingleSelect } from '../../misc/Select'; type ConfigurationEditorProps = { - targetTopic: string | null; // topic name, or null if default configs + targetTopic: string; // topic name, or null if default configs entries: ConfigEntryExtended[]; onForceRefresh: () => void; }; @@ -51,7 +51,7 @@ const ConfigEditorForm: FC<{ onClose: () => void; onSuccess: () => void; targetTopic: string; -}> = ({ editedEntry, onClose, targetTopic, onSuccess, onError }) => { +}> = ({ editedEntry, onClose, targetTopic, onSuccess }) => { const toast = useToast(); const [globalError, setGlobalError] = useState(null); @@ -67,8 +67,11 @@ const ConfigEditorForm: FC<{ }, }); - const hasInfiniteValue = ['BYTE_SIZE', 'DURATION'].includes(editedEntry.frontendFormat); - const valueTypeOptions = []; + const hasInfiniteValue = editedEntry.frontendFormat && ['BYTE_SIZE', 'DURATION'].includes(editedEntry.frontendFormat); + const valueTypeOptions: Array<{ + label: string; + value: Inputs['valueType']; + }> = []; valueTypeOptions.push({ label: 'Default', value: 'default', @@ -87,7 +90,7 @@ const ConfigEditorForm: FC<{ const onSubmit: SubmitHandler = async ({ valueType, customValue }) => { const operation = valueType === 'infinite' || valueType === 'custom' ? 'SET' : 'DELETE'; - let value: number | string = undefined; + let value: number | string | undefined | null = undefined; if (valueType === 'infinite') { value = -1; } else if (valueType === 'custom') { @@ -135,7 +138,7 @@ const ConfigEditorForm: FC<{ control={control} name="valueType" render={({ field: { onChange, value } }) => ( - options={valueTypeOptions} value={value} onChange={onChange} /> + )} /> @@ -180,7 +183,7 @@ const ConfigEditorForm: FC<{ > Cancel - @@ -357,19 +360,20 @@ function isTopicConfigEdittable( return { canEdit: true }; } -export const ConfigEntryEditorController = (p: { +export const ConfigEntryEditorController = (p: { entry: ConfigEntryExtended; value: T; onChange: (e: T) => void; + className?: string; }) => { const { entry, value, onChange } = p; switch (entry.frontendFormat) { case 'BOOLEAN': return ( - options={[ - { value: 'false', label: 'False' }, - { value: 'true', label: 'True' }, + { value: 'false' as T, label: 'False' }, + { value: 'true' as T, label: 'True' }, ]} value={value} onChange={onChange} @@ -384,7 +388,7 @@ export const ConfigEntryEditorController = (p: { className={p.className} options={ entry.enumValues?.map((value) => ({ - value, + value: value as T, label: value, })) ?? [] } @@ -396,7 +400,7 @@ export const ConfigEntryEditorController = (p: { onChange(Math.round(e))} + onChange={(e) => onChange(Math.round(e) as T)} /> ); case 'DURATION': @@ -404,23 +408,23 @@ export const ConfigEntryEditorController = (p: { onChange(Math.round(e))} + onChange={(e) => onChange(Math.round(e) as T)} /> ); case 'PASSWORD': - return onChange(x.target.value)} />; + return onChange(x.target.value as T)} />; case 'RATIO': - return onChange(x)} />; + return onChange(x as T)} />; case 'INTEGER': - return onChange(Math.round(e ?? 0))} />; + return onChange(Math.round(e ?? 0) as T)} />; case 'DECIMAL': - return onChange(e)} />; + return onChange(e as T)} />; default: - return onChange(e.target.value)} />; + return onChange(e.target.value as T)} />; } }; From 6e5c0561696f66b85b7b6b67e4a285acfe735b92 Mon Sep 17 00:00:00 2001 From: Jan Grant Date: Mon, 6 Jan 2025 11:37:58 +0000 Subject: [PATCH 13/60] Bump dependency on golang.org/x/net --- backend/go.mod | 2 +- backend/go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/go.mod b/backend/go.mod index 0c6fb2e62..15d3fb1d3 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -58,7 +58,7 @@ require ( go.uber.org/zap v1.27.0 go.vallahaye.net/connect-gateway v0.8.0 golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 - golang.org/x/net v0.32.0 + golang.org/x/net v0.33.0 golang.org/x/sync v0.10.0 golang.org/x/text v0.21.0 google.golang.org/genproto v0.0.0-20240415180920-8c6c420018be diff --git a/backend/go.sum b/backend/go.sum index 40683a20b..38d08b8ba 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -780,6 +780,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From b9955819995cf35fec6ae22afa4bb70d87c225ff Mon Sep 17 00:00:00 2001 From: Andres Aristizabal Date: Fri, 3 Jan 2025 14:56:19 -0500 Subject: [PATCH 14/60] front-end: add missing data-testid --- frontend/src/components/pages/connect/Overview.tsx | 12 ++++++++++-- .../pages/rp-connect/secrets/Secrets.Create.tsx | 8 +++++++- .../pages/rp-connect/secrets/Secrets.List.tsx | 9 ++++++--- .../pages/rp-connect/secrets/Secrets.Update.tsx | 8 +++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/pages/connect/Overview.tsx b/frontend/src/components/pages/connect/Overview.tsx index 8a4354bf1..adadc8efc 100644 --- a/frontend/src/components/pages/connect/Overview.tsx +++ b/frontend/src/components/pages/connect/Overview.tsx @@ -426,12 +426,20 @@ const TabRedpandaConnect = observer((_p: { defaultView: ConnectView }) => { const tabs = [ { key: 'pipelines', - title: Pipelines, + title: ( + + Pipelines + + ), content: , }, { key: 'secrets', - title: Secrets, + title: ( + + Secrets + + ), content: , }, ] as Tab[]; diff --git a/frontend/src/components/pages/rp-connect/secrets/Secrets.Create.tsx b/frontend/src/components/pages/rp-connect/secrets/Secrets.Create.tsx index f96014df8..d4624c730 100644 --- a/frontend/src/components/pages/rp-connect/secrets/Secrets.Create.tsx +++ b/frontend/src/components/pages/rp-connect/secrets/Secrets.Create.tsx @@ -149,10 +149,16 @@ class RpConnectSecretCreate extends PageComponent { isLoading={this.isCreating} isDisabled={isIdEmpty || isSecretEmpty || Boolean(this.isNameValid)} onClick={action(() => this.createSecret())} + data-testid={'submit-create-rpcn-secret'} > Create secret - diff --git a/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx b/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx index 299364234..ef1f6c56c 100644 --- a/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx +++ b/frontend/src/components/pages/rp-connect/secrets/Secrets.List.tsx @@ -32,7 +32,7 @@ const { ToastContainer, toast } = createStandaloneToast(); const CreateSecretButton = () => { return ( - @@ -130,7 +130,9 @@ class RpConnectSecretsList extends PageComponent { columns={[ { header: 'Secret name', - cell: ({ row: { original } }) => {original.id}, + cell: ({ row: { original } }) => ( + {original.id} + ), size: 200, }, { @@ -180,6 +182,7 @@ class RpConnectSecretsList extends PageComponent { } diff --git a/frontend/src/components/pages/rp-connect/secrets/Secrets.Update.tsx b/frontend/src/components/pages/rp-connect/secrets/Secrets.Update.tsx index 2e54b8a83..9eb54bf78 100644 --- a/frontend/src/components/pages/rp-connect/secrets/Secrets.Update.tsx +++ b/frontend/src/components/pages/rp-connect/secrets/Secrets.Update.tsx @@ -61,6 +61,7 @@ class RpConnectSecretUpdate extends PageComponent<{ secretId: string }> { duration: 4000, isClosable: false, title: 'Secret updated', + id: 'secret-update-success', }); await pipelinesApi.refreshPipelines(true); appGlobal.history.push(returnSecretTab); @@ -118,7 +119,12 @@ class RpConnectSecretUpdate extends PageComponent<{ secretId: string }> { -