From 97a4537330e3a0fb1664f6a4857808375e85e9b3 Mon Sep 17 00:00:00 2001 From: Alex Windett Date: Thu, 23 Mar 2017 15:31:25 +0000 Subject: [PATCH] Topology constraints, metrics uppercase fix, node title link --- frontend/locales/en-us.json | 6 +- .../components/metric-charts/add-metrics.js | 13 ++-- .../src/components/metric-charts/index.js | 4 +- frontend/src/containers/services/topology.js | 36 ++++++++--- frontend/src/mock-state.json | 6 +- .../components/topology/graph-node/index.js | 6 ++ .../components/topology/graph-node/title.js | 8 ++- ui/src/components/topology/topology-graph.js | 63 ++++++++++++------- 8 files changed, 95 insertions(+), 47 deletions(-) diff --git a/frontend/locales/en-us.json b/frontend/locales/en-us.json index b034feb0..80aafe5c 100644 --- a/frontend/locales/en-us.json +++ b/frontend/locales/en-us.json @@ -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", diff --git a/frontend/src/components/metric-charts/add-metrics.js b/frontend/src/components/metric-charts/add-metrics.js index 702d3983..eb5d05f7 100644 --- a/frontend/src/components/metric-charts/add-metrics.js +++ b/frontend/src/components/metric-charts/add-metrics.js @@ -21,26 +21,29 @@ const AddMetrics = ({ const addButton = (metric) => ( - + ); const addedButton = ( - + ); const metricList = metricTypes.map((metric) => ( - + - + - + { added(metric.uuid) ? addedButton : addButton(metric.uuid) } diff --git a/frontend/src/components/metric-charts/index.js b/frontend/src/components/metric-charts/index.js index 9808002b..fb132168 100644 --- a/frontend/src/components/metric-charts/index.js +++ b/frontend/src/components/metric-charts/index.js @@ -47,13 +47,13 @@ const MetricCharts = ({ {type.name} - {/**/} + {/**/} {optionList} - + diff --git a/frontend/src/containers/services/topology.js b/frontend/src/containers/services/topology.js index 1723f6bd..37472f96 100644 --- a/frontend/src/containers/services/topology.js +++ b/frontend/src/containers/services/topology.js @@ -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 ( @@ -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) => ({ diff --git a/frontend/src/mock-state.json b/frontend/src/mock-state.json index 2551e698..d9276147 100644 --- a/frontend/src/mock-state.json +++ b/frontend/src/mock-state.json @@ -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", diff --git a/ui/src/components/topology/graph-node/index.js b/ui/src/components/topology/graph-node/index.js index eabaa865..ed2061cd 100644 --- a/ui/src/components/topology/graph-node/index.js +++ b/ui/src/components/topology/graph-node/index.js @@ -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 = ({ { return ( @@ -15,6 +16,8 @@ const GraphNodeTitle = ({ x={Constants.paddingLeft} y={30} connected={connected} + onClick={onNodeTitleClick} + onKeyDown={onNodeTitleClick} > {data.name} @@ -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( diff --git a/ui/src/components/topology/topology-graph.js b/ui/src/components/topology/topology-graph.js index ef30e8df..870aea5c 100644 --- a/ui/src/components/topology/topology-graph.js +++ b/ui/src/components/topology/topology-graph.js @@ -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) => ( @@ -255,7 +269,7 @@ class TopologyGraph extends React.Component { onMouseUp={onDragEnd} onTouchEnd={onDragEnd} onTouchCancel={onDragEnd} - className='topology-svg' + id='topology-svg' > {renderedNodes} @@ -270,6 +284,7 @@ class TopologyGraph extends React.Component { TopologyGraph.propTypes = { onQuickActions: React.PropTypes.func, + onNodeTitleClick: React.PropTypes.func, services: React.PropTypes.array };