Skip to content

Commit

Permalink
Fix: Search should work for subsections
Browse files Browse the repository at this point in the history
Fix #245
  • Loading branch information
sapegin committed Feb 17, 2017
1 parent 468cf75 commit c095643
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function ComponentsListRenderer({ classes, items }) {
<ul className={classes.list}>
{items.map(({ heading, name, slug, content }) => (
<li className={cx(classes.item, (!content || !content.props.items.length) && classes.isChild)} key={name}>
<Link className={heading && classes.heading} href={`#${slug}`}>{name}</Link>
<Link className={cx(heading && classes.heading)} href={`#${slug}`}>{name}</Link>
{content}
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ exports[`test should render sections with nested components 1`] = `
<li
className="">
<_class
className=""
href="#button">
Button
</_class>
</li>
<li
className="">
<_class
className=""
href="#input">
Input
</_class>
</li>
<li
className="">
<_class
className=""
href="#textarea">
Textarea
</_class>
Expand Down
61 changes: 22 additions & 39 deletions src/rsg-components/TableOfContents/TableOfContents.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,49 @@
import React, { Component, PropTypes } from 'react';
import { filterComponentsByName, getFilterRegExp } from '../../utils/utils';
import { filterSectionsByName } from '../../utils/utils';
import ComponentsList from 'rsg-components/ComponentsList';
import TableOfContentsRenderer from 'rsg-components/TableOfContents/TableOfContentsRenderer';

export default class TableOfContents extends Component {
static propTypes = {
sections: PropTypes.array.isRequired,
};
state = {
searchTerm: '',
};

constructor(props) {
super(props);

this.state = {
searchTerm: '',
};
}

getComponents(components, searchTerm) {
return filterComponentsByName(components || [], searchTerm);
}

getSections(sections = [], searchTerm) {
const regExp = getFilterRegExp(searchTerm);
return sections.reduce((filteredSections, { name, slug, components: subComponents = [], sections: subSections }) => {
subComponents = this.getComponents(subComponents, searchTerm);
if (subComponents.length || !searchTerm || regExp.test(name)) {
filteredSections.push({
heading: true,
name,
slug,
content: this.renderLevel(subComponents, subSections, searchTerm),
});
}
return filteredSections;
}, []);
}

renderLevel(components, sections, searchTerm) {
const items = [
...this.getComponents(components, searchTerm),
...this.getSections(sections, searchTerm),
];
renderLevel(sections) {
const items = sections.map(section => {
const children = [...section.sections || [], ...section.components || []];
return Object.assign({}, section, {
heading: !!section.name && children.length > 0,
content: children.length > 0 && this.renderLevel(children),
});
});
return (
<ComponentsList items={items} />
);
}

render() {
renderSections() {
const { searchTerm } = this.state;
const { sections } = this.props;

// If there is only one section, we treat it as a root section
// In this case the name of the section won't be rendered and it won't get left padding
const content = sections.length === 1
? this.renderLevel(sections[0].components, sections[0].sections, searchTerm)
: this.renderLevel(null, sections, searchTerm);
const firstLevel = sections.length === 1 ? sections[0].components : sections;
const filtered = filterSectionsByName(firstLevel, searchTerm);

return this.renderLevel(filtered);
}

render() {
const { searchTerm } = this.state;
return (
<TableOfContentsRenderer
searchTerm={searchTerm}
onSearchTermChange={searchTerm => this.setState({ searchTerm })}
>
{content}
{this.renderSections()}
</TableOfContentsRenderer>
);
}
Expand Down
13 changes: 0 additions & 13 deletions src/rsg-components/TableOfContents/TableOfContents.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,6 @@ it('should filter list when search field contains a query', () => {
expect(actual).toMatchSnapshot();
});

it('should render a filtered list, should hide empty sections', () => {
const searchTerm = 'inp';
const actual = shallow(
<TableOfContents sections={sections} />
);

expect(actual).toMatchSnapshot();

actual.setState({ searchTerm });

expect(actual).toMatchSnapshot();
});

it('should filter section names', () => {
const searchTerm = 'frm';
const actual = shallow(
Expand Down
Loading

0 comments on commit c095643

Please sign in to comment.