Skip to content

Commit e9d5c2d

Browse files
committed
fixes
1 parent 3e33016 commit e9d5c2d

File tree

8 files changed

+187
-31
lines changed

8 files changed

+187
-31
lines changed

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@xyflow/react": "12.8.4",
4646
"clsx": "2.1.1",
4747
"dagre": "0.8.5",
48+
"diff": "^8.0.2",
4849
"dotenv": "17.2.2",
4950
"fastify": "5.6.0",
5051
"fastify-plugin": "5.0.1",

src/components/ComponentsSelection/ComponentsSelectionContainer.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ManagedControlPlaneTemplate } from '../../lib/api/types/templates/mcpTe
1414
export interface ComponentsSelectionProps {
1515
componentsList: ComponentsListItem[];
1616
setComponentsList: (components: ComponentsListItem[]) => void;
17+
setInitialComponentsList: (components: ComponentsListItem[]) => void;
1718
managedControlPlaneTemplate?: ManagedControlPlaneTemplate;
1819
initialSelection?: Record<string, { isSelected: boolean; version: string }>;
1920
isOnMcpPage?: boolean;
@@ -44,6 +45,7 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
4445
managedControlPlaneTemplate,
4546
initialSelection,
4647
isOnMcpPage,
48+
setInitialComponentsList,
4749
}) => {
4850
const {
4951
data: availableManagedComponentsListData,
@@ -94,7 +96,7 @@ export const ComponentsSelectionContainer: React.FC<ComponentsSelectionProps> =
9496
};
9597
})
9698
.filter((component) => !removeComponents.find((item) => item === component.name));
97-
99+
setInitialComponentsList(newComponentsList);
98100
setComponentsList(newComponentsList);
99101
initialized.current = true;
100102
}, [setComponentsList, defaultComponents, initialSelection, availableManagedComponentsListData?.items]);

src/components/Wizards/CreateManagedControlPlane/CreateManagedControlPlaneWizardContainer.tsx

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
MCPVersionedComponent,
5656
MCPSubject,
5757
} from '../../../lib/api/types/mcpResource.ts';
58+
import { stringify } from 'yaml';
5859

5960
type CreateManagedControlPlaneWizardContainerProps = {
6061
isOpen: boolean;
@@ -145,7 +146,14 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
145146
},
146147
mode: 'onChange',
147148
});
148-
149+
const [initialMcpDataWhenInEditMode, setInitialMcpDataWhenInEditMode] = useState<CreateDialogProps>({
150+
name: '',
151+
displayName: '',
152+
chargingTarget: '',
153+
chargingTargetType: '',
154+
members: [],
155+
componentsList: [],
156+
});
149157
useEffect(() => {
150158
if (selectedStep !== 'metadata') return;
151159

@@ -162,6 +170,7 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
162170

163171
setMetadataFormKey((k) => k + 1);
164172
}, [selectedTemplate, selectedStep, setValue, normalizeChargingTargetType]);
173+
console.log(initialMcpDataWhenInEditMode);
165174

166175
const nextButtonText = useMemo(
167176
() => ({
@@ -399,18 +408,21 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
399408
);
400409
const labels = (initialData?.metadata.labels as unknown as Record<string, string>) ?? {};
401410
const annotations = (initialData?.metadata.annotations as unknown as Record<string, string>) ?? {};
402-
403-
reset({
404-
name: initialData?.metadata.name,
411+
const data = {
412+
name: initialData?.metadata.name ?? '',
405413
displayName: annotations?.[DISPLAY_NAME_ANNOTATION] ?? '',
406414
chargingTarget: labels?.[CHARGING_TARGET_LABEL] ?? '',
407415
chargingTargetType: labels?.[CHARGING_TARGET_TYPE_LABEL] ?? '',
408416
members,
409417
componentsList: componentsList ?? [],
410-
});
418+
};
419+
reset(data);
420+
421+
setInitialMcpDataWhenInEditMode(data);
411422
// eslint-disable-next-line react-hooks/exhaustive-deps
412423
}, [isOpen, isEditMode]);
413-
424+
console.log('initialMcpDataWhenInEditMode');
425+
console.log(initialMcpDataWhenInEditMode);
414426
const normalizeMemberKind = useCallback((kindInput?: string | null) => {
415427
const normalizedKind = (kindInput ?? '').toString().trim().toLowerCase();
416428
return normalizedKind === 'serviceaccount' ? 'ServiceAccount' : 'User';
@@ -467,7 +479,10 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
467479
setValue('members', normalizedMembers, { shouldValidate: true });
468480
appliedTemplateMembersRef.current = true;
469481
}, [selectedStep, selectedTemplate, watch, setValue, user?.email, normalizeMemberRole, normalizeMemberKind]);
470-
482+
const setInitialComponentsListHandler = (components: ComponentsListItem[]) => {
483+
if (!isEditMode) return;
484+
setInitialMcpDataWhenInEditMode({ ...initialMcpDataWhenInEditMode, componentsList: components });
485+
};
471486
useEffect(() => {
472487
if (selectedStep !== 'componentSelection') return;
473488
if (!selectedTemplate) return;
@@ -593,6 +608,7 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
593608
initialSelection={initialSelection}
594609
managedControlPlaneTemplate={selectedTemplate}
595610
isOnMcpPage={isOnMcpPage}
611+
setInitialComponentsList={setInitialComponentsListHandler}
596612
/>
597613
)}
598614
</WizardStep>
@@ -604,6 +620,20 @@ export const CreateManagedControlPlaneWizardContainer: FC<CreateManagedControlPl
604620
data-step="summarize"
605621
>
606622
<SummarizeStep
623+
originalYamlString={stringify(
624+
CreateManagedControlPlane(
625+
initialMcpDataWhenInEditMode.name,
626+
`${projectName}--ws-${workspaceName}`,
627+
{
628+
displayName: initialMcpDataWhenInEditMode.displayName,
629+
chargingTarget: initialMcpDataWhenInEditMode.chargingTarget,
630+
members: initialMcpDataWhenInEditMode.members,
631+
componentsList: initialMcpDataWhenInEditMode.componentsList,
632+
chargingTargetType: initialMcpDataWhenInEditMode.chargingTargetType,
633+
},
634+
idpPrefix,
635+
),
636+
)}
607637
watch={watch}
608638
workspaceName={workspaceName}
609639
projectName={projectName}

src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,26 @@ import YamlViewer from '../../Yaml/YamlViewer.tsx';
1010
import { idpPrefix } from '../../../utils/idpPrefix.ts';
1111
import { UseFormWatch } from 'react-hook-form';
1212
import { CreateDialogProps } from '../../Dialogs/CreateWorkspaceDialogContainer.tsx';
13+
import YamlDiff from '../../Yaml/YamlDiff.tsx';
1314

1415
interface SummarizeStepProps {
1516
watch: UseFormWatch<CreateDialogProps>;
1617
projectName: string;
1718
workspaceName: string;
1819
componentsList?: ComponentsListItem[];
20+
originalYamlString?: string;
1921
}
2022

21-
export const SummarizeStep: React.FC<SummarizeStepProps> = ({ watch, projectName, workspaceName, componentsList }) => {
23+
export const SummarizeStep: React.FC<SummarizeStepProps> = ({
24+
originalYamlString,
25+
watch,
26+
projectName,
27+
workspaceName,
28+
componentsList,
29+
}) => {
2230
const { t } = useTranslation();
31+
console.log('componentsList');
32+
console.log(componentsList);
2333
return (
2434
<>
2535
<Title>{t('common.summarize')}</Title>
@@ -48,23 +58,44 @@ export const SummarizeStep: React.FC<SummarizeStepProps> = ({ watch, projectName
4858
</List>
4959
</div>
5060
<div>
51-
<YamlViewer
52-
yamlString={stringify(
53-
CreateManagedControlPlane(
54-
watch('name'),
55-
`${projectName}--ws-${workspaceName}`,
56-
{
57-
displayName: watch('displayName'),
58-
chargingTarget: watch('chargingTarget'),
59-
members: watch('members'),
60-
componentsList: componentsList ?? [],
61-
chargingTargetType: watch('chargingTargetType'),
62-
},
63-
idpPrefix,
64-
),
65-
)}
66-
filename={`mcp_${projectName}--ws-${workspaceName}`}
67-
/>
61+
{originalYamlString ? (
62+
<YamlDiff
63+
originalYaml={originalYamlString ?? ''}
64+
modifiedYaml={stringify(
65+
CreateManagedControlPlane(
66+
watch('name'),
67+
`${projectName}--ws-${workspaceName}`,
68+
{
69+
displayName: watch('displayName'),
70+
chargingTarget: watch('chargingTarget'),
71+
members: watch('members'),
72+
componentsList: componentsList ?? [],
73+
chargingTargetType: watch('chargingTargetType'),
74+
},
75+
idpPrefix,
76+
),
77+
)}
78+
/>
79+
) : (
80+
<YamlViewer
81+
originalYamlString={originalYamlString}
82+
yamlString={stringify(
83+
CreateManagedControlPlane(
84+
watch('name'),
85+
`${projectName}--ws-${workspaceName}`,
86+
{
87+
displayName: watch('displayName'),
88+
chargingTarget: watch('chargingTarget'),
89+
members: watch('members'),
90+
componentsList: componentsList ?? [],
91+
chargingTargetType: watch('chargingTargetType'),
92+
},
93+
idpPrefix,
94+
),
95+
)}
96+
filename={`mcp_${projectName}--ws-${workspaceName}`}
97+
/>
98+
)}
6899
</div>
69100
</Grid>
70101
</>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* Container wrapper to match YamlViewer spacing if needed */
2+
.container {
3+
width: 100%;
4+
}
5+
6+
/* Line highlight colors for additions/removals */
7+
.added {
8+
background-color: rgba(56, 142, 60, 0.18); /* green-ish */
9+
}
10+
11+
.removed {
12+
background-color: rgba(211, 47, 47, 0.18); /* red-ish */
13+
}

src/components/Yaml/YamlDiff.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { FC, useMemo } from 'react';
2+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
3+
import { materialLight, materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
4+
import { diffLines } from 'diff';
5+
import styles from './YamlDiff.module.css';
6+
import { useTheme } from '../../hooks/useTheme.ts';
7+
8+
type YamlDiffProps = {
9+
originalYaml: string;
10+
modifiedYaml: string;
11+
};
12+
13+
export const YamlDiff: FC<YamlDiffProps> = ({ originalYaml, modifiedYaml }) => {
14+
const { isDarkTheme } = useTheme();
15+
16+
const hunks = useMemo(() => diffLines(originalYaml ?? '', modifiedYaml ?? ''), [originalYaml, modifiedYaml]);
17+
18+
const { content, lineKinds } = useMemo(() => {
19+
const lines: string[] = [];
20+
const kinds: ('added' | 'removed' | 'context')[] = [];
21+
hunks.forEach((part) => {
22+
const prefix = part.added ? '+' : part.removed ? '-' : ' ';
23+
const kind: 'added' | 'removed' | 'context' = part.added ? 'added' : part.removed ? 'removed' : 'context';
24+
const partLines = part.value.replace(/\n$/, '').split('\n');
25+
partLines.forEach((line) => {
26+
lines.push(`${prefix}${line}`);
27+
kinds.push(kind);
28+
});
29+
});
30+
return { content: lines.join('\n'), lineKinds: kinds };
31+
}, [hunks]);
32+
33+
const lineNumberStyle = useMemo(() => ({ paddingRight: '20px', minWidth: '40px', textAlign: 'right' as const }), []);
34+
35+
return (
36+
<div className={styles.container}>
37+
<SyntaxHighlighter
38+
language="diff"
39+
style={isDarkTheme ? materialDark : materialLight}
40+
showLineNumbers
41+
wrapLongLines
42+
lineNumberStyle={lineNumberStyle}
43+
lineProps={(lineNumber) => {
44+
const kind = lineKinds[lineNumber - 1];
45+
if (kind === 'added') return { className: styles.added };
46+
if (kind === 'removed') return { className: styles.removed };
47+
return {};
48+
}}
49+
customStyle={{ margin: 0, padding: '20px', borderRadius: '4px', fontSize: '1rem', background: 'transparent' }}
50+
codeTagProps={{ style: { whiteSpace: 'pre-wrap' } }}
51+
>
52+
{content}
53+
</SyntaxHighlighter>
54+
</div>
55+
);
56+
};
57+
58+
export default YamlDiff;

src/components/Yaml/YamlViewer.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import { FC } from 'react';
22
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
33
import { materialLight, materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
4-
4+
import { createPatch, diffLines } from 'diff';
55
import { Button, FlexBox } from '@ui5/webcomponents-react';
66
import styles from './YamlViewer.module.css';
77
import { useToast } from '../../context/ToastContext.tsx';
88
import { useTranslation } from 'react-i18next';
99
import { useTheme } from '../../hooks/useTheme.ts';
10-
type YamlViewerProps = { yamlString: string; filename: string };
11-
const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
10+
type YamlViewerProps = { originalYamlString?: string; yamlString: string; filename: string };
11+
const YamlViewer: FC<YamlViewerProps> = ({ originalYamlString, yamlString, filename }) => {
1212
const toast = useToast();
1313
const { t } = useTranslation();
1414
const { isDarkTheme } = useTheme();
1515
const copyToClipboard = () => {
1616
navigator.clipboard.writeText(yamlString);
1717
toast.show(t('yaml.copiedToClipboard'));
1818
};
19+
1920
const downloadYaml = () => {
2021
const blob = new Blob([yamlString], { type: 'text/yaml' });
2122
const url = window.URL.createObjectURL(blob);
@@ -28,6 +29,16 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
2829
window.URL.revokeObjectURL(url);
2930
};
3031

32+
const contentToRender =
33+
originalYamlString !== undefined ? createPatch(`${filename}.yaml`, originalYamlString, yamlString) : yamlString;
34+
35+
// console.log(originalYamlString !== undefined ? diffLines(originalYamlString, yamlString) : yamlString);
36+
37+
const language = originalYamlString !== undefined ? 'diff' : 'yaml';
38+
console.log('1');
39+
console.log(yamlString);
40+
console.log('2');
41+
console.log(originalYamlString);
3142
return (
3243
<div className={styles.container}>
3344
<FlexBox className={styles.buttons} direction="Row" justifyContent="End" alignItems="Baseline" gap={16}>
@@ -39,7 +50,7 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
3950
</Button>
4051
</FlexBox>
4152
<SyntaxHighlighter
42-
language="yaml"
53+
language={language}
4354
style={isDarkTheme ? materialDark : materialLight}
4455
showLineNumbers
4556
lineNumberStyle={{
@@ -60,7 +71,7 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
6071
},
6172
}}
6273
>
63-
{yamlString}
74+
{contentToRender}
6475
</SyntaxHighlighter>
6576
</div>
6677
);

0 commit comments

Comments
 (0)