Skip to content

Commit

Permalink
feat(filterrules): add FilterRules (#407)
Browse files Browse the repository at this point in the history
* feat(filterrules): add FilterRules

* feat(filterrules): update some example

* feat(filterrules): add some example and props type and use weakMap to save height/lineheight

* feat(filterrules): update ts and add comment

* feat(filterrules): update FilterRules props and formitem name

* feat(filterrules): add comment and unit test

* feat(filterrrules): update contants file and style

* test(filterrules): update test unit
  • Loading branch information
LuckyFBB committed Nov 14, 2023
1 parent a18112a commit d7f296c
Show file tree
Hide file tree
Showing 13 changed files with 1,161 additions and 34 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"@types/jest": "^29.2.3",
"@types/lodash": "^4.14.191",
"@types/react": "^18.0.0",
"@types/shortid": "^0.0.31",
"@types/showdown": "^1.9.0",
"@types/testing-library__jest-dom": "^5.14.5",
"@umijs/lint": "^4.0.0",
Expand Down Expand Up @@ -123,6 +124,7 @@
"mxgraph": "^4.2.2",
"rc-drawer": "~5.1.0",
"rc-virtual-list": "^3.4.13",
"shortid": "^2.2.16",
"showdown": "^1.9.0",
"standard-version": "^9.5.0",
"use-clippy": "^1.0.9"
Expand Down
195 changes: 161 additions & 34 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

198 changes: 198 additions & 0 deletions src/filterRules/__tests__/__snapshots__/filterRules.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`FilterRules should support FilterRules success render 1`] = `
{
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="ruleController"
>
<div
class="ruleController__item"
>
<div
class="ruleController__item--component"
>
<input
class="ant-input"
type="text"
value=""
/>
</div>
<div
class="ruleController__item--operation"
>
<span
aria-label="plus-circle"
class="anticon anticon-plus-circle icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
data-icon="plus-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
/>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
/>
</svg>
</span>
<span
aria-label="minus-circle"
class="anticon anticon-minus-circle icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
data-icon="minus-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M696 480H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
/>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
class="ruleController"
>
<div
class="ruleController__item"
>
<div
class="ruleController__item--component"
>
<input
class="ant-input"
type="text"
value=""
/>
</div>
<div
class="ruleController__item--operation"
>
<span
aria-label="plus-circle"
class="anticon anticon-plus-circle icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
data-icon="plus-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
/>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
/>
</svg>
</span>
<span
aria-label="minus-circle"
class="anticon anticon-minus-circle icon"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
data-icon="minus-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M696 480H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
/>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
/>
</svg>
</span>
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
67 changes: 67 additions & 0 deletions src/filterRules/__tests__/filterRules.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { Input } from 'antd';
import '@testing-library/jest-dom/extend-expect';

import { INIT_DATA, INIT_ROW_VALUES, IRow } from '../demos/constants';
import FilterRules, { IComponentProps } from '..';

const MyInput = ({ rowValues: { input }, rowKey, onChange }: IComponentProps<IRow>) => (
<Input value={input} onChange={(e) => onChange?.(rowKey, { input: e.target.value })} />
);

describe('FilterRules', () => {
test('should support FilterRules success render', () => {
const wrapper = render(
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
value={INIT_DATA}
initValues={INIT_ROW_VALUES}
/>
);
expect(wrapper).toMatchSnapshot();
});

test('calls onChange on add condition button click', () => {
const handleChange = jest.fn();
const { container } = render(
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
value={INIT_DATA}
onChange={handleChange}
initValues={INIT_ROW_VALUES}
/>
);
fireEvent.click(container.querySelector('.anticon-plus-circle') as Element);
expect(handleChange).toHaveBeenCalled();
});

test('calls onChange on delete condition button click when notEmpty is false', () => {
const handleChange = jest.fn();
const { container } = render(
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
value={INIT_DATA}
onChange={handleChange}
initValues={INIT_ROW_VALUES}
notEmpty={{ data: false }}
/>
);
fireEvent.click(container.querySelector('.anticon-minus-circle') as Element);
expect(handleChange).toHaveBeenCalled();
});

test('not calls onChange on delete condition button click when notEmpty is true', () => {
const handleChange = jest.fn();
const { container } = render(
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
value={INIT_DATA}
onChange={handleChange}
initValues={INIT_ROW_VALUES}
/>
);
fireEvent.click(container.querySelector('.anticon-minus-circle') as Element);
expect(handleChange).not.toHaveBeenCalled();
});
});
27 changes: 27 additions & 0 deletions src/filterRules/demos/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useState } from 'react';
import { Button, Input } from 'antd';
import { FilterRules } from 'dt-react-component';
import { IComponentProps } from 'dt-react-component/filterRules';

import { INIT_DATA, INIT_ROW_VALUES, IRow } from './constants';

const MyInput = ({ rowValues: { input }, rowKey, onChange }: IComponentProps<IRow>) => (
<Input value={input} onChange={(e) => onChange?.(rowKey, { input: e.target.value })} />
);

export default () => {
const [data, setData] = useState(INIT_DATA);

return (
<>
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
value={data}
onChange={(value: any) => setData(value)}
initValues={INIT_ROW_VALUES}
/>

<Button onClick={() => console.log(data)}>控制台查看数据</Button>
</>
);
};
38 changes: 38 additions & 0 deletions src/filterRules/demos/basicCheck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useEffect, useState } from 'react';
import { Button, Form, Input } from 'antd';
import { FilterRules } from 'dt-react-component';
import { IComponentProps } from 'dt-react-component/filterRules';

import { INIT_DATA, INIT_ROW_VALUES, IRow } from './constants';

const MyInput = ({ rowValues: { input }, rowKey, disabled, onChange }: IComponentProps<IRow>) => (
<Input
value={input}
onChange={(e) => onChange?.(rowKey, { input: e.target.value })}
disabled={disabled}
/>
);

export default () => {
const [form] = Form.useForm();
const [disabled, useDisabled] = useState(false);

useEffect(() => {
form.setFieldsValue({ condition: INIT_DATA });
}, []);

return (
<Form form={form}>
<Button style={{ marginBottom: 16 }} onClick={() => useDisabled(!disabled)}>
{disabled ? '编辑' : '查看'}状态
</Button>
<Form.Item name="condition">
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
disabled={disabled}
initValues={INIT_ROW_VALUES}
/>
</Form.Item>
</Form>
);
};
37 changes: 37 additions & 0 deletions src/filterRules/demos/basicUnController.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { Button, Form, Input } from 'antd';
import { FilterRules } from 'dt-react-component';
import { IComponentProps } from 'dt-react-component/filterRules';

import { INIT_DATA, INIT_ROW_VALUES, IRow } from './constants';

const MyInput = ({ name }: IComponentProps<IRow>) => (
<Form.Item name={['condition', ...name, 'input']}>
<Input />
</Form.Item>
);

export default () => {
const [form] = Form.useForm();

return (
<Form form={form}>
<Button
onClick={() => form.setFieldsValue({ condition: INIT_DATA })}
style={{ marginBottom: 16 }}
>
添加数据
</Button>
<Form.Item name="condition">
<FilterRules<IRow>
component={(props) => <MyInput {...props} />}
notEmpty={{ data: false }}
initValues={INIT_ROW_VALUES}
/>
</Form.Item>
<Button onClick={async () => console.log(await form.validateFields())}>
控制台查看数据
</Button>
</Form>
);
};

0 comments on commit d7f296c

Please sign in to comment.