diff --git a/web/features/deployments/detail/deploy-tab.tsx b/web/features/deployments/detail/deploy-tab.tsx index 48b08085d2..c66010e4ef 100644 --- a/web/features/deployments/detail/deploy-tab.tsx +++ b/web/features/deployments/detail/deploy-tab.tsx @@ -12,12 +12,18 @@ import { } from './common' import { DeploymentEnvironmentList } from './deploy-tab/deployment-environment-list' import { - DEPLOYMENT_DETAIL_LIST_GRID_CLASS_NAME, - DETAIL_LIST_CLASS_NAME, - DETAIL_LIST_DESKTOP_ROW_CLASS_NAME, - DETAIL_LIST_HEADER_ROW_CLASS_NAME, - DETAIL_LIST_ROW_CLASS_NAME, -} from './list-styles' + DetailTable, + DetailTableBody, + DetailTableCard, + DetailTableCardList, + DetailTableCell, + DetailTableHead, + DetailTableHeader, + DetailTableRow, +} from './table' +import { + DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES, +} from './table-styles' function NewDeploymentButton({ appInstanceId }: { appInstanceId: string @@ -44,9 +50,9 @@ function DeploymentEnvironmentListSkeleton() { return ( <> -
+ {DEPLOYMENT_TABLE_ROW_SKELETON_KEYS.map(key => ( -
+
@@ -61,39 +67,43 @@ function DeploymentEnvironmentListSkeleton() {
-
+ ))} -
+
-
-
-
{t('deployTab.col.environment')}
-
{t('deployTab.col.status')}
-
{t('deployTab.col.currentRelease')}
-
{t('deployTab.col.actions')}
-
- {DEPLOYMENT_TABLE_ROW_SKELETON_KEYS.map(key => ( -
-
-
+ + + + {t('deployTab.col.environment')} + {t('deployTab.col.status')} + {t('deployTab.col.currentRelease')} + {t('deployTab.col.actions')} + + + + {DEPLOYMENT_TABLE_ROW_SKELETON_KEYS.map(key => ( + + -
-
+ + -
-
+ + -
-
- -
-
-
- ))} -
+ + +
+ +
+
+ + ))} + +
) diff --git a/web/features/deployments/detail/deploy-tab/deployment-environment-list.tsx b/web/features/deployments/detail/deploy-tab/deployment-environment-list.tsx index 061c552232..69c87be237 100644 --- a/web/features/deployments/detail/deploy-tab/deployment-environment-list.tsx +++ b/web/features/deployments/detail/deploy-tab/deployment-environment-list.tsx @@ -19,7 +19,7 @@ import { } from '@langgenius/dify-ui/dropdown-menu' import { useMutation } from '@tanstack/react-query' import { useSetAtom } from 'jotai' -import { useRef, useState } from 'react' +import { Fragment, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { @@ -30,13 +30,19 @@ import { releaseCommit, releaseLabel } from '../../release' import { deploymentStatus, isUndeployedDeploymentRow } from '../../runtime-status' import { openDeployDrawerAtom } from '../../store' import { - DEPLOYMENT_DETAIL_LIST_GRID_CLASS_NAME, - DETAIL_LIST_ACTION_TRIGGER_CLASS_NAME, - DETAIL_LIST_CLASS_NAME, - DETAIL_LIST_DESKTOP_ROW_CLASS_NAME, - DETAIL_LIST_HEADER_ROW_CLASS_NAME, - DETAIL_LIST_ROW_CLASS_NAME, -} from '../list-styles' + DetailTable, + DetailTableBody, + DetailTableCard, + DetailTableCardList, + DetailTableCell, + DetailTableHead, + DetailTableHeader, + DetailTableRow, +} from '../table' +import { + DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES, + DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME, +} from '../table-styles' import { DeploymentStatusSummary } from './deployment-status-summary' function EnvironmentSummary({ environment }: { @@ -131,7 +137,7 @@ function DeploymentRowActions({ appInstanceId, envId, row }: { @@ -236,7 +242,7 @@ function DeploymentEnvironmentMobileRow({ appInstanceId, row }: { const showFailureBanner = status === 'deploy_failed' && Boolean(row.status) return ( -
+
@@ -253,7 +259,7 @@ function DeploymentEnvironmentMobileRow({ appInstanceId, row }: { {row.status}
)} -
+
) } @@ -270,31 +276,34 @@ function DeploymentEnvironmentDesktopRows({ appInstanceId, rows }: { const isLast = index === rows.length - 1 return ( -
-
-
+ + + -
-
+ + -
-
+ + -
-
- -
-
+ + +
+ +
+
+ {showFailureBanner && ( -
- - {row.status} -
+ + +
+ + {row.status} +
+
+
)} -
+ ) })} @@ -309,7 +318,7 @@ export function DeploymentEnvironmentList({ appInstanceId, rows }: { return ( <> -
+ {rows.map(row => ( ))} -
+
-
-
-
{t('deployTab.col.environment')}
-
{t('deployTab.col.status')}
-
{t('deployTab.col.currentRelease')}
-
{t('deployTab.col.actions')}
-
- -
+ + + + {t('deployTab.col.environment')} + {t('deployTab.col.status')} + {t('deployTab.col.currentRelease')} + {t('deployTab.col.actions')} + + + + + +
) diff --git a/web/features/deployments/detail/list-styles.ts b/web/features/deployments/detail/list-styles.ts deleted file mode 100644 index 7a79ef5f93..0000000000 --- a/web/features/deployments/detail/list-styles.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { cn } from '@langgenius/dify-ui/cn' - -export const DETAIL_LIST_CLASS_NAME = 'overflow-hidden rounded-lg border border-divider-subtle bg-background-default' -export const DETAIL_LIST_ROW_CLASS_NAME = 'border-b border-divider-subtle last:border-b-0 hover:bg-background-default-hover' -export const DETAIL_LIST_ACTION_TRIGGER_CLASS_NAME = cn( - 'inline-flex size-8 items-center justify-center rounded-md text-text-tertiary outline-hidden', - 'hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid', - 'data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary', - 'disabled:cursor-not-allowed disabled:opacity-50', -) -export const DETAIL_LIST_HEADER_ROW_CLASS_NAME = 'grid min-h-8 items-center gap-6 border-b border-divider-subtle px-4 py-1.5 system-2xs-medium-uppercase text-text-tertiary' -export const DETAIL_LIST_DESKTOP_ROW_CLASS_NAME = 'grid min-h-12 items-center gap-6 px-4 py-2' -export const DEPLOYMENT_DETAIL_LIST_GRID_CLASS_NAME = 'grid-cols-[minmax(160px,1fr)_minmax(150px,0.75fr)_minmax(180px,1fr)_auto]' -export const RELEASE_DETAIL_LIST_GRID_CLASS_NAME = 'grid-cols-[minmax(150px,1fr)_minmax(130px,0.75fr)_minmax(140px,0.8fr)_minmax(150px,1fr)_auto]' diff --git a/web/features/deployments/detail/settings-tab/access/__tests__/api-keys.spec.tsx b/web/features/deployments/detail/settings-tab/access/__tests__/api-keys.spec.tsx new file mode 100644 index 0000000000..f6797318a4 --- /dev/null +++ b/web/features/deployments/detail/settings-tab/access/__tests__/api-keys.spec.tsx @@ -0,0 +1,106 @@ +import type { DeveloperApiKeyRow } from '@dify/contracts/enterprise/types.gen' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { render, screen } from '@testing-library/react' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { ApiKeyList } from '../api-keys' + +vi.mock('@/service/client', () => ({ + consoleQuery: { + enterprise: { + appDeployAccessService: { + deleteDeveloperApiKey: { + mutationOptions: () => ({ mutationFn: vi.fn() }), + }, + }, + }, + }, +})) + +function apiKey(overrides: Partial = {}): DeveloperApiKeyRow { + return { + id: 'key-1', + name: 'production-key-001', + environment: { id: 'env-1', name: 'production' }, + maskedKey: 'app-****-abcd', + ...overrides, + } +} + +function renderApiKeyList(apiKeys: DeveloperApiKeyRow[]) { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + mutations: { retry: false }, + }, + }) + + return render( + + + , + ) +} + +describe('ApiKeyList', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + // API keys should match the shared semantic table shell used by deployment detail tabs. + describe('Rendering', () => { + it('should render API keys with the shared detail table design', () => { + // Arrange & Act + const { container } = renderApiKeyList([apiKey()]) + + // Assert + const desktopWrapper = container.querySelector('.hidden.pc\\:block') + const tableContainer = desktopWrapper?.querySelector('[data-slot="deployment-detail-table-container"]') + const tableShell = desktopWrapper?.querySelector('[data-slot="deployment-detail-table"]') + const header = tableShell?.querySelector('[data-slot="deployment-detail-table-header"]') + const body = tableShell?.querySelector('[data-slot="deployment-detail-table-body"]') + const row = body?.querySelector('[data-slot="deployment-detail-table-row"]') + const head = header?.querySelector('[data-slot="deployment-detail-table-head"]') + const cell = row?.querySelector('[data-slot="deployment-detail-table-cell"]') + + expect(tableContainer).toHaveClass( + 'overflow-hidden', + 'rounded-lg', + 'border', + 'border-divider-subtle', + 'bg-background-default', + ) + expect(tableShell?.tagName).toBe('TABLE') + expect(header?.tagName).toBe('THEAD') + expect(body?.tagName).toBe('TBODY') + expect(row?.tagName).toBe('TR') + expect(head?.tagName).toBe('TH') + expect(cell?.tagName).toBe('TD') + expect(tableShell).toHaveClass( + 'w-full', + 'table-fixed', + 'border-collapse', + 'caption-bottom', + ) + expect(head).toHaveClass( + 'h-9', + 'px-4', + 'py-2', + 'system-sm-medium-uppercase', + 'text-text-tertiary', + ) + expect(row).toHaveClass( + 'border-b', + 'border-divider-subtle', + 'hover:bg-background-default-hover', + ) + expect(cell).toHaveClass( + 'h-12', + 'min-w-0', + 'px-4', + 'py-2', + ) + expect(row?.querySelector('[data-slot="deployment-detail-table-row-content"]')).toBeNull() + expect(screen.getAllByLabelText('deployments.access.revoke')).toHaveLength(2) + }) + }) +}) diff --git a/web/features/deployments/detail/settings-tab/access/api-keys.tsx b/web/features/deployments/detail/settings-tab/access/api-keys.tsx index c61bb03de5..58543097b4 100644 --- a/web/features/deployments/detail/settings-tab/access/api-keys.tsx +++ b/web/features/deployments/detail/settings-tab/access/api-keys.tsx @@ -13,15 +13,58 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' import { consoleQuery } from '@/service/client' import { environmentName } from '../../../environment' +import { + DetailTable, + DetailTableBody, + DetailTableCard, + DetailTableCardList, + DetailTableCell, + DetailTableHead, + DetailTableHeader, + DetailTableRow, +} from '../../table' +import { + API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES, +} from '../../table-styles' -function ApiKeyRow({ appInstanceId, apiKey }: { +function ApiKeyName({ apiKey }: { + apiKey: DeveloperApiKeyRow +}) { + return ( + + {apiKey.name || apiKey.id || '—'} + + ) +} + +function EnvironmentBadge({ environment }: { + environment: DeveloperApiKeyRow['environment'] +}) { + return ( + + {environmentName(environment)} + + ) +} + +function ApiKeyValue({ value }: { + value: string +}) { + return ( +
+
+ {value} +
+
+ ) +} + +function RevokeApiKeyButton({ appInstanceId, apiKey }: { appInstanceId: string apiKey: DeveloperApiKeyRow }) { const { t } = useTranslation('deployments') const revokeApiKey = useMutation(consoleQuery.enterprise.appDeployAccessService.deleteDeveloperApiKey.mutationOptions()) - const displayValue = apiKey.maskedKey || apiKey.id || '—' - const environmentLabel = environmentName(apiKey.environment) function handleRevoke() { const environmentId = apiKey.environment?.id @@ -38,35 +81,70 @@ function ApiKeyRow({ appInstanceId, apiKey }: { } return ( - - -
- {apiKey.name || apiKey.id} -
- - - - {environmentLabel} - - - -
-
- {displayValue} + + ) +} + +function ApiKeyMobileRow({ appInstanceId, apiKey }: { + appInstanceId: string + apiKey: DeveloperApiKeyRow +}) { + const { t } = useTranslation('deployments') + const displayValue = apiKey.maskedKey || apiKey.id || '—' + + return ( + +
+
+
+ +
+ +
+
- - - - - +
+ + {t('access.api.table.key')} + + +
+
+
+ ) +} + +function ApiKeyDesktopRow({ appInstanceId, apiKey }: { + appInstanceId: string + apiKey: DeveloperApiKeyRow +}) { + const displayValue = apiKey.maskedKey || apiKey.id || '—' + + return ( + + + + + + + + + + + +
+ +
+
+
) } @@ -74,22 +152,14 @@ function ApiKeyTableHeader() { const { t } = useTranslation('deployments') return ( - - - - {t('access.api.table.name')} - - - {t('access.api.table.environment')} - - - {t('access.api.table.key')} - - - {t('access.api.table.action')} - - - + + + {t('access.api.table.name')} + {t('access.api.table.environment')} + {t('access.api.table.key')} + {t('access.api.table.action')} + + ) } @@ -98,20 +168,31 @@ function ApiKeyTable({ appInstanceId, apiKeys }: { apiKeys: DeveloperApiKeyRow[] }) { return ( -
- - - - {apiKeys.map(apiKey => ( - - ))} - -
-
+ <> + + {apiKeys.map((apiKey, index) => ( + + ))} + +
+ + + + {apiKeys.map((apiKey, index) => ( + + ))} + + +
+ ) } diff --git a/web/features/deployments/detail/settings-tab/access/permissions-section.tsx b/web/features/deployments/detail/settings-tab/access/permissions-section.tsx index 7e79fd6e62..5309ba6cb1 100644 --- a/web/features/deployments/detail/settings-tab/access/permissions-section.tsx +++ b/web/features/deployments/detail/settings-tab/access/permissions-section.tsx @@ -5,9 +5,20 @@ import type { } from '@dify/contracts/enterprise/types.gen' import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton' +import { SkeletonRectangle } from '@/app/components/base/skeleton' import { consoleQuery } from '@/service/client' import { Section, SectionState } from '../../common' +import { + DetailTable, + DetailTableBody, + DetailTableCell, + DetailTableHead, + DetailTableHeader, + DetailTableRow, +} from '../../table' +import { + ACCESS_PERMISSION_DETAIL_TABLE_COLUMN_CLASS_NAMES, +} from '../../table-styles' import { EnvironmentPermissionRow } from './permissions' const ACCESS_PERMISSIONS_SKELETON_KEYS = ['production', 'staging', 'development'] @@ -19,19 +30,33 @@ function hasEnvironment(row: EnvironmentAccessRow): row is EnvironmentAccessRow } function AccessPermissionsSkeleton() { + const { t } = useTranslation('deployments') + return ( -
- {ACCESS_PERMISSIONS_SKELETON_KEYS.map(key => ( - - - - - - ))} -
+ + + + {t('access.permissions.col.environment')} + {t('access.permissions.col.permission')} + {t('access.permissions.col.subjects')} + + + + {ACCESS_PERMISSIONS_SKELETON_KEYS.map(key => ( + + + + + + + + + + + + ))} + + ) } @@ -66,16 +91,25 @@ export function AccessPermissionsSection({ ) : ( -
- {permissionRows.map(row => ( - - ))} -
+ + + + {t('access.permissions.col.environment')} + {t('access.permissions.col.permission')} + {t('access.permissions.col.subjects')} + + + + {permissionRows.map(row => ( + + ))} + + )} ) diff --git a/web/features/deployments/detail/settings-tab/access/permissions.tsx b/web/features/deployments/detail/settings-tab/access/permissions.tsx index 68735640d6..e2ee99aefb 100644 --- a/web/features/deployments/detail/settings-tab/access/permissions.tsx +++ b/web/features/deployments/detail/settings-tab/access/permissions.tsx @@ -39,6 +39,10 @@ import { useTranslation } from 'react-i18next' import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton' import { consoleQuery } from '@/service/client' import { environmentName } from '../../../environment' +import { + DetailTableCell, + DetailTableRow, +} from '../../table' type AccessPermissionKind = 'organization' | 'specific' | 'anyone' @@ -412,20 +416,20 @@ export function EnvironmentPermissionRow({ } return ( -
-
-
+ + +
{t('access.permissions.col.environment')}
-
+
-
-
-
+ + +
{t('access.permissions.col.permission')}
-
-
-
+ + +
{t('access.permissions.col.subjects')}
{permissionKind === 'specific' @@ -458,7 +462,7 @@ export function EnvironmentPermissionRow({ {t(`access.permission.${permissionKind}Desc`)}
)} -
-
+
+
) } diff --git a/web/features/deployments/detail/table-styles.ts b/web/features/deployments/detail/table-styles.ts new file mode 100644 index 0000000000..42c16bc708 --- /dev/null +++ b/web/features/deployments/detail/table-styles.ts @@ -0,0 +1,36 @@ +import { cn } from '@langgenius/dify-ui/cn' + +export const DEPLOYMENT_DETAIL_TABLE_COLUMN_CLASS_NAMES = { + actions: 'w-14', + currentRelease: 'w-[34%]', + environment: 'w-[34%]', + status: 'w-[24%]', +} + +export const RELEASE_DETAIL_TABLE_COLUMN_CLASS_NAMES = { + action: 'w-14', + author: 'w-[18%]', + createdAt: 'w-[18%]', + deployedTo: 'w-[28%]', + release: 'w-[28%]', +} + +export const ACCESS_PERMISSION_DETAIL_TABLE_COLUMN_CLASS_NAMES = { + environment: 'w-[22%]', + permission: 'w-[28%]', + subjects: 'w-[50%]', +} + +export const API_KEY_DETAIL_TABLE_COLUMN_CLASS_NAMES = { + action: 'w-16', + environment: 'w-[20%]', + key: 'w-[38%]', + name: 'w-[28%]', +} + +export const DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME = cn( + 'inline-flex size-8 items-center justify-center rounded-md text-text-tertiary outline-hidden', + 'hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid', + 'data-popup-open:bg-state-base-hover data-popup-open:text-text-secondary', + 'disabled:cursor-not-allowed disabled:opacity-50', +) diff --git a/web/features/deployments/detail/table.tsx b/web/features/deployments/detail/table.tsx new file mode 100644 index 0000000000..0da29ec991 --- /dev/null +++ b/web/features/deployments/detail/table.tsx @@ -0,0 +1,91 @@ +import type { ComponentProps } from 'react' +import { cn } from '@langgenius/dify-ui/cn' + +type DetailTableProps = ComponentProps<'table'> & { + containerClassName?: string +} + +export function DetailTable({ className, containerClassName, ...props }: DetailTableProps) { + return ( +
+ + + ) +} + +export function DetailTableHeader({ className, ...props }: ComponentProps<'thead'>) { + return ( + + ) +} + +export function DetailTableBody({ className, ...props }: ComponentProps<'tbody'>) { + return ( + + ) +} + +export function DetailTableRow({ className, ...props }: ComponentProps<'tr'>) { + return ( + + ) +} + +export function DetailTableHead({ className, ...props }: ComponentProps<'th'>) { + return ( +
+ ) +} + +export function DetailTableCell({ className, ...props }: ComponentProps<'td'>) { + return ( + + ) +} + +export function DetailTableCardList({ className, ...props }: ComponentProps<'div'>) { + return ( +
+ ) +} + +export function DetailTableCard({ className, ...props }: ComponentProps<'div'>) { + return ( +
+ ) +} diff --git a/web/features/deployments/detail/versions-tab/__tests__/release-history-table.spec.tsx b/web/features/deployments/detail/versions-tab/__tests__/release-history-table.spec.tsx index 1ec4be03d4..8b547b3b54 100644 --- a/web/features/deployments/detail/versions-tab/__tests__/release-history-table.spec.tsx +++ b/web/features/deployments/detail/versions-tab/__tests__/release-history-table.spec.tsx @@ -100,31 +100,61 @@ describe('ReleaseHistoryTable', () => { }) }) - // The desktop release history should use the same compact table shell as knowledge documents. + // The desktop release history should use the shared semantic deployment detail table. describe('Rendering', () => { - it('should render the desktop release history as a compact document-style table', () => { + it('should render the desktop release history with the shared detail table design', () => { // Arrange & Act const { container } = render() // Assert - const table = screen.getByRole('table') - expect(table).toHaveClass('border-collapse', 'border-0', 'text-sm', 'min-w-[700px]') - expect(container.querySelector('thead')).toHaveClass( - 'h-8', - 'border-b', + const desktopWrapper = container.querySelector('.hidden.pc\\:block') + const tableContainer = desktopWrapper?.querySelector('[data-slot="deployment-detail-table-container"]') + const tableShell = desktopWrapper?.querySelector('[data-slot="deployment-detail-table"]') + const header = tableShell?.querySelector('[data-slot="deployment-detail-table-header"]') + const body = tableShell?.querySelector('[data-slot="deployment-detail-table-body"]') + const row = body?.querySelector('[data-slot="deployment-detail-table-row"]') + const head = header?.querySelector('[data-slot="deployment-detail-table-head"]') + const cell = row?.querySelector('[data-slot="deployment-detail-table-cell"]') + + expect(tableContainer).toHaveClass( + 'overflow-hidden', + 'rounded-lg', + 'border', 'border-divider-subtle', - 'text-xs', - 'leading-8', - 'font-medium', - 'text-text-tertiary', - 'uppercase', + 'bg-background-default', ) - expect(container.querySelector('tbody tr')).toHaveClass( - 'h-8', + expect(tableShell?.tagName).toBe('TABLE') + expect(header?.tagName).toBe('THEAD') + expect(body?.tagName).toBe('TBODY') + expect(row?.tagName).toBe('TR') + expect(head?.tagName).toBe('TH') + expect(cell?.tagName).toBe('TD') + expect(tableShell).toHaveClass( + 'w-full', + 'table-fixed', + 'border-collapse', + 'caption-bottom', + ) + expect(head).toHaveClass( + 'h-9', + 'px-4', + 'py-2', + 'system-sm-medium-uppercase', + 'text-text-tertiary', + ) + expect(row).toHaveClass( 'border-b', 'border-divider-subtle', 'hover:bg-background-default-hover', ) + expect(cell).toHaveClass( + 'h-12', + 'min-w-0', + 'px-4', + 'py-2', + ) + expect(row?.querySelector('[data-slot="deployment-detail-table-row-content"]')).toBeNull() + expect(screen.getAllByText('R-001')).toHaveLength(2) }) }) }) diff --git a/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx b/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx index 5d140d978d..b59d46d2fa 100644 --- a/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx +++ b/web/features/deployments/detail/versions-tab/deploy-release-menu.tsx @@ -17,7 +17,7 @@ import { environmentId, environmentName } from '../../environment' import { releaseDeploymentAction } from '../../release-action' import { deploymentStatus, isUndeployedDeploymentRow } from '../../runtime-status' import { openDeployDrawerAtom } from '../../store' -import { DETAIL_LIST_ACTION_TRIGGER_CLASS_NAME } from '../list-styles' +import { DETAIL_TABLE_ACTION_TRIGGER_CLASS_NAME } from '../table-styles' type EnvironmentOption = AppDeployEnvironment & { id: string @@ -132,7 +132,7 @@ export function DeployReleaseMenu({ appInstanceId, releaseId, releaseRows }: { diff --git a/web/features/deployments/detail/versions-tab/release-history-table.tsx b/web/features/deployments/detail/versions-tab/release-history-table.tsx index 6520c72540..34cf0e422b 100644 --- a/web/features/deployments/detail/versions-tab/release-history-table.tsx +++ b/web/features/deployments/detail/versions-tab/release-history-table.tsx @@ -21,12 +21,18 @@ import { DetailListState, } from '../common' import { - DETAIL_LIST_CLASS_NAME, - DETAIL_LIST_DESKTOP_ROW_CLASS_NAME, - DETAIL_LIST_HEADER_ROW_CLASS_NAME, - DETAIL_LIST_ROW_CLASS_NAME, - RELEASE_DETAIL_LIST_GRID_CLASS_NAME, -} from '../list-styles' + DetailTable, + DetailTableBody, + DetailTableCard, + DetailTableCardList, + DetailTableCell, + DetailTableHead, + DetailTableHeader, + DetailTableRow, +} from '../table' +import { + RELEASE_DETAIL_TABLE_COLUMN_CLASS_NAMES, +} from '../table-styles' import { DeployReleaseMenu } from './deploy-release-menu' import { DeployedToBadge } from './deployed-to-badge' import { getReleaseDeployments } from './release-deployments' @@ -46,9 +52,9 @@ function ReleaseHistoryTableSkeleton() { return ( <> -
+ {RELEASE_TABLE_ROW_SKELETON_KEYS.map(key => ( -
+
@@ -64,40 +70,44 @@ function ReleaseHistoryTableSkeleton() {
-
+
))} -
+
-
-
-
{t('versions.col.release')}
-
{t('versions.col.createdAt')}
-
{t('versions.col.author')}
-
{t('versions.col.deployedTo')}
-
{t('versions.col.action')}
-
- {RELEASE_TABLE_ROW_SKELETON_KEYS.map(key => ( -
-
-
+ + + + {t('versions.col.release')} + {t('versions.col.createdAt')} + {t('versions.col.author')} + {t('versions.col.deployedTo')} + {t('versions.col.action')} + + + + {RELEASE_TABLE_ROW_SKELETON_KEYS.map(key => ( + + -
-
+ + -
-
+ + -
-
+ + -
-
- -
-
-
- ))} -
+ + +
+ +
+
+ + ))} + +
) @@ -113,14 +123,14 @@ function ReleaseHistoryMobileRows({ appInstanceId, releaseRows, deploymentRows, const { t } = useTranslation('deployments') return ( -
+ {releaseRows.map((row) => { const release = row const releaseDeployments = getReleaseDeployments(row, deploymentRows) const hasDeployments = releaseDeployments.length > 0 || deployedToLoading || deployedToHasError return ( -
+
@@ -157,10 +167,10 @@ function ReleaseHistoryMobileRows({ appInstanceId, releaseRows, deploymentRows,
)}
-
+
) })} -
+
) } @@ -243,22 +253,24 @@ function ReleaseHistoryRows({ appInstanceId, releaseRows, deploymentRows, deploy deployedToHasError={deployedToHasError} />
-
-
-
{t('versions.col.release')}
-
{t('versions.col.createdAt')}
-
{t('versions.col.author')}
-
{t('versions.col.deployedTo')}
-
{t('versions.col.action')}
-
- {releaseRows.map((row) => { - const release = row - const releaseDeployments = getReleaseDeployments(row, deploymentRows) + + + + {t('versions.col.release')} + {t('versions.col.createdAt')} + {t('versions.col.author')} + {t('versions.col.deployedTo')} + {t('versions.col.action')} + + + + {releaseRows.map((row) => { + const release = row + const releaseDeployments = getReleaseDeployments(row, deploymentRows) - return ( -
-
-
+ return ( + + -
-
+ + -
-
+ + {row.createdBy?.name ?? '—'} -
-
+ +
-
-
- -
-
-
- ) - })} -
+ + +
+ +
+
+ + ) + })} + +
)