Skip to content

Commit

Permalink
Feat replay ux (#517)
Browse files Browse the repository at this point in the history
* feat: replayCase/replayDetail Breadcrumb

* feat: diffSences Breadcrumb

* feat: agentStatus Badge

---------

Co-authored-by: onePone <[email protected]>
  • Loading branch information
1pone and Xremn authored Nov 1, 2023
1 parent c481165 commit 45fe64e
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 215 deletions.
2 changes: 1 addition & 1 deletion packages/arex-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@arextest/arex-core",
"version": "0.2.7",
"version": "0.2.8",
"homepage": "https://github.com/arextest/arex",
"main": "dist/arex-core.js",
"module": "dist/arex-core.js",
Expand Down
5 changes: 4 additions & 1 deletion packages/arex-core/src/components/HighlightRowTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type HighlightRowTableProps<T> = {
defaultCurrent?: number; // should be defined at the same time as defaultRow
defaultRow?: number; // should be defined at the same time as defaultCurrent
defaultSelectFirst?: boolean;
restHighlight?: boolean; // reset highlight when click the same row
onRowClick?: (record: T, index?: number) => void;
} & TableProps<T>;

Expand All @@ -31,6 +32,7 @@ function HighlightRowTable<T extends object>(props: HighlightRowTableProps<T>) {
defaultSelectFirst,
defaultRow = 0,
defaultCurrent = 1,
restHighlight = true,
onRowClick,
onChange,
...restProps
Expand Down Expand Up @@ -58,7 +60,8 @@ function HighlightRowTable<T extends object>(props: HighlightRowTableProps<T>) {
onClick: () => {
setSelectRow(
((props.pagination as TablePaginationConfig)?.current || page) === selectRow.page &&
index === selectRow.row
index === selectRow.row &&
restHighlight
? invalidSelectRow
: {
row: index,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DeleteOutlined } from '@ant-design/icons';
import { HelpTooltip, useTranslation } from '@arextest/arex-core';
import { css } from '@emotion/react';
import { useRequest } from 'ahooks';
import { Popconfirm, Table, Typography } from 'antd';
import { Badge, Button, Popconfirm, Table, Typography } from 'antd';
import { ColumnsType } from 'antd/es/table';
import dayjs from 'dayjs';
import React, { FC } from 'react';
Expand All @@ -14,6 +14,38 @@ export interface RunningStatusProps {
appId: string;
}

const AgentStatusMap: {
[status: string]: {
code: number;
badgeStatus: 'default' | 'success' | 'warning' | 'processing' | 'error' | undefined;
};
} = {
NONE: {
code: 0, // NONE
badgeStatus: 'default',
},
START: {
code: 1, // Arex first load the config
badgeStatus: 'success',
},
UN_START: {
code: 2, // AREX just to load the config
badgeStatus: 'warning',
},
WORKING: {
code: 3, // AREX is up and recording
badgeStatus: 'processing',
},
SLEEPING: {
code: 4, // AREX is up, but not recording maybe rate=0 or allowDayOfWeeks is not match
badgeStatus: 'error',
},
SHUTDOWN: {
code: 5, // AREX is shutdown, need to restart
badgeStatus: 'default',
},
};

const RunningStatus: FC<RunningStatusProps> = (props) => {
const { t } = useTranslation(['components', 'common']);

Expand Down Expand Up @@ -46,7 +78,15 @@ const RunningStatus: FC<RunningStatusProps> = (props) => {
),
dataIndex: 'agentStatus',
align: 'center',
render: (text) => <Typography.Text>{text || '-'}</Typography.Text>,
render: (status: string) => (
<Typography.Text>
<Badge
status={AgentStatusMap[status]?.badgeStatus || 'default'}
style={{ marginRight: '8px' }}
/>
{status || '-'}
</Typography.Text>
),
},
{
title: t('replay.action', { ns: 'components' }),
Expand All @@ -57,19 +97,12 @@ const RunningStatus: FC<RunningStatusProps> = (props) => {
onConfirm={() => {
confirm(record);
}}
okText='Yes'
cancelText='No'
okText={t('yes', { ns: 'common' })}
cancelText={t('no', { ns: 'common' })}
>
<a
css={css`
color: red;
&:hover {
color: red;
}
`}
>
<Button danger type='link' size='small' icon={<DeleteOutlined />}>
{t('replay.delete', { ns: 'components' })}
</a>
</Button>
</Popconfirm>
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,19 @@ const SerializeSkip: FC<FormItemProps<SerializeSkipInfo[]>> = (props) => {
align: 'center',
width: '15%',
render: (value, record, index) => (
<Space>
<SmallTextButton
danger
icon={<DeleteOutlined />}
onClick={() =>
setDataSource((state) => {
state.splice(index, 1);
})
}
/>
</Space>
<Button
danger
type='link'
size='small'
icon={<DeleteOutlined />}
onClick={() =>
setDataSource((state) => {
state.splice(index, 1);
})
}
>
{t('replay.delete', { ns: 'components' })}
</Button>
),
},
],
Expand Down
4 changes: 3 additions & 1 deletion packages/arex/src/panes/Replay/PlanItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Icon, {
import { ReplayLogsDrawer } from '@arextest/arex-common';
import {
getLocalStorage,
HighlightRowTable,
i18n,
I18nextLng,
SpaceBetweenWrapper,
Expand Down Expand Up @@ -601,9 +602,10 @@ const PlanItem: FC<ReplayPlanItemProps> = (props) => {

<br />

<Table
<HighlightRowTable
size='small'
rowKey='planItemId'
restHighlight={false}
loading={loadingData}
columns={columns}
dataSource={planItemDataFiltered}
Expand Down
8 changes: 7 additions & 1 deletion packages/arex/src/panes/ReplayCase/Case.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { generateId } from '@/utils';

export type CaseProps = {
planItemId: string;
operationName: string | null;
planId: string;
filter?: Key;
onClick?: (record: ReplayCaseType) => void;
Expand Down Expand Up @@ -76,7 +77,12 @@ const Case: FC<CaseProps> = (props) => {
navPane({
type: PanesType.CASE_DETAIL,
id: record.recordId,
data: { ...record, appId: data?.appId },
data: {
...record,
appId: data?.appId,
planItemId: props.planItemId,
operationName: props.operationName,
},
});
}}
>
Expand Down
45 changes: 27 additions & 18 deletions packages/arex/src/panes/ReplayCase/ReplayCase.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HomeOutlined, SettingOutlined } from '@ant-design/icons';
import { SettingOutlined } from '@ant-design/icons';
import { DiffPath } from '@arextest/arex-common';
import {
ArexPaneFC,
Expand All @@ -20,7 +20,7 @@ import {
useTranslation,
} from '@arextest/arex-core';
import { useRequest } from 'ahooks';
import { App, Button, Modal } from 'antd';
import { App, Breadcrumb, Modal } from 'antd';
import dayjs from 'dayjs';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

Expand All @@ -38,7 +38,7 @@ import SaveCase, { SaveCaseRef } from './SaveCase';

const ReplayCasePage: ArexPaneFC<PlanItemStatistics & { filter: number }> = (props) => {
const { message, notification } = App.useApp();
const { activePane } = useMenusPanes();
const { activePane, removePane } = useMenusPanes();
const email = getLocalStorage<string>(EMAIL_KEY);
const { t } = useTranslation(['components']);
const navPane = useNavPane();
Expand Down Expand Up @@ -206,37 +206,46 @@ const ReplayCasePage: ArexPaneFC<PlanItemStatistics & { filter: number }> = (pro
[t],
);

if (!props.data) {
removePane(undefined);
return null;
}

return (
<>
<Breadcrumb
separator='>'
items={[
{
key: props.data.appId,
title: <a>{props.data.appId}</a>,
onClick: () =>
navPane({
type: PanesType.REPLAY,
id: props.data.appId,
}),
},
{
key: props.data.planItemId,
title: props.data.operationName || 'unknown',
},
]}
/>
<PanesTitle
title={
<span>
<Label style={{ font: 'inherit' }}>{t('replay.caseServiceAPI')}</Label>
{decodeURIComponent(props.data.operationName || 'unknown')}
</span>
}
extra={
<Button
id='arex-replay-case-replay-report-btn'
size='small'
icon={<HomeOutlined />}
onClick={() =>
navPane({
type: PanesType.REPLAY,
id: props.data.appId,
})
}
>
{t('replay.replayReport')}
</Button>
}
/>

<CollapseTable
active={!!selectedRecord}
table={
<Case
planId={props.data.planId}
operationName={props.data.operationName}
planItemId={props.data.planItemId}
filter={props.data.filter}
onClick={handleClickRecord}
Expand Down
50 changes: 32 additions & 18 deletions packages/arex/src/panes/ReplayCaseDetail/ReplayCaseDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { HomeOutlined } from '@ant-design/icons';
import {
ArexPaneFC,
clearLocalStorage,
Expand All @@ -7,7 +6,7 @@ import {
useTranslation,
} from '@arextest/arex-core';
import { useRequest } from 'ahooks';
import { Badge, Button, Tabs, theme } from 'antd';
import { Badge, Breadcrumb, Spin, Tabs, theme } from 'antd';
import React, { ReactNode, useEffect, useState } from 'react';

import { APP_ID_KEY, PanesType } from '@/constant';
Expand All @@ -20,7 +19,9 @@ import CaseDetailTab from './CaseDetailTab';

type TagType = { label: ReactNode; key: string; children: ReactNode };

const ReplayCaseDetail: ArexPaneFC<ReplayCaseType & { appId: string }> = (props) => {
const ReplayCaseDetail: ArexPaneFC<
ReplayCaseType & { appId: string; planItemId: string; operationName: string | null }
> = (props) => {
const { token } = theme.useToken();
const { t } = useTranslation(['components']);
const { activePane } = useMenusPanes();
Expand All @@ -33,7 +34,7 @@ const ReplayCaseDetail: ArexPaneFC<ReplayCaseType & { appId: string }> = (props)
return () => clearLocalStorage(APP_ID_KEY);
}, [activePane?.id]);

useRequest(ReportService.viewRecord, {
const { loading } = useRequest(ReportService.viewRecord, {
defaultParams: [
{
recordId: props.data.recordId,
Expand Down Expand Up @@ -75,24 +76,37 @@ const ReplayCaseDetail: ArexPaneFC<ReplayCaseType & { appId: string }> = (props)

return (
<>
<PanesTitle
title={`RecordId: ${props.data.recordId}`}
extra={
<Button
size='small'
icon={<HomeOutlined />}
onClick={() =>
<Breadcrumb
separator='>'
items={[
{
key: props.data.appId,
title: <a>{props.data.appId}</a>,
onClick: () =>
navPane({
type: PanesType.REPLAY,
id: props.data.appId,
})
}
>
{t('replay.replayReport')}
</Button>
}
}),
},
{
key: props.data.planItemId,
title: <a>{props.data.operationName || 'unknown'}</a>,
onClick: () =>
navPane({
type: PanesType.REPLAY_CASE,
id: props.data.planItemId,
}),
},
{
key: props.data.recordId,
title: props.data.recordId,
},
]}
/>
<Tabs items={tabItems} />
<PanesTitle title={`RecordId: ${props.data.recordId}`} />
<Spin spinning={loading}>
<Tabs items={tabItems} />
</Spin>
</>
);
};
Expand Down
Loading

0 comments on commit 45fe64e

Please sign in to comment.