Skip to content

Commit

Permalink
Merge pull request #1414 from nextstrain/collapsible-filters
Browse files Browse the repository at this point in the history
collapsible filter lists in footer
  • Loading branch information
jameshadfield authored Oct 19, 2021
2 parents c871641 + 6bc7f3c commit c35bdc8
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 25 deletions.
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"query-string": "^4.2.3",
"react": "^16.8.6",
"react-addons-css-transition-group": "^15.6.0",
"react-collapsible": "^2.8.4",
"react-dom": "^16.8.6",
"react-ga": "^2.2.0",
"react-helmet": "^5.2.1",
Expand Down
77 changes: 53 additions & 24 deletions src/components/framework/footer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { Suspense, lazy } from "react";
import { connect } from "react-redux";
import styled from 'styled-components';
import Collapsible from "react-collapsible";
import { withTranslation } from "react-i18next";
import {FaAngleUp, FaAngleDown} from "react-icons/fa";
import { dataFont } from "../../globalStyles";
import Flex from "./flex";
import { applyFilter } from "../../actions/tree";
Expand Down Expand Up @@ -92,8 +94,8 @@ const FooterStyles = styled.div`
}
.line {
margin-top: 20px;
margin-bottom: 20px;
margin-top: 15px;
margin-bottom: 15px;
border-bottom: 1px solid #CCC;
}
Expand Down Expand Up @@ -163,6 +165,24 @@ const removeFiltersButton = (dispatch, filterNames, outerClassName, label) => (
</SimpleFilter>
);

const TitleContainer = styled.div`
display: flex;
justify-content: space-between;
margin: 0px;
padding: 0px;
`;
const IconContainer = styled.span`
font-size: 22px;
font-weight: 500;
`;

const CollapseTitle = ({name, isExpanded=false}) => (
<TitleContainer>
{name}
<IconContainer>{isExpanded ? <FaAngleUp /> : <FaAngleDown />}</IconContainer>
</TitleContainer>
);


@connect((state) => {
return {
Expand Down Expand Up @@ -197,30 +217,39 @@ class Footer extends React.Component {
const totalStateCount = this.props.totalStateCounts[filterName];
const filterTitle = this.props.metadata.colorings[filterName] ? this.props.metadata.colorings[filterName].title : filterName;
const activeFilterItems = this.props.activeFilters[filterName].filter((x) => x.active).map((x) => x.value);
const title = (<div>
{t("Filter by {{filterTitle}}", {filterTitle: filterTitle}) + ` (n=${totalStateCount.size})`}
{this.props.activeFilters[filterName].length ? removeFiltersButton(this.props.dispatch, [filterName], "inlineRight", t("Clear {{filterName}} filter", { filterName: filterName})) : null}
</div>);
return (
<div>
{t("Filter by {{filterTitle}}", {filterTitle: filterTitle})}
{this.props.activeFilters[filterName].length ? removeFiltersButton(this.props.dispatch, [filterName], "inlineRight", t("Clear {{filterName}} filter", { filterName: filterName})) : null}
<div className='filterList'>
<Flex wrap="wrap" justifyContent="flex-start" alignItems="center">
{
Array.from(totalStateCount.keys())
.filter((itemName) => isValueValid(itemName)) // remove invalid values present across the tree
.sort() // filters are sorted alphabetically
.map((itemName) => (
<SimpleFilter
key={itemName}
active={activeFilterItems.indexOf(itemName) !== -1}
onClick={() => dispatchFilter(this.props.dispatch, this.props.activeFilters, filterName, itemName)}
>
<span>
{`${itemName} (${totalStateCount.get(itemName)})`}
</span>
</SimpleFilter>
))
}
</Flex>
</div>
<Collapsible
triggerWhenOpen={<CollapseTitle name={title} isExpanded />}
trigger={<CollapseTitle name={title} />}
triggerStyle={{cursor: "pointer", textDecoration: "none"}}
transitionTime={100}
>
<div className='filterList'>
<Flex wrap="wrap" justifyContent="flex-start" alignItems="center">
{
Array.from(totalStateCount.keys())
.filter((itemName) => isValueValid(itemName)) // remove invalid values present across the tree
.sort() // filters are sorted alphabetically
.map((itemName) => (
<SimpleFilter
key={itemName}
active={activeFilterItems.indexOf(itemName) !== -1}
onClick={() => dispatchFilter(this.props.dispatch, this.props.activeFilters, filterName, itemName)}
>
<span>
{`${itemName} (${totalStateCount.get(itemName)})`}
</span>
</SimpleFilter>
))
}
</Flex>
</div>
</Collapsible>
</div>
);
}
Expand Down

0 comments on commit c35bdc8

Please sign in to comment.