Skip to content

Commit a428e56

Browse files
eblairmckeeclaude
andauthored
fixed intellisense and autocomplete for connect pipeline editor and fixed CSS cascade issue with popover not showing (#2272)
* fixed intellisense and autocomplete for connect pipeline editor and fixed CSS cascade issue with popover not showing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fixed uri and mounting bug * fix: updated schema url and fixed ultracite mcp link --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e314fa8 commit a428e56

File tree

4 files changed

+67
-70
lines changed

4 files changed

+67
-70
lines changed

frontend/.mcp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"ultracite": {
88
"command": "npx",
9-
"args": ["-y", "mcp-remote", "https://www.ultracite.ai/api/mcp/mcp"]
9+
"args": ["-y", "mcp-remote", "https://docs.ultracite.ai/mcp"]
1010
}
1111
}
1212
}

frontend/src/components/ui/yaml/yaml-editor.tsx

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* by the Apache License, Version 2.0
1010
*/
1111

12-
import Editor, { type EditorProps, type Monaco } from '@monaco-editor/react';
12+
import Editor, { type EditorProps } from '@monaco-editor/react';
1313
import 'monaco-editor';
1414
import type { editor } from 'monaco-editor';
1515
import type { JSONSchema } from 'monaco-yaml';
@@ -28,6 +28,7 @@ const defaultOptions: editor.IStandaloneEditorConstructionOptions = {
2828
minimap: {
2929
enabled: false,
3030
},
31+
fixedOverflowWidgets: true,
3132
roundedSelection: false,
3233
padding: {
3334
top: 8,
@@ -57,63 +58,53 @@ const defaultOptions: editor.IStandaloneEditorConstructionOptions = {
5758
},
5859
} as const;
5960

60-
const defaultFallbackSchema: MonacoYamlOptions = {
61-
enableSchemaRequest: false,
62-
format: true,
63-
completion: true,
64-
validate: true,
65-
schemas: [
66-
{
67-
fileMatch: ['**/*.yaml', '**/*.yml'],
68-
schema: {
69-
type: 'object',
61+
function buildMonacoYamlOptions(
62+
schema?: YamlEditorProps['schema'],
63+
): MonacoYamlOptions {
64+
const schemaUri = 'https://raw.githubusercontent.com/redpanda-data/console/refs/heads/master/frontend/src/assets/rp-connect-schema.json';
65+
const inlineSchema =
66+
schema?.definitions || schema?.properties
67+
? {
68+
type: 'object' as const,
69+
...(schema.definitions && { definitions: schema.definitions }),
70+
...(schema.properties && { properties: schema.properties }),
71+
}
72+
: { type: 'object' as const };
73+
74+
return {
75+
enableSchemaRequest: false,
76+
format: true,
77+
completion: true,
78+
validate: true,
79+
schemas: [
80+
{
81+
fileMatch: ['**/*.yaml', '**/*.yml'],
82+
schema: inlineSchema,
83+
uri: schemaUri,
7084
},
71-
uri: 'http://example.com/yaml-schema.json',
72-
},
73-
],
74-
};
85+
],
86+
};
87+
}
7588

7689
export const YamlEditor = (props: YamlEditorProps) => {
7790
const { options: givenOptions, schema, ...rest } = props;
7891
const options = { ...defaultOptions, ...(givenOptions ?? {}) };
79-
const monacoRef = useRef<Monaco | null>(null);
8092
const yamlRef = useRef<MonacoYaml | null>(null);
93+
const hasInitializedRef = useRef(false);
8194

82-
// Build Monaco YAML options with schema from props or fallback
83-
const monacoYamlOptions = useMemo<MonacoYamlOptions>(() => {
84-
if (schema?.definitions || schema?.properties) {
85-
return {
86-
enableSchemaRequest: false,
87-
format: true,
88-
completion: true,
89-
validate: true,
90-
schemas: [
91-
{
92-
fileMatch: ['**/*.yaml', '**/*.yml'],
93-
schema: {
94-
type: 'object',
95-
...(schema.definitions && { definitions: schema.definitions }),
96-
...(schema.properties && { properties: schema.properties }),
97-
},
98-
uri: 'https://redpanda-connect-schema.json',
99-
},
100-
],
101-
};
102-
}
103-
return defaultFallbackSchema;
104-
}, [schema]);
95+
const monacoYamlOptions = useMemo<MonacoYamlOptions>(
96+
() => buildMonacoYamlOptions(schema),
97+
[schema],
98+
);
10599

106-
// Reconfigure Monaco YAML when schema changes
100+
// Update Monaco YAML when schema changes after initial mount
107101
useEffect(() => {
108-
if (monacoRef.current) {
109-
// Dispose previous YAML configuration
110-
if (yamlRef.current) {
111-
yamlRef.current.dispose();
112-
}
113-
114-
// Create new YAML configuration with updated schema
115-
yamlRef.current = configureMonacoYaml(monacoRef.current, monacoYamlOptions);
102+
if (!hasInitializedRef.current) {
103+
hasInitializedRef.current = true;
104+
return;
116105
}
106+
107+
yamlRef.current?.update(monacoYamlOptions);
117108
}, [monacoYamlOptions]);
118109

119110
// Cleanup on unmount
@@ -127,13 +118,13 @@ export const YamlEditor = (props: YamlEditorProps) => {
127118

128119
return (
129120
<Editor
130-
onMount={(_, monaco) => {
131-
monacoRef.current = monaco;
121+
beforeMount={(monaco) => {
132122
yamlRef.current = configureMonacoYaml(monaco, monacoYamlOptions);
133123
}}
134124
defaultLanguage="yaml"
135125
loading={<LoadingPlaceholder />}
136126
options={options}
127+
path="pipeline.yaml"
137128
wrapperProps={{
138129
style: {
139130
minWidth: 0,

frontend/src/config.ts

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -393,28 +393,27 @@ export const embeddedAvailableRoutesObservable = {
393393
export const setup = memoizeOne((setupArgs: SetConfigArguments) => {
394394
setConfig(setupArgs);
395395

396+
// Set MonacoEnvironment synchronously before loader.init() to avoid race
397+
// where the editor mounts before the worker URL resolver is available
398+
window.MonacoEnvironment = {
399+
getWorkerUrl(_, label: string): string {
400+
switch (label) {
401+
case 'editorWorkerService': {
402+
return `${window.location.origin}/static/js/editor.worker.js`;
403+
}
404+
case 'typescript': {
405+
return `${window.location.origin}/static/js/ts.worker.js`;
406+
}
407+
default: {
408+
return `${window.location.origin}/static/js/${label}.worker.js`;
409+
}
410+
}
411+
},
412+
};
413+
396414
// Tell monaco editor where to load dependencies from
397415
loader.config({ monaco });
398416

399-
// Ensure yaml workers are being loaded locally as well
400-
loader.init().then(() => {
401-
window.MonacoEnvironment = {
402-
getWorkerUrl(_, label: string): string {
403-
switch (label) {
404-
case 'editorWorkerService': {
405-
return `${window.location.origin}/static/js/editor.worker.js`;
406-
}
407-
case 'typescript': {
408-
return `${window.location.origin}/static/js/ts.worker.js`;
409-
}
410-
default: {
411-
return `${window.location.origin}/static/js/${label}.worker.js`;
412-
}
413-
}
414-
},
415-
};
416-
});
417-
418417
// Get supported endpoints / kafka cluster version
419418
// In the business version, that endpoint (like any other api endpoint) is
420419
// protected, so we need to delay the call until the user is logged in.

frontend/src/globals.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@
33
@import "./components/redpanda-ui/style/theme.css";
44
@import "tailwindcss";
55
@import "tw-animate-css";
6+
7+
/* tw-animate-css defines .fade-in { opacity: 0; animation: .3s forwards fadeIn; }
8+
which collides with Monaco's internal .monaco-hover.fade-in class,
9+
forcing hover widgets to be invisible. Override to restore opacity. */
10+
.monaco-hover.fade-in {
11+
opacity: 1;
12+
}

0 commit comments

Comments
 (0)