New: Custom Filtering for UI (#234)

This commit is contained in:
Qstick 2018-03-14 21:28:46 -04:00 committed by GitHub
parent c6873014c7
commit 7354e02bff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
154 changed files with 3498 additions and 1370 deletions

View file

@ -1,42 +1,107 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, { Component } from 'react';
import { icons } from 'Helpers/Props';
import Menu from 'Components/Menu/Menu';
import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
import FilterMenuContent from './FilterMenuContent';
import Menu from './Menu';
import ToolbarMenuButton from './ToolbarMenuButton';
import styles from './FilterMenu.css';
function FilterMenu(props) {
const {
className,
children,
isDisabled,
...otherProps
} = props;
class FilterMenu extends Component {
return (
<Menu
className={className}
{...otherProps}
>
<ToolbarMenuButton
iconName={icons.FILTER}
text="Filter"
isDisabled={isDisabled}
/>
{children}
</Menu>
);
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
isFilterModalOpen: false
};
}
//
// Listeners
onCustomFiltersPress = () => {
this.setState({ isFilterModalOpen: true });
}
onFiltersModalClose = () => {
this.setState({ isFilterModalOpen: false });
}
//
// Render
render(props) {
const {
className,
isDisabled,
selectedFilterKey,
filters,
customFilters,
buttonComponent: ButtonComponent,
filterModalConnectorComponent: FilterModalConnectorComponent,
onFilterSelect,
...otherProps
} = this.props;
const showCustomFilters = !!FilterModalConnectorComponent;
return (
<div>
<Menu
className={className}
{...otherProps}
>
<ButtonComponent
iconName={icons.FILTER}
text="Filter"
isDisabled={isDisabled}
/>
<FilterMenuContent
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
showCustomFilters={showCustomFilters}
onFilterSelect={onFilterSelect}
onCustomFiltersPress={this.onCustomFiltersPress}
/>
</Menu>
{
showCustomFilters &&
<FilterModalConnectorComponent
isOpen={this.state.isFilterModalOpen}
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
onFilterSelect={onFilterSelect}
onModalClose={this.onFiltersModalClose}
/>
}
</div>
);
}
}
FilterMenu.propTypes = {
className: PropTypes.string,
children: PropTypes.node.isRequired,
isDisabled: PropTypes.bool.isRequired
isDisabled: PropTypes.bool.isRequired,
selectedFilterKey: PropTypes.string.isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
buttonComponent: PropTypes.func.isRequired,
filterModalConnectorComponent: PropTypes.func,
onFilterSelect: PropTypes.func.isRequired
};
FilterMenu.defaultProps = {
className: styles.filterMenu,
isDisabled: false
isDisabled: false,
buttonComponent: ToolbarMenuButton
};
export default FilterMenu;

View file

@ -0,0 +1,85 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import MenuContent from './MenuContent';
import FilterMenuItem from './FilterMenuItem';
import MenuItem from './MenuItem';
import MenuItemSeparator from './MenuItemSeparator';
class FilterMenuContent extends Component {
//
// Render
render() {
const {
selectedFilterKey,
filters,
customFilters,
showCustomFilters,
onFilterSelect,
onCustomFiltersPress,
...otherProps
} = this.props;
return (
<MenuContent {...otherProps}>
{
filters.map((filter) => {
return (
<FilterMenuItem
key={filter.key}
filterKey={filter.key}
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
</FilterMenuItem>
);
})
}
{
customFilters.map((filter) => {
return (
<FilterMenuItem
key={filter.key}
filterKey={filter.key}
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
</FilterMenuItem>
);
})
}
{
showCustomFilters &&
<MenuItemSeparator />
}
{
showCustomFilters &&
<MenuItem onPress={onCustomFiltersPress}>
Custom Filters
</MenuItem>
}
</MenuContent>
);
}
}
FilterMenuContent.propTypes = {
selectedFilterKey: PropTypes.string.isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
showCustomFilters: PropTypes.bool.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onCustomFiltersPress: PropTypes.func.isRequired
};
FilterMenuContent.defaultProps = {
showCustomFilters: false
};
export default FilterMenuContent;

View file

@ -9,12 +9,11 @@ class FilterMenuItem extends Component {
onPress = () => {
const {
name,
value,
filterKey,
onPress
} = this.props;
onPress(name, value);
onPress(filterKey);
}
//
@ -22,18 +21,14 @@ class FilterMenuItem extends Component {
render() {
const {
name,
value,
filterKey,
filterValue,
selectedFilterKey,
...otherProps
} = this.props;
const isSelected = name === filterKey && value === filterValue;
return (
<SelectedMenuItem
isSelected={isSelected}
isSelected={filterKey === selectedFilterKey}
{...otherProps}
onPress={this.onPress}
/>
@ -42,16 +37,9 @@ class FilterMenuItem extends Component {
}
FilterMenuItem.propTypes = {
name: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
filterKey: PropTypes.string,
filterValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
filterKey: PropTypes.string.isRequired,
selectedFilterKey: PropTypes.string.isRequired,
onPress: PropTypes.func.isRequired
};
FilterMenuItem.defaultProps = {
name: null,
value: null
};
export default FilterMenuItem;

View file

@ -0,0 +1,5 @@
.separator {
overflow: hidden;
height: 1px;
background-color: $themeDarkColor;
}

View file

@ -0,0 +1,10 @@
import React from 'react';
import styles from './MenuItemSeparator.css';
function MenuItemSeparator() {
return (
<div className={styles.separator} />
);
}
export default MenuItemSeparator;

View file

@ -0,0 +1,11 @@
.menuButton {
composes: menuButton from './MenuButton.css';
&:hover {
color: #666;
}
}
.label {
margin-left: 5px;
}

View file

@ -0,0 +1,36 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import MenuButton from 'Components/Menu/MenuButton';
import styles from './PageMenuButton.css';
function PageMenuButton(props) {
const {
iconName,
text,
...otherProps
} = props;
return (
<MenuButton
className={styles.menuButton}
{...otherProps}
>
<Icon
name={iconName}
size={18}
/>
<div className={styles.label}>
{text}
</div>
</MenuButton>
);
}
PageMenuButton.propTypes = {
iconName: PropTypes.object.isRequired,
text: PropTypes.string
};
export default PageMenuButton;