Skip to content

Commit db7b4af

Browse files
ZabilsyaZabilsya
andauthored
[DOP-21929] add file format settings (#68)
* [DOP-21929] add file format settings * [DOP-21929] add comments about useWatch --------- Co-authored-by: Zabilsya <[email protected]>
1 parent b728846 commit db7b4af

File tree

61 files changed

+605
-158
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

+605
-158
lines changed

src/entities/file/@x/transfer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
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 { FileFormat, Json } from '../types';
3+
export { FileFormatParams } from '../ui';

src/entities/file/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './types';

src/entities/file/types.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
export enum FileCompression {
2+
NONE = 'none',
3+
BZIP2 = 'bzip2',
4+
GZIP = 'gzip',
5+
LZ4 = 'lz4',
6+
SNAPPY = 'snappy',
7+
ZLIB = 'zlib',
8+
DEFLATE = 'deflate',
9+
}
10+
11+
export enum FileFormatType {
12+
CSV = 'csv',
13+
EXCEL = 'excel',
14+
JSON = 'json',
15+
JSON_LINE = 'jsonline',
16+
ORC = 'orc',
17+
PARQUET = 'parquet',
18+
XML = 'xml',
19+
}
20+
21+
export type FileFormat = Csv | Json | JsonLine | Excel | Orc | Parquet | Xml;
22+
23+
export interface Csv {
24+
type: FileFormatType.CSV;
25+
delimiter: string;
26+
encoding: string;
27+
quote: string;
28+
escape: string;
29+
include_header: boolean;
30+
line_sep: string;
31+
compression: Exclude<FileCompression, FileCompression.ZLIB> | 'none';
32+
}
33+
34+
export interface Json {
35+
type: FileFormatType.JSON;
36+
encoding: string;
37+
line_sep: string;
38+
compression: Exclude<FileCompression, FileCompression.ZLIB> | 'none';
39+
}
40+
41+
export interface JsonLine {
42+
type: FileFormatType.JSON_LINE;
43+
encoding: string;
44+
line_sep: string;
45+
compression: Exclude<FileCompression, FileCompression.ZLIB> | 'none';
46+
}
47+
48+
export interface Excel {
49+
type: FileFormatType.EXCEL;
50+
include_header: boolean;
51+
start_cell: string | null;
52+
}
53+
54+
export interface Orc {
55+
type: FileFormatType.ORC;
56+
compression:
57+
| Exclude<FileCompression, FileCompression.BZIP2 | FileCompression.GZIP | FileCompression.DEFLATE>
58+
| 'none';
59+
}
60+
61+
export interface Parquet {
62+
type: FileFormatType.PARQUET;
63+
compression:
64+
| Exclude<FileCompression, FileCompression.BZIP2 | FileCompression.ZLIB | FileCompression.DEFLATE>
65+
| 'none';
66+
}
67+
68+
export interface Xml {
69+
type: FileFormatType.XML;
70+
root_tag: string;
71+
row_tag: string;
72+
compression: Exclude<FileCompression, FileCompression.ZLIB | FileCompression.DEFLATE> | 'none';
73+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
import { Form, Switch } from 'antd';
3+
import { Select } from '@shared/ui';
4+
import { Typography } from 'antd';
5+
import clsx from 'clsx';
6+
7+
import { FileCompressionProps } from './types';
8+
import classes from './styles.module.less';
9+
10+
const { Text } = Typography;
11+
12+
export const FileCompression = <T,>({ name, options }: FileCompressionProps<T>) => {
13+
const fieldName = [...name, 'compression'];
14+
15+
/* useWatch takes a value from Form.Item, but useFormInstance takes one from general form state
16+
* useWatch returns undefined when Form.Item has not rendered yet
17+
* https://github.com/ant-design/ant-design/issues/49010
18+
*/
19+
Form.useWatch(fieldName);
20+
const formInstance = Form.useFormInstance();
21+
22+
const toggleCompression = (value: boolean) => {
23+
if (value) {
24+
formInstance.setFieldValue(fieldName, undefined);
25+
} else {
26+
formInstance.setFieldValue(fieldName, 'none');
27+
}
28+
};
29+
30+
const switchChecked = formInstance.getFieldValue(fieldName) !== 'none';
31+
32+
const selectClassNames = clsx({
33+
nodrag: true,
34+
[classes.hidden]: !switchChecked,
35+
});
36+
37+
return (
38+
<div className={classes.wrapper}>
39+
<div className={classes.switch}>
40+
<Text className={classes.label}>Compression</Text>
41+
<Switch className="nodrag" checked={switchChecked} onChange={toggleCompression} />
42+
</div>
43+
<Form.Item className={classes.formItem} name={fieldName}>
44+
<Select
45+
className={selectClassNames}
46+
size="large"
47+
options={options}
48+
placeholder="Select compression"
49+
showSearch
50+
/>
51+
</Form.Item>
52+
</div>
53+
);
54+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.formItem {
2+
:global(.ant-form-item-control-input) {
3+
min-height: auto;
4+
}
5+
}
6+
7+
.wrapper {
8+
display: flex;
9+
flex-direction: column;
10+
11+
.switch {
12+
display: flex;
13+
align-items: flex-start;
14+
gap: 12px;
15+
16+
.label {
17+
font-size: 15px;
18+
line-height: 1.5715;
19+
padding-bottom: 2px;
20+
}
21+
}
22+
23+
.hidden {
24+
display: none;
25+
}
26+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { OptionItem } from '@shared/ui';
2+
3+
import { FileFormatFieldName } from '../types';
4+
5+
export interface FileCompressionProps<T> extends FileFormatFieldName {
6+
options: OptionItem<T>[];
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { prepareOptionsForSelect } from '@shared/ui';
2+
3+
import { Csv, FileCompression } from '../../../../types';
4+
5+
export const CSV_COMPRESSION_SELECT_OPTIONS = prepareOptionsForSelect<Csv['compression']>({
6+
data: [
7+
FileCompression.BZIP2,
8+
FileCompression.DEFLATE,
9+
FileCompression.GZIP,
10+
FileCompression.LZ4,
11+
FileCompression.SNAPPY,
12+
],
13+
renderLabel: (data) => data,
14+
renderValue: (data) => data,
15+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react';
2+
import { Form, Input, Radio } from 'antd';
3+
4+
import { FileCompression } from '../FileCompression';
5+
6+
import { CSV_COMPRESSION_SELECT_OPTIONS } from './constants';
7+
import { FileFormatCsvProps } from './types';
8+
9+
export const FileFormatCsv = ({ name }: FileFormatCsvProps) => {
10+
return (
11+
<>
12+
<Form.Item label="Delimiter" name={[...name, 'delimiter']}>
13+
<Input className="nodrag" size="large" />
14+
</Form.Item>
15+
<Form.Item label="Encoding" name={[...name, 'encoding']}>
16+
<Input className="nodrag" size="large" />
17+
</Form.Item>
18+
<Form.Item label="Quote" name={[...name, 'quote']}>
19+
<Input className="nodrag" size="large" />
20+
</Form.Item>
21+
<Form.Item label="Escape" name={[...name, 'escape']}>
22+
<Input className="nodrag" size="large" />
23+
</Form.Item>
24+
<Form.Item label="Include header" name={[...name, 'include_header']}>
25+
<Radio.Group>
26+
<Radio value={true}>Yes</Radio>
27+
<Radio value={false}>No</Radio>
28+
</Radio.Group>
29+
</Form.Item>
30+
<Form.Item label="Line separator" name={[...name, 'line_sep']}>
31+
<Input className="nodrag" size="large" />
32+
</Form.Item>
33+
<FileCompression name={name} options={CSV_COMPRESSION_SELECT_OPTIONS} />
34+
</>
35+
);
36+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { FileFormatFieldName } from '../types';
2+
3+
export interface FileFormatCsvProps extends FileFormatFieldName {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Form, Input, Radio } from 'antd';
2+
import React from 'react';
3+
4+
import { FileFormatExcelProps } from './types';
5+
6+
export const FileFormatExcel = ({ name }: FileFormatExcelProps) => {
7+
return (
8+
<>
9+
<Form.Item label="Include header" name={[...name, 'include_header']}>
10+
<Radio.Group>
11+
<Radio value={true}>Yes</Radio>
12+
<Radio value={false}>No</Radio>
13+
</Radio.Group>
14+
</Form.Item>
15+
<Form.Item label="Start cell" name={[...name, 'start_cell']}>
16+
<Input className="nodrag" size="large" />
17+
</Form.Item>
18+
</>
19+
);
20+
};

0 commit comments

Comments
 (0)