diff --git a/src/Filter.js b/src/Filter.js index 9677fd6..77cbb83 100644 --- a/src/Filter.js +++ b/src/Filter.js @@ -1,5 +1,6 @@ import React, { Component, PropTypes } from 'react'; import { Creatable } from 'react-select'; +import { createTextFilter } from './common'; const propTypes = { value: PropTypes.array, @@ -21,14 +22,7 @@ class Filter extends Component { placeholder="Search by text or tags" promptTextCreator={(txt) => `Search for '${txt}'`} onChange={(selected) => onChange(selected)} - newOptionCreator={({ label, labelKey, valueKey }) => { - const option = {}; - option[valueKey] = label.toLowerCase(); - option[labelKey] = label.toLowerCase(); - option.textFilter = true; - option.className = 'Select-create-option-placeholder'; - return option; - }} + newOptionCreator={({ label }) => createTextFilter(label)} value={value} multi style={{ diff --git a/src/actions.js b/src/actions.js index 45f9ee6..a11597b 100644 --- a/src/actions.js +++ b/src/actions.js @@ -7,6 +7,7 @@ export const TABLE_SORT_CHANGED = 'sematable/TABLE_SORT_CHANGED'; export const TABLE_ROW_CHECKED_CHANGED = 'sematable/TABLE_ROW_CHECKED_CHANGED'; export const TABLE_SELECT_ALL_CHANGED = 'sematable/TABLE_SELECT_ALL_CHANGED'; export const TABLE_DESTROY_STATE = 'sematable/TABLE_DESTROY_STATE'; +export const TABLE_SET_FILTER = 'sematable/TABLE_SET_FILTER'; export const tableInitialize = (tableName, initialData, columns, configs) => ({ type: TABLE_INITIALIZE, @@ -79,3 +80,11 @@ export const tableDestroyState = (tableName) => ({ tableName, }, }); + +export const tableSetFilter = (tableName, filterValue) => ({ + type: TABLE_SET_FILTER, + payload: { + tableName, + filterValue, + }, +}); diff --git a/src/common.js b/src/common.js new file mode 100644 index 0000000..1e5fe1d --- /dev/null +++ b/src/common.js @@ -0,0 +1,34 @@ +import _ from 'lodash'; + +export const createTextFilter = (text) => ({ + value: text.toLowerCase(), + label: text.toLowerCase(), + textFilter: true, + className: 'Select-create-option-placeholder', +}); + +export const createValueFilter = (column, value) => { + const { + key, + getValueTitle = () => undefined, + getValueClassName = () => undefined, + getValueLabel = () => { + let labelValue = value; + if (_.isBoolean(value)) { + labelValue = value ? 'Yes' : 'No'; + } + return `${column.header}:${labelValue}`; + }, + } = column; + const title = getValueTitle(value); + const label = getValueLabel(value); + const className = getValueClassName(value); + return { + key, + label, + value, + title, + className, + valueFilter: true, + }; +}; diff --git a/src/reducer.js b/src/reducer.js index a3ee9f5..503d460 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -10,7 +10,9 @@ import { TABLE_SELECT_ALL_CHANGED, TABLE_ROW_CHECKED_CHANGED, TABLE_DESTROY_STATE, + TABLE_SET_FILTER, } from './actions.js'; +import { createTextFilter, createValueFilter } from './common'; const defaultState = (configs = {}) => ({ page: 0, @@ -46,6 +48,20 @@ const behaviours = { ...state, initialData: payload.data, }), + [TABLE_SET_FILTER]: (state, { payload }) => { + const columnMap = _.keyBy(state.columns, 'key'); + const filter = payload.filterValue.map(f => { + if (_.isString(f)) { + return createTextFilter(f); + } + const column = columnMap[f.key]; + return createValueFilter(column, f.value); + }); + return { + ...state, + filter, + }; + }, [TABLE_PAGE_CHANGED]: (state, { payload }) => ({ ...state, page: payload.page, diff --git a/src/selectors.js b/src/selectors.js index 3ad954b..5a6f16f 100644 --- a/src/selectors.js +++ b/src/selectors.js @@ -1,5 +1,6 @@ -import { createSelector } from 'reselect'; import _ from 'lodash'; +import { createSelector } from 'reselect'; +import { createValueFilter } from './common'; function paginate(rows, { page, pageSize }) { if (pageSize < 1) { @@ -119,28 +120,7 @@ export default (tableName) => { _.forOwn(values, (columnValues, key) => { columnValues.forEach(value => { const column = columnMap[key]; - const { - getValueTitle = () => undefined, - getValueClassName = () => undefined, - getValueLabel = () => { - let labelValue = value; - if (_.isBoolean(value)) { - labelValue = value ? 'Yes' : 'No'; - } - return `${column.header}:${labelValue}`; - }, - } = column; - const title = getValueTitle(value); - const label = getValueLabel(value); - const className = getValueClassName(value); - options.push({ - key, - label, - value, - title, - className, - valueFilter: true, - }); + options.push(createValueFilter(column, value)); }); }); diff --git a/src/sematable.js b/src/sematable.js index f109746..cc65adb 100644 --- a/src/sematable.js +++ b/src/sematable.js @@ -14,6 +14,7 @@ import { tableSortChanged, tableRowCheckedChanged, tableSelectAllChanged, + tableSetFilter, } from './actions.js'; const propTypes = { @@ -28,6 +29,7 @@ const propTypes = { selectedRows: PropTypes.array, primaryKey: PropTypes.string, filterOptions: PropTypes.array, + filterValue: PropTypes.array, onPageChange: PropTypes.func.isRequired, onPageSizeChange: PropTypes.func.isRequired, @@ -35,6 +37,7 @@ const propTypes = { onHeaderClick: PropTypes.func.isRequired, onInitialize: PropTypes.func.isRequired, onNewData: PropTypes.func.isRequired, + onNewFilterValue: PropTypes.func.isRequired, onRowCheckedChange: PropTypes.func.isRequired, onSelectAllChange: PropTypes.func.isRequired, }; @@ -82,6 +85,7 @@ const sematable = (tableName, TableComponent, columns, configs = {}) => { onFilterChange: (filter) => dispatch(tableFilterChanged(tableName, filter)), onHeaderClick: (sortKey) => dispatch(tableSortChanged(tableName, sortKey)), onNewData: (data) => dispatch(tableNewData(tableName, data)), + onNewFilterValue: (data) => dispatch(tableSetFilter(tableName, data)), onSelectAllChange: () => dispatch(tableSelectAllChanged(tableName)), onRowCheckedChange: (row) => dispatch(tableRowCheckedChanged(tableName, row)), onInitialize: (data) => dispatch(tableInitialize(tableName, data, columns, configs)), @@ -94,10 +98,21 @@ const sematable = (tableName, TableComponent, columns, configs = {}) => { } componentWillReceiveProps(nextProps) { - const { data, onNewData } = this.props; + const { + data, + filterValue, + onNewData, + onNewFilterValue, + } = this.props; + if (data !== nextProps.data) { onNewData(nextProps.data); } + + if (filterValue !== nextProps.filterValue) { + console.log(filterValue); + onNewFilterValue(filterValue); + } } render() { diff --git a/stories/index.js b/stories/index.js index 89d70b4..3f8e691 100644 --- a/stories/index.js +++ b/stories/index.js @@ -37,7 +37,13 @@ storiesOf('Sematable', module) > Reset state - + ));