Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/base/src/locale/en-US/dmsDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ export default {
maintenanceTime: 'Maintenance time',
maintenanceTimeTips:
'After setting the maintenance time, workflows can only be executed during this maintenance time period',
sqlWorkbenchMaintenanceTime: 'SQL workbench maintenance time',
sqlWorkbenchMaintenanceTimeTips:
'Non-DQL statements in the SQL workbench can only run during these windows (independent from DB instance maintenance time)',
needAuditSqlService: 'Enable SQL audit service',
closeAuditSqlServiceTips:
'If you do not enable the SQL audit service, the DB instance cannot be used in SQL audit related services, are you sure to close it?',
Expand Down
3 changes: 3 additions & 0 deletions packages/base/src/locale/zh-CN/dmsDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export default {
queryTimeoutSecond: 'SQL超时限制(s)',
maintenanceTime: '运维时间',
maintenanceTimeTips: '设置运维时间后,仅能在此运维时间段内上线工单',
sqlWorkbenchMaintenanceTime: 'SQL 工作台运维时间',
sqlWorkbenchMaintenanceTimeTips:
'设置后,非 DQL 语句仅能在该运维时间段内于 SQL 工作台执行(与数据源运维时间独立)',
needAuditSqlService: '是否开启SQL审核业务',
needAuditSqlServiceTips: '关闭后将禁用所用场景的SQL审核',
closeAuditSqlServiceTips:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('page/DataSource/AddDataSource', () => {

afterEach(() => {
jest.useRealTimers();
jest.clearAllMocks();
jest.restoreAllMocks();
cleanup();
});

Expand Down Expand Up @@ -219,7 +219,8 @@ describe('page/DataSource/AddDataSource', () => {
audit_enabled: true,
rule_template_id: '3',
rule_template_name: 'default_MySQL1',
workflow_exec_enabled: true
workflow_exec_enabled: true,
maintenance_times: []
}
},
user: 'root'
Expand Down Expand Up @@ -443,7 +444,8 @@ describe('page/DataSource/AddDataSource', () => {
sql_query_config: {
allow_query_when_less_than_audit_level: undefined,
audit_enabled: undefined,
workflow_exec_enabled: undefined
workflow_exec_enabled: undefined,
maintenance_times: []
}
},
user: 'root',
Expand All @@ -463,6 +465,114 @@ describe('page/DataSource/AddDataSource', () => {
expect(navigateSpy).toHaveBeenCalledTimes(1);
});

it('should submit sql workbench maintenance times', async () => {
const { baseElement } = customRender();
await act(async () => jest.advanceTimersByTime(9300));
fireEvent.change(getBySelector('#name', baseElement), {
target: {
value: 'name-database-field-case'
}
});
await act(async () => jest.advanceTimersByTime(300));
fireEvent.mouseDown(getBySelector('#type', baseElement));
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(getBySelector('span[title="mysql"]', baseElement));
await act(async () => jest.advanceTimersByTime(3000));
fireEvent.change(getBySelector('#ip', baseElement), {
target: {
value: '1.1.1.3'
}
});
await act(async () => jest.advanceTimersByTime(300));
fireEvent.change(getBySelector('#user', baseElement), {
target: {
value: 'root'
}
});
await act(async () => jest.advanceTimersByTime(300));
fireEvent.change(getBySelector('#password', baseElement), {
target: {
value: 'root'
}
});
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(getBySelector('.editable-select-trigger', baseElement));
await act(async () => jest.advanceTimersByTime(0));
fireEvent.click(getAllBySelector('.ant-dropdown-menu-item')[0]);
await act(async () => jest.advanceTimersByTime(0));

fireEvent.mouseDown(getBySelector('#ruleTemplateName', baseElement));
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(
getBySelector('div[title="custom_template_b"]', baseElement)
);
await act(async () => jest.advanceTimersByTime(300));
fireEvent.mouseDown(
getBySelector('#dataExportRuleTemplateName', baseElement)
);
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(getAllBySelector('div[title="default_MySQL1"]')[1]);
await act(async () => jest.advanceTimersByTime(300));

fireEvent.click(getBySelector('#needAuditForSqlQuery', baseElement));
await act(async () => jest.advanceTimersByTime(0));
fireEvent.mouseDown(getBySelector('#workbenchTemplateName', baseElement));
await act(async () => jest.advanceTimersByTime(0));
fireEvent.click(getAllBySelector('div[title="default_MySQL1"]')[2]);
await act(async () => jest.advanceTimersByTime(0));
fireEvent.mouseDown(
getBySelector('#allowQueryWhenLessThanAuditLevel', baseElement)
);
await act(async () => jest.advanceTimersByTime(0));
fireEvent.click(getBySelector('div[title="warn"]', baseElement));
await act(async () => jest.advanceTimersByTime(0));

const workbenchMaintenanceField = screen
.getByText('SQL 工作台运维时间')
.closest('.ant-form-item') as HTMLElement;
fireEvent.click(getBySelector('button', workbenchMaintenanceField));
await act(async () => jest.advanceTimersByTime(300));
const inputEle = getAllBySelector('.ant-picker-input', baseElement);
expect(inputEle.length).toBe(2);
fireEvent.click(inputEle[0].parentElement!);
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(screen.getAllByText('01')[0]);
await act(async () => jest.advanceTimersByTime(100));
fireEvent.click(screen.getAllByText('05')[1]);
await act(async () => jest.advanceTimersByTime(100));
fireEvent.click(getBySelector('.ant-picker-ok .ant-btn'));
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(screen.getAllByText('03')[0]);
await act(async () => jest.advanceTimersByTime(100));
fireEvent.click(screen.getAllByText('15')[1]);
await act(async () => jest.advanceTimersByTime(100));
fireEvent.click(getBySelector('.ant-picker-ok .ant-btn'));
await act(async () => jest.advanceTimersByTime(300));
fireEvent.click(screen.getByText('确 认'));
await act(async () => jest.advanceTimersByTime(300));

await act(async () => {
fireEvent.click(screen.getByText('提 交'));
});
await act(async () => jest.advanceTimersByTime(3000));
expect(requestAddDBServiceSpy).toHaveBeenCalled();
expect(
requestAddDBServiceSpy.mock.calls[0][0].db_service.sqle_config
.sql_query_config.maintenance_times
).toEqual([
{
maintenance_start_time: {
hour: 1,
minute: 5
},
maintenance_stop_time: {
hour: 3,
minute: 15
}
}
]);
});

it('render prepare api req', async () => {
const requestRuleTemplateList =
sqleMockApi.rule_template.getRuleTemplateTips();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ const AddDataSource = () => {
audit_enabled: values.needAuditForSqlQuery,
rule_template_id: values.workbenchTemplateId,
rule_template_name: values.workbenchTemplateName,
workflow_exec_enabled: values.allowExecuteNonDqlInWorkflow
workflow_exec_enabled: values.allowExecuteNonDqlInWorkflow,
maintenance_times:
values.sqlWorkbenchMaintenanceTime?.map((time) => ({
maintenance_start_time: time.startTime,
maintenance_stop_time: time.endTime
})) ?? []
}
},
// #endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
BasicTag,
EmptyBox
} from '@actiontech/dms-kit';
import { MaintenanceTimePickerPopoverWrapper } from './style';
import {
MaintenanceTimePickerPopoverWrapper,
MaintenanceTimePickerTagsWrapper
} from './style';
const MaintenanceTimePicker: React.FC<MaintenanceTimePickerProps> = (props) => {
const { value = [], onChange } = props;
const [messageApi, contextHolder] = message.useMessage();
Expand Down Expand Up @@ -76,17 +79,19 @@ const MaintenanceTimePicker: React.FC<MaintenanceTimePickerProps> = (props) => {
</Typography.Text>
}
>
{value.map((v, index) => (
<BasicTag
closable
onClose={() => deleteTime(index)}
key={`${generateKey(v)}-${index}`}
size="large"
>
{addZero(v.startTime.hour)}:{addZero(v.startTime.minute)} -
{addZero(v.endTime.hour)}:{addZero(v.endTime.minute)}
</BasicTag>
))}
<MaintenanceTimePickerTagsWrapper>
{value.map((v, index) => (
<BasicTag
closable
onClose={() => deleteTime(index)}
key={`${generateKey(v)}-${index}`}
size="small"
>
{addZero(v.startTime.hour)}:{addZero(v.startTime.minute)} -{' '}
{addZero(v.endTime.hour)}:{addZero(v.endTime.minute)}
</BasicTag>
))}
</MaintenanceTimePickerTagsWrapper>
</EmptyBox>
<Popover
open={popoverVisible}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,38 +991,43 @@ exports[`page/DataSource/MaintenanceTimePicker render has value 1`] = `
class="ant-space-item"
style="margin-right: 8px;"
>
<span
class="ant-tag ant-tag-default basic-tag-wrapper basic-large-tag-wrapper css-d31ub5"
<div
class="css-n2cywu"
>
01
:
05
-
05
:
05
<span
aria-label="close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
class="ant-tag ant-tag-default basic-tag-wrapper basic-small-tag-wrapper css-d31ub5"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
fill-rule="evenodd"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
01
:
05
-

05
:
05
<span
aria-label="close"
class="anticon anticon-close ant-tag-close-icon"
role="img"
tabindex="-1"
>
<path
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
/>
</svg>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
fill-rule="evenodd"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
/>
</svg>
</span>
</span>
</span>
</div>
</div>
<div
class="ant-space-item"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { styled } from '@mui/material/styles';
import { Row } from 'antd';

export const MaintenanceTimePickerTagsWrapper = styled('div')`
display: flex;
flex-direction: column;
gap: 4px;
width: 100%;
min-width: 0;

.ant-tag {
width: 100%;
max-width: 100%;
margin-inline-end: 0 !important;
justify-content: center;
box-sizing: border-box;
font-variant-numeric: tabular-nums;
}
`;

export const MaintenanceTimePickerPopoverWrapper = styled(Row)`
width: 300px;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,78 @@ exports[`SqlAuditFields should match snapshot when needSqlAuditService and needA
</div>
</div>
</div>
<div
class="ant-form-item has-label-tip css-1jlm9cy"
>
<div
class="ant-row ant-form-item-row"
>
<div
class="ant-col ant-form-item-label"
>
<label
class=""
for="sqlWorkbenchMaintenanceTime"
title=""
>
<div
class="label-cont-custom"
>
<div>
SQL 工作台运维时间
</div>
<div
class="tip-content-box"
>
设置后,非 DQL 语句仅能在该运维时间段内于 SQL 工作台执行(与数据源运维时间独立)
</div>
</div>
</label>
</div>
<div
class="ant-col ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center full-width-element"
>
<div
class="ant-space-item"
style="margin-right: 8px;"
/>
<div
class="ant-space-item"
style="margin-right: 8px;"
>
<span
class="ant-typography ant-typography-secondary"
>
请选择时间段
</span>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn ant-btn-default basic-button-wrapper css-10ae2zl"
type="button"
>
<span>
添 加
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="ant-form-item has-label-tip no-margin-field css-1jlm9cy"
>
Expand Down
Loading
Loading