Skip to content

Commit

Permalink
[DOP-20067] run list and run detail
Browse files Browse the repository at this point in the history
  • Loading branch information
Zabilsya committed Nov 6, 2024
1 parent d5139a2 commit 59e85a1
Show file tree
Hide file tree
Showing 40 changed files with 420 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/app/config/router/instance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AuthProvider } from '@entities/auth';
import { CreateQueuePage, QueueDetailPage, QueueListPage, UpdateQueuePage } from '@pages/queue';
import { ConnectionDetailPage, ConnectionListPage } from '@pages/connection';
import { TransferDetailPage, TransferListPage } from '@pages/transfer';
import { RunDetailPage } from '@pages/run';

import { ErrorBoundary, NotFoundError } from '../errorBoundary';

Expand Down Expand Up @@ -95,6 +96,10 @@ export const router = createBrowserRouter([
path: '/transfers/:id',
element: <TransferDetailPage />,
},
{
path: '/transfers/runs/:id',
element: <RunDetailPage />,
},
],
},
{
Expand Down
1 change: 1 addition & 0 deletions src/entities/run/api/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useGetRun';
13 changes: 13 additions & 0 deletions src/entities/run/api/hooks/useGetRun/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useSuspenseQuery, UseSuspenseQueryResult } from '@tanstack/react-query';

import { GetRunRequest, Run } from '../../types';
import { RunQueryKey } from '../../keys';
import { runService } from '../../runService';

/** Hook for getting run info from backend */
export const useGetRun = ({ id }: GetRunRequest): UseSuspenseQueryResult<Run> => {
return useSuspenseQuery({
queryKey: [RunQueryKey.GET_RUN, id],
queryFn: () => runService.getRun({ id }),
});
};
4 changes: 4 additions & 0 deletions src/entities/run/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './runService';
export * from './types';
export * from './keys';
export * from './hooks';
4 changes: 4 additions & 0 deletions src/entities/run/api/keys/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const RunQueryKey = {
GET_RUNS: 'GET_RUNS',
GET_RUN: 'GET_RUN',
} as const;
14 changes: 14 additions & 0 deletions src/entities/run/api/runService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { axiosInstance } from '@shared/config';
import { PaginationResponse } from '@shared/types';

import { GetRunRequest, Run, GetRunsRequest } from './types';

export const runService = {
getRuns: (params: GetRunsRequest): Promise<PaginationResponse<Run>> => {
return axiosInstance.get('runs', { params });
},

getRun: ({ id }: GetRunRequest): Promise<Run> => {
return axiosInstance.get(`runs/${id}`);
},
};
27 changes: 27 additions & 0 deletions src/entities/run/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PaginationRequest } from '@shared/types';

export interface Run {
id: number;
transfer_id: number;
started_at: string | null;
ended_at: string | null;
status: RunStatus;
log_url: string | null;
}

export enum RunStatus {
CREATED = 'CREATED',
STARTED = 'STARTED',
FAILED = 'FAILED',
SEND_STOP_SIGNAL = 'SEND_STOP_SIGNAL',
STOPPED = 'STOPPED',
FINISHED = 'FINISHED',
}

export interface GetRunsRequest extends PaginationRequest {
transfer_id: number;
}

export interface GetRunRequest {
id: number;
}
2 changes: 2 additions & 0 deletions src/entities/run/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './api';
export * from './ui';
9 changes: 9 additions & 0 deletions src/entities/run/ui/RunStatusBadge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { memo } from 'react';
import { Badge } from 'antd';

import { RunStatusBadgeProps } from './types';
import { getRunStatusColor } from './utils';

export const RunStatusBadge = memo(({ status }: RunStatusBadgeProps) => {
return <Badge count={status} status={getRunStatusColor(status)} />;
});
5 changes: 5 additions & 0 deletions src/entities/run/ui/RunStatusBadge/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RunStatus } from '../../api';

export interface RunStatusBadgeProps {
status: RunStatus;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { RunStatus } from '@entities/run';
import { BadgeProps } from 'antd';

/** Util for getting value of prop "status" for run status badge */
export const getRunStatusColor = (status: RunStatus): BadgeProps['status'] => {
switch (status) {
case RunStatus.CREATED:
case RunStatus.STARTED:
return 'default';
case RunStatus.FAILED:
return 'error';
case RunStatus.SEND_STOP_SIGNAL:
case RunStatus.STOPPED:
return 'warning';
case RunStatus.FINISHED:
return 'success';
}
};
1 change: 1 addition & 0 deletions src/entities/run/ui/RunStatusBadge/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './getRunStatusColor';
1 change: 1 addition & 0 deletions src/entities/run/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './RunStatusBadge';
39 changes: 39 additions & 0 deletions src/features/run/RunDetailInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Descriptions } from 'antd';
import { Link } from 'react-router-dom';
import { RunStatusBadge } from '@entities/run';

import { RunDetailInfoProps } from './types';

export const RunDetailInfo = ({ run, transfer, ...props }: RunDetailInfoProps) => {
return (
<Descriptions title="Run info" bordered {...props}>
<Descriptions.Item label="Id" span={3}>
{run.id}
</Descriptions.Item>
<Descriptions.Item label="Status" span={3}>
<RunStatusBadge status={run.status} />
</Descriptions.Item>
<Descriptions.Item label="Started at" span={3}>
{/* //TODO: [DOP-20067] Rewrite on dayjs when "started_at" field will have not null value */}
{run.started_at || ''}
</Descriptions.Item>
<Descriptions.Item label="Ended at" span={3}>
{/* //TODO: [DOP-20067] Rewrite on dayjs when "started_at" field will have not null value */}
{run.ended_at || ''}
</Descriptions.Item>
<Descriptions.Item label="Log URL" span={3}>
{run.log_url ? (
<a href={run.log_url} target="_blank" rel="noreferrer">
{run.log_url}
</a>
) : (
''
)}
</Descriptions.Item>
<Descriptions.Item label="Transfer" span={3}>
<Link to={`/transfers/${transfer.id}`}>{transfer.name}</Link>
</Descriptions.Item>
</Descriptions>
);
};
8 changes: 8 additions & 0 deletions src/features/run/RunDetailInfo/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Run } from '@entities/run';
import { Transfer } from '@entities/transfer';
import { DescriptionsProps } from 'antd';

export interface RunDetailInfoProps extends DescriptionsProps {
run: Run;
transfer: Transfer;
}
49 changes: 49 additions & 0 deletions src/features/run/RunList/constants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import { PaginationResponse } from '@shared/types';
import { TableColumns } from '@shared/ui';
import { Run, RunStatusBadge } from '@entities/run';
import { Typography } from 'antd';
import { Link } from 'react-router-dom';

const { Text } = Typography;

export const RUN_LIST_COLUMNS: TableColumns<PaginationResponse<Run>> = [
{
title: 'Id',
dataIndex: 'id',
render: (id, record) => <Link to={`/transfers/runs/${record.id}`}>{id}</Link>,
width: 150,
},
{
title: 'Status',
dataIndex: 'status',
render: (value, record) => <RunStatusBadge status={record.status} />,
width: 150,
},
{
title: 'Started at',
dataIndex: 'started_at',
//TODO: [DOP-20067] Rewrite on dayjs when "started_at" field will have not null value
width: 150,
},
{
title: 'Ended at',
dataIndex: 'ended_at',
//TODO: [DOP-20067] Rewrite on dayjs when "ended_at" field will have not null value
width: 150,
},
{
title: 'Log url',
dataIndex: 'log_url',
render: (value, record) =>
record.log_url ? (
<Text ellipsis>
<a href={record.log_url} target="_blank" rel="noreferrer">
{record.log_url}
</a>
</Text>
) : (
''
),
},
];
23 changes: 23 additions & 0 deletions src/features/run/RunList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { ManagedTable } from '@shared/ui';
import { PaginationRequest } from '@shared/types';
import { RunQueryKey, runService } from '@entities/run';

import { RUN_LIST_COLUMNS } from './constants';
import { RunListProps } from './types';

export const RunList = ({ transferId }: RunListProps) => {
const handleGetRuns = (params: PaginationRequest) => {
return runService.getRuns({ ...params, transfer_id: transferId });
};

return (
<ManagedTable
queryKey={[RunQueryKey.GET_RUNS, transferId]}
queryFunction={handleGetRuns}
columns={RUN_LIST_COLUMNS}
isHiddenRowActions
rowKey="id"
/>
);
};
3 changes: 3 additions & 0 deletions src/features/run/RunList/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface RunListProps {
transferId: number;
}
2 changes: 2 additions & 0 deletions src/features/run/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './RunList';
export * from './RunDetailInfo';
2 changes: 1 addition & 1 deletion src/features/transfer/TransferDetailInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const TransferDetailInfo = ({
<Descriptions.Item label="Target connection" span={3}>
<Link to={`/connections/${connectionTarget.id}`}>{connectionTarget.name}</Link>
</Descriptions.Item>
<Descriptions.Item label="Group" span={3}>
<Descriptions.Item label="Queue" span={3}>
<Link to={`/queues/${queue.id}`}>{queue.name}</Link>
</Descriptions.Item>
<Descriptions.Item className={classes.subDescription} label="Source params" span={3}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/connection/ConnectionDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const ConnectionDetailPage = () => {

return (
<PageContentWrapper>
<Title>{connection.name}</Title>
<Title>Connection: {connection.name}</Title>
<ConnectionDetail connection={connection} group={group} />
</PageContentWrapper>
);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/group/GroupDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const GroupDetailPage = () => {
return (
<div className={classes.root}>
<PageContentWrapper>
<Title>{group.data.name}</Title>
<Title>Group: {group.data.name}</Title>
<GroupDetailInfo
group={group.data}
owner={owner}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/queue/QueueDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const QueueDetailPage = () => {

return (
<PageContentWrapper>
<Title>{queue.name}</Title>
<Title>Queue: {queue.name}</Title>
<QueueDetail queue={queue} group={group} />
</PageContentWrapper>
);
Expand Down
51 changes: 51 additions & 0 deletions src/pages/run/RunDetailPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { PageDetailParams } from '@shared/types';
import { PageContentWrapper } from '@shared/ui';
import { Typography } from 'antd';
import { useParams } from 'react-router-dom';
import { useGetGroup } from '@entities/group';
import { useGetRun } from '@entities/run';
import { useGetQueue } from '@entities/queue';
import { TransferDetailInfo } from '@features/transfer';
import { ConnectionDetailInfo } from '@features/connection';
import { useGetConnection } from '@entities/connection';
import { useGetTransfer } from '@entities/transfer';
import { RunDetailInfo } from '@features/run';

import classes from './styles.module.less';

const { Title } = Typography;

export const RunDetailPage = () => {
const params = useParams<PageDetailParams>();
const { data: run } = useGetRun({ id: Number(params.id) });
const { data: transfer } = useGetTransfer({ id: run.transfer_id });
const { data: group } = useGetGroup({ id: transfer.group_id });
const { data: connectionSource } = useGetConnection({ id: transfer.source_connection_id });
const { data: connectionTarget } = useGetConnection({ id: transfer.target_connection_id });
const { data: queue } = useGetQueue({ id: transfer.queue_id });

if (!run || !transfer || !group || !connectionSource || !connectionTarget || !queue) {
return null;
}

return (
<div className={classes.root}>
<PageContentWrapper>
<Title>Run: #{run.id}</Title>
<div className={classes.extra}>
<RunDetailInfo run={run} transfer={transfer} />
<TransferDetailInfo
transfer={transfer}
group={group.data}
connectionSource={connectionSource}
connectionTarget={connectionTarget}
queue={queue}
/>
<ConnectionDetailInfo title="Source connection info" group={group.data} connection={connectionSource} />
<ConnectionDetailInfo title="Target connection info" group={group.data} connection={connectionTarget} />
</div>
</PageContentWrapper>
</div>
);
};
11 changes: 11 additions & 0 deletions src/pages/run/RunDetailPage/styles.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.root {
display: flex;
flex-direction: column;
gap: 60px;

.extra {
display: flex;
flex-direction: column;
gap: 32px;
}
}
1 change: 1 addition & 0 deletions src/pages/run/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './RunDetailPage';
Loading

0 comments on commit 59e85a1

Please sign in to comment.