Skip to content

Commit

Permalink
[DOP-20067] run list and run detail (#41)
Browse files Browse the repository at this point in the history
* [DOP-20067] run list and run detail

* [DOP-20067] move RunStatus enum from types to constants

---------

Co-authored-by: Zabilsya <[email protected]>
  • Loading branch information
Zabilsya and Zabilsya authored Nov 8, 2024
1 parent d5139a2 commit ce5a4c3
Show file tree
Hide file tree
Showing 44 changed files with 439 additions and 24 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
5 changes: 3 additions & 2 deletions src/entities/group/api/groupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GetGroupsRequest,
GetGroupUsersRequest,
Group,
GroupData,
GroupUser,
UpdateGroupRequest,
UpdateGroupUserRequest,
Expand All @@ -23,11 +24,11 @@ export const groupService = {
return axiosInstance.get(`groups/${id}`);
},

createGroup: (data: CreateGroupRequest): Promise<Group> => {
createGroup: (data: CreateGroupRequest): Promise<GroupData> => {
return axiosInstance.post(`groups`, data);
},

updateGroup: ({ id, ...data }: UpdateGroupRequest): Promise<Group> => {
updateGroup: ({ id, ...data }: UpdateGroupRequest): Promise<GroupData> => {
return axiosInstance.patch(`groups/${id}`, data);
},

Expand Down
8 changes: 8 additions & 0 deletions src/entities/run/api/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum RunStatus {
CREATED = 'CREATED',
STARTED = 'STARTED',
FAILED = 'FAILED',
SEND_STOP_SIGNAL = 'SEND STOP SIGNAL',
STOPPED = 'STOPPED',
FINISHED = 'FINISHED',
}
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 }),
});
};
5 changes: 5 additions & 0 deletions src/entities/run/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './runService';
export * from './types';
export * from './keys';
export * from './hooks';
export * from './constants';
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}`);
},
};
20 changes: 20 additions & 0 deletions src/entities/run/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PaginationRequest } from '@shared/types';

import { RunStatus } from './constants';

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

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';
11 changes: 11 additions & 0 deletions src/entities/run/ui/RunStatusBadge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { memo } from 'react';
import { Badge } from 'antd';
import { RunStatus } from '@entities/run';

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

export const RunStatusBadge = memo(({ status }: RunStatusBadgeProps) => {
const statusText = RunStatus[status];
return <Badge count={statusText} status={getRunStatusColor(statusText)} />;
});
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: keyof typeof 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';
6 changes: 3 additions & 3 deletions src/features/group/CreateGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react';
import { ControlButtons, ManagedForm } from '@shared/ui';
import { Group, GroupQueryKey, groupService } from '@entities/group';
import { GroupData, GroupQueryKey, groupService } from '@entities/group';
import { Form, Input } from 'antd';
import { useNavigate } from 'react-router-dom';

export const CreateGroup = () => {
const navigate = useNavigate();

const onSuccess = (response: Group) => {
navigate(`/groups/${response.data.id}`);
const onSuccess = (response: GroupData) => {
navigate(`/groups/${response.id}`);
};

const onCancel = () => {
Expand Down
8 changes: 4 additions & 4 deletions src/features/group/UpdateGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { ControlButtons, ManagedForm, ManagedSelect } from '@shared/ui';
import { Group, GroupQueryKey, groupService } from '@entities/group';
import { GroupData, GroupQueryKey, groupService } from '@entities/group';
import { Form, Input } from 'antd';
import { useNavigate } from 'react-router-dom';
import { UserQueryKey, userService } from '@entities/user';
Expand All @@ -15,16 +15,16 @@ export const UpdateGroup = ({ group }: UpdateGroupProps) => {
return groupService.updateGroup({ ...values, id: group.id });
};

const onSuccess = (response: Group) => {
navigate(`/groups/${response.data.id}`);
const onSuccess = (response: GroupData) => {
navigate(`/groups/${response.id}`);
};

const onCancel = () => {
navigate('/groups');
};

return (
<ManagedForm<UpdateGroupForm, Group>
<ManagedForm<UpdateGroupForm, GroupData>
mutationFunction={handleUpdateGroup}
initialValues={getUpdateGroupInitialValues(group)}
onSuccess={onSuccess}
Expand Down
44 changes: 44 additions & 0 deletions src/features/run/RunDetailInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { Descriptions } from 'antd';
import { Link } from 'react-router-dom';
import { RunStatusBadge } from '@entities/run';
import { Typography } from 'antd';

const { Text } = Typography;

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 "ended_at" field will have not null value */}
{run.ended_at || ''}
</Descriptions.Item>
<Descriptions.Item label="Log url" span={3}>
{run.log_url ? (
<Text>
<a href={run.log_url} target="_blank" rel="noreferrer">
{run.log_url}
</a>
</Text>
) : (
''
)}
</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>
<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
Loading

0 comments on commit ce5a4c3

Please sign in to comment.