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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/shared/lib/api/sqle/service/SqlManage/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export interface IExportSqlManageV1Params {
sort_order?: exportSqlManageV1SortOrderEnum;

extra_filters?: string;

export_column_keys?: string;
}

export interface IExportSqlManageRemediationV1Params {
Expand Down
1 change: 1 addition & 0 deletions packages/sqle/src/locale/en-US/sqlManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default {
exporting: 'Exporting file',
exportSuccessTips: 'Export file successfully',
exportFailedTips: 'Export file failed',
noExportColumnTips: 'Please select at least one export column',
remediationExportCurrentProject:
'Export Current Project SQL Remediation Report',
remediationExportAllProjects:
Expand Down
1 change: 1 addition & 0 deletions packages/sqle/src/locale/zh-CN/sqlManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default {
exporting: '正在导出文件',
exportSuccessTips: '导出文件成功',
exportFailedTips: '导出文件失败',
noExportColumnTips: '请至少选择一个导出列',
remediationExportCurrentProject: '导出当前项目SQL整改报表',
remediationExportAllProjects: '导出所有项目SQL整改报表',
remediationExporting: '正在导出 SQL 管控整改报表',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import LocalStorageWrapper from '@actiontech/shared/lib/utils/LocalStorageWrapper';
import SqlManagementColumn from './column';
import {
getSqlManagementExportColumnKeys,
SQL_MANAGEMENT_TABLE_NAME
} from './exportColumnKeys';

const mockUpdateRemark = jest.fn();
const mockOpenModal = jest.fn();

const columns = SqlManagementColumn(
'700300',
true,
mockUpdateRemark,
mockOpenModal
);

describe('page/SqlManagement/SQLEEIndex/exportColumnKeys', () => {
afterEach(() => {
localStorage.clear();
jest.clearAllMocks();
});

it('return default export columns when current user has no settings', () => {
expect(getSqlManagementExportColumnKeys(columns, 'admin')).toEqual([
'sql_fingerprint',
'sql',
'source',
'audit_result',
'instance_name',
'schema_name',
'priority',
'assignees',
'endpoints',
'status',
'remark'
]);
});

it('return visible business columns by local settings order', () => {
LocalStorageWrapper.set(
SQL_MANAGEMENT_TABLE_NAME,
JSON.stringify({
admin: {
sql_fingerprint: { order: 2, show: true },
sql: { order: 1, show: true },
source: { order: 3, show: false },
audit_result: { order: 4, show: true },
selection: { order: 5, show: true },
action: { order: 6, show: true },
filter_business: { order: 7, show: true }
}
})
);

expect(getSqlManagementExportColumnKeys(columns, 'admin')).toEqual([
'sql',
'sql_fingerprint',
'audit_result',
'instance_name',
'schema_name',
'priority',
'assignees',
'endpoints',
'status',
'remark'
]);
});

it('return empty array when all export columns are hidden', () => {
LocalStorageWrapper.set(
SQL_MANAGEMENT_TABLE_NAME,
JSON.stringify({
admin: Object.fromEntries(
[
'sql_fingerprint',
'sql',
'source',
'audit_result',
'instance_name',
'schema_name',
'priority',
'assignees',
'endpoints',
'status',
'remark'
].map((columnKey, index) => [
columnKey,
{ order: index + 1, show: false }
])
)
})
);

expect(getSqlManagementExportColumnKeys(columns, 'admin')).toEqual([]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import LocalStorageWrapper from '@actiontech/shared/lib/utils/LocalStorageWrapper';
import { ActiontechTableColumn } from '@actiontech/shared/lib/components/ActiontechTable';
import { ISqlManage } from '@actiontech/shared/lib/api/sqle/service/common';
import { SqlManagementTableFilterParamType } from './column';

export const SQL_MANAGEMENT_TABLE_NAME = 'sql_management_list';

const SQL_MANAGEMENT_EXPORT_COLUMN_KEYS = [
'sql_fingerprint',
'sql',
'source',
'audit_result',
'instance_name',
'schema_name',
'priority',
'assignees',
'endpoints',
'status',
'remark'
] as const;

type SqlManagementExportColumnKey =
(typeof SQL_MANAGEMENT_EXPORT_COLUMN_KEYS)[number];

type SqlManagementColumnSettings = Partial<
Record<
string,
{
order?: number;
show?: boolean;
}
>
>;

const exportColumnKeySet = new Set<string>(SQL_MANAGEMENT_EXPORT_COLUMN_KEYS);

const getColumnDataIndex = (
dataIndex: ActiontechTableColumn<
ISqlManage,
SqlManagementTableFilterParamType
>[number]['dataIndex']
) => {
return typeof dataIndex === 'string' ? dataIndex : undefined;

Check warning on line 43 in packages/sqle/src/page/SqlManagement/component/SQLEEIndex/exportColumnKeys.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
};

const readLocalColumnSettings = (
tableName: string,
username: string
): SqlManagementColumnSettings => {
try {
const localColumns = JSON.parse(
LocalStorageWrapper.getOrDefault(tableName, '{}')
);
return localColumns?.[username] ?? {};
} catch {
return {};

Check warning on line 56 in packages/sqle/src/page/SqlManagement/component/SQLEEIndex/exportColumnKeys.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}
};

export const getSqlManagementExportColumnKeys = (
columns: ActiontechTableColumn<ISqlManage, SqlManagementTableFilterParamType>,
username: string,
tableName = SQL_MANAGEMENT_TABLE_NAME
): SqlManagementExportColumnKey[] => {
const localColumnSettings = readLocalColumnSettings(tableName, username);

return columns
.map((column, index) => {
const columnKey = getColumnDataIndex(column.dataIndex);
if (!columnKey || !exportColumnKeySet.has(columnKey)) {
return undefined;
}

const localSetting = localColumnSettings[columnKey];
return {
key: columnKey as SqlManagementExportColumnKey,
show: localSetting?.show ?? column.show ?? true,
order: localSetting?.order ?? index + 1,
defaultOrder: index + 1
};
})
.filter((column): column is NonNullable<typeof column> => {
return !!column && column.show;
})
.sort((currentColumn, nextColumn) => {
return (
currentColumn.order - nextColumn.order ||
currentColumn.defaultOrder - nextColumn.defaultOrder

Check warning on line 88 in packages/sqle/src/page/SqlManagement/component/SQLEEIndex/exportColumnKeys.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
);
})
.map((column) => column.key);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
exportSqlManageV1FilterPriorityEnum,
exportSqlManageRemediationV1ExportScopeEnum
} from '@actiontech/shared/lib/api/sqle/service/SqlManage/index.enum';
import LocalStorageWrapper from '@actiontech/shared/lib/utils/LocalStorageWrapper';
import { SQL_MANAGEMENT_TABLE_NAME } from './exportColumnKeys';

jest.mock('react-redux', () => {
return {
Expand Down Expand Up @@ -87,6 +89,7 @@ describe('page/SqlManagement/SQLEEIndex', () => {
jest.clearAllMocks();
jest.restoreAllMocks();
jest.clearAllTimers();
localStorage.clear();
cleanup();
});

Expand Down Expand Up @@ -243,7 +246,9 @@ describe('page/SqlManagement/SQLEEIndex', () => {
{
...exportParams,
filter_assignee: mockCurrentUserReturn.uid,
filter_priority: exportSqlManageV1FilterPriorityEnum.high
filter_priority: exportSqlManageV1FilterPriorityEnum.high,
export_column_keys:
'sql_fingerprint,sql,source,audit_result,instance_name,schema_name,priority,assignees,endpoints,status,remark'
},
{
responseType: 'blob'
Expand All @@ -253,6 +258,97 @@ describe('page/SqlManagement/SQLEEIndex', () => {
expect(screen.getByText('导出文件成功')).toBeInTheDocument();
});

it('export data with current visible column settings order', async () => {
const request = sqlManage.getSqlManageList();
const exportRequest = sqlManage.exportSqlManage();
superRender(<SQLEEIndex />);
expect(request).toHaveBeenCalled();

LocalStorageWrapper.set(
SQL_MANAGEMENT_TABLE_NAME,
JSON.stringify({
[mockCurrentUserReturn.username]: {
sql_fingerprint: { order: 2, show: true },
sql: { order: 1, show: true },
source: { order: 3, show: false },
audit_result: { order: 4, show: true },
instance_name: { order: 5, show: true },
schema_name: { order: 6, show: true },
priority: { order: 7, show: true },
assignees: { order: 8, show: false },
endpoints: { order: 9, show: true },
status: { order: 10, show: true },
remark: { order: 11, show: false },
selection: { order: 12, show: true }
}
})
);

const searchText = 'fingerprint keyword';
const inputEle = getBySelector('#actiontech-table-search-input');
fireEvent.change(inputEle, {
target: { value: searchText }
});

await act(async () => {
fireEvent.keyDown(inputEle, {
key: 'Enter',
code: 'Enter',
keyCode: 13
});
await jest.advanceTimersByTime(300);
});
await act(async () => jest.advanceTimersByTime(3000));

const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
await user.click(screen.getByText('导出报表'));
await user.click(await screen.findByText('导出 SQL管控报表'));

expect(exportRequest).toHaveBeenCalledWith(
{
...exportParams,
fuzzy_search_sql_fingerprint: searchText,
export_column_keys:
'sql,sql_fingerprint,audit_result,instance_name,schema_name,priority,endpoints,status'
},
{
responseType: 'blob'
}
);
});

it('show tips without export request when no visible export columns', async () => {
const request = sqlManage.getSqlManageList();
const exportRequest = sqlManage.exportSqlManage();
superRender(<SQLEEIndex />);
expect(request).toHaveBeenCalled();

LocalStorageWrapper.set(
SQL_MANAGEMENT_TABLE_NAME,
JSON.stringify({
[mockCurrentUserReturn.username]: {
sql_fingerprint: { order: 1, show: false },
sql: { order: 2, show: false },
source: { order: 3, show: false },
audit_result: { order: 4, show: false },
instance_name: { order: 5, show: false },
schema_name: { order: 6, show: false },
priority: { order: 7, show: false },
assignees: { order: 8, show: false },
endpoints: { order: 9, show: false },
status: { order: 10, show: false },
remark: { order: 11, show: false }
}
})
);

const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
await user.click(screen.getByText('导出报表'));
await user.click(await screen.findByText('导出 SQL管控报表'));
expect(exportRequest).not.toHaveBeenCalled();
expect(screen.getByText('请至少选择一个导出列')).toBeInTheDocument();
});

it('export remediation report for current project', async () => {
const request = sqlManage.getSqlManageList();
const exportRequest = sqlManage.exportSqlManageRemediation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ import { BlacklistResV1TypeEnum } from '@actiontech/shared/lib/api/sqle/service/
import { SqlManagementListStyleWrapper } from './style';
import { pickStaticSqlManageFilters } from './sourceExtra.utils';
import useSqlManageSourceExtra from './hooks/useSqlManageSourceExtra';
import {
getSqlManagementExportColumnKeys,
SQL_MANAGEMENT_TABLE_NAME
} from './exportColumnKeys';

const SQLEEIndex = () => {
const { t } = useTranslation();
Expand Down Expand Up @@ -331,7 +335,7 @@ const SQLEEIndex = () => {

const tableSetting = useMemo<ColumnsSettingProps>(
() => ({
tableName: 'sql_management_list',
tableName: SQL_MANAGEMENT_TABLE_NAME,
username: username
}),
[username]
Expand Down Expand Up @@ -370,6 +374,18 @@ const SQLEEIndex = () => {
{ setFalse: finishExport, setTrue: startExport }
] = useBoolean(false);
const handleExport = () => {
const exportColumnKeys = getSqlManagementExportColumnKeys(
columns,
username
);

if (!exportColumnKeys.length) {
messageApi.warning(
t('sqlManagement.pageHeader.action.noExportColumnTips')
);
return;
}

startExport();
const hideLoading = messageApi.loading(
t('sqlManagement.pageHeader.action.exporting')
Expand All @@ -385,7 +401,8 @@ const SQLEEIndex = () => {
? exportSqlManageV1FilterPriorityEnum.high
: undefined,
page_index: undefined,
page_size: undefined
page_size: undefined,
export_column_keys: exportColumnKeys.join(',')
} as IExportSqlManageV1Params;
SqlManage.exportSqlManageV1(params, { responseType: 'blob' })
.then((res) => {
Expand Down
Loading