Skip to content

Commit

Permalink
Fix bug 0321 (#647)
Browse files Browse the repository at this point in the history
* fix: report Select suffixIcon is not propagable

* feat: persist collection

* feat: persist collection

* fix: replay case filter

* fix: replay case filter

* fix: collection initial

* fix: await create case inherit from interface

* feat: collection search

* feat: dynamic class tooltip massage

* feat: user avatar

* fix: get root json value (#646)

Co-authored-by: onePone <[email protected]>

---------

Co-authored-by: onePone <[email protected]>
  • Loading branch information
1pone and Xremn authored Mar 26, 2024
1 parent 96c5a43 commit 11cd78b
Show file tree
Hide file tree
Showing 26 changed files with 587 additions and 462 deletions.
35 changes: 29 additions & 6 deletions packages/arex-core/src/components/StructuredFilter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SearchOutlined } from '@ant-design/icons';
import { CloseOutlined, SearchOutlined } from '@ant-design/icons';
import styled from '@emotion/styled';
import { useKeyPress } from 'ahooks';
import { Button, Flex, Select, SelectProps } from 'antd';
import { Button, Flex, Select, SelectProps, Typography } from 'antd';
import { SizeType } from 'antd/es/config-provider/SizeContext';
import { RefSelectProps } from 'antd/es/select';
import { isEqual } from 'lodash';
Expand Down Expand Up @@ -37,9 +37,10 @@ export type StructuredFilterProps = {
prefix?: ReactNode;
labelDataSource?: Label[];
showSearchButton?: boolean | 'simple';
options: StructuredOptionType[];
onSearch?: (value: SearchDataType) => void;
onChange?: (value: SearchDataType) => void;
options: StructuredOptionType[];
onCancel?: () => void;
} & Omit<SelectProps, 'options' | 'onSearch'>;

export type StructuredFilterRef = {
Expand All @@ -52,6 +53,7 @@ const StructuredFilterWrapper = styled.div<{ size: SizeType }>`
flex-grow: 1;
}
.search-content {
padding-left: 8px;
position: relative;
display: flex;
width: 133.33%;
Expand Down Expand Up @@ -171,7 +173,6 @@ const StructuredFilter = forwardRef<StructuredFilterRef, StructuredFilterProps>(
mode='multiple'
size={size}
open={!keyword && open}
suffixIcon={<SearchOutlined />}
tagRender={(tagProps) => (
<StructuredTag
{...tagProps}
Expand Down Expand Up @@ -201,8 +202,30 @@ const StructuredFilter = forwardRef<StructuredFilterRef, StructuredFilterProps>(
/>

{showSearchButton && (
<Button icon={<SearchOutlined />} onClick={handleSearch} style={{ height: '36px' }}>
{showSearchButton !== 'simple' && t('search')}
<Button
type='text'
size={size}
icon={<CloseOutlined />}
onClick={props.onCancel}
style={{ height: '28px', width: '28px' }}
>
{showSearchButton !== 'simple' && (
<Typography.Text style={{ padding: '0 4px' }}>{t('cancel')}</Typography.Text>
)}
</Button>
)}

{showSearchButton && (
<Button
type='text'
size={size}
icon={<SearchOutlined />}
onClick={handleSearch}
style={{ height: '28px', width: '28px' }}
>
{showSearchButton !== 'simple' && (
<Typography.Text style={{ padding: '0 4px' }}>{t('search')}</Typography.Text>
)}
</Button>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ const CollectionNodeTitle: FC<CollectionNodeTitleProps> = (props) => {
}),
{
manual: true,
onSuccess: (res, [{ caseSourceType, nodeType }]) => {
getCollections({ workspaceId: activeWorkspaceId, parentIds: nodePath }).then(() =>
props.onAddNode?.(res.infoId, nodeType),
);
onSuccess: async (res, [{ caseSourceType, nodeType }]) => {
// case inherit interface
if (caseSourceType === CaseSourceType.CASE)
queryInterface({ id: nodePath[nodePath.length - 1] as string }, res.infoId);
await createCaseInheritInterface(nodePath[nodePath.length - 1] as string, res.infoId);

await getCollections({ workspaceId: activeWorkspaceId, parentIds: nodePath });
props.onAddNode?.(res.infoId, nodeType);
},
},
);
Expand Down Expand Up @@ -170,20 +170,23 @@ const CollectionNodeTitle: FC<CollectionNodeTitleProps> = (props) => {
},
);

const { run: saveCase } = useRequest(FileSystemService.saveCase, {
manual: true,
});

const { run: queryInterface } = useRequest(FileSystemService.queryInterface, {
manual: true,
onSuccess: (parentInterface, params) => {
saveCase({
workspaceId: activeWorkspaceId as string,
...parentInterface,
id: params[1],
});
const { runAsync: createCaseInheritInterface } = useRequest(
(id: string, infoId: string) =>
new Promise((resolve, reject) => {
FileSystemService.queryInterface(id).then((res) => {
FileSystemService.saveCase({
workspaceId: activeWorkspaceId as string,
...res,
id: infoId,
})
.then(resolve)
.catch(reject);
});
}),
{
manual: true,
},
});
);

const menu: MenuProps = {
items: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ export type CollectionSearchedListProps = {
const CollectionSearchedList = (props: CollectionSearchedListProps) => {
const { token } = theme.useToken();

const { data, loading } = useRequest(
const {
data,
loading,
run: search,
} = useRequest(
() =>
FileSystemService.searchCollectionItems({
workspaceId: props.workspaceId,
Expand All @@ -40,7 +44,6 @@ const CollectionSearchedList = (props: CollectionSearchedListProps) => {
})),
}),
{
refreshDeps: [props.workspaceId, props.searchValue],
debounceWait: 300,
ready: !!props.searchValue,
},
Expand Down
120 changes: 64 additions & 56 deletions packages/arex/src/components/CollectionSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DownOutlined } from '@ant-design/icons';
import { DownOutlined, SearchOutlined } from '@ant-design/icons';
import {
CategoryKey,
css,
Expand All @@ -7,6 +7,7 @@ import {
Operator,
RequestMethodEnum,
SearchDataType,
SpaceBetweenWrapper,
StructuredFilter,
styled,
useTranslation,
Expand All @@ -17,13 +18,13 @@ import { Button, ConfigProvider, Tag, Tree } from 'antd';
import { TreeProps } from 'antd/es';
import type { DataNode, DirectoryTreeProps } from 'antd/lib/tree';
import { cloneDeep } from 'lodash';
import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { FC, useCallback, useMemo, useRef, useState } from 'react';

import CollectionSearchedList from '@/components/CollectionSelect/CollectionSearchedList';
import { CollectionNodeType, EMAIL_KEY, MenusType, PanesType } from '@/constant';
import { CollectionNodeType, EMAIL_KEY } from '@/constant';
import { FileSystemService, ReportService } from '@/services';
import { CollectionType } from '@/services/FileSystemService';
import { useCollections, useMenusPanes, useWorkspaces } from '@/store';
import { useCollections, useWorkspaces } from '@/store';
import { negate } from '@/utils';

import CollectionNodeTitle, { CollectionNodeTitleProps } from './CollectionNodeTitle';
Expand Down Expand Up @@ -53,11 +54,14 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
const userName = getLocalStorage<string>(EMAIL_KEY) as string;

const { activeWorkspaceId } = useWorkspaces();
const { activePane, setActiveMenu } = useMenusPanes();
const {
loading,
expandedKeys,
loadedKeys,
collectionsTreeData,
collectionsFlatData,
setExpandedKeys,
setLoadedKeys,
getCollections,
getPath,
moveCollectionNode,
Expand All @@ -74,31 +78,15 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {

const [searchValue, setSearchValue] = useState<SearchDataType>();
const [autoExpandParent, setAutoExpandParent] = useState(true);
const [expandedKeys, setExpandedKeys] = useState<string[]>(); // TODO 初始化展开的节点
const [activeKey, setActiveKey] = useState<string>();

const [showSearchInput, setShowSearchInput] = useState(false);

const searching = useMemo(
() => !!searchValue?.keyword || !!searchValue?.structuredValue?.length,
[searchValue],
);

// auto expand by active pane id
useEffect(() => {
if (activePane && activePane.type === PanesType.REQUEST) {
const [workspaceId, nodeTypeStr, id] = activePane.id.split('-');
setActiveMenu(MenusType.COLLECTION);

if (workspaceId !== activeWorkspaceId) {
getCollections({ workspaceId, infoId: id, nodeType: parseInt(nodeTypeStr) }).then(() =>
setExpandedKeys([...getPath(id).map((item) => item.id)]),
);
} else {
const path = getPath(id).map((item) => item.id);
setExpandedKeys((expand) => [...(expand || []), ...path]);
}
}
}, [activePane]);

const { data: labelData = [] } = useRequest(
() => ReportService.queryLabels({ workspaceId: activeWorkspaceId }),
{
Expand All @@ -119,7 +107,7 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {

const dataList: { key: string; title: string; labelIds: string | null }[] = useMemo(
() =>
Array.from(collectionsFlatData).map(([key, value]) => ({
Object.entries(collectionsFlatData).map(([key, value]) => ({
key,
title: value.nodeName,
labelIds: value.labelIds,
Expand Down Expand Up @@ -152,14 +140,15 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
);

const handleSelect: DirectoryTreeProps<CollectionTreeType>['onSelect'] = (keys, info) => {
const infoId = info.node.infoId;
if (expandable?.includes(info.node.nodeType)) {
setExpandedKeys((expandedKeys) => {
return expandedKeys?.includes(info.node.infoId)
? expandedKeys.filter((key) => key !== info.node.infoId)
: [...(expandedKeys || []), info.node.infoId];
});
setExpandedKeys(
expandedKeys?.includes(infoId)
? expandedKeys.filter((key) => key !== infoId)
: [...expandedKeys, infoId],
);
}
setActiveKey(info.node.infoId);
setActiveKey(infoId);
props.onSelect?.(keys, info.node);
};

Expand All @@ -168,10 +157,8 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
let newExpandedKeys;
if (!structuredValue?.length && !keyword) {
// TODO: 以事件驱动滚动,防止滚动到未加载的节点
setTimeout(
() => activeKey && treeRef.current?.scrollTo({ key: activeKey, align: 'top', offset: 64 }),
200,
);
activeKey && treeRef.current?.scrollTo({ key: activeKey, align: 'top', offset: 64 });
activeKey && setExpandedKeys([...expandedKeys, ...getPath(activeKey).map((item) => item.id)]);
} else {
newExpandedKeys = dataList
.map((item) => {
Expand Down Expand Up @@ -199,13 +186,10 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
}
}
}

return keywordFiltered && structuredFiltered
? collectionsFlatData.get(item.key)?.pid
: null;
return keywordFiltered && structuredFiltered ? collectionsFlatData[item.key]?.pid : null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys(newExpandedKeys as string[]);
setExpandedKeys([...expandedKeys, ...(newExpandedKeys as string[])]);
}
setSearchValue(value);
setAutoExpandParent(true);
Expand Down Expand Up @@ -286,29 +270,49 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
return (
<div className='collection-content-wrapper'>
<EmptyWrapper
empty={!loading && !collectionsTreeData.length}
empty={!loading && !collectionsTreeData?.length}
description={
<Button type='primary' onClick={createCollection}>
{t('collection.create_new')}
</Button>
}
>
<StructuredFilter
size='small'
className='collection-header-search'
// @ts-ignore
ref={searchRef}
showSearchButton={false}
prefix={props.menu}
labelDataSource={labelData.map((item) => ({
id: item.id,
name: item.labelName,
color: item.color,
}))}
options={options}
// placeholder={'Search for Name'}
onChange={handleChange}
/>
<div>
{!props.menu || showSearchInput ? (
<StructuredFilter
size='small'
className='collection-header-search'
key='search-input'
// @ts-ignore
ref={searchRef}
showSearchButton={'simple'}
labelDataSource={labelData.map((item) => ({
id: item.id,
name: item.labelName,
color: item.color,
}))}
options={options}
// placeholder={'Search for Name'}
onChange={handleChange}
onCancel={() => {
setSearchValue(undefined);
setShowSearchInput(false);
}}
/>
) : (
<SpaceBetweenWrapper style={{ margin: '3.5px 0' }}>
<div>{props.menu}</div>
<Button
type='text'
size='small'
key='menus'
icon={<SearchOutlined />}
onClick={() => setShowSearchInput(true)}
/>
</SpaceBetweenWrapper>
)}
</div>

<ConfigProvider theme={{ token: { motion: false } }}>
{searching ? (
<CollectionSearchedList
Expand All @@ -334,11 +338,15 @@ const CollectionSelect: FC<CollectionSelectProps> = (props) => {
ref={treeRef}
height={props.height}
selectedKeys={props.selectedKeys}
loadedKeys={loadedKeys}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
switcherIcon={<DownOutlined />}
treeData={collectionsTreeData}
loadData={handleLoadData}
onLoad={(keys) => {
setLoadedKeys([...loadedKeys, ...(keys as string[])]);
}}
fieldNames={{ title: 'nodeName', key: 'infoId', children: 'children' }}
onDrop={onDrop}
onExpand={onExpand}
Expand Down
1 change: 1 addition & 0 deletions packages/arex/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const isMac = window.platform === 'darwin';

export const URL_AREX = 'https://docs.arextest.com';
export const URL_DOCUMENT_GET_STARTED = 'https://docs.arextest.com/docs/category/get-started';
export const URL_DOCUMENT_MOCK_CONFIG = 'https://docs.arextest.com/docs/chapter3/Mock%20Config/';
export const URL_GITHUB_ISSUES = 'https://github.com/arextest/arex/issues';
export const URL_X = 'https://x.com/AREX_Test';
export const URL_SLACK =
Expand Down
Loading

0 comments on commit 11cd78b

Please sign in to comment.