1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-20 05:49:40 +02:00

refactor(kube/cluster): migrate node apps table to react [EE-4691] (#11016)

This commit is contained in:
Chaim Lev-Ari 2024-04-02 23:12:34 +03:00 committed by GitHub
parent 9c68c6c9f3
commit a5faddc56c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 233 additions and 261 deletions

View file

@ -0,0 +1,56 @@
import LaptopCode from '@/assets/ico/laptop-code.svg?c';
import { Datatable, TableSettingsMenu } from '@@/datatables';
import { useRepeater } from '@@/datatables/useRepeater';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useTableStateWithStorage } from '@@/datatables/useTableState';
import {
BasicTableSettings,
refreshableSettings,
RefreshableTableSettings,
} from '@@/datatables/types';
import { useColumns } from './columns';
import { NodeApplication } from './types';
interface TableSettings extends BasicTableSettings, RefreshableTableSettings {}
export function NodeApplicationsDatatable({
dataset,
onRefresh,
isLoading,
}: {
dataset: Array<NodeApplication>;
onRefresh: () => void;
isLoading: boolean;
}) {
const columns = useColumns(true);
const tableState = useTableStateWithStorage<TableSettings>(
'kube-node-apps',
'Name',
(set) => ({
...refreshableSettings(set),
})
);
useRepeater(tableState.autoRefreshRate, onRefresh);
return (
<Datatable
dataset={dataset}
settingsManager={tableState}
columns={columns}
disableSelect
title="Applications running on this node"
titleIcon={LaptopCode}
isLoading={isLoading}
renderTableSettings={() => (
<TableSettingsMenu>
<TableSettingsMenuAutoRefresh
value={tableState.autoRefreshRate}
onChange={tableState.setAutoRefreshRate}
/>
</TableSettingsMenu>
)}
/>
);
}

View file

@ -0,0 +1,5 @@
import { createColumnHelper } from '@tanstack/react-table';
import { NodeApplication } from './types';
export const helper = createColumnHelper<NodeApplication>();

View file

@ -0,0 +1,38 @@
import { CellContext } from '@tanstack/react-table';
import { isExternalApplication } from '@/react/kubernetes/applications/utils';
import { useIsSystemNamespace } from '@/react/kubernetes/namespaces/queries/useIsSystemNamespace';
import { ExternalBadge } from '@/react/kubernetes/components/ExternalBadge';
import { SystemBadge } from '@/react/kubernetes/components/SystemBadge';
import { Link } from '@@/Link';
import { helper } from './columns.helper';
import { NodeApplication } from './types';
export const name = helper.accessor('Name', {
header: 'Name',
cell: Cell,
});
function Cell({
row: { original: item },
}: CellContext<NodeApplication, string>) {
const isSystem = useIsSystemNamespace(item.ResourcePool);
return (
<div className="flex items-center gap-2">
<Link
to="kubernetes.applications.application"
params={{ name: item.Name, namespace: item.ResourcePool }}
>
{item.Name}
</Link>
{isSystem ? (
<SystemBadge />
) : (
isExternalApplication({ metadata: item.Metadata }) && <ExternalBadge />
)}
</div>
);
}

View file

@ -0,0 +1,57 @@
import { useMemo } from 'react';
import _ from 'lodash';
import { humanize, truncate } from '@/portainer/filters/filters';
import { Link } from '@@/Link';
import { helper } from './columns.helper';
import { name } from './columns.name';
export function useColumns(areStacksVisible: boolean) {
return useMemo(
() =>
_.compact([
name,
areStacksVisible &&
helper.accessor('StackName', {
header: 'Stack',
cell: ({ getValue }) => getValue() || '-',
}),
helper.accessor((item) => item.ResourcePool, {
header: 'Namespace',
cell: ({ getValue }) => {
const namespace = getValue();
return (
<Link
to="kubernetes.resourcePools.resourcePool"
params={{ id: namespace }}
>
{namespace}
</Link>
);
},
}),
helper.accessor('Image', {
header: 'Image',
cell: ({ row: { original: item } }) => (
<>
{truncate(item.Image, 64)}
{item.Containers?.length > 1 && (
<>+ {item.Containers.length - 1}</>
)}
</>
),
}),
helper.accessor('CPU', {
header: 'CPU reservation',
cell: ({ getValue }) => _.round(getValue(), 2),
}),
helper.accessor('Memory', {
header: 'Memory reservation',
cell: ({ getValue }) => humanize(getValue()),
}),
]),
[areStacksVisible]
);
}

View file

@ -0,0 +1,6 @@
import { KubernetesApplication } from '@/kubernetes/models/application/models';
export type NodeApplication = KubernetesApplication & {
CPU: number;
Memory: number;
};