Commit 284d268c authored by Valeriy Panov's avatar Valeriy Panov
Browse files

#179 Pretty filters display

parent 1edc819c
import * as React from 'react';
import { connect } from 'react-redux';
import {withStyles} from 'material-ui/styles';
import Chip from 'material-ui/Chip';
import Paper from 'material-ui/Paper';
import * as flattenjs from 'flattenjs';
import * as _ from 'lodash';
import {Descriptor} from 'model/descriptor.model';
/**
* filterObj example: {crop: ["bannana", "apple"], description: {contains: "de"}, title: {contains: "ti"}}
* If we want to replace the code with a title for showing, we need lookups object.
* It contains pairs key - value:
* where key - should be equal to filterObj key which values we want to substitute.
* where value - object of codes and titles we want to show.
* lookups example: {
* crop: {
* banana: 'Banana',
* apple: 'Apple',
* ...
* },
* ...
* }
*/
interface IPrettyFiltersProps extends React.ClassAttributes<any> {
classes: any;
onSubmit: (newFilter) => any;
filterObj: object;
lookups: object;
}
const styles = (theme) => ({
root: {
display: 'flex',
justifyContent: 'center' as 'center',
flexWrap: 'wrap' as 'wrap',
padding: theme.spacing.unit / 2,
},
chip: {
margin: theme.spacing.unit / 2,
},
});
// Following keywords are skipped for showing
const keywordsToSkip = ['ge', 'gt', 'le', 'lt', 'eq', 'contains', 'sw'];
/**
* Remove value by path from filterObj and return updated filterObj.
* @param filterObj - IPrettyFiltersProps.filterObj.
* @param path - path to value to remove.
* @return IPrettyFiltersProps.filterObj.
*/
function handleFilterObj(filterObj, path) {
// array element
if (path.endsWith(']')) {
const clone = _.clone(filterObj, true);
const lastIndex = path.lastIndexOf('[');
const arrayPath = path.substring(0, lastIndex);
const index = parseInt(path.substring(lastIndex).replace(/[\[\]']+/g, ''), 10);
_.get(clone, arrayPath).splice(index, 1);
return clone;
}
return _.omit(filterObj, [path]);
}
/**
* Return pretty name.
* For example we have path crop[0] and value banana, will return 'crop Banana'.
* Another examples:
* 'description.contains': 'de' -> 'description de'
* 'title.eq': 'ti' -> 'title ti'
* @param path - path to filterObj value ie crop[0]
* @param value - filterObj value ie BN27.
* @param lookups - IPrettyFiltersProps.filterObj.
* @return IPrettyFiltersProps.filterObj.
*/
function getLabelName(path, value, lookups) {
const lastKey = path.replace(/\[(.+?)\]/g, '').split('.').pop();
let name = value;
if (lookups && lookups[lastKey]) {
name = lookups[lastKey][value];
}
const prettyPath: string = path
// remove array indexes square brackets [0], [1]... from path.
.replace(/\[(.+?)\]/g, '')
// split path title.eq -> ['title', 'eq']
.split('.')
// skip for showing keywords such as 'contains', 'eq'...
.filter((e) => keywordsToSkip.indexOf(e) === -1)
// join
.join(' ');
return `${prettyPath} ${name}`;
}
class PrettyFilters extends React.Component<IPrettyFiltersProps, any> {
constructor(props: IPrettyFiltersProps, context: any) {
super(props, context);
this.state = {
chipData: flattenjs.convert(props.filterObj),
};
}
protected handleDelete = (path) => () => {
const {filterObj, onSubmit} = this.props;
const updated = handleFilterObj(filterObj, path);
onSubmit(updated);
}
public componentWillReceiveProps(nextProps) {
const chipData = flattenjs.convert(nextProps.filterObj);
if (!_.isEqual(chipData, this.state.chipData)) {
this.setState({chipData});
}
}
public render() {
const {classes, lookups} = this.props;
const {chipData} = this.state;
const dataArr = Object.getOwnPropertyNames(chipData);
return dataArr.length > 0 && (
<Paper className={ classes.root }>
{ dataArr.map((key) => {
return (
<Chip
key={ key }
label={ getLabelName(key, chipData[key], lookups) }
onDelete={ this.handleDelete(key) }
className={ classes.chip }
/>
);
}) }
</Paper>
);
}
}
const styled = withStyles(styles)(PrettyFilters);
const mapStateToProps = (state, ownProps) => ({
lookups: {
crop: state.lookups.crops.reduce((p, c) => ({...p, ...{[c[0]]: c[1].title}}), []),
category: Descriptor.CATEGORIES,
},
});
export default connect(mapStateToProps)(styled);
......@@ -11,6 +11,7 @@ import Loading from 'ui/common/Loading';
import PaginationComponent from 'ui/common/pagination';
import DatasetFilters from './c/Filters';
import DatasetCard from './c/Card';
import PrettyFilters from 'ui/common/filter/PrettyFilters';
import Grid from 'material-ui/Grid';
......@@ -88,6 +89,12 @@ class BrowsePage extends React.Component<IDatasetsProps, any> {
onChange={ this.onPaginationChange } displayName="datasets"
sortOptions={ Dataset.SORT_OPTIONS } />
</Grid>
<Grid item xs={ 12 }>
<PrettyFilters
filterObj={ pagination.filter }
onSubmit={ this.applyFilters }
/>
</Grid>
{ stillLoading ? <Loading /> :
<Grid container spacing={ 0 }>
<Grid item xs={ 12 }>
......
......@@ -15,6 +15,7 @@ import Loading from 'ui/common/Loading';
import PaginationComponent from 'ui/common/pagination';
import DescriptorListCard from 'ui/catalog/descriptorlist/Card';
import DescriptorListFilters from './c/Filters';
import PrettyFilters from 'ui/common/filter/PrettyFilters';
const styles = (theme) => ({
filterSection: theme.leftPanel.root,
......@@ -29,6 +30,7 @@ interface IBrowsePageProps extends React.ClassAttributes<any> {
loading: any;
listDescriptorLists: any;
listCrops: () => any;
crop: any;
}
// Page to browse and filter descriptor lists
......@@ -100,6 +102,12 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
onChange={ this.onPaginationChange } displayName="datasets"
sortOptions={ DescriptorList.SORT_OPTIONS } />
</Grid>
<Grid item xs={ 12 }>
<PrettyFilters
filterObj={ pagination.filter }
onSubmit={ this.applyFilters }
/>
</Grid>
</Grid>
{ stillLoading ? <Loading /> :
<Grid container spacing={ 0 }>
......
......@@ -13,6 +13,7 @@ import PaginationComponent from 'ui/common/pagination';
import PartnerFilters from './c/Filters';
import Summary from './c/Summary';
import PartnerCard from './c/PartnerCard';
import PrettyFilters from 'ui/common/filter/PrettyFilters';
import Grid from 'material-ui/Grid';
......@@ -101,6 +102,12 @@ class PartnerListPage extends React.Component<IBrowsePageProps, any> {
sortOptions={ Partner.SORT_OPTIONS }
/>
</Grid>
<Grid item xs={ 12 }>
<PrettyFilters
filterObj={ pagination.filter }
onSubmit={ this.applyFilters }
/>
</Grid>
</Grid>
{ stillLoading ? <Loading /> :
<Grid container spacing={ 0 }>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment