Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
3 changes: 2 additions & 1 deletion public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@
"update": "Update"
},
"yaml": {
"YAML": "File"
"YAML": "File",
"showOnlyImportant": "Show only important fields"
},
"createMCP": {
"dialogTitle": "Create Managed Control Plane",
Expand Down
4 changes: 2 additions & 2 deletions src/components/Graphs/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Legend, LegendItem } from './Legend';
import { YamlViewDialog } from '../Yaml/YamlViewDialog';
import YamlViewer from '../Yaml/YamlViewer';
import { stringify } from 'yaml';
import { removeManagedFieldsProperty } from '../../utils/removeManagedFieldsProperty';
import { removeManagedFieldsAndFilterData } from '../../utils/removeManagedFieldsAndFilterData.ts';
import { useTranslation } from 'react-i18next';
import { useGraph } from './useGraph';
import { ManagedResourceItem } from '../../lib/shared/types';
Expand Down Expand Up @@ -44,7 +44,7 @@ const Graph: React.FC = () => {
const { nodes, edges, colorMap, loading, error } = useGraph(colorBy, handleYamlClick);

const yamlString = useMemo(
() => (yamlResource ? stringify(removeManagedFieldsProperty(yamlResource)) : ''),
() => (yamlResource ? stringify(removeManagedFieldsAndFilterData(yamlResource)) : ''),
[yamlResource],
);

Expand Down
31 changes: 27 additions & 4 deletions src/components/Yaml/YamlLoader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { YamlViewButtonProps } from './YamlViewButtonWithLoader.tsx';
import { FC } from 'react';
import { FC, useMemo } from 'react';

import { stringify } from 'yaml';

Expand All @@ -9,24 +9,47 @@ import Loading from '../Shared/Loading.tsx';
import IllustratedError from '../Shared/IllustratedError.tsx';
import YamlViewer from './YamlViewer.tsx';
import { useApiResource } from '../../lib/api/useApiResource';
import { removeManagedFieldsProperty, Resource } from '../../utils/removeManagedFieldsProperty.ts';
import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts';

export const YamlLoader: FC<YamlViewButtonProps> = ({ workspaceName, resourceType, resourceName }) => {
interface YamlLoaderProps extends YamlViewButtonProps {
showOnlyImportantData?: boolean;
setShowOnlyImportantData?: (showOnlyImportantData: boolean) => void;
}

export const YamlLoader: FC<YamlLoaderProps> = ({
workspaceName,
resourceType,
resourceName,
showOnlyImportantData = false,
setShowOnlyImportantData,
}) => {
const { isLoading, data, error } = useApiResource(
ResourceObject(workspaceName ?? '', resourceType, resourceName),
undefined,
true,
);
const { t } = useTranslation();
const yamlString = useMemo(() => {
if (isLoading || error) return '';
return stringify(removeManagedFieldsAndFilterData(data as Resource, showOnlyImportantData));
}, [data, error, isLoading, showOnlyImportantData]);

const yamlStringToCopy = useMemo(() => {
if (isLoading || error) return '';
return stringify(removeManagedFieldsAndFilterData(data as Resource, false));
}, [data, error, isLoading]);
if (isLoading) return <Loading />;
if (error) {
return <IllustratedError details={t('common.cannotLoadData')} />;
}

return (
<YamlViewer
yamlString={stringify(removeManagedFieldsProperty(data as Resource))}
yamlString={yamlString}
yamlStringToCopy={yamlStringToCopy}
filename={`${workspaceName ? `${workspaceName}_` : ''}${resourceType}_${resourceName}`}
setShowOnlyImportantData={setShowOnlyImportantData}
showOnlyImportantData={showOnlyImportantData}
/>
);
};
11 changes: 9 additions & 2 deletions src/components/Yaml/YamlViewButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styles from './YamlViewer.module.css';
import { useTranslation } from 'react-i18next';
import YamlViewer from './YamlViewer.tsx';
import { stringify } from 'yaml';
import { removeManagedFieldsProperty, Resource } from '../../utils/removeManagedFieldsProperty.ts';
import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts';
import { YamlIcon } from './YamlIcon.tsx';
import { YamlViewDialog } from './YamlViewDialog.tsx';

Expand All @@ -13,12 +13,16 @@ export type YamlViewButtonProps = {
};

export const YamlViewButton: FC<YamlViewButtonProps> = ({ resourceObject }) => {
const [showOnlyImportantData, setShowOnlyImportantData] = useState(true);
const [isOpen, setIsOpen] = useState(false);
const { t } = useTranslation();
const resource = resourceObject as Resource;

const yamlString = useMemo(() => {
return stringify(removeManagedFieldsProperty(resource));
return stringify(removeManagedFieldsAndFilterData(resource, showOnlyImportantData));
}, [resource, showOnlyImportantData]);
const yamlStringToCopy = useMemo(() => {
return stringify(removeManagedFieldsAndFilterData(resource, false));
}, [resource]);
return (
<span>
Expand All @@ -27,8 +31,11 @@ export const YamlViewButton: FC<YamlViewButtonProps> = ({ resourceObject }) => {
setIsOpen={setIsOpen}
dialogContent={
<YamlViewer
yamlStringToCopy={yamlStringToCopy}
yamlString={yamlString}
filename={`${resource?.kind ?? ''}${resource?.metadata?.name ? '_' : ''}${resource?.metadata?.name ?? ''}`}
setShowOnlyImportantData={setShowOnlyImportantData}
showOnlyImportantData={showOnlyImportantData}
/>
}
/>
Expand Down
15 changes: 12 additions & 3 deletions src/components/Yaml/YamlViewButtonWithLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import styles from './YamlViewer.module.css';
import { YamlIcon } from './YamlIcon.tsx';
import { YamlViewDialog } from './YamlViewDialog.tsx';

export type YamlViewButtonProps = {
export interface YamlViewButtonProps {
workspaceName?: string;
resourceType: 'projects' | 'workspaces' | 'managedcontrolplanes';
resourceName: string;
};
}

export const YamlViewButtonWithLoader: FC<YamlViewButtonProps> = ({ workspaceName, resourceType, resourceName }) => {
const [showOnlyImportantData, setShowOnlyImportantData] = useState(true);
const [isOpen, setIsOpen] = useState(false);
const { t } = useTranslation();
return (
Expand All @@ -21,8 +22,16 @@ export const YamlViewButtonWithLoader: FC<YamlViewButtonProps> = ({ workspaceNam
isOpen={isOpen}
setIsOpen={setIsOpen}
dialogContent={
<YamlLoader workspaceName={workspaceName} resourceName={resourceName} resourceType={resourceType} />
<YamlLoader
workspaceName={workspaceName}
resourceName={resourceName}
resourceType={resourceType}
showOnlyImportantData={showOnlyImportantData}
setShowOnlyImportantData={setShowOnlyImportantData}
/>
}
setShowOnlyImportantData={setShowOnlyImportantData}
showOnlyImportantData={showOnlyImportantData}
/>

<Button
Expand Down
27 changes: 24 additions & 3 deletions src/components/Yaml/YamlViewDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Bar, Button, Dialog } from '@ui5/webcomponents-react';
import { Bar, Button, CheckBox, Dialog } from '@ui5/webcomponents-react';

import { FC, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
Expand All @@ -7,19 +7,40 @@ export type YamlViewDialogProps = {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
dialogContent: ReactNode;
showOnlyImportantData?: boolean;
setShowOnlyImportantData?: (showOnlyImportantData: boolean) => void;
};

export const YamlViewDialog: FC<YamlViewDialogProps> = ({ isOpen, setIsOpen, dialogContent }) => {
export const YamlViewDialog: FC<YamlViewDialogProps> = ({
isOpen,
setIsOpen,
dialogContent,
showOnlyImportantData,
setShowOnlyImportantData,
}) => {
const { t } = useTranslation();
const handleShowOnlyImportantData = () => {
setShowOnlyImportantData?.(!showOnlyImportantData);
};
return (
<Dialog
open={isOpen}
stretch
initialFocus={'closeButton'}
footer={
<Bar
startContent={
setShowOnlyImportantData && (
<CheckBox
text={t('yaml.showOnlyImportant')}
checked={showOnlyImportantData}
onChange={handleShowOnlyImportantData}
/>
)
}
design="Footer"
endContent={
<Button design="Emphasized" onClick={() => setIsOpen(false)}>
<Button design="Emphasized" id={'closeButton'} onClick={() => setIsOpen(false)}>
{t('common.close')}
</Button>
}
Expand Down
24 changes: 18 additions & 6 deletions src/components/Yaml/YamlViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ import styles from './YamlViewer.module.css';
import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts';
import { useTranslation } from 'react-i18next';
import { useTheme } from '../../hooks/useTheme.ts';
type YamlViewerProps = { yamlString: string; filename: string };
const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
type YamlViewerProps = {
yamlString: string;
yamlStringToCopy: string;
filename: string;
showOnlyImportantData?: boolean;
setShowOnlyImportantData?: (showOnlyImportantData: boolean) => void;
};

// Download button is hidden now due to stakeholder request
const SHOW_DOWNLOAD_BUTTON = false;

const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename, yamlStringToCopy }) => {
const { t } = useTranslation();
const { isDarkTheme } = useTheme();
const { copyToClipboard } = useCopyToClipboard();
Expand All @@ -27,12 +37,14 @@ const YamlViewer: FC<YamlViewerProps> = ({ yamlString, filename }) => {
return (
<div className={styles.container}>
<FlexBox className={styles.buttons} direction="Row" justifyContent="End" alignItems="Baseline" gap={16}>
<Button icon="copy" onClick={() => copyToClipboard(yamlString)}>
<Button icon="copy" onClick={() => copyToClipboard(yamlStringToCopy)}>
{t('buttons.copy')}
</Button>
<Button icon="download" onClick={downloadYaml}>
{t('buttons.download')}
</Button>
{SHOW_DOWNLOAD_BUTTON && (
<Button icon="download" onClick={downloadYaml}>
{t('buttons.download')}
</Button>
)}
</FlexBox>
<SyntaxHighlighter
language="yaml"
Expand Down
1 change: 1 addition & 0 deletions src/lib/api/types/shared/keyNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export const CHARGING_TARGET_LABEL: string = 'openmcp.cloud.sap/charging-target'
export const CHARGING_TARGET_TYPE_LABEL: string = 'openmcp.cloud.sap/charging-target-type';
export const PROJECT_NAME_LABEL: string = 'openmcp.cloud/mcp-project';
export const WORKSPACE_LABEL: string = 'openmcp.cloud/mcp-workspace';
export const LAST_APPLIED_CONFIGURATION_ANNOTATION = 'kubectl.kubernetes.io/last-applied-configuration';
67 changes: 67 additions & 0 deletions src/utils/removeManagedFieldsAndFilterData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { LAST_APPLIED_CONFIGURATION_ANNOTATION } from '../lib/api/types/shared/keyNames';

export type Resource = {
apiVersion: string;
kind: string;
items?: Omit<Resource, 'items'>[];
metadata: {
name: string;
namespace?: string;
labels?: Record<string, string>;
annotations?: {
[LAST_APPLIED_CONFIGURATION_ANNOTATION]?: string;
[key: string]: string | undefined;
};
managedFields?: unknown;
creationTimestamp?: string;
finalizers?: string[];
generation?: number;
resourceVersion?: string;
uid?: string;
};
spec?: unknown;
status?: unknown;
};

export const removeManagedFieldsAndFilterData = (resourceObject: Resource, showOnlyImportantData: boolean) => {
console.log(resourceObject);
if (resourceObject?.metadata?.managedFields) {
return {
...resourceObject,
metadata: {
...resourceObject.metadata,
managedFields: undefined,
annotations: {
...resourceObject.metadata.annotations,
[LAST_APPLIED_CONFIGURATION_ANNOTATION]: showOnlyImportantData
? undefined
: resourceObject?.metadata?.annotations?.[LAST_APPLIED_CONFIGURATION_ANNOTATION],
},
generation: showOnlyImportantData ? undefined : resourceObject?.metadata?.generation,
uid: showOnlyImportantData ? undefined : resourceObject?.metadata?.uid,
},
};
}
if (resourceObject?.items) {
return {
...resourceObject,
items: resourceObject.items.map((item) => ({
...item,
metadata: {
...item.metadata,
managedFields: undefined,
annotations: {
...resourceObject.metadata.annotations,
[LAST_APPLIED_CONFIGURATION_ANNOTATION]: showOnlyImportantData
? undefined
: resourceObject?.metadata?.annotations?.[LAST_APPLIED_CONFIGURATION_ANNOTATION],
},
generation: showOnlyImportantData ? undefined : resourceObject?.metadata?.generation,
uid: showOnlyImportantData ? undefined : resourceObject?.metadata?.uid,
},
})),
};
}

return resourceObject;
};
36 changes: 0 additions & 36 deletions src/utils/removeManagedFieldsProperty.ts

This file was deleted.

Loading