Skip to content

Commit 6ff801c

Browse files
Merge branch 'main' into remove-link
2 parents 3857803 + 2dd91a5 commit 6ff801c

File tree

10 files changed

+135
-22
lines changed

10 files changed

+135
-22
lines changed

frontend-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
"issuerUrl": "issuer-url",
99
"scopes": []
1010
}
11-
}
11+
}

package-lock.json

Lines changed: 7 additions & 7 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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"@types/js-yaml": "^4.0.9",
5454
"@types/node": "^22.13.5",
5555
"@types/react": "^19.0.10",
56-
"@types/react-dom": "19.1.2",
56+
"@types/react-dom": "19.1.3",
5757
"@types/react-syntax-highlighter": "^15.5.13",
5858
"@ui5/webcomponents-cypress-commands": "^2.7.2",
5959
"@vitejs/plugin-react": "^4.3.4",

public/locales/en.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
"permissionErrorMessageSubtitle": "Ask a workspace admin to grant you access.",
4848
"loadingErrorMessage": "Failed to list mcps in workspace"
4949
},
50+
"ControlPlaneCard": {
51+
"deleteConfirmationDialog": "MCP deletion triggered. The list will refresh automatically once completed."
52+
},
5053
"ControlPlaneListAllWorkspaces": {
5154
"emptyListTitleMessage": "No Workspaces created yet",
5255
"emptyListSubtitleMessage": "Create a workspace to get started"
@@ -59,7 +62,14 @@
5962
"typeHeader": "Type",
6063
"messageHeader": "Message",
6164
"reasonHeader": "Reason",
62-
"transitionHeader": "Last transition time"
65+
"transitionHeader": "Last transition time",
66+
"createSupportTicketButton": "Create Support Ticket",
67+
"supportTicketTitleReady": "MCP Ready",
68+
"supportTicketTitleNotReady": "MCP Not Ready",
69+
"supportTicketTitleDeletion": "MCP in Deletion",
70+
"supportTicketTitleIssues": "Issues with Control Plane",
71+
"statusDetailsLabel": "MCP Status",
72+
"detailsLabel": "Details:"
6373
},
6474
"CopyKubeconfigButton": {
6575
"copiedMessage": "Copied to Clipboard",

src/components/ControlPlane/MCPHealthPopoverButton.tsx

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { AnalyticalTable, Icon, Popover } from '@ui5/webcomponents-react';
1+
import {
2+
AnalyticalTable,
3+
Icon,
4+
Popover,
5+
FlexBox,
6+
FlexBoxJustifyContent,
7+
Button,
8+
} from '@ui5/webcomponents-react';
29
import { AnalyticalTableColumnDefinition } from '@ui5/webcomponents-react/wrappers';
310
import PopoverPlacement from '@ui5/webcomponents/dist/types/PopoverPlacement.js';
411
import '@ui5/webcomponents-icons/dist/copy';
@@ -10,14 +17,21 @@ import {
1017
import ReactTimeAgo from 'react-time-ago';
1118
import { AnimatedHoverTextButton } from '../Helper/AnimatedHoverTextButton.tsx';
1219
import { useTranslation } from 'react-i18next';
13-
20+
import { useFrontendConfig } from '../../context/FrontendConfigContext.tsx';
1421
export default function MCPHealthPopoverButton({
1522
mcpStatus,
23+
projectName,
24+
workspaceName,
25+
mcpName,
1626
}: {
1727
mcpStatus: ControlPlaneStatusType | undefined;
28+
projectName: string;
29+
workspaceName: string;
30+
mcpName: string;
1831
}) {
1932
const popoverRef = useRef(null);
2033
const [open, setOpen] = useState(false);
34+
const { links } = useFrontendConfig();
2135

2236
const { t } = useTranslation();
2337

@@ -31,6 +45,46 @@ export default function MCPHealthPopoverButton({
3145
}
3246
};
3347

48+
const getTicketTitle = () => {
49+
switch (mcpStatus?.status) {
50+
case ReadyStatus.Ready:
51+
return t('MCPHealthPopoverButton.supportTicketTitleReady');
52+
case ReadyStatus.NotReady:
53+
return t('MCPHealthPopoverButton.supportTicketTitleNotReady');
54+
case ReadyStatus.InDeletion:
55+
return t('MCPHealthPopoverButton.supportTicketTitleDeletion');
56+
default:
57+
return t('MCPHealthPopoverButton.supportTicketTitleIssues');
58+
}
59+
};
60+
61+
const constructGithubIssuesLink = () => {
62+
const clusterDetails = `${projectName}/${workspaceName}/${mcpName}`;
63+
64+
const statusDetails = mcpStatus?.conditions
65+
? `${t('MCPHealthPopoverButton.statusDetailsLabel')}: ${mcpStatus.status}\n\n${t('MCPHealthPopoverButton.detailsLabel')}\n` +
66+
mcpStatus.conditions
67+
.map((condition) => {
68+
let text = `- ${condition.type}: ${condition.status}\n`;
69+
if (condition.reason)
70+
text += ` - ${t('MCPHealthPopoverButton.reasonHeader')}: ${condition.reason}\n`;
71+
if (condition.message)
72+
text += ` - ${t('MCPHealthPopoverButton.messageHeader')}: ${condition.message}\n`;
73+
return text;
74+
})
75+
.join('')
76+
: '';
77+
78+
const params = new URLSearchParams({
79+
template: '1-mcp_issue.yml',
80+
title: `[${clusterDetails}]: ${getTicketTitle()}`,
81+
'cluster-link': clusterDetails,
82+
'what-happened': statusDetails,
83+
});
84+
85+
return `${links.COM_PAGE_SUPPORT_GITHUB_ISSUE}?${params}`;
86+
};
87+
3488
const statusTableColumns: AnalyticalTableColumnDefinition[] = [
3589
{
3690
Header: t('MCPHealthPopoverButton.statusHeader'),
@@ -77,7 +131,13 @@ export default function MCPHealthPopoverButton({
77131
onClick={handleOpenerClick}
78132
/>
79133
<Popover ref={popoverRef} open={open} placement={PopoverPlacement.Bottom}>
80-
{<StatusTable status={mcpStatus} tableColumns={statusTableColumns} />}
134+
{
135+
<StatusTable
136+
status={mcpStatus}
137+
tableColumns={statusTableColumns}
138+
githubIssuesLink={constructGithubIssuesLink()}
139+
/>
140+
}
81141
</Popover>
82142
</div>
83143
);
@@ -86,10 +146,14 @@ export default function MCPHealthPopoverButton({
86146
function StatusTable({
87147
status,
88148
tableColumns,
149+
githubIssuesLink,
89150
}: {
90151
status: ControlPlaneStatusType | undefined;
91152
tableColumns: AnalyticalTableColumnDefinition[];
153+
githubIssuesLink: string;
92154
}) {
155+
const { t } = useTranslation();
156+
93157
return (
94158
<div style={{ width: 600 }}>
95159
<AnalyticalTable
@@ -101,6 +165,16 @@ function StatusTable({
101165
}) ?? []
102166
}
103167
/>
168+
<FlexBox
169+
justifyContent={FlexBoxJustifyContent.End}
170+
style={{ marginTop: '0.5rem' }}
171+
>
172+
<a href={githubIssuesLink} target="_blank" rel="noreferrer">
173+
<Button>
174+
{t('MCPHealthPopoverButton.createSupportTicketButton')}
175+
</Button>
176+
</a>
177+
</FlexBox>
104178
</div>
105179
);
106180
}

src/components/ControlPlanes/ControlPlaneCard/ControlPlaneCard.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ConnectButton from '../ConnectButton.tsx';
66

77
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
88
import { useState } from 'react';
9+
import { useTranslation } from 'react-i18next';
910

1011
import { DeleteConfirmationDialog } from '../../Dialogs/DeleteConfirmationDialog.tsx';
1112
import MCPHealthPopoverButton from '../../ControlPlane/MCPHealthPopoverButton.tsx';
@@ -23,7 +24,9 @@ import {
2324
PatchMCPResourceForDeletion,
2425
PatchMCPResourceForDeletionBody,
2526
} from '../../../lib/api/types/crate/deleteMCP.ts';
27+
2628
import { YamlViewButton } from '../../Yaml/YamlViewButton.tsx';
29+
import { useToast } from '../../../context/ToastContext.tsx';
2730

2831
interface Props {
2932
controlPlane: ListControlPlanesType;
@@ -37,6 +40,8 @@ export function ControlPlaneCard({
3740
projectName,
3841
}: Props) {
3942
const [dialogDeleteMcpIsOpen, setDialogDeleteMcpIsOpen] = useState(false);
43+
const toast = useToast();
44+
const { t } = useTranslation();
4045

4146
const { trigger: patchTrigger } = useApiResourceMutation<DeleteMCPType>(
4247
PatchMCPResourceForDeletion(
@@ -82,7 +87,12 @@ export function ControlPlaneCard({
8287
alignItems="Center"
8388
className={styles.row}
8489
>
85-
<MCPHealthPopoverButton mcpStatus={controlPlane.status} />
90+
<MCPHealthPopoverButton
91+
mcpStatus={controlPlane.status}
92+
projectName={projectName}
93+
workspaceName={workspace.metadata.name ?? ''}
94+
mcpName={controlPlane.metadata.name}
95+
/>
8696
<FlexBox
8797
direction="Row"
8898
justifyContent="SpaceBetween"
@@ -122,6 +132,7 @@ export function ControlPlaneCard({
122132
onDeletionConfirmed={async () => {
123133
await patchTrigger(PatchMCPResourceForDeletionBody);
124134
await deleteTrigger();
135+
toast.show(t('ControlPlaneCard.deleteConfirmationDialog'));
125136
}}
126137
/>
127138
</>

src/context/FrontendConfigContext.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ReactNode, createContext, use } from 'react';
2-
import { DocLinkCreator } from '../lib/shared/links';
2+
import { LinkCreator } from '../lib/shared/links';
33
import { z } from 'zod';
44

55
export enum Landscape {
@@ -11,7 +11,7 @@ export enum Landscape {
1111
}
1212

1313
interface FrontendConfigContextType extends FrontendConfig {
14-
links: DocLinkCreator;
14+
links: LinkCreator;
1515
}
1616

1717
export const FrontendConfigContext =
@@ -29,7 +29,10 @@ export function FrontendConfigProvider({
2929
children,
3030
}: FrontendConfigProviderProps) {
3131
const config = use(fetchPromise);
32-
const docLinks = new DocLinkCreator(config.documentationBaseUrl);
32+
const docLinks = new LinkCreator(
33+
config.documentationBaseUrl,
34+
config.githubBaseUrl,
35+
);
3336
const value: FrontendConfigContextType = {
3437
links: docLinks,
3538
...config,
@@ -61,6 +64,7 @@ const FrontendConfigSchema = z.object({
6164
backendUrl: z.string(),
6265
gatewayUrl: z.string(),
6366
documentationBaseUrl: z.string(),
67+
githubBaseUrl: z.string(),
6468
oidcConfig: OidcConfigSchema,
6569
landscape: z.optional(z.nativeEnum(Landscape)),
6670
});

src/lib/shared/links.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
export class DocLinkCreator {
1+
export class LinkCreator {
22
private baseUrl: string;
3+
private githubBaseUrl: string;
34

4-
constructor(baseUrl: string) {
5+
constructor(baseUrl: string, githubBaseUrl?: string) {
56
this.baseUrl = baseUrl;
7+
this.githubBaseUrl = githubBaseUrl || baseUrl;
68
}
79
private createLink(path: string) {
810
return `${this.baseUrl}${path}`;
911
}
1012

13+
private createGithubLink(path: string) {
14+
return `${this.githubBaseUrl}${path}`;
15+
}
16+
1117
public get COMMUNITY_PAGE(): string {
1218
return this.createLink('/');
1319
}
@@ -26,4 +32,7 @@ export class DocLinkCreator {
2632
'/docs/managed-control-planes/get-started/get-started-mcp#5-create-managedcontrolplane',
2733
);
2834
}
35+
public get COM_PAGE_SUPPORT_GITHUB_ISSUE(): string {
36+
return this.createGithubLink('/support/issues/new');
37+
}
2938
}

src/utils/testing.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DocLinkCreator } from '../lib/shared/links.ts';
1+
import { LinkCreator } from '../lib/shared/links.ts';
22
import { Landscape } from '../context/FrontendConfigContext.tsx';
33

44
export const isInTestingMode: boolean = !!window.Cypress;
@@ -7,5 +7,5 @@ export const mockedFrontendConfig = {
77
backendUrl: 'http://localhost:3000',
88
landscape: Landscape.Local,
99
documentationBaseUrl: 'http://localhost:3000',
10-
links: new DocLinkCreator(documentationBaseUrl),
10+
links: new LinkCreator(documentationBaseUrl),
1111
};

src/views/ControlPlanes/ControlPlaneView.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,12 @@ export default function ControlPlaneView() {
8181
justifyContent: 'space-between',
8282
}}
8383
>
84-
<MCPHealthPopoverButton mcpStatus={mcp?.status} />
84+
<MCPHealthPopoverButton
85+
mcpStatus={mcp?.status}
86+
projectName={projectName}
87+
workspaceName={workspaceName ?? ''}
88+
mcpName={controlPlaneName}
89+
/>
8590

8691
<CopyKubeconfigButton />
8792
</div>

0 commit comments

Comments
 (0)