Skip to content

Commit 1bdb3cb

Browse files
Merge pull request #1997 from redpanda-data/UX-610-lazy-load-schema-registry-in-produce-records
Lazy load schema registry in a publish topic page
2 parents d8a23e9 + 8b33012 commit 1bdb3cb

File tree

1 file changed

+102
-53
lines changed

1 file changed

+102
-53
lines changed

frontend/src/components/pages/topics/topic-produce.tsx

Lines changed: 102 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
Text,
1818
useToast,
1919
} from '@redpanda-data/ui';
20-
import { autorun, computed } from 'mobx';
20+
import { computed } from 'mobx';
2121
import { observer } from 'mobx-react';
2222
import { type FC, useEffect, useState } from 'react';
2323
import { Controller, type SubmitHandler, useFieldArray, useForm } from 'react-hook-form';
@@ -37,7 +37,6 @@ import {
3737
} from '../../../protogen/redpanda/api/console/v1alpha1/publish_messages_pb';
3838
import { appGlobal } from '../../../state/app-global';
3939
import { api } from '../../../state/backend-api';
40-
import { uiSettings } from '../../../state/ui';
4140
import { uiState } from '../../../state/ui-state';
4241
import { Label } from '../../../utils/tsx-utils';
4342
import { base64ToUInt8Array, isValidBase64, substringWithEllipsis } from '../../../utils/utils';
@@ -229,29 +228,18 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
229228
});
230229

231230
useEffect(() => {
232-
return autorun(() => {
233-
const filteredSoftDeletedSchemaSubjects =
234-
api.schemaSubjects?.filter(
235-
(x) => uiSettings.schemaList.showSoftDeleted || !(uiSettings.schemaList.showSoftDeleted || x.isSoftDeleted)
236-
) ?? [];
237-
238-
const formattedSchemaSubjects = filteredSoftDeletedSchemaSubjects?.filter((x) =>
239-
x.name.toLowerCase().includes(uiSettings.schemaList.quickSearch.toLowerCase())
240-
);
241-
242-
for (const schemaSubject of formattedSchemaSubjects) {
243-
api.refreshSchemaDetails(schemaSubject.name).catch(() => {
244-
// Error handling managed by API layer
245-
});
246-
}
247-
});
231+
// Fetch schema subjects list if not already loaded
232+
if (!api.schemaSubjects) {
233+
api.refreshSchemaSubjects();
234+
}
248235
}, []);
249236

250-
const availableValues = Array.from(api.schemaDetails.values());
237+
const availableValues = api.schemaSubjects?.filter((x) => !x.isSoftDeleted) ?? [];
251238

252239
const keySchemaName = watch('key.schemaName');
253240
const valueSchemaName = watch('value.schemaName');
254241

242+
// biome-ignore lint/complexity: This will be refactored anyway as part of MobX removal
255243
const onSubmit: SubmitHandler<Inputs> = async (data) => {
256244
const req = create(PublishMessageRequestSchema);
257245
req.topic = topicName;
@@ -295,7 +283,24 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
295283
}
296284
req.key.data = encodeData(data.key.data, data.key.encoding);
297285
req.key.encoding = data.key.encoding;
298-
req.key.schemaId = data.key.schemaId;
286+
287+
// Determine schemaId from schemaVersion if schema is selected and encoding is Avro or Protobuf
288+
if (
289+
(data.key.encoding === PayloadEncoding.AVRO || data.key.encoding === PayloadEncoding.PROTOBUF) &&
290+
data.key.schemaName &&
291+
data.key.schemaVersion
292+
) {
293+
const schemaDetail = api.schemaDetails.get(data.key.schemaName);
294+
if (schemaDetail) {
295+
const selectedSchema = schemaDetail.schemas.find(
296+
(schema) => schema.version === data.key.schemaVersion && !schema.isSoftDeleted
297+
);
298+
if (selectedSchema) {
299+
req.key.schemaId = selectedSchema.id;
300+
}
301+
}
302+
}
303+
299304
req.key.index = data.key.protobufIndex;
300305
}
301306

@@ -311,7 +316,24 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
311316
return;
312317
}
313318
req.value.encoding = data.value.encoding;
314-
req.value.schemaId = data.value.schemaId;
319+
320+
// Determine schemaId from schemaVersion if schema is selected and encoding is Avro or Protobuf
321+
if (
322+
(data.value.encoding === PayloadEncoding.AVRO || data.value.encoding === PayloadEncoding.PROTOBUF) &&
323+
data.value.schemaName &&
324+
data.value.schemaVersion
325+
) {
326+
const schemaDetail = api.schemaDetails.get(data.value.schemaName);
327+
if (schemaDetail) {
328+
const selectedSchema = schemaDetail.schemas.find(
329+
(schema) => schema.version === data.value.schemaVersion && !schema.isSoftDeleted
330+
);
331+
if (selectedSchema) {
332+
req.value.schemaId = selectedSchema.id;
333+
}
334+
}
335+
}
336+
315337
req.value.index = data.value.protobufIndex;
316338
}
317339

@@ -426,8 +448,20 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
426448
onChange={(newVal) => {
427449
onChange(newVal);
428450

429-
const detail = availableValues.filter((schema) => schema.name === newVal).first();
430-
setValue('key.schemaVersion', detail?.latestActiveVersion);
451+
if (newVal) {
452+
// Fetch schema details to get available versions
453+
api
454+
.refreshSchemaDetails(newVal)
455+
.then(() => {
456+
const detail = api.schemaDetails.get(newVal);
457+
if (detail?.latestActiveVersion) {
458+
setValue('key.schemaVersion', detail.latestActiveVersion);
459+
}
460+
})
461+
.catch(() => {
462+
// Error handling managed by API layer
463+
});
464+
}
431465
}}
432466
options={availableValues.map((schema) => ({
433467
key: schema.name,
@@ -446,20 +480,24 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
446480
<Controller
447481
control={control}
448482
name="key.schemaVersion"
449-
render={({ field: { onChange, value } }) => (
450-
<SingleSelect<number | undefined>
451-
onChange={onChange}
452-
options={availableValues
453-
.filter((schema) => schema.name === keySchemaName)
454-
.flatMap((schema) => schema.versions)
455-
.sort(({ version: version1 }, { version: version2 }) => version2 - version1)
456-
.map(({ version }) => ({
457-
label: version,
458-
value: version,
459-
}))}
460-
value={value}
461-
/>
462-
)}
483+
render={({ field: { onChange, value } }) => {
484+
const schemaDetail = keySchemaName ? api.schemaDetails.get(keySchemaName) : undefined;
485+
return (
486+
<SingleSelect<number | undefined>
487+
onChange={onChange}
488+
options={
489+
schemaDetail?.versions
490+
.slice()
491+
.sort(({ version: version1 }, { version: version2 }) => version2 - version1)
492+
.map(({ version }) => ({
493+
label: version,
494+
value: version,
495+
})) ?? []
496+
}
497+
value={value}
498+
/>
499+
);
500+
}}
463501
/>
464502
</Label>
465503
)}
@@ -538,8 +576,15 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
538576
onChange={(newVal) => {
539577
onChange(newVal);
540578

541-
const detail = availableValues.filter((schema) => schema.name === newVal).first();
542-
setValue('value.schemaVersion', detail?.latestActiveVersion);
579+
if (newVal) {
580+
// Fetch schema details to get available versions
581+
api.refreshSchemaDetails(newVal).then(() => {
582+
const detail = api.schemaDetails.get(newVal);
583+
if (detail?.latestActiveVersion) {
584+
setValue('value.schemaVersion', detail.latestActiveVersion);
585+
}
586+
});
587+
}
543588
}}
544589
options={availableValues.map((schema) => ({
545590
key: schema.name,
@@ -558,20 +603,24 @@ const PublishTopicForm: FC<{ topicName: string }> = observer(({ topicName }) =>
558603
<Controller
559604
control={control}
560605
name="value.schemaVersion"
561-
render={({ field: { onChange, value } }) => (
562-
<SingleSelect<number | undefined>
563-
onChange={onChange}
564-
options={availableValues
565-
.filter((schema) => schema.name === valueSchemaName)
566-
.flatMap((schema) => schema.versions)
567-
.sort(({ version: version1 }, { version: version2 }) => version2 - version1)
568-
.map(({ version }) => ({
569-
label: version,
570-
value: version,
571-
}))}
572-
value={value}
573-
/>
574-
)}
606+
render={({ field: { onChange, value } }) => {
607+
const schemaDetail = valueSchemaName ? api.schemaDetails.get(valueSchemaName) : undefined;
608+
return (
609+
<SingleSelect<number | undefined>
610+
onChange={onChange}
611+
options={
612+
schemaDetail?.versions
613+
.slice()
614+
.sort(({ version: version1 }, { version: version2 }) => version2 - version1)
615+
.map(({ version }) => ({
616+
label: version,
617+
value: version,
618+
})) ?? []
619+
}
620+
value={value}
621+
/>
622+
);
623+
}}
575624
/>
576625
</Label>
577626
)}

0 commit comments

Comments
 (0)