diff --git a/packages/renderer/src/lib/deployments/DeploymentColumnConditions.spec.ts b/packages/renderer/src/lib/deployments/DeploymentColumnConditions.spec.ts index b2f8b7b756134..377e35fe3b5ae 100644 --- a/packages/renderer/src/lib/deployments/DeploymentColumnConditions.spec.ts +++ b/packages/renderer/src/lib/deployments/DeploymentColumnConditions.spec.ts @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (C) 2023 Red Hat, Inc. + * Copyright (C) 2023-2024 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,26 +22,25 @@ import { render, screen } from '@testing-library/svelte'; import { expect, test } from 'vitest'; import DeploymentColumnConditions from './DeploymentColumnConditions.svelte'; -import type { DeploymentUI } from './DeploymentUI'; - -const deployment: DeploymentUI = { - name: 'my-deployment', - status: '', - namespace: '', - replicas: 0, - ready: 0, - selected: false, - conditions: [ - { type: 'Available', message: 'Running fine' }, - { type: 'ReplicaFailure', message: 'It failed!' }, - { type: 'Progressing', message: 'Working on it' }, - ], -}; +import type { DeploymentCondition } from './DeploymentUI'; + +function createDeploymentUI(conditions: DeploymentCondition[]) { + return { + name: 'my-deployment', + status: '', + namespace: '', + replicas: 0, + ready: 0, + selected: false, + conditions: conditions, + }; +} test('Expect column styling available', async () => { + const deployment = createDeploymentUI([{ type: 'Available', message: 'Running fine' }]); render(DeploymentColumnConditions, { object: deployment }); - const text = screen.getByText(deployment.conditions[0].type); + const text = screen.getByText('Available'); expect(text).toBeInTheDocument(); expect(text).toHaveClass('text-gray-500'); @@ -51,9 +50,10 @@ test('Expect column styling available', async () => { }); test('Expect column styling failure', async () => { + const deployment = createDeploymentUI([{ type: 'ReplicaFailure', message: 'It failed!' }]); render(DeploymentColumnConditions, { object: deployment }); - const text = screen.getByText(deployment.conditions[1].type); + const text = screen.getByText('ReplicaFailure'); expect(text).toBeInTheDocument(); expect(text).toHaveClass('text-gray-500'); @@ -63,9 +63,25 @@ test('Expect column styling failure', async () => { }); test('Expect column styling progressing', async () => { + const deployment = createDeploymentUI([{ type: 'Progressing', message: 'Working on it', reason: '' }]); + render(DeploymentColumnConditions, { object: deployment }); + + const text = screen.getByText('Progressing'); + expect(text).toBeInTheDocument(); + expect(text).toHaveClass('text-gray-500'); + + const dot = text.parentElement?.children[0].children[0]; + expect(dot).toBeInTheDocument(); + expect(dot).toHaveClass('text-sky-400'); +}); + +test('Expect column styling progressed', async () => { + const deployment = createDeploymentUI([ + { type: 'Progressing', message: 'Successfully progressed', reason: 'NewReplicaSetAvailable' }, + ]); render(DeploymentColumnConditions, { object: deployment }); - const text = screen.getByText(deployment.conditions[2].type); + const text = screen.getByText('Progressed'); expect(text).toBeInTheDocument(); expect(text).toHaveClass('text-gray-500'); diff --git a/packages/renderer/src/lib/deployments/DeploymentColumnConditions.svelte b/packages/renderer/src/lib/deployments/DeploymentColumnConditions.svelte index 617bbc8240580..657a7e4ac86bf 100644 --- a/packages/renderer/src/lib/deployments/DeploymentColumnConditions.svelte +++ b/packages/renderer/src/lib/deployments/DeploymentColumnConditions.svelte @@ -3,25 +3,31 @@ import { faCheckCircle, faExclamationTriangle, faQuestionCircle, faSync } from ' import { Tooltip } from '@podman-desktop/ui-svelte'; import Fa from 'svelte-fa'; -import type { DeploymentUI } from './DeploymentUI'; +import type { DeploymentCondition, DeploymentUI } from './DeploymentUI'; export let object: DeploymentUI; // Determine both the icon and color based on the deployment condition -function getConditionAttributes(type: string) { - switch (type) { +function getConditionAttributes(condition: DeploymentCondition) { + let name = condition.type; + switch (condition.type) { case 'Available': // faCheckCircle: Indicates a successful state, typically used to denote availability and operational readiness - return { color: 'text-green-600', icon: faCheckCircle }; + return { color: 'text-green-600', icon: faCheckCircle, name }; case 'Progressing': // faSync: Often used to represent ongoing processes or operations, fitting for a "Progressing" state - return { color: 'text-sky-400', icon: faSync }; + // If reason has NewReplicaSetAvailable then it's progressed + if (condition.reason === 'NewReplicaSetAvailable') { + name = 'Progressed'; + } + + return { color: 'text-sky-400', icon: faSync, name }; case 'ReplicaFailure': // faExclamationTriangle: Alerts and warnings - return { color: 'text-amber-600', icon: faExclamationTriangle }; + return { color: 'text-amber-600', icon: faExclamationTriangle, name }; default: // faQuestionCircle: Uncertain / unknown - return { color: 'text-gray-900', icon: faQuestionCircle }; + return { color: 'text-gray-900', icon: faQuestionCircle, name }; } } @@ -33,9 +39,9 @@ function getConditionAttributes(type: string) {
- {condition.type} + icon="{getConditionAttributes(condition).icon}" + class="{getConditionAttributes(condition).color} mr-1" /> + {getConditionAttributes(condition).name}
diff --git a/packages/renderer/src/lib/deployments/DeploymentUI.ts b/packages/renderer/src/lib/deployments/DeploymentUI.ts index 509c9c9fea8ac..1a1b3d909f81b 100644 --- a/packages/renderer/src/lib/deployments/DeploymentUI.ts +++ b/packages/renderer/src/lib/deployments/DeploymentUI.ts @@ -29,5 +29,6 @@ export interface DeploymentUI { export interface DeploymentCondition { type: string; + reason?: string; message?: string; } diff --git a/packages/renderer/src/lib/deployments/deployment-utils.spec.ts b/packages/renderer/src/lib/deployments/deployment-utils.spec.ts index fd0f3a8519774..470eacd1e5a02 100644 --- a/packages/renderer/src/lib/deployments/deployment-utils.spec.ts +++ b/packages/renderer/src/lib/deployments/deployment-utils.spec.ts @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (C) 2023 Red Hat, Inc. + * Copyright (C) 2023-2024 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,3 +45,19 @@ test('expect basic UI conversion', async () => { expect(deploymentUI.replicas).toEqual(4); expect(deploymentUI.ready).toEqual(2); }); + +test('expect conditions to be sorted even if they are not in order', async () => { + const deployment = { + status: { + conditions: [ + { type: 'B', message: 'message B', reason: 'reason B' }, + { type: 'A', message: 'message A', reason: 'reason A' }, + ], + }, + } as V1Deployment; + const deploymentUI = deploymentUtils.getDeploymentUI(deployment); + expect(deploymentUI.conditions).toEqual([ + { type: 'A', message: 'message A', reason: 'reason A' }, + { type: 'B', message: 'message B', reason: 'reason B' }, + ]); +}); diff --git a/packages/renderer/src/lib/deployments/deployment-utils.ts b/packages/renderer/src/lib/deployments/deployment-utils.ts index 63224c366e3f6..fe83f498d6759 100644 --- a/packages/renderer/src/lib/deployments/deployment-utils.ts +++ b/packages/renderer/src/lib/deployments/deployment-utils.ts @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (C) 2023 Red Hat, Inc. + * Copyright (C) 2023-2024 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,15 @@ import type { DeploymentUI } from './DeploymentUI'; export class DeploymentUtils { getDeploymentUI(deployment: V1Deployment): DeploymentUI { + // Conditions (retrieving and sorting) const conditions = (deployment.status?.conditions ?? []).map(c => { - return { type: c.type, message: c.message }; + return { type: c.type, message: c.message, reason: c.reason }; }); + + // Sort the conditions by type so that they are always in the same order + conditions.sort((a, b) => a.type.localeCompare(b.type)); + + // Status let status = 'STOPPED'; if (deployment.status?.readyReplicas && deployment.status?.readyReplicas > 0) { if (deployment.status?.replicas === deployment.status?.readyReplicas) { @@ -33,6 +39,7 @@ export class DeploymentUtils { status = 'DEGRADED'; } } + return { name: deployment.metadata?.name ?? '', status: status,