mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
fixes 10357: Update Partitionning Setting Flow for Profiler (#10743)
* initial commit for #10357 * added form based on partition condition * localization sync * added unit test * updated sql editor with common component * updated form based on switch * addressing comment * added form type and provided to form instance * added default value for partitionValues in initialValue field
This commit is contained in:
parent
65297e5b1d
commit
4b260f1736
@ -14,7 +14,7 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Form, Input, InputNumber, Select, Switch } from 'antd';
|
||||
import 'codemirror/addon/fold/foldgutter.css';
|
||||
import { SUPPORTED_PARTITION_TYPE } from 'constants/profiler.constant';
|
||||
import { SUPPORTED_PARTITION_TYPE_FOR_DATE_TIME } from 'constants/profiler.constant';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -46,7 +46,9 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
||||
) {
|
||||
const partitionColumnOptions = table.columns.reduce(
|
||||
(result, column) => {
|
||||
if (SUPPORTED_PARTITION_TYPE.includes(column.dataType)) {
|
||||
if (
|
||||
SUPPORTED_PARTITION_TYPE_FOR_DATE_TIME.includes(column.dataType)
|
||||
) {
|
||||
return [
|
||||
...result,
|
||||
{
|
||||
|
@ -11,21 +11,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { cleanup, render, screen } from '@testing-library/react';
|
||||
import {
|
||||
act,
|
||||
cleanup,
|
||||
fireEvent,
|
||||
render,
|
||||
screen,
|
||||
} from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MOCK_TABLE } from '../../../mocks/TableData.mock';
|
||||
import { ProfilerSettingsModalProps } from '../TableProfiler.interface';
|
||||
import ProfilerSettingsModal from './ProfilerSettingsModal';
|
||||
|
||||
jest.mock('antd/lib/grid', () => ({
|
||||
Row: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
Col: jest
|
||||
.fn()
|
||||
.mockImplementation(({ children, ...props }) => (
|
||||
<div data-testid={props['data-testid']}>{children}</div>
|
||||
)),
|
||||
}));
|
||||
|
||||
jest.mock('rest/tableAPI', () => ({
|
||||
getTableProfilerConfig: jest
|
||||
.fn()
|
||||
@ -55,11 +52,51 @@ describe('Test ProfilerSettingsModal component', () => {
|
||||
const sqlEditor = await screen.findByTestId('sql-editor-container');
|
||||
const includeSelect = await screen.findByTestId('include-column-container');
|
||||
const excludeSelect = await screen.findByTestId('exclude-column-container');
|
||||
const partitionSwitch = await screen.findByTestId(
|
||||
'enable-partition-switch'
|
||||
);
|
||||
const intervalType = await screen.findByTestId('interval-type');
|
||||
const columnName = await screen.findByTestId('column-name');
|
||||
|
||||
expect(modal).toBeInTheDocument();
|
||||
expect(sampleContainer).toBeInTheDocument();
|
||||
expect(sqlEditor).toBeInTheDocument();
|
||||
expect(includeSelect).toBeInTheDocument();
|
||||
expect(excludeSelect).toBeInTheDocument();
|
||||
expect(partitionSwitch).toBeInTheDocument();
|
||||
expect(intervalType).toBeInTheDocument();
|
||||
expect(columnName).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Interval Type and Column Name field should be disabled, when partition switch is off', async () => {
|
||||
render(<ProfilerSettingsModal {...mockProps} />);
|
||||
const partitionSwitch = await screen.findByTestId(
|
||||
'enable-partition-switch'
|
||||
);
|
||||
const intervalType = await screen.findByTestId('interval-type');
|
||||
const columnName = await screen.findByTestId('column-name');
|
||||
|
||||
expect(partitionSwitch).toHaveAttribute('aria-checked', 'false');
|
||||
expect(intervalType).toHaveClass('ant-select-disabled');
|
||||
expect(columnName).toHaveClass('ant-select-disabled');
|
||||
});
|
||||
|
||||
it('Interval Type and Column Name field should be enabled, when partition switch is on', async () => {
|
||||
render(<ProfilerSettingsModal {...mockProps} />);
|
||||
const partitionSwitch = await screen.findByTestId(
|
||||
'enable-partition-switch'
|
||||
);
|
||||
const intervalType = await screen.findByTestId('interval-type');
|
||||
const columnName = await screen.findByTestId('column-name');
|
||||
|
||||
expect(partitionSwitch).toHaveAttribute('aria-checked', 'false');
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(partitionSwitch);
|
||||
});
|
||||
|
||||
expect(partitionSwitch).toHaveAttribute('aria-checked', 'true');
|
||||
expect(intervalType).not.toHaveClass('ant-select-disabled');
|
||||
expect(columnName).not.toHaveClass('ant-select-disabled');
|
||||
});
|
||||
});
|
||||
|
@ -14,6 +14,7 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Select,
|
||||
@ -27,7 +28,10 @@ import { Col, Row } from 'antd/lib/grid';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import 'codemirror/addon/fold/foldgutter.css';
|
||||
import { isEmpty, isEqual, isUndefined, omit, startCase } from 'lodash';
|
||||
import SchemaEditor from 'components/schema-editor/SchemaEditor';
|
||||
import { CSMode } from 'enums/codemirror.enum';
|
||||
import { PartitionIntervalType } from 'generated/api/data/createTable';
|
||||
import { isEmpty, isEqual, isNil, isUndefined, pick, startCase } from 'lodash';
|
||||
import React, {
|
||||
Reducer,
|
||||
useCallback,
|
||||
@ -36,17 +40,17 @@ import React, {
|
||||
useReducer,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getTableProfilerConfig, putTableProfileConfig } from 'rest/tableAPI';
|
||||
import {
|
||||
codeMirrorOption,
|
||||
DEFAULT_INCLUDE_PROFILE,
|
||||
INTERVAL_TYPE_OPTIONS,
|
||||
INTERVAL_UNIT_OPTIONS,
|
||||
PROFILER_METRIC,
|
||||
PROFILER_MODAL_LABEL_STYLE,
|
||||
PROFILE_SAMPLE_OPTIONS,
|
||||
SUPPORTED_PARTITION_TYPE,
|
||||
SUPPORTED_COLUMN_DATA_TYPE_FOR_INTERVAL,
|
||||
TIME_BASED_PARTITION,
|
||||
} from '../../../constants/profiler.constant';
|
||||
import {
|
||||
ProfileSampleType,
|
||||
@ -58,6 +62,7 @@ import SVGIcons, { Icons } from '../../../utils/SvgUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
|
||||
import SliderWithInput from '../../SliderWithInput/SliderWithInput';
|
||||
import {
|
||||
ProfilerForm,
|
||||
ProfilerSettingModalState,
|
||||
ProfilerSettingsModalProps,
|
||||
} from '../TableProfiler.interface';
|
||||
@ -70,7 +75,7 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
onVisibilityChange,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const [form] = Form.useForm<ProfilerForm>();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
@ -121,9 +126,14 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
return metricsOptions;
|
||||
}, [columns]);
|
||||
|
||||
const { partitionColumnOptions, isPartitionDisabled } = useMemo(() => {
|
||||
const partitionIntervalType = Form.useWatch(['partitionIntervalType'], form);
|
||||
|
||||
const partitionColumnOptions = useMemo(() => {
|
||||
const partitionColumnOptions = columns.reduce((result, column) => {
|
||||
if (SUPPORTED_PARTITION_TYPE.includes(column.dataType)) {
|
||||
const filter = partitionIntervalType
|
||||
? SUPPORTED_COLUMN_DATA_TYPE_FOR_INTERVAL[partitionIntervalType]
|
||||
: [];
|
||||
if (filter.includes(column.dataType)) {
|
||||
return [
|
||||
...result,
|
||||
{
|
||||
@ -135,13 +145,9 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
|
||||
return result;
|
||||
}, [] as { value: string; label: string }[]);
|
||||
const isPartitionDisabled = partitionColumnOptions.length === 0;
|
||||
|
||||
return {
|
||||
partitionColumnOptions,
|
||||
isPartitionDisabled,
|
||||
};
|
||||
}, [columns]);
|
||||
return partitionColumnOptions;
|
||||
}, [columns, partitionIntervalType]);
|
||||
|
||||
const updateInitialConfig = (tableProfilerConfig: TableProfilerConfig) => {
|
||||
const {
|
||||
@ -193,7 +199,9 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
enablePartition: partitioning.enablePartitioning || false,
|
||||
});
|
||||
|
||||
form.setFieldsValue({ ...partitioning });
|
||||
form.setFieldsValue({
|
||||
...partitioning,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -259,19 +267,23 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
const profileConfig: TableProfilerConfig = {
|
||||
excludeColumns: excludeCol.length > 0 ? excludeCol : undefined,
|
||||
profileQuery: !isEmpty(sqlQuery) ? sqlQuery : undefined,
|
||||
...{
|
||||
profileSample:
|
||||
profileSampleType === ProfileSampleType.Percentage
|
||||
? profileSamplePercentage
|
||||
: profileSampleRows,
|
||||
profileSampleType: profileSampleType,
|
||||
},
|
||||
profileSample:
|
||||
profileSampleType === ProfileSampleType.Percentage
|
||||
? profileSamplePercentage
|
||||
: profileSampleRows,
|
||||
profileSampleType: profileSampleType,
|
||||
includeColumns: !isEqual(includeCol, DEFAULT_INCLUDE_PROFILE)
|
||||
? getIncludesColumns()
|
||||
: undefined,
|
||||
partitioning: enablePartition
|
||||
? {
|
||||
...partitionData,
|
||||
partitionValues:
|
||||
partitionIntervalType === PartitionIntervalType.ColumnValue
|
||||
? partitionData?.partitionValues?.filter(
|
||||
(value) => !isEmpty(value)
|
||||
)
|
||||
: undefined,
|
||||
enablePartitioning: enablePartition,
|
||||
}
|
||||
: undefined,
|
||||
@ -320,19 +332,42 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
[]
|
||||
);
|
||||
|
||||
const handleCodeMirrorChange = useCallback(
|
||||
(_Editor, _EditorChange, value) => {
|
||||
handleStateChange({
|
||||
sqlQuery: value,
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
const handleCodeMirrorChange = useCallback((value) => {
|
||||
handleStateChange({
|
||||
sqlQuery: value,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleIncludeColumnsProfiler = useCallback((changedValues, data) => {
|
||||
const { partitionIntervalType, enablePartitioning } = changedValues;
|
||||
if (partitionIntervalType || !isNil(enablePartitioning)) {
|
||||
form.setFieldsValue({
|
||||
partitionColumnName: undefined,
|
||||
partitionIntegerRangeStart: undefined,
|
||||
partitionIntegerRangeEnd: undefined,
|
||||
partitionIntervalUnit: undefined,
|
||||
partitionInterval: undefined,
|
||||
partitionValues: [''],
|
||||
});
|
||||
}
|
||||
if (!isNil(enablePartitioning)) {
|
||||
form.setFieldsValue({
|
||||
partitionIntervalType: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
const handleIncludeColumnsProfiler = useCallback((_, data) => {
|
||||
handleStateChange({
|
||||
includeCol: data.includeColumns,
|
||||
partitionData: omit(data, 'includeColumns'),
|
||||
partitionData: pick(
|
||||
data,
|
||||
'partitionColumnName',
|
||||
'partitionIntegerRangeEnd',
|
||||
'partitionIntegerRangeStart',
|
||||
'partitionInterval',
|
||||
'partitionIntervalType',
|
||||
'partitionIntervalUnit',
|
||||
'partitionValues'
|
||||
),
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -437,12 +472,15 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
type: t('label.query'),
|
||||
})}{' '}
|
||||
</p>
|
||||
<CodeMirror
|
||||
|
||||
<SchemaEditor
|
||||
className="profiler-setting-sql-editor"
|
||||
data-testid="profiler-setting-sql-editor"
|
||||
options={codeMirrorOption}
|
||||
value={state?.sqlQuery}
|
||||
onBeforeChange={handleCodeMirrorChange}
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
value={state?.sqlQuery || ''}
|
||||
onChange={handleCodeMirrorChange}
|
||||
/>
|
||||
</Col>
|
||||
@ -469,6 +507,7 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
id="profiler-setting-form"
|
||||
initialValues={{
|
||||
includeColumns: state?.includeCol,
|
||||
partitionData: [''],
|
||||
...state?.data?.partitioning,
|
||||
}}
|
||||
layout="vertical"
|
||||
@ -546,54 +585,18 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
</>
|
||||
)}
|
||||
</List>
|
||||
<Form.Item className="m-b-xs">
|
||||
<Space size={12}>
|
||||
<p>{t('label.enable-partition')}</p>
|
||||
<Switch
|
||||
checked={state?.enablePartition}
|
||||
data-testid="enable-partition-switch"
|
||||
disabled={isPartitionDisabled}
|
||||
onChange={handleEnablePartition}
|
||||
/>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">
|
||||
{t('label.column-entity', {
|
||||
entity: t('label.name'),
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
labelCol={{
|
||||
style: {
|
||||
paddingBottom: 8,
|
||||
},
|
||||
}}
|
||||
name="partitionColumnName"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.column-entity', {
|
||||
entity: t('label.name'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<Select
|
||||
allowClear
|
||||
className="w-full"
|
||||
data-testid="column-name"
|
||||
disabled={!state?.enablePartition}
|
||||
options={partitionColumnOptions}
|
||||
placeholder={t('message.select-column-name')}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Col span={24}>
|
||||
<Space align="center" size={12}>
|
||||
<p>{t('label.enable-partition')}</p>
|
||||
<Form.Item className="m-b-0" name="enablePartitioning">
|
||||
<Switch
|
||||
checked={state?.enablePartition}
|
||||
data-testid="enable-partition-switch"
|
||||
onChange={handleEnablePartition}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
@ -601,11 +604,7 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
label={
|
||||
<span className="text-xs">{t('label.interval-type')}</span>
|
||||
}
|
||||
labelCol={{
|
||||
style: {
|
||||
paddingBottom: 8,
|
||||
},
|
||||
}}
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionIntervalType"
|
||||
rules={[
|
||||
{
|
||||
@ -626,64 +625,234 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={<span className="text-xs">{t('label.interval')}</span>}
|
||||
labelCol={{
|
||||
style: {
|
||||
paddingBottom: 8,
|
||||
},
|
||||
}}
|
||||
name="partitionInterval"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.interval'),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<InputNumber
|
||||
className="w-full"
|
||||
data-testid="interval-required"
|
||||
disabled={!state?.enablePartition}
|
||||
placeholder={t('message.enter-interval')}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">{t('label.interval-unit')}</span>
|
||||
<span className="text-xs">
|
||||
{t('label.column-entity', {
|
||||
entity: t('label.name'),
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
labelCol={{
|
||||
style: {
|
||||
paddingBottom: 8,
|
||||
},
|
||||
}}
|
||||
name="partitionIntervalUnit"
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionColumnName"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.interval-unit'),
|
||||
fieldText: t('label.column-entity', {
|
||||
entity: t('label.name'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<Select
|
||||
allowClear
|
||||
className="w-full"
|
||||
data-testid="select-interval-unit"
|
||||
data-testid="column-name"
|
||||
disabled={!state?.enablePartition}
|
||||
options={INTERVAL_UNIT_OPTIONS}
|
||||
placeholder={t('message.select-interval-unit')}
|
||||
options={partitionColumnOptions}
|
||||
placeholder={t('message.select-column-name')}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{partitionIntervalType &&
|
||||
TIME_BASED_PARTITION.includes(partitionIntervalType) ? (
|
||||
<>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">{t('label.interval')}</span>
|
||||
}
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionInterval"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.interval'),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<InputNumber
|
||||
className="w-full"
|
||||
data-testid="interval-required"
|
||||
disabled={!state?.enablePartition}
|
||||
placeholder={t('message.enter-interval')}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">
|
||||
{t('label.interval-unit')}
|
||||
</span>
|
||||
}
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionIntervalUnit"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.interval-unit'),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<Select
|
||||
allowClear
|
||||
className="w-full"
|
||||
data-testid="select-interval-unit"
|
||||
disabled={!state?.enablePartition}
|
||||
options={INTERVAL_UNIT_OPTIONS}
|
||||
placeholder={t('message.select-interval-unit')}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</>
|
||||
) : null}
|
||||
{PartitionIntervalType.IntegerRange === partitionIntervalType ? (
|
||||
<>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">
|
||||
{t('label.start-entity', {
|
||||
entity: t('label.range'),
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionIntegerRangeStart"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.start-entity', {
|
||||
entity: t('label.range'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<InputNumber
|
||||
className="w-full"
|
||||
data-testid="start-range"
|
||||
placeholder={t('message.enter-a-field', {
|
||||
field: t('label.start-entity', {
|
||||
entity: t('label.range'),
|
||||
}),
|
||||
})}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
className="m-b-0"
|
||||
label={
|
||||
<span className="text-xs">
|
||||
{t('label.end-entity', {
|
||||
entity: t('label.range'),
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
labelCol={PROFILER_MODAL_LABEL_STYLE}
|
||||
name="partitionIntegerRangeEnd"
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t('message.field-text-is-required', {
|
||||
fieldText: t('label.end-entity', {
|
||||
entity: t('label.range'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
]}>
|
||||
<InputNumber
|
||||
className="w-full"
|
||||
data-testid="end-range"
|
||||
placeholder={t('message.enter-a-field', {
|
||||
field: t('label.end-entity', {
|
||||
entity: t('label.range'),
|
||||
}),
|
||||
})}
|
||||
size="middle"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{PartitionIntervalType.ColumnValue === partitionIntervalType ? (
|
||||
<Col span={24}>
|
||||
<List name="partitionValues">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
<div className="flex items-center tw-mb-1.5">
|
||||
<p className="w-form-label text-xs m-r-sm">
|
||||
{`${t('label.value')}:`}
|
||||
</p>
|
||||
<Button
|
||||
className="include-columns-add-button"
|
||||
icon={<PlusOutlined />}
|
||||
size="small"
|
||||
type="primary"
|
||||
onClick={() => add()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{fields.map(({ key, name, ...restField }) => (
|
||||
<Row gutter={16} key={key}>
|
||||
<Col className="flex" span={24}>
|
||||
<Form.Item
|
||||
className="w-full m-b-md"
|
||||
{...restField}
|
||||
name={name}
|
||||
rules={[
|
||||
{
|
||||
required: state?.enablePartition,
|
||||
message: t(
|
||||
'message.field-text-is-required',
|
||||
{
|
||||
fieldText: t('label.value'),
|
||||
}
|
||||
),
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
className="w-full"
|
||||
data-testid="partition-value"
|
||||
placeholder={t('message.enter-a-field', {
|
||||
field: t('label.value'),
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Button
|
||||
icon={
|
||||
<SVGIcons
|
||||
alt={t('label.delete')}
|
||||
className="w-4"
|
||||
icon={Icons.DELETE}
|
||||
/>
|
||||
}
|
||||
type="text"
|
||||
onClick={() => remove(name)}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</List>
|
||||
</Col>
|
||||
) : null}
|
||||
</Row>
|
||||
</Form>
|
||||
</Col>
|
||||
|
@ -95,3 +95,13 @@ export interface ProfilerSettingModalState {
|
||||
partitionData: PartitionProfilerConfig | undefined;
|
||||
selectedProfileSampleType: ProfileSampleType | undefined;
|
||||
}
|
||||
|
||||
export interface ProfilerForm extends PartitionProfilerConfig {
|
||||
profileSample: number | undefined;
|
||||
selectedProfileSampleType: ProfileSampleType | undefined;
|
||||
enablePartition: boolean;
|
||||
profileSampleType: ProfileSampleType | undefined;
|
||||
profileSamplePercentage: number;
|
||||
profileSampleRows: number | undefined;
|
||||
includeColumns: ColumnProfilerConfig[];
|
||||
}
|
||||
|
@ -314,13 +314,20 @@ export const STEPS_FOR_ADD_TEST_CASE: Array<StepperStepType> = [
|
||||
},
|
||||
];
|
||||
|
||||
export const SUPPORTED_PARTITION_TYPE = [
|
||||
export const SUPPORTED_PARTITION_TYPE_FOR_DATE_TIME = [
|
||||
DataType.Timestamp,
|
||||
DataType.Date,
|
||||
DataType.Datetime,
|
||||
DataType.Timestampz,
|
||||
];
|
||||
|
||||
export const SUPPORTED_COLUMN_DATA_TYPE_FOR_INTERVAL = {
|
||||
[PartitionIntervalType.IngestionTime]: SUPPORTED_PARTITION_TYPE_FOR_DATE_TIME,
|
||||
[PartitionIntervalType.TimeUnit]: SUPPORTED_PARTITION_TYPE_FOR_DATE_TIME,
|
||||
[PartitionIntervalType.IntegerRange]: [DataType.Int, DataType.Bigint],
|
||||
[PartitionIntervalType.ColumnValue]: [DataType.Varchar],
|
||||
};
|
||||
|
||||
export const INTERVAL_TYPE_OPTIONS = Object.values(PartitionIntervalType).map(
|
||||
(value) => ({
|
||||
value,
|
||||
@ -353,3 +360,14 @@ export const DEFAULT_HISTOGRAM_DATA = {
|
||||
boundaries: [],
|
||||
frequencies: [],
|
||||
};
|
||||
|
||||
export const PROFILER_MODAL_LABEL_STYLE = {
|
||||
style: {
|
||||
paddingBottom: 8,
|
||||
},
|
||||
};
|
||||
|
||||
export const TIME_BASED_PARTITION = [
|
||||
PartitionIntervalType.IngestionTime,
|
||||
PartitionIntervalType.TimeUnit,
|
||||
];
|
||||
|
@ -256,6 +256,7 @@
|
||||
"enable-partition": "Enable Partition",
|
||||
"end-date": "End Date",
|
||||
"end-date-time-zone": "End Date: ({{timeZone}})",
|
||||
"end-entity": "End {{entity}}",
|
||||
"endpoint": "Endpoint",
|
||||
"endpoint-url": "Endpoint URL",
|
||||
"endpoint-url-for-aws": "EndPoint URL for the AWS",
|
||||
@ -589,6 +590,7 @@
|
||||
"query-log-duration": "Query Log Duration",
|
||||
"query-lowercase": "query",
|
||||
"query-plural": "Queries",
|
||||
"range": "Range",
|
||||
"re-deploy": "Re Deploy",
|
||||
"re-enter-new-password": "Re-enter New Password",
|
||||
"re-index-all": "Re-Index All",
|
||||
|
@ -256,6 +256,7 @@
|
||||
"enable-partition": "Activer Partition",
|
||||
"end-date": "Date de Fin",
|
||||
"end-date-time-zone": "End Date: ({{timeZone}})",
|
||||
"end-entity": "End {{entity}}",
|
||||
"endpoint": "Point de Terminaison",
|
||||
"endpoint-url": "Point de terminaison $t(label.url-uppercase)",
|
||||
"endpoint-url-for-aws": "EndPoint URL for the AWS",
|
||||
@ -589,6 +590,7 @@
|
||||
"query-log-duration": "Query Log Duration",
|
||||
"query-lowercase": "query",
|
||||
"query-plural": "Requêtes",
|
||||
"range": "Range",
|
||||
"re-deploy": "Re-Déployer",
|
||||
"re-enter-new-password": "Re-enter New Password",
|
||||
"re-index-all": "Re Index All",
|
||||
|
@ -256,6 +256,7 @@
|
||||
"enable-partition": "パーティションを有効化",
|
||||
"end-date": "終了日時",
|
||||
"end-date-time-zone": "終了日時: ({{timeZone}})",
|
||||
"end-entity": "End {{entity}}",
|
||||
"endpoint": "エンドポイント",
|
||||
"endpoint-url": "エンドポイントURL",
|
||||
"endpoint-url-for-aws": "AWSのエンドポイントURL",
|
||||
@ -589,6 +590,7 @@
|
||||
"query-log-duration": "クエリログの時間",
|
||||
"query-lowercase": "クエリ",
|
||||
"query-plural": "クエリ",
|
||||
"range": "Range",
|
||||
"re-deploy": "再デプロイ",
|
||||
"re-enter-new-password": "新しいパスワードを再度入力してください",
|
||||
"re-index-all": "Re-Index All",
|
||||
|
@ -256,6 +256,7 @@
|
||||
"enable-partition": "Enable Partition",
|
||||
"end-date": "结束日期",
|
||||
"end-date-time-zone": "结束日期: ({{timeZone}})",
|
||||
"end-entity": "End {{entity}}",
|
||||
"endpoint": "终点",
|
||||
"endpoint-url": "终点 URL",
|
||||
"endpoint-url-for-aws": "EndPoint URL for the AWS",
|
||||
@ -589,6 +590,7 @@
|
||||
"query-log-duration": "Query Log Duration",
|
||||
"query-lowercase": "查询",
|
||||
"query-plural": "查询",
|
||||
"range": "Range",
|
||||
"re-deploy": "Re Deploy",
|
||||
"re-enter-new-password": "Re-enter New Password",
|
||||
"re-index-all": "Re Index All",
|
||||
|
Loading…
x
Reference in New Issue
Block a user