From 42fce1ec57de687e2d55187e5c3ada7ff1fa3b9b Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Thu, 11 May 2023 12:55:15 +1200 Subject: [PATCH] fix(kube-tables): update table accessor fns [EE-5464] (#8920) * fix(services): update accessor fns [EE-5464] * small fixes --------- Co-authored-by: testa113 --- .../ServicesDatatable/ServicesDatatable.tsx | 3 +- .../ServicesDatatable/columns/clusterIP.tsx | 71 +++++++++--------- .../ServicesDatatable/columns/created.tsx | 33 +++++---- .../ServicesDatatable/columns/externalIP.tsx | 6 +- .../ServicesDatatable/columns/name.tsx | 72 +++++++++++-------- .../ServicesDatatable/columns/ports.tsx | 7 +- .../ServicesDatatable/columns/targetPorts.tsx | 7 +- .../IngressDatatable/columns/created.tsx | 31 ++++---- .../IngressDatatable/columns/ingressRules.tsx | 26 ++++--- 9 files changed, 148 insertions(+), 108 deletions(-) diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/ServicesDatatable.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/ServicesDatatable.tsx index b11cc10de..050b4469e 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/ServicesDatatable.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/ServicesDatatable.tsx @@ -21,6 +21,7 @@ import { useTableState } from '@@/datatables/useTableState'; import { useMutationDeleteServices, useServices } from '../service'; import { Service } from '../types'; import { DefaultDatatableSettings } from '../../datatables/DefaultDatatableSettings'; +import { isSystemNamespace } from '../../namespaces/utils'; import { columns } from './columns'; import { createStore } from './datatable-store'; @@ -40,7 +41,7 @@ export function ServicesDatatable() { const filteredServices = servicesQuery.data?.filter( (service) => (isAdmin && tableState.showSystemResources) || - !KubernetesNamespaceHelper.isSystemNamespace(service.Namespace) + !isSystemNamespace(service.Namespace) ); return ( diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/clusterIP.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/clusterIP.tsx index 6b84e7d00..452f7293b 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/clusterIP.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/clusterIP.tsx @@ -1,38 +1,41 @@ import { columnHelper } from './helper'; -export const clusterIP = columnHelper.accessor('ClusterIPs', { - header: 'Cluster IP', - id: 'clusterIP', - cell: ({ getValue }) => { - const clusterIPs = getValue(); +export const clusterIP = columnHelper.accessor( + (row) => row.ClusterIPs?.join(','), + { + header: 'Cluster IP', + id: 'clusterIP', + cell: ({ row }) => { + const clusterIPs = row.original.ClusterIPs; - if (!clusterIPs?.length) { - return '-'; - } - return clusterIPs.map((ip) =>
{ip}
); - }, - sortingFn: (rowA, rowB) => { - const a = rowA.original.ClusterIPs; - const b = rowB.original.ClusterIPs; - - const ipA = a?.[0]; - const ipB = b?.[0]; - - // no ip's at top, followed by 'None', then ordered by ip - if (!ipA) return 1; - if (!ipB) return -1; - if (ipA === ipB) return 0; - if (ipA === 'None') return 1; - if (ipB === 'None') return -1; - - // natural sort of the ip - return ipA.localeCompare( - ipB, - navigator.languages[0] || navigator.language, - { - numeric: true, - ignorePunctuation: true, + if (!clusterIPs?.length) { + return '-'; } - ); - }, -}); + return clusterIPs.map((ip) =>
{ip}
); + }, + sortingFn: (rowA, rowB) => { + const a = rowA.original.ClusterIPs; + const b = rowB.original.ClusterIPs; + + const ipA = a?.[0]; + const ipB = b?.[0]; + + // no ip's at top, followed by 'None', then ordered by ip + if (!ipA) return 1; + if (!ipB) return -1; + if (ipA === ipB) return 0; + if (ipA === 'None') return 1; + if (ipB === 'None') return -1; + + // natural sort of the ip + return ipA.localeCompare( + ipB, + navigator.languages[0] || navigator.language, + { + numeric: true, + ignorePunctuation: true, + } + ); + }, + } +); diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/created.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/created.tsx index c28627c13..d6994a3e7 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/created.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/created.tsx @@ -2,19 +2,22 @@ import { formatDate } from '@/portainer/filters/filters'; import { columnHelper } from './helper'; -export const created = columnHelper.accessor('CreationTimestamp', { - header: 'Created', - id: 'created', - cell: ({ row, getValue }) => { - const date = formatDate(getValue()); - - const owner = - row.original.Labels?.['io.portainer.kubernetes.application.owner']; - - if (owner) { - return `${date} by ${owner}`; - } - - return date; +export const created = columnHelper.accessor( + (row) => { + const owner = row.Labels?.['io.portainer.kubernetes.application.owner']; + const date = formatDate(row.CreationTimestamp); + return owner ? `${date} by ${owner}` : date; }, -}); + { + header: 'Created', + id: 'created', + cell: ({ row }) => { + const date = formatDate(row.original.CreationTimestamp); + + const owner = + row.original.Labels?.['io.portainer.kubernetes.application.owner']; + + return owner ? `${date} by ${owner}` : date; + }, + } +); diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/externalIP.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/externalIP.tsx index 84c6e9a93..7e414deb5 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/externalIP.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/externalIP.tsx @@ -8,14 +8,14 @@ import { columnHelper } from './helper'; export const externalIP = columnHelper.accessor( (row) => { if (row.Type === 'ExternalName') { - return row.ExternalName; + return row.ExternalName || ''; } if (row.ExternalIPs?.length) { - return row.ExternalIPs?.slice(0); + return row.ExternalIPs?.join(',') || ''; } - return row.IngressStatus?.slice(0); + return row.IngressStatus?.map((status) => status.IP).join(',') || ''; }, { header: 'External IP', diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/name.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/name.tsx index c06c99e6a..1561c7aad 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/name.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/name.tsx @@ -1,37 +1,53 @@ import { Authorized } from '@/react/hooks/useUser'; -import KubernetesNamespaceHelper from '@/kubernetes/helpers/namespaceHelper'; +import { isSystemNamespace } from '@/react/kubernetes/namespaces/utils'; import { columnHelper } from './helper'; -export const name = columnHelper.accessor('Name', { - header: 'Name', - id: 'name', - cell: ({ row, getValue }) => { - const name = getValue(); - const isSystem = KubernetesNamespaceHelper.isSystemNamespace( - row.original.Namespace - ); +export const name = columnHelper.accessor( + (row) => { + let name = row.Name; const isExternal = - !row.original.Labels || - !row.original.Labels['io.portainer.kubernetes.application.owner']; + !row.Labels || !row.Labels['io.portainer.kubernetes.application.owner']; + const isSystem = isSystemNamespace(row.Namespace); - return ( - - {name} + if (isExternal && !isSystem) { + name = `${name} external`; + } - {isSystem && ( - - system - - )} - - {isExternal && !isSystem && ( - - external - - )} - - ); + if (isSystem) { + name = `${name} system`; + } + return name; }, -}); + { + header: 'Name', + id: 'Name', + cell: ({ row }) => { + const name = row.original.Name; + const isSystem = isSystemNamespace(row.original.Namespace); + + const isExternal = + !row.original.Labels || + !row.original.Labels['io.portainer.kubernetes.application.owner']; + + return ( + + {name} + + {isSystem && ( + + system + + )} + + {isExternal && !isSystem && ( + + external + + )} + + ); + }, + } +); diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/ports.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/ports.tsx index d36061ff1..92e554460 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/ports.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/ports.tsx @@ -4,7 +4,12 @@ import { columnHelper } from './helper'; export const ports = columnHelper.accessor( (row) => - row.Ports.map((port) => `${port.Port}:${port.NodePort}/${port.Protocol}`), + row.Ports.map( + (port) => + `${port.Port}${port.NodePort !== 0 ? `:${port.NodePort}` : ''}/${ + port.Protocol + }` + ).join(',') || '-', { header: () => ( <> diff --git a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/targetPorts.tsx b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/targetPorts.tsx index e0d30fa14..292cff805 100644 --- a/app/react/kubernetes/ServicesView/ServicesDatatable/columns/targetPorts.tsx +++ b/app/react/kubernetes/ServicesView/ServicesDatatable/columns/targetPorts.tsx @@ -1,13 +1,12 @@ import { columnHelper } from './helper'; export const targetPorts = columnHelper.accessor( - (row) => row.Ports.map((port) => `${port.TargetPort}`), + (row) => row.Ports.map((port) => port.TargetPort).join(','), { header: 'Target Ports', id: 'targetPorts', - cell: ({ getValue }) => { - const ports = getValue(); - + cell: ({ row }) => { + const ports = row.original.Ports.map((port) => port.TargetPort); if (!ports.length) { return '-'; } diff --git a/app/react/kubernetes/ingresses/IngressDatatable/columns/created.tsx b/app/react/kubernetes/ingresses/IngressDatatable/columns/created.tsx index 144855256..e9d88c4a6 100644 --- a/app/react/kubernetes/ingresses/IngressDatatable/columns/created.tsx +++ b/app/react/kubernetes/ingresses/IngressDatatable/columns/created.tsx @@ -2,18 +2,21 @@ import { formatDate } from '@/portainer/filters/filters'; import { columnHelper } from './helper'; -export const created = columnHelper.accessor('CreationDate', { - header: 'Created', - cell: ({ row, getValue }) => { - const date = formatDate(getValue()); - const owner = - row.original.Labels?.['io.portainer.kubernetes.ingress.owner']; - - if (owner) { - return `${date} by ${owner}`; - } - - return date; +export const created = columnHelper.accessor( + (row) => { + const owner = row.Labels?.['io.portainer.kubernetes.ingress.owner']; + const date = formatDate(row.CreationDate); + return owner ? `${date} by ${owner}` : date; }, - id: 'created', -}); + { + header: 'Created', + cell: ({ row, getValue }) => { + const date = formatDate(getValue()); + const owner = + row.original.Labels?.['io.portainer.kubernetes.ingress.owner']; + + return owner ? `${date} by ${owner}` : date; + }, + id: 'created', + } +); diff --git a/app/react/kubernetes/ingresses/IngressDatatable/columns/ingressRules.tsx b/app/react/kubernetes/ingresses/IngressDatatable/columns/ingressRules.tsx index cedcaa338..36a9dedad 100644 --- a/app/react/kubernetes/ingresses/IngressDatatable/columns/ingressRules.tsx +++ b/app/react/kubernetes/ingresses/IngressDatatable/columns/ingressRules.tsx @@ -4,18 +4,28 @@ import { AlertTriangle, ArrowRight } from 'lucide-react'; import { Icon } from '@@/Icon'; import { Badge } from '@@/Badge'; -import { Ingress, TLS, Path } from '../../types'; +import { Ingress, TLS } from '../../types'; import { columnHelper } from './helper'; -export const ingressRules = columnHelper.accessor('Paths', { - header: 'Rules and Paths', - id: 'ingressRules', - cell: Cell, -}); +export const ingressRules = columnHelper.accessor( + ({ Paths, TLS }) => + // return an accessor function with all the useful text to search for + Paths.map((path) => { + const isHttp = isHTTP(TLS || [], path.Host); + return `${isHttp ? 'http' : 'https'}://${path.Host}${path.Path}${ + path.ServiceName + }:${path.Port} ${!path.HasService && "Service doesn't exist"}`; + }).join(','), + { + header: 'Rules and Paths', + id: 'ingressRules', + cell: Cell, + } +); -function Cell({ row, getValue }: CellContext) { - const paths = getValue(); +function Cell({ row }: CellContext) { + const paths = row.original.Paths; if (!paths) { return
;