Skip to content

Commit 794a009

Browse files
ZabilsyaZabilsya
andauthored
[DOP-22361] add filter rows transformation (#69)
* [DOP-22361] add filter rows transformation * [DOP-22361] fix after review --------- Co-authored-by: Zabilsya <[email protected]>
1 parent db7b4af commit 794a009

File tree

61 files changed

+666
-95
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+666
-95
lines changed

src/entities/file/ui/FileFormatParams/components/FileCompression/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ export const FileCompression = <T,>({ name, options }: FileCompressionProps<T>)
4242
</div>
4343
<Form.Item className={classes.formItem} name={fieldName}>
4444
<Select
45+
/** className "nodrag" and "nowheel" for select in custom node React Flow https://reactflow.dev/api-reference/react-flow#no-drag-class-name */
4546
className={selectClassNames}
47+
popupClassName="nowheel"
4648
size="large"
4749
options={options}
4850
placeholder="Select compression"

src/entities/file/ui/FileFormatParams/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ export const FileFormatParams = ({ name }: FileFormatParamsProps) => {
1818
<>
1919
<Form.Item label="File format" name={[name, 'file_format', 'type']} rules={[{ required: true }]}>
2020
<Select
21+
/** className "nodrag" and "nowheel" for select in custom node React Flow https://reactflow.dev/api-reference/react-flow#no-drag-class-name */
2122
className="nodrag"
23+
popupClassName="nowheel"
2224
size="large"
2325
options={name === 'source_params' ? SOURCE_FILE_FORMAT_SELECT_OPTIONS : TARGET_FILE_FORMAT_SELECT_OPTIONS}
2426
placeholder="Select file format"

src/entities/transfer/api/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FileFormat, Json } from '@entities/file/@x/transfer';
2+
import { Transformations } from '@entities/transformation/@x/transfer';
23
import { ConnectionType, PaginationRequest } from '@shared/types';
34

45
export interface Transfer {
@@ -30,6 +31,7 @@ export interface Transfer {
3031
strategy_params: TransferStrategyParams;
3132
is_scheduled: boolean;
3233
schedule: string;
34+
transformations: Transformations;
3335
}
3436

3537
export type TransferConnectionParamFieldName = 'source_params' | 'target_params';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** Cross-import entities using public API in FSD https://feature-sliced.design/ru/docs/reference/public-api#public-api-for-cross-imports */
2+
export type { Transformations } from '../types';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './types';
2+
export * from './utils';
3+
export * from './ui';
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export enum TransformationType {
2+
ROWS_FILTER = 'dataframe_rows_filter',
3+
}
4+
5+
export enum TransformationRowsFilterType {
6+
IS_NULL = 'is_null',
7+
IS_NOT_NULL = 'is_not_null',
8+
EQUAL = 'equal',
9+
NOT_EQUAL = 'not_equal',
10+
GREATER_THAN = 'greater_than',
11+
GREATER_OR_EQUAL = 'greater_or_equal',
12+
LESS_THAN = 'less_than',
13+
LESS_OR_EQUAL = 'less_or_equal',
14+
LIKE = 'like',
15+
ILIKE = 'ilike',
16+
NOT_LIKE = 'not_like',
17+
NOT_ILIKE = 'not_ilike',
18+
REGEXP = 'regexp',
19+
}
20+
21+
interface TransformationRowsFilterNullable {
22+
type: Extract<
23+
TransformationRowsFilterType,
24+
TransformationRowsFilterType.IS_NULL | TransformationRowsFilterType.IS_NOT_NULL
25+
>;
26+
field: string;
27+
}
28+
29+
interface TransformationRowsFilterDefault {
30+
type: Exclude<
31+
TransformationRowsFilterType,
32+
TransformationRowsFilterType.IS_NULL | TransformationRowsFilterType.IS_NOT_NULL
33+
>;
34+
field: string;
35+
value: string;
36+
}
37+
38+
export interface TransformationRowsFilter {
39+
type: TransformationType.ROWS_FILTER;
40+
filters: Array<TransformationRowsFilterNullable | TransformationRowsFilterDefault>;
41+
}
42+
43+
export type Transformations = Array<TransformationRowsFilter>;
44+
45+
export interface TransformationsForm {
46+
[TransformationType.ROWS_FILTER]?: TransformationRowsFilter['filters'];
47+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { prepareOptionsForSelect } from '@shared/ui';
2+
3+
import { TransformationRowsFilterType } from '../../../../types';
4+
5+
export const FILTER_ROWS_TYPE_SELECT_OPTIONS = prepareOptionsForSelect({
6+
data: Object.values(TransformationRowsFilterType),
7+
renderLabel: (data) => data.replaceAll('_', ' '),
8+
renderValue: (data) => data,
9+
});
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Button, Form, Input } from 'antd';
2+
import React, { useMemo, useState } from 'react';
3+
import { DeleteOutlined } from '@ant-design/icons';
4+
import { Select } from '@shared/ui';
5+
6+
import { TransformationRowsFilter, TransformationRowsFilterType, TransformationType } from '../../../../types';
7+
import { FilterRowsValue } from '../FilterRowsValue';
8+
9+
import { FilterRowsItemProps } from './types';
10+
import classes from './styles.module.less';
11+
import { FILTER_ROWS_TYPE_SELECT_OPTIONS } from './constants';
12+
13+
export const FilterRowsItem = ({ onRemove, name }: FilterRowsItemProps) => {
14+
const formInstance = Form.useFormInstance();
15+
16+
const initialType = useMemo(() => {
17+
const filterRowsItems: TransformationRowsFilter['filters'][0] | undefined = formInstance.getFieldValue([
18+
'transformations',
19+
TransformationType.ROWS_FILTER,
20+
name,
21+
]);
22+
23+
return filterRowsItems?.type;
24+
}, [formInstance, name]);
25+
26+
/** Use custom type state, because Form.useWatch doesn't support dynamic fieldname like in Form.List */
27+
const [type, setType] = useState(() => initialType);
28+
29+
const handleChangeType = (newType: TransformationRowsFilterType) => {
30+
setType(newType);
31+
};
32+
33+
const handleRemove = () => {
34+
onRemove?.(name);
35+
};
36+
37+
return (
38+
<div className={classes.root}>
39+
<Form.Item className={classes.column} label="Column" name={[name, 'field']} rules={[{ required: true }]}>
40+
<Input className="nodrag" size="large" />
41+
</Form.Item>
42+
<Form.Item className={classes.type} label="Operator" name={[name, 'type']} rules={[{ required: true }]}>
43+
<Select
44+
/** className "nodrag" and "nowheel" for select in custom node React Flow https://reactflow.dev/api-reference/react-flow#no-drag-class-name */
45+
className="nodrag"
46+
popupClassName="nowheel"
47+
size="large"
48+
options={FILTER_ROWS_TYPE_SELECT_OPTIONS}
49+
onChange={handleChangeType}
50+
placeholder="Select type"
51+
/>
52+
</Form.Item>
53+
<FilterRowsValue name={name} type={type} />
54+
{onRemove && (
55+
<Button className="nodrag" type="primary" danger onClick={handleRemove}>
56+
<DeleteOutlined />
57+
</Button>
58+
)}
59+
</div>
60+
);
61+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.root {
2+
display: flex;
3+
align-items: center;
4+
gap: 12px;
5+
6+
.column {
7+
min-width: 300px;
8+
}
9+
10+
.type {
11+
min-width: 180px;
12+
flex-grow: 1;
13+
}
14+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FormListFieldData, FormListOperation } from 'antd';
2+
3+
export interface FilterRowsItemProps extends FormListFieldData {
4+
onRemove?: FormListOperation['remove'];
5+
}

0 commit comments

Comments
 (0)