Topology constraints, metrics uppercase fix, node title link
This commit is contained in:
parent
398071ade2
commit
97a4537330
@ -2,18 +2,18 @@
|
||||
"your-dashboard": "Your dashboard",
|
||||
"project-feed": "Project Feed",
|
||||
"summary": "Summary",
|
||||
"metric-s": "Metrics",
|
||||
"metrics": "Metrics",
|
||||
"networks": "Networks",
|
||||
"tags-metadata": "Tags and Meta Data",
|
||||
"activity-feed": "Activity Feed",
|
||||
"firewall": "Firewall",
|
||||
"service-manifest": "Service manifest",
|
||||
"settings": "Settings",
|
||||
"projects": "Projects",
|
||||
"people": "People",
|
||||
"services": "Services",
|
||||
"instances": "Instances",
|
||||
"manifest": "Project manifest",
|
||||
"service-manifest": "Service manifest",
|
||||
"create-new": "Create new project",
|
||||
"rollback": "Rollback",
|
||||
"import-services-title": "Import your services",
|
||||
@ -52,7 +52,7 @@
|
||||
"description": "Please provide your billing details.",
|
||||
"save-details-label": "Save details"
|
||||
},
|
||||
"metrics": {
|
||||
"metrics-section": {
|
||||
"add": {
|
||||
"add-label": "Add",
|
||||
"added-label": "Added",
|
||||
|
@ -21,26 +21,29 @@ const AddMetrics = ({
|
||||
|
||||
const addButton = (metric) => (
|
||||
<AddMetricButton metric={metric} onClick={onAddMetric}>
|
||||
<FormattedMessage id={'metrics.add.add-label'} onClick={onAddMetric} />
|
||||
<FormattedMessage
|
||||
id={'metrics-section.add.add-label'}
|
||||
onClick={onAddMetric}
|
||||
/>
|
||||
</AddMetricButton>
|
||||
);
|
||||
|
||||
const addedButton = (
|
||||
<AddMetricButton disabled>
|
||||
<FormattedMessage id={'metrics.add.added-label'} />
|
||||
<FormattedMessage id={'metrics-section.add.added-label'} />
|
||||
</AddMetricButton>
|
||||
);
|
||||
|
||||
const metricList = metricTypes.map((metric) => (
|
||||
<AddMetricTile key={metric.id}>
|
||||
<AddMetricTitle>
|
||||
<FormattedMessage id={`metrics.${metric.id}.title`} />
|
||||
<FormattedMessage id={`metrics-section.${metric.id}.title`} />
|
||||
</AddMetricTitle>
|
||||
<AddMetricDescription>
|
||||
<FormattedMessage id={`metrics.${metric.id}.description`} />
|
||||
<FormattedMessage id={`metrics-section.${metric.id}.description`} />
|
||||
</AddMetricDescription>
|
||||
<AddMetricLink href='http://somelink.com'>
|
||||
<FormattedMessage id={'metrics.add.link-label'} />
|
||||
<FormattedMessage id={'metrics-section.add.link-label'} />
|
||||
</AddMetricLink>
|
||||
{ added(metric.uuid) ? addedButton : addButton(metric.uuid) }
|
||||
</AddMetricTile>
|
||||
|
@ -47,13 +47,13 @@ const MetricCharts = ({
|
||||
<MetricHeader>
|
||||
<MetricTitle>
|
||||
{type.name}
|
||||
{/*<FormattedMessage id={`metrics.${type.id}.title`} />*/}
|
||||
{/*<FormattedMessage id={`metrics-section.${type.id}.title`} />*/}
|
||||
</MetricTitle>
|
||||
<MetricSelect onChange={handleSelectChange} value={String(duration)}>
|
||||
{optionList}
|
||||
</MetricSelect>
|
||||
<MetricSettingsButton onClick={handleSettingsClick}>
|
||||
<FormattedMessage id={'metrics.metric.settings-label'} />
|
||||
<FormattedMessage id={'metrics-section.metric.settings-label'} />
|
||||
</MetricSettingsButton>
|
||||
<MetricCloseButton onClick={handleRemoveMetric} />
|
||||
</MetricHeader>
|
||||
|
@ -2,7 +2,8 @@ import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import { colors } from '@ui/shared/constants';
|
||||
import { colors, breakpoints } from '@ui/shared/constants';
|
||||
import { unitcalc } from '@ui/shared/functions';
|
||||
import { TopologyGraph } from '@ui/components/topology';
|
||||
import { LayoutContainer } from '@components/layout';
|
||||
import ServicesTooltip from '@components/services/tooltip';
|
||||
@ -22,6 +23,11 @@ const StyledBackground = styled.div`
|
||||
|
||||
const StyledContainer = styled(LayoutContainer)`
|
||||
position: relative;
|
||||
padding: ${unitcalc(4)} 2rem;
|
||||
|
||||
${breakpoints.large`
|
||||
padding: ${unitcalc(4)} 0;
|
||||
`}
|
||||
`;
|
||||
|
||||
const Services = (props) => {
|
||||
@ -30,14 +36,16 @@ const Services = (props) => {
|
||||
org = {},
|
||||
project = {},
|
||||
toggleTooltip,
|
||||
uiTooltip
|
||||
uiTooltip,
|
||||
push
|
||||
} = props;
|
||||
|
||||
const onQuickActions = (evt, tooltipData) => {
|
||||
const service = services.reduce((acc, service) =>
|
||||
service.uuid === tooltipData.service ? service : acc
|
||||
, {});
|
||||
const getService = (uuid) => services.reduce((acc, service) =>
|
||||
service.uuid === uuid ? service : acc
|
||||
, {});
|
||||
|
||||
const onQuickActions = (evt, tooltipData) => {
|
||||
const service = getService(tooltipData.service);
|
||||
const ttData = {
|
||||
...tooltipData,
|
||||
data: {
|
||||
@ -54,11 +62,20 @@ const Services = (props) => {
|
||||
service: uiTooltip.service
|
||||
});
|
||||
|
||||
const onNodeTitleClick = (uuid) => {
|
||||
const service = getService(uuid);
|
||||
|
||||
const path = `/${org.id}/projects/${project.id}/services/${service.id}`;
|
||||
|
||||
push(path);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledBackground>
|
||||
<StyledContainer>
|
||||
<TopologyGraph
|
||||
onQuickActions={onQuickActions}
|
||||
onNodeTitleClick={onNodeTitleClick}
|
||||
services={services}
|
||||
/>
|
||||
<ServicesTooltip {...uiTooltip} onBlur={handleTooltipBlur} />
|
||||
@ -71,6 +88,7 @@ Services.propTypes = {
|
||||
org: PropTypes.org,
|
||||
services: React.PropTypes.arrayOf(PropTypes.service),
|
||||
project: PropTypes.project,
|
||||
push: React.PropTypes.func.isRequired,
|
||||
toggleTooltip: React.PropTypes.func,
|
||||
uiTooltip: React.PropTypes.object
|
||||
};
|
||||
@ -78,12 +96,14 @@ Services.propTypes = {
|
||||
const mapStateToProps = (state, {
|
||||
match = {
|
||||
params: {}
|
||||
}
|
||||
},
|
||||
push
|
||||
}) => ({
|
||||
org: orgByIdSelector(match.params.org)(state),
|
||||
project: projectByIdSelector(match.params.projectId)(state),
|
||||
services: servicesForTopologySelector(match.params.projectId)(state),
|
||||
uiTooltip: serviceUiTooltipSelector(state)
|
||||
uiTooltip: serviceUiTooltipSelector(state),
|
||||
push: push
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
@ -75,7 +75,7 @@
|
||||
"id": "cpu-wait-time",
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"measurement": "%"
|
||||
"measurement": "bytes"
|
||||
}, {
|
||||
"uuid": "dca08514-72e5-46ce-ad91-e68b3b0914d7",
|
||||
"name": "Zfs used",
|
||||
@ -96,14 +96,14 @@
|
||||
"id": "load-average",
|
||||
"min": 0,
|
||||
"max": 20,
|
||||
"measurement": "kb"
|
||||
"measurement": " Mb"
|
||||
}, {
|
||||
"uuid": "dca08514-72e5-46ce-ad92-e68b3b0914d4",
|
||||
"name": "Memory",
|
||||
"id": "mem-agg-usage",
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"measurement": "%"
|
||||
"measurement": " Mb"
|
||||
}, {
|
||||
"uuid": "dca08514-72e5-46ce-ad93-e68b3b0914d4",
|
||||
"name": "Memory limit",
|
||||
|
@ -14,6 +14,7 @@ const GraphNode = ({
|
||||
data,
|
||||
index,
|
||||
onDragStart,
|
||||
onNodeTitleClick,
|
||||
onQuickActions
|
||||
}) => {
|
||||
|
||||
@ -61,6 +62,9 @@ const GraphNode = ({
|
||||
onQuickActions(evt, d);
|
||||
};
|
||||
|
||||
const onTitleClick = () =>
|
||||
onNodeTitleClick(data.uuid);
|
||||
|
||||
const onStart = (evt) => {
|
||||
evt.preventDefault();
|
||||
onDragStart(evt, data.id);
|
||||
@ -107,6 +111,7 @@ const GraphNode = ({
|
||||
<GraphNodeTitle
|
||||
connected={connected}
|
||||
data={data}
|
||||
onNodeTitleClick={onTitleClick}
|
||||
/>
|
||||
<GraphNodeButton
|
||||
connected={connected}
|
||||
@ -123,6 +128,7 @@ GraphNode.propTypes = {
|
||||
data: React.PropTypes.object.isRequired,
|
||||
index: React.PropTypes.number.isRequired,
|
||||
onDragStart: React.PropTypes.func,
|
||||
onNodeTitleClick: React.PropTypes.func,
|
||||
onQuickActions: React.PropTypes.func
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,8 @@ import HeartIcon from './icon-heart.svg';
|
||||
|
||||
const GraphNodeTitle = ({
|
||||
connected,
|
||||
data
|
||||
data,
|
||||
onNodeTitleClick
|
||||
}) => {
|
||||
|
||||
return (
|
||||
@ -15,6 +16,8 @@ const GraphNodeTitle = ({
|
||||
x={Constants.paddingLeft}
|
||||
y={30}
|
||||
connected={connected}
|
||||
onClick={onNodeTitleClick}
|
||||
onKeyDown={onNodeTitleClick}
|
||||
>
|
||||
{data.name}
|
||||
</GraphTitle>
|
||||
@ -32,7 +35,8 @@ const GraphNodeTitle = ({
|
||||
|
||||
GraphNodeTitle.propTypes = {
|
||||
connected: React.PropTypes.bool,
|
||||
data: React.PropTypes.object.isRequired
|
||||
data: React.PropTypes.object.isRequired,
|
||||
onNodeTitleClick: React.PropTypes.func
|
||||
};
|
||||
|
||||
export default Baseline(
|
||||
|
@ -5,7 +5,6 @@ import Constants from './constants';
|
||||
import GraphNode from './graph-node';
|
||||
import GraphLink from './graph-link';
|
||||
import React from 'react';
|
||||
import { triggerMouseEvent } from '../../shared/functions';
|
||||
|
||||
const StyledSvg = styled.svg`
|
||||
width: 100%;
|
||||
@ -103,26 +102,36 @@ class TopologyGraph extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
isWithinSVGBounds(target, x, y) {
|
||||
const svgBounds = document
|
||||
.getElementsByClassName('topology-svg')[0]
|
||||
.getBoundingClientRect();
|
||||
getSvgSize() {
|
||||
return document.getElementById('topology-svg') ?
|
||||
document.getElementById('topology-svg').getBoundingClientRect() :
|
||||
svgSize;
|
||||
}
|
||||
|
||||
const nodeHeight = target.getBoundingClientRect().height;
|
||||
const nodeWidth = target.getBoundingClientRect().width;
|
||||
constrain(x, y, children=false) {
|
||||
const svgSize = this.getSvgSize();
|
||||
|
||||
const constraints = {
|
||||
top: svgBounds.top + (nodeHeight / 2),
|
||||
left: svgBounds.left + (nodeWidth / 2),
|
||||
bottom: svgBounds.bottom - (nodeHeight / 2),
|
||||
right: svgBounds.right - (nodeWidth / 2)
|
||||
const nodeRect = children ?
|
||||
Constants.nodeRectWithChildren :
|
||||
Constants.nodeRect;
|
||||
|
||||
if(x < nodeRect.right + 2) {
|
||||
x = nodeRect.right + 2;
|
||||
}
|
||||
else if(x > svgSize.width + nodeRect.left - 2) {
|
||||
x = svgSize.width + nodeRect.left - 2;
|
||||
}
|
||||
if(y < -nodeRect.top + 2) {
|
||||
y = -nodeRect.top + 2;
|
||||
}
|
||||
else if(y > svgSize.height - nodeRect.bottom - 2) {
|
||||
y = svgSize.height - nodeRect.bottom - 2;
|
||||
}
|
||||
|
||||
return {
|
||||
x,
|
||||
y
|
||||
};
|
||||
|
||||
if ( x > constraints.right || x < constraints.left ) return false;
|
||||
|
||||
if ( y < constraints.top || y > constraints.bottom ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -147,9 +156,14 @@ class TopologyGraph extends React.Component {
|
||||
y: 0
|
||||
} : simNode(service.uuid);
|
||||
|
||||
const constrained = {
|
||||
...sNode,
|
||||
...this.constrain(sNode.x, sNode.y, service.children)
|
||||
};
|
||||
|
||||
return ({
|
||||
...service,
|
||||
...sNode
|
||||
...constrained
|
||||
});
|
||||
});
|
||||
|
||||
@ -188,10 +202,6 @@ class TopologyGraph extends React.Component {
|
||||
? evt.changedTouches[0].pageY
|
||||
: evt.clientY;
|
||||
|
||||
if ( !this.isWithinSVGBounds(evt.target, x, y) ) {
|
||||
triggerMouseEvent(evt.target, 'mouseup');
|
||||
}
|
||||
|
||||
const offset = {
|
||||
x: x - dragInfo.position.x,
|
||||
y: y - dragInfo.position.y
|
||||
@ -229,12 +239,16 @@ class TopologyGraph extends React.Component {
|
||||
};
|
||||
};
|
||||
|
||||
const onTitleClick = (serviceUUID) =>
|
||||
this.props.onNodeTitleClick(serviceUUID);
|
||||
|
||||
const renderedNodes = nodesData.map((n, index) => (
|
||||
<GraphNode
|
||||
key={index}
|
||||
data={n}
|
||||
index={index}
|
||||
onDragStart={onDragStart}
|
||||
onNodeTitleClick={onTitleClick}
|
||||
onQuickActions={onQuickActions}
|
||||
connected={n.id !== 'consul'}
|
||||
/>
|
||||
@ -255,7 +269,7 @@ class TopologyGraph extends React.Component {
|
||||
onMouseUp={onDragEnd}
|
||||
onTouchEnd={onDragEnd}
|
||||
onTouchCancel={onDragEnd}
|
||||
className='topology-svg'
|
||||
id='topology-svg'
|
||||
>
|
||||
<g>
|
||||
{renderedNodes}
|
||||
@ -270,6 +284,7 @@ class TopologyGraph extends React.Component {
|
||||
|
||||
TopologyGraph.propTypes = {
|
||||
onQuickActions: React.PropTypes.func,
|
||||
onNodeTitleClick: React.PropTypes.func,
|
||||
services: React.PropTypes.array
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user