Skip to content

Commit dbf976a

Browse files
initial commit for landscapers from different branch
1 parent f5a4462 commit dbf976a

File tree

8 files changed

+262
-118
lines changed

8 files changed

+262
-118
lines changed

public/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@
149149
"accessError": "Managed Control Plane does not have access information yet",
150150
"componentsTitle": "Components",
151151
"crossplaneTitle": "Crossplane",
152-
"gitOpsTitle": "GitOps"
152+
"gitOpsTitle": "GitOps",
153+
"landscapersTitle": "Landscapers"
153154
},
154155
"ToastContext": {
155156
"errorMessage": "useToast must be used within a ToastProvider"
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { useTranslation } from 'react-i18next';
2+
import {
3+
AnalyticalTable,
4+
AnalyticalTableColumnDefinition,
5+
AnalyticalTableScaleWidthMode,
6+
Title,
7+
MultiComboBox,
8+
MultiComboBoxItem,
9+
} from '@ui5/webcomponents-react';
10+
import useResource from '../../lib/api/useApiResource';
11+
import '@ui5/webcomponents-icons/dist/sys-enter-2';
12+
import '@ui5/webcomponents-icons/dist/sys-cancel-2';
13+
import { ListNamespaces } from '../../lib/api/types/k8s/listNamespaces';
14+
import { useEffect, useState } from 'react';
15+
import { resourcesInterval } from '../../lib/shared/constants';
16+
import { InstalationsRequest } from '../../lib/api/types/landscaper/listInstallations';
17+
18+
export function Landscapers() {
19+
const { t } = useTranslation();
20+
21+
// Namespaces z API
22+
const { data: namespaces, error: namespacesError } = useResource(
23+
ListNamespaces,
24+
{
25+
refreshInterval: resourcesInterval,
26+
},
27+
);
28+
29+
const [selectedNamespaces, setSelectedNamespaces] = useState<string[]>([]);
30+
const [installations, setInstallations] = useState<any[]>([]);
31+
const [loading, setLoading] = useState(false);
32+
33+
// Handler wyboru namespace’ów
34+
const handleSelectionChange = (e: CustomEvent) => {
35+
const selectedItems = Array.from(e.detail.items || []);
36+
const selectedValues = selectedItems.map((item: any) => item.text);
37+
setSelectedNamespaces(selectedValues);
38+
};
39+
40+
// Fetch installations, gdy zmienią się namespace’y
41+
useEffect(() => {
42+
const fetchInstallations = async () => {
43+
if (selectedNamespaces.length === 0) {
44+
setInstallations([]);
45+
return;
46+
}
47+
setLoading(true);
48+
try {
49+
const paths = selectedNamespaces
50+
.map((ns) => InstalationsRequest(ns).path)
51+
.filter((p): p is string => p !== null && p !== undefined);
52+
53+
const allResponses = await Promise.all(
54+
paths.map((path) => fetch(path).then((res) => res.json())),
55+
);
56+
57+
const allItems = allResponses.flatMap((res) => res.items || []);
58+
setInstallations(allItems);
59+
} catch (error) {
60+
console.error(error);
61+
setInstallations([]);
62+
} finally {
63+
setLoading(false);
64+
}
65+
};
66+
67+
fetchInstallations();
68+
}, [selectedNamespaces]);
69+
70+
// Definicja kolumn tabeli
71+
const columns: AnalyticalTableColumnDefinition[] = [
72+
{
73+
Header: t('Namespace'),
74+
accessor: 'metadata.namespace',
75+
},
76+
{
77+
Header: t('Name'),
78+
accessor: 'metadata.name',
79+
},
80+
{
81+
Header: t('Phase'),
82+
accessor: 'status.phase',
83+
},
84+
{
85+
Header: t('Created At'),
86+
accessor: 'metadata.creationTimestamp',
87+
},
88+
];
89+
90+
return (
91+
<>
92+
<Title level="H4">{t('Providers.headerProviders')}</Title>
93+
94+
{namespaces && (
95+
<MultiComboBox
96+
placeholder={t('Select namespace')}
97+
style={{ marginBottom: '1rem', maxWidth: '400px' }}
98+
onSelectionChange={handleSelectionChange}
99+
>
100+
{namespaces.map((ns) => (
101+
<MultiComboBoxItem key={ns.metadata.name} text={ns.metadata.name} />
102+
))}
103+
</MultiComboBox>
104+
)}
105+
106+
<AnalyticalTable
107+
columns={columns}
108+
data={installations}
109+
minRows={1}
110+
loading={loading}
111+
scaleWidthMode={AnalyticalTableScaleWidthMode.Smart}
112+
filterable
113+
retainColumnWidth
114+
reactTableOptions={{
115+
autoResetHiddenColumns: false,
116+
autoResetPage: false,
117+
autoResetExpanded: false,
118+
autoResetGroupBy: false,
119+
autoResetSelectedRows: false,
120+
autoResetSortBy: false,
121+
autoResetFilters: false,
122+
autoResetRowState: false,
123+
autoResetResize: false,
124+
}}
125+
/>
126+
</>
127+
);
128+
}
Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
1-
import useApiResource from '../../useApiResource';
2-
import { ListGraphInstallations } from './listInstallations';
3-
import { ListGraphExecutions } from './listExecutions';
4-
import { ListGraphDeployItems } from './listDeployItems';
1+
// import useApiResource from '../../useApiResource';
2+
// import { ListGraphInstallations } from './listInstallations';
3+
// import { ListGraphExecutions } from './listExecutions';
54

6-
interface GraphLandscaperResourceType {
7-
kind: string;
8-
apiVersion: string;
9-
metadata: {
10-
name: string;
11-
namespace: string;
12-
uid: string;
13-
ownerReferences: {
14-
uid: string;
15-
}[];
16-
};
17-
status: {
18-
phase: string;
19-
};
20-
}
5+
// interface GraphLandscaperResourceType {
6+
// kind: string;
7+
// apiVersion: string;
8+
// metadata: {
9+
// name: string;
10+
// namespace: string;
11+
// uid: string;
12+
// ownerReferences: {
13+
// uid: string;
14+
// }[];
15+
// };
16+
// status: {
17+
// phase: string;
18+
// };
19+
// }
2120

22-
export const useLandscaperGraphResources = () => {
23-
const installations = useApiResource(ListGraphInstallations);
24-
const executions = useApiResource(ListGraphExecutions);
25-
const deployItems = useApiResource(ListGraphDeployItems);
21+
// export const useLandscaperGraphResources = () => {
22+
// const installations = useApiResource(ListGraphInstallations);
23+
// const executions = useApiResource(ListGraphExecutions);
2624

27-
return {
28-
data: [
29-
...(installations.data?.map((m) => {
30-
return {
31-
kind: 'Installation',
32-
apiVersion: 'landscaper.gardener.cloud/v1alpha1',
33-
...m,
34-
};
35-
}) ?? []),
36-
...(executions.data?.map((m) => {
37-
return {
38-
kind: 'Execution',
39-
apiVersion: 'landscaper.gardener.cloud/v1alpha1',
40-
...m,
41-
};
42-
}) ?? []),
43-
...(deployItems.data?.map((m) => {
44-
return {
45-
kind: 'DeployItem',
46-
apiVersion: 'landscaper.gardener.cloud/v1alpha1',
47-
...m,
48-
};
49-
}) ?? []),
50-
] as GraphLandscaperResourceType[],
51-
error: [installations.error, executions.error, deployItems.error].filter(
52-
(e) => e !== undefined,
53-
),
54-
};
55-
};
25+
// return {
26+
// data: [
27+
// ...(installations.data?.map((m) => {
28+
// return {
29+
// kind: 'Installation',
30+
// apiVersion: 'landscaper.gardener.cloud/v1alpha1',
31+
// ...m,
32+
// };
33+
// }) ?? []),
34+
// ...(executions.data?.map((m) => {
35+
// return {
36+
// kind: 'Execution',
37+
// apiVersion: 'landscaper.gardener.cloud/v1alpha1',
38+
// ...m,
39+
// };
40+
// }) ?? []),
41+
// ...(deployItems.data?.map((m) => {
42+
// return {
43+
// kind: 'DeployItem',
44+
// apiVersion: 'landscaper.gardener.cloud/v1alpha1',
45+
// ...m,
46+
// };
47+
// }) ?? []),
48+
// ] as GraphLandscaperResourceType[],
49+
// error: [installations.error, executions.error, deployItems.error].filter(
50+
// (e) => e !== undefined,
51+
// ),
52+
// };
53+
// };
Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
import { Resource } from '../resource';
22

3-
interface GraphDeployItemsType {
4-
metadata: {
5-
name: string;
6-
namespace: string;
7-
uid: string;
8-
ownerReferences: {
9-
uid: string;
10-
}[];
11-
};
12-
status: {
13-
phase: string;
14-
};
3+
interface DeployItemsListResponse {
4+
items: [
5+
{
6+
metadata: {
7+
name: string;
8+
namespace: string;
9+
uid: string;
10+
ownerReferences: {
11+
uid: string;
12+
}[];
13+
};
14+
status: {
15+
phase: string;
16+
};
17+
},
18+
];
1519
}
1620

17-
export const ListGraphDeployItems: Resource<GraphDeployItemsType[]> = {
18-
path: '/apis/landscaper.gardener.cloud/v1alpha1/deployitems',
19-
jq: '[.items[] | {metadata: .metadata | {name, namespace, uid, ownerReferences: (try [{uid: .ownerReferences[].uid}] catch [])}, status: .status | {phase}}]',
20-
};
21+
export const DeployItemsRequest = (
22+
namespace: string,
23+
): Resource<DeployItemsListResponse> => ({
24+
path: `/apis/landscaper.gardener.cloud/v1alpha1/namespaces/${namespace}/installations`,
25+
});
Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
import { Resource } from '../resource';
22

3-
interface GraphExecutionsType {
4-
metadata: {
5-
name: string;
6-
namespace: string;
7-
uid: string;
8-
ownerReferences: {
9-
uid: string;
10-
}[];
11-
};
12-
status: {
13-
phase: string;
14-
};
3+
interface ExecutionsListResponse {
4+
items: [
5+
{
6+
metadata: {
7+
name: string;
8+
namespace: string;
9+
uid: string;
10+
ownerReferences: {
11+
uid: string;
12+
}[];
13+
};
14+
status: {
15+
phase: string;
16+
};
17+
},
18+
];
1519
}
1620

17-
export const ListGraphExecutions: Resource<GraphExecutionsType[]> = {
18-
path: '/apis/landscaper.gardener.cloud/v1alpha1/executions',
19-
jq: '[.items[] | {metadata: .metadata | {name, namespace, uid, ownerReferences: (try [{uid: .ownerReferences[].uid}] catch [])}, status: .status | {phase}}]',
20-
};
21+
export const ExecutionsRequest = (
22+
namespace: string,
23+
): Resource<ExecutionsListResponse> => ({
24+
path: `/apis/landscaper.gardener.cloud/v1alpha1/namespaces/${namespace}/installations`,
25+
});
Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,22 @@
11
import { Resource } from '../resource';
22

3-
interface GraphInstallationsType {
4-
metadata: {
5-
name: string;
6-
namespace: string;
7-
uid: string;
8-
ownerReferences: {
9-
uid: string;
10-
}[];
11-
};
12-
status: {
13-
phase: string;
14-
};
3+
interface InstalationsListResponse {
4+
items: [
5+
{
6+
metadata: {
7+
name: string;
8+
namespace: string;
9+
creationTimestamp: string;
10+
};
11+
status: {
12+
phase: string;
13+
};
14+
},
15+
];
1516
}
1617

17-
export const ListGraphInstallations: Resource<GraphInstallationsType[]> = {
18-
path: '/apis/landscaper.gardener.cloud/v1alpha1/installations',
19-
jq: '[.items[] | {metadata: .metadata | {name, namespace, uid, ownerReferences: (try [{uid: .ownerReferences[].uid}] catch [])}, status: .status | {phase}}]',
20-
};
21-
22-
interface TableInstallationsType {
23-
metadata: {
24-
name: string;
25-
namespace: string;
26-
creationTimestamp: string;
27-
};
28-
status: {
29-
phase: string;
30-
};
31-
}
32-
33-
export const ListTableInstallations: Resource<TableInstallationsType[]> = {
34-
path: '/apis/landscaper.gardener.cloud/v1alpha1/installations',
35-
jq: '[.items[] | {metadata: .metadata | {name, namespace, creationTimestamp}, status: .status | {phase}}]',
36-
};
18+
export const InstalationsRequest = (
19+
namespace: string,
20+
): Resource<InstalationsListResponse> => ({
21+
path: `/apis/landscaper.gardener.cloud/v1alpha1/namespaces/landscaper02/installations`,
22+
});

src/lib/shared/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const resourcesInterval = 30000;
1+
export const resourcesInterval = 100000;

0 commit comments

Comments
 (0)