Skip to content
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

Filtering #59

Merged
merged 23 commits into from
Apr 21, 2017
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
3 changes: 0 additions & 3 deletions actionlist/.flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*

; Ignore unexpected extra "@providesModule"
.*/node_modules/react-native-router-flux/node_modules/.*

; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
Expand Down
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>{filterTypes.DocumentCreatedDate.title}</ContentHeader>
<ContentHeader>{filterTypes.DocumentAssignedDate.title}</ContentHeader>
</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 = props => (
<View>
<Text style={style.headerText}>{props.children}</Text>
</View>
);

ContentHeader.propTypes = {
children: React.PropTypes.node.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>{filter.title}</ContentHeader>
<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);
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 @@ -36,6 +36,7 @@
"react-native-button": "^1.8.2",
"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
7 changes: 7 additions & 0 deletions actionlist/test_constants/componentTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@ export const Middlewares = [];
export const InitialState = {
actionItemsReducer: {
sortValue: 'test',
filterStatus: {
documentRouteStatus: 'All',
documentType: 'All',
documentCreationDate: 'All',
documentAssignedDate: 'All',
actionRequested: 'All',
},
},
};