1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

feat(edge/stacks): increase status transparency [EE-5554] (#9094)

This commit is contained in:
Chaim Lev-Ari 2023-07-13 23:55:52 +03:00 committed by GitHub
parent db61fb149b
commit 0bcb57568c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 1305 additions and 316 deletions

View file

@ -38,10 +38,10 @@ export function DeploymentCounter({
return (
<span
className={clsx(styles.root, {
[styles.statusOk]: type === 'Ok',
[styles.statusError]: type === 'Error',
[styles.statusAcknowledged]: type === 'Acknowledged',
[styles.statusImagesPulled]: type === 'ImagesPulled',
[styles.statusOk]: type === StatusType.Running,
[styles.statusError]: type === StatusType.Error,
[styles.statusAcknowledged]: type === StatusType.Acknowledged,
[styles.statusImagesPulled]: type === StatusType.ImagesPulled,
[styles.statusTotal]: type === undefined,
})}
>

View file

@ -4,7 +4,7 @@ import { Datatable } from '@@/datatables';
import { useTableState } from '@@/datatables/useTableState';
import { useEdgeStacks } from '../../queries/useEdgeStacks';
import { EdgeStack } from '../../types';
import { EdgeStack, StatusType } from '../../types';
import { createStore } from './store';
import { columns } from './columns';
@ -51,11 +51,16 @@ export function EdgeStacksDatatable() {
function aggregateStackStatus(stackStatus: EdgeStack['Status']) {
const aggregateStatus = { ok: 0, error: 0, acknowledged: 0, imagesPulled: 0 };
return Object.values(stackStatus).reduce((acc, envStatus) => {
acc.ok += Number(envStatus.Details.Ok);
acc.error += Number(envStatus.Details.Error);
acc.acknowledged += Number(envStatus.Details.Acknowledged);
acc.imagesPulled += Number(envStatus.Details.ImagesPulled);
return acc;
}, aggregateStatus);
return Object.values(stackStatus).reduce(
(acc, envStatus) =>
envStatus.Status.reduce((acc, status) => {
const { Type } = status;
acc.ok += Number(Type === StatusType.Running);
acc.error += Number(Type === StatusType.Error);
acc.acknowledged += Number(Type === StatusType.Acknowledged);
acc.imagesPulled += Number(Type === StatusType.ImagesPulled);
return acc;
}, acc),
aggregateStatus
);
}

View file

@ -0,0 +1,87 @@
import _ from 'lodash';
import {
AlertTriangle,
CheckCircle,
type Icon as IconType,
Loader2,
XCircle,
} from 'lucide-react';
import { Icon, IconMode } from '@@/Icon';
import { DeploymentStatus, EdgeStack, StatusType } from '../../types';
export function EdgeStackStatus({ edgeStack }: { edgeStack: EdgeStack }) {
const status = Object.values(edgeStack.Status);
const lastStatus = _.compact(status.map((s) => _.last(s.Status)));
const { icon, label, mode, spin } = getStatus(
edgeStack.NumDeployments,
lastStatus
);
return (
<div className="mx-auto inline-flex items-center gap-2">
{icon && <Icon icon={icon} spin={spin} mode={mode} />}
{label}
</div>
);
}
function getStatus(
numDeployments: number,
envStatus: Array<DeploymentStatus>
): {
label: string;
icon?: IconType;
spin?: boolean;
mode?: IconMode;
} {
if (envStatus.length < numDeployments) {
return {
label: 'Deploying',
icon: Loader2,
spin: true,
mode: 'primary',
};
}
const allFailed = envStatus.every((s) => s.Type === StatusType.Error);
if (allFailed) {
return {
label: 'Failed',
icon: XCircle,
mode: 'danger',
};
}
const allRunning = envStatus.every((s) => s.Type === StatusType.Running);
if (allRunning) {
return {
label: 'Running',
icon: CheckCircle,
mode: 'success',
};
}
const hasDeploying = envStatus.some((s) => s.Type === StatusType.Deploying);
const hasRunning = envStatus.some((s) => s.Type === StatusType.Running);
const hasFailed = envStatus.some((s) => s.Type === StatusType.Error);
if (hasRunning && hasFailed && !hasDeploying) {
return {
label: 'Partially Running',
icon: AlertTriangle,
mode: 'warning',
};
}
return {
label: 'Deploying',
icon: Loader2,
spin: true,
mode: 'primary',
};
}

View file

@ -6,6 +6,9 @@ import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
import { buildNameColumn } from '@@/datatables/NameCell';
import { StatusType } from '../../types';
import { EdgeStackStatus } from '../EdgeStackStatus';
import { DecoratedEdgeStack } from './types';
import { DeploymentCounter, DeploymentCounterLink } from './DeploymentCounter';
@ -25,7 +28,7 @@ export const columns = _.compact([
cell: ({ getValue, row }) => (
<DeploymentCounterLink
count={getValue()}
type="Acknowledged"
type={StatusType.Acknowledged}
stackId={row.original.Id}
/>
),
@ -39,7 +42,7 @@ export const columns = _.compact([
cell: ({ getValue, row }) => (
<DeploymentCounterLink
count={getValue()}
type="ImagesPulled"
type={StatusType.ImagesPulled}
stackId={row.original.Id}
/>
),
@ -54,7 +57,7 @@ export const columns = _.compact([
cell: ({ getValue, row }) => (
<DeploymentCounterLink
count={getValue()}
type="Ok"
type={StatusType.Running}
stackId={row.original.Id}
/>
),
@ -69,7 +72,7 @@ export const columns = _.compact([
cell: ({ getValue, row }) => (
<DeploymentCounterLink
count={getValue()}
type="Error"
type={StatusType.Error}
stackId={row.original.Id}
/>
),
@ -79,6 +82,19 @@ export const columns = _.compact([
className: '[&>*]:justify-center',
},
}),
columnHelper.accessor('Status', {
header: 'Status',
cell: ({ row }) => (
<div className="w-full text-center">
<EdgeStackStatus edgeStack={row.original} />
</div>
),
enableSorting: false,
enableHiding: false,
meta: {
className: '[&>*]:justify-center',
},
}),
columnHelper.accessor('NumDeployments', {
header: 'Deployments',
cell: ({ getValue }) => (