diff --git a/public/locales/en.json b/public/locales/en.json index 1c24f1b6..69466187 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -143,5 +143,16 @@ }, "main": { "failedMessage": "Failed to load frontend configuration" + }, + "Providers": { + "headerProviders": "Providers", + "tableHeaderVersion": "Version", + "tableHeaderName": "Name", + "tableHeaderCreated": "Created", + "tableHeaderInstalled": "Installed", + "tableHeaderHealthy": "Healthy" + }, + "ProvidersConfig": { + "headerProvidersConfig": "Providers Config" } } \ No newline at end of file diff --git a/src/components/ControlPlane/ManagedResources.tsx b/src/components/ControlPlane/ManagedResources.tsx index ec50f248..c2342f32 100644 --- a/src/components/ControlPlane/ManagedResources.tsx +++ b/src/components/ControlPlane/ManagedResources.tsx @@ -12,6 +12,8 @@ import { timeAgo } from '../../utils/i18n/timeAgo'; import IllustratedError from '../Shared/IllustratedError'; import '@ui5/webcomponents-icons/dist/sys-enter-2'; import '@ui5/webcomponents-icons/dist/sys-cancel-2'; +import { resourcesInterval } from '../../lib/shared/constants'; +import { StatusCellProps } from '../../lib/shared/interfaces'; interface CellData { cell: { @@ -40,7 +42,7 @@ export function ManagedResources() { error, isLoading, } = useResource(ManagedResourcesRequest, { - refreshInterval: 30000, // Resources are quite expensive to fetch, so we refresh every 30 seconds + refreshInterval: resourcesInterval, // Resources are quite expensive to fetch, so we refresh every 30 seconds }); const columns: AnalyticalTableColumnDefinition[] = [ @@ -136,15 +138,10 @@ export function ManagedResources() { ); } -interface ResourceStatusCellProps { - value: boolean; - transitionTime: string; -} - function ResourceStatusCell({ value, transitionTime, -}: ResourceStatusCellProps) { +}: StatusCellProps) { return ( { + cell: { + value: T | null; // null for grouping rows + row: { + original?: ProvidersRow; // missing for grouping rows + } + }; +} + +type ProvidersRow = { + name: string + version: string; + healthy: boolean; + healthyTransitionTime: string; + installed: boolean; + installedTransitionTime: string; + created: string; +} + +export function Providers() { + const { t } = useTranslation(); + + let {data: providers, error, isLoading} = useResource(ProvidersListRequest, { + refreshInterval: resourcesInterval + }); + + const columns: AnalyticalTableColumnDefinition[] = [ + { + Header: t('Providers.tableHeaderName'), + accessor: 'name', + }, + { + Header: t('Providers.tableHeaderVersion'), + accessor: 'version', + }, + { + Header: t('Providers.tableHeaderInstalled'), + accessor: 'installed', + Cell: (cellData: CellData) => cellData.cell.row.original?.installed != null ? : null + }, + { + Header: t('Providers.tableHeaderHealthy'), + accessor: 'healthy', + Cell: (cellData: CellData) => cellData.cell.row.original?.installed != null ? : null + }, + { + Header: t('Providers.tableHeaderCreated'), + accessor: 'created', + }, + ]; + + const rows: ProvidersRow[] = + providers?.items?.map((item) => { + const installed = item.status.conditions?.find((condition) => condition.type === 'Installed'); + const healthy = item.status.conditions?.find((condition) => condition.type === 'Healthy'); + + return { + name: item.metadata.name, + created: timeAgo.format(new Date(item.metadata.creationTimestamp)), + installed: installed?.status === "True", + installedTransitionTime: installed?.lastTransitionTime ?? "", + healthy: healthy?.status === "True", + healthyTransitionTime: healthy?.lastTransitionTime ?? "", + version: item.spec.package.match(/\d+(\.\d+)+/g)?.toString() ?? "", + } + }) + ?? []; + + return ( + <> + {t('Providers.headerProviders')} + + {error && } + + {!error && + + } + + ) +} + +function ResourceStatusCell({ value, transitionTime }: StatusCellProps) { + return +} diff --git a/src/components/ControlPlane/ProvidersConfig.tsx b/src/components/ControlPlane/ProvidersConfig.tsx new file mode 100644 index 00000000..4c4dd8de --- /dev/null +++ b/src/components/ControlPlane/ProvidersConfig.tsx @@ -0,0 +1,40 @@ + +import { useTranslation } from 'react-i18next'; +import { AnalyticalTable, AnalyticalTableColumnDefinition, AnalyticalTableScaleWidthMode, Title } from '@ui5/webcomponents-react'; +import '@ui5/webcomponents-icons/dist/sys-enter-2'; +import '@ui5/webcomponents-icons/dist/sys-cancel-2'; + +//empty table TBD +export function ProvidersConfig() { + const { t } = useTranslation(); + + const columns: AnalyticalTableColumnDefinition[] = []; + + return ( + <> + {t('ProvidersConfig.headerProvidersConfig')} + + + ) +} diff --git a/src/components/ControlPlane/ProvidersList.tsx b/src/components/ControlPlane/ProvidersList.tsx index 95dd16bf..5d00613f 100644 --- a/src/components/ControlPlane/ProvidersList.tsx +++ b/src/components/ControlPlane/ProvidersList.tsx @@ -1,51 +1,12 @@ -import ConfiguredAnalyticstable from '../Shared/ConfiguredAnalyticsTable.tsx'; -import { - AnalyticalTableColumnDefinition, - Title, -} from '@ui5/webcomponents-react'; -import ReactTimeAgo from 'react-time-ago'; -import IllustratedError from '../Shared/IllustratedError.tsx'; -import useResource from '../../lib/api/useApiResource'; -import { ListProviders } from '../../lib/api/types/crossplane/listProviders'; -import { useTranslation } from 'react-i18next'; +import { Providers } from "./Providers.tsx"; +import { ProvidersConfig } from "./ProvidersConfig.tsx"; import { ManagedResources } from './ManagedResources'; export default function ProvidersList() { - const { data, error, isLoading } = useResource(ListProviders); - const { t } = useTranslation(); - - if (error) { - return ; - } - - const columns: AnalyticalTableColumnDefinition[] = [ - { - Header: t('ProvidersList.tableNameHeader'), - accessor: 'metadata.name', - }, - { - Header: t('ProvidersList.tableStatusHeader'), - accessor: 'status.phase', - }, - { - Header: t('ProvidersList.tableCreatedHeader'), - accessor: 'metadata.creationTimestamp', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Cell: (props: any) => , - }, - ]; - return ( <> - Providers - - ProviderConfigs - - + + ); diff --git a/src/lib/api/types/crossplane/listProviders.ts b/src/lib/api/types/crossplane/listProviders.ts index 36571c28..ffd92c4b 100644 --- a/src/lib/api/types/crossplane/listProviders.ts +++ b/src/lib/api/types/crossplane/listProviders.ts @@ -1,7 +1,25 @@ import { Resource } from '../resource'; -//TODO: type any to correct type and adapt the jq query to the required paramters -export const ListProviders: Resource = { - path: '/apis/pkg.crossplane.io/v1/providers', - jq: '[.items[]]', -}; + export type ProvidersListResponse = { + items: [{ + spec: { + package: string; + }; + kind: string; + metadata: { + name: string; + creationTimestamp: string; + }; + status: { + conditions: [{ + type: "Healthy" | "Installed" | unknown; + status: "True" | "False"; + lastTransitionTime: string; + }] + }; + }]; + }; + + export const ProvidersListRequest: Resource = { + path: "/apis/pkg.crossplane.io/v1/providers", + }; \ No newline at end of file diff --git a/src/lib/shared/constants.ts b/src/lib/shared/constants.ts new file mode 100644 index 00000000..8465326c --- /dev/null +++ b/src/lib/shared/constants.ts @@ -0,0 +1 @@ +export const resourcesInterval = 30000; diff --git a/src/lib/shared/interfaces.ts b/src/lib/shared/interfaces.ts new file mode 100644 index 00000000..5493b25d --- /dev/null +++ b/src/lib/shared/interfaces.ts @@ -0,0 +1,4 @@ +export interface StatusCellProps { + value: boolean; + transitionTime: string; +} \ No newline at end of file