Skip to content

Commit e5d5796

Browse files
committed
feat: populate crossplane and flux with data
1 parent 97d852d commit e5d5796

File tree

4 files changed

+165
-42
lines changed

4 files changed

+165
-42
lines changed

src/components/Hints/CrossplaneHint.tsx

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,65 @@
11
import { Card, CardHeader, ProgressIndicator, Button } from '@ui5/webcomponents-react';
2+
import { ManagedResourcesResponse } from '../../lib/api/types/crossplane/listManagedResources';
23
import { useTranslation } from 'react-i18next';
34

45
interface CrossplaneHintProps {
56
enabled?: boolean;
7+
version?: string;
68
onActivate?: () => void;
9+
managedResources?: ManagedResourcesResponse | undefined;
10+
isLoading?: boolean;
11+
error?: any;
712
}
813

9-
export const CrossplaneHint: React.FC<CrossplaneHintProps> = ({ enabled = false, onActivate }) => {
10-
const { t } = useTranslation();
11-
12-
const cardStyle = enabled
14+
export const CrossplaneHint: React.FC<CrossplaneHintProps> = ({ enabled = false, version, onActivate, managedResources, isLoading, error }) => {
15+
const { t } = useTranslation();
16+
17+
const cardStyle = enabled
1318
? {}
1419
: {
1520
background: '#f3f3f3',
1621
filter: 'grayscale(0.7)',
1722
opacity: 0.7,
1823
};
1924

25+
// Flatten all items from all managedResources entries
26+
const allItems = managedResources
27+
? managedResources
28+
.filter((managedResource) => managedResource.items)
29+
.flatMap((managedResource) => managedResource.items)
30+
: [];
31+
32+
// Health state counts for slider segments
33+
const healthyCount = allItems.filter((item: any) => {
34+
const conditions = item.status?.conditions || [];
35+
const ready = conditions.find((c: any) => c.type === 'Ready' && c.status === 'True');
36+
const synced = conditions.find((c: any) => c.type === 'Synced' && c.status === 'True');
37+
return !!ready && !!synced;
38+
}).length;
39+
40+
const totalCount = allItems.length;
41+
42+
// Progress value: percent of resources that are both Ready and Synced
43+
const progressValue = totalCount > 0 ? Math.round((healthyCount / totalCount) * 100) : 0;
44+
// Display value: show ratio
45+
const progressDisplay = enabled
46+
? managedResources
47+
? `${Math.round((healthyCount / totalCount) * 100)}% Available`
48+
: 'No Resources'
49+
: 'Inactive';
50+
// Value state: positive if half are ready & synced
51+
const progressValueState = enabled
52+
? managedResources
53+
? (healthyCount >= totalCount / 2 && totalCount > 0 ? 'Positive' : 'Critical')
54+
: 'None'
55+
: 'None';
56+
2057
return (
2158
<div style={{ position: 'relative', width: '100%' }}>
2259
<Card
2360
header={
2461
<CardHeader
25-
additionalText={enabled ? 'Active' : undefined}
62+
additionalText={enabled ? `Active v${version ?? ''}` : undefined}
2663
avatar={
2764
<img
2865
src="/crossplane-icon.png"
@@ -37,12 +74,18 @@ export const CrossplaneHint: React.FC<CrossplaneHintProps> = ({ enabled = false,
3774
style={cardStyle}
3875
>
3976
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '1rem 0' }}>
40-
<ProgressIndicator
41-
value={100}
42-
displayValue={enabled ? '100% Available' : 'Inactive'}
43-
valueState={enabled ? 'Positive' : 'None'}
44-
style={{ width: '80%', maxWidth: 500, minWidth: 120 }}
45-
/>
77+
{isLoading ? (
78+
<ProgressIndicator value={0} displayValue={t('Loading...')} valueState="None" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
79+
) : error ? (
80+
<ProgressIndicator value={0} displayValue={t('Error loading resources')} valueState="Negative" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
81+
) : (
82+
<ProgressIndicator
83+
value={progressValue}
84+
displayValue={progressDisplay}
85+
valueState={progressValueState}
86+
style={{ width: '80%', maxWidth: 500, minWidth: 120 }}
87+
/>
88+
)}
4689
</div>
4790
{!enabled && (
4891
<div style={{

src/components/Hints/GitOpsHint.tsx

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
11

22
import { Card, CardHeader, ProgressIndicator, Button } from '@ui5/webcomponents-react';
3+
import { ManagedResourcesResponse } from '../../lib/api/types/crossplane/listManagedResources';
34
import { useTranslation } from 'react-i18next';
45

56
interface GitOpsHintProps {
67
enabled?: boolean;
8+
version?: string;
79
onActivate?: () => void;
10+
managedResources?: ManagedResourcesResponse | undefined;
11+
isLoading?: boolean;
12+
error?: any;
813
}
914

10-
export const GitOpsHint: React.FC<GitOpsHintProps> = ({ enabled = false, onActivate }) => {
11-
const { t } = useTranslation();
15+
export const GitOpsHint: React.FC<GitOpsHintProps> = ({ enabled=false, version, onActivate, managedResources, isLoading, error }) => {
16+
const { t } = useTranslation();
1217

18+
// Flatten all items from all managedResources entries
19+
const allItems = managedResources
20+
? managedResources
21+
.filter((managedResource) => managedResource.items)
22+
.flatMap((managedResource) => managedResource.items)
23+
: [];
24+
25+
const totalCount = allItems.length;
26+
27+
// Count the number of items with the flux label
28+
const fluxLabelCount = allItems.filter(
29+
(item) => item?.metadata?.labels && Object.prototype.hasOwnProperty.call(item.metadata.labels, 'kustomize.toolkit.fluxcd.io/name')
30+
).length;
31+
32+
const progressValue = totalCount > 0 ? Math.round((fluxLabelCount / totalCount) * 100) : 0;
33+
// Display value: show ratio
34+
const progressDisplay = enabled
35+
? managedResources
36+
? `${Math.round((fluxLabelCount / totalCount) * 100)}% Available`
37+
: 'No Resources'
38+
: 'Inactive';
39+
// Value state: positive if half are ready & synced
40+
const progressValueState = enabled
41+
? managedResources
42+
? (fluxLabelCount >= totalCount / 2 && totalCount > 0 ? 'Positive' : 'Critical')
43+
: 'None'
44+
: 'None';
45+
1346
const cardStyle = enabled
1447
? {}
1548
: {
@@ -23,7 +56,7 @@ export const GitOpsHint: React.FC<GitOpsHintProps> = ({ enabled = false, onActiv
2356
<Card
2457
header={
2558
<CardHeader
26-
additionalText={enabled ? 'Active' : undefined}
59+
additionalText={enabled ? `Active v${version ?? ''}` : undefined}
2760
avatar={
2861
<img
2962
src="/flux.png"
@@ -37,13 +70,19 @@ export const GitOpsHint: React.FC<GitOpsHintProps> = ({ enabled = false, onActiv
3770
}
3871
style={cardStyle}
3972
>
40-
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '1rem 0' }}>
41-
<ProgressIndicator
42-
value={100}
43-
displayValue={enabled ? '100% Available' : 'Inactive'}
44-
valueState={enabled ? 'Positive' : 'None'}
45-
style={{ width: '80%', maxWidth: 500, minWidth: 120}}
46-
/>
73+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '1rem 0' }}>
74+
{isLoading ? (
75+
<ProgressIndicator value={0} displayValue={t('Loading...')} valueState="None" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
76+
) : error ? (
77+
<ProgressIndicator value={0} displayValue={t('Error loading resources')} valueState="Negative" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
78+
) : (
79+
<ProgressIndicator
80+
value={progressValue}
81+
displayValue={progressDisplay}
82+
valueState={progressValueState}
83+
style={{ width: '80%', maxWidth: 500, minWidth: 120 }}
84+
/>
85+
)}
4786
</div>
4887
{!enabled && (
4988
<div style={{

src/components/Hints/Hints.tsx

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,58 @@ import { GitOpsHint } from './GitOpsHint';
44
import { VaultHint } from './VaultHint';
55

66
import { ControlPlaneType } from '../../lib/api/types/crate/controlPlanes';
7-
7+
import { ManagedResourcesRequest } from '../../lib/api/types/crossplane/listManagedResources';
8+
import { resourcesInterval } from '../../lib/shared/constants';
9+
import { useApiResource } from '../../lib/api/useApiResource';
810
import React from 'react';
911

1012
interface HintsProps {
1113
mcp: ControlPlaneType;
1214
}
1315

14-
const Hints: React.FC<HintsProps> = ({ mcp }) => (
16+
17+
const Hints: React.FC<HintsProps> = ({ mcp }) => {
18+
const {
19+
data: managedResources,
20+
isLoading: managedResourcesLoading,
21+
error: managedResourcesError,
22+
} = useApiResource(ManagedResourcesRequest, {
23+
refreshInterval: resourcesInterval,
24+
});
25+
26+
return (
1527
<FlexBox
16-
direction={FlexBoxDirection.Row}
17-
style={{
18-
gap: '12px',
19-
justifyContent: 'space-between',
20-
alignItems: 'stretch',
21-
width: '100%'
22-
}}
28+
direction={FlexBoxDirection.Row}
29+
style={{
30+
gap: '12px',
31+
justifyContent: 'space-between',
32+
alignItems: 'stretch',
33+
width: '100%'
34+
}}
2335
>
24-
<CrossplaneHint enabled={!!mcp?.spec?.components?.crossplane} />
25-
<GitOpsHint enabled={!!mcp?.spec?.components?.flux} />
26-
<VaultHint enabled={!!mcp?.spec?.components?.externalSecretsOperator} />
36+
<CrossplaneHint
37+
enabled={!!mcp?.spec?.components?.crossplane}
38+
version={mcp?.spec?.components?.crossplane?.version}
39+
managedResources={managedResources}
40+
isLoading={managedResourcesLoading}
41+
error={managedResourcesError}
42+
/>
43+
<GitOpsHint
44+
enabled={!!mcp?.spec?.components?.flux}
45+
version={mcp?.spec?.components?.flux?.version}
46+
managedResources={managedResources}
47+
isLoading={managedResourcesLoading}
48+
error={managedResourcesError}
49+
/>
50+
<VaultHint
51+
enabled={!!mcp?.spec?.components?.externalSecretsOperator}
52+
version={mcp?.spec?.components?.externalSecretsOperator?.version}
53+
managedResources={managedResources}
54+
isLoading={managedResourcesLoading}
55+
error={managedResourcesError}
56+
/>
2757
</FlexBox>
28-
);
58+
);
59+
};
2960

3061
export default Hints;

src/components/Hints/VaultHint.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import { useTranslation } from 'react-i18next';
44

55
interface VaultHintProps {
66
enabled?: boolean;
7+
version?: string;
78
onActivate?: () => void;
9+
managedResources?: any;
10+
isLoading?: boolean;
11+
error?: any;
812
}
913

10-
export const VaultHint: React.FC<VaultHintProps> = ({ enabled = false, onActivate }) => {
14+
export const VaultHint: React.FC<VaultHintProps> = ({ enabled = false, version, onActivate, managedResources, isLoading, error }) => {
1115
const { t } = useTranslation();
1216

1317
const cardStyle = enabled
@@ -23,7 +27,7 @@ export const VaultHint: React.FC<VaultHintProps> = ({ enabled = false, onActivat
2327
<Card
2428
header={
2529
<CardHeader
26-
additionalText={enabled ? 'Active' : undefined}
30+
additionalText={enabled ? `Active v${version ?? ''}` : undefined}
2731
avatar={
2832
<img
2933
src="/vault.png"
@@ -38,12 +42,18 @@ export const VaultHint: React.FC<VaultHintProps> = ({ enabled = false, onActivat
3842
style={cardStyle}
3943
>
4044
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '1rem 0' }}>
41-
<ProgressIndicator
42-
value={100}
43-
displayValue={enabled ? '100% Available' : 'Inactive'}
44-
valueState={enabled ? 'Positive' : 'None'}
45-
style={{ width: '80%', maxWidth: 500, minWidth: 120 }}
46-
/>
45+
{isLoading ? (
46+
<ProgressIndicator value={0} displayValue={t('Loading...')} valueState="None" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
47+
) : error ? (
48+
<ProgressIndicator value={0} displayValue={t('Error loading resources')} valueState="Negative" style={{ width: '80%', maxWidth: 500, minWidth: 120 }} />
49+
) : (
50+
<ProgressIndicator
51+
value={managedResources ? 100 : 0}
52+
displayValue={enabled ? (managedResources ? '100% Available' : 'No Resources') : 'Inactive'}
53+
valueState={enabled ? (managedResources ? 'Positive' : 'None') : 'None'}
54+
style={{ width: '80%', maxWidth: 500, minWidth: 120 }}
55+
/>
56+
)}
4757
</div>
4858
{!enabled && (
4959
<div style={{

0 commit comments

Comments
 (0)