2016-12-09 22:11:05 +01:00
|
|
|
const React = require('react');
|
2016-12-17 16:57:27 +01:00
|
|
|
import styles from './common.scss';
|
|
|
|
|
|
|
|
|
2016-12-10 11:47:25 +01:00
|
|
|
const {
|
|
|
|
List, ListItem, ListItemContent,
|
|
|
|
Button, Icon,
|
2016-12-10 12:21:27 +01:00
|
|
|
Switch,
|
2016-12-10 11:47:25 +01:00
|
|
|
} = require('react-mdl');
|
2016-12-09 22:11:05 +01:00
|
|
|
const { Link } = require('react-router');
|
|
|
|
|
2017-01-04 00:29:27 +01:00
|
|
|
export { styles };
|
|
|
|
|
2016-12-10 15:39:03 +01:00
|
|
|
export const shorten = (str, len = 50) => (str && str.length > len ? `${str.substring(0, len)}...` : str);
|
|
|
|
|
2016-12-09 22:11:05 +01:00
|
|
|
export const AppsLinkList = ({ apps }) => (
|
|
|
|
<List style={{ textAlign: 'left' }}>
|
|
|
|
{apps.length > 0 && apps.map(({ appName, description = '-', icon = 'apps' }) => (
|
|
|
|
<ListItem twoLine key={appName}>
|
2016-12-10 15:39:03 +01:00
|
|
|
<ListItemContent avatar={icon} subtitle={shorten(description)}>
|
2016-12-09 22:11:05 +01:00
|
|
|
<Link key={appName} to={`/applications/${appName}`}>
|
|
|
|
{appName}
|
|
|
|
</Link>
|
|
|
|
</ListItemContent>
|
|
|
|
</ListItem>
|
|
|
|
))}
|
|
|
|
</List>
|
|
|
|
);
|
|
|
|
|
2016-12-10 11:47:25 +01:00
|
|
|
export const HeaderTitle = ({ title, actions, subtitle }) => (
|
2016-12-10 12:21:27 +01:00
|
|
|
<div style={{ display: 'flex', borderBottom: '1px solid #f1f1f1', marginBottom: '10px', padding: '16px 20px ' }}>
|
2016-12-13 20:54:53 +01:00
|
|
|
<div style={{ flex: '2' }}>
|
2016-12-10 12:21:27 +01:00
|
|
|
<h6 style={{ margin: 0 }}>{title}</h6>
|
|
|
|
{subtitle && <small>{subtitle}</small>}
|
|
|
|
</div>
|
|
|
|
|
2016-12-13 19:56:52 +01:00
|
|
|
{actions && <div style={{ flex: '1', textAlign: 'right' }}>{actions}</div>}
|
2016-12-10 12:21:27 +01:00
|
|
|
</div>
|
2016-12-10 11:47:25 +01:00
|
|
|
);
|
|
|
|
|
2017-01-26 11:53:07 +01:00
|
|
|
export const DataTableHeader = ({ title, actions }) => (
|
|
|
|
<div className={styles.dataTableHeader}>
|
|
|
|
<div className={styles.title}>
|
|
|
|
<h2 className={styles.titleText}>{title}</h2>
|
|
|
|
</div>
|
|
|
|
{actions &&
|
|
|
|
<div className={styles.actions}>
|
|
|
|
{actions}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2016-12-10 11:47:25 +01:00
|
|
|
export const FormButtons = ({ submitText = 'Create', onCancel }) => (
|
|
|
|
<div>
|
|
|
|
<Button type="submit" ripple raised primary icon="add">
|
|
|
|
<Icon name="add" />
|
|
|
|
{ submitText }
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button type="cancel" ripple raised onClick={onCancel} style={{ float: 'right' }}>
|
|
|
|
<Icon name="cancel" />
|
|
|
|
Cancel
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
);
|
2016-12-10 12:21:27 +01:00
|
|
|
|
2017-01-26 11:53:07 +01:00
|
|
|
export const SwitchWithLabel = ({ onChange, checked, children, ...switchProps }) => (
|
|
|
|
<span className={styles.switchWithLabel}>
|
|
|
|
<span className={styles.label}>{children}</span>
|
|
|
|
<span className={styles.switch}>
|
|
|
|
<Switch checked={checked} onChange={onChange} {...switchProps} />
|
2016-12-10 12:21:27 +01:00
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
|
2016-12-10 13:49:22 +01:00
|
|
|
export const TogglesLinkList = ({ toggles }) => (
|
2016-12-17 16:57:27 +01:00
|
|
|
<List style={{ textAlign: 'left' }} className={styles.truncate}>
|
2016-12-10 13:49:22 +01:00
|
|
|
{toggles.length > 0 && toggles.map(({ name, description = '-', icon = 'toggle' }) => (
|
|
|
|
<ListItem twoLine key={name}>
|
|
|
|
<ListItemContent avatar={icon} subtitle={description}>
|
2017-01-01 17:34:06 +01:00
|
|
|
<Link key={name} to={`/features/view/${name}`}>
|
2016-12-10 13:49:22 +01:00
|
|
|
{name}
|
|
|
|
</Link>
|
|
|
|
</ListItemContent>
|
|
|
|
</ListItem>
|
|
|
|
))}
|
|
|
|
</List>
|
|
|
|
);
|
2016-12-10 14:02:41 +01:00
|
|
|
|
|
|
|
export function getIcon (type) {
|
|
|
|
switch (type) {
|
|
|
|
case 'feature-updated': return 'autorenew';
|
|
|
|
case 'feature-created': return 'add';
|
|
|
|
case 'feature-deleted': return 'remove';
|
|
|
|
case 'feature-archived': return 'archived';
|
|
|
|
default: return 'star';
|
|
|
|
}
|
|
|
|
};
|
2016-12-10 15:10:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
export const IconLink = ({ icon, children, ...props }) => (
|
|
|
|
<a {...props} style={{ textDecoration: 'none' }}>
|
|
|
|
<Icon name={icon} style={{ marginRight: '5px', verticalAlign: 'middle' }}/>
|
|
|
|
<span style={{ textDecoration: 'none', verticalAlign: 'middle' }}>{children}</span>
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
|
|
|
|
export const ExternalIconLink = ({ url, children }) => (
|
|
|
|
<IconLink icon="queue" href={url} target="_blank" rel="noopener">
|
|
|
|
{children}
|
|
|
|
</IconLink>
|
|
|
|
);
|
2016-12-17 20:54:48 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
};
|