diff --git a/circle.yml b/circle.yml
index d902f72f..0eceb64d 100644
--- a/circle.yml
+++ b/circle.yml
@@ -4,7 +4,6 @@ machine:
- git config --global user.email "circleci@joyent.zone"
- git config --global user.name "circlebot"
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
- - curl -o- -L https://yarnpkg.com/install.sh | bash
services:
- docker
diff --git a/frontend/Makefile b/frontend/Makefile
index 561cc1cc..97eab1ff 100644
--- a/frontend/Makefile
+++ b/frontend/Makefile
@@ -7,11 +7,11 @@ UI := $(shell pwd)/../ui
.PHONY: install-production
install-production: compile
- yarn install --production --prefer-offline
+ yarn install --production --no-lockfile
.PHONY: install
install:
- NODE_ENV=development yarn install --prefer-offline
+ NODE_ENV=development yarn install --no-lockfile
.PHONY: clean
clean:
diff --git a/frontend/src/components/header/index.js b/frontend/src/components/header/index.js
index ebdc33d4..e34123b3 100644
--- a/frontend/src/components/header/index.js
+++ b/frontend/src/components/header/index.js
@@ -23,10 +23,15 @@ const {
const {
remcalc
} = fns;
+
const {
pseudoEl
} = composers;
+const borderSide = props => props.toggled
+ ? 'bottom'
+ : 'top';
+
const StyledHeader = styled.header`
background-color: #ffffff;
padding-top: ${remcalc(21)};
@@ -34,7 +39,7 @@ const StyledHeader = styled.header`
`;
const StyledLogo = styled.img`
- padding-top: ${remcalc(10)}
+ padding-top: ${remcalc(10)};
`;
const StyledProfileWrapper = styled.div`
@@ -43,26 +48,26 @@ const StyledProfileWrapper = styled.div`
const StyledAvatarWrapper = styled.div`
&:after {
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- border-${props => props.toggled ? 'bottom' : 'top'}: 5px solid black;
+ border-left: ${remcalc(5)} solid transparent;
+ border-right: ${remcalc(5)} solid transparent;
+ border-${borderSide}: ${remcalc(5)} solid black;
${pseudoEl({
top: '50%',
- right: '10px'
+ right: remcalc(10)
})}
}
`;
const StyledTooltipWrapper = styled.div`
position: absolute;
- left: -40px;
- bottom: -180px;
+ left: ${remcalc(-40)};
+ bottom: ${remcalc(-180)};
`;
const StyledName = styled.span`
position: relative;
- top: -12px;
+ top: ${remcalc(-12)};
`;
const EmptyButton = styled.button`
@@ -71,7 +76,7 @@ const EmptyButton = styled.button`
`;
const StyledAvatar = styled(Avatar)`
- marginLeft: 12px;
+ marginLeft: ${remcalc(12)};
`;
const arrowPosition = {
diff --git a/frontend/src/components/instance-item/index.js b/frontend/src/components/instance-item/index.js
new file mode 100644
index 00000000..c874ee1f
--- /dev/null
+++ b/frontend/src/components/instance-item/index.js
@@ -0,0 +1,37 @@
+const React = require('react');
+
+const MetricsOutlet = require('@components/metrics-outlet');
+const PropTypes = require('@root/prop-types');
+const List = require('@ui/components/list');
+
+const {
+ ListItem,
+ ListItemView,
+ ListItemMeta,
+ ListItemTitle,
+ ListItemOptions
+} = List;
+
+const InstanceItem = ({
+ instance = {},
+ toggleCollapsed = () => null
+}) => (
+
+
+
+ {instance.name}
+
+
+
+
+ …
+
+
+);
+
+InstanceItem.propTypes = {
+ instance: PropTypes.instance,
+ toggleCollapsed: React.PropTypes.func
+};
+
+module.exports = InstanceItem;
\ No newline at end of file
diff --git a/frontend/src/components/instance-list/index.js b/frontend/src/components/instance-list/index.js
new file mode 100644
index 00000000..5662c827
--- /dev/null
+++ b/frontend/src/components/instance-list/index.js
@@ -0,0 +1,32 @@
+const React = require('react');
+
+const InstanceItem = require('@components/instance-item');
+const PropTypes = require('@root/prop-types');
+
+const InstanceList = ({
+ instances = [],
+ toggleCollapsed = () => null
+}) => {
+ const onClick = (uuid) => () => toggleCollapsed(uuid);
+
+ const instanceList = instances.map((instance) => (
+
+ ));
+
+ return (
+
+ {instanceList}
+
+ );
+};
+
+InstanceList.propTypes = {
+ instances: React.PropTypes.arrayOf(PropTypes.instance),
+ toggleCollapsed: React.PropTypes.func
+};
+
+module.exports = InstanceList;
diff --git a/frontend/src/components/metrics-row/index.js b/frontend/src/components/metrics-outlet/index.js
similarity index 70%
rename from frontend/src/components/metrics-row/index.js
rename to frontend/src/components/metrics-outlet/index.js
index ff842e52..807f7a92 100644
--- a/frontend/src/components/metrics-row/index.js
+++ b/frontend/src/components/metrics-outlet/index.js
@@ -2,6 +2,7 @@ const React = require('react');
const Styled = require('styled-components');
const Column = require('@ui/components/column');
+const List = require('@ui/components/list');
const MiniMetric = require('@ui/components/mini-metric');
const PropTypes = require('@root/prop-types');
const Row = require('@ui/components/row');
@@ -18,6 +19,15 @@ const {
MiniMetricView
} = MiniMetric;
+const {
+ ListItemOutlet
+} = List;
+
+const StyledOutlet = styled(ListItemOutlet)`
+ padding-left: 0;
+ padding-right: 0;
+`;
+
const StyledRow = styled(Row)`
margin: 0;
@@ -27,9 +37,11 @@ const StyledRow = styled(Row)`
}
`;
-const MetricsRow = ({
- datasets = []
-}) => {
+const MetricsOutlet = (props) => {
+ const {
+ datasets = []
+ } = props;
+
const _datasets = datasets.map((metric, i) => (
@@ -43,14 +55,16 @@ const MetricsRow = ({
));
return (
-
- {_datasets}
-
+
+
+ {_datasets}
+
+
);
};
-MetricsRow.propTypes = {
+MetricsOutlet.propTypes = {
datasets: React.PropTypes.arrayOf(PropTypes.dataset)
};
-module.exports = MetricsRow;
+module.exports = MetricsOutlet;
diff --git a/frontend/src/components/service-item/index.js b/frontend/src/components/service-item/index.js
index 3fe83741..6adb37c4 100644
--- a/frontend/src/components/service-item/index.js
+++ b/frontend/src/components/service-item/index.js
@@ -4,7 +4,7 @@ const ReactRouter = require('react-router');
const Anchor = require('@ui/components/anchor');
const List = require('@ui/components/list');
-const MetricsRow = require('@components/metrics-row');
+const MetricsOutlet = require('@components/metrics-outlet');
const PropTypes = require('@root/prop-types');
const {
@@ -19,7 +19,6 @@ const {
ListItemSubTitle,
ListItemDescription,
ListItemGroupView,
- ListItemOutlet,
ListItemOptions,
ListItemHeader
} = List;
@@ -86,9 +85,7 @@ const ServiceItem = ({
{isChild && subtitle}
{description}
-
-
-
+
);
diff --git a/frontend/src/containers/project/instances.js b/frontend/src/containers/project/instances.js
index dbb58acf..2909f1b5 100644
--- a/frontend/src/containers/project/instances.js
+++ b/frontend/src/containers/project/instances.js
@@ -1,9 +1,63 @@
const React = require('react');
+const ReactRedux = require('react-redux');
+const actions = require('@state/actions');
+const EmptyInstances = require('@components/empty/instances');
+const PropTypes = require('@root/prop-types');
const Section = require('./section');
+const InstanceList = require('@components/instance-list');
+const selectors = require('@state/selectors');
+
+const {
+ toggleInstanceCollapsed
+} = actions;
+
+const {
+ connect
+} = ReactRedux;
+
+const {
+ instancesByProjectIdSelector
+} = selectors;
+
+const Instances = (props) => {
+ const {
+ instances = [],
+ toggleCollapsed = () => null
+ } = props;
+
+ const empty = instances.length ? null : (
+
+ );
+
+ return (
+
+ );
+};
+
+Instances.propTypes = {
+ instances: React.PropTypes.arrayOf(PropTypes.instance),
+ toggleCollapsed: React.PropTypes.func
+};
+
+const mapStateToProps = (state, {
+ params = {}
+}) => ({
+ instances: instancesByProjectIdSelector(params.projectId)(state)
+});
+
+const mapDispatchToProps = (dispatch) => ({
+ toggleCollapsed: (uuid) => dispatch(toggleInstanceCollapsed(uuid))
+});
+
+module.exports = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(Instances);
-module.exports = (props) => (
-
-);
diff --git a/frontend/src/containers/service/instances.js b/frontend/src/containers/service/instances.js
index 6572c529..019d38d2 100644
--- a/frontend/src/containers/service/instances.js
+++ b/frontend/src/containers/service/instances.js
@@ -4,8 +4,7 @@ const ReactRedux = require('react-redux');
const actions = require('@state/actions');
const EmptyInstances = require('@components/empty/instances');
const PropTypes = require('@root/prop-types');
-const List = require('@ui/components/list');
-const DatasetsRow = require('@components/metrics-row');
+const InstanceList = require('@components/instance-list');
const selectors = require('@state/selectors');
const {
@@ -20,45 +19,23 @@ const {
instancesByServiceIdSelector
} = selectors;
-const {
- ListItem,
- ListItemView,
- ListItemMeta,
- ListItemTitle,
- ListItemOptions,
- ListItemOutlet
-} = List;
-
-const Instances = ({
- instances = [],
- toggleCollapsed = () => null
-}) => {
- const onClick = (uuid) => () => toggleCollapsed(uuid);
+const Instances = (props) => {
+ const {
+ instances = [],
+ toggleCollapsed = () => null
+ } = props;
const empty = instances.length ? null : (
);
- const instanceList = instances.map((instance) => (
-
-
-
- {instance.name}
-
-
-
-
-
-
- …
-
-
- ));
-
return (
{empty}
- {instanceList}
+
);
};
diff --git a/frontend/src/prop-types.js b/frontend/src/prop-types.js
index c3422655..9908426d 100644
--- a/frontend/src/prop-types.js
+++ b/frontend/src/prop-types.js
@@ -44,11 +44,11 @@ const Dataset = React.PropTypes.shape({
type: React.PropTypes.string,
data: React.PropTypes.arrayOf(
React.PropTypes.shape({
- firstQuartile: React.PropTypes.string,
- thirdQuartile: React.PropTypes.string,
- median: React.PropTypes.string,
- max: React.PropTypes.string,
- min: React.PropTypes.string
+ firstQuartile: React.PropTypes.number,
+ thirdQuartile: React.PropTypes.number,
+ median: React.PropTypes.number,
+ max: React.PropTypes.number,
+ min: React.PropTypes.number
})
)
});
diff --git a/frontend/src/state/selectors.js b/frontend/src/state/selectors.js
index 27aa0201..7c154b3d 100644
--- a/frontend/src/state/selectors.js
+++ b/frontend/src/state/selectors.js
@@ -93,6 +93,16 @@ const metricsByServiceId = (serviceId) => createSelector(
metricTypes.filter((i) => i.service === service.uuid)
);
+const instancesByProjectId = (projectId) => createSelector(
+ [instances, projectById(projectId), collapsedInstances, metricDatasets],
+ (instances, project, collapsed, metrics) =>
+ instances.filter((i) => i.project === project.uuid)
+ .map((instance) => ({
+ ...instance,
+ metrics: datasets(metrics, instance.metrics),
+ collapsed: isCollapsed(collapsed, instance.uuid)
+ }))
+);
module.exports = {
accountSelector: account,
@@ -108,5 +118,6 @@ module.exports = {
projectByIdSelector: projectById,
servicesByProjectIdSelector: servicesByProjectId,
instancesByServiceIdSelector: instancesByServiceId,
- metricsByServiceIdSelector: metricsByServiceId
+ metricsByServiceIdSelector: metricsByServiceId,
+ instancesByProjectIdSelector: instancesByProjectId
};
diff --git a/ui/.storybook/config.js b/ui/.storybook/config.js
index 61c63a83..bb888c3a 100644
--- a/ui/.storybook/config.js
+++ b/ui/.storybook/config.js
@@ -6,11 +6,11 @@ function loadStories() {
let stories = req.keys();
stories = stories.sort();
- stories.forEach( story => req(story));
+ stories.forEach(story => req(story));
// Fallback to stories/index.js file for anything that
// hasn't been moved
require('../stories');
}
-configure(loadStories, module);
\ No newline at end of file
+configure(loadStories, module);
diff --git a/ui/package.json b/ui/package.json
index 457f437a..99eaf728 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -14,8 +14,9 @@
"dependencies": {
"build-array": "^1.0.0",
"chart.js": "^2.4.0",
- "chartjs-chart-box-plot": "^1.0.0-9",
+ "chartjs-chart-box-plot": "prerelease",
"color": "^1.0.3",
+ "d3": "^4.4.1",
"lodash.find": "^4.6.0",
"lodash.first": "^3.0.0",
"lodash.flatten": "^4.4.0",
diff --git a/ui/src/components/add-metric/tile.js b/ui/src/components/add-metric/tile.js
index 66e8e16d..50f60f39 100644
--- a/ui/src/components/add-metric/tile.js
+++ b/ui/src/components/add-metric/tile.js
@@ -28,7 +28,7 @@ const StyledTile = styled.div`
width: ${remcalc(300)};
height: ${remcalc(247)};
box-shadow: ${boxes.bottomShaddow};
- border: 1px solid ${colors.borderSecondary};
+ border: ${remcalc(1)} solid ${colors.borderSecondary};
background-color: ${colors.brandSecondary};
${breakpoints.small`
diff --git a/ui/src/components/base/index.js b/ui/src/components/base/index.js
index efcc93e9..f0fd7f78 100644
--- a/ui/src/components/base/index.js
+++ b/ui/src/components/base/index.js
@@ -15,10 +15,10 @@ const {
} = Styled;
const {
- generateFonts
+ generateFonts,
+ remcalc
} = fncs;
-
// The name that will be used in the 'font-family' property
const fontFamilies = [
'LibreFranklin'
@@ -156,7 +156,7 @@ module.exports = styled.div`
}
& figure {
- margin: 1em 40px;
+ margin: 1em ${remcalc(40)};
}
& hr {
@@ -208,12 +208,12 @@ module.exports = styled.div`
& [type="button"]:-moz-focusring,
& [type="reset"]:-moz-focusring,
& [type="submit"]:-moz-focusring {
- outline: 1px dotted ButtonText;
+ outline: ${remcalc(1)} dotted ButtonText;
}
& fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
+ border: ${remcalc(1)} solid #c0c0c0;
+ margin: 0 ${remcalc(2)};
padding: 0.35em 0.625em 0.75em;
}
@@ -245,7 +245,7 @@ module.exports = styled.div`
& [type="search"] {
-webkit-appearance: textfield;
- outline-offset: -2px;
+ outline-offset: ${remcalc(-2)};
}
& [type="search"]::-webkit-search-cancel-button,
@@ -302,7 +302,7 @@ module.exports = styled.div`
& abbr[title],
& abbr[data-original-title] {
cursor: help;
- border-bottom: 1px dotted ${typography.abbrBorderColor};
+ border-bottom: ${remcalc(1)} dotted ${typography.abbrBorderColor};
}
& address {
@@ -352,8 +352,8 @@ module.exports = styled.div`
}
&:focus {
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
+ outline: ${remcalc(5)} auto -webkit-focus-ring-color;
+ outline-offset: ${remcalc(-2)};
}
}
@@ -444,8 +444,8 @@ module.exports = styled.div`
}
& button:focus {
- outline: 1px dotted;
- outline: 5px auto -webkit-focus-ring-color;
+ outline: ${remcalc(1)} dotted;
+ outline: ${remcalc(5)} auto -webkit-focus-ring-color;
}
& input,
diff --git a/ui/src/components/button/index.js b/ui/src/components/button/index.js
index cf45c79d..7fa255d2 100644
--- a/ui/src/components/button/index.js
+++ b/ui/src/components/button/index.js
@@ -56,7 +56,7 @@ const color = match({
const borderRadius = match({
rect: 0
-}, remcalc(boxes.borderRadius));
+}, boxes.borderRadius);
// based on bootstrap 4
const style = css`
@@ -96,7 +96,7 @@ const style = css`
background-image: none;
background-color: ${background};
border-radius: ${borderRadius};
- border: solid 1px ${border};
+ border: solid ${remcalc(1)} ${border};
box-shadow: ${boxes.bottomShaddow};
@@ -104,12 +104,12 @@ const style = css`
outline: 0;
text-decoration: none;
background-color: ${background};
- border: solid 1px ${border};
+ border: solid ${remcalc(1)} ${border};
}
&:hover {
background-color: ${backgroundHover};
- border: solid 1px ${borderHover};
+ border: solid ${remcalc(1)} ${borderHover};
}
&:active,
@@ -119,7 +119,7 @@ const style = css`
outline: 0;
background-color: ${backgroundActive};
- border: solid 1px ${borderActive};
+ border: solid ${remcalc(1)} ${borderActive};
}
&[disabled] {
diff --git a/ui/src/components/checkbox/index.js b/ui/src/components/checkbox/index.js
index 311c4960..15b0ce48 100644
--- a/ui/src/components/checkbox/index.js
+++ b/ui/src/components/checkbox/index.js
@@ -1,11 +1,16 @@
-const React = require('react');
const constants = require('../../shared/constants');
+const fns = require('../../shared/functions');
+const React = require('react');
const Styled = require('styled-components');
const {
boxes
} = constants;
+const {
+ remcalc
+} = fns;
+
const {
default: styled,
} = Styled;
@@ -26,8 +31,8 @@ const StyledInput = styled.input`
const StyledLabel = styled.label`
color: rgb(100, 100, 100);
position: absolute;
- width: 24px;
- height: 24px;
+ width: ${remcalc(24)};
+ height: ${remcalc(24)};
top: 0;
border-radius: ${boxes.borderRadius};
background-color: rgb(255, 255, 255);
@@ -38,12 +43,12 @@ const StyledLabel = styled.label`
opacity: 0;
content: '';
position: absolute;
- width: 9px;
- height: 4px;
+ width: ${remcalc(9)};
+ height: ${remcalc(4)};
background: transparent;
- top: 7px;
- left: 7px;
- border: 3px solid #333;
+ top: ${remcalc(7)};
+ left: ${remcalc(7)};
+ border: ${remcalc(3)} solid #333;
border-top: none;
border-right: none;
transform: rotate(-45deg);
@@ -57,8 +62,8 @@ const StyledLabel = styled.label`
`;
const StyledDiv = styled.div`
- width: 24px;
- height: 24px;
+ width: ${remcalc(24)};
+ height: ${remcalc(24)};
position: relative;
`;
diff --git a/ui/src/components/close/index.js b/ui/src/components/close/index.js
index bc955fe9..07658740 100644
--- a/ui/src/components/close/index.js
+++ b/ui/src/components/close/index.js
@@ -17,14 +17,18 @@ const StyledButton = styled.button`
position: absolute;
top: ${remcalc(16)};
right: ${remcalc(16)};
+
+ ${props => props.customStyles ? props.customStyles : null}
`;
const Close = ({
style,
- onClick
+ onClick,
+ customStyles = ''
}) => {
return (
@@ -37,6 +41,7 @@ const Close = ({
};
Close.propTypes = {
+ customStyles: React.PropTypes.string,
onClick: React.PropTypes.func,
style: React.PropTypes.object
};
diff --git a/ui/src/components/h1/index.js b/ui/src/components/h1/index.js
index 1d0a3319..bd216017 100644
--- a/ui/src/components/h1/index.js
+++ b/ui/src/components/h1/index.js
@@ -15,5 +15,5 @@ module.exports = styled.h1`
font-style: normal;
font-stretch: normal;
color: #364acd;
- border-bottom: 1px solid #d8d8d8;
+ border-bottom: ${remcalc(1)} solid #d8d8d8;
`;
diff --git a/ui/src/components/input/index.js b/ui/src/components/input/index.js
index 81b89968..d9120564 100644
--- a/ui/src/components/input/index.js
+++ b/ui/src/components/input/index.js
@@ -25,9 +25,9 @@ const {
const successBakcground = css`
background-color: ${colors.brandSecondary};
- background-image: url("./input-confirm.svg");
+ background-image: url('./input-confirm.svg');
background-repeat: no-repeat;
- background-position: 98% 20px;
+ background-position: 98% ${remcalc(20)};
`;
const defaultBackground = css`
@@ -40,17 +40,17 @@ const Label = styled.label`
const InputField = styled.input`
${baseBox()};
-
+
${props => props.success ? successBakcground : defaultBackground }
-
+
border-color: ${props => props.error ? colors.alert : 'auto'}
color: ${props => props.error ? colors.alert : colors.fonts.semibold}
display: block;
- font-size: 16px;
+ font-size: ${remcalc(16)};
padding: ${remcalc('15 18')};
visibility: visible;
width: 100%;
-
+
&:focus {
border-color: ${boxes.border.checked};
outline: none;
diff --git a/ui/src/components/list/header.js b/ui/src/components/list/header.js
index 3d022475..c59a6f39 100644
--- a/ui/src/components/list/header.js
+++ b/ui/src/components/list/header.js
@@ -20,7 +20,7 @@ const StyledItem = styled(Item)`
position: absolute;
background-color: ${colors.brandPrimary};
- border: solid 1px ${colors.borderPrimary};
+ border: solid ${remcalc(1)} ${colors.borderPrimary};
box-shadow: none;
width: calc(100% + ${remcalc(2)});
diff --git a/ui/src/components/list/item.js b/ui/src/components/list/item.js
index 28d3563c..d11b6d52 100644
--- a/ui/src/components/list/item.js
+++ b/ui/src/components/list/item.js
@@ -19,10 +19,10 @@ const {
} = Styled;
const paper = `
- 0 8px 0 -5px #fafafa,
- 0 8px 1px -4px ${colors.borderSecondary},
- 0 16px 0 -10px #fafafa,
- 0 16px 1px -9px ${colors.borderSecondary};
+ 0 ${remcalc(8)} 0 ${remcalc(-5)} #fafafa,
+ 0 ${remcalc(8)} ${remcalc(1)} ${remcalc(-4)} ${colors.borderSecondary},
+ 0 ${remcalc(16)} 0 ${remcalc(-10)} #fafafa,
+ 0 ${remcalc(16)} ${remcalc(1)} ${remcalc(-9)} ${colors.borderSecondary};
`;
const height = (props) => props.collapsed
@@ -52,7 +52,7 @@ const Item = styled(Row)`
height: ${height};
min-height: ${minHeight};
box-shadow: ${shadow};
- border: 1px solid ${colors.borderSecondary};
+ border: ${remcalc(1)} solid ${colors.borderSecondary};
background-color: ${colors.brandSecondary};
margin-bottom: ${marginBottom};
`;
diff --git a/ui/src/components/list/options.js b/ui/src/components/list/options.js
index 6f8f0f90..39807a72 100644
--- a/ui/src/components/list/options.js
+++ b/ui/src/components/list/options.js
@@ -27,7 +27,7 @@ const borderLeftColor = (props) => !props.fromHeader
const Nav = styled.nav`
flex: 0 0 ${remcalc(47)};
- border-left: 1px solid ${borderLeftColor};
+ border-left: ${remcalc(1)} solid ${borderLeftColor};
`;
const StyledButton = styled(Button)`
diff --git a/ui/src/components/list/subtitle.js b/ui/src/components/list/subtitle.js
index dda0c90c..99cb05b2 100644
--- a/ui/src/components/list/subtitle.js
+++ b/ui/src/components/list/subtitle.js
@@ -35,7 +35,7 @@ const Span = styled.span`
font-weight: normal;
font-style: normal;
font-stretch: normal;
- font-size: 14px;
+ font-size: ${remcalc(14)};
color: ${color};
justify-content: flex-end;
diff --git a/ui/src/components/modal/index.js b/ui/src/components/modal/index.js
index 9649e705..66eeb0f6 100644
--- a/ui/src/components/modal/index.js
+++ b/ui/src/components/modal/index.js
@@ -1,11 +1,19 @@
+const fns = require('../../shared/functions');
+
const constants = require('../../shared/constants');
const React = require('react');
const Styled = require('styled-components');
+const Close = require('../close');
+
const {
colors
} = constants;
+const {
+ remcalc
+} = fns;
+
const {
default: styled
} = Styled;
@@ -15,31 +23,17 @@ const StyledModal = styled.div`
display: block;
left: 50%;
margin: 0 auto;
- padding: 20px;
+ padding: ${remcalc(20)};
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
z-index: 1;
-`;
-
-const StyledClose = styled.button`
- background-color: #FFFFFF;
- border: solid 1px #D8D8D8;
- border-radius: 4px;
- box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.05);
- color: black;
- cursor: #000000;
- font-size: 20px;
- padding: 0 10px;
- position: absolute;
- right: -20px;
- text-align: center;
- text-decoration: none;
- top: -15px;
+ max-width: 80%;
+ min-width: 50%;
`;
const StyledOverlay = styled.div`
- background: rgba(0, 0, 0, 0.4);
+ background: rgba(74, 73, 74, 0.46);
height: 100%;
left: 0;
position: absolute;
@@ -52,6 +46,7 @@ const Modal = ({
active = true,
children,
className,
+ customCloseStyle,
handleDismiss,
name,
style
@@ -68,11 +63,10 @@ const Modal = ({
tabIndex={-2}
/>
- X
+ />
{children}
@@ -83,6 +77,7 @@ Modal.propTypes = {
active: React.PropTypes.bool,
children: React.PropTypes.node,
className: React.PropTypes.string,
+ customCloseStyle: React.PropTypes.string,
handleDismiss: React.PropTypes.func,
name: React.PropTypes.string,
style: React.PropTypes.object
diff --git a/ui/src/components/modal/story.js b/ui/src/components/modal/story.js
index 74a142fc..c1f586c9 100644
--- a/ui/src/components/modal/story.js
+++ b/ui/src/components/modal/story.js
@@ -1,5 +1,15 @@
+const constants = require('../../shared/constants');
+const fns = require('../../shared/functions');
const React = require('react');
+const {
+ colors
+} = constants;
+
+const {
+ remcalc
+} = fns;
+
const {
storiesOf
} = require('@kadira/storybook');
@@ -7,6 +17,11 @@ const {
const Base= require('../base');
const Modal = require('./');
+const _customCloseStyle = `
+ border: solid ${colors.alert} ${remcalc(5)};
+ border-radius: 50%;
+`;
+
storiesOf('Modal', module)
.add('Default', () => (
@@ -14,4 +29,18 @@ storiesOf('Modal', module)
This is the Modal
+ ))
+ .add('Custom Styles on Close', () => (
+
+
+ This is the Modal
+
+
+ ))
+ .add('Dismiss Function', () => (
+
+
+ This has a handleDismiss (noop) function
+
+
));
\ No newline at end of file
diff --git a/ui/src/components/pagination/index.js b/ui/src/components/pagination/index.js
index 352efc37..ca69b1fb 100644
--- a/ui/src/components/pagination/index.js
+++ b/ui/src/components/pagination/index.js
@@ -13,7 +13,8 @@ const {
} = constants;
const {
- rndId
+ rndId,
+ remcalc
} = fns;
const {
@@ -36,12 +37,12 @@ const StyledLi = styled.li`
cursor: pointer;
display: flex;
float: left;
- height: 50px;
+ height: ${remcalc(50)};
justify-content: center;
- margin-right: 10px;
- min-width: 50px;
- padding-left: 15px;
- padding-right: 15px;
+ margin-right: ${remcalc(10)};
+ min-width: ${remcalc(50)};
+ padding-left: ${remcalc(15)};
+ padding-right: ${remcalc(15)};
position: relative;
${baseBox()}
diff --git a/ui/src/components/radio-group/item.js b/ui/src/components/radio-group/item.js
index 565048d5..98177329 100644
--- a/ui/src/components/radio-group/item.js
+++ b/ui/src/components/radio-group/item.js
@@ -35,7 +35,7 @@ const RadioItem = styled.div`
&[aria-checked="true"] {
border: ${boxes.border.checked};
- box-shadow: ${remcalc(boxes.borderRadius)};
+ box-shadow: ${boxes.borderRadius};
}
&.disabled {
diff --git a/ui/src/components/radio/index.js b/ui/src/components/radio/index.js
index 62154afe..8c57492c 100644
--- a/ui/src/components/radio/index.js
+++ b/ui/src/components/radio/index.js
@@ -46,12 +46,12 @@ const StyledSpan = styled.span`
&::before {
content: '';
position: absolute;
- width: 10px;
- height: 10px;
- box-shadow: 0 0 0 1px #646464;
- border: 8px solid ${colors.brandInactive};
- top: 5px;
- left: 5px;
+ width: ${remcalc(10)};
+ height: ${remcalc(10)};
+ box-shadow: 0 0 0 ${remcalc(1)} #646464;
+ border: ${remcalc(8)} solid ${colors.brandInactive};
+ top: ${remcalc(5)};
+ left: ${remcalc(5)};
border-radius: 100%;
}
diff --git a/ui/src/components/range-slider/index.js b/ui/src/components/range-slider/index.js
index 8a2a7104..0373bb59 100644
--- a/ui/src/components/range-slider/index.js
+++ b/ui/src/components/range-slider/index.js
@@ -38,7 +38,7 @@ const rangeThumb = css`
cursor: pointer;
height: ${remcalc(24)};
position: relative;
- top: -10px;
+ top: ${remcalc(-10)};
width: ${remcalc(36)};
${baseBox()}
@@ -46,7 +46,7 @@ const rangeThumb = css`
const rangeLower = css`
background: ${colors.brandPrimary};
- height: 6px;
+ height: ${remcalc(6)};
${baseBox({
radius: remcalc(50),
@@ -56,7 +56,7 @@ const rangeLower = css`
const rangeUpper = css`
background: #E6E6E6;
- height: 6px;
+ height: ${remcalc(6)};
${baseBox({
radius: remcalc(50)
diff --git a/ui/src/components/select/index.js b/ui/src/components/select/index.js
index 5f33b49a..f9d4dde5 100644
--- a/ui/src/components/select/index.js
+++ b/ui/src/components/select/index.js
@@ -26,27 +26,27 @@ const SelectWrapper = styled.div`
display: inline-block;
&:after {
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- border-bottom: 5px solid black;
+ border-left: ${remcalc(5)} solid transparent;
+ border-right: ${remcalc(5)} solid transparent;
+ border-bottom: ${remcalc(5)} solid black;
${pseudoEl({
- top: '25px',
- right: '20px'
+ top: remcalc(25),
+ right: remcalc(20)
})}
}
`;
const StyledSelect = styled.select`
- font-size:16px;
+ font-size: ${remcalc(16)};
min-width: ${remcalc(288)};
min-height: ${remcalc(54)};
- border-radius: 4px;
+ border-radius: ${remcalc(4)};
padding-left: ${remcalc(20)};
background-color: #FFFFFF;
- box-shadow: inset 0 3px 0 0 rgba(0, 0, 0, 0.05);
- border: solid 1px #D8D8D8;
+ box-shadow: inset 0 ${remcalc(3)} 0 0 rgba(0, 0, 0, 0.05);
+ border: solid ${remcalc(1)} #D8D8D8;
-webkit-appearance: none;
&:before {
diff --git a/ui/src/components/tabs/tab/index.js b/ui/src/components/tabs/tab/index.js
index ab417de1..2aa1e567 100644
--- a/ui/src/components/tabs/tab/index.js
+++ b/ui/src/components/tabs/tab/index.js
@@ -34,9 +34,9 @@ const StyledTab = styled.div`
const StyledRadio = styled.input`
clip: rect(0 0 0 0);
- height: 1px;
+ height: ${remcalc(1)};
opacity: 0;
- width: 1px;
+ width: ${remcalc(1)};
${moveZ({
position: 'fixed',
@@ -61,7 +61,7 @@ const StyledRadio = styled.input`
const StyledLabel = styled.label`
background: transparent;
- border: 1px solid #D8D8D8;
+ border: ${remcalc(1)} solid #D8D8D8;
display: inline-block;
font-size: ${remcalc(20)};
padding: ${remcalc('12 25')};
@@ -81,7 +81,7 @@ const StyledContent = styled.div`
background: ${colors.brandInactive};
border: ${boxes.border.unchecked};
box-sizing: border-box;
- box-shadow: 0 -1px 26px 0 rgba(0, 0, 0, 0.2);
+ box-shadow: 0 ${remcalc(-1)} ${remcalc(26)} 0 rgba(0, 0, 0, 0.2);
display: block;
float: left;
font-size: ${remcalc(16)};
diff --git a/ui/src/components/textarea/index.js b/ui/src/components/textarea/index.js
index b7b0f0ad..f11d8aaa 100644
--- a/ui/src/components/textarea/index.js
+++ b/ui/src/components/textarea/index.js
@@ -30,14 +30,14 @@ const InputField = styled.textarea`
background: ${colors.brandSecondary};
color: ${props => props.error ? colors.alert : colors.fonts.semibold}
display: block;
- font-size: 16px;
+ font-size: ${remcalc(16)};
padding: ${remcalc('15 18')};
visibility: visible;
width: 100%;
min-height: ${remcalc(96)};
${baseBox()};
border-color: ${props => props.error ? colors.alert : ''};
-
+
&:focus {
border-color: ${boxes.border.checked};
outline: none;
diff --git a/ui/src/components/toggle/index.js b/ui/src/components/toggle/index.js
index d50bc992..b32b9de9 100644
--- a/ui/src/components/toggle/index.js
+++ b/ui/src/components/toggle/index.js
@@ -30,7 +30,7 @@ const StyledText = styled.span`
const StyledDiv = styled.div`
display: inline-block;
background-color: ${colors.brandInactive};
-
+
${baseBox()}
`;
@@ -46,17 +46,18 @@ const StyledInput0 = styled.input`
display: none;
& + span {
- background: linear-gradient(to right,
- transparent 50%,
+ background: linear-gradient(to right,
+ transparent 50%,
${colors.brandSecondary} 50%);
background-position: left bottom;
- box-shadow: inset -7px 0 9px -7px rgba(0,0,0,0.4);
-
+ box-shadow: inset
+ ${remcalc(-7)} 0 ${remcalc(9)} ${remcalc(-7)}
+ rgba(0,0,0,0.4);
+
${inputStyled}
}
-
+
&:checked {
-
& + span {
background-position: right bottom;
}
@@ -66,17 +67,16 @@ const StyledInput0 = styled.input`
const StyledInput1 = styled.input`
display: none;
- & + span {
- background: linear-gradient(to right,
- ${colors.brandSecondary} 50%,
+ & + span {
+ background: linear-gradient(to right,
+ ${colors.brandSecondary} 50%,
transparent 50%);
background-position: right bottom;
-
+
${inputStyled}
}
-
+
&:checked {
-
& + span {
background-position: left bottom;
}
diff --git a/ui/src/components/tooltip/index.js b/ui/src/components/tooltip/index.js
index 7d0c40bd..cb4ab090 100644
--- a/ui/src/components/tooltip/index.js
+++ b/ui/src/components/tooltip/index.js
@@ -56,14 +56,14 @@ const StyledList = styled.ul`
&:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #fff;
- border-width: 10px;
- margin-left: -10px;
+ border-width: ${remcalc(10)};
+ margin-left: ${remcalc(-10)};
}
&:before {
border-color: rgba(216, 216, 216, 0);
border-bottom-color: #d8d8d8;
- border-width: 12px;
- margin-left: -12px;
+ border-width: ${remcalc(12)};
+ margin-left: ${remcalc(-12)};
}
`;
module.exports = ({
diff --git a/ui/src/components/topology/index.js b/ui/src/components/topology/index.js
new file mode 100644
index 00000000..5a8114e8
--- /dev/null
+++ b/ui/src/components/topology/index.js
@@ -0,0 +1,425 @@
+const constants = require('../../shared/constants');
+const d3 = require('d3');
+const fns = require('../../shared/functions');
+const React = require('react');
+const Styled = require('styled-components');
+
+const {
+ colors
+} = constants;
+
+const {
+ remcalc
+} = fns;
+
+const {
+ default: styled
+} = Styled;
+
+/* eslint-disable */
+function rightRoundedRect(x, y, width, height, radius) {
+ return 'M' + x + ',' + y // Move to top left (absolute)
+ + 'h ' + (width - 2 * radius) // Horizontal line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + radius // Relative arc
+ + 'v ' + (height - 2 * radius) // Vertical line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + radius // Relative arch
+ + 'h ' + (2 * radius - width) // Horizontal lint to (relative)
+ + 'z '; // path back to start
+}
+/* eslint-enable */
+
+/* eslint-disable */
+function leftRoundedRect(x, y, width, height, radius) {
+ return 'M' + (x + width) + ',' + y // Move to (absolute) start at top-right
+ + 'v ' + height // Vertical line to (relative)
+ + 'h ' + (2 * radius - width) // Horizontal line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + -radius // Relative arc
+ + 'v ' + -(height - 2 * radius) // Vertical line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + -radius // Relative arch
+ + 'z '; // path back to start
+}
+/* eslint-enable */
+
+function topRoundedRect(x, y, width, height, radius) {
+ return 'M' + x + ',' + -(y - height) // Move to (absolute) start at bottom-left
+ + 'v ' + -(height - radius) // Vertical line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + -radius // Relative arc
+ + 'h ' + -(2 * radius - width) // Horizontal line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + radius // Relative arc
+ + 'v ' + (height - radius) // Vertical line to (relative)
+ + 'h ' + (2 * radius - width) // Horizontal line to (relative)
+ + 'z '; // path back to start
+}
+
+function bottomRoundedRect(x, y, width, height, radius) {
+ return 'M' + x + ',' + -(y - (height - 2 * radius)) // Move to (absolute) start at bottom-right
+ + 'v ' + -(height - 2 * radius) // Vertical line to (relative)
+ + 'h ' + (width) // Horizontal line to (relative)
+ + 'v ' + (height - 2 * radius) // Vertical line to (relative)
+ + 'a ' + -radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + radius // Relative arc
+ + 'h ' + (2 * radius - width) // Horizontal line to (relative)
+ + 'a ' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + -radius // Relative arc
+ + 'z '; // path back to start
+}
+
+/* eslint-disable */
+function rect(x, y, width, height) {
+ return 'M' + x + ',' + -(y - height) // Move to (absolute) start at bottom-right
+ + 'v ' + -(height) // Vertical line to (relative)
+ + 'h ' + width // Horizontal line to (relative)
+ + 'v ' + height // Vertical line to (relative)
+ + 'h ' + -(width) // Horizontal line to (relative)
+ + 'z '; // path back to start
+}
+/* eslint-enable */
+
+const StyledSVGContainer = styled.svg`
+ & {
+ .links line {
+ stroke: #343434;
+ stroke-opacity: 1;
+ }
+
+ .health, .health_warn {
+ font-family: "Libre Franklin";
+ font-size: ${remcalc(12)};
+ font-weight: bold;
+ font-style: normal;
+ font-stretch: normal;
+ text-align: center;
+ }
+
+ .health_warn {
+ font-size: ${remcalc(15)};
+ }
+
+ .stat {
+ font-family: "Libre Franklin";
+ font-size: ${remcalc(12)};
+ font-weight: normal;
+ font-style: normal;
+ font-stretch: normal;
+ line-height: 1.5;
+ }
+
+ .node_statistics {
+ font-family: "Libre Franklin";
+ font-size: ${remcalc(12)};
+ font-weight: normal;
+ font-style: normal;
+ font-stretch: normal;
+ line-height: 1.5;
+ }
+
+ .node_statistics p {
+ margin: 0 0 0 0;
+ color: rgba(255, 255, 255, 0.8);
+ }
+
+ .primary, .secondary {
+ font-family: "Libre Franklin";
+ font-size: ${remcalc(12)};
+ font-weight: normal;
+ font-style: normal;
+ font-stretch: normal;
+ line-height: 1.5;
+ }
+
+ .info_text {
+ font-family: "Libre Franklin";
+ font-size: ${remcalc(16)};
+ font-weight: 600;
+ font-style: normal;
+ font-stretch: normal;
+ line-height: 1.5;
+ }
+ }
+`;
+
+class TopologyGraph extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.svg = null;
+
+ const {
+ width,
+ height,
+ } = props;
+
+ this.simulation = d3.forceSimulation()
+ .force('charge', d3.forceManyBody()
+ .strength(() => -50)
+ .distanceMin(() => 30))
+ .force('link', d3.forceLink().distance(() => 200).id((d) => d.id))
+ // TODO manually handle looking for collisions in the tick, we then get the BBox
+ // and keep moving things for a while to try to get a fit.
+ .force('collide',
+ d3.forceCollide().radius((d) => 220 + 0.5).iterations(15))
+ .force('center', d3.forceCenter(width * 1/3, height * 1/3));
+ }
+
+ componentDidMount() {
+ const component = this;
+
+ const {
+ simulation,
+ } = this;
+
+ const svg = d3.select(this._refs.svg);
+ const {
+ width,
+ height,
+ graph = {
+ nodes: [],
+ links: []
+ },
+ } = this.props;
+
+ // Drawing the links between nodes
+ const link = svg.append('g')
+ .attr('class', 'links')
+ .selectAll('line')
+ .data(graph.links)
+ .enter().append('line')
+ .attr('stroke-width', remcalc(12));
+
+ // And svg group, to contain all of the attributes in @antonas' first prototype
+ svg.selectAll('.node')
+ .data(graph.nodes)
+ .enter()
+ .append('g')
+ .attr('class', 'node_group');
+
+ svg.selectAll('.node_group').each(function(d) {
+ // Create different type of node for services with Primaries + Secondaries
+ // We could extend this further to allow us to have as many nested services
+ // as wanted.
+ // TODO handle this per prop
+ // if (d.id === 'Percona') {
+ // createExtendedNode(d3.select(this));
+ // } else {
+ component.createServiceNodes(d, d3.select(this));
+ // }
+ });
+
+ simulation
+ .nodes(graph.nodes)
+ .on('tick', ticked);
+
+ simulation.force('link')
+ .links(graph.links);
+
+ function contrain(dimension, r, z) {
+ return Math.max(0, Math.min(dimension - r, z));
+ }
+
+ function ticked() {
+ // TODO: Think of a common way of extracting the bounding boxes for each
+ // item and to grab the x{1,2} and y{1,2} values.
+ link
+ .attr('x1', function(d) {
+ let x;
+ svg.selectAll('.node_group').each(function(_, i) {
+ if (i !== d.source.index) return;
+ x = d3.select(this).node().getBBox().width;
+ });
+ return contrain(width, x, d.source.x) + 80;
+ })
+ .attr('y1', function(d) {
+ let y;
+ svg.selectAll('.node_group').each(function(_, i) {
+ if (i !== d.source.index) return;
+ y = d3.select(this).node().getBBox().height;
+ });
+ return contrain(height, y, d.source.y) + 24;
+ })
+ .attr('x2', function(d) {
+ let x;
+ svg.selectAll('.node_group').each(function(_, i) {
+ if (i !== d.target.index) return;
+ x = d3.select(this).node().getBBox().width;
+ });
+ return contrain(width, x, d.target.x) + 80;
+ })
+ .attr('y2', function(d) {
+ let y;
+ svg.selectAll('.node_group').each(function(_, i) {
+ if (i !== d.target.index) return;
+ y = d3.select(this).node().getBBox().height;
+ });
+ return contrain(height, y, d.target.y) + 24;
+ });
+
+ svg.selectAll('.node_group')
+ .attr('transform', function(d) {
+ const x = d3.select(this).node().getBBox().width;
+ const y = d3.select(this).node().getBBox().height;
+ return 'translate(' + contrain(width, x, d.x) + ','
+ + contrain(height, y, d.y) + ')';
+ });
+ }
+ }
+
+ createHealthCheckBadge(element, x, y) {
+ const paddingLeft = 30;
+ const health = element.append('g');
+
+ // TODO: replace these element with the designed SVG elements from
+ // @antonasdeduchovas' designs with full svg elements.
+
+ health.append('circle')
+ .attr('class', 'alert')
+ .attr('cx', function() {
+ return element
+ .node()
+ .getBBox()
+ .width + paddingLeft;
+ })
+ .attr('cy', '24')
+ .attr('stroke-width', 0)
+ .attr('fill', (d) =>
+ d.id === 'Memcached' ? 'rgb(217, 77, 68)' : 'rgb(0,175,102)')
+ .attr('r', remcalc(9));
+
+ // An icon or label that exists within the circle, inside the infobox
+ health.append('text')
+ .attr('class', 'health')
+ .attr('x', function() {
+ return element
+ .node()
+ .getBBox()
+ .width + 3;
+ })
+ .attr('y', '29')
+ .attr('text-anchor', 'middle')
+ .attr('fill', colors.brandPrimaryColor)
+ .text((d) => d.id === 'Memcached' ? '!' : '❤');
+ }
+
+ createServiceNodeBody(data, element, d) {
+ const stats = element.append('g');
+ stats.append('path')
+ .attr('class', 'node')
+ .attr('d', d)
+ .attr('stroke', '#343434')
+ .attr('stroke-width', remcalc(1))
+ .attr('fill', '#464646');
+
+ const html = stats
+ .append('switch')
+ .append('foreignObject')
+ .attr('requiredFeatures',
+ 'http://www.w3.org/TR/SVG11/feature#Extensibility')
+ .attr('x', 12)
+ .attr('y', 57)
+ .attr('width', 160)
+ .attr('height', 70)
+ // From here everything will be rendered with react using a ref.
+ // However for now these values are hard-coded.
+ .append('xhtml:div')
+ .attr('class', 'node_statistics');
+ // Remove with react + dyanmic data.
+
+ html.selectAll('.node_statistics').data(data.metrics).enter()
+ .append('p')
+ .text((d) => `${d.name}: ${d.stat}`);
+ }
+
+ createServiceNodes(data, elm) {
+ const component = this;
+
+ const {
+ dragged,
+ dragstarted,
+ dragended,
+ } = this;
+
+ const width = 170;
+ const topHeight = 47;
+ const radius = 4;
+
+ // Box where label will live
+ elm.append('path')
+ .attr('class', 'node')
+ .attr('d', topRoundedRect('0', '0', width, topHeight, radius))
+ .attr('stroke', colors.topologyBackground)
+ .attr('stroke-width', remcalc(1))
+ .attr('fill', colors.brandSecondaryColor);
+
+ const text = elm.append('g');
+
+ text.append('text')
+ .attr('class', 'info_text')
+ .attr('x', '12')
+ .attr('y', '30')
+ .attr('text-anchor', 'start')
+ .attr('fill', colors.brandPrimaryColor)
+ .text(d => d.id);
+
+ // if (service is registered twice in the scheduler) {
+ // Do not show healthcheck in the header
+ // } else {
+ this.createHealthCheckBadge(text);
+ // }
+
+ // if (service is registered twice in the scheduler) {
+ // this.createServiceNodeBody(data, elm, rect('0',`-${topHeight}`, width, 78, 4));
+ // } else {
+ this.createServiceNodeBody(data, elm,
+ bottomRoundedRect('0', `-${topHeight}`, width, 78, 4));
+ // }
+
+ // <==== END ====>
+
+ // Set up movement for service nodes
+ elm.call(d3.drag()
+ .on('start', dragstarted.bind(component))
+ .on('drag', dragged.bind(component))
+ .on('end', dragended.bind(component)));
+ }
+
+
+ dragstarted(d) {
+ if (!d3.event.active) this.simulation.alphaTarget(0.3).restart();
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+
+ dragged(d) {
+ d.fx = d3.event.x;
+ d.fy = d3.event.y;
+ }
+
+ dragended(d) {
+ if (!d3.event.active) this.simulation.alphaTarget(0);
+ d.fx = null;
+ d.fy = null;
+ }
+
+ ref(name) {
+ this._refs = this._refs || {};
+
+ return (el) => {
+ this._refs[name] = el;
+ };
+ }
+
+ render() {
+ return (
+
+ );
+ }
+
+}
+
+TopologyGraph.propTypes = {
+ graph: React.PropTypes.object,
+ height: React.PropTypes.number,
+ width: React.PropTypes.number,
+};
+
+module.exports = TopologyGraph;
diff --git a/ui/src/components/topology/story.js b/ui/src/components/topology/story.js
new file mode 100644
index 00000000..f6710b78
--- /dev/null
+++ b/ui/src/components/topology/story.js
@@ -0,0 +1,154 @@
+const React = require('react');
+
+const {
+ storiesOf
+} = require('@kadira/storybook');
+
+const Base = require('../base');
+const Topology = require('./');
+const TopologyView = require('./view');
+const services = {
+ nodes: [
+ {
+ id: 'Nginx',
+ attrs: {
+ dcs: 1,
+ instances: 2,
+ healthy: true,
+ },
+ metrics: [
+ {
+ name: 'CPU',
+ stat: '50%',
+ },
+ {
+ name: 'Memory',
+ stat: '20%',
+ },
+ {
+ name: 'Network',
+ stat: '5.9KB/sec',
+ },
+ ]
+ },
+ {
+ id: 'WordPress',
+ attrs: {
+ dcs: 1,
+ instances: 2,
+ healthy: true,
+ },
+ metrics: [
+ {
+ name: 'CPU',
+ stat: '50%',
+ },
+ {
+ name: 'Memory',
+ stat: '20%',
+ },
+ {
+ name: 'Network',
+ stat: '5.9KB/sec',
+ },
+ ]
+ },
+ {
+ id: 'Memcached',
+ attrs: {
+ dcs: 1,
+ instances: 2,
+ healthy: true,
+ },
+ metrics: [
+ {
+ name: 'CPU',
+ stat: '50%',
+ },
+ {
+ name: 'Memory',
+ stat: '20%',
+ },
+ {
+ name: 'Network',
+ stat: '5.9KB/sec',
+ },
+ ]
+ },
+ {
+ id: 'Percona',
+ attrs: {
+ dcs: 1,
+ instances: 2,
+ healthy: true,
+ },
+ metrics: [
+ {
+ name: 'CPU',
+ stat: '50%',
+ },
+ {
+ name: 'Memory',
+ stat: '20%',
+ },
+ {
+ name: 'Network',
+ stat: '5.9KB/sec',
+ },
+ ]
+ },
+ {
+ id: 'NFS',
+ attrs: {
+ dcs: 1,
+ instances: 2,
+ healthy: true,
+ },
+ metrics: [
+ {
+ name: 'CPU',
+ stat: '50%',
+ },
+ {
+ name: 'Memory',
+ stat: '20%',
+ },
+ {
+ name: 'Network',
+ stat: '5.9KB/sec',
+ },
+ ]
+ }
+ ],
+ links: [
+ {
+ source: 'Nginx',
+ target: 'WordPress',
+ },
+ {
+ source: 'WordPress',
+ target: 'Memcached',
+ },
+ {
+ source: 'WordPress',
+ target: 'NFS',
+ },
+ {
+ source: 'WordPress',
+ target: 'Percona',
+ }
+ ]
+};
+
+storiesOf('Topology', module)
+ .add('5 services', () => (
+
+
+
+
+
+ ));
diff --git a/ui/src/components/topology/view.js b/ui/src/components/topology/view.js
new file mode 100644
index 00000000..83aba5b5
--- /dev/null
+++ b/ui/src/components/topology/view.js
@@ -0,0 +1,33 @@
+const constants = require('../../shared/constants');
+const fns = require('../../shared/functions');
+const React = require('react');
+const Styled = require('styled-components');
+
+const {
+ colors
+} = constants;
+
+const {
+ remcalc
+} = fns;
+
+const {
+ default: styled
+} = Styled;
+
+const TopologyView = styled.div`
+ border: ${remcalc(1)} solid ${colors.borderSecondary};
+ background-color: ${colors.brandSecondary};
+`;
+
+const Topology = (props) => (
+
+ {props.children}
+
+);
+
+Topology.propTypes = {
+ children: React.PropTypes.node,
+};
+
+module.exports = Topology;
diff --git a/ui/src/components/widget/index.js b/ui/src/components/widget/index.js
index cedf32d9..377619d4 100644
--- a/ui/src/components/widget/index.js
+++ b/ui/src/components/widget/index.js
@@ -8,7 +8,8 @@ const {
} = constants;
const {
- rndId
+ rndId,
+ remcalc
} = fns;
const {
@@ -40,7 +41,7 @@ const StyledInput = styled.input`
const StyledContent = styled.div`
border: ${boxes.border.unchecked};
- border-radius: 4px;
+ border-radius: ${remcalc(4)};
cursor: pointer;
padding: remcalc(36);
diff --git a/ui/src/index.js b/ui/src/index.js
index 89758ed4..bd8efb81 100644
--- a/ui/src/index.js
+++ b/ui/src/index.js
@@ -23,6 +23,7 @@ module.exports = {
Tab: require('./components/tabs/tab'),
Tabs: require('./components/tabs'),
Toggle: require('./components/toggle'),
+ Topology: require('./components/topology'),
Tooltip: require('./components/tooltip'),
Textarea: require('./components/textarea'),
Widget: require('./components/widget'),
diff --git a/ui/src/shared/constants/baseunits.js b/ui/src/shared/constants/baseunits.js
new file mode 100644
index 00000000..4b8e9765
--- /dev/null
+++ b/ui/src/shared/constants/baseunits.js
@@ -0,0 +1,12 @@
+// WIP - possibly create a function like spacerXL, spacerS, spacerM for things lik
+// padding, margins, widths
+
+const baseunit = {
+ xs: 3,
+ s: 6,
+ m: 12,
+ l: 18,
+ xl: 24
+};
+
+module.exports = baseunit;
diff --git a/ui/src/shared/constants/boxes.js b/ui/src/shared/constants/boxes.js
index ca0852c6..532d1f43 100644
--- a/ui/src/shared/constants/boxes.js
+++ b/ui/src/shared/constants/boxes.js
@@ -1,15 +1,18 @@
const colors = require('./colors');
+const fns = require('../functions');
-const boxes = {
- borderRadius: '4px',
- bottomShaddow: '0 2px 0 0 rgba(0, 0, 0, 0.05)',
- bottomShaddowDarker: '0 2px 0 0 rgba(0, 0, 0, 0.1)',
- insetShaddow: 'inset 0 3px 0 0 rgba(0, 0, 0, 0.05)',
+const {
+ remcalc
+} = fns;
+
+module.exports = {
+ borderRadius: remcalc(4),
+ bottomShaddow: `0 ${remcalc(2)} 0 0 rgba(0, 0, 0, 0.05)`,
+ bottomShaddowDarker: `0 ${remcalc(2)} 0 0 rgba(0, 0, 0, 0.1)`,
+ insetShaddow: `inset 0 ${remcalc(3)} 0 0 rgba(0, 0, 0, 0.05)`,
border: {
- checked: `1px solid ${colors.brandPrimary}`,
- unchecked: `1px solid ${colors.borderSecondary}`,
- confirmed: `1px solid ${colors.confirmation}`
+ checked: `${remcalc(1)} solid ${colors.brandPrimary}`,
+ unchecked: `${remcalc(1)} solid ${colors.borderSecondary}`,
+ confirmed: `${remcalc(1)} solid ${colors.confirmation}`
}
};
-
-module.exports = boxes;
diff --git a/ui/src/shared/constants/colors.js b/ui/src/shared/constants/colors.js
index 6ce75c50..380ff3a5 100644
--- a/ui/src/shared/constants/colors.js
+++ b/ui/src/shared/constants/colors.js
@@ -45,13 +45,18 @@ const metrics = {
seperator: '#D9DEF3'
};
+const topology = {
+ topologyBackground: '#343434',
+};
+
const colors = {
...brandPrimary,
...brandSecondary,
...brandInactive,
...notifications,
...metrics,
- fonts
+ ...topology,
+ fonts,
};
module.exports = colors;
diff --git a/ui/src/shared/constants/index.js b/ui/src/shared/constants/index.js
index 2368e31d..d43f03bd 100644
--- a/ui/src/shared/constants/index.js
+++ b/ui/src/shared/constants/index.js
@@ -6,6 +6,7 @@ const boxes = require('./boxes');
const typography = require('./typography');
const sizes = require('./sizes');
const breakpoints = require('./breakpoints');
+const baseunit = require('./baseunits');
const tables = {
bg: 'transparent',
@@ -22,7 +23,8 @@ const constants = traverse({
forms,
sizes,
tables,
- typography
+ typography,
+ baseunit
}).map(function(x) {
return isFunction(x) ? x(this.parent.node) : x;
});
diff --git a/ui/stories/index.js b/ui/stories/index.js
index f0739a4f..39fe5594 100644
--- a/ui/stories/index.js
+++ b/ui/stories/index.js
@@ -7,9 +7,8 @@ const {
const {
Base,
- Container,
- Row,
Column,
+ Container,
MiniMetric: {
MiniMetricGraph,
MiniMetricMeta,
@@ -17,6 +16,7 @@ const {
MiniMetricSubtitle,
MiniMetricView
},
+ Row,
} = require('../src/');
const MiniMetricData = require('../src/components/list/mini-metric-data');
diff --git a/ui/yarn.lock b/ui/yarn.lock
index 8e64b4d7..0316ccc2 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -162,8 +162,8 @@ ajv-keywords@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.0.tgz#c11e6859eafff83e0dafc416929472eca946aa2c"
ajv@^4.7.0:
- version "4.10.3"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.10.3.tgz#3e4fea9675b157de7888b80dd0ed735b83f28e11"
+ version "4.10.4"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.10.4.tgz#c0974dd00b3464984892d6010aa9c2c945933254"
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
@@ -293,6 +293,13 @@ array-unique@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+array.prototype.find@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.1.tgz#1557f888df6c57e4d1256f20852d687a25b51fde"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.0"
+
arrify@^1.0.0, arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -1296,8 +1303,8 @@ babel-types@^6.13.0, babel-types@^6.15.0, babel-types@^6.16.0, babel-types@^6.18
to-fast-properties "^1.0.1"
babylon@^6.1.0, babylon@^6.11.0, babylon@^6.12.0, babylon@^6.13.0:
- version "6.14.1"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815"
+ version "6.15.0"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
babylon@~5.8.3:
version "5.8.38"
@@ -1396,11 +1403,11 @@ browserify-zlib@^0.1.4:
dependencies:
pako "~0.2.0"
-browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.4.0, browserslist@~1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.5.1.tgz#67c3f2a1a6ad174cd01d25d2362e6e6083b26986"
+browserslist@^1.0.1, browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.4.0, browserslist@^1.5.2, browserslist@~1.5.1:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.5.2.tgz#1c82fde0ee8693e6d15c49b7bff209dc06298c56"
dependencies:
- caniuse-db "^1.0.30000601"
+ caniuse-db "^1.0.30000604"
buf-compare@^1.0.0:
version "1.0.1"
@@ -1435,9 +1442,9 @@ builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
-builtin-status-codes@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz#6f22003baacf003ccd287afe6872151fddc58579"
+builtin-status-codes@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
caching-transform@^1.0.0:
version "1.0.1"
@@ -1489,9 +1496,19 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000601, caniuse-db@^1.0.30000604:
- version "1.0.30000604"
- resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000604.tgz#bc139270a777564d19c0aadcd832b491d093bda5"
+caniuse-api@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.5.2.tgz#8f393c682f661c0a997b77bba6e826483fb3600e"
+ dependencies:
+ browserslist "^1.0.1"
+ caniuse-db "^1.0.30000346"
+ lodash.memoize "^4.1.0"
+ lodash.uniq "^4.3.0"
+ shelljs "^0.7.0"
+
+caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000346, caniuse-db@^1.0.30000604:
+ version "1.0.30000607"
+ resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000607.tgz#f9d5b542f30d064c305544ff8938b217c67b88e9"
capture-stack-trace@^1.0.0:
version "1.0.0"
@@ -1537,12 +1554,9 @@ chart.js@^2.4.0:
chartjs-color "^2.0.0"
moment "^2.10.6"
-chartjs-chart-box-plot@^1.0.0-9:
- version "1.0.0-9"
- resolved "https://registry.yarnpkg.com/chartjs-chart-box-plot/-/chartjs-chart-box-plot-1.0.0-9.tgz#bd392c689301e71b13f602818629f5a0965eaddb"
- dependencies:
- react "^15.4.1"
- react-dom "^15.4.1"
+chartjs-chart-box-plot@prerelease:
+ version "1.0.0-16"
+ resolved "https://registry.yarnpkg.com/chartjs-chart-box-plot/-/chartjs-chart-box-plot-1.0.0-16.tgz#2544012ae84b04fa9922fe528017f5b748346497"
chartjs-color-string@^0.4.0:
version "0.4.0"
@@ -1774,7 +1788,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
-commander@^2.8.1, commander@^2.9.0:
+commander@2, commander@^2.8.1, commander@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
@@ -2076,6 +2090,216 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
+d3-array@1, d3-array@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.0.2.tgz#174237bf356a852fadd6af87743d928631de7655"
+
+d3-axis@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.4.tgz#bdfdcf5e859824062e0f17ad920f76236e72512c"
+
+d3-brush@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.3.tgz#4fa5374cc3b755d0990bf76b71b7a66417751c74"
+ dependencies:
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-interpolate "1"
+ d3-selection "1"
+ d3-transition "1"
+
+d3-chord@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.3.tgz#a398bae7cb632a3c4ea687a555a6b9ee4609d990"
+ dependencies:
+ d3-array "1"
+ d3-path "1"
+
+d3-collection@1, d3-collection@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.2.tgz#df5acb5400443e9eabe9c1379896c67e52426b39"
+
+d3-color@1, d3-color@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.0.2.tgz#83cb4b3a9474e40795f009d97e97a15649830bbc"
+
+d3-dispatch@1, d3-dispatch@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.2.tgz#5b511e79a46a1f89492841c0a8f656687d5daa0a"
+
+d3-drag@1, d3-drag@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.0.2.tgz#d634cc3f7689f99dd03fd7eb1af2945c0f4339ad"
+ dependencies:
+ d3-dispatch "1"
+ d3-selection "1"
+
+d3-dsv@1, d3-dsv@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.3.tgz#049fe43c0f5f60c7ff7d376616bc76d6fc9d378f"
+ dependencies:
+ commander "2"
+ iconv-lite "0.4"
+ rw "1"
+
+d3-ease@1, d3-ease@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.2.tgz#b486f8f3ca308ca7be38197d65622b6e30983377"
+
+d3-force@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.0.4.tgz#f84dcbb3200be41de7bc30fa71923143156758bf"
+ dependencies:
+ d3-collection "1"
+ d3-dispatch "1"
+ d3-quadtree "1"
+ d3-timer "1"
+
+d3-format@1, d3-format@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.0.2.tgz#138618320b4bbeb43b5c0ff30519079fbbd7375e"
+
+d3-geo@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.4.0.tgz#15e58c414b5bafa1a960eeeb29059c94a60d8408"
+ dependencies:
+ d3-array "1"
+
+d3-hierarchy@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.0.3.tgz#986b4925e81f1e0b4087e9442850f950cf27d338"
+
+d3-interpolate@1, d3-interpolate@1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.2.tgz#b52e6927a04fe1fe2a4cffc139e5389ed3e5e790"
+ dependencies:
+ d3-color "1"
+
+d3-path@1, d3-path@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.3.tgz#60103d0dea9a6cd6ca58de86c6d56724002d3fde"
+
+d3-polygon@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.2.tgz#6552c0fb03aa2d05023351da6e0e8adc4df0202b"
+
+d3-quadtree@1, d3-quadtree@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.2.tgz#e7e873af06aaa427eaa4af094cc4cbfb350b9e38"
+
+d3-queue@3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.3.tgz#10ee4dd0574a1affaabfb931d0ba4f117926edc6"
+
+d3-random@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.0.2.tgz#83ff6a391206209c30565299e43c6549866db269"
+
+d3-request@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-request/-/d3-request-1.0.3.tgz#63fc7dfd784607db0df5d535d7cb898fceba755a"
+ dependencies:
+ d3-collection "1"
+ d3-dispatch "1"
+ d3-dsv "1"
+ xmlhttprequest "1"
+
+d3-scale@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.4.tgz#50e28bf6a193b706745528515ed9b3d44205a033"
+ dependencies:
+ d3-array "1"
+ d3-collection "1"
+ d3-color "1"
+ d3-format "1"
+ d3-interpolate "1"
+ d3-time "1"
+ d3-time-format "2"
+
+d3-selection@1, d3-selection@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.0.3.tgz#e63e51416172427854c1bcdfa066eb5fe872c108"
+
+d3-shape@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.0.4.tgz#145ee100ccbec42f8e3f1996cd05c786f79fe1c6"
+ dependencies:
+ d3-path "1"
+
+d3-time-format@2, d3-time-format@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.0.3.tgz#3241569b74ddc9c42e0689c0e8a903579fd6280a"
+ dependencies:
+ d3-time "1"
+
+d3-time@1, d3-time@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.4.tgz#2ceba09a76b7450c992a1ded4e10fc6195e69649"
+
+d3-timer@1, d3-timer@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.3.tgz#7a308a10c8524778e6b32d1d6c1c329209ae0ebf"
+
+d3-transition@1, d3-transition@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.0.3.tgz#91dc986bddb30973639320a85db72ce4ab1a27bb"
+ dependencies:
+ d3-color "1"
+ d3-dispatch "1"
+ d3-ease "1"
+ d3-interpolate "1"
+ d3-selection "1"
+ d3-timer "1"
+
+d3-voronoi@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.1.tgz#998544dca98ef0e89a6c40c0bac3510d1bc1b8b9"
+
+d3-zoom@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.1.1.tgz#d2362d8f7043c1fc5d96a438de69f4e02ef1e67b"
+ dependencies:
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-interpolate "1"
+ d3-selection "1"
+ d3-transition "1"
+
+d3@^4.4.1:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/d3/-/d3-4.4.1.tgz#2cbb08f92970364076ffe91ab83ef66b80610785"
+ dependencies:
+ d3-array "1.0.2"
+ d3-axis "1.0.4"
+ d3-brush "1.0.3"
+ d3-chord "1.0.3"
+ d3-collection "1.0.2"
+ d3-color "1.0.2"
+ d3-dispatch "1.0.2"
+ d3-drag "1.0.2"
+ d3-dsv "1.0.3"
+ d3-ease "1.0.2"
+ d3-force "1.0.4"
+ d3-format "1.0.2"
+ d3-geo "1.4.0"
+ d3-hierarchy "1.0.3"
+ d3-interpolate "1.1.2"
+ d3-path "1.0.3"
+ d3-polygon "1.0.2"
+ d3-quadtree "1.0.2"
+ d3-queue "3.0.3"
+ d3-random "1.0.2"
+ d3-request "1.0.3"
+ d3-scale "1.0.4"
+ d3-selection "1.0.3"
+ d3-shape "1.0.4"
+ d3-time "1.0.4"
+ d3-time-format "2.0.3"
+ d3-timer "1.0.3"
+ d3-transition "1.0.3"
+ d3-voronoi "1.1.1"
+ d3-zoom "1.1.1"
+
d@^0.1.1, d@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309"
@@ -2487,9 +2711,10 @@ eslint-plugin-promise@^3.4.0:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.4.0.tgz#6ba9048c2df57be77d036e0c68918bc9b4fc4195"
eslint-plugin-react@^6.8.0:
- version "6.8.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.8.0.tgz#741ab5438a094532e5ce1bbb935d6832356f492d"
+ version "6.9.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.9.0.tgz#54c2e9906b76f9d10142030bdc34e9d6840a0bb2"
dependencies:
+ array.prototype.find "^2.0.1"
doctrine "^1.2.2"
jsx-ast-utils "^1.3.4"
@@ -2498,8 +2723,8 @@ eslint-plugin-standard@^2.0.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz#3589699ff9c917f2c25f76a916687f641c369ff3"
eslint@^3.12.2:
- version "3.12.2"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.12.2.tgz#6be5a9aa29658252abd7f91e9132bab1f26f3c34"
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.13.1.tgz#564d2646b5efded85df96985332edd91a23bff25"
dependencies:
babel-code-frame "^6.16.0"
chalk "^1.1.3"
@@ -2531,7 +2756,7 @@ eslint@^3.12.2:
require-uncached "^1.0.2"
shelljs "^0.7.5"
strip-bom "^3.0.0"
- strip-json-comments "~1.0.1"
+ strip-json-comments "~2.0.1"
table "^3.7.8"
text-table "~0.2.0"
user-home "^2.0.0"
@@ -3019,7 +3244,7 @@ got@^5.0.0:
unzip-response "^1.0.2"
url-parse-lax "^1.0.0"
-graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@~4.1.4:
+graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@~4.1.4:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
@@ -3155,14 +3380,14 @@ hyphenate-style-name@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
+iconv-lite@0.4, iconv-lite@^0.4.13, iconv-lite@~0.4.13:
+ version "0.4.15"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
+
iconv-lite@0.4.13:
version "0.4.13"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
-iconv-lite@^0.4.13, iconv-lite@~0.4.13:
- version "0.4.15"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
-
icss-replace-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5"
@@ -3856,8 +4081,8 @@ lodash.isarray@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.isequal@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.4.0.tgz#6295768e98e14dc15ce8d362ef6340db82852031"
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash.isfunction@^3.0.8:
version "3.0.8"
@@ -3883,6 +4108,10 @@ lodash.map@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
+lodash.memoize@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+
lodash.merge@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
@@ -3907,6 +4136,10 @@ lodash.some@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
+lodash.uniq@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+
lodash@4.x.x, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.10.0, lodash@^4.12.0, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -4255,8 +4488,8 @@ normalize-selector@^0.2.0:
resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03"
normalize-url@^1.4.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.8.0.tgz#a9550b079aa3523c85d78df24eef1959fce359ab"
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.0.tgz#c2bb50035edee62cd81edb2d45da68dc25e3423e"
dependencies:
object-assign "^4.0.1"
prepend-http "^1.0.0"
@@ -4705,24 +4938,24 @@ postcss-less@^0.14.0:
postcss "^5.0.21"
postcss-load-config@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.0.0.tgz#1399f60dcd6bd9c3124b2eb22960f77f9dc08b3d"
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.1.0.tgz#1c3c217608642448c03bebf3c32b1b28985293f9"
dependencies:
cosmiconfig "^2.1.0"
object-assign "^4.1.0"
- postcss-load-options "^1.0.2"
- postcss-load-plugins "^2.0.0"
+ postcss-load-options "^1.1.0"
+ postcss-load-plugins "^2.2.0"
-postcss-load-options@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.0.2.tgz#b99eb5759a588f4b2dd8b6471c6985f72060e7b0"
+postcss-load-options@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.1.0.tgz#e39215d154a19f69f9cb6052bffad4a82f09f354"
dependencies:
cosmiconfig "^2.1.0"
object-assign "^4.1.0"
-postcss-load-plugins@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.1.0.tgz#dbb6f46271df8d16e19b5d691ebda5175ce424a0"
+postcss-load-plugins@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.2.0.tgz#84ef9cf36e637810ac5265e03f6d4c48ead83314"
dependencies:
cosmiconfig "^2.1.1"
object-assign "^4.1.0"
@@ -4755,10 +4988,13 @@ postcss-merge-longhand@^2.0.1:
postcss "^5.0.4"
postcss-merge-rules@^2.0.3:
- version "2.0.11"
- resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.0.11.tgz#c5d7c8de5056a7377aea0dff2fd83f92cafb9b8a"
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.1.tgz#5e5640020ce43cddd343c73bba91c9a358d1fe0f"
dependencies:
+ browserslist "^1.5.2"
+ caniuse-api "^1.5.2"
postcss "^5.0.4"
+ postcss-selector-parser "^2.2.2"
vendors "^1.0.0"
postcss-message-helpers@^2.0.0:
@@ -4841,8 +5077,8 @@ postcss-normalize-url@^3.0.7:
postcss-value-parser "^3.2.3"
postcss-ordered-values@^2.1.0:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.2.tgz#be8b511741fab2dac8e614a2302e9d10267b0771"
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d"
dependencies:
postcss "^5.0.4"
postcss-value-parser "^3.0.1"
@@ -4896,7 +5132,7 @@ postcss-scss@^0.4.0:
dependencies:
postcss "^5.2.5"
-postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.1.1:
+postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.1.1, postcss-selector-parser@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.2.tgz#3d70f5adda130da51c7c0c2fc023f56b1374fe08"
dependencies:
@@ -4934,8 +5170,8 @@ postcss-zindex@^2.0.1:
uniqs "^2.0.0"
postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.18, postcss@^5.0.2, postcss@^5.0.20, postcss@^5.0.21, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.4, postcss@^5.2.5, postcss@^5.2.8:
- version "5.2.8"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.8.tgz#05720c49df23c79bda51fd01daeb1e9222e94390"
+ version "5.2.10"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.10.tgz#b58b64e04f66f838b7bc7cb41f7dac168568a945"
dependencies:
chalk "^1.1.3"
js-base64 "^2.1.9"
@@ -5142,8 +5378,11 @@ rc@^1.0.1, rc@^1.1.6, rc@~1.1.6:
strip-json-comments "~1.0.4"
react-addons-test-utils@^15.4.1:
- version "15.4.1"
- resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.4.1.tgz#1e4caab151bf27cce26df5f9cb714f4fd8359ae1"
+ version "15.4.2"
+ resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz#93bcaa718fcae7360d42e8fb1c09756cc36302a2"
+ dependencies:
+ fbjs "^0.8.4"
+ object-assign "^4.1.0"
react-docgen@^2.12.1:
version "2.13.0"
@@ -5158,8 +5397,8 @@ react-docgen@^2.12.1:
recast "^0.11.5"
react-dom@^15.4.1:
- version "15.4.1"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.1.tgz#d54c913261aaedb17adc20410d029dcc18a1344a"
+ version "15.4.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f"
dependencies:
fbjs "^0.8.1"
loose-envify "^1.1.0"
@@ -5212,7 +5451,7 @@ react-modal@^1.2.0, react-modal@^1.2.1:
exenv "1.2.0"
lodash.assign "^4.2.0"
-react-select:
+react-select@^1.0.0-rc.2:
version "1.0.0-rc.2"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.0.0-rc.2.tgz#9fc11b149a3dc1ac831289d21b40a59742f82f8d"
dependencies:
@@ -5233,8 +5472,8 @@ react-stubber@^1.0.0:
babel-runtime "^6.5.0"
react@^15.4.1:
- version "15.4.1"
- resolved "https://registry.yarnpkg.com/react/-/react-15.4.1.tgz#498e918602677a3983cd0fd206dfe700389a0dd6"
+ version "15.4.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef"
dependencies:
fbjs "^0.8.4"
loose-envify "^1.1.0"
@@ -5553,6 +5792,10 @@ run-async@^0.1.0:
dependencies:
once "^1.3.0"
+rw@1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.2.tgz#14ef5137ff7547c73ecf0e0af1f0aee07e5401ee"
+
rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
@@ -5643,9 +5886,9 @@ shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
-shelljs@^0.7.4, shelljs@^0.7.5:
- version "0.7.5"
- resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675"
+shelljs@^0.7.0, shelljs@^0.7.4, shelljs@^0.7.5:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
dependencies:
glob "^7.0.0"
interpret "^1.0.0"
@@ -5690,8 +5933,8 @@ sort-keys@^1.0.0, sort-keys@^1.1.1:
is-plain-obj "^1.0.0"
source-list-map@^0.1.4, source-list-map@~0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.7.tgz#d4b5ce2a46535c72c7e8527c71a77d250618172e"
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
source-map-support@^0.4.0, source-map-support@^0.4.2:
version "0.4.8"
@@ -5811,10 +6054,10 @@ stream-combiner@^0.2.1:
through "~2.3.4"
stream-http@^2.3.1:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.5.0.tgz#585eee513217ed98fe199817e7313b6f772a6802"
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.1.tgz#7d20fcdfebc16b16e4174e31dd94cd9c70f10e89"
dependencies:
- builtin-status-codes "^2.0.0"
+ builtin-status-codes "^3.0.0"
inherits "^2.0.1"
readable-stream "^2.1.0"
to-arraybuffer "^1.0.0"
@@ -5897,10 +6140,14 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
-strip-json-comments@~1.0.1, strip-json-comments@~1.0.4:
+strip-json-comments@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
style-loader@0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.13.1.tgz#468280efbc0473023cd3a6cd56e33b5a1d7fc3a9"
@@ -6295,8 +6542,8 @@ uniq@^1.0.1:
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
uniqid@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.0.tgz#33d9679f65022f48988a03fd24e7dcaf8f109eca"
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1"
dependencies:
macaddress "^0.2.8"
@@ -6486,8 +6733,8 @@ whatwg-fetch@>=0.10.0:
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz#078b9461bbe91cea73cbce8bb122a05f9e92b772"
whatwg-url@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.2.0.tgz#abf1a3f5ff4bc2005b3f0c2119382631789d8e44"
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.3.0.tgz#92aaee21f4f2a642074357d70ef8500a7cbb171a"
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
@@ -6550,10 +6797,10 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write-file-atomic@^1.1.2, write-file-atomic@^1.1.4:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.2.0.tgz#14c66d4e4cb3ca0565c28cf3b7a6f3e4d5938fab"
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a"
dependencies:
- graceful-fs "^4.1.2"
+ graceful-fs "^4.1.11"
imurmurhash "^0.1.4"
slide "^1.1.5"
@@ -6608,6 +6855,10 @@ xmlbuilder@^4.1.0, xmlbuilder@~4.1.0:
dependencies:
lodash "^3.5.0"
+xmlhttprequest@1:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
+
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"