Skip to content
This repository has been archived by the owner on Mar 2, 2022. It is now read-only.

feat: add dnd sort #31

Merged
merged 4 commits into from
Dec 23, 2019
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: 1 addition & 1 deletion README.en_US.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pro-table is encapsulated in an antd table, supports some presets, and encapsula
| request | a method to get the dataSource. | `(params?: {pageSize: number;current: number;[key: string]: any;}) => Promise<RequestData<T>>` | - |
| postData | Do some processing on the data obtained through the url. | `(data: T[]) => T[]` | - |
| defaultData | Default data array. | `T[]` | - |
| onInit | Triggered after the table data is successfully initialized, it will be triggered multiple times. | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| onPostAction | Triggered after the table data is successfully initialized, it will be triggered multiple times. | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| toolBarRender | Render toolbar, support for returning a dom array, will automatically increase margin-right. | `(action: UseFetchDataAction<RequestData<T>>) => React.ReactNode[]` | - |
| onLoad | Triggered after the data is loaded, it will be triggered multiple times. | `(dataSource: T[]) => void` | - |
| tableClassName | The className of the packaged table | string | - |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pro-table 在 antd 的 table 上进行了一层封装,支持了一些预设,
| request | 一个获得 dataSource 的方法 | `(params?: {pageSize: number;current: number;[key: string]: any;}) => Promise<RequestData<T>>` | - |
| postData | 对通过 url 获取的数据进行一些处理 | `(data: T[]) => T[]` | - |
| defaultData | 默认的数据 | `T[]` | - |
| onInit | 表格的数据初始化成功之后触发,会多次触发。 | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| onPostAction | 表格的数据初始化成功之后触发,会多次触发。 | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| toolBarRender | 渲染工具栏,支持返回一个 dom 数组,会自动增加 margin-right | `(action: UseFetchDataAction<RequestData<T>>) => React.ReactNode[]` | - |
| onLoad | 数据加载完成后触发,会多次触发 | `(dataSource: T[]) => void` | - |
| tableClassName | 封装的 table 的 className | string | - |
Expand Down
2 changes: 1 addition & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pro-table 在 antd 的 table 上进行了一层封装,支持了一些预设,
| request | 一个获得 dataSource 的方法 | `(params?: {pageSize: number;current: number;[key: string]: any;}) => Promise<RequestData<T>>` | - |
| postData | 对通过 url 获取的数据进行一些处理 | `(data: T[]) => T[]` | - |
| defaultData | 默认的数据 | `T[]` | - |
| onInit | 表格的数据初始化成功之后触发,会多次触发。 | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| onPostAction | 表格的数据初始化成功之后触发,会多次触发。 | `(action: UseFetchDataAction<RequestData<T>>) => void` | [] |
| toolBarRender | 渲染工具栏,支持返回一个 dom 数组,会自动增加 margin-right | `(action: UseFetchDataAction<RequestData<T>>) => React.ReactNode[]` | - |
| onLoad | 数据加载完成后触发,会多次触发 | `(dataSource: T[]) => void` | - |
| tableClassName | 封装的 table 的 className | string | - |
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@
"@ant-design/icons": "^4.0.0-alpha.11",
"antd": "^3.25.1",
"classnames": "^2.2.6",
"dnd-core": "^10.0.2",
"moment": "^2.24.0",
"rc-resize-observer": "^0.1.3",
"react-dnd": "^10.0.2",
"react-dnd-html5-backend": "^10.0.2",
"unstated-next": "^1.1.0",
"use-merge-value": "^1.0.1"
},
Expand Down
101 changes: 67 additions & 34 deletions src/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './index.less';

import React, { useEffect, CSSProperties, useRef, useState, ReactNode } from 'react';
import { Table, Card, Typography, Tooltip } from 'antd';
import { Table, Card, Typography, Empty, Tooltip } from 'antd';
import classNames from 'classnames';
import useMergeValue from 'use-merge-value';
import moment from 'moment';
Expand All @@ -13,7 +13,7 @@ import Toolbar, { OptionsType, ToolBarProps } from './component/toolBar';
import Alert from './component/alert';
import FormSearch from './Form';
import { StatusType } from './component/status';
import { parsingText, parsingValueEnumToArray } from './component/util';
import { parsingText, parsingValueEnumToArray, checkUndefinedOrNull } from './component/util';

/**
* money 金额
Expand Down Expand Up @@ -103,6 +103,10 @@ export interface ProColumns<T = unknown> extends Omit<ColumnProps<T>, 'render' |
* 在 table 中隐藏
*/
hideInTable?: boolean;
/**
* from 的排序
*/
order?: number;
}

export interface ProTableProps<T> extends Omit<TableProps<T>, 'columns' | 'rowSelection'> {
Expand Down Expand Up @@ -137,7 +141,7 @@ export interface ProTableProps<T> extends Omit<TableProps<T>, 'columns' | 'rowSe
/**
* 初始化的参数,可以操作 table
*/
onInit?: (action: {
onPostAction?: (action: {
fetch: () => Promise<void>;
reload: () => Promise<void>;
fetchMore: () => void;
Expand Down Expand Up @@ -221,23 +225,30 @@ const mergePagination = <T extends any[], U>(
pageSize,
onChange: (page: number, newPageSize?: number) => {
// pageSize 改变之后就没必要切换页码
if (newPageSize !== pageSize) {
action.setPageSize(pageSize);
} else if (current !== page) {
action.setCurrent(page);
if (newPageSize !== pageSize && current !== page) {
action.setPageInfo({ pageSize, page });
} else {
if (newPageSize !== pageSize) {
action.setPageInfo({ pageSize });
}
if (current !== page) {
action.setPageInfo({ page });
}
}

const { onChange } = pagination as PaginationConfig;
if (onChange) {
onChange(page, newPageSize || 10);
}
},
onShowSizeChange: (curt: number, size: number) => {
action.setPageSize(size);
action.setCurrent(curt);

onShowSizeChange: (page: number, showPageSize: number) => {
action.setPageInfo({
pageSize: showPageSize,
page,
});
const { onShowSizeChange } = pagination as PaginationConfig;
if (onShowSizeChange) {
onShowSizeChange(curt, size || 10);
onShowSizeChange(page, showPageSize || 10);
}
},
};
Expand Down Expand Up @@ -378,7 +389,7 @@ const ColumRender = <T, U = any>({ item, text, row, index }: ColumRenderInterfac
}
return renderDom as React.ReactNode;
}
return (dom as React.ReactNode) || null;
return checkUndefinedOrNull(dom) ? dom : null;
};

const genColumnList = <T, U = {}>(
Expand All @@ -389,7 +400,7 @@ const genColumnList = <T, U = {}>(
},
): ColumnProps<T>[] =>
columns
.map(item => {
.map((item, columnsIndex) => {
const { key, dataIndex } = item;
const columnKey = `${key || ''}-${dataIndex || ''}`;
const config = map[columnKey] || { fixed: item.fixed };
Expand All @@ -398,6 +409,7 @@ const genColumnList = <T, U = {}>(
const itemValue = String(record[item.dataIndex || ''] || '') as string;
return String(itemValue) === String(value);
},
index: columnsIndex,
filters: parsingValueEnumToArray(item.valueEnum),
...item,
fixed: config.fixed,
Expand Down Expand Up @@ -425,7 +437,7 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {
headerTitle,
postData,
pagination: propsPagination,
onInit,
onPostAction,
columns: propsColumns = [],
toolBarRender = () => [],
onLoad,
Expand All @@ -442,6 +454,7 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {
} = props;

const [formSearch, setFormSearch] = useState<{}>({});

/**
* 需要初始化 不然默认可能报错
*/
Expand Down Expand Up @@ -472,39 +485,52 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {
onLoad,
effects: [
Object.values(params)
.filter(item => item)
.filter(item => checkUndefinedOrNull(item))
.join('-'),
Object.values(formSearch)
.filter(item => item)
.filter(item => checkUndefinedOrNull(item))
.join('-'),
],
},
);

const rootRef = useRef<HTMLDivElement>(null);

action.fullScreen = () => {
if (!rootRef.current || !document.fullscreenEnabled) {
return;
}
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
rootRef.current.requestFullscreen();
}
};

useEffect(() => {
// 页码更改的时候触发一下
// 不然会造成 action 中数据老旧
if (onInit) {
onInit({
if (onPostAction) {
onPostAction({
reload: action.reload,
fetch: action.fetch,
fetchMore: action.fetchMore,
});
}
}, []);
}, [
action.pageSize,
action.current,
action.total,
Object.values(params)
.filter(item => checkUndefinedOrNull(item))
.join('-'),
Object.values(formSearch)
.filter(item => checkUndefinedOrNull(item))
.join('-'),
]);

const fullScreen = useRef<() => void>();
useEffect(() => {
fullScreen.current = () => {
if (!rootRef.current || !document.fullscreenEnabled) {
return;
}
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
rootRef.current.requestFullscreen();
}
};
}, [rootRef.current]);

action.fullScreen = fullScreen.current;

const pagination = mergePagination<T[], {}>(propsPagination, action);

Expand Down Expand Up @@ -537,6 +563,9 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {

// 映射 selectedRowKeys 与 selectedRow
useEffect(() => {
if (action.loading !== false || propsRowSelection === false) {
return;
}
const tableKey = reset.rowKey;
setSelectedRows(
((action.dataSource as T[]) || []).filter((item, index) => {
Expand All @@ -550,7 +579,7 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {
return (selectedRowKeys as any).includes(item[tableKey]);
}),
);
}, [selectedRowKeys.join('-'), action.loading]);
}, [selectedRowKeys.join('-'), action.loading, propsRowSelection === false]);

const rowSelection: TableRowSelection<T> = {
selectedRowKeys,
Expand All @@ -563,6 +592,10 @@ const ProTable = <T, U = {}>(props: ProTableProps<T>) => {
},
};

if (counter.columns.length < 1) {
return <Empty />;
}

return (
<div className={className} id="ant-design-pro-table" style={style} ref={rootRef}>
{search && (
Expand Down
98 changes: 98 additions & 0 deletions src/component/columnSetting/DndItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useRef } from 'react';
import { XYCoord } from 'dnd-core';
import { useDrag, useDrop, DropTargetMonitor } from 'react-dnd';

export interface CardProps {
id: any;
index: number;
move?: (dragIndex: number, hoverIndex: number) => void;
end: (id: string, dragIndex: number) => void;
}

interface DragItem {
index: number;
id: string;
type: string;
}
const ItemTypes = {
CARD: 'card',
};

const Card: React.FC<CardProps> = ({ id, end, move, children, index }) => {
const ref = useRef<HTMLDivElement>(null);
const [, drop] = useDrop({
accept: ItemTypes.CARD,
hover(item: DragItem, monitor: DropTargetMonitor) {
if (!ref.current) {
return;
}
const dragIndex = item.index;
const hoverIndex = index;

// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}

// Determine rectangle on screen
const hoverBoundingRect = ref.current!.getBoundingClientRect();

// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

// Determine mouse position
const clientOffset = monitor.getClientOffset();

// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top;

// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%

// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}

// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action

if (move) {
move(dragIndex, hoverIndex);
}

// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex;
},
});

const [{ isDragging }, drag] = useDrag({
item: { type: ItemTypes.CARD, id, index },
collect: (monitor: any) => ({
isDragging: monitor.isDragging(),
}),
end: (item?: { id: string; index: number }) => {
if (!item) {
return;
}
end(item.id, item.index);
},
});

const opacity = isDragging ? 0 : 1;
drag(drop(ref));
return (
<div ref={ref} style={{ opacity }}>
{children}
</div>
);
};

export default Card;
3 changes: 2 additions & 1 deletion src/component/columnSetting/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
font-size: 12px;
}
&-item {
display: block;
width: 100%;
&-option {
display: none;
float: right;
cursor: pointer;
> span {
> i.anticon {
color: @primary-color;
cursor: pointer;
}
}
> span + span {
Expand Down
Loading