-
+
{deploymentReasonLabel && (
diff --git a/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.spec.tsx b/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.spec.tsx
index 0487137548d..d7f94026945 100644
--- a/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.spec.tsx
+++ b/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.spec.tsx
@@ -1,5 +1,5 @@
import download from 'downloadjs'
-import { ClusterStateEnum } from 'qovery-typescript-axios'
+import { ClusterDeploymentHistoryOperationEnum, ClusterStateEnum } from 'qovery-typescript-axios'
import { type RefObject } from 'react'
import { clusterFactoryMock, clusterLogFactoryMock } from '@qovery/shared/factories'
import { renderWithProviders, screen } from '@qovery/shared/util-tests'
@@ -45,6 +45,20 @@ describe('ClusterHeaderLogs', () => {
expect(screen.getByText('Romain Billard')).toBeInTheDocument()
})
+ it('should render an Operator update badge when operation is OPERATOR_UPDATE', () => {
+ renderWithProviders(
+
+ )
+
+ expect(screen.getByText('Operator update')).toBeInTheDocument()
+ })
+
+ it('should not render an Operator update badge when operation is CLUSTER', () => {
+ renderWithProviders(
)
+
+ expect(screen.queryByText('Operator update')).not.toBeInTheDocument()
+ })
+
it('should trigger scroll up on click', async () => {
const { userEvent } = renderWithProviders(
)
const scrollUpButton = screen.getByTestId('scroll-up-button')
diff --git a/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.tsx b/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.tsx
index c5d67642b6e..4a94246eb88 100644
--- a/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.tsx
+++ b/libs/domains/clusters/feature/src/lib/cluster-logs/cluster-header-logs/cluster-header-logs.tsx
@@ -2,6 +2,7 @@ import download from 'downloadjs'
import posthog from 'posthog-js'
import {
type Cluster,
+ ClusterDeploymentHistoryOperationEnum,
type ClusterLogs,
type ClusterStatus,
type DeploymentHistoryActionStatus,
@@ -9,7 +10,7 @@ import {
} from 'qovery-typescript-axios'
import { type RefObject, useContext } from 'react'
import { DevopsCopilotContext } from '@qovery/shared/devops-copilot/feature'
-import { Button, Icon, Tooltip, Truncate } from '@qovery/shared/ui'
+import { Badge, Button, Icon, Tooltip, Truncate } from '@qovery/shared/ui'
import { dateDifference, dateFullFormat, dateUTCString, formatDuration } from '@qovery/shared/util-dates'
import { useIntervalTick } from '@qovery/shared/util-hooks'
import { EventOriginIcon } from '@qovery/shared/util-icons'
@@ -35,6 +36,7 @@ export interface ClusterHeaderLogsProps {
triggeredBy?: string | null
actionStatus?: DeploymentHistoryActionStatus
totalDuration?: string | null
+ operation?: ClusterDeploymentHistoryOperationEnum
}
export function ClusterHeaderLogs({
@@ -49,6 +51,7 @@ export function ClusterHeaderLogs({
triggeredBy,
actionStatus,
totalDuration,
+ operation,
}: ClusterHeaderLogsProps) {
const { setDevopsCopilotOpen, sendMessageRef } = useContext(DevopsCopilotContext)
@@ -90,6 +93,11 @@ export function ClusterHeaderLogs({
)}
+ {operation === ClusterDeploymentHistoryOperationEnum.OPERATOR_UPDATE && (
+
+ Operator update
+
+ )}
{createdAt && (
<>
{
it('returns undefined without status details', () => {
@@ -18,3 +20,34 @@ describe('getTriggerAction', () => {
expect(getTriggerAction({})).toBe('UNKNOWN')
})
})
+
+describe('DeploymentAction', () => {
+ it('renders the action label derived from the status', () => {
+ renderWithProviders()
+
+ expect(screen.getByText('Deploy')).toBeInTheDocument()
+ })
+
+ it('renders the Operator action with a screen-reader description for an Operator update', () => {
+ const { container } = renderWithProviders(
+
+ )
+
+ expect(screen.getByText('Operator')).toHaveAttribute('aria-hidden', 'true')
+ expect(screen.getByText('Operator update')).toHaveClass('sr-only')
+ expect(screen.queryByText('Deploy')).not.toBeInTheDocument()
+ expect(container.querySelector('.fa-rotate-right')).toBeInTheDocument()
+ expect(container.querySelector('.fa-rocket')).not.toBeInTheDocument()
+ expect(container.querySelector('[tabindex]')).toBeNull()
+ })
+
+ it('renders the status action without a description for a cluster operation', () => {
+ const { container } = renderWithProviders(
+
+ )
+
+ expect(screen.getByText('Deploy')).not.toHaveAttribute('aria-hidden')
+ expect(screen.queryByText('Operator update')).not.toBeInTheDocument()
+ expect(container.querySelector('.fa-rocket')).toBeInTheDocument()
+ })
+})
diff --git a/libs/shared/ui/src/lib/components/deployment-action/deployment-action.tsx b/libs/shared/ui/src/lib/components/deployment-action/deployment-action.tsx
index 21c5181e20c..24e883dc413 100644
--- a/libs/shared/ui/src/lib/components/deployment-action/deployment-action.tsx
+++ b/libs/shared/ui/src/lib/components/deployment-action/deployment-action.tsx
@@ -1,4 +1,5 @@
import {
+ ClusterDeploymentHistoryOperationEnum,
type ClusterStateEnum,
type DeploymentHistoryTriggerAction,
type ServiceActionEnum,
@@ -137,6 +138,15 @@ export const getDeploymentAction = (
.exhaustive()
}
+const getDeploymentOperationAction = (operation?: ClusterDeploymentHistoryOperationEnum) =>
+ operation === ClusterDeploymentHistoryOperationEnum.OPERATOR_UPDATE
+ ? {
+ status: 'Operator',
+ description: 'Operator update',
+ icon: ,
+ }
+ : undefined
+
export const getTriggerAction = (statusDetails?: {
action?: ServiceActionEnum
sub_action?: ServiceSubActionEnum
@@ -148,6 +158,7 @@ export const getTriggerAction = (statusDetails?: {
export const DeploymentAction = ({
status,
+ operation,
className,
iconClassName,
textClassName,
@@ -161,17 +172,22 @@ export const DeploymentAction = ({
| StageStatusEnum
| StepMetricStatusEnum
| undefined
+ operation?: ClusterDeploymentHistoryOperationEnum
className?: string
iconClassName?: string
textClassName?: string
}) => {
- const action = getDeploymentAction(status)
+ const operationAction = getDeploymentOperationAction(operation)
+ const action = operationAction ?? getDeploymentAction(status)
if (!status || !action) return null
return (
{action.icon}
- {action.status}
+
+ {action.status}
+
+ {operationAction && {operationAction.description}}
)
}
diff --git a/package.json b/package.json
index 9cda0d0263e..26248dcb196 100644
--- a/package.json
+++ b/package.json
@@ -78,7 +78,7 @@
"mermaid": "11.6.0",
"monaco-editor": "0.53.0",
"posthog-js": "1.345.1",
- "qovery-typescript-axios": "1.1.1004",
+ "qovery-typescript-axios": "1.1.1007",
"react": "19.3.0",
"react-country-flag": "3.0.2",
"react-datepicker": "4.12.0",
diff --git a/yarn.lock b/yarn.lock
index c8d85d5dfea..6ece0fd2fff 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6285,7 +6285,7 @@ __metadata:
prettier: 3.2.5
prettier-plugin-tailwindcss: 0.5.14
pretty-quick: 4.0.0
- qovery-typescript-axios: 1.1.1004
+ qovery-typescript-axios: 1.1.1007
qovery-ws-typescript-axios: 0.1.666
react: 19.3.0
react-country-flag: 3.0.2
@@ -24656,12 +24656,12 @@ __metadata:
languageName: node
linkType: hard
-"qovery-typescript-axios@npm:1.1.1004":
- version: 1.1.1004
- resolution: "qovery-typescript-axios@npm:1.1.1004"
+"qovery-typescript-axios@npm:1.1.1007":
+ version: 1.1.1007
+ resolution: "qovery-typescript-axios@npm:1.1.1007"
dependencies:
axios: 1.20.0
- checksum: 99fca71abb55689b534cb7c3874deabb11fe6c20a564d7bd4b03d034f5a2a37c4daefbb568b46b468141b7ad7a858daae7e1013516fa8ba272046ba9ba635d73
+ checksum: f8662f1567d11edcbe0119c2db44ceeb0b1f0181517b31ca70c89173872dde9fde0f07087b48cbd0d81372c4399675191b520378e9021539ecca100182a5bba8
languageName: node
linkType: hard