mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
cleans up the filter and sorting toolbar + fab for new feature toggle… (#61)
* cleans up the filter and sorting toolbar + fab for new feature toggle + makes name default sorting
This commit is contained in:
parent
92eaed85d1
commit
5242e2aa0d
@ -27,6 +27,17 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.listLink {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.listLink:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.hideLt920 {
|
||||
display: none;
|
||||
@ -75,3 +86,8 @@
|
||||
justify-content: center;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.dropdownButton {
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import styles from './common.scss';
|
||||
const {
|
||||
List, ListItem, ListItemContent,
|
||||
Button, Icon,
|
||||
Switch,
|
||||
Switch, MenuItem,
|
||||
} = require('react-mdl');
|
||||
const { Link } = require('react-router');
|
||||
|
||||
@ -112,6 +112,20 @@ export const ExternalIconLink = ({ url, children }) => (
|
||||
</IconLink>
|
||||
);
|
||||
|
||||
export const DropdownButton = ({ label, id }) => (
|
||||
<Button id={id} className={styles.dropdownButton}>
|
||||
{label}
|
||||
<Icon name="arrow_drop_down" className="mdl-color-text--grey-600"/>
|
||||
</Button>
|
||||
);
|
||||
|
||||
export const MenuItemWithIcon = ({ icon, label, disabled, ...menuItemProps }) => (
|
||||
<MenuItem disabled={disabled} style={{ display: 'flex', alignItems: 'center' }} {...menuItemProps}>
|
||||
<Icon name={icon} style={{ paddingRight: '16px' }}/>
|
||||
{label}
|
||||
</MenuItem>
|
||||
);
|
||||
|
||||
const badNumbers = [NaN, Infinity, -Infinity];
|
||||
export function calc (value, total, decimal) {
|
||||
if (typeof value !== 'number' ||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import { Switch, Icon, Chip } from 'react-mdl';
|
||||
import { Switch, Icon, Chip, ListItem } from 'react-mdl';
|
||||
import Progress from './progress';
|
||||
import { calc, styles as commonStyles } from '../common';
|
||||
|
||||
@ -27,13 +27,13 @@ const Feature = ({
|
||||
const remainingStrategies = strategies.length - strategiesToShow;
|
||||
|
||||
const strategyChips = strategies && strategies.slice(0, strategiesToShow).map((s, i) =>
|
||||
<Chip className={styles.iconListItemChip} key={i}>{s.name}</Chip>);
|
||||
<Chip className={styles.strategyChip} key={i}>{s.name}</Chip>);
|
||||
const summaryChip = remainingStrategies > 0 &&
|
||||
<Chip className={styles.iconListItemChip}>+{remainingStrategies}</Chip>;
|
||||
<Chip className={styles.strategyChip}>+{remainingStrategies}</Chip>;
|
||||
|
||||
return (
|
||||
<li key={name} className="mdl-list__item mdl-list__item--two-line">
|
||||
<span className={styles.iconListItemProgress}>
|
||||
<ListItem twoLine>
|
||||
<span className={styles.listItemMetric}>
|
||||
<div style={{ width: '40px', textAlign: 'center' }}>
|
||||
{
|
||||
isStale ?
|
||||
@ -46,26 +46,29 @@ const Feature = ({
|
||||
}
|
||||
</div>
|
||||
</span>
|
||||
<span className={styles.iconListItemToggle} style={{ flexShrink: 0 }}>
|
||||
<span className={styles.listItemToggle}>
|
||||
<Switch title={`Toggle ${name}`} key="left-actions" onChange={() => toggleFeature(name)} checked={enabled} />
|
||||
</span>
|
||||
<span className="mdl-list__item-primary-content" style={{ minWidth: 0 }}>
|
||||
<Link to={`/features/view/${name}`} className={[styles.link, commonStyles.truncate].join(' ')}>
|
||||
<span className={['mdl-list__item-primary-content', styles.listItemLink].join(' ')}>
|
||||
<Link to={`/features/view/${name}`} className={[commonStyles.listLink, commonStyles.truncate].join(' ')}>
|
||||
{name}
|
||||
<span className={['mdl-list__item-sub-title', commonStyles.truncate].join(' ')}>{description}</span>
|
||||
</Link>
|
||||
</span>
|
||||
<span className={commonStyles.hideLt920} style={{ flexShrink: 0 }}>
|
||||
<span className={[styles.listItemStrategies, commonStyles.hideLt920].join(' ')}>
|
||||
{strategyChips}
|
||||
{summaryChip}
|
||||
</span>
|
||||
</li>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
Feature.propTypes = {
|
||||
feature: PropTypes.object,
|
||||
toggleFeature: PropTypes.func,
|
||||
settings: PropTypes.object,
|
||||
metricsLastHour: PropTypes.object,
|
||||
metricsLastMinute: PropTypes.object,
|
||||
};
|
||||
|
||||
export default Feature;
|
||||
|
@ -1,56 +1,34 @@
|
||||
.action {
|
||||
color: #aaa !important;
|
||||
cursor: pointer;
|
||||
.toolbar {
|
||||
position: relative;
|
||||
padding: 0 104px 16px 24px;
|
||||
}
|
||||
|
||||
.yes {
|
||||
color: green;
|
||||
.toolbarButton {
|
||||
position: absolute;
|
||||
top: 56px;
|
||||
right: 24px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.no {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.iconListItemProgress {
|
||||
.listItemMetric {
|
||||
float: left;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.iconListItemToggle {
|
||||
float: left;
|
||||
.listItemToggle {
|
||||
margin-right: 16px;
|
||||
width: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.iconListItemChip {
|
||||
.listItemLink {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.listItemStrategies {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.strategyChip {
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
|
||||
.topList {
|
||||
display: flex;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.topListItem0 {
|
||||
flex: 1;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.topListItem {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.topListItem2 {
|
||||
flex: 2;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import Feature from './feature-list-item-component';
|
||||
import { Link } from 'react-router';
|
||||
import { Icon, Chip, ChipContact, IconButton, FABButton, Textfield, Menu, MenuItem, Grid, Cell } from 'react-mdl';
|
||||
import { Icon, FABButton, Textfield, Menu, MenuItem, Card, CardActions, List } from 'react-mdl';
|
||||
|
||||
import { styles as commonStyles } from '../common';
|
||||
import { MenuItemWithIcon, DropdownButton, styles as commonStyles } from '../common';
|
||||
import styles from './feature.scss';
|
||||
|
||||
export default class FeatureListComponent extends React.PureComponent {
|
||||
@ -15,6 +15,8 @@ export default class FeatureListComponent extends React.PureComponent {
|
||||
featureMetrics: PropTypes.object.isRequired,
|
||||
fetchFeatureToggles: PropTypes.func.isRequired,
|
||||
fetchFeatureMetrics: PropTypes.func.isRequired,
|
||||
updateSetting: PropTypes.func.isRequired,
|
||||
settings: React.PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
@ -49,56 +51,43 @@ export default class FeatureListComponent extends React.PureComponent {
|
||||
render () {
|
||||
const { features, toggleFeature, featureMetrics, settings } = this.props;
|
||||
|
||||
return (
|
||||
<Grid className="mdl-color--white">
|
||||
<Cell col={12}>
|
||||
<div className={styles.topList}>
|
||||
<Chip onClick={() => this.toggleMetrics()} className={styles.topListItem0}>
|
||||
{ settings.showLastHour &&
|
||||
<ChipContact className="mdl-color--teal mdl-color-text--white">
|
||||
<Icon name="hourglass_full" style={{ fontSize: '16px' }} />
|
||||
</ChipContact> }
|
||||
{ '1 hour' }
|
||||
</Chip>
|
||||
|
||||
<Chip onClick={() => this.toggleMetrics()} className={styles.topListItem0}>
|
||||
{ !settings.showLastHour &&
|
||||
<ChipContact className="mdl-color--teal mdl-color-text--white">
|
||||
<Icon name="hourglass_empty" style={{ fontSize: '16px' }} />
|
||||
</ChipContact> }
|
||||
{ '1 minute' }
|
||||
</Chip>
|
||||
|
||||
<div className={styles.topListItem2} style={{ margin: '-10px 10px 0 10px' }}>
|
||||
return (<div>
|
||||
<div className={styles.toolbar}>
|
||||
<Textfield
|
||||
floatingLabel
|
||||
value={settings.filter}
|
||||
onChange={(e) => { this.setFilter(e.target.value); }}
|
||||
label="Filter toggles"
|
||||
label="Search"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Link to="/features/create" className={styles.toolbarButton}>
|
||||
<FABButton accent title="Create feature toggle">
|
||||
<Icon name="add"/>
|
||||
</FABButton>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div style={{ position: 'relative' }} className={styles.topListItem0}>
|
||||
<IconButton name="sort" id="demo-menu-top-right" colored title="Sort" />
|
||||
<Menu target="demo-menu-top-right" valign="bottom" align="right" ripple onClick={
|
||||
(e) => this.setSort(e.target.getAttribute('data-target'))}>
|
||||
<MenuItem disabled>Filter by:</MenuItem>
|
||||
<MenuItem disabled={!settings.sort || settings.sort === 'nosort'} data-target="nosort">Default</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'name'} data-target="name">Name</MenuItem>
|
||||
<Card shadow={0} className={commonStyles.fullwidth}>
|
||||
<CardActions>
|
||||
<DropdownButton id="metric" label={`Last ${settings.showLastHour ? 'hour' : 'minute'}`}/>
|
||||
<Menu target="metric" onClick={() => this.toggleMetrics()}
|
||||
style={{ width: '168px' }}>
|
||||
<MenuItemWithIcon icon="hourglass_empty" disabled={!settings.showLastHour} data-target="minute"
|
||||
label="Last minute"/>
|
||||
<MenuItemWithIcon icon="hourglass_full" disabled={settings.showLastHour} data-target="hour"
|
||||
label="Last hour"/>
|
||||
</Menu>
|
||||
<DropdownButton id="sorting" label={`By ${settings.sort}`}/>
|
||||
<Menu target="sorting" onClick={(e) => this.setSort(e.target.getAttribute('data-target'))}
|
||||
style={{ width: '168px' }}>
|
||||
<MenuItem disabled={!settings.sort || settings.sort === 'name'} data-target="name">Name</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'enabled'} data-target="enabled">Enabled</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'appName'} data-target="appName">Application name</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'created'} data-target="created">Created</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'strategies'} data-target="strategies">Strategies</MenuItem>
|
||||
<MenuItem disabled={settings.sort === 'metrics'} data-target="metrics">Metrics</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
<Link to="/features/create" className={styles.topListItem0}>
|
||||
<IconButton ripple raised name="add" component="span" style={{ color: 'black' }}/>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<ul className={['mdl-list', commonStyles.list].join(' ')}>
|
||||
</CardActions>
|
||||
<hr className={commonStyles.divider}/>
|
||||
<List className={commonStyles.list}>
|
||||
{features.map((feature, i) =>
|
||||
<Feature key={i}
|
||||
settings={settings}
|
||||
@ -107,15 +96,9 @@ export default class FeatureListComponent extends React.PureComponent {
|
||||
feature={feature}
|
||||
toggleFeature={toggleFeature}/>
|
||||
)}
|
||||
</ul>
|
||||
<hr />
|
||||
<Link to="/features/create" className={styles.topListItem0}>
|
||||
<FABButton ripple component="span" mini>
|
||||
<Icon name="add" />
|
||||
</FABButton>
|
||||
</Link>
|
||||
</Cell>
|
||||
</Grid>
|
||||
</List>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,6 @@ const mapStateToProps = (state) => {
|
||||
// eslint-disable-next-line
|
||||
a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1
|
||||
));
|
||||
} else if (settings.sort === 'appName') {
|
||||
// AppName
|
||||
// features = features.sort((a, b) => {
|
||||
// if (a.appName < b.appName) { return -1; }
|
||||
// if (a.appName > b.appName) { return 1; }
|
||||
// return 0;
|
||||
// });
|
||||
} else if (settings.sort === 'created') {
|
||||
features = features.sort((a, b) => (
|
||||
new Date(a.createdAt) > new Date(b.createdAt) ? -1 : 1
|
||||
|
Loading…
Reference in New Issue
Block a user