Skip to content

Commit

Permalink
Merge pull request #87 from MetaPhase-Consulting/feature/comparison-d…
Browse files Browse the repository at this point in the history
…rawer

Feature/comparison drawer
  • Loading branch information
mjoyce91 authored Feb 25, 2019
2 parents 82d0919 + 87acc1b commit 8bc2241
Show file tree
Hide file tree
Showing 15 changed files with 427 additions and 52 deletions.
12 changes: 12 additions & 0 deletions src/Components/CompareCheck/CompareCheck.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class CompareCheck extends Component {
constructor(props) {
super(props);
this.toggleSaved = this.toggleSaved.bind(this);
this.eventListener = this.eventListener.bind(this);
this.state = {
saved: false,
localStorageKey: null,
Expand All @@ -20,12 +21,19 @@ class CompareCheck extends Component {
componentWillMount() {
const localStorageKey = this.props.type;
this.setState({ localStorageKey });

// add listener on localStorage 'compare' key
window.addEventListener('compare-ls', this.eventListener);
}

componentDidMount() {
this.getSaved();
}

componentWillUnmount() {
window.removeEventListener('compare-ls', this.eventListener);
}

onToggle() {
this.props.onToggle();
}
Expand Down Expand Up @@ -55,6 +63,10 @@ class CompareCheck extends Component {
}
}

eventListener() {
this.getSaved();
}

// eslint-disable-next-line class-methods-use-this
joinClassNames(className) {
return className
Expand Down
74 changes: 74 additions & 0 deletions src/Components/CompareDrawer/CompareDrawer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import PropTypes from 'prop-types';
import FA from 'react-fontawesome';
import shortid from 'shortid';
import COMPARE_LIMIT from '../../Constants/Compare';
import { getPostName } from '../../utilities';
import {
NO_GRADE,
NO_POST,
} from '../../Constants/SystemMessages';
import CompareCheck from '../CompareCheck';
import ViewComparisonLink from '../ViewComparisonLink/ViewComparisonLink';
import ResetComparisons from '../ResetComparisons/ResetComparisons';
import { COMPARE_LIST } from '../../Constants/PropTypes';

const CompareDrawer = ({ comparisons, isHidden }) => {
const limit = 5;
const compareArray = (comparisons || []).slice(0, COMPARE_LIMIT);
const emptyArray = Array(limit - compareArray.length).fill();
return (
<div className={`compare-drawer ${isHidden ? 'drawer-hidden' : ''}`}>
<div className="compare-drawer-inner-container">
{
compareArray.map(c => (
<div key={c.id} className="compare-item">
<div className="check-container">
<CompareCheck
refKey={c.position_number}
customElement={<FA name="close" />}
interactiveElementProps={{ title: 'Remove this comparison' }}
/>
</div>
<span className="data-point title">
<strong>{c.title}</strong>
</span>
<span className="data-point">
<strong>Grade:</strong> {c.grade || NO_GRADE}
</span>
<span className="data-point">
<strong>Post:</strong> {getPostName(c.post, NO_POST)}
</span>
</div>
))
}
{
emptyArray.map(() => (
<div
key={shortid.generate()}
className="compare-item compare-item-empty"
/>
))
}
<div className="button-container">
<ViewComparisonLink />
<ResetComparisons
className="reset-link"
/>
</div>
</div>
</div>
);
};

CompareDrawer.propTypes = {
comparisons: COMPARE_LIST,
isHidden: PropTypes.bool,
};

CompareDrawer.defaultProps = {
comparisons: [],
isHidden: false,
};

export default CompareDrawer;
36 changes: 36 additions & 0 deletions src/Components/CompareDrawer/CompareDrawer.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { shallow } from 'enzyme';
import React from 'react';
import CompareDrawer from './CompareDrawer';
import resultsObject from '../../__mocks__/resultsObject';

describe('CompareDrawer', () => {
const props = {
comparisons: resultsObject.results,
isHidden: false,
};
it('is defined', () => {
const wrapper = shallow(<CompareDrawer {...props} />);
expect(wrapper).toBeDefined();
});

it('applies correct css class when isHidden === true', () => {
const wrapper = shallow(<CompareDrawer {...props} isHidden />);
expect(wrapper.find('.drawer-hidden').exists()).toBe(true);
});

it('does not apply new css class when isHidden === false', () => {
const wrapper = shallow(<CompareDrawer {...props} isHidden={false} />);
expect(wrapper.find('.drawer-hidden').exists()).toBe(false);
});

it('displays the correct number of results data cards', () => {
const wrapper = shallow(<CompareDrawer {...props} isHidden={false} />);
expect(wrapper.find('.check-container').length).toBe(resultsObject.results.length);
});

it('displays the correct number of empty cards', () => {
const maxCards = 5;
const wrapper = shallow(<CompareDrawer {...props} isHidden={false} />);
expect(wrapper.find('.compare-item-empty').length).toBe(maxCards - resultsObject.results.length);
});
});
117 changes: 117 additions & 0 deletions src/Components/CompareDrawer/CompareDrawerContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { isEqual, omit } from 'lodash';
import { comparisonsFetchData } from '../../actions/comparisons';
import CompareDrawer from './CompareDrawer';
import { COMPARE_LIST } from '../../Constants/PropTypes';
import { getScrollDistanceFromBottom } from '../../utilities';

class Compare extends Component {
constructor(props) {
super(props);
this.lsListener = this.lsListener.bind(this);
this.scrollListener = this.scrollListener.bind(this);

/* set to 0 for now, but could change to the distance in px from the bottom of the screen
that you want the drawer to hide at */
this.scrollDistance = 0;

this.state = {
prevComparisons: [],
comparisons: [],
isHidden: false,
};
}

componentWillMount() {
// initialize with any existing comparison choices
const ls = localStorage.getItem('compare') || '[]';
const initialArr = JSON.parse(ls);
this.setState({ comparisons: initialArr }, () => {
this.getComparisons(this.state.comparisons.toString());
});

// add listener on localStorage 'compare' key
window.addEventListener('compare-ls', this.lsListener);

// add listener for scroll location, to hide the comparison farther down the page
window.addEventListener('scroll', this.scrollListener);
}

shouldComponentUpdate(nextProps, nextState) {
// we ignore comparisons state, since its just tracking the user's choices
return !(isEqual(nextProps, this.props)) || !(isEqual(omit(nextState, 'comparisons'), omit(this.state, 'comparisons')));
}

componentWillUnmount() {
window.removeEventListener('compare-ls', this.lsListener);
}

getComparisons(ids) {
this.props.fetchData(ids);
}

lsListener() {
const comparisons = JSON.parse(localStorage.getItem('compare') || []);
this.setState({ prevComparisons: this.state.comparisons, comparisons }, () => {
this.getComparisons(this.state.comparisons.toString());
});
}

scrollListener() {
const { isHidden } = this.state;

// eslint-disable-next-line no-unused-expressions
getScrollDistanceFromBottom() < this.scrollDistance ?
!isHidden && this.setState({ isHidden: true })
:
isHidden && this.setState({ isHidden: false });
}

render() {
const { isHidden, comparisons: comparisonsState, prevComparisons } = this.state;
const { comparisons, hasErrored } = this.props;

const comparisonsToUse = comparisonsState.length > prevComparisons.length
? comparisonsState : prevComparisons;

/* sort based on any prior compare list, so the cards don't get jumbled
after one is removed, as it persists until the new request completes */
const sortedComparisons = comparisons.sort((a, b) =>
(comparisonsToUse.indexOf(a.position_number) >
comparisonsToUse.indexOf(b.position_number) ? 1 : -1),
);

const isHidden$ = isHidden || !sortedComparisons.length;
return (
<CompareDrawer
comparisons={sortedComparisons}
hasErrored={hasErrored}
isHidden={isHidden$}
/>
);
}
}

Compare.propTypes = {
fetchData: PropTypes.func.isRequired,
hasErrored: PropTypes.bool,
comparisons: COMPARE_LIST,
};

Compare.defaultProps = {
comparisons: [],
hasErrored: false,
};

const mapStateToProps = state => ({
comparisons: state.comparisons,
hasErrored: state.comparisonsHasErrored,
});

export const mapDispatchToProps = dispatch => ({
fetchData: url => dispatch(comparisonsFetchData(url)),
});

export default connect(mapStateToProps, mapDispatchToProps)(Compare);
31 changes: 31 additions & 0 deletions src/Components/CompareDrawer/CompareDrawerContainer.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import TestUtils from 'react-dom/test-utils';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { testDispatchFunctions } from '../../testUtilities/testUtilities';
import CompareDrawerContainer, { mapDispatchToProps } from './CompareDrawerContainer';
import resultsObject from '../../__mocks__/resultsObject';

const middlewares = [thunk];
const mockStore = configureStore(middlewares);

describe('CompareDrawerContainer', () => {
it('is defined', () => {
const compare = TestUtils.renderIntoDocument(<Provider store={mockStore({})}><MemoryRouter>
<CompareDrawerContainer
fetchData={() => {}}
comparisons={resultsObject.results}
/>
</MemoryRouter></Provider>);
expect(compare).toBeDefined();
});
});

describe('mapDispatchToProps', () => {
const config = {
fetchData: ['1,2'],
};
testDispatchFunctions(mapDispatchToProps, config);
});
1 change: 1 addition & 0 deletions src/Components/CompareDrawer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './CompareDrawerContainer';
10 changes: 6 additions & 4 deletions src/Components/ResetComparisons/ResetComparisons.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { EMPTY_FUNCTION } from '../../Constants/PropTypes';
import { localStorageSetKey } from '../../utilities';

class ResetComparisons extends Component {

render() {
const { onToggle, ...rest } = this.props;
const exists = () => {
let result = false;
const retrievedKey = localStorage
Expand All @@ -16,14 +18,14 @@ class ResetComparisons extends Component {
return result;
};
const remove = () => {
localStorage.setItem('compare', '[]');
this.props.onToggle();
localStorageSetKey('compare', '[]');
onToggle();
};
const compare = exists() ?
<a onClick={remove} role="button" tabIndex={0}>Reset comparison choices</a>
<a onClick={remove} role="button" tabIndex={0}>Clear All</a>
: null;
return (
<div>
<div {...rest}>
{compare}
</div>
);
Expand Down
10 changes: 0 additions & 10 deletions src/Components/ResultsPage/ResultsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ ACCORDION_SELECTION_OBJECT, FILTER_ITEMS_ARRAY, USER_PROFILE, BID_RESULTS,
SAVED_SEARCH_MESSAGE, SAVED_SEARCH_OBJECT, MISSION_DETAILS_ARRAY,
POST_DETAILS_ARRAY, EMPTY_FUNCTION, NEW_SAVED_SEARCH_SUCCESS_OBJECT } from '../../Constants/PropTypes';
import { ACCORDION_SELECTION } from '../../Constants/DefaultProps';
import ViewComparisonLink from '../ViewComparisonLink/ViewComparisonLink';
import ResetComparisons from '../ResetComparisons/ResetComparisons';
import ResultsContainer from '../ResultsContainer/ResultsContainer';
import ResultsSearchHeader from '../ResultsSearchHeader/ResultsSearchHeader';
import ResultsFilterContainer from '../ResultsFilterContainer/ResultsFilterContainer';
Expand Down Expand Up @@ -49,14 +47,6 @@ class Results extends Component {
defaultLocation={defaultLocation}
/>
}
<div className="usa-grid-full top-nav">
<div className="usa-width-one-third reset-compare-link">
<ResetComparisons onToggle={this.onChildToggle} />
</div>
<div className="usa-width-one-third comparisons-button">
<ViewComparisonLink onToggle={this.onChildToggle} />
</div>
</div>
<div className="usa-grid-full results-section-container">
<ResultsFilterContainer
filters={filters}
Expand Down
2 changes: 1 addition & 1 deletion src/Components/ViewComparisonLink/ViewComparisonLink.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ViewComparisonLink extends Component {
// else, parse the key's value to use in the Link
const compareArray = JSON.parse(localStorage.getItem('compare'));
return (
<Link className={'usa-button'} to={`compare/${compareArray.toString()}`}>Compare positions</Link>
<Link className={'usa-button'} to={`compare/${compareArray.toString()}`}>Compare</Link>
);
}
}
Expand Down
Loading

0 comments on commit 8bc2241

Please sign in to comment.