Skip to content

Commit b4312b7

Browse files
authored
[DOP-33475] Добавить компонент для работы с SQL (#166)
1 parent 32fb80d commit b4312b7

52 files changed

Lines changed: 488 additions & 124 deletions

File tree

Some content is hidden

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

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@tanstack/react-query": "5.90.21",
2525
"@tanstack/react-query-devtools": "5.91.3",
2626
"@xyflow/react": "12.10.1",
27+
"ace-builds": "1.43.6",
2728
"antd": "4.24.16",
2829
"axios": "1.13.6",
2930
"clsx": "2.1.1",
@@ -32,6 +33,7 @@
3233
"i18next": "24.2.3",
3334
"rc-picker": "4.11.3",
3435
"react": "18.3.1",
36+
"react-ace": "14.0.1",
3537
"react-dom": "18.3.1",
3638
"react-error-boundary": "4.1.2",
3739
"react-i18next": "15.7.4",

src/app/styles/variables.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
@typography-title-margin-bottom: 0;
1919

2020
@input-bg: #f1f3f5;
21+
@input-border: 1px solid #d9d9d9;
2122
@select-background: #f1f3f5;
2223
@picker-bg: #f1f3f5;
2324
@tooltip-bg: #000000;

src/entities/transformation/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const TRANSFORMATIONS_FORM_DEFAULT_VALUE: TransformationsForm = {
2121
[TransformationType.FILTER_FILE]: [],
2222
[TransformationType.FILTER_ROWS]: [],
2323
[TransformationType.FILTER_COLUMNS]: [],
24+
[TransformationType.FILTER_SQL]: [],
2425
};
2526

2627
export const TRANSFORMATIONS_REQUEST_DEFAULT_VALUE: Transformations = [
@@ -71,6 +72,8 @@ const FILE_TRANSFORMATION_TYPES = Object.values(TransformationType);
7172

7273
const DB_TRANSFORMATION_TYPES = FILE_TRANSFORMATION_TYPES.filter((type) => type !== TransformationType.FILTER_FILE);
7374

75+
export const DEFAULT_TRANSFORMATION_TYPES = DB_TRANSFORMATION_TYPES;
76+
7477
export const CONNECTION_TYPE_SUPPORT_TRANSFORMATION_TYPES: Record<ConnectionType, TransformationType[]> = {
7578
[ConnectionType.CLICKHOUSE]: DB_TRANSFORMATION_TYPES,
7679
[ConnectionType.FTP]: FILE_TRANSFORMATION_TYPES,

src/entities/transformation/types.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export enum TransformationType {
44
FILTER_ROWS = 'dataframe_rows_filter',
55
FILTER_COLUMNS = 'dataframe_columns_filter',
66
FILTER_FILE = 'file_metadata_filter',
7+
FILTER_SQL = 'sql',
78
}
89

910
export enum TransformationFilterRowsType {
@@ -107,15 +108,43 @@ export interface TransformationFilterFileForm {
107108
filters: Array<TransformationFilterFileRegexpItemForm | TransformationFilterFileSizeItemForm>;
108109
}
109110

110-
export type Transformations = Array<TransformationFilterRows | TransformationFilterColumns | TransformationFilterFile>;
111+
export enum TransformationFilterSqlDialect {
112+
SPARK = 'spark',
113+
}
114+
115+
export type TransformationFilterSql = {
116+
type: TransformationType.FILTER_SQL;
117+
dialect: TransformationFilterSqlDialect;
118+
query: string;
119+
};
120+
121+
export type Transformations = Array<
122+
TransformationFilterRows | TransformationFilterColumns | TransformationFilterFile | TransformationFilterSql
123+
>;
124+
125+
export interface TransformationFilterSqlSparkItemForm {
126+
dialect: TransformationFilterSqlDialect;
127+
query: string;
128+
}
129+
130+
export type TransformationFormFilterSql = {
131+
type: TransformationType.FILTER_SQL;
132+
filters: Array<TransformationFilterSqlSparkItemForm>;
133+
};
111134

112135
export interface TransformationsForm {
113136
[TransformationType.FILTER_FILE]?: TransformationFilterFileForm['filters'];
114137
[TransformationType.FILTER_ROWS]?: TransformationFilterRows['filters'];
115138
[TransformationType.FILTER_COLUMNS]?: TransformationFilterColumns['filters'];
139+
[TransformationType.FILTER_SQL]?: TransformationFormFilterSql['filters'];
116140
}
117141

118-
export type TransformationsFormNestedType<T extends keyof TransformationsForm> =
142+
export type TransformationsFormWithNestedType =
143+
| TransformationType.FILTER_FILE
144+
| TransformationType.FILTER_ROWS
145+
| TransformationType.FILTER_COLUMNS;
146+
147+
export type TransformationsFormNestedType<T extends TransformationsFormWithNestedType> =
119148
Required<TransformationsForm>[T][number]['type'];
120149

121150
export interface ShowButtonsContextProps {

src/entities/transformation/ui/TransformationForm/TransformationForm.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Button, Form, FormListFieldData } from 'antd';
2-
import React, { memo, useLayoutEffect } from 'react';
2+
import { memo, useLayoutEffect } from 'react';
33
import { useTranslation } from 'react-i18next';
44

55
import { useShowButtons } from '../../hooks';
6-
import { Transformations, TransformationType } from '../../types';
6+
import { TransformationsForm, TransformationType } from '../../types';
77

88
import { TransformationFormItem } from './components';
99
import { TransformationFormProps } from './types';
@@ -17,20 +17,24 @@ const TransformationFormComponent = <T extends TransformationType>({
1717
const { isDisplayed } = useShowButtons();
1818

1919
const formInstance = Form.useFormInstance();
20-
const filtersValues: Transformations[number]['filters'] | undefined = formInstance.getFieldValue([
20+
const filtersValues: TransformationsForm[T] | undefined = formInstance.getFieldValue([
2121
'transformations',
2222
transformationType,
2323
]);
24+
const isFilterEmpty = !filtersValues?.length;
2425

2526
/** Add at least one element to array form value here,
2627
* because it is inconvenient to check for the presence of a default value of this array,
2728
* when forming a request to backend or initial form values */
2829
useLayoutEffect(() => {
29-
const needFillEmpty = !canHaveEmptyRecordsList && !filtersValues?.length;
30+
const needFillEmpty = !canHaveEmptyRecordsList && isFilterEmpty;
3031
if (needFillEmpty) {
3132
formInstance.setFieldValue(['transformations', transformationType], [{}]);
3233
}
33-
}, [formInstance, filtersValues, transformationType, canHaveEmptyRecordsList]);
34+
}, [formInstance, isFilterEmpty, transformationType, canHaveEmptyRecordsList]);
35+
36+
const isNeedShowAddNew = (fields: FormListFieldData[]) =>
37+
isDisplayed && !(transformationType === TransformationType.FILTER_SQL && fields.length);
3438

3539
const canRemoveItem = ({ name }: FormListFieldData) => (name || canHaveEmptyRecordsList) && isDisplayed;
3640

@@ -47,9 +51,11 @@ const TransformationFormComponent = <T extends TransformationType>({
4751
key={field.key}
4852
/>
4953
))}
50-
<Button className="nodrag" size="large" type="primary" onClick={() => add()} hidden={!isDisplayed}>
51-
{t('add')}
52-
</Button>
54+
{isNeedShowAddNew(fields) && (
55+
<Button className="nodrag" size="large" type="primary" onClick={() => add()}>
56+
{t('add')}
57+
</Button>
58+
)}
5359
</div>
5460
)}
5561
</Form.List>

src/entities/transformation/ui/TransformationForm/components/FilterComponent/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import React from 'react';
2-
import { TransformationsFormNestedType, TransformationType } from '@entities/transformation';
1+
import {
2+
TransformationsFormNestedType,
3+
TransformationsFormWithNestedType,
4+
TransformationType,
5+
} from '@entities/transformation';
36

47
import { FilterColumnsValue } from '../FilterColumnsValue';
58
import { FilterFileValue } from '../FilterFileValue';
69
import { FilterRowsValue } from '../FilterRowsValue';
710

811
import { FilterComponentProps } from './types';
912

10-
export const FilterComponent = <T extends TransformationType>({
13+
export const FilterComponent = <T extends TransformationsFormWithNestedType>({
1114
transformationType,
1215
nestedType,
1316
name,

src/entities/transformation/ui/TransformationForm/components/FilterComponent/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { TransformationsFormNestedType, TransformationType } from '@entities/transformation';
1+
import { TransformationsFormNestedType, TransformationsFormWithNestedType } from '@entities/transformation';
22

3-
export interface FilterComponentProps<T extends TransformationType> {
3+
export interface FilterComponentProps<T extends TransformationsFormWithNestedType> {
44
name: number;
55
transformationType: T;
66
nestedType?: TransformationsFormNestedType<T>;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { AceSqlEditor } from '@shared/ui/AceSqlEditor';
2+
import { getCountLines } from '@shared/utils';
3+
4+
import { FilterSqlProps } from './types';
5+
import { FONT_SIZE, LINE_HEIGHT, WIDTH } from './constants';
6+
import * as classes from './styles.module.less';
7+
8+
export const FilterSql = ({ autoHeightMaxLineCount, value, onChange }: FilterSqlProps) => {
9+
/** Calc the number of lines in the SQL expression to set the height of the editor */
10+
const linesCount = Math.max(1, getCountLines(value as string));
11+
const heightLinesCount = autoHeightMaxLineCount ? Math.min(linesCount, autoHeightMaxLineCount) : linesCount;
12+
13+
return (
14+
<AceSqlEditor
15+
className={classes.root}
16+
tabSize={2}
17+
fontSize={`${FONT_SIZE}em`}
18+
width={WIDTH}
19+
height={`${heightLinesCount * LINE_HEIGHT + 2}px`}
20+
lineHeight={`${LINE_HEIGHT}px`}
21+
value={value}
22+
onChange={onChange}
23+
/>
24+
);
25+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const SPARK_SQL_QUERY_SELECT_DOCS_URL = 'https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select.html';
2+
3+
export const SPARK_SQL_API_DOCS_URL = 'https://spark.apache.org/docs/latest/api/sql';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Typography } from 'antd';
2+
import { Trans } from 'react-i18next';
3+
4+
import { SPARK_SQL_API_DOCS_URL, SPARK_SQL_QUERY_SELECT_DOCS_URL } from './constants';
5+
const { Link } = Typography;
6+
7+
export const FilterSqlTooltip = () => {
8+
return (
9+
<Trans
10+
ns="transformation"
11+
i18nKey="filterSqlTooltip"
12+
components={{
13+
SparkSqlQuerySelectDocs: <Link href={SPARK_SQL_QUERY_SELECT_DOCS_URL} target="_blank" rel="noreferrer" />,
14+
SparkSqlApiDocs: <Link href={SPARK_SQL_API_DOCS_URL} target="_blank" rel="noreferrer" />,
15+
}}
16+
/>
17+
);
18+
};

0 commit comments

Comments
 (0)