Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ function RouteComponent() {
</div>
) : isLogsFetched && logs.length > 0 ? (
<>
<div className="flex h-11 min-h-11 w-full items-center justify-end border-b border-neutral bg-surface-neutral-subtle px-1">
<ClusterHeaderLogs data={logs} refScrollSection={refScrollSection} />
<div className="flex h-11 min-h-11 w-full items-center border-b border-neutral bg-surface-neutral-subtle">
<ClusterHeaderLogs
cluster={cluster}
clusterStatus={clusterStatus}
data={logs}
refScrollSection={refScrollSection}
/>
</div>
<ClusterLogsList logs={logs} firstDate={firstDate} refScrollSection={refScrollSection} />
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import download from 'downloadjs'
import { ClusterStateEnum } from 'qovery-typescript-axios'
import { type RefObject } from 'react'
import { clusterLogFactoryMock } from '@qovery/shared/factories'
import { clusterFactoryMock, clusterLogFactoryMock } from '@qovery/shared/factories'
import { renderWithProviders, screen } from '@qovery/shared/util-tests'
import ClusterHeaderLogs, { type ClusterHeaderLogsProps } from './cluster-header-logs'

Expand All @@ -15,24 +16,28 @@ const refScrollSection: RefObject<HTMLDivElement> = {
describe('ClusterHeaderLogs', () => {
const baseData = clusterLogFactoryMock(2, false)

const props: ClusterHeaderLogsProps = {
cluster: clusterFactoryMock(1)[0],
clusterStatus: {
cluster_id: '1',
status: ClusterStateEnum.DEPLOYED,
last_execution_id: '1',
is_deployed: true,
},
refScrollSection: refScrollSection,
data: baseData,
}

beforeEach(() => {
jest.clearAllMocks()
})

it('should render successfully', () => {
const props: ClusterHeaderLogsProps = {
refScrollSection: refScrollSection,
data: baseData,
}
const { baseElement } = renderWithProviders(<ClusterHeaderLogs {...props} />)
expect(baseElement).toBeTruthy()
})

it('should trigger scroll up on click', async () => {
const props: ClusterHeaderLogsProps = {
refScrollSection: refScrollSection,
data: baseData,
}
const { userEvent } = renderWithProviders(<ClusterHeaderLogs {...props} />)
const scrollUpButton = screen.getByTestId('scroll-up-button')

Expand All @@ -41,10 +46,6 @@ describe('ClusterHeaderLogs', () => {
})

it('should trigger scroll down on click', async () => {
const props: ClusterHeaderLogsProps = {
refScrollSection: refScrollSection,
data: baseData,
}
const { userEvent } = renderWithProviders(<ClusterHeaderLogs {...props} />)
const scrollDownButton = screen.getByTestId('scroll-down-button')

Expand All @@ -53,10 +54,6 @@ describe('ClusterHeaderLogs', () => {
})

it('should trigger download on click', async () => {
const props: ClusterHeaderLogsProps = {
refScrollSection: refScrollSection,
data: baseData,
}
const { userEvent } = renderWithProviders(<ClusterHeaderLogs {...props} />)
const buttons = screen.getAllByRole('button')
const downloadButton = buttons[2]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import download from 'downloadjs'
import { type ClusterLogs } from 'qovery-typescript-axios'
import { type Cluster, type ClusterLogs, type ClusterStatus } from 'qovery-typescript-axios'
import { type RefObject } from 'react'
import { Button, Icon } from '@qovery/shared/ui'
import { Badge, Button, Icon, Tooltip } from '@qovery/shared/ui'
import { trimId } from '@qovery/shared/util-js'

export interface ClusterHeaderLogsProps {
cluster: Cluster
clusterStatus: ClusterStatus
refScrollSection: RefObject<HTMLDivElement>
data: ClusterLogs[]
}

export function ClusterHeaderLogs(props: ClusterHeaderLogsProps) {
const { refScrollSection, data } = props

export function ClusterHeaderLogs({ cluster, clusterStatus, refScrollSection, data }: ClusterHeaderLogsProps) {
const downloadJSON = () => {
download(JSON.stringify(data), `data-${Date.now()}.json`, 'text/json;charset=utf-8')
}
Expand All @@ -26,44 +27,69 @@ export function ClusterHeaderLogs(props: ClusterHeaderLogsProps) {
}
}

const lastExecutionId = clusterStatus.last_execution_id ?? ''

return (
<>
<Button
data-testid="scroll-up-button"
className="rounded-br-none rounded-tr-none border-r-0"
type="button"
variant="outline"
color="neutral"
size="sm"
iconOnly
onClick={() => forcedScroll()}
>
<Icon iconName="arrow-up-to-line" />
</Button>
<Button
data-testid="scroll-down-button"
className="mr-2 rounded-bl-none rounded-tl-none"
variant="outline"
type="button"
color="neutral"
size="sm"
iconOnly
onClick={() => forcedScroll(true)}
>
<Icon iconName="arrow-down-to-line" />
</Button>
<Button
type="button"
variant="outline"
color="neutral"
size="sm"
className="mr-1"
iconOnly
onClick={() => downloadJSON()}
>
<Icon iconName="cloud-arrow-down" />
</Button>
</>
<div className="flex w-full items-center justify-between gap-2 pl-5 pr-3 text-sm">
<div className="flex items-center gap-2">
<Tooltip
side="bottom"
content={
<span>
Cluster version: {cluster.version} <br />
Cluster ID: {cluster.id}
</span>
}
>
<Badge variant="surface" className="max-w-full whitespace-nowrap">
{cluster.version}
</Badge>
</Tooltip>
<Tooltip side="bottom" content={<span>Execution id: {lastExecutionId}</span>}>
<span className="flex items-center gap-1.5 truncate">
<Icon iconName="code" iconStyle="regular" className="text-base text-neutral-subtle" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Icon iconName="code" iconStyle="regular" className="text-base text-neutral-subtle" />
<Icon iconName="code" iconStyle="regular" className="text-sm text-neutral-subtle" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh I'm even wondering if we should not just have the execution id in the same small "tag" as the cluster version, could be even more clean

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay! do you want I update the size for the service side too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep you can harmonize the changes on both pages!

<span className="font-normal text-neutral">{trimId(lastExecutionId)}</span>
</span>
</Tooltip>
</div>
<div>
<Button
data-testid="scroll-up-button"
className="rounded-br-none rounded-tr-none border-r-0"
type="button"
variant="outline"
color="neutral"
size="sm"
iconOnly
onClick={() => forcedScroll()}
>
<Icon iconName="arrow-up-to-line" />
</Button>
<Button
data-testid="scroll-down-button"
className="mr-2 rounded-bl-none rounded-tl-none"
variant="outline"
type="button"
color="neutral"
size="sm"
iconOnly
onClick={() => forcedScroll(true)}
>
<Icon iconName="arrow-down-to-line" />
</Button>
<Button
type="button"
variant="outline"
color="neutral"
size="sm"
className="mr-1"
iconOnly
onClick={() => downloadJSON()}
>
<Icon iconName="cloud-arrow-down" />
</Button>
</div>
</div>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
} from 'qovery-typescript-axios'
import { Fragment, useCallback, useMemo, useState } from 'react'
import { P, match } from 'ts-pattern'
// This import introduces a circular dependency with @qovery/shared/devops-copilot/feature.
// Keep in mind for future refactoring if possible.
// eslint-disable-next-line @nx/enforce-module-boundaries
import { DevopsCopilotTroubleshootTrigger } from '@qovery/shared/devops-copilot/feature'
import { IconEnum } from '@qovery/shared/enums'
import { ENVIRONMENT_LOGS_URL, ENVIRONMENT_STAGES_URL } from '@qovery/shared/routes'
Expand Down Expand Up @@ -494,15 +497,7 @@ export function EnvironmentDeploymentList() {
<Table.Body>
{table.getRowModel().rows.map((row) => (
<Fragment key={row.id}>
<Table.Row
onClick={() => handleRowClick(row)}
onKeyDown={(e) => {
if (e.key === 'Enter') handleRowClick(row)
}}
tabIndex={0}
role="link"
className="h-[68px] divide-x divide-neutral hover:cursor-pointer hover:bg-surface-neutral-subtle focus:bg-surface-neutral-subtle"
>
<Table.Row className="h-[68px] divide-x divide-neutral">
{row.getVisibleCells().map((cell) => (
<Table.Cell
key={cell.id}
Expand Down
Loading