From 787115e5673c1e2a4218a0ccfe8b6a1943c05b17 Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Wed, 1 Oct 2025 13:25:25 +0200 Subject: [PATCH 1/3] feat: add YAML splitter --- src/AppRouter.tsx | 34 ++++--- src/components/ControlPlane/FluxList.tsx | 11 ++- .../ControlPlane/ManagedResources.tsx | 3 +- src/components/ControlPlane/Providers.tsx | 3 +- .../ControlPlane/ProvidersConfig.tsx | 3 +- .../ControlPlaneCard/ControlPlaneCard.tsx | 7 +- .../ControlPlaneListWorkspaceGridTile.tsx | 5 +- src/components/Graphs/Graph.tsx | 45 +++------ src/components/Projects/ProjectsList.tsx | 5 +- src/components/Splitter/SplitterContext.tsx | 39 ++++++++ .../Splitter/SplitterLayout.module.css | 9 ++ src/components/Splitter/SplitterLayout.tsx | 30 ++++++ .../SummarizeStep.tsx | 4 +- src/components/Yaml/YamlLoader.tsx | 55 ----------- src/components/Yaml/YamlPanel.module.css | 10 ++ src/components/Yaml/YamlPanel.tsx | 45 +++++++++ src/components/Yaml/YamlSidePanel.module.css | 10 ++ src/components/Yaml/YamlSidePanel.tsx | 96 +++++++++++++++++++ .../Yaml/YamlSidePanelWithLoader.tsx | 29 ++++++ src/components/Yaml/YamlViewButton.module.css | 11 +++ src/components/Yaml/YamlViewButton.tsx | 88 +++++++++-------- .../Yaml/YamlViewButtonWithLoader.tsx | 50 ---------- src/components/Yaml/YamlViewDialog.tsx | 57 ----------- src/components/Yaml/YamlViewer.module.css | 19 ---- src/components/Yaml/YamlViewer.tsx | 37 +------ src/spaces/mcp/pages/McpPage.tsx | 5 +- 26 files changed, 389 insertions(+), 321 deletions(-) create mode 100644 src/components/Splitter/SplitterContext.tsx create mode 100644 src/components/Splitter/SplitterLayout.module.css create mode 100644 src/components/Splitter/SplitterLayout.tsx delete mode 100644 src/components/Yaml/YamlLoader.tsx create mode 100644 src/components/Yaml/YamlPanel.module.css create mode 100644 src/components/Yaml/YamlPanel.tsx create mode 100644 src/components/Yaml/YamlSidePanel.module.css create mode 100644 src/components/Yaml/YamlSidePanel.tsx create mode 100644 src/components/Yaml/YamlSidePanelWithLoader.tsx create mode 100644 src/components/Yaml/YamlViewButton.module.css delete mode 100644 src/components/Yaml/YamlViewButtonWithLoader.tsx delete mode 100644 src/components/Yaml/YamlViewDialog.tsx diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index d47fe664..44a35d43 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -6,6 +6,8 @@ import { SentryRoutes } from './mount.ts'; import ProjectPage from './spaces/onboarding/pages/ProjectPage.tsx'; import McpPage from './spaces/mcp/pages/McpPage.tsx'; import { SearchParamToggleVisibility } from './components/Helper/FeatureToggleExistance.tsx'; +import { SplitterProvider } from './components/Splitter/SplitterContext.tsx'; +import { SplitterLayout } from './components/Splitter/SplitterLayout.tsx'; function AppRouter() { return ( @@ -20,20 +22,24 @@ function AppRouter() { - - - }> - } /> - } /> - } - /> - - } /> - } /> - - + + + + + }> + } /> + } /> + } + /> + + } /> + } /> + + + + ); } diff --git a/src/components/ControlPlane/FluxList.tsx b/src/components/ControlPlane/FluxList.tsx index ccbf5f18..a7f769b1 100644 --- a/src/components/ControlPlane/FluxList.tsx +++ b/src/components/ControlPlane/FluxList.tsx @@ -11,6 +11,7 @@ import { YamlViewButton } from '../Yaml/YamlViewButton.tsx'; import { useMemo } from 'react'; import StatusFilter from '../Shared/StatusFilter/StatusFilter.tsx'; import { ResourceStatusCell } from '../Shared/ResourceStatusCell.tsx'; +import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; export default function FluxList() { const { data: gitReposData, error: repoErr, isLoading: repoIsLoading } = useApiResource(FluxRequest); //404 if component not enabled @@ -81,7 +82,7 @@ export default function FluxList() { accessor: 'yaml', disableFilters: true, Cell: (cellData: CellData) => ( - + ), }, ], @@ -125,7 +126,9 @@ export default function FluxList() { width: 75, accessor: 'yaml', disableFilters: true, - Cell: (cellData: CellData) => , + Cell: (cellData: CellData) => ( + + ), }, ], [t], @@ -173,14 +176,14 @@ export default function FluxList() {
{t('FluxList.gitOpsTitle')} - +
{t('FluxList.kustomizationsTitle')} - + { cell: { @@ -107,7 +108,7 @@ export function ManagedResources() { disableFilters: true, Cell: (cellData: CellData) => cellData.cell.row.original?.item ? ( - + ) : undefined, }, ], diff --git a/src/components/ControlPlane/Providers.tsx b/src/components/ControlPlane/Providers.tsx index 11dc4393..0e9dc16b 100644 --- a/src/components/ControlPlane/Providers.tsx +++ b/src/components/ControlPlane/Providers.tsx @@ -19,6 +19,7 @@ import '@ui5/webcomponents-icons/dist/sys-enter-2'; import '@ui5/webcomponents-icons/dist/sys-cancel-2'; import StatusFilter from '../Shared/StatusFilter/StatusFilter.tsx'; import { ResourceStatusCell } from '../Shared/ResourceStatusCell.tsx'; +import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; interface CellData { cell: { @@ -110,7 +111,7 @@ export function Providers() { accessor: 'yaml', disableFilters: true, Cell: (cellData: CellData) => ( - + ), }, ], diff --git a/src/components/ControlPlane/ProvidersConfig.tsx b/src/components/ControlPlane/ProvidersConfig.tsx index 7cd7b1c9..722c8cea 100644 --- a/src/components/ControlPlane/ProvidersConfig.tsx +++ b/src/components/ControlPlane/ProvidersConfig.tsx @@ -13,6 +13,7 @@ import { formatDateAsTimeAgo } from '../../utils/i18n/timeAgo'; import { YamlViewButton } from '../Yaml/YamlViewButton.tsx'; import { useMemo } from 'react'; +import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; type Rows = { parent: string; @@ -79,7 +80,7 @@ export function ProvidersConfig() { disableFilters: true, Cell: (cellData: CellData) => cellData.cell.row.original?.resource ? ( - + ) : undefined, }, ], diff --git a/src/components/ControlPlanes/ControlPlaneCard/ControlPlaneCard.tsx b/src/components/ControlPlanes/ControlPlaneCard/ControlPlaneCard.tsx index c5564ef2..22dab2d5 100644 --- a/src/components/ControlPlanes/ControlPlaneCard/ControlPlaneCard.tsx +++ b/src/components/ControlPlanes/ControlPlaneCard/ControlPlaneCard.tsx @@ -22,13 +22,13 @@ import { PatchMCPResourceForDeletionBody, } from '../../../lib/api/types/crate/deleteMCP.ts'; -import { YamlViewButtonWithLoader } from '../../Yaml/YamlViewButtonWithLoader.tsx'; +import { YamlViewButton } from '../../Yaml/YamlViewButton.tsx'; import { useToast } from '../../../context/ToastContext.tsx'; import { canConnectToMCP } from '../controlPlanes.ts'; + import { Infobox } from '../../Ui/Infobox/Infobox.tsx'; import { ControlPlaneCardMenu } from './ControlPlaneCardMenu.tsx'; - import { EditManagedControlPlaneWizardDataLoader } from '../../Wizards/CreateManagedControlPlane/EditManagedControlPlaneWizardDataLoader.tsx'; import { DISPLAY_NAME_ANNOTATION } from '../../../lib/api/types/shared/keyNames.ts'; @@ -99,7 +99,8 @@ export const ControlPlaneCard = ({ controlPlane, workspace, projectName }: Props setIsEditManagedControlPlaneWizardOpen={handleIsManagedControlPlaneWizardOpen} /> - - >) => ( @@ -31,33 +30,22 @@ const nodeTypes = { const Graph: React.FC = () => { const { t } = useTranslation(); + const { openInAside } = useSplitter(); const { isDarkTheme } = useTheme(); const [colorBy, setColorBy] = useState('provider'); - const [yamlDialogOpen, setYamlDialogOpen] = useState(false); - const [yamlResource, setYamlResource] = useState(null); - const handleYamlClick = useCallback((item: ManagedResourceItem) => { - setYamlResource(item); - setYamlDialogOpen(true); - }, []); + const handleYamlClick = useCallback( + (item: ManagedResourceItem) => { + const yamlFilename = item + ? `${item.kind ?? ''}${item.metadata?.name ? '_' : ''}${item.metadata?.name ?? ''}` + : ''; - const { nodes, edges, colorMap, loading, error } = useGraph(colorBy, handleYamlClick); - - const yamlString = useMemo( - () => (yamlResource ? stringify(removeManagedFieldsAndFilterData(yamlResource as unknown as Resource, true)) : ''), - [yamlResource], + openInAside(); + }, + [openInAside], ); - const yamlStringToCopy = useMemo( - () => (yamlResource ? stringify(removeManagedFieldsAndFilterData(yamlResource as unknown as Resource, false)) : ''), - [yamlResource], - ); - - const yamlFilename = useMemo(() => { - if (!yamlResource) return ''; - const { kind, metadata } = yamlResource; - return `${kind ?? ''}${metadata?.name ? '_' : ''}${metadata?.name ?? ''}`; - }, [yamlResource]); + const { nodes, edges, colorMap, loading, error } = useGraph(colorBy, handleYamlClick); const legendItems: LegendItem[] = useMemo( () => @@ -136,13 +124,6 @@ const Graph: React.FC = () => {
- - } - /> ); }; diff --git a/src/components/Projects/ProjectsList.tsx b/src/components/Projects/ProjectsList.tsx index 62080c60..3284f27f 100644 --- a/src/components/Projects/ProjectsList.tsx +++ b/src/components/Projects/ProjectsList.tsx @@ -9,7 +9,7 @@ import '@ui5/webcomponents-icons/dist/copy'; import '@ui5/webcomponents-icons/dist/arrow-right'; import { ListProjectNames } from '../../lib/api/types/crate/listProjectNames'; import { t } from 'i18next'; -import { YamlViewButtonWithLoader } from '../Yaml/YamlViewButtonWithLoader.tsx'; +import { YamlViewButton } from '../Yaml/YamlViewButton.tsx'; import { useMemo } from 'react'; import { ProjectsListItemMenu } from './ProjectsListItemMenu.tsx'; @@ -98,7 +98,8 @@ export default function ProjectsList() { alignItems: 'center', }} > - diff --git a/src/components/Splitter/SplitterContext.tsx b/src/components/Splitter/SplitterContext.tsx new file mode 100644 index 00000000..8f1e0789 --- /dev/null +++ b/src/components/Splitter/SplitterContext.tsx @@ -0,0 +1,39 @@ +import { createContext, ReactNode, use, useCallback, useMemo, useState } from 'react'; + +interface SplitterContextType { + isAsideVisible: boolean; + asideContent: ReactNode; + closeAside: () => void; + openInAside: (content: ReactNode) => void; +} + +const SplitterContext = createContext(null); + +export function SplitterProvider({ children }: { children: ReactNode }) { + const [isAsideVisible, setIsAsideVisible] = useState(false); + const [asideContent, setAsideContent] = useState(null); + + const openInAside = useCallback((node: ReactNode) => { + setAsideContent(node); + setIsAsideVisible(true); + }, []); + + const closeAside = useCallback(() => { + setIsAsideVisible(false); + setAsideContent(null); + }, []); + + const value = useMemo(() => { + return { isAsideVisible, asideContent, closeAside, openInAside }; + }, [isAsideVisible, asideContent, closeAside, openInAside]); + + return {children}; +} + +export function useSplitter() { + const context = use(SplitterContext); + if (!context) { + throw new Error('useSplitter must be used within an SplitterProvider.'); + } + return context; +} diff --git a/src/components/Splitter/SplitterLayout.module.css b/src/components/Splitter/SplitterLayout.module.css new file mode 100644 index 00000000..1285c831 --- /dev/null +++ b/src/components/Splitter/SplitterLayout.module.css @@ -0,0 +1,9 @@ +.splitter { + width: 100%; + height: calc(100% - 3.25rem); +} + +.asideContent { + width: 100%; + background-color: var(--sapGroup_TitleBackground); +} diff --git a/src/components/Splitter/SplitterLayout.tsx b/src/components/Splitter/SplitterLayout.tsx new file mode 100644 index 00000000..09c0f0c5 --- /dev/null +++ b/src/components/Splitter/SplitterLayout.tsx @@ -0,0 +1,30 @@ +import { ReactNode } from 'react'; +import { SplitterElement, SplitterLayout as Ui5SplitterLayout } from '@ui5/webcomponents-react'; +import { useSplitter } from './SplitterContext.tsx'; + +import styles from './SplitterLayout.module.css'; + +export interface SplitterLayoutProps { + children: ReactNode; // main content +} +export function SplitterLayout({ children }: SplitterLayoutProps) { + const { isAsideVisible, asideContent } = useSplitter(); + + return ( + + {children} + + {isAsideVisible ? ( + + {asideContent} + + ) : null} + + ); +} diff --git a/src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx b/src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx index c4c7ae98..b7182040 100644 --- a/src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx +++ b/src/components/Wizards/CreateManagedControlPlane/SummarizeStep.tsx @@ -6,7 +6,7 @@ import { ComponentsListItem, CreateManagedControlPlane, } from '../../../lib/api/types/crate/createManagedControlPlane.ts'; -import YamlViewer from '../../Yaml/YamlViewer.tsx'; +import YamlPanel from '../../Yaml/YamlPanel.tsx'; import { idpPrefix } from '../../../utils/idpPrefix.ts'; import { UseFormWatch } from 'react-hook-form'; import { CreateDialogProps } from '../../Dialogs/CreateWorkspaceDialogContainer.tsx'; @@ -78,7 +78,7 @@ export const SummarizeStep: React.FC = ({ )} /> ) : ( - void; -} - -export const YamlLoader: FC = ({ - 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 ; - if (error) { - return ; - } - - return ( - - ); -}; diff --git a/src/components/Yaml/YamlPanel.module.css b/src/components/Yaml/YamlPanel.module.css new file mode 100644 index 00000000..046617cd --- /dev/null +++ b/src/components/Yaml/YamlPanel.module.css @@ -0,0 +1,10 @@ +.container { + position: relative; +} + +.buttons { + position: sticky; + top: 0; + right: 0; + z-index: 1; +} diff --git a/src/components/Yaml/YamlPanel.tsx b/src/components/Yaml/YamlPanel.tsx new file mode 100644 index 00000000..1587c3d0 --- /dev/null +++ b/src/components/Yaml/YamlPanel.tsx @@ -0,0 +1,45 @@ +import { FC } from 'react'; +import { Button, FlexBox } from '@ui5/webcomponents-react'; +import styles from './YamlPanel.module.css'; +import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts'; +import { useTranslation } from 'react-i18next'; +import { SHOW_DOWNLOAD_BUTTON } from './YamlSidePanel.tsx'; +import { YamlViewer } from './YamlViewer.tsx'; +type YamlPanelProps = { + yamlString: string; + filename: string; +}; + +const YamlPanel: FC = ({ yamlString, filename }) => { + const { t } = useTranslation(); + const { copyToClipboard } = useCopyToClipboard(); + const downloadYaml = () => { + const blob = new Blob([yamlString], { type: 'text/yaml' }); + const url = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `${filename}.yaml`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + }; + + return ( +
+ + + {SHOW_DOWNLOAD_BUTTON && ( + + )} + + +
+ ); +}; + +export default YamlPanel; diff --git a/src/components/Yaml/YamlSidePanel.module.css b/src/components/Yaml/YamlSidePanel.module.css new file mode 100644 index 00000000..7112b16d --- /dev/null +++ b/src/components/Yaml/YamlSidePanel.module.css @@ -0,0 +1,10 @@ +.panel { + width: 100%; +} + +.content { + display: flex; + overflow-y: scroll; + height: 100%; + width: 100%; +} diff --git a/src/components/Yaml/YamlSidePanel.tsx b/src/components/Yaml/YamlSidePanel.tsx new file mode 100644 index 00000000..cf0cda23 --- /dev/null +++ b/src/components/Yaml/YamlSidePanel.tsx @@ -0,0 +1,96 @@ +import { + CheckBox, + FlexBox, + Panel, + Title, + Toolbar, + ToolbarButton, + ToolbarSeparator, + ToolbarSpacer, +} from '@ui5/webcomponents-react'; + +import { useTranslation } from 'react-i18next'; +import { YamlViewer } from './YamlViewer.tsx'; +import { useSplitter } from '../Splitter/SplitterContext.tsx'; +import { useMemo, useState } from 'react'; +import { stringify } from 'yaml'; +import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; +import { useCopyToClipboard } from '../../hooks/useCopyToClipboard.ts'; +import styles from './YamlSidePanel.module.css'; + +export const SHOW_DOWNLOAD_BUTTON = false; // Download button is hidden now due to stakeholder request + +export interface YamlSidePanelProps { + resource: Resource; + filename: string; +} +export function YamlSidePanel({ resource, filename }: YamlSidePanelProps) { + const [showOnlyImportantData, setShowOnlyImportantData] = useState(false); + const { closeAside } = useSplitter(); + const { t } = useTranslation(); + + const yamlStringToDisplay = useMemo(() => { + return stringify(removeManagedFieldsAndFilterData(resource, showOnlyImportantData)); + }, [resource, showOnlyImportantData]); + const yamlStringToCopy = useMemo(() => { + return stringify(removeManagedFieldsAndFilterData(resource, false)); + }, [resource]); + + const { copyToClipboard } = useCopyToClipboard(); + const handleDownloadClick = () => { + const blob = new Blob([yamlStringToCopy], { type: 'text/yaml' }); + const url = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `${filename}.yaml`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + }; + + return ( + + YAML + + + setShowOnlyImportantData(!showOnlyImportantData)} + /> + + copyToClipboard(yamlStringToCopy)} + /> + {SHOW_DOWNLOAD_BUTTON ? ( + + ) : null} + + + + } + > +
+ +
+
+ ); +} diff --git a/src/components/Yaml/YamlSidePanelWithLoader.tsx b/src/components/Yaml/YamlSidePanelWithLoader.tsx new file mode 100644 index 00000000..48a3d10a --- /dev/null +++ b/src/components/Yaml/YamlSidePanelWithLoader.tsx @@ -0,0 +1,29 @@ +import { useApiResource } from '../../lib/api/useApiResource.ts'; +import { ResourceObject } from '../../lib/api/types/crate/resourceObject.ts'; +import { useTranslation } from 'react-i18next'; +import Loading from '../Shared/Loading.tsx'; +import IllustratedError from '../Shared/IllustratedError.tsx'; + +import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; +import { YamlSidePanel } from './YamlSidePanel.tsx'; + +export interface YamlSidePanelWithLoaderProps { + workspaceName?: string; + resourceType: 'projects' | 'workspaces' | 'managedcontrolplanes'; + resourceName: string; +} +export function YamlSidePanelWithLoader({ workspaceName, resourceType, resourceName }: YamlSidePanelWithLoaderProps) { + const { t } = useTranslation(); + const { isLoading, data, error } = useApiResource( + ResourceObject(workspaceName ?? '', resourceType, resourceName), + undefined, + true, + ); + + if (isLoading) return ; + if (error) return ; + + const filename = `${workspaceName ? `${workspaceName}_` : ''}${resourceType}_${resourceName}`; + + return ; +} diff --git a/src/components/Yaml/YamlViewButton.module.css b/src/components/Yaml/YamlViewButton.module.css new file mode 100644 index 00000000..e871c4e7 --- /dev/null +++ b/src/components/Yaml/YamlViewButton.module.css @@ -0,0 +1,11 @@ +.button { + width: 4rem; + display: flex; + align-items: center; + justify-content: center; + + svg { + width: 32px; + transform: translateY(1px); + } +} diff --git a/src/components/Yaml/YamlViewButton.tsx b/src/components/Yaml/YamlViewButton.tsx index 4f1aef0a..735fd340 100644 --- a/src/components/Yaml/YamlViewButton.tsx +++ b/src/components/Yaml/YamlViewButton.tsx @@ -1,58 +1,66 @@ import { Button } from '@ui5/webcomponents-react'; -import { FC, useMemo, useState } from 'react'; -import styles from './YamlViewer.module.css'; +import styles from './YamlViewButton.module.css'; import { useTranslation } from 'react-i18next'; -import YamlViewer from './YamlViewer.tsx'; -import { stringify } from 'yaml'; -import { removeManagedFieldsAndFilterData, Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; +import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts'; import { YamlIcon } from './YamlIcon.tsx'; -import { YamlViewDialog } from './YamlViewDialog.tsx'; +import { useSplitter } from '../Splitter/SplitterContext.tsx'; +import { YamlSidePanel } from './YamlSidePanel.tsx'; +import { YamlSidePanelWithLoader } from './YamlSidePanelWithLoader.tsx'; -export type YamlViewButtonProps = { - resourceObject: unknown; -}; +export interface YamlViewButtonResourceProps { + variant: 'resource'; + resource: Resource; +} +export interface YamlViewButtonLoaderProps { + variant: 'loader'; + workspaceName?: string; + resourceType: 'projects' | 'workspaces' | 'managedcontrolplanes'; + resourceName: string; +} +export type YamlViewButtonProps = YamlViewButtonResourceProps | YamlViewButtonLoaderProps; -export const YamlViewButton: FC = ({ resourceObject }) => { - const [showOnlyImportantData, setShowOnlyImportantData] = useState(true); - const [isOpen, setIsOpen] = useState(false); +export function YamlViewButton(props: YamlViewButtonProps) { const { t } = useTranslation(); - const resource = resourceObject as Resource; + const { openInAside } = useSplitter(); - const yamlString = useMemo(() => { - return stringify(removeManagedFieldsAndFilterData(resource, showOnlyImportantData)); - }, [resource, showOnlyImportantData]); - const yamlStringToCopy = useMemo(() => { - return stringify(removeManagedFieldsAndFilterData(resource, false)); - }, [resource]); - return ( - - { + switch (props.variant) { + case 'resource': { + const { resource } = props; + openInAside( + - } - setShowOnlyImportantData={setShowOnlyImportantData} - showOnlyImportantData={showOnlyImportantData} - /> + />, + ); + break; + } + + case 'loader': { + const { workspaceName, resourceType, resourceName } = props; + openInAside( + , + ); + break; + } + } + }; + return ( + ); -}; +} diff --git a/src/components/Yaml/YamlViewButtonWithLoader.tsx b/src/components/Yaml/YamlViewButtonWithLoader.tsx deleted file mode 100644 index b5565b0f..00000000 --- a/src/components/Yaml/YamlViewButtonWithLoader.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Button } from '@ui5/webcomponents-react'; -import { FC, useState } from 'react'; -import { YamlLoader } from './YamlLoader.tsx'; -import { useTranslation } from 'react-i18next'; -import styles from './YamlViewer.module.css'; -import { YamlIcon } from './YamlIcon.tsx'; -import { YamlViewDialog } from './YamlViewDialog.tsx'; - -export type YamlViewButtonProps = { - workspaceName?: string; - resourceType: 'projects' | 'workspaces' | 'managedcontrolplanes'; - resourceName: string; -}; - -export const YamlViewButtonWithLoader: FC = ({ workspaceName, resourceType, resourceName }) => { - const [showOnlyImportantData, setShowOnlyImportantData] = useState(true); - const [isOpen, setIsOpen] = useState(false); - const { t } = useTranslation(); - return ( - - - } - setShowOnlyImportantData={setShowOnlyImportantData} - showOnlyImportantData={showOnlyImportantData} - /> - - - - ); -}; diff --git a/src/components/Yaml/YamlViewDialog.tsx b/src/components/Yaml/YamlViewDialog.tsx deleted file mode 100644 index ca5826cb..00000000 --- a/src/components/Yaml/YamlViewDialog.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Bar, Button, CheckBox, Dialog } from '@ui5/webcomponents-react'; - -import { FC, ReactNode } from 'react'; -import { useTranslation } from 'react-i18next'; - -export type YamlViewDialogProps = { - isOpen: boolean; - setIsOpen: (isOpen: boolean) => void; - dialogContent: ReactNode; - showOnlyImportantData?: boolean; - setShowOnlyImportantData?: (showOnlyImportantData: boolean) => void; -}; - -export const YamlViewDialog: FC = ({ - isOpen, - setIsOpen, - dialogContent, - showOnlyImportantData, - setShowOnlyImportantData, -}) => { - const { t } = useTranslation(); - const handleShowOnlyImportantData = () => { - setShowOnlyImportantData?.(!showOnlyImportantData); - }; - return ( - - ) - } - design="Footer" - endContent={ - - } - /> - } - onClick={(e) => e.stopPropagation()} - onClose={() => { - setIsOpen(false); - }} - > - {isOpen && dialogContent} - - ); -}; diff --git a/src/components/Yaml/YamlViewer.module.css b/src/components/Yaml/YamlViewer.module.css index 2ac78014..4867abeb 100644 --- a/src/components/Yaml/YamlViewer.module.css +++ b/src/components/Yaml/YamlViewer.module.css @@ -1,22 +1,3 @@ .container { position: relative; } - -.buttons { - position: sticky; - top: 0; - right: 0; - z-index: 1; -} - -.button { - width: 4rem; - display: flex; - align-items: center; - justify-content: center; - - svg { - width: 32px; - transform: translateY(1px); - } -} \ No newline at end of file diff --git a/src/components/Yaml/YamlViewer.tsx b/src/components/Yaml/YamlViewer.tsx index e48dab60..575c7c03 100644 --- a/src/components/Yaml/YamlViewer.tsx +++ b/src/components/Yaml/YamlViewer.tsx @@ -2,50 +2,17 @@ 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'; 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 = ({ yamlString, filename, yamlStringToCopy }) => { - const { t } = useTranslation(); +export const YamlViewer: FC = ({ yamlString }) => { const { isDarkTheme } = useTheme(); - const { copyToClipboard } = useCopyToClipboard(); - const downloadYaml = () => { - const blob = new Blob([yamlString], { type: 'text/yaml' }); - const url = window.URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = `${filename}.yaml`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - window.URL.revokeObjectURL(url); - }; return (
- - - {SHOW_DOWNLOAD_BUTTON && ( - - )} - = ({ yamlString, filename, yamlStringToCop
); }; - -export default YamlViewer; diff --git a/src/spaces/mcp/pages/McpPage.tsx b/src/spaces/mcp/pages/McpPage.tsx index fbf3248f..d6b0fa29 100644 --- a/src/spaces/mcp/pages/McpPage.tsx +++ b/src/spaces/mcp/pages/McpPage.tsx @@ -29,7 +29,7 @@ import ComponentList from '../../../components/ControlPlane/ComponentList.tsx'; import MCPHealthPopoverButton from '../../../components/ControlPlane/MCPHealthPopoverButton.tsx'; import { useApiResource } from '../../../lib/api/useApiResource.ts'; -import { YamlViewButtonWithLoader } from '../../../components/Yaml/YamlViewButtonWithLoader.tsx'; +import { YamlViewButton } from '../../../components/Yaml/YamlViewButton.tsx'; import { Landscapers } from '../../../components/ControlPlane/Landscapers.tsx'; import { AuthProviderMcp } from '../auth/AuthContextMcp.tsx'; import { isNotFoundError } from '../../../lib/api/error.ts'; @@ -105,7 +105,8 @@ export default function McpPage() { workspaceName={workspaceName ?? ''} mcpName={controlPlaneName} /> - Date: Wed, 1 Oct 2025 13:27:05 +0200 Subject: [PATCH 2/3] Update src/components/Yaml/YamlSidePanel.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/Yaml/YamlSidePanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Yaml/YamlSidePanel.tsx b/src/components/Yaml/YamlSidePanel.tsx index cf0cda23..6f686bfc 100644 --- a/src/components/Yaml/YamlSidePanel.tsx +++ b/src/components/Yaml/YamlSidePanel.tsx @@ -25,7 +25,7 @@ export interface YamlSidePanelProps { filename: string; } export function YamlSidePanel({ resource, filename }: YamlSidePanelProps) { - const [showOnlyImportantData, setShowOnlyImportantData] = useState(false); + const [showOnlyImportantData, setShowOnlyImportantData] = useState(true); const { closeAside } = useSplitter(); const { t } = useTranslation(); From 333cb1c3d13600041258192fc7700091082ccdb6 Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Wed, 1 Oct 2025 14:33:31 +0200 Subject: [PATCH 3/3] add comment --- src/components/Splitter/SplitterLayout.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Splitter/SplitterLayout.module.css b/src/components/Splitter/SplitterLayout.module.css index 1285c831..f7a69efc 100644 --- a/src/components/Splitter/SplitterLayout.module.css +++ b/src/components/Splitter/SplitterLayout.module.css @@ -1,6 +1,6 @@ .splitter { width: 100%; - height: calc(100% - 3.25rem); + height: calc(100% - 3.25rem); /* subtract height of ShellBar */ } .asideContent {