Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codemod): getTableData => useTableData for util #161

Merged
merged 1 commit into from
Oct 8, 2023
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
16 changes: 9 additions & 7 deletions packages/codemod/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ npx -p @oceanbase/codemod codemod src

### `antd-to-oceanbase-design`

import components and typs from `antd` and `@alipay/bigfish/antd` to `@oceanbase/design`.
import components and types from `antd` and `@alipay/bigfish/antd` to `@oceanbase/design`.

```diff
import React from 'react';
Expand All @@ -43,7 +43,7 @@ import components and typs from `antd` and `@alipay/bigfish/antd` to `@oceanbase

### `obui-to-oceanbase-design-and-ui`

import components and typs from `antd` to `@oceanbase/design` and `@oceanbase/ui`.
import components and types from `antd` to `@oceanbase/design` and `@oceanbase/ui`.

```diff
import React from 'react';
Expand Down Expand Up @@ -86,7 +86,7 @@ import `PageContainer` from `@alipay/tech-ui` to `@ant-design/pro-components` an

### `antd-and-ob-charts-to-oceanbase-charts`

import components and typs from `@ant-design/charts` and `@alipay/ob-charts` to `@oceanbase/charts`.
import components and types from `@ant-design/charts` and `@alipay/ob-charts` to `@oceanbase/charts`.

```diff
import React from 'react';
Expand Down Expand Up @@ -118,15 +118,17 @@ import components and typs from `@ant-design/charts` and `@alipay/ob-charts` to

### `obutil-to-oceanbase-util`

import components and typs from `@alipay/ob-util` to `@oceanbase/util`.
import utils and hooks from `@alipay/ob-util` to `@oceanbase/util`. Additionally, it will rename `getTableData` to `useTableData` to follow hooks naming conventions.

```diff
import React from 'react';
- import { isNullValue, sortByNumber } from '@alipay/ob-util';
+ import { isNullValue, sortByNumber } from '@oceanbase/util';
- import { isNullValue, sortByNumber, getTableData } from '@alipay/ob-util';
+ import { isNullValue, sortByNumber, useTableData } from '@oceanbase/util';

const Demo = () => {
return <div />;
- const { tableProps } = getTableData(fn, {});
+ const { tableProps } = useTableData(fn, {});
return <div />;
};

export default Demo;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { getTableData } from '@alipay/ob-util';

const Demo = () => {
const { tableProps, refresh } = getTableData({
fn: getClusters,
params: {
configName,
},
refreshDeps: [],
options: {
pagePropName: 'pageNo',
sizePropName: 'pageSize',
formatResult: (res: any) => {
const { data, pageNo, pageSize, total } = res || {};
return {
list: data || [],
current: pageNo,
pageSize,
total,
};
},
},
});
return <div />;
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { useTableData } from '@oceanbase/util';

const Demo = () => {
const { tableProps, refresh } = useTableData({
fn: getClusters,
params: {
configName,
},
refreshDeps: [],
options: {
pagePropName: 'pageNo',
sizePropName: 'pageSize',
formatResult: (res: any) => {
const { data, pageNo, pageSize, total } = res || {};
return {
list: data || [],
current: pageNo,
pageSize,
total,
};
},
},
});
return <div />;
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineTest } from 'jscodeshift/src/testUtils';

const testUnit = 'obutil-to-oceanbase-util';
const tests = ['obutil'];
const tests = ['obutil', 'getTableData'];

describe(testUnit, () => {
tests.forEach(test =>
Expand Down
9 changes: 9 additions & 0 deletions packages/codemod/transforms/obutil-to-oceanbase-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ module.exports = (file, api, options) => {
...options,
fromPkgNames: '@alipay/ob-util',
toPkgList: [
{
name: '@oceanbase/util',
components: [
{
// rename
getTableData: 'useTableData',
},
],
},
{
name: '@oceanbase/util',
},
Expand Down
33 changes: 27 additions & 6 deletions packages/codemod/transforms/utils/import-component.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { addSubmoduleImport, removeEmptyModuleImport, parseStrToArray } = require('./index');
const { markDependency } = require('./marker');
const { printOptions } = require('./config');
const { isPlainObject } = require('lodash');
const { flatten } = require('lodash');

function importComponent(j, root, options) {
const { fromPkgNames, toPkgList } = options;
Expand All @@ -15,11 +17,15 @@ function importComponent(j, root, options) {
);
if (fromPkgName) {
path.value.specifiers.forEach(specifier => {
const toPkgByComponents = toPkgList.find(toPkg =>
toPkg.components?.includes(specifier.imported.name)
const toPkgByComponents = toPkgList.find(
toPkg =>
toPkg.components?.includes(specifier.imported.name) ||
toPkg.components?.find(component => component[specifier.imported.name])
);
const toPkgByTypes = toPkgList.find(toPkg =>
toPkg.types?.includes(specifier.imported.name)
const toPkgByTypes = toPkgList.find(
toPkg =>
toPkg.types?.includes(specifier.imported.name) ||
toPkg.types?.find(type => type[specifier.imported.name])
);
const toPkg = toPkgByComponents || toPkgByTypes;
if (toPkg) {
Expand All @@ -31,13 +37,28 @@ function importComponent(j, root, options) {
path.value.specifiers = path.value.specifiers.filter(
item => !item.imported || item.imported.name !== specifier.imported.name
);
// add new imports
const renameComponent = toPkg.components?.find(
component => component[specifier.imported.name]
);
const renameType = toPkg.types?.find(type => type[specifier.imported.name]);
const rename = renameComponent || renameType;
// add and rename new imports
addSubmoduleImport(j, root, {
moduleName: toPkg.name,
importedName: specifier.imported.name,
importedName: rename ? rename[specifier.imported.name] : specifier.imported.name,
importKind: toPkgByTypes ? 'type' : 'value',
after: fromPkgName,
});
// rename used part
if (rename) {
root
.find(j.Identifier, {
name: specifier.imported.name,
})
.forEach(path => {
path.node.name = rename[specifier.imported.name];
});
}
}
markDependency(toPkg.name);
}
Expand Down
94 changes: 1 addition & 93 deletions packages/util/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,3 @@
import { some, isNil, noop, omitBy } from 'lodash';
import { useAntdTable } from 'ahooks';
import { DEFAULT_LIST_DATA } from '../constant';
import { isNullValue } from '../util';

const sortOrderMap = {
ascend: 'asc',
descend: 'desc',
};

const defaultAsnycFnOfUseTableData = () => {
const promise = new Promise(resolve => {
resolve({
tableProps: {
dataSource: [],
loading: false,
pagination: {
total: 0,
current: 1,
pageSize: 10,
},
},
refresh: noop,
search: {
changeType: noop,
submit: noop,
reset: noop,
},
});
});
promise.then(data => {
return data;
});
return promise;
};

/**
* 获取表格数据,内置后端分页、筛选和排序的请求逻辑,同时支持条件请求
* TODO: 后续需要补全 TS 类型定义
*/
export function useTableData({ fn, params = {}, condition = [], refreshDeps = [], options = {} }) {
const { pagePropName = 'page', sizePropName = 'size', ...restOptions } = options as any;
const newOptions = {
formatResult: res => {
const { data } = (res || {}) as any;
// 接口请求出错时,后端返回的 res.data 可能为 undefined。避免前端解析错误导致页面崩溃,这里需要做健壮性处理
const { page: { totalElements = 0 } = {}, contents = [] } = data || DEFAULT_LIST_DATA;
return {
total: totalElements,
list: contents,
};
},
refreshDeps,
...restOptions,
};

const serviceFn = some(condition, item => isNullValue(item))
? defaultAsnycFnOfUseTableData
: ({ current, pageSize, sorter = {}, filters = {} }) => {
// eslint-disable-next-line
let newFilters = {} as any;
Object.keys(filters).forEach(key => {
// antd 4.x 的表格筛选,在筛选项为空时,对应字段为 null 值,为了适配这里调用 join 方法前需要做非空判断
newFilters[key] = filters[key] && filters[key].join(',');
});
// 对列表查询参数进行处理
const newParams = omitBy(
{
[pagePropName]: current,
[sizePropName]: pageSize,
// @ts-ignore
sort: sorter.order
? // @ts-ignore
`${sorter.field},${sortOrderMap[sorter.order as 'ascend' | 'descend']}`
: null,
...newFilters,
...params,
},
value => isNil(value) || value === '' // 将空值剔除
);
return fn(newParams);
};

const result = useAntdTable(serviceFn, newOptions);
if (result) {
// @ts-ignore
result.tableProps.pagination.showSizeChanger = true;
// @ts-ignore
result.tableProps.pagination.showTotal = (total: number) => `共 ${total} 条`;
}
return result;
}

export { useTableData } from './useTableData';
export { useQuery } from './useQuery';
export { useScrollToPosition } from './useScrollToPosition';
92 changes: 92 additions & 0 deletions packages/util/src/hooks/useTableData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { some, isNil, noop, omitBy } from 'lodash';
import { useAntdTable } from 'ahooks';
import { DEFAULT_LIST_DATA } from '../constant';
import { isNullValue } from '../util';

const sortOrderMap = {
ascend: 'asc',
descend: 'desc',
};

const defaultAsnycFnOfUseTableData = () => {
const promise = new Promise(resolve => {
resolve({
tableProps: {
dataSource: [],
loading: false,
pagination: {
total: 0,
current: 1,
pageSize: 10,
},
},
refresh: noop,
search: {
changeType: noop,
submit: noop,
reset: noop,
},
});
});
promise.then(data => {
return data;
});
return promise;
};

/**
* 获取表格数据,内置后端分页、筛选和排序的请求逻辑,同时支持条件请求
* TODO: 后续需要补全 TS 类型定义
*/
export function useTableData({ fn, params = {}, condition = [], refreshDeps = [], options = {} }) {
const { pagePropName = 'page', sizePropName = 'size', ...restOptions } = options as any;
const newOptions = {
formatResult: res => {
const { data } = (res || {}) as any;
// 接口请求出错时,后端返回的 res.data 可能为 undefined。避免前端解析错误导致页面崩溃,这里需要做健壮性处理
const { page: { totalElements = 0 } = {}, contents = [] } = data || DEFAULT_LIST_DATA;
return {
total: totalElements,
list: contents,
};
},
refreshDeps,
...restOptions,
};

const serviceFn = some(condition, item => isNullValue(item))
? defaultAsnycFnOfUseTableData
: ({ current, pageSize, sorter = {}, filters = {} }) => {
// eslint-disable-next-line
let newFilters = {} as any;
Object.keys(filters).forEach(key => {
// antd 4.x 的表格筛选,在筛选项为空时,对应字段为 null 值,为了适配这里调用 join 方法前需要做非空判断
newFilters[key] = filters[key] && filters[key].join(',');
});
// 对列表查询参数进行处理
const newParams = omitBy(
{
[pagePropName]: current,
[sizePropName]: pageSize,
// @ts-ignore
sort: sorter.order
? // @ts-ignore
`${sorter.field},${sortOrderMap[sorter.order as 'ascend' | 'descend']}`
: null,
...newFilters,
...params,
},
value => isNil(value) || value === '' // 将空值剔除
);
return fn(newParams);
};

const result = useAntdTable(serviceFn, newOptions);
if (result) {
// @ts-ignore
result.tableProps.pagination.showSizeChanger = true;
// @ts-ignore
result.tableProps.pagination.showTotal = (total: number) => `共 ${total} 条`;
}
return result;
}