mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat: add warning events count next to the status badge (#828)
This commit is contained in:
parent
f4df51884c
commit
1332f718ae
18 changed files with 120 additions and 37 deletions
|
@ -28,6 +28,7 @@ const tests: NamespaceTestData[] = [
|
|||
Status: {
|
||||
phase: 'Active',
|
||||
},
|
||||
UnhealthyEventCount: 0,
|
||||
Annotations: null,
|
||||
CreationDate: '2024-10-17T17:50:08+13:00',
|
||||
NamespaceOwner: 'admin',
|
||||
|
@ -118,6 +119,7 @@ const tests: NamespaceTestData[] = [
|
|||
Status: {
|
||||
phase: 'Active',
|
||||
},
|
||||
UnhealthyEventCount: 0,
|
||||
Annotations: {
|
||||
asdf: 'asdf',
|
||||
},
|
||||
|
|
|
@ -41,6 +41,7 @@ export function NamespacesDatatable() {
|
|||
const namespacesQuery = useNamespacesQuery(environmentId, {
|
||||
autoRefreshRate: tableState.autoRefreshRate * 1000,
|
||||
withResourceQuota: true,
|
||||
withUnhealthyEvents: true,
|
||||
});
|
||||
const namespaces = Object.values(namespacesQuery.data ?? []);
|
||||
|
||||
|
@ -181,6 +182,7 @@ function TableActions({
|
|||
queryClient.setQueryData(
|
||||
queryKeys.list(environmentId, {
|
||||
withResourceQuota: true,
|
||||
withUnhealthyEvents: true,
|
||||
}),
|
||||
() => remainingNamespaces
|
||||
);
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { AlertTriangle } from 'lucide-react';
|
||||
|
||||
import { isoDate } from '@/portainer/filters/filters';
|
||||
import { useAuthorizations } from '@/react/hooks/useUser';
|
||||
import { pluralize } from '@/portainer/helpers/strings';
|
||||
|
||||
import { Link } from '@@/Link';
|
||||
import { StatusBadge } from '@@/StatusBadge';
|
||||
import { Badge } from '@@/Badge';
|
||||
import { SystemBadge } from '@@/Badge/SystemBadge';
|
||||
import { TooltipWithChildren } from '@@/Tip/TooltipWithChildren';
|
||||
import { Icon } from '@@/Icon';
|
||||
|
||||
import { helper } from './helper';
|
||||
import { actions } from './actions';
|
||||
|
@ -45,12 +49,34 @@ export function useColumns() {
|
|||
}),
|
||||
helper.accessor('Status', {
|
||||
header: 'Status',
|
||||
cell({ getValue }) {
|
||||
cell({ getValue, row: { original: item } }) {
|
||||
const status = getValue();
|
||||
return (
|
||||
<StatusBadge color={getColor(status.phase)}>
|
||||
{status.phase}
|
||||
</StatusBadge>
|
||||
<div className="flex items-center gap-2">
|
||||
<StatusBadge color={getColor(status.phase)}>
|
||||
{status.phase}
|
||||
</StatusBadge>
|
||||
{item.UnhealthyEventCount > 0 && (
|
||||
<TooltipWithChildren message="View events" position="top">
|
||||
<span className="inline-flex">
|
||||
<Link
|
||||
to="kubernetes.resourcePools.resourcePool"
|
||||
params={{ id: item.Name, tab: 'events' }}
|
||||
data-cy={`namespace-warning-link-${item.Name}`}
|
||||
>
|
||||
<Badge type="warnSecondary">
|
||||
<Icon
|
||||
icon={AlertTriangle}
|
||||
className="!mr-1 h-3 w-3"
|
||||
/>
|
||||
{item.UnhealthyEventCount}{' '}
|
||||
{pluralize(item.UnhealthyEventCount, 'warning')}
|
||||
</Badge>
|
||||
</Link>
|
||||
</span>
|
||||
</TooltipWithChildren>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
function getColor(status?: string) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { EnvironmentId } from '@/react/portainer/environments/types';
|
|||
export const queryKeys = {
|
||||
list: (
|
||||
environmentId: EnvironmentId,
|
||||
options?: { withResourceQuota?: boolean }
|
||||
options?: { withResourceQuota?: boolean; withUnhealthyEvents?: boolean }
|
||||
) =>
|
||||
compact([
|
||||
'environments',
|
||||
|
@ -13,6 +13,7 @@ export const queryKeys = {
|
|||
'kubernetes',
|
||||
'namespaces',
|
||||
options?.withResourceQuota,
|
||||
options?.withUnhealthyEvents,
|
||||
]),
|
||||
namespace: (environmentId: EnvironmentId, namespace: string) =>
|
||||
[
|
||||
|
|
|
@ -13,14 +13,21 @@ export function useNamespacesQuery<T = PortainerNamespace[]>(
|
|||
options?: {
|
||||
autoRefreshRate?: number;
|
||||
withResourceQuota?: boolean;
|
||||
withUnhealthyEvents?: boolean;
|
||||
select?: (namespaces: PortainerNamespace[]) => T;
|
||||
}
|
||||
) {
|
||||
return useQuery(
|
||||
queryKeys.list(environmentId, {
|
||||
withResourceQuota: !!options?.withResourceQuota,
|
||||
withUnhealthyEvents: !!options?.withUnhealthyEvents,
|
||||
}),
|
||||
async () => getNamespaces(environmentId, options?.withResourceQuota),
|
||||
async () =>
|
||||
getNamespaces(
|
||||
environmentId,
|
||||
options?.withResourceQuota,
|
||||
options?.withUnhealthyEvents
|
||||
),
|
||||
{
|
||||
...withGlobalError('Unable to get namespaces.'),
|
||||
refetchInterval() {
|
||||
|
@ -34,9 +41,13 @@ export function useNamespacesQuery<T = PortainerNamespace[]>(
|
|||
// getNamespaces is used to retrieve namespaces using the Portainer backend with caching
|
||||
export async function getNamespaces(
|
||||
environmentId: EnvironmentId,
|
||||
withResourceQuota?: boolean
|
||||
withResourceQuota?: boolean,
|
||||
withUnhealthyEvents?: boolean
|
||||
) {
|
||||
const params = withResourceQuota ? { withResourceQuota } : {};
|
||||
const params = {
|
||||
withResourceQuota,
|
||||
withUnhealthyEvents,
|
||||
};
|
||||
try {
|
||||
const { data: namespaces } = await axios.get<PortainerNamespace[]>(
|
||||
`kubernetes/${environmentId}/namespaces`,
|
||||
|
|
|
@ -10,6 +10,7 @@ export interface PortainerNamespace {
|
|||
Id: string;
|
||||
Name: string;
|
||||
Status: NamespaceStatus;
|
||||
UnhealthyEventCount: number;
|
||||
Annotations: Record<string, string> | null;
|
||||
CreationDate: string;
|
||||
NamespaceOwner: string;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue