From acdf6ff12aaf72f1a92749ff1208d40ff622947d Mon Sep 17 00:00:00 2001
From: zzyangh <799463087@qq.com>
Date: Fri, 17 Oct 2025 13:22:02 +0800
Subject: [PATCH 1/4] [chore]: Update api
---
.../shared/lib/api/sqle/service/common.d.ts | 30 ++++---------------
.../api/sqle/service/configuration/index.d.ts | 9 ------
.../api/sqle/service/configuration/index.ts | 23 --------------
.../sqle/service/sql_optimization/index.d.ts | 2 +-
.../lib/api/sqle/service/workflow/index.d.ts | 12 ++++++++
5 files changed, 19 insertions(+), 57 deletions(-)
diff --git a/packages/shared/lib/api/sqle/service/common.d.ts b/packages/shared/lib/api/sqle/service/common.d.ts
index 23f03f29f..76821c29c 100644
--- a/packages/shared/lib/api/sqle/service/common.d.ts
+++ b/packages/shared/lib/api/sqle/service/common.d.ts
@@ -2069,14 +2069,6 @@ export interface IGetSystemModuleRedDotsRes {
message?: string;
}
-export interface IGetSystemVariablesResV1 {
- code?: number;
-
- data?: ISystemVariablesResV1;
-
- message?: string;
-}
-
export interface IGetTableMetadataResV1 {
code?: number;
@@ -2740,6 +2732,8 @@ export interface IOptimizationsummary {
}
export interface IOptimizeSQLReq {
+ db_type?: string;
+
explain_info?: string;
instance_name?: string;
@@ -2813,6 +2807,10 @@ export interface IProjectScore {
score?: number;
}
+export interface IReExecuteTaskOnWorkflowReq {
+ exec_sql_ids?: number[];
+}
+
export interface IRecordSource {
name?: RecordSourceNameEnum;
@@ -3445,14 +3443,6 @@ export interface IStatisticsAuditedSQLResV1 {
risk_rate?: number;
}
-export interface ISystemVariablesResV1 {
- cb_operation_logs_expired_hours?: number;
-
- operation_record_expired_hours?: number;
-
- url?: string;
-}
-
export interface ITable {
name?: string;
}
@@ -3853,14 +3843,6 @@ export interface IUpdateStagesInstanceDep {
stage_instance_id?: string;
}
-export interface IUpdateSystemVariablesReqV1 {
- cb_operation_logs_expired_hours?: number;
-
- operation_record_expired_hours?: number;
-
- url?: string;
-}
-
export interface IUpdateTaskBackupStrategyReq {
strategy?: UpdateTaskBackupStrategyReqStrategyEnum;
}
diff --git a/packages/shared/lib/api/sqle/service/configuration/index.d.ts b/packages/shared/lib/api/sqle/service/configuration/index.d.ts
index 9d464d719..b289212c8 100644
--- a/packages/shared/lib/api/sqle/service/configuration/index.d.ts
+++ b/packages/shared/lib/api/sqle/service/configuration/index.d.ts
@@ -17,8 +17,6 @@ import {
IGetLicenseResV1,
ICheckLicenseResV1,
ISSHPublicKeyInfoV1Rsp,
- IGetSystemVariablesResV1,
- IUpdateSystemVariablesReqV1,
IGetWechatAuditConfigurationResV1,
IUpdateWechatConfigurationReqV1,
ITestWechatConfigurationReqV1,
@@ -87,13 +85,6 @@ export interface IGetSSHPublicKeyReturn extends ISSHPublicKeyInfoV1Rsp {}
export interface IGenSSHPublicKeyReturn extends IBaseRes {}
-export interface IGetSystemVariablesV1Return extends IGetSystemVariablesResV1 {}
-
-export interface IUpdateSystemVariablesV1Params
- extends IUpdateSystemVariablesReqV1 {}
-
-export interface IUpdateSystemVariablesV1Return extends IBaseRes {}
-
export interface IGetWechatAuditConfigurationV1Return
extends IGetWechatAuditConfigurationResV1 {}
diff --git a/packages/shared/lib/api/sqle/service/configuration/index.ts b/packages/shared/lib/api/sqle/service/configuration/index.ts
index 5c5c7fabd..38443cc41 100644
--- a/packages/shared/lib/api/sqle/service/configuration/index.ts
+++ b/packages/shared/lib/api/sqle/service/configuration/index.ts
@@ -31,9 +31,6 @@ import {
ICheckSQLELicenseV1Return,
IGetSSHPublicKeyReturn,
IGenSSHPublicKeyReturn,
- IGetSystemVariablesV1Return,
- IUpdateSystemVariablesV1Params,
- IUpdateSystemVariablesV1Return,
IGetWechatAuditConfigurationV1Return,
IUpdateWechatAuditConfigurationV1Params,
IUpdateWechatAuditConfigurationV1Return,
@@ -233,26 +230,6 @@ class ConfigurationService extends ServiceBase {
);
}
- public getSystemVariablesV1(options?: AxiosRequestConfig) {
- return this.get(
- '/v1/configurations/system_variables',
- undefined,
- options
- );
- }
-
- public updateSystemVariablesV1(
- params: IUpdateSystemVariablesV1Params,
- options?: AxiosRequestConfig
- ) {
- const paramsData = this.cloneDeep(params);
- return this.patch(
- '/v1/configurations/system_variables',
- paramsData,
- options
- );
- }
-
public getWechatAuditConfigurationV1(options?: AxiosRequestConfig) {
return this.get(
'/v1/configurations/wechat_audit',
diff --git a/packages/shared/lib/api/sqle/service/sql_optimization/index.d.ts b/packages/shared/lib/api/sqle/service/sql_optimization/index.d.ts
index 23cd18fa9..84a813835 100644
--- a/packages/shared/lib/api/sqle/service/sql_optimization/index.d.ts
+++ b/packages/shared/lib/api/sqle/service/sql_optimization/index.d.ts
@@ -138,7 +138,7 @@ export interface ISQLOptimizeV2Params extends IOptimizeSQLReq {
schema_name?: string;
- db_type?: string;
+ db_type: string;
optimization_name: string;
diff --git a/packages/shared/lib/api/sqle/service/workflow/index.d.ts b/packages/shared/lib/api/sqle/service/workflow/index.d.ts
index a9c47ac0e..d0f9c9668 100644
--- a/packages/shared/lib/api/sqle/service/workflow/index.d.ts
+++ b/packages/shared/lib/api/sqle/service/workflow/index.d.ts
@@ -11,6 +11,7 @@ import {
IBackupSqlListRes,
ICreateRollbackWorkflowReq,
ICreateRollbackWorkflowRes,
+ IReExecuteTaskOnWorkflowReq,
IGetWorkflowResV1,
IUpdateWorkflowReqV1,
IRejectWorkflowReqV1,
@@ -215,6 +216,17 @@ export interface IGetWorkflowAttachmentParams {
task_id: string;
}
+export interface IReExecuteTaskOnWorkflowV1Params
+ extends IReExecuteTaskOnWorkflowReq {
+ project_name: string;
+
+ workflow_id: string;
+
+ task_id: string;
+}
+
+export interface IReExecuteTaskOnWorkflowV1Return extends IBaseRes {}
+
export interface ITerminateSingleTaskByWorkflowV1Params {
workflow_id: string;
From c74994710da09c47d61010cf291dd6384e4f6345 Mon Sep 17 00:00:00 2001
From: zzyangh <799463087@qq.com>
Date: Fri, 17 Oct 2025 13:22:52 +0800
Subject: [PATCH 2/4] [chore](System): Replace api types
---
.../CBOperationLogsExpiredHours.tsx | 2 +-
.../OperationRecordExpiredHours.tsx | 2 +-
.../components/UrlAddressPrefixTips.tsx | 2 +-
.../src/page/System/GlobalSetting/index.tsx | 2 +-
.../lib/api/sqle/service/workflow/index.ts | 23 +++++++++++++++++++
5 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/packages/base/src/page/System/GlobalSetting/components/CBOperationLogsExpiredHours.tsx b/packages/base/src/page/System/GlobalSetting/components/CBOperationLogsExpiredHours.tsx
index d5a9c0107..741742bd9 100644
--- a/packages/base/src/page/System/GlobalSetting/components/CBOperationLogsExpiredHours.tsx
+++ b/packages/base/src/page/System/GlobalSetting/components/CBOperationLogsExpiredHours.tsx
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
import { ConfigItem } from '@actiontech/dms-kit';
import { EditInputNumber, LabelContent } from '@actiontech/dms-kit';
import useValidatorNumber from './useValidatorNumber';
-import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/base/service/common';
import { PERMISSIONS, usePermission } from '@actiontech/shared/lib/features';
export interface CBOperationLogsExpiredHoursProps {
expiredHours: number | undefined;
diff --git a/packages/base/src/page/System/GlobalSetting/components/OperationRecordExpiredHours.tsx b/packages/base/src/page/System/GlobalSetting/components/OperationRecordExpiredHours.tsx
index 512081f4f..1fa748a78 100644
--- a/packages/base/src/page/System/GlobalSetting/components/OperationRecordExpiredHours.tsx
+++ b/packages/base/src/page/System/GlobalSetting/components/OperationRecordExpiredHours.tsx
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
import { ConfigItem } from '@actiontech/dms-kit';
import { EditInputNumber, LabelContent } from '@actiontech/dms-kit';
import useValidatorNumber from './useValidatorNumber';
-import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/base/service/common';
import { PERMISSIONS, usePermission } from '@actiontech/shared/lib/features';
export interface OperationRecordExpiredHoursProps {
expiredHours: number | undefined;
diff --git a/packages/base/src/page/System/GlobalSetting/components/UrlAddressPrefixTips.tsx b/packages/base/src/page/System/GlobalSetting/components/UrlAddressPrefixTips.tsx
index 35ff9521f..5dce40080 100644
--- a/packages/base/src/page/System/GlobalSetting/components/UrlAddressPrefixTips.tsx
+++ b/packages/base/src/page/System/GlobalSetting/components/UrlAddressPrefixTips.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';
import { ConfigItem } from '@actiontech/dms-kit';
import { EditInput, LabelContent } from '@actiontech/dms-kit';
-import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/base/service/common';
import { PERMISSIONS, usePermission } from '@actiontech/shared/lib/features';
export interface UrlAddressPrefixTipsProps {
url: string | undefined;
diff --git a/packages/base/src/page/System/GlobalSetting/index.tsx b/packages/base/src/page/System/GlobalSetting/index.tsx
index 94b1d484e..0b096c3fd 100644
--- a/packages/base/src/page/System/GlobalSetting/index.tsx
+++ b/packages/base/src/page/System/GlobalSetting/index.tsx
@@ -4,7 +4,7 @@ import { useBoolean, useRequest } from 'ahooks';
import useHideConfigInputNode from '@actiontech/dms-kit/es/components/ConfigItem/hooks/useHideConfigInputNode';
import { DmsApi } from '@actiontech/shared/lib/api';
import { ResponseCode, ConfigFieldMapMeta } from '@actiontech/dms-kit';
-import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { IUpdateSystemVariablesReqV1 } from '@actiontech/shared/lib/api/base/service/common';
import { Spin } from 'antd';
import SystemBasicTitle from '../components/BasicTitle';
import OperationRecordExpiredHours from './components/OperationRecordExpiredHours';
diff --git a/packages/shared/lib/api/sqle/service/workflow/index.ts b/packages/shared/lib/api/sqle/service/workflow/index.ts
index 3590da223..949d99d13 100644
--- a/packages/shared/lib/api/sqle/service/workflow/index.ts
+++ b/packages/shared/lib/api/sqle/service/workflow/index.ts
@@ -32,6 +32,8 @@ import {
ITerminateMultipleTaskByWorkflowV1Params,
ITerminateMultipleTaskByWorkflowV1Return,
IGetWorkflowAttachmentParams,
+ IReExecuteTaskOnWorkflowV1Params,
+ IReExecuteTaskOnWorkflowV1Return,
ITerminateSingleTaskByWorkflowV1Params,
ITerminateSingleTaskByWorkflowV1Return,
IGetWorkflowV1Params,
@@ -299,6 +301,27 @@ class WorkflowService extends ServiceBase {
);
}
+ public reExecuteTaskOnWorkflowV1(
+ params: IReExecuteTaskOnWorkflowV1Params,
+ options?: AxiosRequestConfig
+ ) {
+ const paramsData = this.cloneDeep(params);
+ const project_name = paramsData.project_name;
+ delete paramsData.project_name;
+
+ const workflow_id = paramsData.workflow_id;
+ delete paramsData.workflow_id;
+
+ const task_id = paramsData.task_id;
+ delete paramsData.task_id;
+
+ return this.post(
+ `/v1/projects/${project_name}/workflows/${workflow_id}/tasks/${task_id}/re_execute`,
+ paramsData,
+ options
+ );
+ }
+
public terminateSingleTaskByWorkflowV1(
params: ITerminateSingleTaskByWorkflowV1Params,
options?: AxiosRequestConfig
From caa79978789416a8cb684aaa873c097de7369698 Mon Sep 17 00:00:00 2001
From: zzyangh <799463087@qq.com>
Date: Wed, 22 Oct 2025 14:53:53 +0800
Subject: [PATCH 3/4] [feature](SqlExecWorkflow): Add retry execute action for
failed task
---
packages/dms-kit/src/data/routePaths.ts | 2 +-
.../mockApi/sqle/execWorkflow/index.ts | 7 +
packages/sqle/src/data/EmitterKey.ts | 4 +-
packages/sqle/src/data/ModalName.ts | 5 +-
.../sqle/src/locale/zh-CN/execWorkflow.ts | 7 +-
.../OverviewList/action.tsx | 42 ++-
.../OverviewList/index.tsx | 26 +-
.../OverviewList/index.type.ts | 2 +-
.../RetryExecuteModal/index.tsx | 277 ++++++++++++++++++
.../RetryExecuteModal/style.ts | 17 ++
.../Common/ResultCard/FileMode.tsx | 24 +-
.../Common/ResultCard/SqlMode.tsx | 50 ++++
.../Common/ResultCard/index.type.ts | 3 +
.../SqlStatementResultTable/actions.tsx | 39 +++
.../SqlStatementResultTable/columns.tsx | 10 +-
.../Common/SqlStatementResultTable/index.tsx | 34 ++-
.../SqlStatementResultTable/index.type.ts | 7 +-
.../PaginationList/FileExecuteMode/index.tsx | 4 +-
.../PaginationList/SqlExecuteMode/index.tsx | 5 +-
.../SqlFileStatementOverview/index.tsx | 76 ++++-
.../WaterfallList/FileExecuteMode/index.tsx | 4 +-
.../WaterfallList/SqlExecuteMode/index.tsx | 4 +-
.../TaskResultList/index.type.ts | 1 +
.../hooks/useRetryExecute.ts | 51 ++++
.../components/AuditExecResultPanel/index.tsx | 42 ++-
.../hooks/useAuditExecResultPanelSetup.ts | 3 +-
.../src/page/SqlExecWorkflow/Detail/index.tsx | 1 +
.../sqle/src/store/sqlExecWorkflow/index.ts | 29 +-
28 files changed, 744 insertions(+), 32 deletions(-)
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/index.tsx
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/style.ts
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/actions.tsx
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/hooks/useRetryExecute.ts
diff --git a/packages/dms-kit/src/data/routePaths.ts b/packages/dms-kit/src/data/routePaths.ts
index 231c0d526..53c427cdb 100644
--- a/packages/dms-kit/src/data/routePaths.ts
+++ b/packages/dms-kit/src/data/routePaths.ts
@@ -207,7 +207,7 @@ export const ROUTE_PATHS = {
},
sql_files_overview: {
prefix: '/sqle/project/:projectID/exec-workflow',
- path: ':taskId/files/:fileId/sqls',
+ path: ':workflowId/task/:taskId/files/:fileId/sqls',
query: 'instance_name&schema'
}
},
diff --git a/packages/shared/lib/testUtil/mockApi/sqle/execWorkflow/index.ts b/packages/shared/lib/testUtil/mockApi/sqle/execWorkflow/index.ts
index a00b8efe5..6ae23cd8f 100644
--- a/packages/shared/lib/testUtil/mockApi/sqle/execWorkflow/index.ts
+++ b/packages/shared/lib/testUtil/mockApi/sqle/execWorkflow/index.ts
@@ -47,6 +47,7 @@ class MockWorkflowApi implements MockSpyApy {
this.createRollbackWorkflow();
this.updateTaskBackupStrategy();
this.getBackupSqlList();
+ this.reExecuteTaskOnWorkflow();
}
public getWorkflows() {
@@ -349,6 +350,12 @@ VALUES ('1234567890', 'example@email.com', '123456789012345678', '9876543210', '
);
return spy;
}
+
+ public reExecuteTaskOnWorkflow() {
+ const spy = jest.spyOn(workflow, 'reExecuteTaskOnWorkflowV1');
+ spy.mockImplementation(() => createSpySuccessResponse({}));
+ return spy;
+ }
}
export default new MockWorkflowApi();
diff --git a/packages/sqle/src/data/EmitterKey.ts b/packages/sqle/src/data/EmitterKey.ts
index 588787c75..616503426 100644
--- a/packages/sqle/src/data/EmitterKey.ts
+++ b/packages/sqle/src/data/EmitterKey.ts
@@ -41,7 +41,9 @@ enum EmitterKey {
Refresh_Sql_Exec_workflow_Audit_Result_List = 'Refresh_Sql_Exec_workflow_Audit_Result_List',
Refresh_Sql_Audit_List = 'Refresh_Sql_Audit_List',
- Refresh_Sql_Optimization_List = 'Refresh_Sql_Optimization_List'
+ Refresh_Sql_Optimization_List = 'Refresh_Sql_Optimization_List',
+
+ Sql_Retry_Execute_Done = 'Sql_Retry_Execute_Done'
}
export default EmitterKey;
diff --git a/packages/sqle/src/data/ModalName.ts b/packages/sqle/src/data/ModalName.ts
index e92d42445..8e15f0259 100644
--- a/packages/sqle/src/data/ModalName.ts
+++ b/packages/sqle/src/data/ModalName.ts
@@ -45,5 +45,8 @@ export enum ModalName {
Sql_Optimization_Result_Modal = 'SQL_OPTIMIZATION_RESULT_MODAL',
Sql_Optimization_Query_Plan_Flow_Modal = 'SQL_OPTIMIZATION_QUERY_PLAN_FLOW_MODAL',
Sql_Optimization_Query_Plan_Diff_Modal = 'SQL_OPTIMIZATION_QUERY_PLAN_DIFF_MODAL',
- Sql_Optimization_Result_Drawer = 'SQL_OPTIMIZATION_RESULT_DRAWER'
+ Sql_Optimization_Result_Drawer = 'SQL_OPTIMIZATION_RESULT_DRAWER',
+
+ // sql exec workflow
+ Sql_Exec_Workflow_Retry_Execute_Modal = 'SQL_EXEC_WORKFLOW_RETRY_EXECUTE_MODAL'
}
diff --git a/packages/sqle/src/locale/zh-CN/execWorkflow.ts b/packages/sqle/src/locale/zh-CN/execWorkflow.ts
index f7ca11a3d..c1dc215b8 100644
--- a/packages/sqle/src/locale/zh-CN/execWorkflow.ts
+++ b/packages/sqle/src/locale/zh-CN/execWorkflow.ts
@@ -259,7 +259,12 @@ export default {
cancelExecScheduled: '取消定时上线',
cancelExecScheduledTips: '取消定时上线成功',
sqlExecuteConfirmTips:
- '当前操作将立即执行该数据源上的SQL语句, 是否确认立即上线'
+ '当前操作将立即执行该数据源上的SQL语句, 是否确认立即上线',
+ retryExecute: '再次执行',
+ retryExecuteSuccess: '再次执行成功',
+ pleaseSelectSql: '请选择需要再次执行的SQL',
+ selectRetryExecuteSqlDesc: '已执行成功的SQL无法再次执行',
+ selectRetryExecuteSql: '选择再次执行的SQL'
}
},
taskResult: {},
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/action.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/action.tsx
index 830551b2f..6068f9fcb 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/action.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/action.tsx
@@ -5,7 +5,8 @@ import {
import {
WorkflowRecordResV2StatusEnum,
UpdateWorkflowScheduleReqV2NotifyTypeEnum,
- GetWorkflowTasksItemV2StatusEnum
+ GetWorkflowTasksItemV2StatusEnum,
+ WorkflowStepResV2TypeEnum
} from '@actiontech/shared/lib/api/sqle/service/common.enum';
import {
ActiontechTableActionsWithPermissions,
@@ -14,6 +15,7 @@ import {
import dayjs from 'dayjs';
import { checkTimeInWithMaintenanceTime } from '../../../../Common/utils';
import { t } from '../../../../../../locale';
+import { IWorkflowRecordResV2 } from '@actiontech/shared/lib/api/sqle/service/common';
type Params = {
currentUsername: string;
@@ -28,6 +30,8 @@ type Params = {
taskId?: string
) => Promise;
executable: boolean;
+ onRetryExecute: (record: IGetWorkflowTasksItemV2) => void;
+ workflowInfoRecord?: IWorkflowRecordResV2;
};
export const AuditResultOverviewListAction = (
@@ -40,7 +44,8 @@ export const AuditResultOverviewListAction = (
workflowStatus,
openScheduleModalAndSetCurrentTask,
scheduleTimeHandle,
- executable
+ executable,
+ workflowInfoRecord
} = params;
const unusableStatus = [
@@ -74,6 +79,24 @@ export const AuditResultOverviewListAction = (
return status === GetWorkflowTasksItemV2StatusEnum.wait_for_execution;
};
+ const enableSqlRetryExecute = (
+ maintenanceTime: IMaintenanceTimeResV1[] = []
+ ) => {
+ if (
+ !workflowInfoRecord?.workflow_step_list
+ ?.find((v) => v.type === WorkflowStepResV2TypeEnum.sql_execute)
+ ?.assignee_user_name_list?.includes(currentUsername)
+ ) {
+ return false;
+ }
+
+ if (maintenanceTime.length) {
+ return checkTimeInWithMaintenanceTime(dayjs(), maintenanceTime);
+ }
+
+ return true;
+ };
+
const enableSqlScheduleTime = (
currentStepAssigneeUsernameList: string[] = [],
status?: GetWorkflowTasksItemV2StatusEnum
@@ -110,6 +133,21 @@ export const AuditResultOverviewListAction = (
return {
width: 180,
buttons: [
+ {
+ key: 'retryExecute',
+ text: t('execWorkflow.detail.overview.table.retryExecute'),
+ buttonProps(record) {
+ return {
+ disabled: !enableSqlRetryExecute(
+ record?.instance_maintenance_times
+ ),
+ hidden:
+ record?.status !== GetWorkflowTasksItemV2StatusEnum.exec_failed,
+ onClick: () => params.onRetryExecute(record!)
+ };
+ },
+ permissions: PERMISSIONS.ACTIONS.SQLE.SQL_EXEC_WORKFLOW.EXEC_TASK
+ },
{
key: 'terminate',
text: t('execWorkflow.detail.operator.terminate'),
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.tsx
index 5fdd06fbb..0a49816f2 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.tsx
@@ -9,6 +9,13 @@ import { ActiontechTable } from '@actiontech/dms-kit/es/components/ActiontechTab
import { auditResultOverviewColumn } from './column';
import { WorkflowOverviewListProps } from './index.type';
import { AuditResultOverviewListAction } from './action';
+import {
+ updateRetryExecuteData,
+ updateSqlExecWorkflowModalStatus
+} from '../../../../../../store/sqlExecWorkflow/index';
+import { ModalName } from '../../../../../../data/ModalName';
+import { useDispatch } from 'react-redux';
+import { IGetWorkflowTasksItemV2 } from '@actiontech/shared/lib/api/sqle/service/common';
const WorkflowOverviewList: React.FC = ({
workflowInfo,
@@ -22,6 +29,7 @@ const WorkflowOverviewList: React.FC = ({
const { username } = useCurrentUser();
const { projectName } = useCurrentProject();
const { parse2TableActionPermissions } = usePermission();
+ const dispatch = useDispatch();
const {
contextHolder,
scheduleModalVisible,
@@ -38,6 +46,20 @@ const WorkflowOverviewList: React.FC = ({
refreshOverview: refreshOverviewAction
});
+ const onRetryExecute = (record: IGetWorkflowTasksItemV2) => {
+ dispatch(
+ updateRetryExecuteData({
+ taskId: record.task_id?.toString() ?? ''
+ })
+ );
+ dispatch(
+ updateSqlExecWorkflowModalStatus({
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: true
+ })
+ );
+ };
+
return (
<>
{contextHolder}
@@ -63,7 +85,9 @@ const WorkflowOverviewList: React.FC = ({
openScheduleModalAndSetCurrentTask,
currentUsername: username,
workflowStatus: workflowInfo?.record?.status,
- executable: !!workflowInfo?.record?.executable
+ executable: !!workflowInfo?.record?.executable,
+ onRetryExecute,
+ workflowInfoRecord: workflowInfo?.record
})
)}
onRow={(record) => {
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.type.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.type.ts
index 9454f1a8d..afbe12957 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.type.ts
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/index.type.ts
@@ -2,7 +2,7 @@ import { AuditExecResultPanelProps } from '../index.type';
export type WorkflowOverviewListProps = Omit<
AuditExecResultPanelProps,
- 'taskInfos' | 'activeTabKey'
+ 'taskInfos' | 'activeTabKey' | 'refreshTaskWithTaskId'
>;
export type WorkflowOverviewListActionsParams = {
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/index.tsx
new file mode 100644
index 000000000..179e7b293
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/index.tsx
@@ -0,0 +1,277 @@
+import {
+ BasicTable,
+ useTableRequestParams,
+ ResponseCode,
+ BasicButton,
+ BasicTypographyEllipsis,
+ ROUTE_PATHS
+} from '@actiontech/dms-kit';
+import { useTranslation } from 'react-i18next';
+import { useRequest } from 'ahooks';
+import task from '@actiontech/shared/lib/api/sqle/service/task';
+import workflow from '@actiontech/shared/lib/api/sqle/service/workflow';
+import { getAuditTaskSQLsV2FilterExecStatusEnum } from '@actiontech/shared/lib/api/sqle/service/task/index.enum';
+import { IAuditTaskSQLResV2 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { IGetAuditTaskSQLsV2Params } from '@actiontech/shared/lib/api/sqle/service/task/index.d';
+import { useEffect, useState } from 'react';
+import { SQLRenderer, useTypedParams } from '@actiontech/shared';
+import { Space, message } from 'antd';
+import { useCurrentProject } from '@actiontech/shared/lib/features';
+import {
+ RetryExecuteModalStyleWrapper,
+ RetryExecuteModalTitleDescStyleWrapper
+} from './style';
+import ExecStatusTag from '../TaskResultList/Common/ResultCard/components/ExecStatusTag';
+import { useSelector, useDispatch } from 'react-redux';
+import { IReduxState } from '../../../../../../store';
+import { ModalName } from '../../../../../../data/ModalName';
+import { updateSqlExecWorkflowModalStatus } from '../../../../../../store/sqlExecWorkflow/index';
+import EmitterKey from '../../../../../../data/EmitterKey';
+import EventEmitter from '../../../../../../utils/EventEmitter';
+
+const RetryExecuteModal = () => {
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
+ const urlParams =
+ useTypedParams();
+
+ const { taskId, execSqlId, pageIndex, pageSize, visible } = useSelector(
+ (state: IReduxState) => ({
+ taskId: state.sqlExecWorkflow.retryExecuteData?.taskId ?? '',
+ execSqlId: state.sqlExecWorkflow.retryExecuteData?.execSqlId,
+ pageIndex: state.sqlExecWorkflow.retryExecuteData?.pageIndex,
+ pageSize: state.sqlExecWorkflow.retryExecuteData?.pageSize,
+ visible:
+ !!state.sqlExecWorkflow.modalStatus[
+ ModalName.Sql_Exec_Workflow_Retry_Execute_Modal
+ ]
+ })
+ );
+
+ const { projectName } = useCurrentProject();
+
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ const [allSelectedKeys, setAllSelectedKeys] = useState([]);
+
+ const [messageApi, contextHolder] = message.useMessage();
+
+ const { tableChange, pagination } = useTableRequestParams<
+ IAuditTaskSQLResV2,
+ IGetAuditTaskSQLsV2Params
+ >();
+
+ const { data, loading } = useRequest(
+ () => {
+ return task
+ .getAuditTaskSQLsV2({
+ page_index: `${pagination.page_index}`,
+ page_size: `${pagination.page_size}`,
+ task_id: taskId
+ })
+ .then((res) => {
+ if (res.data.code === ResponseCode.SUCCESS) {
+ return res.data;
+ }
+ });
+ },
+ {
+ ready: visible && !!taskId,
+ refreshDeps: [taskId, pagination],
+ onSuccess: (result) => {
+ const currentPageKeys =
+ result?.data?.map((item) => item.exec_sql_id) || [];
+ const currentPageSelectedKeys = allSelectedKeys.filter((key) =>
+ currentPageKeys.includes(Number(key))
+ );
+ setSelectedRowKeys(currentPageSelectedKeys);
+ }
+ }
+ );
+
+ const { run: retryExecute, loading: retryExecuteLoading } = useRequest(
+ () => {
+ return workflow
+ .reExecuteTaskOnWorkflowV1({
+ project_name: projectName,
+ workflow_id: urlParams.workflowId ?? '',
+ task_id: taskId,
+ exec_sql_ids: allSelectedKeys as number[]
+ })
+ .then((res) => {
+ if (res.data.code === ResponseCode.SUCCESS) {
+ messageApi.success(
+ t('execWorkflow.detail.overview.table.retryExecuteSuccess')
+ );
+ handleClose();
+ EventEmitter.emit(EmitterKey.Sql_Retry_Execute_Done, taskId);
+ }
+ });
+ },
+ {
+ manual: true
+ }
+ );
+
+ const handleClose = () => {
+ setSelectedRowKeys([]);
+ setAllSelectedKeys([]);
+ tableChange(
+ {
+ current: 1,
+ pageSize: 20
+ },
+ {},
+ {},
+ {
+ action: 'paginate',
+ currentDataSource: []
+ }
+ );
+ dispatch(
+ updateSqlExecWorkflowModalStatus({
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: false
+ })
+ );
+ };
+
+ useEffect(() => {
+ if (pageIndex && pageSize && visible) {
+ tableChange(
+ {
+ current: pageIndex,
+ pageSize: pageSize
+ },
+ {},
+ {},
+ {
+ action: 'paginate',
+ currentDataSource: []
+ }
+ );
+ }
+
+ if (execSqlId && !allSelectedKeys.length && visible) {
+ setAllSelectedKeys([execSqlId]);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [pageIndex, pageSize, visible, tableChange, execSqlId]);
+
+ const handleRetryExecute = () => {
+ if (!allSelectedKeys.length) {
+ messageApi.error(t('execWorkflow.detail.overview.table.pleaseSelectSql'));
+ return;
+ }
+ retryExecute();
+ };
+
+ return (
+
+ {t('execWorkflow.detail.overview.table.selectRetryExecuteSql')}
+
+ {t('execWorkflow.detail.overview.table.selectRetryExecuteSqlDesc')}
+
+
+ }
+ footer={
+
+ {t('common.cancel')}
+
+ {t('common.submit')}
+
+
+ }
+ closable={false}
+ centered
+ >
+ {contextHolder}
+ {
+ if (!sql) return null;
+ return (
+
+ );
+ }
+ },
+ {
+ dataIndex: 'exec_status',
+ width: 110,
+ title: () => t('execWorkflow.audit.table.execStatus'),
+ render: (status) => {
+ return ;
+ }
+ },
+ {
+ dataIndex: 'exec_result',
+ className: 'ellipsis-column-width',
+ title: () => t('execWorkflow.audit.table.execResult'),
+ render: (result) => {
+ return result ? (
+
+ ) : (
+ '-'
+ );
+ }
+ }
+ ]}
+ dataSource={data?.data}
+ onChange={tableChange}
+ pagination={{
+ total: data?.total_nums ?? 0,
+ current: pagination.page_index,
+ pageSize: pagination.page_size
+ }}
+ loading={loading || retryExecuteLoading}
+ rowSelection={{
+ selectedRowKeys,
+ onChange: (selectedKeys) => {
+ setSelectedRowKeys(selectedKeys);
+
+ const currentPageKeys =
+ data?.data?.map((item) => item.exec_sql_id) || [];
+
+ const otherPageSelectedKeys = allSelectedKeys.filter(
+ (key) => !currentPageKeys.includes(Number(key))
+ );
+ const newAllSelectedKeys = [
+ ...otherPageSelectedKeys,
+ ...selectedKeys
+ ];
+ setAllSelectedKeys(newAllSelectedKeys);
+ },
+ columnWidth: 60,
+ getCheckboxProps: (record) => {
+ return {
+ disabled:
+ record.exec_status ===
+ getAuditTaskSQLsV2FilterExecStatusEnum.succeeded
+ };
+ }
+ }}
+ scroll={{ y: '500px' }}
+ />
+
+ );
+};
+
+export default RetryExecuteModal;
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/style.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/style.ts
new file mode 100644
index 000000000..e44ccf102
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/style.ts
@@ -0,0 +1,17 @@
+import { styled } from '@mui/material';
+import { BasicModal } from '@actiontech/dms-kit';
+import { Typography } from 'antd';
+
+export const RetryExecuteModalStyleWrapper = styled(BasicModal)`
+ & .ant-modal-body {
+ padding: 0 !important;
+
+ .ant-table-wrapper.actiontech-table-namespace {
+ padding-bottom: 0;
+ }
+ }
+`;
+
+export const RetryExecuteModalTitleDescStyleWrapper = styled(Typography.Text)`
+ font-weight: 100;
+`;
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/FileMode.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/FileMode.tsx
index c21ebadbc..5ee00f416 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/FileMode.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/FileMode.tsx
@@ -13,14 +13,17 @@ import SqlStatementResultTable from '../SqlStatementResultTable';
import { Trans } from 'react-i18next';
import { TasksResultCardStyleWrapper } from './style';
import { SqlFileOutlined } from '@actiontech/icons';
-import { TypedLink } from '@actiontech/shared';
+import { TypedLink, useTypedParams } from '@actiontech/shared';
import { ROUTE_PATHS } from '@actiontech/dms-kit';
const FileMode: React.FC = ({
taskId,
projectID,
+ enableRetryExecute,
...props
}) => {
+ const { workflowId } =
+ useTypedParams();
const auditResult = useMemo(() => {
const res: IAuditResult[] = [];
@@ -90,7 +93,12 @@ const FileMode: React.FC = ({
{
e.stopPropagation();
}}
@@ -123,7 +131,12 @@ const FileMode: React.FC = ({
= ({
}
+ enableSqlRetryExecute={!!enableRetryExecute}
instanceName={props.instanceName}
schema={props.schema}
/>
@@ -150,7 +164,9 @@ const FileMode: React.FC = ({
requestErrorMessage,
taskId,
props.instanceName,
- props.schema
+ props.schema,
+ enableRetryExecute,
+ workflowId
]);
return (
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/SqlMode.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/SqlMode.tsx
index 597d2168c..c1fb8e50a 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/SqlMode.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/SqlMode.tsx
@@ -34,15 +34,29 @@ import RollbackWorkflowEntry from './components/RollbackWorkflowEntry';
import { formatterSQL } from '@actiontech/dms-kit';
import AuditExceptionTree from './components/AuditExceptionTree';
import { IAuditResultItem } from '../../../../../../../../components/ReportDrawer/index.type';
+import { useDispatch } from 'react-redux';
+import {
+ updateRetryExecuteData,
+ updateSqlExecWorkflowModalStatus
+} from '../../../../../../../../store/sqlExecWorkflow/index';
+import { ModalName } from '../../../../../../../../data/ModalName';
+import {
+ PermissionControl,
+ PERMISSIONS
+} from '@actiontech/shared/lib/features';
+
const SqlMode: React.FC = ({
projectID,
taskId,
onUpdateDescription,
+ pagination,
+ enableRetryExecute,
...props
}) => {
const { t } = useTranslation();
const [messageApi, contextHolder] = message.useMessage();
const { sqleTheme } = useThemeStyleData();
+ const dispatch = useDispatch();
const [loading, { setTrue: updateDescPending, setFalse: updateDescDone }] =
useBoolean();
const [currentContentKey, setCurrentContentKey] =
@@ -82,6 +96,24 @@ const SqlMode: React.FC = ({
})
);
};
+
+ const onRetryExecute = () => {
+ dispatch(
+ updateSqlExecWorkflowModalStatus({
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: true
+ })
+ );
+ dispatch(
+ updateRetryExecuteData({
+ taskId: taskId ?? '',
+ execSqlId: props.exec_sql_id ?? 0,
+ pageIndex: pagination?.page_index,
+ pageSize: pagination?.page_size
+ })
+ );
+ };
+
const updateSqlDescribe = (sqlDescribe: string) => {
updateDescPending();
task
@@ -152,6 +184,24 @@ const SqlMode: React.FC = ({
/>
{/* #endif */}
+
+
+
+ {t('execWorkflow.detail.overview.table.retryExecute')}
+
+
+
{t('execWorkflow.audit.copyExecSql')}
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/index.type.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/index.type.ts
index 66bb23ae0..0d775f757 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/index.type.ts
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/index.type.ts
@@ -7,9 +7,11 @@ import {
WorkflowResV2ExecModeEnum,
AuditTaskResV1StatusEnum
} from '@actiontech/shared/lib/api/sqle/service/common.enum';
+import { TablePagination } from '@actiontech/dms-kit/es/components/ActiontechTable';
type BaseProps = {
taskId: string;
+ enableRetryExecute?: boolean;
};
export type SqlExecuteResultCardProps = BaseProps &
@@ -22,6 +24,7 @@ export type SqlExecuteResultCardProps = BaseProps &
taskStatus?: AuditTaskResV1StatusEnum;
instanceName?: string;
schema?: string;
+ pagination?: TablePagination;
};
export type FileExecuteResultCardProps = BaseProps &
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/actions.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/actions.tsx
new file mode 100644
index 000000000..0815009f5
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/actions.tsx
@@ -0,0 +1,39 @@
+import {
+ ActiontechTableActionsWithPermissions,
+ PERMISSIONS
+} from '@actiontech/shared/lib/features';
+import { IAuditTaskSQLResV2 } from '@actiontech/shared/lib/api/sqle/service/common';
+import { t } from '../../../../../../../../locale';
+import { getAuditTaskSQLsV2FilterExecStatusEnum } from '@actiontech/shared/lib/api/sqle/service/task/index.enum';
+
+type Params = {
+ enableSqlRetryExecute: boolean;
+ onRetryExecute: (record: IAuditTaskSQLResV2) => void;
+};
+
+export const SQLStatementResultActions = (
+ params: Params
+): ActiontechTableActionsWithPermissions => {
+ return {
+ width: 100,
+ buttons: [
+ {
+ key: 'retryExecute',
+ text: t('execWorkflow.detail.overview.table.retryExecute'),
+ buttonProps(record) {
+ return {
+ disabled: !params.enableSqlRetryExecute,
+ hidden: ![
+ getAuditTaskSQLsV2FilterExecStatusEnum.failed,
+ getAuditTaskSQLsV2FilterExecStatusEnum.initialized
+ ].includes(
+ record?.exec_status as getAuditTaskSQLsV2FilterExecStatusEnum
+ ),
+ onClick: () => params.onRetryExecute(record!)
+ };
+ },
+ permissions: PERMISSIONS.ACTIONS.SQLE.SQL_EXEC_WORKFLOW.EXEC_TASK
+ }
+ ]
+ };
+};
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/columns.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/columns.tsx
index f32802bde..2fb4388f4 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/columns.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/columns.tsx
@@ -2,14 +2,14 @@ import { IAuditTaskSQLResV2 } from '@actiontech/shared/lib/api/sqle/service/comm
import ExecStatusTag from '../ResultCard/components/ExecStatusTag';
import { getAuditTaskSQLsV2FilterExecStatusEnum } from '@actiontech/shared/lib/api/sqle/service/task/index.enum';
import { SQLRenderer } from '@actiontech/shared';
-import { BasicTableProps } from '@actiontech/dms-kit/es/components/BasicTable/BasicTable.types';
import { BasicToolTip } from '@actiontech/dms-kit';
import { t } from '../../../../../../../../locale';
import ResultIconRender from '../../../../../../../../components/AuditResultMessage/ResultIconRender';
+import { ActiontechTableColumn } from '@actiontech/dms-kit/es/components/ActiontechTable';
export const SQLStatementResultColumns = (
onClickAuditResult: (record: IAuditTaskSQLResV2) => void
-): BasicTableProps['columns'] => {
+): ActiontechTableColumn => {
return [
{
dataIndex: 'number',
@@ -56,10 +56,12 @@ export const SQLStatementResultColumns = (
dataIndex: 'exec_status',
title: () => t('audit.table.execResult'),
className: 'exec-status-column',
- render: (status: getAuditTaskSQLsV2FilterExecStatusEnum, record) => {
+ render: (status, record) => {
return (
-
+
);
}
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/index.tsx
index 3373812d9..9ed0de7c0 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/SqlStatementResultTable/index.tsx
@@ -1,4 +1,4 @@
-import { BasicTable } from '@actiontech/dms-kit';
+import { ActiontechTable } from '@actiontech/dms-kit';
import { SqlStatementResultTableProps } from './index.type';
import { SQLStatementResultColumns } from './columns';
import { useBoolean } from 'ahooks';
@@ -9,6 +9,13 @@ import AuditResultDrawer from '../../../../../../Common/AuditResultList/Table/Au
import { useCurrentProject } from '@actiontech/shared/lib/features';
import { parse2ReactRouterPath } from '@actiontech/shared/lib/components/TypedRouter/utils';
import { ROUTE_PATHS } from '@actiontech/dms-kit';
+import { SQLStatementResultActions } from './actions';
+import { usePermission } from '@actiontech/shared/lib/features';
+import { useDispatch } from 'react-redux';
+import { updateRetryExecuteData } from '../../../../../../../../store/sqlExecWorkflow';
+import { updateSqlExecWorkflowModalStatus } from '../../../../../../../../store/sqlExecWorkflow';
+import { ModalName } from '../../../../../../../../data/ModalName';
+
const SqlStatementResultTable: React.FC = (
props
) => {
@@ -16,9 +23,11 @@ const SqlStatementResultTable: React.FC = (
auditResultDrawerVisibility,
{ setFalse: closeAuditResultDrawer, setTrue: openAuditResultDrawer }
] = useBoolean();
+ const dispatch = useDispatch();
const { projectID } = useCurrentProject();
const [currentAuditResultRecord, setCurrentAuditResultRecord] =
useState();
+ const { parse2TableActionPermissions } = usePermission();
const onClickAuditResult = (record: IAuditTaskSQLResV2) => {
openAuditResultDrawer();
setCurrentAuditResultRecord(record);
@@ -42,12 +51,33 @@ const SqlStatementResultTable: React.FC = (
})
);
};
+
+ const onRetryExecute = () => {
+ dispatch(
+ updateRetryExecuteData({
+ taskId: props.taskId ?? ''
+ })
+ );
+ dispatch(
+ updateSqlExecWorkflowModalStatus({
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: true
+ })
+ );
+ };
+
return (
-
& { taskId?: string; instanceName?: string; schema?: string };
+> & {
+ taskId?: string;
+ instanceName?: string;
+ schema?: string;
+ enableSqlRetryExecute: boolean;
+};
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/FileExecuteMode/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/FileExecuteMode/index.tsx
index 981bc70ef..55ad5bdd6 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/FileExecuteMode/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/FileExecuteMode/index.tsx
@@ -25,7 +25,8 @@ const FileExecuteMode: React.FC = ({
auditResultActiveKey,
assigneeUserNames,
instanceName,
- schema
+ schema,
+ enableRetryExecute
}) => {
const { t } = useTranslation();
@@ -93,6 +94,7 @@ const FileExecuteMode: React.FC = ({
executeMode={WorkflowResV2ExecModeEnum.sql_file}
instanceName={instanceName}
schema={schema}
+ enableRetryExecute={enableRetryExecute}
/>
);
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/SqlExecuteMode/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/SqlExecuteMode/index.tsx
index 529601fc6..a8e7b48ae 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/SqlExecuteMode/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/PaginationList/SqlExecuteMode/index.tsx
@@ -24,7 +24,8 @@ const SqlExecuteMode: React.FC = ({
enableBackup,
taskStatus,
instanceName,
- schema
+ schema,
+ enableRetryExecute
}) => {
const { t } = useTranslation();
@@ -91,6 +92,8 @@ const SqlExecuteMode: React.FC = ({
taskStatus={taskStatus}
instanceName={instanceName}
schema={schema}
+ pagination={pagination}
+ enableRetryExecute={enableRetryExecute}
/>
);
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx
index b5d6c2369..287e3a463 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx
@@ -38,13 +38,27 @@ import DownloadRecord from '../../../../../Common/DownloadRecord';
import { AuditResultFilterContainerStyleWrapper } from '../../../../../Common/AuditResultFilterContainer/style';
import { LeftArrowOutlined, SqlFileOutlined } from '@actiontech/icons';
import { ROUTE_PATHS } from '@actiontech/dms-kit';
+import { ModalName } from '../../../../../../../data/ModalName';
+import EmitterKey from '../../../../../../../data/EmitterKey';
+import EventEmitter from '../../../../../../../utils/EventEmitter';
+import { initSqlExecWorkflowModalStatus } from '../../../../../../../store/sqlExecWorkflow';
+import { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
+import RetryExecuteModal from '../../RetryExecuteModal';
+import workflow from '@actiontech/shared/lib/api/sqle/service/workflow';
+import { useCurrentProject } from '@actiontech/shared/lib/features';
+import useRetryExecute from '../../hooks/useRetryExecute';
+
const SqlFileStatementOverview: React.FC = () => {
const { t } = useTranslation();
- const { taskId, fileId } =
+ const dispatch = useDispatch();
+ const { taskId, fileId, workflowId } =
useTypedParams<
typeof ROUTE_PATHS.SQLE.SQL_EXEC_WORKFLOW.sql_files_overview
>();
+ const { projectName } = useCurrentProject();
+
const extractQuery = useTypedQuery();
const navigate = useTypedNavigate();
@@ -65,6 +79,37 @@ const SqlFileStatementOverview: React.FC = () => {
updateTableFilterInfo,
AuditTaskExtraFilterMeta()
);
+
+ const { data: workflowInfo, loading: getWorkflowLoading } = useRequest(
+ () =>
+ workflow
+ .getWorkflowV2({
+ project_name: projectName,
+ workflow_id: workflowId ?? ''
+ })
+ .then((res) => res.data.data),
+ {
+ ready: !!workflowId
+ }
+ );
+
+ const { loading: taskListLoading, data: currentTask } = useRequest(
+ () =>
+ workflow
+ .getSummaryOfInstanceTasksV2({
+ workflow_id: workflowId ?? '',
+ project_name: projectName
+ })
+ .then((res) => {
+ if (res.data.code === ResponseCode.SUCCESS) {
+ return res.data.data?.find((i) => i.task_id?.toString() === taskId);
+ }
+ }),
+ {
+ ready: !!workflowId
+ }
+ );
+
const { data: currentFileOverview } = useRequest(() =>
task
.getAuditFileExecStatistic({
@@ -77,7 +122,7 @@ const SqlFileStatementOverview: React.FC = () => {
}
})
);
- const { data, loading } = useRequest(
+ const { data, loading, refresh } = useRequest(
() =>
handleTableRequestError(
task.getAuditTaskSQLsV2({
@@ -104,6 +149,29 @@ const SqlFileStatementOverview: React.FC = () => {
ROUTE_PATHS.SQLE.SQL_EXEC_WORKFLOW.sql_files_overview
);
+ useEffect(() => {
+ dispatch(
+ initSqlExecWorkflowModalStatus({
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: false
+ }
+ })
+ );
+ }, [dispatch]);
+
+ const { enableRetryExecute } = useRetryExecute({
+ currentTask,
+ workflowInfo
+ });
+
+ useEffect(() => {
+ const { unsubscribe } = EventEmitter.subscribe(
+ EmitterKey.Sql_Retry_Execute_Done,
+ refresh
+ );
+ return unsubscribe;
+ }, [refresh]);
+
return (
{
{
isPaginationFixed
instanceName={searchParams?.instance_name ?? ''}
schema={searchParams?.schema ?? ''}
+ enableSqlRetryExecute={enableRetryExecute}
/>
+
);
};
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/FileExecuteMode/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/FileExecuteMode/index.tsx
index 97b50aa7b..e3c60e261 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/FileExecuteMode/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/FileExecuteMode/index.tsx
@@ -25,7 +25,8 @@ const FileExecuteMode: React.FC = ({
auditResultActiveKey,
assigneeUserNames,
instanceName,
- schema
+ schema,
+ enableRetryExecute
}) => {
const { projectID } = useCurrentProject();
const scrollPageNumber = useRef(0);
@@ -119,6 +120,7 @@ const FileExecuteMode: React.FC = ({
taskId={taskId}
instanceName={instanceName}
schema={schema}
+ enableRetryExecute={enableRetryExecute}
/>
);
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/SqlExecuteMode/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/SqlExecuteMode/index.tsx
index e3fb9649c..d7989506c 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/SqlExecuteMode/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/WaterfallList/SqlExecuteMode/index.tsx
@@ -25,7 +25,8 @@ const SqlExecuteMode: React.FC = ({
enableBackup,
taskStatus,
instanceName,
- schema
+ schema,
+ enableRetryExecute
}) => {
const { projectID } = useCurrentProject();
const scrollPageNumber = useRef(0);
@@ -177,6 +178,7 @@ const SqlExecuteMode: React.FC = ({
taskStatus={taskStatus}
instanceName={instanceName}
schema={schema}
+ enableRetryExecute={enableRetryExecute}
/>
);
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/index.type.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/index.type.ts
index f974fab78..d6eb60a36 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/index.type.ts
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/index.type.ts
@@ -23,4 +23,5 @@ export type TasksResultListBaseProps = {
taskStatus?: AuditTaskResV1StatusEnum;
instanceName?: string;
schema?: string;
+ enableRetryExecute: boolean;
};
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/hooks/useRetryExecute.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/hooks/useRetryExecute.ts
new file mode 100644
index 000000000..43d57034d
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/hooks/useRetryExecute.ts
@@ -0,0 +1,51 @@
+import {
+ IGetWorkflowTasksItemV2,
+ IWorkflowResV2
+} from '@actiontech/shared/lib/api/sqle/service/common';
+import { useMemo } from 'react';
+import {
+ GetWorkflowTasksItemV2StatusEnum,
+ WorkflowStepResV2TypeEnum
+} from '@actiontech/shared/lib/api/sqle/service/common.enum';
+import { checkTimeInWithMaintenanceTime } from '../../../../Common/utils';
+import dayjs from 'dayjs';
+import { useCurrentUser } from '@actiontech/shared/lib/features';
+
+interface IUseRetryExecuteParams {
+ currentTask?: IGetWorkflowTasksItemV2;
+ workflowInfo?: IWorkflowResV2;
+}
+
+const useRetryExecute = (params: IUseRetryExecuteParams) => {
+ const { currentTask, workflowInfo } = params;
+
+ const { username } = useCurrentUser();
+
+ const enableRetryExecute = useMemo(() => {
+ if (currentTask?.status !== GetWorkflowTasksItemV2StatusEnum.exec_failed) {
+ return false;
+ }
+ if (
+ !workflowInfo?.record?.workflow_step_list
+ ?.find((v) => v.type === WorkflowStepResV2TypeEnum.sql_execute)
+ ?.assignee_user_name_list?.includes(username)
+ ) {
+ return false;
+ }
+
+ if (currentTask?.instance_maintenance_times?.length) {
+ return checkTimeInWithMaintenanceTime(
+ dayjs(),
+ currentTask?.instance_maintenance_times
+ );
+ }
+
+ return true;
+ }, [currentTask, workflowInfo, username]);
+
+ return {
+ enableRetryExecute
+ };
+};
+
+export default useRetryExecute;
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx
index 552b2361a..d27310fcd 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx
@@ -18,7 +18,7 @@ import {
import { ToggleButtonStyleWrapper } from '../../../Common/style';
import DownloadRecord from '../../../Common/DownloadRecord';
import AuditResultFilterContainer from '../../../Common/AuditResultFilterContainer';
-import { useMemo } from 'react';
+import { useEffect, useMemo } from 'react';
import { getAuditTaskSQLsV2FilterExecStatusEnum } from '@actiontech/shared/lib/api/sqle/service/task/index.enum';
import {
execStatusDictionary,
@@ -28,12 +28,21 @@ import TaskResultList from './TaskResultList';
import useTaskResultSetup from './hooks/useTaskResultSetup';
import ListLayoutSelector from './ListLayoutSelector';
import WorkflowOverviewList from './OverviewList';
+import RetryExecuteModal from './RetryExecuteModal';
+import { useDispatch } from 'react-redux';
+import { initSqlExecWorkflowModalStatus } from '../../../../../store/sqlExecWorkflow/index';
+import { ModalName } from '../../../../../data/ModalName';
+import EmitterKey from '../../../../../data/EmitterKey';
+import EventEmitter from '../../../../../utils/EventEmitter';
+import useRetryExecute from './hooks/useRetryExecute';
+
const AuditExecResultPanel: React.FC = ({
activeTabKey,
taskInfos,
...resetProps
}) => {
const { t } = useTranslation();
+ const dispatch = useDispatch();
const { getAuditLevelStatusSelectOptionValues } = useStaticStatus();
const {
noDuplicate,
@@ -78,6 +87,35 @@ const AuditExecResultPanel: React.FC = ({
resetProps.workflowInfo?.record?.current_step_number,
resetProps.workflowInfo?.record?.workflow_step_list
]);
+
+ const { enableRetryExecute } = useRetryExecute({
+ currentTask: resetProps.overviewList?.list?.find(
+ (v) => v.task_id?.toString() === activeTabKey
+ ),
+ workflowInfo: resetProps.workflowInfo
+ });
+
+ useEffect(() => {
+ dispatch(
+ initSqlExecWorkflowModalStatus({
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: false
+ }
+ })
+ );
+ }, [dispatch]);
+
+ useEffect(() => {
+ const { unsubscribe } = EventEmitter.subscribe(
+ EmitterKey.Sql_Retry_Execute_Done,
+ () => {
+ resetProps.refreshWorkflow();
+ resetProps.refreshOverviewAction();
+ }
+ );
+ return unsubscribe;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [resetProps.refreshWorkflow, resetProps.refreshOverviewAction]);
return (
{t('audit.result')}
@@ -203,8 +241,10 @@ const AuditExecResultPanel: React.FC = ({
taskStatus={currentTask?.status}
instanceName={currentTask?.instance_name}
schema={currentTask?.instance_schema}
+ enableRetryExecute={enableRetryExecute}
/>
+
);
};
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/hooks/useAuditExecResultPanelSetup.ts b/packages/sqle/src/page/SqlExecWorkflow/Detail/hooks/useAuditExecResultPanelSetup.ts
index 7f74bd1fe..b6bb1c9a2 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/hooks/useAuditExecResultPanelSetup.ts
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/hooks/useAuditExecResultPanelSetup.ts
@@ -85,8 +85,7 @@ const useAuditExecResultPanelSetup = () => {
})
),
{
- ready:
- !!urlParams.workflowId && activeTabKey === WORKFLOW_OVERVIEW_TAB_KEY,
+ ready: !!urlParams.workflowId,
onSuccess: ({ list }) => {
getOverviewListSuccessHandle?.(list ?? []);
// 接口404时,错误重试次数 pollingErrorRetryCount无效 导致重复抛出404错误提示。所以如果当list不存在时也停止轮询
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/index.tsx
index 66140c34f..1832a14a3 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/index.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/index.tsx
@@ -21,6 +21,7 @@ import ModifySqlStatement from './components/ModifySqlStatement';
import useAuditExecResultPanelSetup from './hooks/useAuditExecResultPanelSetup';
import AuditExecResultPanel from './components/AuditExecResultPanel';
import SqlRollback from './components/SqlRollback';
+
const SqlWorkflowDetail: React.FC = () => {
const { username } = useCurrentUser();
const [
diff --git a/packages/sqle/src/store/sqlExecWorkflow/index.ts b/packages/sqle/src/store/sqlExecWorkflow/index.ts
index 3b2510c57..97e92f537 100644
--- a/packages/sqle/src/store/sqlExecWorkflow/index.ts
+++ b/packages/sqle/src/store/sqlExecWorkflow/index.ts
@@ -4,19 +4,30 @@ import {
WorkflowBaseInfoFormFields
} from '../../page/SqlExecWorkflow/Create/index.type';
import { IVersionStageInstance } from '@actiontech/shared/lib/api/sqle/service/common';
+import { commonModalReducer } from '../common';
+import { ModalStatus } from '@actiontech/shared/lib/types/common.type';
type SqlExecWorkflowReduxState = {
clonedExecWorkflowSqlAuditInfo: SqlAuditInfoFormFields | null;
clonedExecWorkflowBaseInfo: WorkflowBaseInfoFormFields | null;
versionFirstStageInstances: IVersionStageInstance[] | null;
workflowRollbackSqlIds: number[] | null;
+ retryExecuteData: {
+ taskId: string;
+ execSqlId?: number;
+ pageIndex?: number;
+ pageSize?: number;
+ } | null;
+ modalStatus: ModalStatus;
};
const initialState: SqlExecWorkflowReduxState = {
clonedExecWorkflowSqlAuditInfo: null,
clonedExecWorkflowBaseInfo: null,
versionFirstStageInstances: null,
- workflowRollbackSqlIds: null
+ workflowRollbackSqlIds: null,
+ retryExecuteData: null,
+ modalStatus: {}
};
const sqlExecWorkflow = createSlice({
name: 'sqlExecWorkflow',
@@ -53,14 +64,26 @@ const sqlExecWorkflow = createSlice({
}>
) => {
state.workflowRollbackSqlIds = workflowRollbackSqlIds;
- }
+ },
+ updateRetryExecuteData: (
+ state,
+ {
+ payload: data
+ }: PayloadAction
+ ) => {
+ state.retryExecuteData = data;
+ },
+ ...commonModalReducer()
}
});
export const {
updateClonedExecWorkflowSqlAuditInfo,
updateClonedExecWorkflowBaseInfo,
updateVersionFirstStageInstances,
- updateWorkflowRollbackSqlIds
+ updateWorkflowRollbackSqlIds,
+ updateRetryExecuteData,
+ initModalStatus: initSqlExecWorkflowModalStatus,
+ updateModalStatus: updateSqlExecWorkflowModalStatus
} = sqlExecWorkflow.actions;
export default sqlExecWorkflow.reducer;
From dc1f8b26460e0944e47e57b20445ca8540e114d4 Mon Sep 17 00:00:00 2001
From: zzyangh <799463087@qq.com>
Date: Wed, 22 Oct 2025 15:13:33 +0800
Subject: [PATCH 4/4] [test]: Update unit tests
---
.../__snapshots__/router.base.test.tsx.snap | 2 +-
.../router.ce.base.test.tsx.snap | 2 +-
.../src/router/test/router.ce.sqle.test.tsx | 2 +-
.../base/src/router/test/router.sqle.test.tsx | 2 +-
.../__snapshots__/index.test.tsx.snap | 83 ++
.../Detail/__tests__/index.test.tsx | 23 +-
.../__snapshots__/index.test.tsx.snap | 56 +
.../OverviewList/__tests__/index.test.tsx | 163 ++-
.../__snapshots__/index.test.tsx.snap | 495 +++++++
.../__tests__/index.test.tsx | 222 +++
.../ResultCard/__tests__/FileMode.test.tsx | 10 +
.../ResultCard/__tests__/SqlMode.test.tsx | 74 +
.../__snapshots__/FileMode.test.tsx.snap | 52 +-
.../__snapshots__/SqlMode.ce.test.tsx.snap | 4 +
.../__snapshots__/SqlMode.test.tsx.snap | 465 +++++++
.../__snapshots__/index.test.tsx.snap | 445 +++++-
.../__tests__/index.test.tsx | 83 +-
.../__snapshots__/index.test.tsx.snap | 12 +-
.../FileExecuteMode/__tests__/index.test.tsx | 1 +
.../__snapshots__/index.test.tsx.snap | 13 +
.../SqlExecuteMode/__tests__/index.test.tsx | 12 +-
.../__snapshots__/index.test.tsx.snap | 4 +
.../PaginationList/__tests__/index.test.tsx | 3 +-
.../__snapshots__/index.test.tsx.snap | 67 +-
.../__tests__/index.test.tsx | 71 +-
.../__snapshots__/index.test.tsx.snap | 12 +-
.../FileExecuteMode/__tests__/index.test.tsx | 1 +
.../__snapshots__/index.test.tsx.snap | 26 +
.../SqlExecuteMode/__tests__/index.test.tsx | 12 +-
.../__snapshots__/index.test.tsx.snap | 4 +
.../WaterfallList/__tests__/index.test.tsx | 3 +-
.../__snapshots__/index.test.tsx.snap | 2 +
.../TaskResultList/__tests__/index.test.tsx | 2 +
.../__snapshots__/index.test.tsx.snap | 1206 +++++++++++++++--
.../__tests__/index.test.tsx | 160 ++-
.../src/store/sqlExecWorkflow/index.test.ts | 68 +-
36 files changed, 3714 insertions(+), 148 deletions(-)
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/__snapshots__/index.test.tsx.snap
create mode 100644 packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/index.test.tsx
diff --git a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap
index 5577819f8..d755c2c7d 100644
--- a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap
+++ b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap
@@ -387,7 +387,7 @@ exports[`base/router-base-ee render base route data snap 1`] = `
workflowSqlFileStatementOverview
,
"key": "workflowSqlFileStatementOverview",
- "path": ":taskId/files/:fileId/sqls",
+ "path": ":workflowId/task/:taskId/files/:fileId/sqls",
},
],
"element": ,
"key": "workflowSqlFileStatementOverview",
- "path": ":taskId/files/:fileId/sqls",
+ "path": ":workflowId/task/:taskId/files/:fileId/sqls",
},
],
"element":
{
it('render SQLFileStatementOverview', async () => {
const { baseElement } = customRender([
- `/sqle/project/${projectID}/exec-workflow/123/files/434/sqls`
+ `/sqle/project/${projectID}/exec-workflow/789/task/123/files/434/sqls`
]);
await act(async () => jest.advanceTimersByTime(300));
diff --git a/packages/base/src/router/test/router.sqle.test.tsx b/packages/base/src/router/test/router.sqle.test.tsx
index 111fae236..baffe5a13 100644
--- a/packages/base/src/router/test/router.sqle.test.tsx
+++ b/packages/base/src/router/test/router.sqle.test.tsx
@@ -194,7 +194,7 @@ describe('base/router-sqle-ee', () => {
it('render SQLFileStatementOverview', async () => {
const { baseElement } = customRender([
- `/sqle/project/${projectID}/exec-workflow/123/files/434/sqls`
+ `/sqle/project/${projectID}/exec-workflow/789/task/123/files/434/sqls`
]);
await act(async () => jest.advanceTimersByTime(300));
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap
index 0b4d377b3..451a3798b 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap
@@ -672,6 +672,20 @@ exports[`sqle/ExecWorkflow/Detail render current workflow status is wait for exe
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
{
return {
@@ -89,9 +90,23 @@ describe('sqle/ExecWorkflow/Detail', () => {
);
getAuditTaskSpy = task.getAuditTask();
useParamsMock.mockReturnValue({ workflowId: 'workflowId' });
- mockUsePermission(undefined, {
- mockSelector: true
- });
+ (useSelector as jest.Mock).mockImplementation((selector) =>
+ selector({
+ permission: {
+ moduleFeatureSupport: {
+ sqlOptimization: false,
+ knowledge: false
+ },
+ userOperationPermissions: null
+ },
+ sqlExecWorkflow: {
+ retryExecuteData: {},
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: false
+ }
+ }
+ })
+ );
});
afterEach(() => {
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/__tests__/__snapshots__/index.test.tsx.snap
index 7faf529ac..73a9b46e7 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/__tests__/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/OverviewList/__tests__/__snapshots__/index.test.tsx.snap
@@ -316,6 +316,20 @@ exports[`test OverviewList matches the snapshot and displays loading state 1`] =
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
+
+
+
+ 再次执行
+
+
+
({
...jest.requireActual('react-redux'),
- useSelector: jest.fn()
+ useSelector: jest.fn(),
+ useDispatch: jest.fn()
}));
describe('test OverviewList', () => {
@@ -35,6 +40,7 @@ describe('test OverviewList', () => {
let executeOneTaskOnWorkflowSpy: jest.SpyInstance;
let terminateSingleTaskByWorkflowSpy: jest.SpyInstance;
let updateWorkflowScheduleSpy: jest.SpyInstance;
+ const dispatchSpy = jest.fn();
ignoreConsoleErrors([UtilsConsoleErrorStringsEnum.INVALID_CUSTOM_ATTRIBUTE]);
@@ -71,6 +77,7 @@ describe('test OverviewList', () => {
mockUsePermission(undefined, {
mockSelector: true
});
+ (useDispatch as jest.Mock).mockImplementation(() => dispatchSpy);
});
afterEach(() => {
@@ -637,4 +644,156 @@ describe('test OverviewList', () => {
expect(screen.queryByText('定时上线')).not.toBeVisible();
expect(screen.queryByText('取消定时上线')).not.toBeVisible();
});
+
+ it('render the retry execute button and allows retry execute when the task status is exec_failed, the current user is authorized, and outside maintenance window', async () => {
+ mockUseCurrentUser({ username: 'test_user' });
+ customRender({
+ workflowInfo: {
+ ...WorkflowsOverviewListData,
+ record: {
+ ...WorkflowsOverviewListData.record,
+ workflow_step_list: [
+ {
+ workflow_step_id: 24,
+ number: 3,
+ type: WorkflowStepResV2TypeEnum.sql_execute,
+ assignee_user_name_list: ['test_user'],
+ state: WorkflowStepResV2StateEnum.approved
+ }
+ ]
+ }
+ },
+ overviewList: {
+ list: [
+ {
+ ...WorkflowTasksItemData[0],
+ status: GetWorkflowTasksItemV2StatusEnum.exec_failed,
+ instance_maintenance_times: [
+ {
+ maintenance_start_time: { hour: 9, minute: 0 },
+ maintenance_stop_time: { hour: 20, minute: 0 }
+ }
+ ]
+ }
+ ],
+ total: 1
+ }
+ });
+
+ expect(screen.getByText('再次执行').closest('button')).not.toBeDisabled();
+ fireEvent.click(screen.getByText('再次执行'));
+
+ await act(async () => jest.advanceTimersByTime(0));
+ expect(dispatchSpy).toHaveBeenCalledTimes(2);
+ expect(dispatchSpy).toHaveBeenNthCalledWith(1, {
+ type: 'sqlExecWorkflow/updateRetryExecuteData',
+ payload: {
+ taskId: WorkflowTasksItemData[0].task_id?.toString()
+ }
+ });
+ expect(dispatchSpy).toHaveBeenNthCalledWith(2, {
+ type: 'sqlExecWorkflow/updateModalStatus',
+ payload: {
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: true
+ }
+ });
+ });
+
+ it('render the retry execute button but disabled when the task status is exec_failed but the current user is not authorized or during maintenance window', async () => {
+ mockUseCurrentUser({ username: 'test_user' });
+ customRender({
+ overviewList: {
+ list: [
+ {
+ ...WorkflowTasksItemData[0],
+ current_step_assignee_user_name_list: [''],
+ status: GetWorkflowTasksItemV2StatusEnum.wait_for_execution,
+ instance_maintenance_times: [
+ {
+ maintenance_start_time: { hour: 9, minute: 0 },
+ maintenance_stop_time: { hour: 20, minute: 0 }
+ }
+ ]
+ }
+ ],
+ total: 1
+ }
+ });
+ expect(screen.getByText('再次执行').closest('button')).not.toBeVisible();
+
+ cleanup();
+
+ // user not in the assignee_user_name_list
+ customRender({
+ workflowInfo: {
+ ...WorkflowsOverviewListData,
+ record: {
+ ...WorkflowsOverviewListData.record,
+ workflow_step_list: [
+ {
+ workflow_step_id: 24,
+ number: 3,
+ type: WorkflowStepResV2TypeEnum.sql_execute,
+ assignee_user_name_list: ['admin'],
+ state: WorkflowStepResV2StateEnum.approved
+ }
+ ]
+ }
+ },
+ overviewList: {
+ list: [
+ {
+ ...WorkflowTasksItemData[0],
+ status: GetWorkflowTasksItemV2StatusEnum.exec_failed,
+ instance_maintenance_times: [
+ {
+ maintenance_start_time: { hour: 9, minute: 0 },
+ maintenance_stop_time: { hour: 20, minute: 0 }
+ }
+ ]
+ }
+ ],
+ total: 1
+ }
+ });
+ expect(screen.getByText('再次执行').closest('button')).toBeDisabled();
+
+ cleanup();
+
+ // current time not allow execute workflow
+ customRender({
+ workflowInfo: {
+ ...WorkflowsOverviewListData,
+ record: {
+ ...WorkflowsOverviewListData.record,
+ workflow_step_list: [
+ {
+ workflow_step_id: 24,
+ number: 3,
+ type: WorkflowStepResV2TypeEnum.sql_execute,
+ assignee_user_name_list: ['test_user'],
+ state: WorkflowStepResV2StateEnum.approved
+ }
+ ]
+ }
+ },
+ overviewList: {
+ list: [
+ {
+ ...WorkflowTasksItemData[0],
+ status: GetWorkflowTasksItemV2StatusEnum.wait_for_audit,
+ instance_maintenance_times: [
+ {
+ maintenance_start_time: { hour: 1, minute: 0 },
+ maintenance_stop_time: { hour: 3, minute: 0 }
+ }
+ ]
+ }
+ ],
+ total: 1
+ }
+ });
+ expect(screen.getByText('再次执行').closest('button')).toBeDisabled();
+ });
});
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/__snapshots__/index.test.tsx.snap
new file mode 100644
index 000000000..1d88325d3
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,495 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RetryExecuteModal handles row selection correctly 1`] = `
+
+
+
+
+`;
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/index.test.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/index.test.tsx
new file mode 100644
index 000000000..b4577d5c5
--- /dev/null
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/RetryExecuteModal/__tests__/index.test.tsx
@@ -0,0 +1,222 @@
+import { fireEvent, screen } from '@testing-library/react';
+import { act } from '@testing-library/react';
+import { sqleSuperRender } from '../../../../../../../testUtils/superRender';
+import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject';
+import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser';
+import { mockUsePermission } from '@actiontech/shared/lib/testUtil/mockHook/mockUsePermission';
+import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data';
+import RetryExecuteModal from '../index';
+import execWorkflow from '@actiontech/shared/lib/testUtil/mockApi/sqle/execWorkflow';
+import { createSpySuccessResponse } from '@actiontech/shared/lib/testUtil';
+import { useSelector, useDispatch } from 'react-redux';
+import { useParams } from 'react-router-dom';
+import { ModalName } from '../../../../../../../data/ModalName';
+import EmitterKey from '../../../../../../../data/EmitterKey';
+import EventEmitter from '../../../../../../../utils/EventEmitter';
+
+jest.mock('react-router-dom', () => {
+ return {
+ ...jest.requireActual('react-router-dom'),
+ useParams: jest.fn()
+ };
+});
+
+jest.mock('react-redux', () => ({
+ ...jest.requireActual('react-redux'),
+ useSelector: jest.fn(),
+ useDispatch: jest.fn()
+}));
+
+describe('RetryExecuteModal', () => {
+ let getAuditTaskSQLsSpy: jest.SpyInstance;
+ let reExecuteTaskOnWorkflowSpy: jest.SpyInstance;
+ const useParamsMock: jest.Mock = useParams as jest.Mock;
+ const dispatchSpy = jest.fn();
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ jest.useFakeTimers();
+ mockUseCurrentProject();
+ mockUseCurrentUser();
+ mockUsePermission(undefined, { mockSelector: true });
+
+ getAuditTaskSQLsSpy = execWorkflow.getAuditTaskSQLs();
+ getAuditTaskSQLsSpy.mockImplementation(() =>
+ createSpySuccessResponse({
+ data: [
+ {
+ number: 1,
+ exec_sql: 'SELECT * ',
+ sql_source_file: '',
+ audit_result: null,
+ audit_level: '',
+ audit_status: 'finished',
+ exec_result: '',
+ exec_status: 'initialized',
+ description: '',
+ exec_sql_id: 1
+ }
+ ],
+ total_nums: 1
+ })
+ );
+ reExecuteTaskOnWorkflowSpy = execWorkflow.reExecuteTaskOnWorkflow();
+ useParamsMock.mockReturnValue({ workflowId: '456' });
+
+ (useSelector as jest.Mock).mockImplementation((selector) => {
+ return selector({
+ sqlExecWorkflow: {
+ retryExecuteData: {
+ taskId: '123',
+ // execSqlId: 1,
+ pageIndex: 1,
+ pageSize: 20
+ },
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: true
+ }
+ }
+ });
+ });
+ (useDispatch as jest.Mock).mockImplementation(() => dispatchSpy);
+ });
+
+ afterEach(() => {
+ jest.useRealTimers();
+ jest.clearAllMocks();
+ jest.restoreAllMocks();
+ });
+
+ it('handles row selection correctly', async () => {
+ const eventEmitterSpy = jest.spyOn(EventEmitter, 'emit');
+ const { baseElement } = sqleSuperRender(
);
+
+ await act(async () => jest.advanceTimersByTime(3000));
+
+ expect(getAuditTaskSQLsSpy).toHaveBeenCalledWith({
+ page_index: '1',
+ page_size: '20',
+ task_id: '123'
+ });
+ expect(baseElement).toMatchSnapshot();
+
+ const checkboxes = screen.getAllByRole('checkbox');
+ fireEvent.click(checkboxes[0]);
+ await act(async () => jest.advanceTimersByTime(0));
+ fireEvent.click(screen.getByText('提 交'));
+ await act(async () => jest.advanceTimersByTime(0));
+ expect(reExecuteTaskOnWorkflowSpy).toHaveBeenCalledTimes(1);
+ expect(reExecuteTaskOnWorkflowSpy).toHaveBeenCalledWith({
+ project_name: mockProjectInfo.projectName,
+ workflow_id: '456',
+ task_id: '123',
+ exec_sql_ids: [1]
+ });
+
+ await act(async () => jest.advanceTimersByTime(3000));
+
+ expect(dispatchSpy).toHaveBeenCalledTimes(1);
+ expect(dispatchSpy).toHaveBeenCalledWith({
+ type: 'sqlExecWorkflow/updateModalStatus',
+ payload: {
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: false
+ }
+ });
+
+ expect(eventEmitterSpy).toHaveBeenCalledTimes(1);
+ expect(eventEmitterSpy).toHaveBeenCalledWith(
+ EmitterKey.Sql_Retry_Execute_Done,
+ '123'
+ );
+ eventEmitterSpy.mockRestore();
+ });
+
+ it('shows error message when no SQLs are selected', async () => {
+ (useSelector as jest.Mock).mockImplementation((selector) => {
+ return selector({
+ sqlExecWorkflow: {
+ retryExecuteData: {
+ taskId: '123'
+ },
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: true
+ }
+ }
+ });
+ });
+ sqleSuperRender(
);
+
+ await act(async () => jest.advanceTimersByTime(3000));
+
+ fireEvent.click(screen.getByText('提 交'));
+
+ expect(screen.getByText('请选择需要再次执行的SQL')).toBeInTheDocument();
+ });
+
+ it('should checked when execSqlId is exists', async () => {
+ (useSelector as jest.Mock).mockImplementation((selector) => {
+ return selector({
+ sqlExecWorkflow: {
+ retryExecuteData: {
+ taskId: '123',
+ execSqlId: 1
+ },
+ modalStatus: {
+ [ModalName.Sql_Exec_Workflow_Retry_Execute_Modal]: true
+ }
+ }
+ });
+ });
+ sqleSuperRender(
);
+
+ await act(async () => jest.advanceTimersByTime(3000));
+ const checkboxes = screen.getAllByRole('checkbox');
+ expect(checkboxes[0]).toBeChecked();
+ });
+
+ it('closes modal and resets state when cancel is clicked', async () => {
+ sqleSuperRender(
);
+
+ await act(async () => jest.advanceTimersByTime(3000));
+
+ fireEvent.click(screen.getByText('取 消'));
+
+ expect(dispatchSpy).toHaveBeenCalledTimes(1);
+ expect(dispatchSpy).toHaveBeenCalledWith({
+ type: 'sqlExecWorkflow/updateModalStatus',
+ payload: {
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: false
+ }
+ });
+ });
+
+ it('succeeded sql should be disabled', async () => {
+ getAuditTaskSQLsSpy.mockImplementation(() =>
+ createSpySuccessResponse({
+ data: [
+ {
+ number: 1,
+ exec_sql: 'SELECT * ',
+ sql_source_file: '',
+ audit_result: null,
+ audit_level: '',
+ audit_status: 'finished',
+ exec_result: '',
+ exec_status: 'succeeded',
+ description: '',
+ exec_sql_id: 1
+ }
+ ],
+ total_nums: 1
+ })
+ );
+ sqleSuperRender(
);
+
+ await act(async () => jest.advanceTimersByTime(3000));
+
+ const checkboxes = screen.getAllByRole('checkbox');
+ expect(checkboxes[0]).toBeDisabled();
+ });
+});
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/FileMode.test.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/FileMode.test.tsx
index d01885844..b0f9ee36d 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/FileMode.test.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/FileMode.test.tsx
@@ -7,6 +7,12 @@ import task from '@actiontech/shared/lib/testUtil/mockApi/sqle/task';
import { sqleSuperRender } from '../../../../../../../../../testUtils/superRender';
import { TaskFileListMockData } from '@actiontech/shared/lib/testUtil/mockApi/sqle/task/data';
import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser';
+import { mockUsePermission } from '@actiontech/shared/lib/testUtil';
+
+jest.mock('react-redux', () => ({
+ ...jest.requireActual('react-redux'),
+ useSelector: jest.fn()
+}));
describe('test TaskResultList/Result/FileMode', () => {
let getTaskSQLsSpy: jest.SpyInstance;
@@ -15,6 +21,9 @@ describe('test TaskResultList/Result/FileMode', () => {
mockUseCurrentUser();
jest.useFakeTimers();
getTaskSQLsSpy = task.getAuditTaskSQLs();
+ mockUsePermission(undefined, {
+ mockSelector: true
+ });
});
afterEach(() => {
jest.useRealTimers();
@@ -26,6 +35,7 @@ describe('test TaskResultList/Result/FileMode', () => {
taskId="123"
projectID="300200"
{...(TaskFileListMockData[0] as unknown as IAuditFileStatistic)}
+ enableRetryExecute
/>
);
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/SqlMode.test.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/SqlMode.test.tsx
index 0d4757669..b2003692f 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/SqlMode.test.tsx
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/SqlMode.test.tsx
@@ -14,13 +14,23 @@ import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/moc
import { AuditTaskSQLResV2BackupStrategyEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum';
import { AuditTaskResV1StatusEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum';
import { AuditTaskSQLsMockDataWithExceptionRule } from '@actiontech/shared/lib/testUtil/mockApi/sqle/task/data';
+import { useDispatch } from 'react-redux';
+import { mockUsePermission } from '@actiontech/shared/lib/testUtil';
+import { ModalName } from '../../../../../../../../../data/ModalName';
const projectID = '700300';
const taskId = 'task_id_1234';
+jest.mock('react-redux', () => ({
+ ...jest.requireActual('react-redux'),
+ useDispatch: jest.fn(),
+ useSelector: jest.fn()
+}));
+
describe('sqle/ExecWorkflow/AuditDetail/SqlMode', () => {
let requestUpdateSqlDesc: jest.SpyInstance;
const onUpdateDescriptionFn = jest.fn();
+ const dispatchSpy = jest.fn();
const customRender = (
params: Omit<
@@ -46,6 +56,10 @@ describe('sqle/ExecWorkflow/AuditDetail/SqlMode', () => {
jest.useFakeTimers();
requestUpdateSqlDesc = task.updateAuditTaskSQLs();
rule_template.getRuleList();
+ (useDispatch as jest.Mock).mockImplementation(() => dispatchSpy);
+ mockUsePermission(undefined, {
+ mockSelector: true
+ });
});
afterEach(() => {
@@ -311,4 +325,64 @@ describe('sqle/ExecWorkflow/AuditDetail/SqlMode', () => {
expect(screen.getByText('审核异常')).toBeInTheDocument();
});
+
+ it('should render retry execute action when exec status is failed or initialized', async () => {
+ const { container } = customRender({
+ number: 1,
+ exec_status: getAuditTaskSQLsV2FilterExecStatusEnum.failed,
+ enableRetryExecute: true,
+ exec_sql: 'select 1;'
+ });
+ expect(container).toMatchSnapshot();
+ expect(screen.getByText('再次执行')).toBeInTheDocument();
+
+ cleanup();
+
+ customRender({
+ number: 1,
+ exec_status: getAuditTaskSQLsV2FilterExecStatusEnum.initialized,
+ enableRetryExecute: true,
+ exec_sql: 'select 1;'
+ });
+ expect(container).toMatchSnapshot();
+ expect(screen.getByText('再次执行')).toBeInTheDocument();
+ });
+
+ it('should dispatch action when click retry execute button', async () => {
+ const mockData = {
+ taskId: 'testId',
+ pagination: {
+ page_index: 2,
+ page_size: 20
+ },
+ exec_sql_id: 0
+ };
+ customRender({
+ number: 1,
+ exec_status: getAuditTaskSQLsV2FilterExecStatusEnum.failed,
+ enableRetryExecute: true,
+ exec_sql: 'select 1;',
+ ...mockData
+ });
+ expect(screen.getByText('再次执行')).toBeInTheDocument();
+ fireEvent.click(screen.getByText('再次执行'));
+ await act(async () => jest.advanceTimersByTime(0));
+ expect(dispatchSpy).toHaveBeenCalledTimes(2);
+ expect(dispatchSpy).toHaveBeenNthCalledWith(1, {
+ type: 'sqlExecWorkflow/updateModalStatus',
+ payload: {
+ modalName: ModalName.Sql_Exec_Workflow_Retry_Execute_Modal,
+ status: true
+ }
+ });
+ expect(dispatchSpy).toHaveBeenNthCalledWith(2, {
+ type: 'sqlExecWorkflow/updateRetryExecuteData',
+ payload: {
+ taskId: mockData.taskId,
+ execSqlId: mockData.exec_sql_id,
+ pageIndex: mockData.pagination.page_index,
+ pageSize: mockData.pagination.page_size
+ }
+ });
+ });
});
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/__snapshots__/FileMode.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/__snapshots__/FileMode.test.tsx.snap
index 20a0194e4..f01f09c6b 100644
--- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/__snapshots__/FileMode.test.tsx.snap
+++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/Common/ResultCard/__tests__/__snapshots__/FileMode.test.tsx.snap
@@ -84,7 +84,7 @@ exports[`test TaskResultList/Result/FileMode should match snapshot 1`] = `
create_table_if_not_exist.sql
@@ -247,7 +247,7 @@ exports[`test TaskResultList/Result/FileMode should match snapshot 2`] = `
create_table_if_not_exist.sql
@@ -410,7 +410,7 @@ exports[`test TaskResultList/Result/FileMode should render audit result count 1`
create_table_if_not_exist.sql
@@ -597,7 +597,7 @@ exports[`test TaskResultList/Result/FileMode should render collapse children and
create_table_if_not_exist.sql
@@ -689,7 +689,7 @@ exports[`test TaskResultList/Result/FileMode should render collapse children and
class="ant-spin-container"
>
+
+
@@ -16,7 +337,7 @@ exports[`test TaskResultList/SQLStatementResultTable should match snapshot 1`] =
class="ant-spin-container"
>