Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c6578bf
init
lucasgoral Sep 30, 2025
cfb88ac
init
lucasgoral Sep 30, 2025
c72cfe8
fix
lucasgoral Sep 30, 2025
551137c
fixes
lucasgoral Sep 30, 2025
2c26168
Create YamlDiffEditor.tsx
lucasgoral Sep 30, 2025
74b20cf
fix
lucasgoral Sep 30, 2025
f0f6d7a
fix
lucasgoral Sep 30, 2025
a7d1fe5
Create remove-me.yaml
lucasgoral Oct 1, 2025
761f2b6
fix
lucasgoral Oct 1, 2025
2f8fbac
Delete remove-me.yaml
lucasgoral Oct 1, 2025
b7b3c66
fix
lucasgoral Oct 1, 2025
9cab399
Merge branch 'main' into resources-yaml-edit
lucasgoral Oct 1, 2025
de46380
Update YamlViewer.tsx
lucasgoral Oct 1, 2025
d303b4a
Update YamlLoader.tsx
lucasgoral Oct 1, 2025
eb5a125
fix
lucasgoral Oct 1, 2025
0e1fe63
Update YamlViewer.tsx
lucasgoral Oct 1, 2025
2d5d9f6
fix
lucasgoral Oct 1, 2025
4694584
Delete generate-github-themes.ts
lucasgoral Oct 1, 2025
3110aeb
fix
lucasgoral Oct 1, 2025
eb04c0e
Update monaco.ts
lucasgoral Oct 1, 2025
f8a59fd
merge
lucasgoral Oct 1, 2025
a937eef
fix
lucasgoral Oct 2, 2025
442bd02
Merge branch 'main' into resources-yaml-edit
lucasgoral Oct 2, 2025
33d4d0d
fixes
lucasgoral Oct 2, 2025
a7e6cb8
fix
lucasgoral Oct 2, 2025
a8428a4
fix
lucasgoral Oct 2, 2025
198714f
fix
lucasgoral Oct 2, 2025
6bc59d2
Update monaco.ts
lucasgoral Oct 2, 2025
736aac4
Revert "Update monaco.ts"
lucasgoral Oct 2, 2025
64412df
Update WorkspacesList.module.css
lucasgoral Oct 2, 2025
cd88b8e
Merge branch 'main' into resources-yaml-edit
lucasgoral Oct 2, 2025
eb98bcc
Update src/components/Yaml/YamlPanel.tsx
lucasgoral Oct 2, 2025
6e226d4
Update src/components/Yaml/YamlViewer.tsx
lucasgoral Oct 2, 2025
7dcf2e8
Update YamlViewer.tsx
lucasgoral Oct 2, 2025
b6ae075
Merge branch 'resources-yaml-edit' of https://github.com/openmcp-proj…
lucasgoral Oct 2, 2025
51cf3f0
Update monaco.ts
lucasgoral Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
608 changes: 281 additions & 327 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@fastify/static": "8.2.0",
"@fastify/vite": "8.2.0",
"@hookform/resolvers": "5.2.2",
"@monaco-editor/react": "^4.7.0",
"@sentry/node": "10.15.0",
"@sentry/react": "10.15.0",
"@sentry/vite-plugin": "4.3.0",
Expand All @@ -54,13 +55,14 @@
"i18next": "25.5.2",
"javascript-time-ago": "2.5.12",
"js-yaml": "4.1.0",
"monaco-editor": "^0.45.0",
"monaco-yaml": "^5.4.0",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-error-boundary": "6.0.0",
"react-hook-form": "7.63.0",
"react-i18next": "16.0.0",
"react-router-dom": "7.9.3",
"react-syntax-highlighter": "15.6.6",
"react-time-ago": "7.3.5",
"swr": "2.3.6",
"yaml": "2.8.1",
Expand All @@ -76,7 +78,6 @@
"@types/node": "22.18.6",
"@types/react": "19.1.14",
"@types/react-dom": "19.1.9",
"@types/react-syntax-highlighter": "15.5.13",
"@ui5/webcomponents-cypress-commands": "2.14.1",
"@vitejs/plugin-react": "5.0.4",
"@vitest/eslint-plugin": "1.3.13",
Expand All @@ -97,6 +98,7 @@
"typescript": "5.9.2",
"typescript-eslint": "8.44.1",
"vite": "7.1.7",
"vite-plugin-static-copy": "^3.1.2",
"vitest": "3.2.4"
}
}
2 changes: 1 addition & 1 deletion src/components/Graphs/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { NodeData, ColorBy } from './types';
import CustomNode from './CustomNode';
import { Legend, LegendItem } from './Legend';
import { YamlViewDialog } from '../Yaml/YamlViewDialog';
import YamlViewer from '../Yaml/YamlViewer';
import { YamlViewer } from '../Yaml/YamlViewer';
import { stringify } from 'yaml';
import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts';
import { useTranslation } from 'react-i18next';
Expand Down
35 changes: 16 additions & 19 deletions src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
ComponentsListItem,
CreateManagedControlPlane,
} from '../../../lib/api/types/crate/createManagedControlPlane.ts';
import YamlViewer from '../../Yaml/YamlViewer.tsx';
import { YamlViewer } from '../../Yaml/YamlViewer.tsx';
import { idpPrefix } from '../../../utils/idpPrefix.ts';
import { UseFormWatch } from 'react-hook-form';
import { CreateDialogProps } from '../../Dialogs/CreateWorkspaceDialogContainer.tsx';
Expand All @@ -30,7 +30,20 @@ export const SummarizeStep: React.FC<SummarizeStepProps> = ({
isEditMode = false,
}) => {
const { t } = useTranslation();

const yamlString = stringify(
CreateManagedControlPlane(
watch('name'),
`${projectName}--ws-${workspaceName}`,
{
displayName: watch('displayName'),
chargingTarget: watch('chargingTarget'),
members: watch('members'),
componentsList: componentsList ?? [],
chargingTargetType: watch('chargingTargetType'),
},
idpPrefix,
),
);
return (
<>
<Title>{t('common.summarize')}</Title>
Expand Down Expand Up @@ -78,23 +91,7 @@ export const SummarizeStep: React.FC<SummarizeStepProps> = ({
)}
/>
) : (
<YamlViewer
yamlString={stringify(
CreateManagedControlPlane(
watch('name'),
`${projectName}--ws-${workspaceName}`,
{
displayName: watch('displayName'),
chargingTarget: watch('chargingTarget'),
members: watch('members'),
componentsList: componentsList ?? [],
chargingTargetType: watch('chargingTargetType'),
},
idpPrefix,
),
)}
filename={`mcp_${projectName}--ws-${workspaceName}`}
/>
<YamlViewer yamlString={yamlString} filename={`mcp_${projectName}--ws-${workspaceName}`} />
)}
</div>
</Grid>
Expand Down
14 changes: 6 additions & 8 deletions src/components/Yaml/YamlDiff.module.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
.container {
width: 100%;
}
position: relative;

.added {
background-color: rgba(56, 142, 60, 0.18);
}

.removed {
background-color: rgba(211, 47, 47, 0.18);
width: 100%;
height: 100%;
max-height: 100%;
max-width: 100%;
overflow: hidden;
}
48 changes: 4 additions & 44 deletions src/components/Yaml/YamlDiff.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,16 @@
import { FC, useMemo } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { materialLight, materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { diffLines } from 'diff';
import styles from './YamlDiff.module.css';
import { useTheme } from '../../hooks/useTheme.ts';
import { FC } from 'react';

import { YamlDiffEditor } from '../YamlEditor/YamlDiffEditor.tsx';
import styles from './YamlDiff.module.css';
type YamlDiffProps = {
originalYaml: string;
modifiedYaml: string;
};

export const YamlDiff: FC<YamlDiffProps> = ({ originalYaml, modifiedYaml }) => {
const { isDarkTheme } = useTheme();

const hunks = useMemo(() => diffLines(originalYaml ?? '', modifiedYaml ?? ''), [originalYaml, modifiedYaml]);

const { content, lineKinds } = useMemo(() => {
const lines: string[] = [];
const kinds: ('added' | 'removed' | 'context')[] = [];
hunks.forEach((part) => {
const prefix = part.added ? '+' : part.removed ? '-' : ' ';
const kind: 'added' | 'removed' | 'context' = part.added ? 'added' : part.removed ? 'removed' : 'context';
const partLines = part.value.replace(/\n$/, '').split('\n');
partLines.forEach((line) => {
lines.push(`${prefix}${line}`);
kinds.push(kind);
});
});
return { content: lines.join('\n'), lineKinds: kinds };
}, [hunks]);

const lineNumberStyle = useMemo(() => ({ paddingRight: '20px', minWidth: '40px', textAlign: 'right' as const }), []);

return (
<div className={styles.container}>
<SyntaxHighlighter
language="diff"
style={isDarkTheme ? materialDark : materialLight}
showLineNumbers
wrapLongLines
lineNumberStyle={lineNumberStyle}
lineProps={(lineNumber) => {
const kind = lineKinds[lineNumber - 1];
if (kind === 'added') return { className: styles.added };
if (kind === 'removed') return { className: styles.removed };
return {};
}}
customStyle={{ margin: 0, padding: '20px', borderRadius: '4px', fontSize: '1rem', background: 'transparent' }}
codeTagProps={{ style: { whiteSpace: 'pre-wrap' } }}
>
{content}
</SyntaxHighlighter>
<YamlDiffEditor original={originalYaml} modified={modifiedYaml} />
</div>
);
};
2 changes: 1 addition & 1 deletion src/components/Yaml/YamlLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
import { ResourceObject } from '../../lib/api/types/crate/resourceObject.ts';
import Loading from '../Shared/Loading.tsx';
import IllustratedError from '../Shared/IllustratedError.tsx';
import YamlViewer from './YamlViewer.tsx';
import { YamlViewer } from './YamlViewer.tsx';
import { useApiResource } from '../../lib/api/useApiResource';
import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts';

Expand Down
2 changes: 1 addition & 1 deletion src/components/Yaml/YamlViewButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button } from '@ui5/webcomponents-react';
import { FC, useMemo, useState } from 'react';
import styles from './YamlViewer.module.css';
import { useTranslation } from 'react-i18next';
import YamlViewer from './YamlViewer.tsx';
import { YamlViewer } from './YamlViewer.tsx';
import { stringify } from 'yaml';
import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts';
import { YamlIcon } from './YamlIcon.tsx';
Expand Down
6 changes: 6 additions & 0 deletions src/components/Yaml/YamlViewDialog.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.wrapper {
width: 100%;
height: 100%;
max-height: 100%;
max-width: 100%;
}
4 changes: 2 additions & 2 deletions src/components/Yaml/YamlViewDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Bar, Button, CheckBox, Dialog } from '@ui5/webcomponents-react';

import { FC, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';

import styles from './YamlViewDialog.module.css';
export type YamlViewDialogProps = {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
Expand Down Expand Up @@ -51,7 +51,7 @@ export const YamlViewDialog: FC<YamlViewDialogProps> = ({
setIsOpen(false);
}}
>
{isOpen && dialogContent}
<div className={styles.wrapper}>{isOpen && dialogContent}</div>
</Dialog>
);
};
7 changes: 6 additions & 1 deletion src/components/Yaml/YamlViewer.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
.container {
position: relative;
width: 100%;
height: 100%;
max-height: 100%;
max-width: 100%;
overflow: hidden;
}

.buttons {
Expand All @@ -19,4 +24,4 @@
width: 32px;
transform: translateY(1px);
}
}
}
45 changes: 10 additions & 35 deletions src/components/Yaml/YamlViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { FC } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { materialLight, materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism';

import { Button, FlexBox } from '@ui5/webcomponents-react';
import styles from './YamlViewer.module.css';
import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts';
import { useTranslation } from 'react-i18next';
import { useTheme } from '../../hooks/useTheme.ts';
import { YamlEditor } from '../YamlEditor/YamlEditor';

import styles from './YamlViewer.module.css';

type YamlViewerProps = {
yamlString: string;
yamlStringToCopy: string;
yamlStringToCopy?: string;
filename: string;
showOnlyImportantData?: boolean;
setShowOnlyImportantData?: (showOnlyImportantData: boolean) => void;
Expand All @@ -18,9 +17,8 @@ type YamlViewerProps = {
// Download button is hidden now due to stakeholder request
const SHOW_DOWNLOAD_BUTTON = false;

const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename, yamlStringToCopy }) => {
export const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename, yamlStringToCopy }) => {
const { t } = useTranslation();
const { isDarkTheme } = useTheme();
const { copyToClipboard } = useCopyToClipboard();
const downloadYaml = () => {
const blob = new Blob([yamlString], { type: 'text/yaml' });
Expand All @@ -37,7 +35,7 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename, yamlStringToCop
return (
<div className={styles.container}>
<FlexBox className={styles.buttons} direction="Row" justifyContent="End" alignItems="Baseline" gap={16}>
<Button icon="copy" onClick={() => copyToClipboard(yamlStringToCopy)}>
<Button icon="copy" onClick={() => copyToClipboard(yamlStringToCopy ?? yamlString)}>
{t('buttons.copy')}
</Button>
{SHOW_DOWNLOAD_BUTTON && (
Expand All @@ -46,32 +44,9 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename, yamlStringToCop
</Button>
)}
</FlexBox>
<SyntaxHighlighter
language="yaml"
style={isDarkTheme ? materialDark : materialLight}
showLineNumbers
lineNumberStyle={{
paddingRight: '20px',
minWidth: '40px',
textAlign: 'right',
}}
customStyle={{
margin: 0,
padding: '20px',
borderRadius: '4px',
fontSize: '1rem',
background: 'transparent',
}}
codeTagProps={{
style: {
whiteSpace: 'pre-wrap',
},
}}
>
{yamlString}
</SyntaxHighlighter>

{/* Use controlled value with a stable model path to update content without remounting */}
<YamlEditor height="90vh" value={yamlString} path={`${filename}.yaml`} options={{ readOnly: true }} />
</div>
);
};

export default YamlViewer;
51 changes: 51 additions & 0 deletions src/components/YamlEditor/YamlDiffEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { DiffEditor } from '@monaco-editor/react';
import type { ComponentProps } from 'react';
import { useTheme } from '../../hooks/useTheme';
import { GITHUB_DARK_DEFAULT, GITHUB_LIGHT_DEFAULT } from '../../lib/monaco.ts';

// Reuse all props from the underlying Monaco DiffEditor component, except language (we force YAML)
export type YamlDiffEditorProps = Omit<
ComponentProps<typeof DiffEditor>,
'language' | 'defaultLanguage' | 'originalLanguage' | 'modifiedLanguage'
>;

// Simple wrapper that forwards all props to Monaco DiffEditor
export const YamlDiffEditor = (props: YamlDiffEditorProps) => {
const { isDarkTheme } = useTheme();
const { theme, options, ...rest } = props;
const computedTheme = theme ?? (isDarkTheme ? GITHUB_DARK_DEFAULT : GITHUB_LIGHT_DEFAULT);

const simplifiedOptions = {
// Start from consumer-provided options, then enforce our simplified look
...options,
scrollbar: {
...(options?.scrollbar ?? {}),
useShadows: false,
vertical: 'auto' as const,
horizontal: 'auto' as const,
alwaysConsumeMouseWheel: false,
},
lineNumbers: 'off' as const,
minimap: { enabled: false },
glyphMargin: false,
renderLineHighlight: 'none' as const,
folding: false,
renderOverviewRuler: false,
scrollBeyondLastLine: false,
renderMarginRevertIcon: false,
automaticLayout: true,
};

return (
<div style={{ width: '100%', height: '100%', minHeight: '50vh' }}>
<DiffEditor
{...rest}
theme={computedTheme}
options={simplifiedOptions}
height="90vh"
// Force YAML language for both panes
language="yaml"
/>
</div>
);
};
Loading
Loading