Skip to content
This repository was archived by the owner on Jul 24, 2025. It is now read-only.

Commit 92c5166

Browse files
committed
Merge pull request #2 from ilan-pinto/patternfly-klusterlet
feat: klusterlet and dashboard fixes Signed-off-by: Ilan Pinto <ilpinto@redhat.com>
2 parents 4ef114e + daac146 commit 92c5166

11 files changed

Lines changed: 227 additions & 100 deletions

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
"out": true // set this to false to include "out" folder in search results
88
},
99
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10-
"typescript.tsc.autoDetect": "off"
10+
"typescript.tsc.autoDetect": "off",
11+
"cSpell.words": [
12+
"klusterlet"
13+
]
1114
}

webview-ui/src/App.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import React from "react";
22
import ShowSelectedContext from "./comp/SelectedContext";
3-
import ShowKlusterlets from "./comp/Klusterlets";
4-
import ShowAppliedManifestWorks from "./comp/AppliedManifestWorks";
5-
import ShowSubscriptionStatuses from "./comp/SubscriptionStatuses";
3+
64
import OcmHeader from "./comp/Header";
75
import { Page, PageSection } from "@patternfly/react-core";
86
import ClusterManagerPage from "./parent/clusterManagerParent";
7+
import ManagedClusterPage from "./parent/managedClusterParent";
98

109

1110

@@ -20,11 +19,8 @@ export default class App extends React.Component {
2019
header= { <OcmHeader /> } >
2120
<PageSection style={{ color: "black" }}>
2221
<ShowSelectedContext/>
23-
<ClusterManagerPage/>
24-
25-
<ShowKlusterlets/>
26-
<ShowAppliedManifestWorks/>
27-
<ShowSubscriptionStatuses/>
22+
<ClusterManagerPage/>
23+
<ManagedClusterPage/>
2824
</PageSection>
2925
</Page>
3026
)

webview-ui/src/common/Graph.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const resourceTranslationMap:ResourceObject = {
3131
configmap: 'cm',
3232
secret: 'secret',
3333
ingress: 'ing',
34-
serviceaccount: 'sa',
34+
serviceaccount: 'sa',
3535
cronjob: 'cronjob',
3636
endpoint: 'ep',
3737
limitrange: 'limits',
@@ -67,14 +67,16 @@ export const Graph: React.FC<GraphProps> = ({ data ,images }) => {
6767
namespace: data.namespace,
6868
children: data.children.map(mf => {
6969
images.forEach( (image: kubeImage) => {
70-
let field = mf.kind.toLowerCase()
71-
let shortKind = resourceTranslationMap[field]
72-
if (shortKind === image.name.toLowerCase()) {
70+
if (resourceTranslationMap[mf.kind.toLowerCase()] === image.name.toLowerCase()) {
7371
mf.icon = image.uri
7472
return mf
73+
}
74+
else if (resourceTranslationMap[mf.kind.toLowerCase().slice(0, -1)] === image.name.toLowerCase()) {
75+
mf.icon = image.uri
76+
return mf
7577
}
7678
return mf
77-
})
79+
})
7880
return mf
7981
})
8082
}

webview-ui/src/comp/AppliedManifestWorks.tsx

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,61 @@
1-
import { useState, useEffect } from 'react';
21
import { OcmResource } from '../../../src/data/loader'
32
import { Gallery, Title } from '@patternfly/react-core';
43
import GalleryTableComponent from '../common/ConditionTable';
5-
import {DateFormat} from '../common/common'
6-
export default function ShowAppliedManifestWorks() {
7-
let [appliedManifestWorks, setAppliedManifestWorks] = useState<OcmResource[]>([]);
4+
import {DateFormat, kubeImage} from '../common/common'
5+
import Graph from '../common/Graph';
86

9-
useEffect(() => {
10-
window.addEventListener("message", event => {
11-
if ('crsDistribution' in event.data.msg && 'AppliedManifestWork' === event.data.msg.crsDistribution.kind) {
12-
setAppliedManifestWorks(JSON.parse(event.data.msg.crsDistribution.crs));
13-
}
14-
});
15-
});
167

17-
const AppliedResourcesColumn: Object[] = [
18-
8+
type AppliedManifestWorksProps = {
9+
appliedManifestWorks: OcmResource[],
10+
kubeImages: kubeImage[]
11+
}
12+
13+
export default function ShowAppliedManifestWorks(Props:AppliedManifestWorksProps) {
14+
15+
16+
const AppliedResourcesColumn: Object[] = [
1917
{title: "Resource Name",},
2018
{title: "Resource"},
2119
{title: "Group" , },
2220
{title: "Namespace" }
2321
]
2422
return (
2523
<section className="component-row">
26-
{ appliedManifestWorks.length > 0 &&
27-
<>
24+
{ Props.appliedManifestWorks.length > 0 &&
25+
<>
26+
2827
<Title headingLevel='h2' size='md' style={{ marginTop: '40px' }}>Applied ManifestWorks</Title>
2928
<Gallery className='ocm-gallery' hasGutter={true} >
30-
{appliedManifestWorks.map(appliedManifestWork => {
29+
{Props.appliedManifestWorks.map(appliedManifestWork => {
30+
console.log(`appliedManifestWork`)
31+
console.log(appliedManifestWork)
3132
const row = appliedManifestWork.kr.status.appliedResources.map( (resource:any) => {
3233
return [ resource.name, resource.resource, resource.group, resource.namespace]
3334
})
34-
35+
3536
return <GalleryTableComponent
3637
title={`ManifestWork Name: ${appliedManifestWork.kr.spec.manifestWorkName}`}
3738
subtitle={`Creation TimeStamp: ${new Date(appliedManifestWork.kr.metadata.creationTimestamp).toLocaleString("en-US",DateFormat)}`}
3839
rows={row}
3940
cells={AppliedResourcesColumn}
4041
sort={{index: 1, direction:"asc"}}
4142
id={`${appliedManifestWork.kr.spec.manifestWorkName}`}
42-
/>
43+
>
44+
<Graph data={{ name: appliedManifestWork.kr.spec.manifestWorkName,
45+
namespace: appliedManifestWork.kr.metadata.namespace?appliedManifestWork.kr.metadata.namespace:'missing namespace',
46+
children: appliedManifestWork.kr.status.appliedResources.map( (appliedResources:any) => {
47+
48+
return {
49+
group: appliedResources.group,
50+
name: appliedResources.name,
51+
namespace: appliedResources.namespace,
52+
kind: appliedResources.resource,
53+
version: appliedResources.version
54+
}
55+
})
56+
} } images={Props.kubeImages}
57+
/>
58+
</GalleryTableComponent>
4359
}
4460
)}
4561
</Gallery>

webview-ui/src/comp/ClusterManagerDashboard.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { Panel, PanelMain, PanelMainBody } from "@patternfly/react-core"
1+
import { Divider, Flex, FlexItem, Icon, Panel, PanelMain, PanelMainBody } from "@patternfly/react-core"
2+
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon'
3+
import TopologyIcon from '@patternfly/react-icons/dist/esm/icons/topology-icon'
24
import { OcmResource } from "../../../src/data/loader"
35
import { kubeImage } from "../common/common"
46

@@ -21,14 +23,35 @@ type ClusterManagerDashboardProps = {
2123
export default function ClusterManagerDashboard( Props: ClusterManagerDashboardProps) {
2224

2325
return(
24-
<Panel>
26+
<Panel variant="raised">
2527
{ (Props.data.clusterManagers && Props.data.clusterManagers.length > 0) &&
2628
<PanelMain>
27-
<PanelMainBody>
28-
{ Props.data.clusterManagers?<p> Hub Clusters: {Props.data.clusterManagers.length} </p>:null}
29-
{ Props.data.managedClusters?<p> Managed Clusters: {Props.data.managedClusters.length} </p>:null}
30-
{ Props.data.managedClusterSets?<p> managedClusterSets: {Props.data.managedClusterSets.length} </p>:null}
31-
{ Props.data.placements?<p> Placements: {Props.data.placements.length} </p>:null}
29+
<PanelMainBody>
30+
<Flex>
31+
<FlexItem>
32+
<Icon>
33+
<CubeIcon/>
34+
</Icon>
35+
{ Props.data.clusterManagers?<p> Hub Clusters: {Props.data.clusterManagers.length} </p>:null}
36+
{ Props.data.managedClusters?<p> Managed Clusters: {Props.data.managedClusters.length} </p>:null}
37+
38+
</FlexItem>
39+
<Divider
40+
component="div"
41+
orientation={{
42+
default: 'vertical'
43+
}
44+
}
45+
/>
46+
<FlexItem>
47+
<Icon>
48+
<TopologyIcon/>
49+
</Icon>
50+
{ Props.data.placements?<p> Placements: {Props.data.placements.length} </p>:null}
51+
{ Props.data.managedClusterSets?<p> managedClusterSets: {Props.data.managedClusterSets.length} </p>:null}
52+
53+
</FlexItem>
54+
</Flex>
3255
</PanelMainBody>
3356
</PanelMain>
3457
}
Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
import { useState, useEffect } from 'react';
21
import { OcmResource } from '../../../src/data/loader'
32
import { ConditionTableComponent } from '../common/ConditionTable';
43
import { DateFormat } from '../common/common';
54
import { OcmLabels } from '../common/Labels';
65

7-
export default function ShowKlusterlets() {
8-
let [klusterlets, setKlusterlets] = useState<OcmResource[]>([]);
6+
type klusterletProps = {
7+
klusterlet: OcmResource[]
8+
}
9+
10+
export default function ShowKlusterlet(Props: klusterletProps) {
11+
912

10-
useEffect(() => {
11-
window.addEventListener("message", event => {
12-
if ('crsDistribution' in event.data.msg && 'Klusterlet' === event.data.msg.crsDistribution.kind) {
13-
setKlusterlets(JSON.parse(event.data.msg.crsDistribution.crs));
14-
}
15-
});
16-
});
1713

18-
const row = klusterlets.map(klusterlet => {
14+
const row = Props.klusterlet.map(klusterlet => {
1915
return klusterlet.kr.status.conditions.map( (condition:any) => {
2016
return [new Date(condition.lastTransitionTime).toLocaleString("en-US",DateFormat),
2117
condition.message,
@@ -26,11 +22,11 @@ export default function ShowKlusterlets() {
2622
})
2723
return (
2824
//TODO-Add panel
29-
//TODO-add clusterlet dashboard
25+
//TODO-add Klusterlet dashboard
3026
<section className="component-row">
31-
{ klusterlets.length > 0 &&
27+
{ Props.klusterlet.length > 0 &&
3228
<>
33-
{klusterlets.map(klusterlet => {
29+
{Props.klusterlet.map(klusterlet => {
3430
return <>
3531
<ConditionTableComponent id='' title={`${klusterlet.kr.metadata.name}` } rows={ row[0]} />
3632
{klusterlet.kr.metadata.labels?<OcmLabels labels={klusterlet.kr.metadata.labels} />:null }

webview-ui/src/comp/ManagedClusterSets.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ export default function ShowManagedClusterSets(Props: managedClusterSetsProps) {
2121
<Gallery className='ocm-gallery' hasGutter={true} >
2222

2323
{Props.managedClusterSets.map(managedClusterSet => {
24-
console.log(`managedClusterSet`)
25-
console.log(managedClusterSet)
2624
const code = yaml.dump(managedClusterSet.kr.spec.clusterSelector)
2725
const row = managedClusterSet.kr.status.conditions.map( (condition:any) => {
2826
return [new Date(condition.lastTransitionTime).toLocaleString("en-US",DateFormat),

webview-ui/src/comp/SubscriptionReports.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,19 @@ export default function ShowSubscriptionReports(Props: SubscriptionReportsProps)
2929
<Gallery className='ocm-gallery' hasGutter={true} >
3030

3131
{Props.subscriptionReports.map( subscriptionReport => {
32-
const rows = [[subscriptionReport.kr.summary.clusters,
33-
subscriptionReport.kr.summary.deployed,
34-
subscriptionReport.kr.summary.failed,
35-
subscriptionReport.kr.summary.inProgress,
36-
subscriptionReport.kr.summary.propagationFailed
37-
]]
38-
39-
console.log(rows)
32+
console.log(`subscriptionReport`)
33+
console.log(subscriptionReport)
34+
35+
let rows = [[0,0,0,0,0]]
36+
37+
if (subscriptionReport.kr.summary && subscriptionReport.kr.summary.clusters > -1 ) {
38+
rows = [[subscriptionReport.kr.summary.clusters,
39+
subscriptionReport.kr.summary.deployed,
40+
subscriptionReport.kr.summary.failed,
41+
subscriptionReport.kr.summary.inProgress,
42+
subscriptionReport.kr.summary.propagationFailed
43+
]]
44+
}
4045

4146
return <GalleryItem>
4247
<Card>
@@ -45,21 +50,19 @@ export default function ShowSubscriptionReports(Props: SubscriptionReportsProps)
4550
<Title headingLevel='h3' size='md'>Namespace: {subscriptionReport.kr.metadata.namespace?subscriptionReport.kr.metadata.namespace:'missing namespace'}</Title>
4651
</CardHeader>
4752
<CardBody>
53+
4854
<p> Report Type: {subscriptionReport.kr.reportType}</p>
55+
{/*TODO add placement name and chanel */}
4956
<Graph data={{ name: subscriptionReport.kr.metadata.name,
5057
namespace: subscriptionReport.kr.metadata.namespace?subscriptionReport.kr.metadata.namespace:'missing namespace',
51-
children: subscriptionReport.kr.resources
58+
children: subscriptionReport.kr.resources?subscriptionReport.kr.resources:[]
5259
} } images={Props.kubeImages}/>
5360
<div style={{ borderTop: "1px solid #fff ", marginLeft: 10, marginRight: 10 }}></div>
5461
<Table gridBreakPoint= 'grid-md' rows={rows} cells={SubscriptionReportsSummeryColumns} >
5562
<TableHeader/>
5663
<TableBody />
5764
</Table>
58-
5965
</CardBody>
60-
61-
62-
6366
</Card>
6467
</GalleryItem>
6568
})}

webview-ui/src/comp/SubscriptionStatuses.tsx

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,49 @@
1-
import { VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow, } from '@vscode/webview-ui-toolkit/react';
2-
import { useState, useEffect } from 'react';
31
import { OcmResource } from '../../../src/data/loader'
4-
import { Title } from '@patternfly/react-core';
2+
import { Gallery, Title } from '@patternfly/react-core';
3+
import GalleryTableComponent from '../common/ConditionTable';
54

6-
export default function ShowSubscriptionStatuses() {
7-
let [subscriptionStatuses, setSubscriptionStatuses] = useState<OcmResource[]>([]);
5+
type SubscriptionStatusesProps ={
6+
subscriptionStatuses: OcmResource[],
7+
subscription: OcmResource[],
8+
}
89

9-
useEffect(() => {
10-
window.addEventListener("message", event => {
11-
if ('crsDistribution' in event.data.msg && 'SubscriptionStatus' === event.data.msg.crsDistribution.kind) {
12-
setSubscriptionStatuses(JSON.parse(event.data.msg.crsDistribution.crs));
13-
}
14-
});
15-
});
10+
const SubscriptionStatusesColumns: Object[] = [
11+
{title: "kind" ,},
12+
{title: "LastUpdateTime", },
13+
{title: "Name" },
14+
{title: "Namespace" },
15+
{title: "PropagationFailed" }
16+
]
17+
18+
export default function ShowSubscriptionStatuses(Props: SubscriptionStatusesProps) {
1619

1720
return (
1821
<section className="component-row">
19-
{ subscriptionStatuses.length >0 &&
22+
{ Props.subscriptionStatuses.length >0 &&
2023
<>
2124
<Title headingLevel='h2' size='md' style={{ marginTop: '40px' }}>Subscription Status</Title>
22-
<VSCodeDataGrid gridTemplateColumns="1fr 1fr" aria-label='SubscriptionStatus' >
23-
<VSCodeDataGridRow rowType="sticky-header">
24-
<VSCodeDataGridCell cellType='columnheader' gridColumn='1'>Subscription Name</VSCodeDataGridCell>
25-
<VSCodeDataGridCell cellType='columnheader' gridColumn='2'>Report Type</VSCodeDataGridCell>
26-
</VSCodeDataGridRow>
27-
28-
{subscriptionStatuses.map(subscriptionStatus => {
29-
return <VSCodeDataGridRow>
30-
<VSCodeDataGridCell gridColumn='1' >{subscriptionStatus.kr.metadata.name}</VSCodeDataGridCell>
31-
<VSCodeDataGridCell gridColumn='2'>{subscriptionStatus.kr.statuses.packages.map( ( pkg:any )=> { return<p> - kind: {pkg.kind}, lastUpdateTime: {pkg.lastUpdateTime}, name: {pkg.name}, namespace: {pkg.namespace}, phase: {pkg.phase} </p> })} </VSCodeDataGridCell>
32-
</VSCodeDataGridRow>
33-
} )
34-
}
35-
</VSCodeDataGrid>
25+
<Gallery className='ocm-gallery' hasGutter={true} >
26+
{Props.subscriptionStatuses.map(subscriptionStatus => {
27+
console.log(`subscriptionStatus`)
28+
console.log(subscriptionStatus)
29+
return <GalleryTableComponent
30+
title={`Subscription Name: ${subscriptionStatus.name}`}
31+
rows={subscriptionStatus.kr.statuses.packages.map( ( pkg:any )=> {return [ pkg.kind,
32+
pkg.lastUpdateTime,
33+
pkg.name,
34+
pkg.namespace,
35+
pkg.phase
36+
]}
37+
) }
38+
cells={SubscriptionStatusesColumns}
39+
id={`${subscriptionStatus.kr.metadata.name}`}
40+
>
41+
<p> Namespace: {subscriptionStatus.namespace} </p>
42+
</GalleryTableComponent>
43+
}
44+
)}
3645
<div style={{ borderTop: "1px solid #fff ", marginLeft: 10, marginRight: 10 }}></div>
46+
</Gallery>
3747
</>
3848
}
3949
</section>

0 commit comments

Comments
 (0)