diff --git a/frontend/package.json b/frontend/package.json index 0be3ca9967..d228354ffc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,7 +34,6 @@ "immutability-helper": "^2.0.0", "immutable": "^3.8.1", "normalize.css": "^5.0.0", - "percent": "^2.0.0", "react": "^15.3.1", "react-addons-css-transition-group": "^15.3.1", "react-dom": "^15.3.1", diff --git a/frontend/src/component/common/index.js b/frontend/src/component/common/index.js index 32cabc50b6..bd2c5e5082 100644 --- a/frontend/src/component/common/index.js +++ b/frontend/src/component/common/index.js @@ -96,3 +96,24 @@ export const ExternalIconLink = ({ url, children }) => ( {children} ); + +const badNumbers = [NaN, Infinity, -Infinity]; +export function calc (value, total, decimal) { + if (typeof value !== 'number' || + typeof total !== 'number' || + typeof decimal !== 'number') { + return null; + } + + if (total === 0) { + return 0; + } + + badNumbers.forEach((number) => { + if ([value, total, decimal].indexOf(number) > -1) { + return number; + } + }); + + return (value / total * 100).toFixed(decimal); +}; diff --git a/frontend/src/component/feature/feature-list-item-component.jsx b/frontend/src/component/feature/feature-list-item-component.jsx index 597f8f30bd..815dc32516 100644 --- a/frontend/src/component/feature/feature-list-item-component.jsx +++ b/frontend/src/component/feature/feature-list-item-component.jsx @@ -1,9 +1,8 @@ import React, { PropTypes } from 'react'; import { Link } from 'react-router'; import { Chip, Switch, Icon, IconButton } from 'react-mdl'; -import percentLib from 'percent'; import Progress from './progress'; -import { shorten } from '../common'; +import { shorten, calc } from '../common'; import style from './feature.scss'; @@ -21,8 +20,8 @@ const Feature = ({ const isStale = showLastHour ? metricsLastHour.isFallback : metricsLastMinute.isFallback; const percent = 1 * (showLastHour ? - percentLib.calc(metricsLastHour.yes, metricsLastHour.yes + metricsLastHour.no, 0) : - percentLib.calc(metricsLastMinute.yes, metricsLastMinute.yes + metricsLastMinute.no, 0) + calc(metricsLastHour.yes, metricsLastHour.yes + metricsLastHour.no, 0) : + calc(metricsLastMinute.yes, metricsLastMinute.yes + metricsLastMinute.no, 0) ); return (
  • @@ -30,12 +29,12 @@ const Feature = ({
    { isStale ? - : -
    - -
    + : +
    + +
    }
    diff --git a/frontend/src/component/feature/form/_strategies-add.jsx b/frontend/src/component/feature/form/_strategies-add.jsx new file mode 100644 index 0000000000..2897a69165 --- /dev/null +++ b/frontend/src/component/feature/form/_strategies-add.jsx @@ -0,0 +1,72 @@ +import React, { PropTypes } from 'react'; +import { Menu, MenuItem, IconButton } from 'react-mdl'; + + +const StaticMenu = ({ icon = 'add', title, onClick, items }) => ( +
    + trigger: + { + e.preventDefault(); + }} /> +
      + {items.map(name =>
    • { + e.preventDefault(); + onClick(name); + }}>{name}
    • )} +
    +
    +); + +class AddStrategy extends React.Component { + + static propTypes () { + return { + strategies: PropTypes.array.isRequired, + addStrategy: PropTypes.func.isRequired, + fetchStrategies: PropTypes.func.isRequired, + }; + } + + addStrategy = (strategyName) => { + const selectedStrategy = this.props.strategies.find(s => s.name === strategyName); + const parameters = {}; + const keys = Object.keys(selectedStrategy.parametersTemplate || {}); + keys.forEach(prop => { parameters[prop] = ''; }); + + + this.props.addStrategy({ + name: selectedStrategy.name, + parameters, + }); + }; + + stopPropagation (e) { + e.stopPropagation(); + e.preventDefault(); + } + + render () { + const menuStyle = { + maxHeight: '300px', + overflowY: 'auto', + backgroundColor: 'rgb(247, 248, 255)', + }; + return ( +
    + + } + onClick={(name) => this.addStrategy(name)} + items={this.props.strategies.map(s => s.name)} + /> + + +
    + ); + } +} + + +export default AddStrategy; diff --git a/frontend/src/component/feature/view-edit-container.jsx b/frontend/src/component/feature/view-edit-container.jsx index f3d2644374..83954ba937 100644 --- a/frontend/src/component/feature/view-edit-container.jsx +++ b/frontend/src/component/feature/view-edit-container.jsx @@ -2,7 +2,6 @@ import React, { PropTypes } from 'react'; import { Tabs, Tab, Grid, Cell, Icon, ProgressBar, List, ListItem, ListItemContent } from 'react-mdl'; import { Link } from 'react-router'; -import percentLib from 'percent'; import Progress from './progress'; import { connect } from 'react-redux'; @@ -11,7 +10,7 @@ import { fetchFeatureToggles, toggleFeature } from '../../store/feature-actions' import { fetchFeatureMetrics, fetchSeenApps } from '../../store/feature-metrics-actions'; import { fetchHistoryForToggle } from '../../store/history-actions'; -import { AppsLinkList, SwitchWithLabel, getIcon } from '../common'; +import { AppsLinkList, SwitchWithLabel, getIcon, calc } from '../common'; const MetricTab = ({ metrics, featureToggle, toggleFeature }) => { @@ -21,8 +20,8 @@ const MetricTab = ({ metrics, featureToggle, toggleFeature }) => { seenApps = [], } = metrics; - const lastHourPercent = 1 * percentLib.calc(lastHour.yes, lastHour.yes + lastHour.no, 0); - const lastMinutePercent = 1 * percentLib.calc(lastMinute.yes, lastMinute.yes + lastMinute.no, 0); + const lastHourPercent = 1 * calc(lastHour.yes, lastHour.yes + lastHour.no, 0); + const lastMinutePercent = 1 * calc(lastMinute.yes, lastMinute.yes + lastMinute.no, 0); return (