Skip to content

Commit

Permalink
Issue 563 - Resources Filtering (#1200)
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmfox authored and julianguyen committed Oct 28, 2018
1 parent a1d7844 commit 81816fc
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 17 deletions.
1 change: 1 addition & 0 deletions client/app/components/Input/Input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
}
&Label {
@include setMargin($size-0, $size-0, $size-0, $size-8);
text-transform: capitalize;
}
}

Expand Down
5 changes: 5 additions & 0 deletions client/app/components/Input/InputTag.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type Props = {
placeholder?: string,
checkboxes: Checkbox[],
onChange?: Function,
onCheckboxChange?: Function,
};

export type State = {
Expand All @@ -33,6 +34,10 @@ export class InputTag extends React.Component<Props, State> {
const newCheckbox = Object.assign({}, checkbox);
if (newCheckbox.id === id) {
newCheckbox.checked = checked;
const { onCheckboxChange } = this.props;
if (onCheckboxChange) {
onCheckboxChange(newCheckbox);
}
}
return newCheckbox;
});
Expand Down
3 changes: 2 additions & 1 deletion client/app/components/Input/InputTag.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@

&Label {
@include setPadding($size-4, $size-4, $size-4, $size-4);
text-transform: capitalize;
}

&Highlighted {
background: $light-grey;
border-radius: $size-4;
font-weight: bold;
}
}
}
1 change: 1 addition & 0 deletions client/app/styles/_legacy.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
@import "~app/assets/stylesheets/core/links.scss";
@import "~app/assets/stylesheets/core/buttons.scss";
@import "~app/assets/stylesheets/core/grids.scss";
@import "~app/assets/stylesheets/core/margins.scss";
73 changes: 73 additions & 0 deletions client/app/widgets/Resources/__tests__/Resources.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @flow
import { mount } from 'enzyme';
import React from 'react';
import { Resources } from '../index';

const component = (
<Resources
resources={[
{
name: '7 Cups',
link: 'https://www.7cups.com',
tags: [
'therapy',
'counseling',
'paid',
'free',
'texting',
'android',
'iOS',
],
languages: ['English', 'Español'],
type: 'Services',
},
{
name: 'A Canvas of the Minds',
link: 'https://acanvasoftheminds.com/',
tags: ['free', 'blog'],
languages: ['English'],
type: 'Communities',
},
]}
/>
);

describe('Resources', () => {
it('filters when tag selected', () => {
const wrapper = mount(component);
expect(wrapper.find('.resource').length).toEqual(2);
wrapper.find('.tagAutocomplete').simulate('focus');
expect(wrapper.find('.tagMenu').exists()).toEqual(true);
const id = wrapper
.find('.tagLabel')
.at(0)
.text();
wrapper
.find('.tagLabel')
.at(0)
.simulate('click');
expect(wrapper.find('.checkboxLabel').text()).toEqual(id);
expect(wrapper.find('.resource').length).toEqual(1);
expect(wrapper.find('.tag').findWhere(t => t.text() === id).length).toEqual(1);
});

it('unfilters when tag unselected', () => {
const wrapper = mount(component);
expect(wrapper.find('.resource').length).toEqual(2);
wrapper.find('.tagAutocomplete').simulate('focus');
const id = wrapper
.find('.tagLabel')
.at(0)
.text();
wrapper
.find('.tagLabel')
.at(0)
.simulate('click');
expect(wrapper.find('.resource').length).toEqual(1);
wrapper.find(`input#${id}`).prop('onChange')({
currentTarget: { checked: false },
});
wrapper.update();
expect(wrapper.find('.resource').length).toEqual(2);
});
});
100 changes: 84 additions & 16 deletions client/app/widgets/Resources/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,93 @@ import React from 'react';
import css from './Resources.scss';
import { Resource } from '../../components/Resource';
import { Utils } from '../../utils';
import { InputTag } from '../../components/Input/InputTag';
import { I18n } from '../../libs/i18n';

export type Props = {
resources: any,
};

export const Resources = (props: Props) => {
const { resources } = props;
return (
<div className={css.gridThree}>
{resources.map(resource => (
<div className={css.gridThreeItem} key={Utils.randomString()}>
<Resource
tagged
tags={resource.languages.concat(resource.tags)}
title={resource.name}
link={resource.link}
/>
</div>
))}
</div>
);
export type State = {
checkboxes: any,
};

export type Selected = {
checked: boolean,
id: string,
key: string,
label: string,
value: string,
};

export class Resources extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { checkboxes: this.createCheckboxes() };
}

createCheckboxes = () => {
const { resources } = this.props;
const tagsList = [
...new Set(
resources
.map(res => res.tags.concat(res.languages))
.reduce((acc, val) => acc.concat(val), []),
),
];
return tagsList.map<any>((tag: string) => ({
id: tag,
key: tag,
value: tag,
label: tag,
checked: false,
}));
};

checkboxChange = (box: Selected) => {
this.setState((prevState: State) => {
const updatedBoxes = prevState.checkboxes
.filter(checkbox => checkbox.id !== box.id)
.concat(box);
return { checkboxes: updatedBoxes };
});
};

filterList = (check: Array<*>) => {
const { resources } = this.props;
const selectedTags = check.filter(c => c.checked === true);
const matchingResources = resources.filter((r) => {
const tagCheck = selectedTags.map((t: Selected) => r.tags.concat(r.languages).includes(t.id));
return !tagCheck.includes(false);
});
return matchingResources;
};

render() {
const { checkboxes } = this.state;
const filteredResources = this.filterList(checkboxes);
return (
<React.Fragment>
<InputTag
id="resourceTags"
name="resourceTags"
placeholder={I18n.t('common.form.press_enter')}
checkboxes={checkboxes}
onCheckboxChange={box => this.checkboxChange(box)}
/>
<div className={`${css.gridThree} ${css.marginTop}`}>
{filteredResources.map(resource => (
<div className={css.gridThreeItem} key={Utils.randomString()}>
<Resource
tagged
tags={resource.languages.concat(resource.tags)}
title={resource.name}
link={resource.link}
/>
</div>
))}
</div>
</React.Fragment>
);
}
}

0 comments on commit 81816fc

Please sign in to comment.