From 1e6c465f5abd0bdf6ff7ec7837046b395bfec340 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Thu, 13 Oct 2016 16:45:42 +0200 Subject: [PATCH 1/6] Current topo follows details panel! --- client/app/scripts/actions/app-actions.js | 8 +++- client/app/scripts/reducers/root.js | 57 ++++++++++++++++------- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js index eff78794b..34203e885 100644 --- a/client/app/scripts/actions/app-actions.js +++ b/client/app/scripts/actions/app-actions.js @@ -286,6 +286,7 @@ export function clickRelative(nodeId, topologyId, label, origin) { topologyId }); updateRoute(getState); + resetUpdateBuffer(); const state = getState(); getNodeDetails( state.get('topologyUrlsById'), @@ -294,6 +295,11 @@ export function clickRelative(nodeId, topologyId, label, origin) { state.get('nodeDetails'), dispatch ); + getNodesDelta( + getCurrentTopologyUrl(state), + getActiveTopologyOptions(state), + dispatch + ); }; } @@ -461,7 +467,7 @@ export function hitEsc() { } else if (state.get('showingHelp')) { dispatch(hideHelp()); } else if (state.get('nodeDetails').last() && !controlPipe) { - dispatch({ type: ActionTypes.DESELECT_NODE }); + dispatch({ type: ActionTypes.CLICK_CLOSE_DETAILS }); updateRoute(getState); } }; diff --git a/client/app/scripts/reducers/root.js b/client/app/scripts/reducers/root.js index 09d6de922..fc81a0802 100644 --- a/client/app/scripts/reducers/root.js +++ b/client/app/scripts/reducers/root.js @@ -69,6 +69,7 @@ export const initialState = makeMap({ exportingGraph: false }); + // adds ID field to topology (based on last part of URL path) and save urls in // map for easy lookup function processTopologies(state, nextTopologies) { @@ -87,12 +88,14 @@ function processTopologies(state, nextTopologies) { return state.mergeDeepIn(['topologies'], immNextTopologies); } + function setTopology(state, topologyId) { state = state.set('currentTopology', findTopologyById( state.get('topologies'), topologyId)); return state.set('currentTopologyId', topologyId); } + function setDefaultTopologyOptions(state, topologyList) { topologyList.forEach(topology => { let defaultOptions = makeOrderedMap(); @@ -113,6 +116,7 @@ function setDefaultTopologyOptions(state, topologyList) { return state; } + function closeNodeDetails(state, nodeId) { const nodeDetails = state.get('nodeDetails'); if (nodeDetails.size > 0) { @@ -128,6 +132,7 @@ function closeNodeDetails(state, nodeId) { return state; } + function closeAllNodeDetails(state) { while (state.get('nodeDetails').size) { state = closeNodeDetails(state); @@ -135,10 +140,33 @@ function closeAllNodeDetails(state) { return state; } + function resumeUpdate(state) { return state.set('updatePausedAt', null); } + +function setSelectedNode(state, {nodeId, label, origin, topologyId}) { + state = resumeUpdate(state); + if (state.hasIn(['nodeDetails', nodeId])) { + // bring to front + const details = state.getIn(['nodeDetails', nodeId]); + state = state.deleteIn(['nodeDetails', nodeId]); + state = state.setIn(['nodeDetails', nodeId], details); + } else { + state = state.setIn(['nodeDetails', nodeId], {id: nodeId, label, origin, topologyId}); + } + state = state.set('selectedNodeId', nodeId); + if (topologyId !== state.get('currentTopologyId')) { + state = setTopology(state, topologyId); + state = state.update('nodes', nodes => nodes.clear()); + state = state.set('availableCanvasMetrics', makeList()); + } + + return state; +} + + export function rootReducer(state = initialState, action) { if (!action.type) { error('Payload missing a type!', action); @@ -193,7 +221,17 @@ export function rootReducer(state = initialState, action) { } case ActionTypes.CLICK_CLOSE_DETAILS: { - return closeNodeDetails(state, action.nodeId); + state = closeNodeDetails(state, action.nodeId); + const topCard = state.get('nodeDetails').last(); + if (!topCard) { + return state; + } + + return setSelectedNode(state, { + nodeId: topCard.id, + label: topCard.label, + topologyId: topCard.topologyId, + }); } case ActionTypes.CLICK_CLOSE_TERMINAL: { @@ -233,22 +271,7 @@ export function rootReducer(state = initialState, action) { } case ActionTypes.CLICK_RELATIVE: { - if (state.hasIn(['nodeDetails', action.nodeId])) { - // bring to front - const details = state.getIn(['nodeDetails', action.nodeId]); - state = state.deleteIn(['nodeDetails', action.nodeId]); - state = state.setIn(['nodeDetails', action.nodeId], details); - } else { - state = state.setIn(['nodeDetails', action.nodeId], - { - id: action.nodeId, - label: action.label, - origin: action.origin, - topologyId: action.topologyId - } - ); - } - return state; + return setSelectedNode(state, action); } case ActionTypes.CLICK_RESUME_UPDATE: { From 05cd10cfcba612fadb218f06d2665dc14313ec2e Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Thu, 13 Oct 2016 16:46:20 +0200 Subject: [PATCH 2/6] Revert "Current topo follows details panel!" This reverts commit 7a5e04f44f46b3fc94dc0f67b68b4633659b88a9. --- client/app/scripts/actions/app-actions.js | 8 +--- client/app/scripts/reducers/root.js | 57 +++++++---------------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js index 34203e885..eff78794b 100644 --- a/client/app/scripts/actions/app-actions.js +++ b/client/app/scripts/actions/app-actions.js @@ -286,7 +286,6 @@ export function clickRelative(nodeId, topologyId, label, origin) { topologyId }); updateRoute(getState); - resetUpdateBuffer(); const state = getState(); getNodeDetails( state.get('topologyUrlsById'), @@ -295,11 +294,6 @@ export function clickRelative(nodeId, topologyId, label, origin) { state.get('nodeDetails'), dispatch ); - getNodesDelta( - getCurrentTopologyUrl(state), - getActiveTopologyOptions(state), - dispatch - ); }; } @@ -467,7 +461,7 @@ export function hitEsc() { } else if (state.get('showingHelp')) { dispatch(hideHelp()); } else if (state.get('nodeDetails').last() && !controlPipe) { - dispatch({ type: ActionTypes.CLICK_CLOSE_DETAILS }); + dispatch({ type: ActionTypes.DESELECT_NODE }); updateRoute(getState); } }; diff --git a/client/app/scripts/reducers/root.js b/client/app/scripts/reducers/root.js index fc81a0802..09d6de922 100644 --- a/client/app/scripts/reducers/root.js +++ b/client/app/scripts/reducers/root.js @@ -69,7 +69,6 @@ export const initialState = makeMap({ exportingGraph: false }); - // adds ID field to topology (based on last part of URL path) and save urls in // map for easy lookup function processTopologies(state, nextTopologies) { @@ -88,14 +87,12 @@ function processTopologies(state, nextTopologies) { return state.mergeDeepIn(['topologies'], immNextTopologies); } - function setTopology(state, topologyId) { state = state.set('currentTopology', findTopologyById( state.get('topologies'), topologyId)); return state.set('currentTopologyId', topologyId); } - function setDefaultTopologyOptions(state, topologyList) { topologyList.forEach(topology => { let defaultOptions = makeOrderedMap(); @@ -116,7 +113,6 @@ function setDefaultTopologyOptions(state, topologyList) { return state; } - function closeNodeDetails(state, nodeId) { const nodeDetails = state.get('nodeDetails'); if (nodeDetails.size > 0) { @@ -132,7 +128,6 @@ function closeNodeDetails(state, nodeId) { return state; } - function closeAllNodeDetails(state) { while (state.get('nodeDetails').size) { state = closeNodeDetails(state); @@ -140,33 +135,10 @@ function closeAllNodeDetails(state) { return state; } - function resumeUpdate(state) { return state.set('updatePausedAt', null); } - -function setSelectedNode(state, {nodeId, label, origin, topologyId}) { - state = resumeUpdate(state); - if (state.hasIn(['nodeDetails', nodeId])) { - // bring to front - const details = state.getIn(['nodeDetails', nodeId]); - state = state.deleteIn(['nodeDetails', nodeId]); - state = state.setIn(['nodeDetails', nodeId], details); - } else { - state = state.setIn(['nodeDetails', nodeId], {id: nodeId, label, origin, topologyId}); - } - state = state.set('selectedNodeId', nodeId); - if (topologyId !== state.get('currentTopologyId')) { - state = setTopology(state, topologyId); - state = state.update('nodes', nodes => nodes.clear()); - state = state.set('availableCanvasMetrics', makeList()); - } - - return state; -} - - export function rootReducer(state = initialState, action) { if (!action.type) { error('Payload missing a type!', action); @@ -221,17 +193,7 @@ export function rootReducer(state = initialState, action) { } case ActionTypes.CLICK_CLOSE_DETAILS: { - state = closeNodeDetails(state, action.nodeId); - const topCard = state.get('nodeDetails').last(); - if (!topCard) { - return state; - } - - return setSelectedNode(state, { - nodeId: topCard.id, - label: topCard.label, - topologyId: topCard.topologyId, - }); + return closeNodeDetails(state, action.nodeId); } case ActionTypes.CLICK_CLOSE_TERMINAL: { @@ -271,7 +233,22 @@ export function rootReducer(state = initialState, action) { } case ActionTypes.CLICK_RELATIVE: { - return setSelectedNode(state, action); + if (state.hasIn(['nodeDetails', action.nodeId])) { + // bring to front + const details = state.getIn(['nodeDetails', action.nodeId]); + state = state.deleteIn(['nodeDetails', action.nodeId]); + state = state.setIn(['nodeDetails', action.nodeId], details); + } else { + state = state.setIn(['nodeDetails', action.nodeId], + { + id: action.nodeId, + label: action.label, + origin: action.origin, + topologyId: action.topologyId + } + ); + } + return state; } case ActionTypes.CLICK_RESUME_UPDATE: { From dc61317ba5225c7976dc015fc4187c00abe1f094 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Mon, 17 Oct 2016 17:11:38 +0200 Subject: [PATCH 3/6] Bring shapes into the details panel and use them for view-in-topo (click on shape/title to view it in its topo) --- .../app/scripts/charts/node-shape-circle.js | 6 +- client/app/scripts/charts/node-shape-hex.js | 6 +- .../app/scripts/charts/node-shape-square.js | 6 +- client/app/scripts/charts/node-shape-stack.js | 8 +- client/app/scripts/charts/node.js | 4 +- client/app/scripts/components/node-details.js | 67 +++++-- client/app/styles/main.less | 184 +++++++++++------- 7 files changed, 180 insertions(+), 101 deletions(-) diff --git a/client/app/scripts/charts/node-shape-circle.js b/client/app/scripts/charts/node-shape-circle.js index dcf2327eb..8587f720e 100644 --- a/client/app/scripts/charts/node-shape-circle.js +++ b/client/app/scripts/charts/node-shape-circle.js @@ -4,11 +4,11 @@ import {getMetricValue, getMetricColor, getClipPathDefinition} from '../utils/me import {CANVAS_METRIC_FONT_SIZE} from '../constants/styles.js'; -export default function NodeShapeCircle({id, highlighted, size, color, metric}) { +export default function NodeShapeCircle({id, highlighted, size, color, metric, wireframe}) { const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric }); + const className = classNames('shape', { metrics: hasMetric, wireframe }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -21,7 +21,7 @@ export default function NodeShapeCircle({id, highlighted, size, color, metric}) clipPath={`url(#${clipId})`} />} {highlighted && hasMetric ? {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-hex.js b/client/app/scripts/charts/node-shape-hex.js index d7045c9ab..2e1a8c917 100644 --- a/client/app/scripts/charts/node-shape-hex.js +++ b/client/app/scripts/charts/node-shape-hex.js @@ -30,7 +30,7 @@ function getPoints(h) { } -export default function NodeShapeHex({id, highlighted, size, color, metric}) { +export default function NodeShapeHex({id, highlighted, size, color, metric, wireframe}) { const pathProps = v => ({ d: getPoints(size * v * 2), transform: `rotate(90) translate(-${size * getWidth(v)}, -${size * v})` @@ -42,7 +42,7 @@ export default function NodeShapeHex({id, highlighted, size, color, metric}) { const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric }); + const className = classNames('shape', { metrics: hasMetric, wireframe }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -58,7 +58,7 @@ export default function NodeShapeHex({id, highlighted, size, color, metric}) { {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-square.js b/client/app/scripts/charts/node-shape-square.js index d4cd116bc..345877bfd 100644 --- a/client/app/scripts/charts/node-shape-square.js +++ b/client/app/scripts/charts/node-shape-square.js @@ -5,7 +5,7 @@ import {CANVAS_METRIC_FONT_SIZE} from '../constants/styles.js'; export default function NodeShapeSquare({ - id, highlighted, size, color, rx = 0, ry = 0, metric + id, highlighted, size, color, rx = 0, ry = 0, metric, wireframe }) { const rectProps = (scale, radiusScale) => ({ width: scale * size * 2, @@ -19,7 +19,7 @@ export default function NodeShapeSquare({ const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric }); + const className = classNames('shape', { metrics: hasMetric, wireframe }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -34,7 +34,7 @@ export default function NodeShapeSquare({ {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-stack.js b/client/app/scripts/charts/node-shape-stack.js index 3d691888c..e566460d3 100644 --- a/client/app/scripts/charts/node-shape-stack.js +++ b/client/app/scripts/charts/node-shape-stack.js @@ -14,15 +14,13 @@ export default function NodeShapeStack(props) { - + - - - - + + ); } diff --git a/client/app/scripts/charts/node.js b/client/app/scripts/charts/node.js index 63511fdfa..bf354d1d0 100644 --- a/client/app/scripts/charts/node.js +++ b/client/app/scripts/charts/node.js @@ -36,7 +36,7 @@ const nodeShapes = { cloud: NodeShapeCloud }; -function getNodeShape({ shape, stack }) { +export function getNodeShape({ shape, stack }) { const nodeShape = nodeShapes[shape]; if (!nodeShape) { throw new Error(`Unknown shape: ${shape}!`); @@ -142,7 +142,7 @@ class Node extends React.Component { } - +
- {showSwitchTopology && }
@@ -138,30 +149,60 @@ export class NodeDetails extends React.Component { const { details, nodeControlStatus, nodeMatches = makeMap() } = this.props; const showControls = details.controls && details.controls.length > 0; const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo); + const controlsColor = brightenColor(nodeColor); const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {}; const tools = this.renderTools(); const styles = { controls: { - backgroundColor: brightenColor(nodeColor) + backgroundColor: controlsColor, }, header: { backgroundColor: nodeColor } }; + const NodeShapeType = getNodeShape(details); + const shapeMarginTop = details.stack ? -20 : -27; + const topologyTitle = `View ${this.props.label} in ${this.props.topologyId}`; + const showSwitchTopology = this.props.nodeId !== this.props.selectedNodeId; + const highlighted = this.state.highlighted; + + const commonProps = { + onClick: this.handleShowTopologyForNode, + onMouseEnter: showSwitchTopology && this.handleNodeMouseEnter, + onMouseLeave: showSwitchTopology && this.handleNodeMouseLeave, + style: { + cursor: showSwitchTopology && 'pointer', + }, + }; + const headerClassName = classnames('node-details-header', { + 'show-switch-topology': showSwitchTopology, + }); return (
{tools} -
+
-

+ + + {showSwitchTopology && {topologyTitle}} + + + +

-
- {details.parents && } -
+ {details.parents && }
diff --git a/client/app/styles/main.less b/client/app/styles/main.less index ba220398e..f14911ea2 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -482,77 +482,105 @@ h2 { } } } - - .stack .shape .highlighted { - display: none; - } - - .stack .onlyHighlight .shape { - .border { display: none; } - .shadow { display: none; } - .node { display: none; } - .highlighted { display: inline; } - } - - .stack .shape .metric-fill { - display: none; - } - - .shape { - transform: scale(1); - cursor: pointer; - - /* cloud paths have stroke-width set dynamically */ - &:not(.shape-cloud) .border { - stroke-width: @node-border-stroke-width; - fill: @background-color; - transition: stroke-opacity 0.333s @base-ease, fill 0.333s @base-ease; - stroke-opacity: 1; - } - - &.metrics .border { - fill: @background-lighter-color; - stroke-opacity: 0.3; - } - - .metric-fill { - stroke: none; - fill: #A0BE7E; - fill-opacity: 0.7; - } - - .shadow { - stroke: none; - fill: @background-lighter-color; - } - - .node { - fill: @text-color; - stroke: @background-lighter-color; - stroke-width: 2px; - } - - text { - font-size: 12px; - dominant-baseline: middle; - text-anchor: middle; - } - - .highlighted { - fill: @weave-blue; - fill-opacity: @node-highlight-fill-opacity; - stroke: @weave-blue; - stroke-width: @node-highlight-stroke-width; - stroke-opacity: @node-highlight-stroke-opacity; - } - } - - .stack .shape .border { - stroke-width: @node-border-stroke-width - 0.5; - } - } +// +// stacks and shapes!!! +// + +.stack .shape .highlighted { + display: none; +} + +.stack .onlyHighlight .shape { + .border { display: none; } + .shadow { display: none; } + .node { display: none; } + .highlighted { display: inline; } +} + +.stack .shape .metric-fill { + display: none; +} + +.shape { + transform: scale(1); + + /* cloud paths have stroke-width set dynamically */ + &:not(.shape-cloud) .border { + stroke-width: @node-border-stroke-width; + fill: @background-color; + transition: stroke-opacity 0.333s @base-ease, fill 0.333s @base-ease; + stroke-opacity: 1; + } + + &.metrics .border { + fill: @background-lighter-color; + stroke-opacity: 0.3; + } + + .metric-fill { + stroke: none; + fill: #A0BE7E; + fill-opacity: 0.7; + } + + .shadow { + stroke: none; + fill: @background-lighter-color; + } + + text { + font-size: 12px; + dominant-baseline: middle; + text-anchor: middle; + } + + .highlighted { + fill: @weave-blue; + fill-opacity: @node-highlight-fill-opacity; + stroke: @weave-blue; + stroke-width: @node-highlight-stroke-width; + stroke-opacity: @node-highlight-stroke-opacity; + } +} + +.shape.wireframe { + .shadow, .border { + fill-opacity: 0; + } + + .border { + stroke: white; + } + + .node { + fill: white; + stroke: white; + // fill-opacity: 0.9; + // stroke-opacity: 0.9; + } +} + +.noNode .wireframe .node { + display: none; +} + +.stack .shape .border { + stroke-width: @node-border-stroke-width - 0.5; +} + +.shape:not(.wireframe) .node { + fill: @text-color; + stroke: @background-lighter-color; + stroke-width: 2px; +} + + +// ---- + + + .matched-results { text-align: center; @@ -643,17 +671,28 @@ h2 { &-header { .colorable; + &.show-switch-topology &-label { + .btn-opacity; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + &-wrapper { - padding: 36px 36px 8px 36px; + padding: 36px 36px 8px 24px; } &-label { color: white; - margin: 0; - width: 348px; + margin: 0 0 0 64px; padding-top: 0; } + svg { + float: left; + } + .details-tools { position: absolute; top: 16px; @@ -667,6 +706,7 @@ h2 { } &-relatives { + margin-left: 64px; margin-top: 4px; font-size: 120%; color: @white; From 30bca04e5d8814c6ec02f071298f58f76df520d0 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Thu, 3 Nov 2016 10:57:34 +0100 Subject: [PATCH 4/6] Revert "Bring shapes into the details panel and use them for view-in-topo" This reverts commit 1bf54130ffb4e6c83f0bd816f7a037f819d561ac. --- .../app/scripts/charts/node-shape-circle.js | 6 +- client/app/scripts/charts/node-shape-hex.js | 6 +- .../app/scripts/charts/node-shape-square.js | 6 +- client/app/scripts/charts/node-shape-stack.js | 8 +- client/app/scripts/charts/node.js | 4 +- client/app/scripts/components/node-details.js | 67 ++------ client/app/styles/main.less | 162 +++++++----------- 7 files changed, 90 insertions(+), 169 deletions(-) diff --git a/client/app/scripts/charts/node-shape-circle.js b/client/app/scripts/charts/node-shape-circle.js index 8587f720e..dcf2327eb 100644 --- a/client/app/scripts/charts/node-shape-circle.js +++ b/client/app/scripts/charts/node-shape-circle.js @@ -4,11 +4,11 @@ import {getMetricValue, getMetricColor, getClipPathDefinition} from '../utils/me import {CANVAS_METRIC_FONT_SIZE} from '../constants/styles.js'; -export default function NodeShapeCircle({id, highlighted, size, color, metric, wireframe}) { +export default function NodeShapeCircle({id, highlighted, size, color, metric}) { const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric, wireframe }); + const className = classNames('shape', { metrics: hasMetric }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -21,7 +21,7 @@ export default function NodeShapeCircle({id, highlighted, size, color, metric, w clipPath={`url(#${clipId})`} />} {highlighted && hasMetric ? {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-hex.js b/client/app/scripts/charts/node-shape-hex.js index 2e1a8c917..d7045c9ab 100644 --- a/client/app/scripts/charts/node-shape-hex.js +++ b/client/app/scripts/charts/node-shape-hex.js @@ -30,7 +30,7 @@ function getPoints(h) { } -export default function NodeShapeHex({id, highlighted, size, color, metric, wireframe}) { +export default function NodeShapeHex({id, highlighted, size, color, metric}) { const pathProps = v => ({ d: getPoints(size * v * 2), transform: `rotate(90) translate(-${size * getWidth(v)}, -${size * v})` @@ -42,7 +42,7 @@ export default function NodeShapeHex({id, highlighted, size, color, metric, wire const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric, wireframe }); + const className = classNames('shape', { metrics: hasMetric }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -58,7 +58,7 @@ export default function NodeShapeHex({id, highlighted, size, color, metric, wire {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-square.js b/client/app/scripts/charts/node-shape-square.js index 345877bfd..d4cd116bc 100644 --- a/client/app/scripts/charts/node-shape-square.js +++ b/client/app/scripts/charts/node-shape-square.js @@ -5,7 +5,7 @@ import {CANVAS_METRIC_FONT_SIZE} from '../constants/styles.js'; export default function NodeShapeSquare({ - id, highlighted, size, color, rx = 0, ry = 0, metric, wireframe + id, highlighted, size, color, rx = 0, ry = 0, metric }) { const rectProps = (scale, radiusScale) => ({ width: scale * size * 2, @@ -19,7 +19,7 @@ export default function NodeShapeSquare({ const clipId = `mask-${id}`; const {height, hasMetric, formattedValue} = getMetricValue(metric, size); const metricStyle = { fill: getMetricColor(metric) }; - const className = classNames('shape', { metrics: hasMetric, wireframe }); + const className = classNames('shape', { metrics: hasMetric }); const fontSize = size * CANVAS_METRIC_FONT_SIZE; return ( @@ -34,7 +34,7 @@ export default function NodeShapeSquare({ {formattedValue} : - } + } ); } diff --git a/client/app/scripts/charts/node-shape-stack.js b/client/app/scripts/charts/node-shape-stack.js index e566460d3..3d691888c 100644 --- a/client/app/scripts/charts/node-shape-stack.js +++ b/client/app/scripts/charts/node-shape-stack.js @@ -14,13 +14,15 @@ export default function NodeShapeStack(props) { - + - + + + + - ); } diff --git a/client/app/scripts/charts/node.js b/client/app/scripts/charts/node.js index bf354d1d0..63511fdfa 100644 --- a/client/app/scripts/charts/node.js +++ b/client/app/scripts/charts/node.js @@ -36,7 +36,7 @@ const nodeShapes = { cloud: NodeShapeCloud }; -export function getNodeShape({ shape, stack }) { +function getNodeShape({ shape, stack }) { const nodeShape = nodeShapes[shape]; if (!nodeShape) { throw new Error(`Unknown shape: ${shape}!`); @@ -142,7 +142,7 @@ class Node extends React.Component {
} - +
+ {showSwitchTopology && }
@@ -149,60 +138,30 @@ export class NodeDetails extends React.Component { const { details, nodeControlStatus, nodeMatches = makeMap() } = this.props; const showControls = details.controls && details.controls.length > 0; const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo); - const controlsColor = brightenColor(nodeColor); const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {}; const tools = this.renderTools(); const styles = { controls: { - backgroundColor: controlsColor, + backgroundColor: brightenColor(nodeColor) }, header: { backgroundColor: nodeColor } }; - const NodeShapeType = getNodeShape(details); - const shapeMarginTop = details.stack ? -20 : -27; - const topologyTitle = `View ${this.props.label} in ${this.props.topologyId}`; - const showSwitchTopology = this.props.nodeId !== this.props.selectedNodeId; - const highlighted = this.state.highlighted; - - const commonProps = { - onClick: this.handleShowTopologyForNode, - onMouseEnter: showSwitchTopology && this.handleNodeMouseEnter, - onMouseLeave: showSwitchTopology && this.handleNodeMouseLeave, - style: { - cursor: showSwitchTopology && 'pointer', - }, - }; - const headerClassName = classnames('node-details-header', { - 'show-switch-topology': showSwitchTopology, - }); return (
{tools} -
+
- - - {showSwitchTopology && {topologyTitle}} - - - -

+

- {details.parents && } +
+ {details.parents && } +
diff --git a/client/app/styles/main.less b/client/app/styles/main.less index f14911ea2..ba220398e 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -482,105 +482,77 @@ h2 { } } } -} -// -// stacks and shapes!!! -// - -.stack .shape .highlighted { - display: none; -} - -.stack .onlyHighlight .shape { - .border { display: none; } - .shadow { display: none; } - .node { display: none; } - .highlighted { display: inline; } -} - -.stack .shape .metric-fill { - display: none; -} - -.shape { - transform: scale(1); - - /* cloud paths have stroke-width set dynamically */ - &:not(.shape-cloud) .border { - stroke-width: @node-border-stroke-width; - fill: @background-color; - transition: stroke-opacity 0.333s @base-ease, fill 0.333s @base-ease; - stroke-opacity: 1; + .stack .shape .highlighted { + display: none; } - &.metrics .border { - fill: @background-lighter-color; - stroke-opacity: 0.3; + .stack .onlyHighlight .shape { + .border { display: none; } + .shadow { display: none; } + .node { display: none; } + .highlighted { display: inline; } } - .metric-fill { - stroke: none; - fill: #A0BE7E; - fill-opacity: 0.7; + .stack .shape .metric-fill { + display: none; } - .shadow { - stroke: none; - fill: @background-lighter-color; + .shape { + transform: scale(1); + cursor: pointer; + + /* cloud paths have stroke-width set dynamically */ + &:not(.shape-cloud) .border { + stroke-width: @node-border-stroke-width; + fill: @background-color; + transition: stroke-opacity 0.333s @base-ease, fill 0.333s @base-ease; + stroke-opacity: 1; + } + + &.metrics .border { + fill: @background-lighter-color; + stroke-opacity: 0.3; + } + + .metric-fill { + stroke: none; + fill: #A0BE7E; + fill-opacity: 0.7; + } + + .shadow { + stroke: none; + fill: @background-lighter-color; + } + + .node { + fill: @text-color; + stroke: @background-lighter-color; + stroke-width: 2px; + } + + text { + font-size: 12px; + dominant-baseline: middle; + text-anchor: middle; + } + + .highlighted { + fill: @weave-blue; + fill-opacity: @node-highlight-fill-opacity; + stroke: @weave-blue; + stroke-width: @node-highlight-stroke-width; + stroke-opacity: @node-highlight-stroke-opacity; + } } - text { - font-size: 12px; - dominant-baseline: middle; - text-anchor: middle; + .stack .shape .border { + stroke-width: @node-border-stroke-width - 0.5; } - .highlighted { - fill: @weave-blue; - fill-opacity: @node-highlight-fill-opacity; - stroke: @weave-blue; - stroke-width: @node-highlight-stroke-width; - stroke-opacity: @node-highlight-stroke-opacity; - } } -.shape.wireframe { - .shadow, .border { - fill-opacity: 0; - } - - .border { - stroke: white; - } - - .node { - fill: white; - stroke: white; - // fill-opacity: 0.9; - // stroke-opacity: 0.9; - } -} - -.noNode .wireframe .node { - display: none; -} - -.stack .shape .border { - stroke-width: @node-border-stroke-width - 0.5; -} - -.shape:not(.wireframe) .node { - fill: @text-color; - stroke: @background-lighter-color; - stroke-width: 2px; -} - - -// ---- - - - .matched-results { text-align: center; @@ -671,28 +643,17 @@ h2 { &-header { .colorable; - &.show-switch-topology &-label { - .btn-opacity; - opacity: 0.8; - &:hover { - opacity: 1; - } - } - &-wrapper { - padding: 36px 36px 8px 24px; + padding: 36px 36px 8px 36px; } &-label { color: white; - margin: 0 0 0 64px; + margin: 0; + width: 348px; padding-top: 0; } - svg { - float: left; - } - .details-tools { position: absolute; top: 16px; @@ -706,7 +667,6 @@ h2 { } &-relatives { - margin-left: 64px; margin-top: 4px; font-size: 120%; color: @white; From 4da2a826028278156e1e0185d42868f4d95e245d Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Thu, 3 Nov 2016 13:11:54 +0100 Subject: [PATCH 5/6] Add label to show-in-topo button --- client/app/scripts/components/node-details.js | 4 +++- client/app/styles/main.less | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/client/app/scripts/components/node-details.js b/client/app/scripts/components/node-details.js index 56a2c20ee..156f24af8 100644 --- a/client/app/scripts/components/node-details.js +++ b/client/app/scripts/components/node-details.js @@ -54,7 +54,9 @@ export class NodeDetails extends React.Component {
{showSwitchTopology && } + className="fa fa-long-arrow-left" onClick={this.handleShowTopologyForNode}> + View in {this.props.topologyId} + }
diff --git a/client/app/styles/main.less b/client/app/styles/main.less index ba220398e..e20c6903b 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -619,7 +619,7 @@ h2 { top: 6px; right: 8px; - span { + > span { .btn-opacity; padding: 4px 5px; margin-left: 2px; @@ -627,7 +627,13 @@ h2 { color: @white; cursor: pointer; border: 1px solid rgba(255, 255, 255, 0); - border-radius: 10%; + border-radius: 4px; + + span { + font-family: @base-font; + font-size: 0.9em; + margin-left: 4px; + } &:hover { border-color: rgba(255, 255, 255, 0.6); From fe2bfe2ffad9c7a1cb1370406273f61c6214bf17 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Fri, 4 Nov 2016 10:07:08 +0100 Subject: [PATCH 6/6] Use the familiar ALLCAPS for topo name in show-in-topo button --- client/app/scripts/components/node-details.js | 2 +- client/app/styles/main.less | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/app/scripts/components/node-details.js b/client/app/scripts/components/node-details.js index 156f24af8..4e7f7ee6a 100644 --- a/client/app/scripts/components/node-details.js +++ b/client/app/scripts/components/node-details.js @@ -55,7 +55,7 @@ export class NodeDetails extends React.Component {
{showSwitchTopology && - View in {this.props.topologyId} + Show in {this.props.topologyId.replace(/-/g, ' ')} }
diff --git a/client/app/styles/main.less b/client/app/styles/main.less index e20c6903b..52ae2e67b 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -633,6 +633,12 @@ h2 { font-family: @base-font; font-size: 0.9em; margin-left: 4px; + + span { + font-size: 1em; + margin-left: 0; + text-transform: uppercase; + } } &:hover {