Skip to content

Filtering #59

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

Merged
merged 23 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from 21 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
4 changes: 2 additions & 2 deletions actionlist/__tests__/components/sideMenuSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ describe('SideMenu', () => {
<Provider store={store}>
<SideMenu />
</Provider>);
expect(wrapper.find(View).length).to.equal(9);
expect(wrapper.find(Text).length).to.equal(8);
expect(wrapper.find(View).length).to.equal(21);
expect(wrapper.find(Text).length).to.equal(15);
expect(wrapper.find(Text).first().text()).to.equal('Home');
expect(wrapper.find(Text).at(1).text()).to.equal('Preferences');
expect(wrapper.find(Text).at(2).text()).to.equal('Filter');
Expand Down
4 changes: 3 additions & 1 deletion actionlist/app/actions/action_items.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createAction } from 'redux-actions';
import { TOGGLE_DRAWER, SORT_ACTION_LIST, SELECT_DROPDOWN_OPTION } from './types';
import { TOGGLE_DRAWER, SORT_ACTION_LIST, FILTER_ACTION_LIST, RESET_FILTERS, SELECT_DROPDOWN_OPTION } from './types';

export const toggleDrawer = createAction(TOGGLE_DRAWER);
export const filterActionList = createAction(FILTER_ACTION_LIST);
export const sortActionList = createAction(SORT_ACTION_LIST);
export const selectDropdownOption = createAction(SELECT_DROPDOWN_OPTION);
export const resetFilters = createAction(RESET_FILTERS);
2 changes: 2 additions & 0 deletions actionlist/app/actions/types.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const TOGGLE_DRAWER = 'toggle_drawer';
export const FILTER_ACTION_LIST = 'filter_action_list';
export const SORT_ACTION_LIST = 'sort_action_list';
export const SELECT_DROPDOWN_OPTION = 'select_dropdown_option';
export const RESET_FILTERS = 'reset_filters';
138 changes: 101 additions & 37 deletions actionlist/app/components/SideMenu.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React from 'react';

import {
StyleSheet,
View,
Text,
ScrollView,
TouchableHighlight,
} from 'react-native';

import Button from 'react-native-button';
import { Actions } from 'react-native-router-flux';
import Actions from 'react-native-router-flux';
import { connect } from 'react-redux';
import { sortActionList } from '../actions/action_items';
import { Colors, sortTypes } from '../lib/commons';
import { sortActionList, resetFilters } from '../actions/action_items';
import { Colors, sortTypes, filterTypes } from '../lib/commons';
import FilterPicker from './filterPicker';
import ContentHeader from './contentHeader';

const style = StyleSheet.create({
view: {
Expand All @@ -29,6 +31,29 @@ const style = StyleSheet.create({
textAlign: 'left',
borderBottomWidth: 0.5,
},
resetContainer: {
backgroundColor: '#990000',
padding: 5,
borderRadius: 8,
marginRight: 10,
marginLeft: 70,
marginBottom: 10,
marginTop: 10,
width: 100,
},
resetButton: {
fontSize: 10,
color: '#ffffff',
},
picker: {
fontSize: 10,
color: Colors.IUGray,
fontFamily: 'BentonSansBold, Arial, sans-serif',
},
container: {
backgroundColor: '#f4f7f9',
paddingTop: 0,
},
subtext: {
color: Colors.IUCrimson,
marginLeft: 15,
Expand All @@ -48,54 +73,93 @@ const style = StyleSheet.create({
},
});

const SideMenu = ({ optionSelected, onSort }) => (
<View style={style.view}>
<Button style={style.text} onPress={() => Actions.home()}>Home</Button>
<Button style={style.text} onPress={() => Actions.pref()} >Preferences</Button>
<Button style={style.text}>Filter</Button>
const SideMenu = ({ optionSelected,
filters,
onSort,
onReset,
}) => (
<ScrollView style={style.container}>
<View style={style.view}>
<Text style={style.text}>
Sort
</Text>
<TouchableHighlight onPress={() => onSort(sortTypes.creationDate)}>
<Text
style={(optionSelected === sortTypes.creationDate) ?
style.selected_text : style.subtext}
>Date Created</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.lastApprovedDate)}>
<Text
style={(optionSelected === sortTypes.lastApprovedDate) ?
style.selected_text : style.subtext}
>Date Last Approved</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.processType)}>
<Text
style={(optionSelected === sortTypes.processType) ?
style.selected_text : style.subtext}
>Process Type</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.actionRequested)}>
<Text
style={(optionSelected === sortTypes.actionRequested) ?
style.selected_text : style.subtext}
>Action Requested</Text>
</TouchableHighlight>
<Button style={style.text} onPress={() => Actions.home()}>Home</Button>
<Button style={style.text} onPress={() => Actions.pref()} >Preferences</Button>
<Button style={style.text}>Filter</Button>
<View style={style.view}>
<Text style={style.text}>
Sort
</Text>
<TouchableHighlight onPress={() => onSort(sortTypes.creationDate)}>
<Text
style={(optionSelected === sortTypes.creationDate) ?
style.selected_text : style.subtext}
>Date Created</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.lastApprovedDate)}>
<Text
style={(optionSelected === sortTypes.lastApprovedDate) ?
style.selected_text : style.subtext}
>Date Last Approved</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.processType)}>
<Text
style={(optionSelected === sortTypes.processType) ?
style.selected_text : style.subtext}
>Process Type</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => onSort(sortTypes.actionRequested)}>
<Text
style={(optionSelected === sortTypes.actionRequested) ?
style.selected_text : style.subtext}
>Action Requested</Text>
</TouchableHighlight>
<Text style={style.text}>Filter</Text>
<FilterPicker
filter={filterTypes.DocumentRouteStatus}
value={filters.documentRouteStatus}
filterKey={'documentRouteStatus'}
/>
<FilterPicker
filter={filterTypes.DocumentType}
value={filters.documentType}
filterKey={'documentType'}
/>
<FilterPicker
filter={filterTypes.ActionRequested}
value={filters.actionRequested}
filterKey={'actionRequested'}
/>
<ContentHeader title={filterTypes.DocumentCreatedDate.title} />
<ContentHeader title={filterTypes.DocumentAssignedDate.title} />
</View>
<Button
containerStyle={style.resetContainer}
style={style.resetButton}
onPress={() => onReset()}
>Reset Filters</Button>
</View>
</View>
</ScrollView>
);

const mapStateToProps = state => ({
optionSelected: state.actionItemsReducer.optionSelected,
filters: state.actionItemsReducer.filterStatus,
});

const mapDispatchToProps = dispatch => ({
onReset: () => dispatch(resetFilters()),
onSort: criteria => dispatch(sortActionList(criteria)),
});

SideMenu.propTypes = {
onSort: React.PropTypes.func.isRequired,
optionSelected: React.PropTypes.string.isRequired,
onReset: React.PropTypes.func.isRequired,
filters: React.PropTypes.shape({
documentRouteStatus: React.PropTypes.string,
documentType: React.PropTypes.string,
documentCreationDate: React.PropTypes.string,
documentAssignedDate: React.PropTypes.string,
actionRequested: React.PropTypes.string,
}).isRequired,
};

export default connect(mapStateToProps, mapDispatchToProps)(SideMenu);
1 change: 0 additions & 1 deletion actionlist/app/components/action_item_header.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,3 @@ ActionItemHeader.propTypes = {
};

export default ActionItemHeader;

28 changes: 28 additions & 0 deletions actionlist/app/components/contentHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import {
StyleSheet,
View,
Text,
} from 'react-native';
import { Colors } from '../lib/commons';

const style = StyleSheet.create({
headerText: {
fontSize: 10,
color: Colors.IUCrimson,
fontFamily: 'BentonSansBold, Arial, sans-serif',
margin: 10,
},
});

const ContentHeader = ({ title }) => (
<View>
<Text style={style.headerText}>{title}</Text>
Copy link
Contributor

@burnumd burnumd Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend not using a title prop and just use the children prop. It looks like it's allowed for Text components to have node children, so if you just use children you can pass off prop validation to the react-native component and allow yourself more flexibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to use children and lint threw an error saying I need to have a prop validation for it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the type of children should be documented as React.PropTypes.node: jsx-eslint/eslint-plugin-react#7

</View>
);

ContentHeader.propTypes = {
title: React.PropTypes.string.isRequired,
};

export default ContentHeader;
16 changes: 14 additions & 2 deletions actionlist/app/components/display_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ const styles = StyleSheet.create({
},
});

const DisplayList = ({ dataSource }) => (
const filterData = (dataSource, filters) => (
dataSource.filter(item => ((item.actionRequested.label === filters.actionRequested || filters.actionRequested === 'All') &&
(item.processType.label === filters.documentType || filters.documentType === 'All') &&
(item.processInstanceStatus.label === filters.documentRouteStatus || filters.documentRouteStatus === 'All')))
);

const DisplayList = ({ dataSource, filterStatus }) => (
<View style={styles.full_container}>
<LazyloadScrollView>
<Accordion
sections={dataSource}
sections={filterData(dataSource, filterStatus)}
renderHeader={ActionItemHeader}
renderContent={ActionItemBody}
/>
Expand All @@ -35,10 +41,16 @@ const DisplayList = ({ dataSource }) => (

const mapStateToProps = state => ({
dataSource: state.actionItemsReducer.dataSource,
filterStatus: state.actionItemsReducer.filterStatus,
});

DisplayList.propTypes = {
dataSource: React.PropTypes.arrayOf(React.PropTypes.shape({})).isRequired,
filterStatus: React.PropTypes.shape({
actionRequested: React.PropTypes.string,
documentType: React.PropTypes.string,
documentRouteStatus: React.PropTypes.string,
}).isRequired,
};

export default connect(mapStateToProps)(DisplayList);
43 changes: 43 additions & 0 deletions actionlist/app/components/filterPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import {
View,
Picker,
} from 'react-native';

/* eslint-disable no-unused-vars */
import { connect } from 'react-redux';
import { filterActionList } from '../actions/action_items';
import ContentHeader from './contentHeader';

const FilterPicker = ({ filter, value, filterKey, onActionListFiltering }) => (
<View>
<ContentHeader title={filter.title} />
<Picker
selectedValue={value}
onValueChange={selectedOption => onActionListFiltering(filterKey, selectedOption)}
>
{
filter.data.map(i => (
<Picker.Item value={i} label={i} key={i} />
))
}
</Picker>
</View>
);

const mapDispatchToProps = dispatch => ({
onActionListFiltering: (filterType, value) =>
dispatch(filterActionList({ filterType, value })),
});

FilterPicker.propTypes = {
onActionListFiltering: React.PropTypes.func.isRequired,
filter: React.PropTypes.shape({
title: React.PropTypes.string,
data: React.PropTypes.arrayOf(React.PropTypes.string),
}).isRequired,
value: React.PropTypes.string.isRequired,
filterKey: React.PropTypes.string.isRequired,
};

export default connect(null, mapDispatchToProps)(FilterPicker);
6 changes: 2 additions & 4 deletions actionlist/app/containers/PreferencesContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import PreferencesButton from '../components/PreferencesButton';
import Dropdown from '../components/Dropdown';
import { Colors, documentStatuses } from '../lib/commons';

const camelCase = require('camel-case');

const styles = StyleSheet.create({
componentContainer: {
backgroundColor: Colors.IULimeStone,
Expand Down Expand Up @@ -71,10 +69,10 @@ const PreferencesContainer = () => (
documentStatuses.map(documentStatus => (
<View style={styles.preferenceSelect}>
<View>
<Text style={styles.text}>{camelCase(documentStatus)}</Text>
<Text style={styles.text}>{documentStatus}</Text>
</View>
<View>
<Dropdown option={camelCase(documentStatus)} />
<Dropdown option={documentStatus} />
</View>
</View>
))}
Expand Down
30 changes: 30 additions & 0 deletions actionlist/app/lib/commons.js

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions actionlist/app/reducers/action_items.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* eslint arrow-body-style: ["error", "as-needed", { "requireReturnForObjectLiteral": true }] */
import { handleActions } from 'redux-actions';
import { TOGGLE_DRAWER, SORT_ACTION_LIST, SELECT_DROPDOWN_OPTION } from '../actions/types';
import { processInstances, sortTypes, Colors } from '../lib/commons';
import { TOGGLE_DRAWER, SORT_ACTION_LIST, FILTER_ACTION_LIST, RESET_FILTERS, SELECT_DROPDOWN_OPTION } from '../actions/types';
import { processInstances, sortTypes, filterStatus, Colors } from '../lib/commons';

export const defaultState = {
dataSource: processInstances,
drawerExpanded: false,
filterStatus,
optionSelected: '',
dropdownColors: {
saved: Colors.White,
Expand Down Expand Up @@ -94,8 +95,27 @@ const selectDropdownOption = (state, action) => {
};
};

const filterActionList = (state, action) => {
return {
...state,
filterStatus: {
...state.filterStatus,
[action.payload.filterType]: action.payload.value,
},
};
};

const resetFilters = (state) => {
return {
...state,
filterStatus,
};
};

export default handleActions({
[TOGGLE_DRAWER]: toggleDrawer,
[SORT_ACTION_LIST]: sortActionList,
[FILTER_ACTION_LIST]: filterActionList,
[SELECT_DROPDOWN_OPTION]: selectDropdownOption,
[RESET_FILTERS]: resetFilters,
}, defaultState);
1 change: 1 addition & 0 deletions actionlist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"jest": "18.1.0",
"react-native-collapsible": "^0.8.0",
"react-native-drawer": "^2.3.0",
"react-native-radio-buttons": "^0.14.0",
"react-native-modal-dropdown": "^0.4.2",
"react-native-router-flux": "^3.38.0",
"react-native-side-menu": "^0.20.1",
Expand Down
Loading