1
0
mirror of https://github.com/yldio/copilot.git synced 2024-11-28 14:10:04 +02:00

Merge branch 'master' into seperating-normalize-css

This commit is contained in:
Alex Windett 2017-01-20 13:27:14 +00:00 committed by GitHub
commit 27fccb364d
28 changed files with 2384 additions and 1729 deletions

View File

@ -50,6 +50,18 @@ server.register(plugins, (err) => {
process.exit(1); process.exit(1);
} }
server.route({
method: 'GET',
path: '/static/images/{param*}',
handler: {
directory: {
path: './images/',
redirectToSlash: true,
index: false
}
}
});
server.route({ server.route({
method: 'GET', method: 'GET',
path: '/static/{param*}', path: '/static/{param*}',

View File

@ -0,0 +1,100 @@
const Container = require('@ui/components/container');
const PropTypes = require('@root/prop-types');
const React = require('react');
const ReactRouter = require('react-router');
const Styled = require('styled-components');
const flatten = require('lodash.flatten');
const fns = require('@ui/shared/functions');
const {
remcalc
} = fns;
const {
default: styled
} = Styled;
// Main Contonent Wrapper Styles
const StyledDiv = styled.div`
background-color: #FAFAFA;
height: ${remcalc(91)};
border-bottom: solid ${remcalc(1)} #d8d8d8;
`;
const BreadcrumbA = styled.a`
text-decoration: none !important;
`;
const BreadcrumbSpan = styled.span`
color: #646464;
`;
const H1 = styled.h1`
margin: 0 0 0 0;
padding-top: ${remcalc(31)};
padding-bottom: ${remcalc(31)};
`;
const {
Link
} = ReactRouter;
function getNameLink(name) {
return flatten(name.map((part, i) => {
if (!part.name) {
return null;
}
const link = (
<Link key={part.pathname} to={part.pathname}>
{
({
href,
onClick,
}) =>
<BreadcrumbA href={href} onClick={onClick}>
{part.name}
</BreadcrumbA>
}
</Link>
);
const key = `${part.pathname}${i}`;
const slash = (
<BreadcrumbSpan key={key}> / </BreadcrumbSpan>
);
return (i === 0) ? link : [
slash,
link
];
}));
}
const Breadcrumb = ({
children,
links = [],
name = []
}) => {
return (
<Container>
<StyledDiv>
<H1
style={{
fontSize: remcalc(24)
}}
>
{getNameLink(name)}
</H1>
</StyledDiv>
</Container>
);
};
Breadcrumb.propTypes = {
children: React.PropTypes.node,
links: React.PropTypes.arrayOf(PropTypes.link),
name: React.PropTypes.arrayOf(PropTypes.link)
};
module.exports = Breadcrumb;

View File

@ -66,6 +66,8 @@ const StyledTooltipWrapper = styled.div`
`; `;
const StyledName = styled.span` const StyledName = styled.span`
color: #646464;
font-size: ${remcalc(16)}
position: relative; position: relative;
top: ${remcalc(-12)}; top: ${remcalc(-12)};
`; `;

View File

@ -42,6 +42,7 @@ const StyledNav = styled.div`
// TODO: refactor colours into constants in UI // TODO: refactor colours into constants in UI
const NavigationLinkContainer = styled.div` const NavigationLinkContainer = styled.div`
position: relative;
padding: ${remcalc(11)} ${remcalc(12)} ${remcalc(12)}; padding: ${remcalc(11)} ${remcalc(12)} ${remcalc(12)};
color: #646464; color: #646464;
border: solid ${remcalc(1)} #d8d8d8; border: solid ${remcalc(1)} #d8d8d8;
@ -77,6 +78,17 @@ const NavLi = styled.li`
} }
`; `;
const Shadow = styled.div`
z-index: 1;
position: absolute;
height: ${remcalc(5)};
width: 100%;
left: 0;
bottom: 0;
background-image:
linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.06));
`;
const OrgNavigation = ({ const OrgNavigation = ({
orgs = [] orgs = []
}) => { }) => {
@ -98,6 +110,7 @@ const OrgNavigation = ({
}) => }) =>
<a href={href} onClick={onClick}> <a href={href} onClick={onClick}>
<NavigationLinkContainer className={isActive ? 'active' : ''}> <NavigationLinkContainer className={isActive ? 'active' : ''}>
{ !isActive && <Shadow />}
<OrgImage> <OrgImage>
<OrgAvatar <OrgAvatar
height={remcalc(26)} height={remcalc(26)}

View File

@ -0,0 +1,31 @@
const React = require('react');
const PropTypes = require('@root/prop-types');
// const List = require('@ui/components/list');
// const {
// ListItem,
// ListItemView,
// ListItemMeta,
// ListItemTitle,
// ListItemOptions
// } = List;
const PersonItem = ({
person = {},
}) => {
return (
<tr>
<td>{person.uuid}</td>
<td>{person.uuid}</td>
<td>{person.uuid}</td>
</tr>
);
};
PersonItem.propTypes = {
person: PropTypes.person,
};
module.exports = PersonItem;

View File

@ -0,0 +1,39 @@
const React = require('react');
const PersonItem = require('@components/people-item');
const PropTypes = require('@root/prop-types');
const PeopleList = ({
people = []
}) => {
const peopleList = people.map((person) => (
<PersonItem
key={person.uuid}
person={person}
/>
));
return (
<div>
<table>
<thead>
<tr>
<th>Member</th>
<th>Status</th>
<th>Role</th>
</tr>
</thead>
<tbody>
{peopleList}
</tbody>
</table>
</div>
);
};
PeopleList.propTypes = {
people: React.PropTypes.arrayOf(PropTypes.person),
};
module.exports = PeopleList;

View File

@ -1,30 +1,11 @@
const flatten = require('lodash.flatten');
const React = require('react'); const React = require('react');
const ReactIntl = require('react-intl'); const ReactIntl = require('react-intl');
const Styled = require('styled-components');
const ReactRouter = require('react-router'); const ReactRouter = require('react-router');
const H1 = require('@ui/components/base-elements').H1;
const Li = require('@ui/components/horizontal-list/li'); const Li = require('@ui/components/horizontal-list/li');
const PropTypes = require('@root/prop-types'); const PropTypes = require('@root/prop-types');
const Ul = require('@ui/components/horizontal-list/ul'); const Ul = require('@ui/components/horizontal-list/ul');
const fns = require('@ui/shared/functions'); const Breadcrumb = require('@components/breadcrumb');
const {
default: styled
} = Styled;
const BreadcrumbA = styled.a`
text-decoration: none !important;
`;
const BreadcrumbSpan = styled.span`
color: #646464;
`;
const {
remcalc
} = fns;
const { const {
FormattedMessage FormattedMessage
@ -34,11 +15,12 @@ const {
Link Link
} = ReactRouter; } = ReactRouter;
const Section = ({ const Section = (props) => {
children, const {
links = [], children,
name = [] links = [],
}) => { } = props;
const navLinks = links.map((link) => ( const navLinks = links.map((link) => (
<Li key={link.name}> <Li key={link.name}>
<Link activeClassName='active' to={link.pathname}> <Link activeClassName='active' to={link.pathname}>
@ -47,44 +29,9 @@ const Section = ({
</Li> </Li>
)); ));
const nameLinks = flatten(name.map((part, i) => {
if (!part.name) {
return null;
}
const link = (
<Link key={part.pathname} to={part.pathname}>
{
({
href,
onClick,
}) =>
<BreadcrumbA href={href} onClick={onClick}>
{part.name}
</BreadcrumbA>
}
</Link>
);
const slash = (
<BreadcrumbSpan key={`${part.pathname}${i}`}> / </BreadcrumbSpan>
);
return (i === 0) ? link : [
slash,
link
];
}));
return ( return (
<div> <div>
<H1 <Breadcrumb {...props} />
style={{
fontSize: remcalc(24)
}}
>
{nameLinks}
</H1>
<Ul> <Ul>
{navLinks} {navLinks}
</Ul> </Ul>
@ -95,8 +42,7 @@ const Section = ({
Section.propTypes = { Section.propTypes = {
children: React.PropTypes.node, children: React.PropTypes.node,
links: React.PropTypes.arrayOf(PropTypes.link), links: React.PropTypes.arrayOf(PropTypes.link)
name: React.PropTypes.arrayOf(PropTypes.link)
}; };
module.exports = Section; module.exports = Section;

View File

@ -3,6 +3,13 @@ const React = require('react');
const ReactRedux = require('react-redux'); const ReactRedux = require('react-redux');
// const ReactRouter = require('react-router'); // const ReactRouter = require('react-router');
const Row = require('@ui/components/row');
const Column= require('@ui/components/column');
const Button= require('@ui/components/button');
const PropTypes = require('@root/prop-types');
const PeopleList = require('@components/people-list');
const selectors = require('@state/selectors');
const Section = require('./section'); const Section = require('./section');
// const { // const {
@ -13,23 +20,53 @@ const {
connect connect
} = ReactRedux; } = ReactRedux;
// const { const {
// Link, peopleByOrgIdSelector
// Match, } = selectors;
// Miss,
// Redirect const buttonStyle = {
// } = ReactRouter; float: 'right'
};
const People = (props) => { const People = (props) => {
const {
people = []
} = props;
return ( return (
<Section {...props}> <Section {...props}>
<p>people</p> <Row>
<Column smOffset={9} xs={2}>
<Button style={buttonStyle}>Invite</Button>
</Column>
</Row>
<Row>
<Column>
<PeopleList
people={people}
/>
</Column>
</Row>
</Section> </Section>
); );
}; };
People.propTypes = {}; People.propTypes = {
people: React.PropTypes.arrayOf(PropTypes.person)
// toggleCollapsed: React.PropTypes.func
};
const mapStateToProps = (state) => ({}); const mapStateToProps = (state, {
params = {}
}) => ({
people: peopleByOrgIdSelector(params.org)(state)
});
module.exports = connect(mapStateToProps)(People); const mapDispatchToProps = (dispatch) => ({});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(People);

View File

@ -211,18 +211,23 @@
"owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01", "owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01",
"id": "nicola", "id": "nicola",
"name": "Your dashboard", "name": "Your dashboard",
"image": "https://pbs.twimg.com/profile_images/641289584580493312/VBfsPlff_400x400.jpg" "image": "https://pbs.twimg.com/profile_images/641289584580493312/VBfsPlff_400x400.jpg",
"members": {}
}, { }, {
"owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01", "owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01",
"uuid": "e12ad7db-91b2-4154-83dd-40dcfc700dcc", "uuid": "e12ad7db-91b2-4154-83dd-40dcfc700dcc",
"id": "biz-tech", "id": "biz-tech",
"name": "BizTech" "name": "BizTech",
"members": [{
"uuid": "fd853d8f-e1dd-49b5-b7b3-ae9adfea1e2f"
}]
}, { }, {
"owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01", "owner": "b94033c1-3665-4c36-afab-d9c3d0b51c01",
"uuid": "551f316d-e414-480f-9787-b4c408db3edd", "uuid": "551f316d-e414-480f-9787-b4c408db3edd",
"id": "make-us-proud", "id": "make-us-proud",
"name": "Make Us Proud", "name": "Make Us Proud",
"image": "/static/images/make-us-proud.svg" "image": "/static/images/make-us-proud.svg",
"members": {}
}] }]
}, },
"projects": { "projects": {

View File

@ -61,6 +61,10 @@ const Sections = React.PropTypes.arrayOf(
React.PropTypes.string React.PropTypes.string
); );
const Person = React.PropTypes.shape({
...BaseObject
});
module.exports = { module.exports = {
account: Account, account: Account,
link: Link, link: Link,
@ -71,5 +75,6 @@ module.exports = {
instance: Instance, instance: Instance,
metric: Metric, metric: Metric,
metricType: MetricType, metricType: MetricType,
dataset: Dataset dataset: Dataset,
person: Person
}; };

View File

@ -18,6 +18,7 @@ const services = (state) => get(state, 'services.data', []);
const collapsedServices = (state) => get(state, 'services.ui.collapsed', []); const collapsedServices = (state) => get(state, 'services.ui.collapsed', []);
const collapsedInstances = (state) => get(state, 'instances.ui.collapsed', []); const collapsedInstances = (state) => get(state, 'instances.ui.collapsed', []);
const instances = (state) => get(state, 'instances.data', []); const instances = (state) => get(state, 'instances.data', []);
const members = (state) => get(state, 'members.data', []);
const metricTypes = (state) => get(state, 'metrics.data.types', []); const metricTypes = (state) => get(state, 'metrics.data.types', []);
const metricDatasets = (state) => get(state, 'metrics.data.datasets', []); const metricDatasets = (state) => get(state, 'metrics.data.datasets', []);
@ -110,6 +111,12 @@ const instancesByProjectId = (projectId) => createSelector(
})) }))
); );
const peopleByOrgId = (orgId) => createSelector(
// [members, orgById(orgId)], (members, org) => org.members
[members, orgById(orgId)], (members, org) => org.members
);
module.exports = { module.exports = {
accountSelector: account, accountSelector: account,
accountUISelector: accountUi, accountUISelector: accountUi,
@ -126,5 +133,6 @@ module.exports = {
instancesByServiceIdSelector: instancesByServiceId, instancesByServiceIdSelector: instancesByServiceId,
metricsByServiceIdSelector: metricsByServiceId, metricsByServiceIdSelector: metricsByServiceId,
instancesByProjectIdSelector: instancesByProjectId, instancesByProjectIdSelector: instancesByProjectId,
metricTypeByUuidSelector: metricTypeByUuid metricTypeByUuidSelector: metricTypeByUuid,
peopleByOrgIdSelector: peopleByOrgId
}; };

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@ install-production: compile clean
.PHONY: compile .PHONY: compile
compile: install compile: install
mkdir -p dist mkdir -p dist
cp -R src/ dist/. cp -R src/. dist/.
$(bindir)/babel src --out-dir dist --source-maps inline $(bindir)/babel src --out-dir dist --source-maps inline
.PHONY: build .PHONY: build

View File

@ -27,6 +27,7 @@
"lodash.isfunction": "^3.0.8", "lodash.isfunction": "^3.0.8",
"lodash.isstring": "^4.0.1", "lodash.isstring": "^4.0.1",
"lodash.isundefined": "^3.0.1", "lodash.isundefined": "^3.0.1",
"moment": "^2.17.1",
"param-case": "^2.1.0", "param-case": "^2.1.0",
"random-natural": "^1.0.3", "random-natural": "^1.0.3",
"react": "^15.4.2", "react": "^15.4.2",

View File

@ -69,14 +69,6 @@ const style = css`
padding: ${remcalc('14 16')}; padding: ${remcalc('14 16')};
position: relative; position: relative;
font-family: -apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
"Helvetica Neue",
Arial,
sans-serif;
font-size: ${remcalc(16)}; font-size: ${remcalc(16)};
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
@ -130,6 +122,7 @@ const style = css`
`; `;
const StyledButton = styled.button` const StyledButton = styled.button`
min-width: ${remcalc(120)};
${style} ${style}
`; `;

View File

@ -1,13 +1,8 @@
const constants = require('../../shared/constants');
const fns = require('../../shared/functions'); const fns = require('../../shared/functions');
const Item = require('./item'); const Item = require('./item');
const React = require('react'); const React = require('react');
const Styled = require('styled-components'); const Styled = require('styled-components');
const {
colors
} = constants;
const { const {
remcalc remcalc
} = fns; } = fns;
@ -19,8 +14,9 @@ const {
const StyledItem = styled(Item)` const StyledItem = styled(Item)`
position: absolute; position: absolute;
background-color: ${colors.brandPrimary}; background-color: #3B4AAF;
border: solid ${remcalc(1)} ${colors.borderPrimary};
border: solid ${remcalc(1)} #2D3884;
box-shadow: none; box-shadow: none;
width: calc(100% + ${remcalc(2)}); width: calc(100% + ${remcalc(2)});

View File

@ -1,33 +0,0 @@
const React = require('react');
const Styled = require('styled-components');
const fns = require('../../shared/functions');
const {
remcalc
} = fns;
const {
default: styled
} = Styled;
const StyledBody = styled.div`
margin: 0;
width: 100%;
height: ${remcalc(264)};
`;
const Body = ({
children
}) => {
return (
<StyledBody name='metric-body'>
{children}
</StyledBody>
);
};
Body.propTypes = {
children: React.PropTypes.node
};
module.exports = Body;

View File

@ -0,0 +1,174 @@
const React = require('react');
const Styled = require('styled-components');
const moment = require('moment');
const Chart = require('chart.js');
const whisker = require('chartjs-chart-box-plot');
whisker(Chart);
const {
default: styled
} = Styled;
const Container = styled.div`
position: relative;
height: 100%;
width: 100%;
`;
const Canvas = styled.canvas`
`;
class Graph extends React.Component {
componentDidMount() {
const {
yMax = 100,
yMin = 0,
yMeasurement = '%'
} = this.props;
const {
data,
xMax,
xMin,
xUnitStepSize
} = this.processData(this.props);
this._chart = new Chart(this._refs.component, {
type: 'whisker',
responsive: true,
maintainAspectRatio: true,
data: {
datasets: [{
data: data
}]
},
options: {
layout: {
padding: 10
},
scales: {
xAxes: [{
display: true,
type: 'time',
time: {
unit: 'minute',
unitStepSize: xUnitStepSize,
max: xMax,
min: xMin,
/*displayFormats: {
hour: 'MMM D, hA'
}*/
},
}],
yAxes: [{
display: true,
ticks: {
min: yMin,
max: yMax,
callback: (value, index, values) => {
return `${value.toFixed(2)}${yMeasurement}`;
}
}
}]
},
legend: {
display: false
}
},
});
}
componentWillReceiveProps(nextProps) {
const {
data,
xMax,
xMin,
xUnitStepSize
} = this.processData(nextProps);
this._chart.data.datasets = [{
data
}];
this._chart.options.scales.xAxes[0].time.max = xMax;
this._chart.options.scales.xAxes[0].time.min = xMin;
this._chart.options.scales.xAxes[0].time.unitStepSize = xUnitStepSize;
this._chart.update(0);
}
processData(props) {
const {
data = [],
duration = 360
} = this.props;
// I'm going to assume that data will be structured in 10min intervals...
// And that newest data will be at the end...
// Let's rock and roll!
// All this shizzle below needs to be recalculated on new props, yay!
const now = moment();
// first time on scale x
const before = moment().subtract(duration, 'minutes');
// remove leading data before first time on scale x
const totalData = data.slice(data.length - 1 - duration/10);
// adjust time of first data, if there's less data than would fill the chart
const start = moment(before)
.add(duration - (totalData.length-1)*10, 'minutes');
// add times to data
const dataWithTime = totalData.map((d, i) => {
const add = i*10;
return Object.assign(
{},
d,
{
x: moment(start).add(add, 'minutes').toDate()
}
);
});
// set min and max
const xMax = now.toDate();
const xMin = before.toDate();
// calculate stepsize
const xUnitStepSize = duration/6;
return {
data: dataWithTime,
xMax,
xMin,
xUnitStepSize
};
}
ref(name) {
this._refs = this._refs || {};
return (el) => {
this._refs[name] = el;
};
}
render() {
return (
<Container name='metric-body'>
<Canvas
height={262}
innerRef={this.ref('component')}
width={940}
/>
</Container>
);
}
}
Graph.propTypes = {
data: React.PropTypes.array,
duration: React.PropTypes.number,
yMax: React.PropTypes.number,
yMeasurement: React.PropTypes.string,
yMin: React.PropTypes.number
};
module.exports = Graph;

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>icon: settings </title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="project:-adding-metrics-1.4" transform="translate(-979.000000, -413.000000)" fill="#FFFFFF">
<g id="metric:-cpu" transform="translate(208.000000, 391.000000)">
<g id="metric-head" transform="translate(5.000000, 0.000000)">
<g id="button:-settinga" transform="translate(742.000000, 0.000000)">
<path d="M33,34 C31.3425,34 30,32.6575 30,31 C30,29.3425 31.3425,28 33,28 C34.6575,28 36,29.3425 36,31 C36,32.6575 34.6575,34 33,34 L33,34 Z M42,32.5 L42,29.5 L40.3485,29.5 C40.155,28.543 39.774,27.655 39.252,26.869 L40.425,25.696 L38.304,23.575 L37.131,24.748 C36.345,24.226 35.457,23.845 34.5,23.6515 L34.5,22 L31.5,22 L31.5,23.6515 C30.543,23.845 29.655,24.226 28.869,24.748 L27.696,23.575 L25.575,25.696 L26.748,26.869 C26.226,27.655 25.845,28.543 25.6515,29.5 L24,29.5 L24,32.5 L25.6515,32.5 C25.845,33.457 26.226,34.345 26.748,35.131 L25.575,36.304 L27.696,38.425 L28.869,37.252 C29.655,37.774 30.543,38.155 31.5,38.3485 L31.5,40 L34.5,40 L34.5,38.3485 C35.457,38.155 36.345,37.774 37.131,37.252 L38.304,38.425 L40.425,36.304 L39.252,35.131 C39.774,34.345 40.155,33.457 40.3485,32.5 L42,32.5 Z" id="icon:-settings-"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
MetricBody: require('./body'), MetricGraph: require('./graph'),
MetricCloseButton: require('./close-button'), MetricCloseButton: require('./close-button'),
MetricHeader: require('./header'), MetricHeader: require('./header'),
MetricSelect: require('./select'), MetricSelect: require('./select'),

View File

@ -0,0 +1,307 @@
module.exports = [{
firstQuartile: 15,
thirdQuartile: 15,
median: 15,
max: 15,
min: 15,
}, {
firstQuartile: 26,
thirdQuartile: 26,
median: 26,
max: 26,
min: 26,
}, {
firstQuartile: 17,
thirdQuartile: 17,
median: 17,
max: 17,
min: 17,
}, {
firstQuartile: 15,
thirdQuartile: 25,
median: 19,
max: 19,
min: 20,
}, {
firstQuartile: 19,
thirdQuartile: 25,
median: 21,
max: 20,
min: 25,
}, {
firstQuartile: 24,
thirdQuartile: 30,
median: 25,
max: 26,
min: 27,
}, {
firstQuartile: 28,
thirdQuartile: 34,
median: 30,
max: 30,
min: 30,
}, {
firstQuartile: 30,
thirdQuartile: 45,
median: 35,
max: 40,
min: 40,
}, {
firstQuartile: 20,
thirdQuartile: 55,
median: 45,
max: 44,
min: 44,
}, {
firstQuartile: 55,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 57,
max: 58,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 56,
max: 56,
min: 56,
}, {
firstQuartile: 60,
thirdQuartile: 56,
median: 60,
max: 60,
min: 60,
}, {
firstQuartile: 57,
thirdQuartile: 57,
median: 57,
max: 57,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 20,
thirdQuartile: 45,
median: 45,
max: 45,
min: 45,
}, {
firstQuartile: 15,
thirdQuartile: 40,
median: 30,
max: 49,
min: 30,
}, {
firstQuartile: 15,
thirdQuartile: 15,
median: 15,
max: 15,
min: 15,
}, {
firstQuartile: 26,
thirdQuartile: 26,
median: 26,
max: 26,
min: 26,
}, {
firstQuartile: 17,
thirdQuartile: 17,
median: 17,
max: 17,
min: 17,
}, {
firstQuartile: 15,
thirdQuartile: 25,
median: 19,
max: 19,
min: 20,
}, {
firstQuartile: 19,
thirdQuartile: 25,
median: 21,
max: 20,
min: 25,
}, {
firstQuartile: 24,
thirdQuartile: 30,
median: 25,
max: 26,
min: 10,
}, {
firstQuartile: 28,
thirdQuartile: 34,
median: 30,
max: 30,
min: 30,
}, {
firstQuartile: 30,
thirdQuartile: 45,
median: 35,
max: 40,
min: 40,
}, {
firstQuartile: 20,
thirdQuartile: 55,
median: 45,
max: 44,
min: 44,
}, {
firstQuartile: 55,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 57,
max: 58,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 56,
max: 56,
min: 56,
}, {
firstQuartile: 60,
thirdQuartile: 56,
median: 60,
max: 60,
min: 60,
}, {
firstQuartile: 57,
thirdQuartile: 57,
median: 57,
max: 57,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 20,
thirdQuartile: 45,
median: 45,
max: 45,
min: 45,
}, {
firstQuartile: 15,
thirdQuartile: 40,
median: 30,
max: 49,
min: 30,
}, {
firstQuartile: 15,
thirdQuartile: 15,
median: 15,
max: 15,
min: 15,
}, {
firstQuartile: 26,
thirdQuartile: 26,
median: 26,
max: 26,
min: 26,
}, {
firstQuartile: 17,
thirdQuartile: 17,
median: 17,
max: 17,
min: 17,
}, {
firstQuartile: 15,
thirdQuartile: 25,
median: 19,
max: 19,
min: 20,
}, {
firstQuartile: 19,
thirdQuartile: 25,
median: 21,
max: 20,
min: 25,
}, {
firstQuartile: 24,
thirdQuartile: 30,
median: 25,
max: 26,
min: 27,
}, {
firstQuartile: 28,
thirdQuartile: 34,
median: 30,
max: 30,
min: 30,
}, {
firstQuartile: 30,
thirdQuartile: 45,
median: 35,
max: 40,
min: 40,
}, {
firstQuartile: 20,
thirdQuartile: 55,
median: 45,
max: 44,
min: 44,
}, {
firstQuartile: 55,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 57,
max: 58,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 56,
median: 56,
max: 56,
min: 56,
}, {
firstQuartile: 60,
thirdQuartile: 56,
median: 60,
max: 60,
min: 60,
}, {
firstQuartile: 57,
thirdQuartile: 57,
median: 57,
max: 57,
min: 57,
}, {
firstQuartile: 57,
thirdQuartile: 55,
median: 55,
max: 55,
min: 55,
}, {
firstQuartile: 20,
thirdQuartile: 45,
median: 45,
max: 45,
min: 45,
}, {
firstQuartile: 15,
thirdQuartile: 40,
median: 30,
max: 49,
min: 30,
}];

View File

@ -59,8 +59,10 @@ const Select = ({
form, form,
id = rndId(), id = rndId(),
name, name,
onChange,
required, required,
selected selected,
value
}) => { }) => {
return ( return (
<SelectWrapper> <SelectWrapper>
@ -70,8 +72,10 @@ const Select = ({
form={form} form={form}
id={id} id={id}
name={name} name={name}
onChange={onChange}
required={required} required={required}
selected={selected} selected={selected}
value={value}
> >
{children} {children}
</StyledSelect> </StyledSelect>
@ -86,8 +90,10 @@ Select.propTypes = {
form: React.PropTypes.string, form: React.PropTypes.string,
id: React.PropTypes.string, id: React.PropTypes.string,
name: React.PropTypes.string, name: React.PropTypes.string,
onChange: React.PropTypes.func,
required: React.PropTypes.bool, required: React.PropTypes.bool,
selected: React.PropTypes.bool selected: React.PropTypes.bool,
value: React.PropTypes.string
}; };
module.exports = Select; module.exports = Select;

View File

@ -3,7 +3,8 @@ const Styled = require('styled-components');
const fns = require('../../shared/functions'); const fns = require('../../shared/functions');
const constants = require('../../shared/constants'); const constants = require('../../shared/constants');
const Button = require('../button'); const Button = require('../button');
const SettingsIcon = require('!babel!svg-react!./close.svg?name=SettingsIcon'); const SettingsIcon =
require('!babel!svg-react!./icon-settings.svg?name=SettingsIcon');
const { const {
default: styled default: styled

View File

@ -6,7 +6,7 @@ const {
} = require('@kadira/storybook'); } = require('@kadira/storybook');
const { const {
MetricBody, MetricGraph,
MetricCloseButton, MetricCloseButton,
MetricHeader, MetricHeader,
MetricSelect, MetricSelect,
@ -15,7 +15,42 @@ const {
MetricView MetricView
} = require('./'); } = require('./');
const MetricData = require('./metric-data');
const onButtonClick = () => {}; const onButtonClick = () => {};
const onMetricSelect = () => {};
const hour = 60; // in minutes - for moment
const sixHours = 6*hour;
const twelveHours = 12*hour;
const oneDay = 24*hour;
const twoDays = 48*hour;
const withinRange = (
value,
newMin,
newMax,
precision = 2,
oldMin = 0,
oldMax = 100
) => {
const normalisedValue = value-oldMin;
const newRange = newMax-newMin;
const oldRange = oldMax-oldMin;
const newValue = newMin + normalisedValue*newRange/oldRange;
return newValue.toFixed(2);
};
const percentageMetricData = MetricData;
const kbMetricData = MetricData.map(m => {
return {
firstQuartile: withinRange(m.firstQuartile, 1.55, 2.0),
thirdQuartile: withinRange(m.thirdQuartile, 1.55, 2.0),
median: withinRange(m.median, 1.55, 2.0),
max: withinRange(m.max, 1.55, 2.0),
min: withinRange(m.min, 1.55, 2.0),
};
});
storiesOf('Metric', module) storiesOf('Metric', module)
.add('Metric', () => ( .add('Metric', () => (
@ -23,16 +58,46 @@ storiesOf('Metric', module)
<MetricView> <MetricView>
<MetricHeader> <MetricHeader>
<MetricTitle>Aggregated CPU usage</MetricTitle> <MetricTitle>Aggregated CPU usage</MetricTitle>
<MetricSelect> <MetricSelect onChange={onMetricSelect} value={sixHours}>
<option selected>6 hours</option> <option value={sixHours}>6 hours</option>
<option>12 hours</option> <option value={twelveHours}>12 hours</option>
<option>24 hours</option> <option value={oneDay}>24 hours</option>
<option>Two days</option> <option value={twoDays}>Two days</option>
</MetricSelect> </MetricSelect>
<MetricSettingsButton>Settings</MetricSettingsButton> <MetricSettingsButton onClick={onButtonClick}>
Settings
</MetricSettingsButton>
<MetricCloseButton onClick={onButtonClick} /> <MetricCloseButton onClick={onButtonClick} />
</MetricHeader> </MetricHeader>
<MetricBody /> <MetricGraph
data={percentageMetricData}
duration={sixHours}
yMax={100}
yMeasurement='%'
yMin={0}
/>
</MetricView>
<MetricView>
<MetricHeader>
<MetricTitle>Aggregated CPU usage</MetricTitle>
<MetricSelect onChange={onMetricSelect} value={twoDays}>
<option value={sixHours}>6 hours</option>
<option value={twelveHours}>12 hours</option>
<option value={oneDay}>24 hours</option>
<option value={twoDays}>Two days</option>
</MetricSelect>
<MetricSettingsButton onClick={onButtonClick}>
Settings
</MetricSettingsButton>
<MetricCloseButton onClick={onButtonClick} />
</MetricHeader>
<MetricGraph
data={kbMetricData}
duration={oneDay}
yMax={2.0}
yMeasurement='kb'
yMin={1.55}
/>
</MetricView> </MetricView>
</Base> </Base>
)); ));

View File

@ -1,4 +1,5 @@
const constants = require('../../shared/constants'); const constants = require('../../shared/constants');
const fns = require('../../shared/functions');
const React = require('react'); const React = require('react');
const Styled = require('styled-components'); const Styled = require('styled-components');
@ -7,6 +8,10 @@ const {
colors colors
} = constants; } = constants;
const {
remcalc
} = fns;
const { const {
default: styled default: styled
} = Styled; } = Styled;
@ -15,6 +20,7 @@ const Container = styled.div`
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
max-width: ${remcalc(940)};
box-shadow: ${boxes.bottomShaddow}; box-shadow: ${boxes.bottomShaddow};
border: 1px solid ${colors.borderSecondary}; border: 1px solid ${colors.borderSecondary};
`; `;

View File

@ -0,0 +1,55 @@
const React = require('react');
const Base = require('../base');
const Row = require('../row');
const Column = require('../column');
const {
storiesOf,
// action,
// linkTo
} = require('@kadira/storybook');
const {
MiniMetricGraph,
MiniMetricMeta,
MiniMetricTitle,
MiniMetricSubtitle,
MiniMetricView
} = require('./');
const MiniMetricData = require('../list/mini-metric-data');
storiesOf('Metric (Mini)', module)
.add('Mini Metric', () => (
<Base>
<Row around>
<Column xs={3}>
<MiniMetricView>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
</Column>
<Column xs={3}>
<MiniMetricView>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
</Column>
<Column xs={3}>
<MiniMetricView>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
</Column>
</Row>
</Base>
));

View File

@ -49,4 +49,4 @@ View.propTypes = {
children: React.PropTypes.node children: React.PropTypes.node
}; };
module.exports = View; module.exports = View;

View File

@ -4378,7 +4378,7 @@ mobx@^2.3.4:
version "2.7.0" version "2.7.0"
resolved "https://registry.yarnpkg.com/mobx/-/mobx-2.7.0.tgz#cf3d82d18c0ca7f458d8f2a240817b3dc7e54a01" resolved "https://registry.yarnpkg.com/mobx/-/mobx-2.7.0.tgz#cf3d82d18c0ca7f458d8f2a240817b3dc7e54a01"
moment@^2.10.6: moment@^2.10.6, moment@^2.17.1:
version "2.17.1" version "2.17.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82" resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82"