diff --git a/packages/base/src/__snapshots__/App.test.tsx.snap b/packages/base/src/__snapshots__/App.test.tsx.snap index bd549bfd1..2bfc72951 100644 --- a/packages/base/src/__snapshots__/App.test.tsx.snap +++ b/packages/base/src/__snapshots__/App.test.tsx.snap @@ -1054,7 +1054,7 @@ exports[`App render App when "checkPageAction" is false 1`] = `
- SQLE操作记录 + 操作记录
@@ -2231,7 +2231,7 @@ exports[`App render App when token is existed 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/locale/zh-CN/dmsHome.ts b/packages/base/src/locale/zh-CN/dmsHome.ts index 69eece452..ddf771fce 100644 --- a/packages/base/src/locale/zh-CN/dmsHome.ts +++ b/packages/base/src/locale/zh-CN/dmsHome.ts @@ -69,7 +69,7 @@ export default { action_1_0: '授权审计', action_1_1: '权限模板审计', action_1_2: '数据源操作审计', - action_1_3: 'SQLE操作记录' + action_1_3: '操作记录' } } } diff --git a/packages/base/src/locale/zh-CN/dmsMenu.ts b/packages/base/src/locale/zh-CN/dmsMenu.ts index 682f23e37..232d307dd 100644 --- a/packages/base/src/locale/zh-CN/dmsMenu.ts +++ b/packages/base/src/locale/zh-CN/dmsMenu.ts @@ -8,7 +8,7 @@ export default { authAudit: '授权审计', templateAudit: '权限模板审计', instanceAudit: '数据源操作审计', - SQLEOperateRecord: 'SQLE操作记录', + SQLEOperateRecord: '操作记录', inspectionAndDiagnosis: '巡检与诊断', SQLWorkbench: 'SQL工作台', ruleTemplate: '审核规则模板', @@ -68,6 +68,7 @@ export default { viewRule: '查看规则', ruleManage: '规则管理', system: '系统设置', + globalOperationRecord: '全局操作记录', changeTheme: '模式切换', instanceManager: '数据源管理', knowledge: '知识库' diff --git a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap index 221d09608..34e9a6522 100644 --- a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -689,7 +689,7 @@ exports[`test base/home/CEDefaultScene should match snapshot when role is admin
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap index d1feb901f..a6661062c 100644 --- a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap @@ -708,7 +708,7 @@ exports[`test base/home/DefaultScene should match snapshot when role is admin 1`
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap index cb9819629..0307c2b45 100644 --- a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap @@ -700,7 +700,7 @@ exports[`test base/Home/StepItems should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx index a8d289aee..27f41cce0 100644 --- a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx +++ b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx @@ -117,7 +117,7 @@ describe('test base/Home/StepItems', () => { `/sqle/project/${projectID}/exec-workflow/create` ); - fireEvent.click(screen.getByText('SQLE操作记录')); + fireEvent.click(screen.getByText('操作记录')); expect(navigateSpy).toHaveBeenCalledTimes(13); expect(navigateSpy).toHaveBeenNthCalledWith( 13, diff --git a/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap index d49bc881e..ee30eb452 100644 --- a/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -702,7 +702,7 @@ exports[`test base/page/Home should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap index 6b8b42b0c..c4064919e 100644 --- a/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap @@ -721,7 +721,7 @@ exports[`test base/page/Home should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap index e25d67106..a3a89b884 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap @@ -434,7 +434,7 @@ exports[`test genMenuItemsWithMenuStructTree should match snapshot 4`] = ` "label": - SQLE操作记录 + 操作记录 , "permission": "page:operation_record", "structKey": "sqle-log", diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx index 859533ddb..a8346481a 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx @@ -6,7 +6,8 @@ import { UserShieldFilled, CenterCircleHexagonFilled, DatabaseFilled, - ProfileEditFilled + ProfileEditFilled, + OperateAuditFilled } from '@actiontech/icons'; import { ContextMenuItem } from './ContextMenu/index.type'; import ContextMenu from './ContextMenu'; @@ -16,6 +17,7 @@ import { usePermission } from '@actiontech/shared/lib/features'; import { useTypedNavigate } from '@actiontech/shared'; +import { ROUTE_PATHS } from '@actiontech/dms-kit'; const GlobalSetting: React.FC = () => { const { t } = useTranslation(); @@ -37,14 +39,15 @@ const GlobalSetting: React.FC = () => { key: 'user-center', icon: , text: t('menu.userCenter'), - onClick: () => handleClickItem('/user-center'), + onClick: () => handleClickItem(ROUTE_PATHS.BASE.USER_CENTER), permission: PERMISSIONS.PAGES.BASE.USER_CENTER }, { key: 'data-source-management', icon: , text: t('dmsMenu.globalSettings.instanceManager'), - onClick: () => handleClickItem(`/data-source-management`), + onClick: () => + handleClickItem(ROUTE_PATHS.BASE.DATA_SOURCE_MANAGEMENT.index.path), permission: PERMISSIONS.PAGES.BASE.DATA_SOURCE_MANAGEMENT }, // #if [sqle] @@ -52,15 +55,24 @@ const GlobalSetting: React.FC = () => { key: 'rule-manager', icon: , text: t('dmsMenu.globalSettings.ruleManage'), - onClick: () => handleClickItem('/sqle/rule-manager'), + onClick: () => + handleClickItem(ROUTE_PATHS.SQLE.RULE_MANAGEMENT.index.path), permission: PERMISSIONS.PAGES.SQLE.RULE_MANAGEMENT }, // #endif + { + key: 'operationRecord', + icon: , + text: t('dmsMenu.globalSettings.globalOperationRecord'), + onClick: () => + handleClickItem(ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index), + permission: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD + }, { key: 'system', icon: , text: t('dmsMenu.globalSettings.system'), - onClick: () => handleClickItem('/system'), + onClick: () => handleClickItem(ROUTE_PATHS.BASE.SYSTEM.index.path), permission: PERMISSIONS.PAGES.BASE.SYSTEM_SETTING } ]; diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx index 76b084861..4e72f74d1 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx @@ -55,7 +55,7 @@ describe('base/page/Nav/SideMenu/GlobalSetting', () => { await act(async () => jest.advanceTimersByTime(500)); expect(baseElement).toMatchSnapshot(); - expect(getAllBySelector('.content-item-text').length).toBe(4); + expect(getAllBySelector('.content-item-text').length).toBe(5); fireEvent.click(screen.getByText('用户中心')); expect(navigateSpy).toHaveBeenNthCalledWith(1, '/user-center'); @@ -68,5 +68,8 @@ describe('base/page/Nav/SideMenu/GlobalSetting', () => { fireEvent.click(screen.getByText('系统设置')); expect(navigateSpy).toHaveBeenNthCalledWith(4, '/system'); + + fireEvent.click(screen.getByText('全局操作记录')); + expect(navigateSpy).toHaveBeenNthCalledWith(5, '/operation-record'); }); }); diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap index 22d094c80..020203ef2 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap @@ -153,6 +153,30 @@ exports[`base/page/Nav/SideMenu/GlobalSetting render snap when is "checkPagePerm 规则管理 +
+ + + + +
+ 全局操作记录 +
+
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 d755c2c7d..12380435e 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 @@ -343,6 +343,13 @@ exports[`base/router-base-ee render base route data snap 1`] = ` "key": "globalDashboard", "path": "/sqle/global-dashboard", }, + { + "element":
+ globalOperationRecord +
, + "key": "globalOperationRecord", + "path": "/operation-record", + }, { "children": [ { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap index 85d49cecb..0e00d46ee 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap @@ -207,6 +207,13 @@ exports[`base/router-base-ce render base route data snap 1`] = ` "key": "globalDashboard", "path": "/sqle/global-dashboard", }, + { + "element":
+ globalOperationRecord +
, + "key": "globalOperationRecord", + "path": "/operation-record", + }, { "children": [ { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap index e50c80294..f1084a170 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap @@ -156,6 +156,16 @@ exports[`base/router-sqle-ce render sqle project detail router render sqle proje `; +exports[`base/router-sqle-ce render sqle project detail router render sqle project detail router when version is ce render operationRecord 2`] = ` + +
+
+ globalOperationRecord +
+
+ +`; + exports[`base/router-sqle-ce render sqle project detail router render sqle project detail router when version is ce render route dashboard 1`] = `
diff --git a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap index 51ecb6569..aa6ced2bb 100644 --- a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap @@ -228,6 +228,20 @@ exports[`base/router-sqle-ee render sqle project detail router render sqle proje `; +exports[`base/router-sqle-ee render sqle project detail router render sqle project detail router when version is ce render global operationRecord 1`] = ` + +
+
+
+ globalOperationRecord +
+
+
+ +`; + exports[`base/router-sqle-ee render sqle project detail router render sqle project detail router when version is ce render operationRecord 1`] = `
diff --git a/packages/base/src/router/test/router.ce.sqle.test.tsx b/packages/base/src/router/test/router.ce.sqle.test.tsx index 981fecd69..e1063b394 100644 --- a/packages/base/src/router/test/router.ce.sqle.test.tsx +++ b/packages/base/src/router/test/router.ce.sqle.test.tsx @@ -382,6 +382,13 @@ describe('base/router-sqle-ce', () => { expect(screen.getByText('operationRecord')).toBeInTheDocument(); }); + it('render operationRecord', () => { + const { baseElement } = customRender([`/operation-record`]); + + expect(baseElement).toMatchSnapshot(); + expect(screen.getByText('globalOperationRecord')).toBeInTheDocument(); + }); + describe('render route sqlManagement', () => { it('render sqlManagement', async () => { const { baseElement } = customRender([ diff --git a/packages/base/src/router/test/router.sqle.test.tsx b/packages/base/src/router/test/router.sqle.test.tsx index baffe5a13..914183510 100644 --- a/packages/base/src/router/test/router.sqle.test.tsx +++ b/packages/base/src/router/test/router.sqle.test.tsx @@ -448,6 +448,13 @@ describe('base/router-sqle-ee', () => { expect(screen.getByText('operationRecord')).toBeInTheDocument(); }); + it('render global operationRecord', () => { + const { baseElement } = customRender([`/operation-record`]); + + expect(baseElement).toMatchSnapshot(); + expect(screen.getByText('globalOperationRecord')).toBeInTheDocument(); + }); + describe('render route sqlManagement', () => { it('render sqlManagement', async () => { const { baseElement } = customRender([ diff --git a/packages/dms-kit/docs/CHANGELOG.md b/packages/dms-kit/docs/CHANGELOG.md index 263865039..d832c357d 100644 --- a/packages/dms-kit/docs/CHANGELOG.md +++ b/packages/dms-kit/docs/CHANGELOG.md @@ -40,4 +40,8 @@ nav: ## 1.0.5 -- 修复BasicButton样式 \ No newline at end of file +- 修复BasicButton样式 + +## 1.0.6 + +- 添加全局操作记录path \ No newline at end of file diff --git a/packages/dms-kit/package.json b/packages/dms-kit/package.json index f19c1faf0..709542ec3 100644 --- a/packages/dms-kit/package.json +++ b/packages/dms-kit/package.json @@ -1,6 +1,6 @@ { "name": "@actiontech/dms-kit", - "version": "1.0.5", + "version": "1.0.6", "description": "DMS Kit - React UI Components Library", "main": "lib/index.js", "module": "es/index.js", diff --git a/packages/dms-kit/src/data/routePaths.ts b/packages/dms-kit/src/data/routePaths.ts index 34ee411c1..0ce753932 100644 --- a/packages/dms-kit/src/data/routePaths.ts +++ b/packages/dms-kit/src/data/routePaths.ts @@ -335,6 +335,9 @@ export const ROUTE_PATHS = { path: ':projectID/operation-record' } }, + GLOBAL_OPERATION_LOG: { + index: '/operation-record' + }, PLUGIN_AUDIT: { index: { prefix: '/sqle/project', diff --git a/packages/shared/lib/api/base/index.ts b/packages/shared/lib/api/base/index.ts index c924de868..220befc3e 100644 --- a/packages/shared/lib/api/base/index.ts +++ b/packages/shared/lib/api/base/index.ts @@ -16,6 +16,7 @@ export { default as MemberGroupService } from './service/MemberGroup'; export { default as NotificationService } from './service/Notification'; export { default as OAuth2Service } from './service/OAuth2'; export { default as OpPermissionService } from './service/OpPermission'; +export { default as OperationRecordService } from './service/OperationRecord'; export { default as ProjectService } from './service/Project'; export { default as ResourceOverviewService } from './service/ResourceOverview'; export { default as RoleService } from './service/Role'; diff --git a/packages/shared/lib/api/base/service/OperationRecord/index.d.ts b/packages/shared/lib/api/base/service/OperationRecord/index.d.ts new file mode 100644 index 000000000..2a9cb1a23 --- /dev/null +++ b/packages/shared/lib/api/base/service/OperationRecord/index.d.ts @@ -0,0 +1,44 @@ +import { + IGetOperationRecordListReply, + IAddOperationRecordReq, + IAddOperationRecordReply +} from '../common.d'; + +export interface IGetOperationRecordListParams { + filter_operate_time_from?: string; + + filter_operate_time_to?: string; + + filter_operate_project_name?: string; + + fuzzy_search_operate_user_name?: string; + + filter_operate_type_name?: string; + + filter_operate_action?: string; + + page_index: number; + + page_size: number; +} + +export interface IGetOperationRecordListReturn + extends IGetOperationRecordListReply {} + +export interface IAddOperationRecordParams extends IAddOperationRecordReq {} + +export interface IAddOperationRecordReturn extends IAddOperationRecordReply {} + +export interface IExportOperationRecordListParams { + filter_operate_time_from?: string; + + filter_operate_time_to?: string; + + filter_operate_project_name?: string; + + fuzzy_search_operate_user_name?: string; + + filter_operate_type_name?: string; + + filter_operate_action?: string; +} diff --git a/packages/shared/lib/api/base/service/OperationRecord/index.ts b/packages/shared/lib/api/base/service/OperationRecord/index.ts new file mode 100644 index 000000000..d73a17c0d --- /dev/null +++ b/packages/shared/lib/api/base/service/OperationRecord/index.ts @@ -0,0 +1,55 @@ +/* tslint:disable no-identical-functions */ +/* tslint:disable no-useless-cast */ +/* tslint:disable no-unnecessary-type-assertion */ +/* tslint:disable no-big-function */ +/* tslint:disable no-duplicate-string */ +import ServiceBase from '../Service.base'; +import { AxiosRequestConfig } from 'axios'; + +import { + IGetOperationRecordListParams, + IGetOperationRecordListReturn, + IAddOperationRecordParams, + IAddOperationRecordReturn, + IExportOperationRecordListParams +} from './index.d'; + +class OperationRecordService extends ServiceBase { + public GetOperationRecordList( + params: IGetOperationRecordListParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.get( + '/v1/dms/operation_records', + paramsData, + options + ); + } + + public AddOperationRecord( + params: IAddOperationRecordParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.post( + '/v1/dms/operation_records', + paramsData, + options + ); + } + + public ExportOperationRecordList( + params: IExportOperationRecordListParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.get( + '/v1/dms/operation_records/exports', + paramsData, + options + ); + } +} + +export default new OperationRecordService(); diff --git a/packages/shared/lib/api/base/service/common.d.ts b/packages/shared/lib/api/base/service/common.d.ts index 137f05549..5a2a9a019 100644 --- a/packages/shared/lib/api/base/service/common.d.ts +++ b/packages/shared/lib/api/base/service/common.d.ts @@ -25,6 +25,7 @@ import { OpPermissionItemOpPermissionTypeEnum, OpPermissionItemRangeTypeEnum, OperationOperationTypeEnum, + OperationRecordListItemStatusEnum, ProjectInfoProjectPriorityEnum, ProjectV1ProjectPriorityEnum, ProjectV2ProjectPriorityEnum, @@ -144,6 +145,16 @@ export interface IAddMemberReq { member?: IMember; } +export interface IAddOperationRecordReply { + code?: number; + + message?: string; +} + +export interface IAddOperationRecordReq { + operation_record?: IOperationRecord; +} + export interface IAddProjectReply { code?: number; @@ -992,6 +1003,16 @@ export interface IGetOauth2TipsResData { login_tip?: string; } +export interface IGetOperationRecordListReply { + code?: number; + + data?: IOperationRecordListItem[]; + + message?: string; + + total_nums?: number; +} + export interface IGetProjectTipsReply { code?: number; @@ -1837,10 +1858,6 @@ export interface IListMemberReply { } export interface IListMemberRoleWithOpRange { - member_group?: IProjectMemberGroup; - - op_permissions?: IUidWithName[]; - op_range_type?: ListMemberRoleWithOpRangeOpRangeTypeEnum; range_uids?: IUidWithName[]; @@ -2182,6 +2199,52 @@ export interface IOperation { operation_type?: OperationOperationTypeEnum; } +export interface IOperationRecord { + operation_action?: string; + + operation_i18n_content?: II18nStr; + + operation_project_name?: string; + + operation_req_ip?: string; + + operation_status?: string; + + operation_time?: string; + + operation_type_name?: string; + + operation_user_agent?: string; + + operation_user_name?: string; +} + +export interface IOperationRecordListItem { + id?: number; + + operation_action?: string; + + operation_content?: string; + + operation_time?: string; + + operation_type_name?: string; + + operation_user?: IOperationUser; + + operation_user_agent?: string; + + project_name?: string; + + status?: OperationRecordListItemStatusEnum; +} + +export interface IOperationUser { + ip?: string; + + user_name?: string; +} + export interface IParam { desc?: string; diff --git a/packages/shared/lib/api/base/service/common.enum.ts b/packages/shared/lib/api/base/service/common.enum.ts index 2074d5bea..51abaeff8 100644 --- a/packages/shared/lib/api/base/service/common.enum.ts +++ b/packages/shared/lib/api/base/service/common.enum.ts @@ -312,6 +312,12 @@ export enum OperationOperationTypeEnum { 'SQL' = 'SQL' } +export enum OperationRecordListItemStatusEnum { + 'succeeded' = 'succeeded', + + 'failed' = 'failed' +} + export enum ProjectInfoProjectPriorityEnum { 'high' = 'high', diff --git a/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap b/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap index 7f822d835..6839c6301 100644 --- a/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap @@ -250,6 +250,7 @@ exports[`usePermission should match snapshot 1`] = ` "USER_CENTER": "page:user_center", }, "SQLE": { + "GLOBAL_OPERATION_RECORD": "page:global_operation_record", "KNOWLEDGE": "page:knowledge", "OPERATION_RECORD": "page:operation_record", "PROJECT_RULE_TEMPLATE": "page:project_rule_template", @@ -1714,6 +1715,16 @@ exports[`usePermission should match snapshot 2`] = ` ], "type": "page", }, + "page:global_operation_record": { + "id": "page:global_operation_record", + "role": [ + "admin", + "systemAdministrator", + "auditAdministrator", + "certainProjectManager", + ], + "type": "page", + }, "page:knowledge": { "id": "page:knowledge", "moduleSupport": [ @@ -1733,6 +1744,7 @@ exports[`usePermission should match snapshot 2`] = ` }, "page:operation_record": { "id": "page:operation_record", + "projectPermission": "project_admin", "role": [ "admin", "systemAdministrator", diff --git a/packages/shared/lib/features/usePermission/permissionManifest.ts b/packages/shared/lib/features/usePermission/permissionManifest.ts index 49dd88dd2..6c1575530 100644 --- a/packages/shared/lib/features/usePermission/permissionManifest.ts +++ b/packages/shared/lib/features/usePermission/permissionManifest.ts @@ -114,6 +114,17 @@ export const PERMISSION_MANIFEST: Record< SystemRole.admin, SystemRole.systemAdministrator, SystemRole.auditAdministrator + ], + projectPermission: OpPermissionItemOpPermissionTypeEnum.project_admin + }, + [PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD]: { + id: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD, + type: 'page', + role: [ + SystemRole.admin, + SystemRole.systemAdministrator, + SystemRole.auditAdministrator, + SystemRole.certainProjectManager ] }, [PERMISSIONS.PAGES.SQLE.SQL_OPTIMIZATION]: { diff --git a/packages/shared/lib/features/usePermission/permissions.ts b/packages/shared/lib/features/usePermission/permissions.ts index 90eadafcd..befae38d3 100644 --- a/packages/shared/lib/features/usePermission/permissions.ts +++ b/packages/shared/lib/features/usePermission/permissions.ts @@ -12,6 +12,7 @@ export const PERMISSIONS = { }, SQLE: { OPERATION_RECORD: 'page:operation_record', + GLOBAL_OPERATION_RECORD: 'page:global_operation_record', SQL_OPTIMIZATION: 'page:sql_optimization', REPORT_STATISTICS: 'page:report_statistics', RULE_MANAGEMENT: 'page:rule_management', diff --git a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts index 1fdd564f7..cce92f635 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts @@ -1,11 +1,11 @@ import { - IOperationRecordList, IOperationTypeNameList, IOperationActionList } from '../../../../api/sqle/service/common'; -import { OperationRecordListStatusEnum } from '../../../../api/sqle/service/common.enum'; +import { IOperationRecordListItem } from '../../../../api/base/service/common'; +import { OperationRecordListItemStatusEnum } from '../../../../api/base/service/common.enum'; -export const operationRecordListMockData: IOperationRecordList[] = [ +export const operationRecordListMockData: IOperationRecordListItem[] = [ { id: 54, operation_time: '2024-01-03T11:28:34+08:00', @@ -17,7 +17,9 @@ export const operationRecordListMockData: IOperationRecordList[] = [ operation_action: '编辑流程模板', operation_content: '编辑流程模板', project_name: 'default', - status: OperationRecordListStatusEnum.succeeded + status: OperationRecordListItemStatusEnum.succeeded, + operation_user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' }, { id: 53, @@ -29,8 +31,10 @@ export const operationRecordListMockData: IOperationRecordList[] = [ operation_type_name: '流程模板', operation_action: '编辑流程模板', operation_content: '编辑流程模板', - project_name: 'default', - status: OperationRecordListStatusEnum.failed + project_name: '', + status: OperationRecordListItemStatusEnum.failed, + operation_user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' } ]; diff --git a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts index 950dba0e0..6e4e1c07e 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts @@ -1,4 +1,5 @@ import operationRecord from '../../../../api/sqle/service/OperationRecord'; +import baseOperationRecord from '../../../../api/base/service/OperationRecord'; import { MockSpyApy, createSpySuccessResponse } from '../../common'; import { operationRecordListMockData, @@ -15,7 +16,7 @@ class MockOperationRecordApi implements MockSpyApy { } public getOperationRecordList() { - const spy = jest.spyOn(operationRecord, 'getOperationRecordListV1'); + const spy = jest.spyOn(baseOperationRecord, 'GetOperationRecordList'); spy.mockImplementation(() => createSpySuccessResponse({ data: operationRecordListMockData, @@ -26,7 +27,7 @@ class MockOperationRecordApi implements MockSpyApy { } public exportOperationRecordList() { - const spy = jest.spyOn(operationRecord, 'getExportOperationRecordListV1'); + const spy = jest.spyOn(baseOperationRecord, 'ExportOperationRecordList'); spy.mockImplementation(() => createSpySuccessResponse({})); return spy; } diff --git a/packages/sqle/src/locale/zh-CN/menu.ts b/packages/sqle/src/locale/zh-CN/menu.ts index d3ba37278..55860fc3f 100644 --- a/packages/sqle/src/locale/zh-CN/menu.ts +++ b/packages/sqle/src/locale/zh-CN/menu.ts @@ -28,7 +28,7 @@ export default { projectOverview: '项目概览', allInstanceType: '所有数据库类型', syncDataSource: '外部数据源同步', - operationRecord: 'SQLE操作记录', + operationRecord: '操作记录', sqlManagement: 'SQL管控', sqlAudit: 'SQL审核', pluginAudit: 'IDE审核' diff --git a/packages/sqle/src/locale/zh-CN/operationRecord.ts b/packages/sqle/src/locale/zh-CN/operationRecord.ts index d042f26e5..034ac19ac 100644 --- a/packages/sqle/src/locale/zh-CN/operationRecord.ts +++ b/packages/sqle/src/locale/zh-CN/operationRecord.ts @@ -1,6 +1,7 @@ // eslint-disable-next-line import/no-anonymous-default-export export default { - pageTitle: '操作记录列表', + pageTitle: '操作记录', + globalPageTitle: '全局操作记录', ceTips: '当出现问题或错误时,您可以通过分析操作记录,查看导致问题产生的步骤或操作,以便更好地解决和预防类似问题,保证操作的安全与合规性。', list: { @@ -13,7 +14,8 @@ export default { operator: '操作人', operationType: '操作类型', operationAction: '操作内容', - platformOperation: '-- (平台操作)' + platformOperation: '-- (平台操作)', + globalOperation: '全局操作' }, column: { operatingTime: '操作时间', diff --git a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap index 292d6edf1..fc64dcc06 100644 --- a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap @@ -10,7 +10,7 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = `
- SQLE操作记录 + 全局操作记录
-
-
-
- - - - - - - 操作类型 - - - 请选择{{name}} - - - -
-
-
- 操作内容 + 项目 - - - - - - - + @@ -436,6 +362,18 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = ` > 操作内容 + + UserAgent + + + 项目 + + +
+   +
+ + +
+   +
+ 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + default + @@ -577,6 +618,91 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = ` > 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + - + @@ -765,7 +891,7 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = ` `; -exports[`sqle/OperationRecord/List render operation record table when request return data 1`] = ` +exports[`sqle/OperationRecord/List render operation record table when project name is exited 1`] = `
@@ -775,7 +901,7 @@ exports[`sqle/OperationRecord/List render operation record table when request re
- SQLE操作记录 + 操作记录
- - - - - - - + @@ -1014,6 +1124,12 @@ exports[`sqle/OperationRecord/List render operation record table when request re > 操作内容 + + UserAgent + + +
+   +
+ 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ @@ -1155,6 +1360,86 @@ exports[`sqle/OperationRecord/List render operation record table when request re > 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ @@ -1343,7 +1628,7 @@ exports[`sqle/OperationRecord/List render operation record table when request re `; -exports[`sqle/OperationRecord/List render table when request return error 1`] = ` +exports[`sqle/OperationRecord/List render operation record table when request return data 1`] = `
@@ -1353,7 +1638,7 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] =
- SQLE操作记录 + 全局操作记录
- - - - - - - + @@ -1592,6 +1861,18 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] = > 操作内容 + + UserAgent + + + 项目 + + +
+   +
+ + +
+   +
+ 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + default + @@ -1733,6 +2117,91 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] = > 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + - + @@ -1920,3 +2389,354 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] =
`; + +exports[`sqle/OperationRecord/List render table when request return error 1`] = ` + +
+
+
+
+ 全局操作记录 +
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 操作时间 + + 操作人 + + 操作类型 + + 操作内容 + + UserAgent + + 项目 + + 状态 +
+
+
+
+
+
+
+
+
+
+
+ +`; diff --git a/packages/sqle/src/page/OperationRecord/List/column.tsx b/packages/sqle/src/page/OperationRecord/List/column.tsx index deecb6e44..388a08406 100644 --- a/packages/sqle/src/page/OperationRecord/List/column.tsx +++ b/packages/sqle/src/page/OperationRecord/List/column.tsx @@ -1,20 +1,20 @@ -import { formatTime } from '@actiontech/dms-kit'; -import { IOperationRecordList } from '@actiontech/shared/lib/api/sqle/service/common'; +import { formatTime, BasicTypographyEllipsis } from '@actiontech/dms-kit'; +import { IOperationRecordListItem } from '@actiontech/shared/lib/api/base/service/common'; import { ActiontechTableColumn, PageInfoWithoutIndexAndSize } from '@actiontech/dms-kit/es/components/ActiontechTable'; -import { IGetOperationRecordListV1Params } from '@actiontech/shared/lib/api/sqle/service/OperationRecord/index.d'; +import { IGetOperationRecordListParams } from '@actiontech/shared/lib/api/base/service/OperationRecord/index.d'; import { t } from '../../../locale'; import OperationStatus from '../components/OperationStatus'; export type OperationRecordListFilterParamType = PageInfoWithoutIndexAndSize< - IGetOperationRecordListV1Params, - 'filter_operate_project_name' | 'fuzzy_search_operate_user_name' + IGetOperationRecordListParams, + 'fuzzy_search_operate_user_name' >; export const OperationRecordListColumn: ActiontechTableColumn< - IOperationRecordList, + IOperationRecordListItem, OperationRecordListFilterParamType > = [ { @@ -24,8 +24,7 @@ export const OperationRecordListColumn: ActiontechTableColumn< return formatTime(time); }, filterCustomType: 'date-range', - filterKey: ['filter_operate_time_from', 'filter_operate_time_to'], - width: 300 + filterKey: ['filter_operate_time_from', 'filter_operate_time_to'] }, { dataIndex: 'operation_user', @@ -36,34 +35,41 @@ export const OperationRecordListColumn: ActiontechTableColumn< return '-'; } return `${userInfo.user_name ?? ''} ${userInfo.ip ?? ''}`; - }, - width: 300 + } }, { dataIndex: 'operation_type_name', - title: () => t('operationRecord.list.column.operationType'), - filterCustomType: 'select', - filterKey: 'filter_operate_type_name', - width: 300 + title: () => t('operationRecord.list.column.operationType') + // filterCustomType: 'select', + // filterKey: 'filter_operate_type_name', }, { dataIndex: 'operation_content', - title: () => t('operationRecord.list.column.operationAction'), + title: () => t('operationRecord.list.column.operationAction') + // filterCustomType: 'select', + // filterKey: 'filter_operate_action', + }, + + { + dataIndex: 'operation_user_agent', + title: () => 'UserAgent', + className: 'ellipsis-column-width', + render: (userAgent?: string) => { + return ; + } + }, + { + dataIndex: 'project_name', + title: () => t('operationRecord.list.column.projectName'), + render(name?: string) { + if (!name) { + return '-'; + } + return name; + }, filterCustomType: 'select', - filterKey: 'filter_operate_action', - width: 600 + filterKey: 'filter_operate_project_name' }, - // todo: 后期可能会迁移,目前在sqle里先隐藏 - // { - // dataIndex: 'project_name', - // title: () => t('operationRecord.list.column.projectName'), - // render(name?: string) { - // if (!name) { - // return '--'; - // } - // return name; - // } - // }, { dataIndex: 'status', title: () => t('operationRecord.list.column.status'), @@ -72,7 +78,6 @@ export const OperationRecordListColumn: ActiontechTableColumn< return '-'; } return ; - }, - width: 180 + } } ]; diff --git a/packages/sqle/src/page/OperationRecord/List/index.test.tsx b/packages/sqle/src/page/OperationRecord/List/index.test.tsx index 505ac4969..8e40a033e 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.test.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.test.tsx @@ -4,18 +4,22 @@ import OperationRecordList from '.'; import operationRecord from '@actiontech/shared/lib/testUtil/mockApi/sqle/operationRecord'; import { operationRecordListMockData } from '@actiontech/shared/lib/testUtil/mockApi/sqle/operationRecord/data'; import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; -import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; import { createSpyErrorResponse } from '@actiontech/shared/lib/testUtil/mockApi'; import { getAllBySelector, getBySelector } from '@actiontech/shared/lib/testUtil/customQuery'; +import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; +import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil'; describe('sqle/OperationRecord/List', () => { beforeEach(() => { jest.useFakeTimers(); operationRecord.mockAllApi(); - mockUseCurrentProject(); + mockUseCurrentProject({ + projectName: undefined + }); + mockUseCurrentUser(); }); beforeAll(() => { @@ -24,28 +28,50 @@ describe('sqle/OperationRecord/List', () => { }); it('render operation record table when request return data', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); - const actionSpy = operationRecord.getOperationActionList(); - const typeNameSpy = operationRecord.getOperationTypeNameList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + // const actionSpy = operationRecord.getOperationActionList(); + // const typeNameSpy = operationRecord.getOperationTypeNameList(); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); expect(baseElement).toMatchSnapshot(); expect(operationRecordListSpy).toHaveBeenCalledTimes(1); - expect(actionSpy).toHaveBeenCalledTimes(1); - expect(typeNameSpy).toHaveBeenCalledTimes(1); + expect(operationRecordListSpy).toHaveBeenNthCalledWith(1, { + page_index: 1, + page_size: 20, + fuzzy_search_operate_user_name: '' + }); + // expect(actionSpy).toHaveBeenCalledTimes(1); + // expect(typeNameSpy).toHaveBeenCalledTimes(1); expect( screen.getByText(`共 ${operationRecordListMockData.length} 条数据`) ).toBeInTheDocument(); }); + it('render operation record table when project name is exited', async () => { + mockUseCurrentProject({ + projectName: mockProjectInfo.projectName + }); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + const { baseElement } = superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(baseElement).toMatchSnapshot(); + expect(operationRecordListSpy).toHaveBeenCalledTimes(1); + expect(operationRecordListSpy).toHaveBeenNthCalledWith(1, { + page_index: 1, + page_size: 20, + filter_operate_project_name: mockProjectInfo.projectName, + fuzzy_search_operate_user_name: '' + }); + }); + it('render table when request return error', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); operationRecordListSpy.mockImplementationOnce(() => createSpyErrorResponse({ message: 'error info' }) ); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); - expect(screen.getByText('SQLE操作记录')).toBeInTheDocument(); + expect(screen.getByText('全局操作记录')).toBeInTheDocument(); expect(baseElement).toMatchSnapshot(); }); @@ -75,7 +101,6 @@ describe('sqle/OperationRecord/List', () => { await act(async () => jest.advanceTimersByTime(3000)); expect(operationRecordListSpy).toHaveBeenCalled(); expect(operationRecordListSpy).toHaveBeenCalledWith({ - filter_operate_project_name: mockProjectInfo.projectName, fuzzy_search_operate_user_name: 'test', page_index: 1, page_size: 20 @@ -83,19 +108,67 @@ describe('sqle/OperationRecord/List', () => { }); it('render action when filter item show', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); expect(operationRecordListSpy).toHaveBeenCalledTimes(1); fireEvent.click(screen.getByText('筛选')); - await act(async () => jest.advanceTimersByTime(300)); + await act(async () => jest.advanceTimersByTime(0)); const filterItems = getAllBySelector( '.actiontech-table-filter-container-namespace .ant-space-item', baseElement ); - expect(filterItems.length).toBe(3); + expect(filterItems.length).toBe(2); expect(baseElement).toMatchSnapshot(); + + fireEvent.mouseDown(getBySelector('.ant-select-selector', filterItems[1])); + await act(async () => jest.advanceTimersByTime(0)); + expect( + getAllBySelector('.ant-select-item-option', baseElement).length + ).toBe(3); + }); + + it('render project filter options when user is project manager', async () => { + mockUseCurrentUser({ + bindProjects: [ + { + is_manager: true, + project_name: 'default', + project_id: '1', + archived: false + }, + { + is_manager: false, + project_name: 'test', + project_id: '2', + archived: false + } + ], + userRoles: { + admin: false, + certainProjectManager: true, + systemAdministrator: false, + auditAdministrator: false, + projectDirector: false + } + }); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + const { baseElement } = superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(operationRecordListSpy).toHaveBeenCalledTimes(1); + + fireEvent.click(screen.getByText('筛选')); + await act(async () => jest.advanceTimersByTime(0)); + const filterItems = getAllBySelector( + '.actiontech-table-filter-container-namespace .ant-space-item', + baseElement + ); + fireEvent.mouseDown(getBySelector('.ant-select-selector', filterItems[1])); + await act(async () => jest.advanceTimersByTime(0)); + expect( + getAllBySelector('.ant-select-item-option', baseElement).length + ).toBe(1); }); it('should export data file when click export button', async () => { @@ -108,7 +181,6 @@ describe('sqle/OperationRecord/List', () => { expect(exportListSpy).toHaveBeenCalledTimes(1); expect(exportListSpy).toHaveBeenCalledWith( { - filter_operate_project_name: mockProjectInfo.projectName, fuzzy_search_operate_user_name: '' }, { @@ -118,4 +190,28 @@ describe('sqle/OperationRecord/List', () => { await act(async () => jest.advanceTimersByTime(3300)); expect(screen.getByText('操作记录列表导出成功')).toBeInTheDocument(); }); + + it('should export data file when click export button and project name is exited', async () => { + mockUseCurrentProject({ + projectName: mockProjectInfo.projectName + }); + const exportListSpy = operationRecord.exportOperationRecordList(); + superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + fireEvent.click(screen.getByText('导出')); + await act(async () => jest.advanceTimersByTime(300)); + expect(screen.getByText('正在导出操作记录列表...')).toBeInTheDocument(); + expect(exportListSpy).toHaveBeenCalledTimes(1); + expect(exportListSpy).toHaveBeenCalledWith( + { + fuzzy_search_operate_user_name: '', + filter_operate_project_name: mockProjectInfo.projectName + }, + { + responseType: 'blob' + } + ); + await act(async () => jest.advanceTimersByTime(3300)); + expect(screen.getByText('操作记录列表导出成功')).toBeInTheDocument(); + }); }); diff --git a/packages/sqle/src/page/OperationRecord/List/index.tsx b/packages/sqle/src/page/OperationRecord/List/index.tsx index 6dc87a811..06ddec731 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.tsx @@ -1,14 +1,14 @@ -import { useMemo, useState, useEffect } from 'react'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Space, message } from 'antd'; import { useRequest, useBoolean } from 'ahooks'; import { BasicButton, PageHeader } from '@actiontech/dms-kit'; -import operationRecord from '@actiontech/shared/lib/api/sqle/service/OperationRecord'; +import operationRecord from '@actiontech/shared/lib/api/base/service/OperationRecord'; import { IGetOperationRecordListV1Params, IGetExportOperationRecordListV1Params } from '@actiontech/shared/lib/api/sqle/service/OperationRecord/index.d'; -import { IOperationRecordList } from '@actiontech/shared/lib/api/sqle/service/common'; +import { IOperationRecordListItem } from '@actiontech/shared/lib/api/base/service/common'; import { ActiontechTable, useTableRequestParams, @@ -18,29 +18,33 @@ import { FilterCustomProps, TableToolbar } from '@actiontech/dms-kit/es/components/ActiontechTable'; -import { useCurrentProject } from '@actiontech/shared/lib/features'; +import { + useCurrentProject, + useCurrentUser +} from '@actiontech/shared/lib/features'; import { OperationRecordListColumn, OperationRecordListFilterParamType } from './column'; -import useOperationTypeName from '../../../hooks/useOperationTypeName'; -import useOperationActions from '../../../hooks/useOperationActions'; +// import useOperationTypeName from '../../../hooks/useOperationTypeName'; +// import useOperationActions from '../../../hooks/useOperationActions'; import { ResponseCode } from '../../../data/common'; import { DownArrowLineOutlined } from '@actiontech/icons'; const OperationRecordList: React.FC = () => { const { t } = useTranslation(); const [messageApi, contextHolder] = message.useMessage(); const { projectName } = useCurrentProject(); - const [currentOperationTypeName, setCurrentOperationTypeName] = - useState(); + const { bindProjects, userRoles } = useCurrentUser(); + // const [currentOperationTypeName, setCurrentOperationTypeName] = + // useState(); const [ exportButtonEnableStatus, { setFalse: finishExport, setTrue: startExport } ] = useBoolean(false); - const { updateOperationTypeNameList, operationTypeNameOptions } = - useOperationTypeName(); - const { updateOperationActions, operationActionOptions } = - useOperationActions(); + // const { updateOperationTypeNameList, operationTypeNameOptions } = + // useOperationTypeName(); + // const { updateOperationActions, operationActionOptions } = + // useOperationActions(); const { tableFilterInfo, updateTableFilterInfo, @@ -50,7 +54,7 @@ const OperationRecordList: React.FC = () => { setSearchKeyword, refreshBySearchKeyword } = useTableRequestParams< - IOperationRecordList, + IOperationRecordListItem, OperationRecordListFilterParamType >(); const { requestErrorMessage, handleTableRequestError } = @@ -64,11 +68,13 @@ const OperationRecordList: React.FC = () => { const params: IGetOperationRecordListV1Params = { ...pagination, ...tableFilterInfo, - filter_operate_project_name: projectName, fuzzy_search_operate_user_name: searchKeyword }; + if (!!projectName) { + params.filter_operate_project_name = projectName; + } return handleTableRequestError( - operationRecord.getOperationRecordListV1(params) + operationRecord.GetOperationRecordList(params) ); }, { @@ -76,7 +82,31 @@ const OperationRecordList: React.FC = () => { } ); const filterCustomProps = useMemo(() => { - return new Map([ + let operationOptions; + if ( + userRoles.admin || + userRoles.auditAdministrator || + userRoles.systemAdministrator + ) { + operationOptions = [ + { + label: t('operationRecord.list.filterForm.globalOperation'), + value: '' + }, + ...bindProjects.map((v) => ({ + label: v.project_name, + value: v.project_name + })) + ]; + } else { + operationOptions = bindProjects + .filter((i) => i.is_manager) + .map((v) => ({ + label: v.project_name, + value: v.project_name + })); + } + return new Map([ [ 'operation_time', { @@ -84,32 +114,44 @@ const OperationRecordList: React.FC = () => { } ], [ - 'operation_type_name', - { - options: operationTypeNameOptions, - onChange: (value: unknown) => { - setCurrentOperationTypeName(value as string); - } - } - ], - [ - 'operation_content', + 'project_name', { - options: operationActionOptions(currentOperationTypeName) + options: operationOptions } ] + // [ + // 'operation_type_name', + // { + // options: operationTypeNameOptions, + // onChange: (value: unknown) => { + // setCurrentOperationTypeName(value as string); + // } + // } + // ], + // [ + // 'operation_content', + // { + // options: operationActionOptions(currentOperationTypeName) + // } + // ] ]); - }, [ - operationTypeNameOptions, - operationActionOptions, - currentOperationTypeName - ]); + }, [bindProjects, t, userRoles]); + + const columns = useMemo(() => { + if (!!projectName) { + return OperationRecordListColumn.filter( + (column) => column.dataIndex !== 'project_name' + ); + } + return OperationRecordListColumn; + }, [projectName]); + const { filterButtonMeta, filterContainerMeta, updateAllSelectedFilterItem } = - useTableFilterContainer(OperationRecordListColumn, updateTableFilterInfo); - useEffect(() => { - updateOperationTypeNameList(); - updateOperationActions(); - }, [updateOperationActions, updateOperationTypeNameList]); + useTableFilterContainer(columns, updateTableFilterInfo); + // useEffect(() => { + // updateOperationTypeNameList(); + // updateOperationActions(); + // }, [updateOperationActions, updateOperationTypeNameList]); const onExport = () => { startExport(); const hideLoading = messageApi.loading( @@ -118,11 +160,13 @@ const OperationRecordList: React.FC = () => { ); const param: IGetExportOperationRecordListV1Params = { ...tableFilterInfo, - filter_operate_project_name: projectName, fuzzy_search_operate_user_name: searchKeyword }; + if (!!projectName) { + param.filter_operate_project_name = projectName; + } operationRecord - .getExportOperationRecordListV1(param, { + .ExportOperationRecordList(param, { responseType: 'blob' }) .then((res) => { @@ -139,7 +183,11 @@ const OperationRecordList: React.FC = () => {
{contextHolder} { current: pagination.page_index }} loading={loading} - columns={OperationRecordListColumn} + columns={columns} onChange={tableChange} errorMessage={requestErrorMessage} /> diff --git a/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap b/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap index d9e6cb9bf..d795051e8 100644 --- a/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap @@ -9,7 +9,7 @@ exports[`slqe/OperationRecord CE should match snap shot 1`] = `
- 操作记录列表 + 全局操作记录
- 操作记录列表为企业版功能。如您想使用该功能,可以通过以下链接联系我们。 + 操作记录为企业版功能。如您想使用该功能,可以通过以下链接联系我们。

- SQLE操作记录 + 操作记录
- - - - - - - + @@ -274,6 +258,12 @@ exports[`slqe/OperationRecord should render operation record list 1`] = ` > 操作内容 + + UserAgent + + +
+   +
+
= ({ - status -}) => { +const OperationStatus: React.FC<{ + status: OperationRecordListItemStatusEnum; +}> = ({ status }) => { const { t } = useTranslation(); return ( - {status === OperationRecordListStatusEnum.succeeded ? ( + {status === OperationRecordListItemStatusEnum.succeeded ? ( <> {t('common.success')} diff --git a/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx b/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx index dd752ea96..96136ec0e 100644 --- a/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx +++ b/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx @@ -1,14 +1,14 @@ import OperationStatus from '../OperationStatus'; import { superRender } from '@actiontech/shared/lib/testUtil/superRender'; -import { OperationRecordListStatusEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum'; +import { OperationRecordListItemStatusEnum } from '@actiontech/shared/lib/api/base/service/common.enum'; describe('sqle/OperationRecord/OperationStatus', () => { it('should match snap shot', () => { const { baseElement } = superRender( - + ); const { baseElement: baseElement2 } = superRender( - + ); expect(baseElement).toMatchSnapshot(); expect(baseElement2).toMatchSnapshot(); diff --git a/packages/sqle/src/page/OperationRecord/index.ce.test.tsx b/packages/sqle/src/page/OperationRecord/index.ce.test.tsx index e8f74c921..5f3ff4b2e 100644 --- a/packages/sqle/src/page/OperationRecord/index.ce.test.tsx +++ b/packages/sqle/src/page/OperationRecord/index.ce.test.tsx @@ -5,11 +5,24 @@ import { screen } from '@testing-library/react'; import OperationRecord from '.'; import { superRender } from '@actiontech/shared/lib/testUtil/superRender'; +import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; describe('slqe/OperationRecord CE', () => { test('should match snap shot', async () => { + mockUseCurrentProject({ + projectName: undefined + }); const { baseElement } = superRender(); expect(baseElement).toMatchSnapshot(); expect(screen.queryByText('导出')).not.toBeInTheDocument(); + expect(screen.getByText('全局操作记录')).toBeInTheDocument(); + }); + + test('should match snap shot when project name is exited', async () => { + mockUseCurrentProject({ + projectName: 'test' + }); + superRender(); + expect(screen.getByText('操作记录')).toBeInTheDocument(); }); }); diff --git a/packages/sqle/src/page/OperationRecord/index.tsx b/packages/sqle/src/page/OperationRecord/index.tsx index 949953316..d496f0ffc 100644 --- a/packages/sqle/src/page/OperationRecord/index.tsx +++ b/packages/sqle/src/page/OperationRecord/index.tsx @@ -3,12 +3,23 @@ import { PageHeader } from '@actiontech/dms-kit'; import { EnterpriseFeatureDisplay } from '@actiontech/shared'; import { Typography } from 'antd'; import OperationRecordList from './List'; +import { useCurrentProject } from '@actiontech/shared/lib/features'; + const OperationRecord = () => { const { t } = useTranslation(); + + const { projectName } = useCurrentProject(); + return ( <> {/* #if [ce] */} - + {/* #endif */} + }, + { + path: ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index, + key: 'globalOperationRecord', + element: , + permission: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD } ];