Skip to content

Commit

Permalink
Merge pull request #435 from redbadger/reset-all-filters
Browse files Browse the repository at this point in the history
Reset all filters button on Events page
  • Loading branch information
frigus02 authored Jun 16, 2018
2 parents 3927644 + 923aff7 commit 4d3027b
Show file tree
Hide file tree
Showing 15 changed files with 589 additions and 90 deletions.
2 changes: 1 addition & 1 deletion src/actions/event-filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ export const clearStagedEventFilters = () => (

export const clearEventFilters = () => (
dispatch: Dispatch<EventFiltersAction>
) => dispatch({ type: "CLEAR__EVENT_FILTERS" });
) => dispatch({ type: "CLEAR_EVENT_FILTERS" });
4 changes: 4 additions & 0 deletions src/components/EventList.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class EventList extends Component<Props, State> {
sectionSeparator = () => <View style={styles.sectionSeparator} />;

keyExtractor = getId;
sectionList = null;

renderItem = ({ item }: RenderItemInfo) => {
const {
Expand Down Expand Up @@ -168,6 +169,9 @@ class EventList extends Component<Props, State> {
refreshing={refreshing}
onRefresh={onRefresh}
windowSize={10}
ref={sectionList => {
this.sectionList = sectionList;
}}
/>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/constants/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,6 @@ export default {
stageImage: "community"
}
]
}
},
resetAllFilters: "Reset all filters"
};
33 changes: 27 additions & 6 deletions src/screens/EventsScreen/FilterHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,29 @@ import {
} from "../../constants/colors";
import text from "../../constants/text";
import { formatDateRange } from "../../data/formatters";
import ResetAllFiltersButton from "./ResetAllFiltersButton";

export type Props = {
onFilterCategoriesPress: Function,
dateFilter: ?DateRange,
onFilterButtonPress: () => void,
onDateFilterButtonPress: () => void,
selectedCategories: Set<EventCategoryName>,
numTagFiltersSelected: number
numTagFiltersSelected: number,
resetAllFiltersPress: () => void,
scrollEventListToTop: () => void
};

class FilterHeader extends React.PureComponent<Props> {
static defaultProps = {
resetAllFiltersPress: () => {}
};

resetAllFilters = () => {
this.props.resetAllFiltersPress();
this.props.scrollEventListToTop();
};

render() {
const {
dateFilter,
Expand All @@ -37,14 +49,23 @@ class FilterHeader extends React.PureComponent<Props> {
? formatDateRange(dateFilter)
: text.selectDates;

const anyAppliedFilters: boolean =
!!dateFilter || numTagFiltersSelected > 0 || selectedCategories.size > 0;

return (
<View accessibilityTraits={["header"]} style={styles.container}>
<ContentPadding>
<View testID="event-filter-header" style={styles.content}>
<FilterHeaderCategories
onFilterPress={onFilterCategoriesPress}
selectedCategories={selectedCategories}
<View>
<ResetAllFiltersButton
visible={anyAppliedFilters}
onPress={this.resetAllFilters}
/>
<View testID="event-filter-header" style={styles.content}>
<FilterHeaderCategories
onFilterPress={onFilterCategoriesPress}
selectedCategories={selectedCategories}
/>
</View>
</View>
</ContentPadding>
<View style={styles.contentFilters}>
Expand Down Expand Up @@ -77,7 +98,7 @@ const styles = StyleSheet.create({
backgroundColor: filterBgColor
},
content: {
paddingTop: 16,
marginTop: 16,
paddingBottom: 12
},
contentFilters: {
Expand Down
57 changes: 48 additions & 9 deletions src/screens/EventsScreen/FilterHeader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import FilterHeader from "./FilterHeader";
import type { Props as ComponentProps } from "./FilterHeader";
import FilterHeaderButton from "./FilterHeaderButton";
import FilterHeaderCategories from "./FilterHeaderCategories";
import ResetAllFiltersButton from "./ResetAllFiltersButton";

const render = (
props: ComponentProps = {
Expand All @@ -13,7 +14,9 @@ const render = (
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
}
) => shallow(<FilterHeader {...props} />);

Expand All @@ -25,7 +28,9 @@ describe("renders correctly", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
expect(output).toMatchSnapshot();
});
Expand All @@ -37,7 +42,9 @@ describe("renders correctly", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
expect(output).toMatchSnapshot();
});
Expand All @@ -49,7 +56,9 @@ describe("renders correctly", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
expect(output).toMatchSnapshot();
});
Expand All @@ -64,7 +73,9 @@ describe("renders correctly", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
expect(output).toMatchSnapshot();
});
Expand All @@ -76,7 +87,9 @@ describe("renders correctly", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 2
resetAllFiltersPress: () => {},
numTagFiltersSelected: 2,
scrollEventListToTop: () => {}
});
expect(output).toMatchSnapshot();
});
Expand All @@ -91,7 +104,9 @@ describe("filter buttons", () => {
onFilterCategoriesPress: mock,
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
output.find(FilterHeaderCategories).prop("onFilterPress")();

Expand All @@ -106,7 +121,9 @@ describe("filter buttons", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: mock,
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
const button = output.find(FilterHeaderButton).at(0);
button.simulate("press");
Expand All @@ -122,11 +139,33 @@ describe("filter buttons", () => {
onFilterCategoriesPress: () => {},
onFilterButtonPress: mock,
onDateFilterButtonPress: () => {},
numTagFiltersSelected: 0
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: () => {}
});
const button = output.find(FilterHeaderButton).at(1);
button.simulate("press");

expect(mock).toBeCalledWith();
});

it("calls scrollEventListToTop when users presses 'Reset all filters' button", () => {
const mock = jest.fn();
const output = render({
dateFilter: null,
selectedCategories: new Set(["Music"]),
onFilterCategoriesPress: () => {},
onFilterButtonPress: () => {},
onDateFilterButtonPress: () => {},
resetAllFiltersPress: () => {},
numTagFiltersSelected: 0,
scrollEventListToTop: mock
});
output
.find(ResetAllFiltersButton)
.props()
.onPress();

expect(mock).toBeCalledWith();
});
});
9 changes: 8 additions & 1 deletion src/screens/EventsScreen/FilterHeaderConnected.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
selectTagFilterSelectedCount
} from "../../selectors/event-filters";
import Component from "./FilterHeader";
import { clearEventFilters } from "../../actions/event-filters";

type OwnProps = {
onFilterCategoriesPress: Function,
Expand All @@ -32,6 +33,10 @@ const getNumTagFiltersSelected = createSelector(
selectTagFilterSelectedCount
);

type DispatchProps = {
resetAllFiltersPress: () => void
};

// Note we must add a return type here for react-redux connect to work
// with flow correctly. If not provided is silently fails if types do
// not line up. See https://github.com/facebook/flow/issues/5343
Expand All @@ -40,7 +45,9 @@ const mapStateToProps = (state: State): StateProps => ({
numTagFiltersSelected: getNumTagFiltersSelected(state)
});

const mapDispatchToProps = {};
const mapDispatchToProps = (dispatch): DispatchProps => ({
resetAllFiltersPress: () => dispatch(clearEventFilters())
});

const connector: Connector<OwnProps, Props> = connect(
mapStateToProps,
Expand Down
22 changes: 20 additions & 2 deletions src/screens/EventsScreen/FilterHeaderConnected.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,36 @@ const initialState = {
}
};

const defaultProps = {
selectedCategories: new Set()
};

const mockStore = configureStore([thunk]);

describe("ConnectedFilterHeader", () => {
it("renders connector", () => {
const store = mockStore(initialState);
const output = shallow(<FilterHeader store={store} />);
const output = shallow(<FilterHeader store={store} {...defaultProps} />);
expect(output).toMatchSnapshot();
});

it("renders component", () => {
const store = mockStore(initialState);
const output = shallow(<FilterHeader store={store} />);
const output = shallow(<FilterHeader store={store} {...defaultProps} />);
expect(output.dive()).toMatchSnapshot();
});

it("dispatches clear filters action", () => {
const store = mockStore(initialState);
const output = shallow(<FilterHeader store={store} {...defaultProps} />);

output.props().resetAllFiltersPress();

const actions = store.getActions();
expect(actions).toEqual([
{
type: "CLEAR_EVENT_FILTERS"
}
]);
});
});
Loading

0 comments on commit 4d3027b

Please sign in to comment.