implement sort context

This commit is contained in:
AllenFang
2018-05-13 16:14:21 +08:00
parent 6d08a24a8f
commit 2525465a5a
3 changed files with 99 additions and 92 deletions

View File

@@ -0,0 +1,88 @@
import React from 'react';
import PropTypes from 'prop-types';
import Const from '../const';
import { sort, nextOrder } from '../store/sort';
import remoteResolver from '../props-resolver/remote-resolver';
export default () => {
const SortContext = React.createContext();
class SortProvider extends remoteResolver(React.Component) {
static propTypes = {
columns: PropTypes.array.isRequired,
defaultSorted: PropTypes.arrayOf(PropTypes.shape({
dataField: PropTypes.string.isRequired,
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
})),
defaultSortDirection: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC])
}
constructor(props) {
super(props);
let sortOrder;
let sortColumn;
const { columns, defaultSorted, defaultSortDirection } = props;
if (defaultSorted && defaultSorted.length > 0) {
const sortField = defaultSorted[0].dataField;
sortOrder = defaultSorted[0].order || defaultSortDirection;
const sortColumns = columns.filter(col => col.dataField === sortField);
if (sortColumns.length > 0) {
sortColumn = sortColumns[0];
if (sortColumn.onSort) {
sortColumn.onSort(sortField, sortOrder);
}
if (this.isRemoteSort() || this.isRemotePagination()) {
this.handleSortChange();
}
}
}
this.state = { sortOrder, sortColumn };
}
handleSort = (column) => {
const sortOrder = nextOrder(column, this.state, this.props.defaultSortDirection);
if (column.onSort) {
column.onSort(column.dataField, sortOrder);
}
if (this.isRemoteSort() || this.isRemotePagination()) {
this.handleSortChange();
} else {
this.setState(() => ({
sortOrder,
sortColumn: column
}));
}
}
render() {
let { data } = this.props;
const { sortOrder, sortColumn } = this.state;
if (!this.isRemoteSort() && !this.isRemotePagination() && sortColumn) {
data = sort(data, sortOrder, sortColumn);
}
return (
<SortContext.Provider
value={ {
data,
sortOrder,
onSort: this.handleSort,
sortField: sortColumn ? sortColumn.dataField : null
} }
>
{ this.props.children }
</SortContext.Provider>
);
}
}
return {
Provider: SortProvider,
Consumer: SortContext.Consumer
};
};

View File

@@ -1,81 +0,0 @@
/* eslint react/prop-types: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import remoteResolver from '../props-resolver/remote-resolver';
export default Base =>
class SortWrapper extends remoteResolver(Component) {
static propTypes = {
store: PropTypes.object.isRequired
}
constructor(props) {
super(props);
this.handleSort = this.handleSort.bind(this);
}
componentWillMount() {
const { columns, defaultSorted, defaultSortDirection, store } = this.props;
// defaultSorted is an array, it's ready to use as multi / single sort
// when we start to support multi sort, please update following code to use array.forEach
if (defaultSorted && defaultSorted.length > 0) {
const dataField = defaultSorted[0].dataField;
const order = defaultSorted[0].order;
const column = columns.filter(col => col.dataField === dataField);
if (column.length > 0) {
store.setSort(column[0], order, defaultSortDirection);
if (column[0].onSort) {
column[0].onSort(store.sortField, store.sortOrder);
}
if (this.isRemoteSort() || this.isRemotePagination()) {
this.handleSortChange();
} else {
store.sortBy(column[0]);
}
}
}
}
componentWillReceiveProps(nextProps) {
if (!this.isRemoteSort() && !this.isRemotePagination()) {
let sortedColumn;
for (let i = 0; i < nextProps.columns.length; i += 1) {
if (nextProps.columns[i].dataField === nextProps.store.sortField) {
sortedColumn = nextProps.columns[i];
break;
}
}
if (sortedColumn && sortedColumn.sort) {
nextProps.store.sortBy(sortedColumn);
}
}
}
handleSort(column) {
const { store } = this.props;
store.setSort(column, undefined, this.props.defaultSortDirection);
if (column.onSort) {
column.onSort(store.sortField, store.sortOrder);
}
if (this.isRemoteSort() || this.isRemotePagination()) {
this.handleSortChange();
} else {
store.sortBy(column);
this.forceUpdate();
}
}
render() {
return (
<Base
{ ...this.props }
onSort={ this.handleSort }
data={ this.props.store.data }
/>
);
}
};

View File

@@ -14,17 +14,17 @@ function comparator(a, b) {
return result;
}
export const sort = ({ data, sortOrder, sortField }) => (sortFunc) => {
export const sort = (data, sortOrder, { dataField, sortFunc }) => {
const _data = [...data];
_data.sort((a, b) => {
let result;
let valueA = _.get(a, sortField);
let valueB = _.get(b, sortField);
let valueA = _.get(a, dataField);
let valueB = _.get(b, dataField);
valueA = _.isDefined(valueA) ? valueA : '';
valueB = _.isDefined(valueB) ? valueB : '';
if (sortFunc) {
result = sortFunc(valueA, valueB, sortOrder, sortField);
result = sortFunc(valueA, valueB, sortOrder, dataField);
} else {
if (sortOrder === Const.SORT_DESC) {
result = comparator(valueA, valueB);
@@ -37,11 +37,11 @@ export const sort = ({ data, sortOrder, sortField }) => (sortFunc) => {
return _data;
};
export const nextOrder = store => (field, order, defaultOrder = Const.SORT_DESC) => {
if (order) return order;
if (field !== store.sortField) {
return defaultOrder;
}
return store.sortOrder === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
export const nextOrder = (
currentSortColumn,
{ sortOrder, sortColumn },
defaultOrder = Const.SORT_DESC
) => {
if (!sortColumn || currentSortColumn.dataField !== sortColumn.dataField) return defaultOrder;
return sortOrder === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
};