diff --git a/frontend/src/state/selectors.js b/frontend/src/state/selectors.js
index 3b2d0c87..32622655 100644
--- a/frontend/src/state/selectors.js
+++ b/frontend/src/state/selectors.js
@@ -126,17 +126,8 @@ const metricByInterval = (data = [], {
const q1 = statistics.quantile(data, 0.25);
const median = statistics.median(data);
const q3 = statistics.quantile(data, 0.75);
-
- const iqr = q3-q1;
- const outlierMultiplier = 1.5;
- let max = statistics.max(data);
- if(max < q3 + iqr*outlierMultiplier) {
- max = q3;
- }
- let min = statistics.min(data);
- if(min > q1 - iqr*outlierMultiplier){
- min = q3;
- }
+ const max = statistics.max(data);
+ const min = statistics.min(data);
return {
start: sample.start.valueOf(),
diff --git a/ui/src/components/topology/big-data.js b/ui/src/components/topology/big-data.js
new file mode 100644
index 00000000..a68f696b
--- /dev/null
+++ b/ui/src/components/topology/big-data.js
@@ -0,0 +1,2 @@
+/* eslint-disable */
+module.exports = [{"uuid":"primary-consul","id":"consul","name":"Consul","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":"primary-nginx","id":"nginx","name":"Nginx","instances":1,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":[21393,688632,3802,211054,514555,823837,728066,626040,39531,338897,870461,306578,557611,24764,866947,521183,920500,673424,752876,125936,195071,101278,766252,272044,579947,211151,712793,831906,897694,261116,246274,380300,299558,303216,974334,127763,437955,143274,634968,431609,282549,262582,418482,284724,798952,308763,111726],"datacentres":1,"healthy":true},{"uuid":"primary-mongodb","id":"mongodb","name":"MongoDB","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":21393,"id":"accountservice","name":"AccountService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":688632,"id":"addressservice","name":"AddressService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":3802,"id":"bloomreachservice","name":"BloomreachService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":211054,"id":"cartservice","name":"CartService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":514555,"id":"extra service reported by containerpilot: cartservice-https","name":"Extra service reported by ContainerPilot: CartService-HTTPS","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":823837,"id":"cctokenizationclientservice","name":"CCTokenizationClientService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":728066,"id":"checkoutservice","name":"CheckoutService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":626040,"id":"colorswatchservice","name":"ColorSwatchService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":39531,"id":"emailmarketingservice","name":"EmailMarketingService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":338897,"id":"favoriteservice","name":"FavoriteService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":870461,"id":"findinstoreservice","name":"FindInStoreService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":306578,"id":"fitpredictorservice","name":"FitpredictorService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":557611,"id":"hidefromcatalogservice","name":"HidefromcatalogService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":24764,"id":"internationalcheckoutservice","name":"InternationalCheckoutService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":866947,"id":"internationalposervice","name":"InternationalPOService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":521183,"id":"internationalshippingservice","name":"InternationalShippingService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":920500,"id":"inventoryservice","name":"InventoryService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":673424,"id":"localizationservice","name":"LocalizationService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":752876,"id":"moreaccountservice","name":"MoreAccountService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":125936,"id":"navigationservice","name":"NavigationService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":195071,"id":"ordercreationjob","name":"OrderCreationJob","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":101278,"id":"orderservice","name":"OrderService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":766252,"id":"orderservice","name":"OrderService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":272044,"id":"paymentmethodservice","name":"PaymentMethodService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":579947,"id":"paymentservice","name":"PaymentService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":211151,"id":"paymentservice","name":"PaymentService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":712793,"id":"priceservice","name":"PriceService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":831906,"id":"privatesaleservice","name":"PrivatesaleService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":897694,"id":"productarrayservice","name":"ProductArrayService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":261116,"id":"productdetailservice","name":"ProductDetailService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":246274,"id":"productservice","name":"ProductService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":380300,"id":"profileservice","name":"ProfileService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":299558,"id":"promoservice","name":"PromoService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":303216,"id":"promotionservice","name":"PromotionService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":974334,"id":"questionanswerservice","name":"QuestionanswerService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":127763,"id":"redbaloonservice","name":"RedBaloonService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":437955,"id":"extra service reported by containerpilot: redbaloonservice-https","name":"Extra service reported by ContainerPilot: RedBaloonService-HTTPS","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":143274,"id":"reviewsservice","name":"ReviewsService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":634968,"id":"searchfacetsservice","name":"SearchFacetsService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":431609,"id":"searchindexservice","name":"SearchIndexService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":282549,"id":"shoprunnerservice","name":"ShopRunnerService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":262582,"id":"taxservice","name":"TaxService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":418482,"id":"toggleservice","name":"ToggleService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":284724,"id":"useraccountservice","name":"UserAccountService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":798952,"id":"userauthenticationservice","name":"UserAuthenticationService","instances":4,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true},{"uuid":308763,"id":"waitlistoverlayservice","name":"WaitlistOverlayService","instances":5,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"connections":["primary-mongodb"],"datacentres":1,"healthy":true},{"uuid":111726,"id":"waitlistservice","name":"WaitlistService","instances":3,"project":"9fcb374d-a267-4c2a-9d9c-ba469b804639","metrics":[{"name":"CPU","value":"50%"},{"name":"Memory","value":"20%"},{"name":"Network","value":"2.9Kb/sec"}],"datacentres":1,"healthy":true}]
diff --git a/ui/src/components/topology/graph-link/arrow.js b/ui/src/components/topology/graph-link/arrow.js
new file mode 100644
index 00000000..24e3a951
--- /dev/null
+++ b/ui/src/components/topology/graph-link/arrow.js
@@ -0,0 +1,53 @@
+import { Baseline } from '../../../shared/composers';
+import React from 'react';
+import {
+ GraphLinkCircle,
+ GraphLinkArrowLine
+} from './shapes';
+
+const GraphLinkArrow = ({
+ data,
+ index
+}) => {
+
+ const {
+ targetPosition,
+ arrowAngle
+ } = data;
+
+ return (
+
+
+
+
+
+ );
+};
+
+GraphLinkArrow.propTypes = {
+ data: React.PropTypes.object.isRequired,
+ index: React.PropTypes.number
+};
+
+export default Baseline(
+ GraphLinkArrow
+);
diff --git a/ui/src/components/topology/graph-link/functions.js b/ui/src/components/topology/graph-link/functions.js
new file mode 100644
index 00000000..73c2e3cf
--- /dev/null
+++ b/ui/src/components/topology/graph-link/functions.js
@@ -0,0 +1,100 @@
+import Constants from '../constants';
+
+const getAngleFromPoints = (source, target) => {
+
+ const lineAngle = Math.atan2(target.y-source.y, target.x - source.x);
+ const lineAngleDeg = lineAngle*180/Math.PI;
+ const zeroToThreeSixty = lineAngleDeg < 0 ? 360 + lineAngleDeg : lineAngleDeg;
+
+ return zeroToThreeSixty;
+};
+
+const getPosition = (angle, positions, position, noCorners=false) => {
+ const positionIndex = noCorners ?
+ Math.round(angle/90)*2 : Math.round(angle/45);
+ const offsetPosition = positions[positionIndex];
+ return {
+ id: offsetPosition.id,
+ x: position.x + offsetPosition.x,
+ y: position.y + offsetPosition.y
+ };
+};
+
+const getPositions = (rect, halfCorner=0) => ([{
+ id: 'r',
+ x: rect.right,
+ y: 0
+}, {
+ id: 'br',
+ x: rect.right - halfCorner,
+ y: rect.bottom - halfCorner
+}, {
+ id: 'b',
+ x: 0,
+ y: rect.bottom
+}, {
+ id: 'bl',
+ x: rect.left + halfCorner,
+ y: rect.bottom - halfCorner
+}, {
+ id: 'l',
+ x: rect.left,
+ y: 0
+}, {
+ id: 'tl',
+ x: rect.left + halfCorner,
+ y: rect.top + halfCorner
+}, {
+ id: 't',
+ x: 0,
+ y: rect.top
+}, {
+ id: 'tr',
+ x: rect.right- halfCorner,
+ y: rect.top + halfCorner
+},{
+ id: 'r',
+ x: rect.right,
+ y: 0
+}]);
+
+const getRect = (data) => {
+ return data.children ?
+ Constants.nodeRectWithChildren :
+ Constants.nodeRect;
+};
+
+const calculateLineLayout = ({
+ source,
+ target
+}) => {
+ // actually, this will need to be got dynamically, in case them things are different sizes
+ // yeah right, now you'll get to do exactly that
+
+ const sourceRect = getRect(source);
+ const targetRect= getRect(target);
+
+ const halfCorner = 2;
+
+ const sourcePositions = getPositions(sourceRect, halfCorner);
+ const sourceAngle = getAngleFromPoints(source, target);
+ const sourcePosition = getPosition(sourceAngle, sourcePositions, source);
+
+ const targetPositions = getPositions(targetRect, halfCorner);
+ const targetAngle = getAngleFromPoints(target, sourcePosition);
+ const targetPosition = getPosition(targetAngle, targetPositions, target); //, true);
+
+ const arrowAngle = getAngleFromPoints(sourcePosition, targetPosition);
+
+ return {
+ source,
+ target,
+ sourcePosition,
+ targetPosition,
+ arrowAngle
+ };
+};
+
+export {
+ calculateLineLayout
+};
diff --git a/ui/src/components/topology/graph-link/index.js b/ui/src/components/topology/graph-link/index.js
index 86e4e86a..e8f5702a 100644
--- a/ui/src/components/topology/graph-link/index.js
+++ b/ui/src/components/topology/graph-link/index.js
@@ -1,143 +1,32 @@
import { Baseline } from '../../../shared/composers';
-import Constants from '../constants';
import React from 'react';
import {
- GraphLinkLine,
- GraphLinkCircle,
- GraphLinkArrow
+ GraphLinkLine
} from './shapes';
-const getAngleFromPoints = (source, target) => {
-
- const lineAngle = Math.atan2(target.y-source.y, target.x - source.x);
- const lineAngleDeg = lineAngle*180/Math.PI;
- const zeroToThreeSixty = lineAngleDeg < 0 ? 360 + lineAngleDeg : lineAngleDeg;
-
- return zeroToThreeSixty;
-};
-
-const getPosition = (angle, positions, position, noCorners=false) => {
- const positionIndex = noCorners ?
- Math.round(angle/90)*2 : Math.round(angle/45);
- const offsetPosition = positions[positionIndex];
- return {
- id: offsetPosition.id,
- x: position.x + offsetPosition.x,
- y: position.y + offsetPosition.y
- };
-};
-
-const getPositions = (rect, halfCorner=0) => ([{
- id: 'r',
- x: rect.right,
- y: 0
-}, {
- id: 'br',
- x: rect.right - halfCorner,
- y: rect.bottom - halfCorner
-}, {
- id: 'b',
- x: 0,
- y: rect.bottom
-}, {
- id: 'bl',
- x: rect.left + halfCorner,
- y: rect.bottom - halfCorner
-}, {
- id: 'l',
- x: rect.left,
- y: 0
-}, {
- id: 'tl',
- x: rect.left + halfCorner,
- y: rect.top + halfCorner
-}, {
- id: 't',
- x: 0,
- y: rect.top
-}, {
- id: 'tr',
- x: rect.right- halfCorner,
- y: rect.top + halfCorner
-},{
- id: 'r',
- x: rect.right,
- y: 0
-}]);
-
-const getRect = (data) => {
- return data.children ?
- Constants.nodeRectWithChildren :
- Constants.nodeRect;
-};
-
const GraphLink = ({
data,
index
}) => {
const {
- source,
- target
+ sourcePosition,
+ targetPosition
} = data;
- // actually, this will need to be got dynamically, in case them things are different sizes
- // yeah right, now you'll get to do exactly that
-
- const sourceRect = getRect(source);
- const targetRect= getRect(target);
-
- const halfCorner = 2;
-
- const sourcePositions = getPositions(sourceRect, halfCorner);
- const sourceAngle = getAngleFromPoints(source, target);
- const sourcePosition = getPosition(sourceAngle, sourcePositions, source);
-
- const targetPositions = getPositions(targetRect, halfCorner);
- const targetAngle = getAngleFromPoints(target, sourcePosition);
- const targetPosition = getPosition(targetAngle, targetPositions, target); //, true);
-
- const arrowAngle = getAngleFromPoints(sourcePosition, targetPosition);
-
return (
-
-
-
-
-
-
-
-
+
);
};
GraphLink.propTypes = {
data: React.PropTypes.object.isRequired,
- index: React.PropTypes.number.isRequired
+ index: React.PropTypes.number
};
export default Baseline(
diff --git a/ui/src/components/topology/graph-link/shapes.js b/ui/src/components/topology/graph-link/shapes.js
index c92f3abb..95960f1f 100644
--- a/ui/src/components/topology/graph-link/shapes.js
+++ b/ui/src/components/topology/graph-link/shapes.js
@@ -12,7 +12,7 @@ export const GraphLinkCircle = styled.circle`
stroke-width: 1.5;
`;
-export const GraphLinkArrow = styled.line`
+export const GraphLinkArrowLine = styled.line`
stroke: ${colors.base.white};
stroke-width: 2;
stroke-linecap: round;
diff --git a/ui/src/components/topology/graph-node/index.js b/ui/src/components/topology/graph-node/index.js
index ed2061cd..2c406867 100644
--- a/ui/src/components/topology/graph-node/index.js
+++ b/ui/src/components/topology/graph-node/index.js
@@ -67,7 +67,7 @@ const GraphNode = ({
const onStart = (evt) => {
evt.preventDefault();
- onDragStart(evt, data.id);
+ onDragStart(evt, data.uuid);
};
const nodeRectEvents = connected ? {
diff --git a/ui/src/components/topology/graph-simulation.js b/ui/src/components/topology/graph-simulation.js
index 2b3957df..bdc8e601 100644
--- a/ui/src/components/topology/graph-simulation.js
+++ b/ui/src/components/topology/graph-simulation.js
@@ -14,6 +14,16 @@ const rectRadius = (size) => {
return Math.round(hypotenuse(width, height)/2);
};
+const forcePlayAnimation = (simulation, animationTicks) => {
+ const n = Math.ceil(
+ Math.log(
+ simulation.alphaMin()) / Math.log(
+ 1 - simulation.alphaDecay())) - animationTicks;
+ for (var i = 0; i < n; ++i) {
+ simulation.tick();
+ }
+};
+
const createLinks = (services) =>
services.reduce((acc, service, index) =>
service.connections ?
@@ -28,13 +38,12 @@ const createLinks = (services) =>
const createSimulation = (
services,
svgSize,
- onTick,
- onEnd
+ animationTicks = 0
) => {
// This is not going to work given that as well as the d3 layout stuff, other things might be at play too
// We should pass two objects to the components - one for positioning and one for data
const nodes = services.map((service, index) => ({
- id: service.uuid,
+ uuid: service.uuid,
index: index
}));
@@ -47,15 +56,17 @@ const createSimulation = (
const nodeRadius = rectRadius(Constants.nodeSizeWithChildren);
+ const simulation = forceSimulation(nodes)
+ .force('link', forceLink(links).id(d => d.uuid))
+ .force('collide', forceCollide(nodeRadius))
+ .force('center', forceCenter(width/2, height/2));
+
+ forcePlayAnimation(simulation, animationTicks);
+
return ({
- simulation: forceSimulation(nodes)
- .force('link', forceLink(links).id(d => d.id))
- .force('collide', forceCollide(nodeRadius))
- .force('center', forceCenter(width/2, height/2))
- .on('tick', onTick)
- .on('end', onEnd),
- nodes: nodes,
- links: links
+ nodes,
+ links,
+ simulation
});
};
diff --git a/ui/src/components/topology/story-helper.js b/ui/src/components/topology/story-helper.js
index b6e4f0b9..04bed77d 100644
--- a/ui/src/components/topology/story-helper.js
+++ b/ui/src/components/topology/story-helper.js
@@ -4,7 +4,7 @@ import { Baseline } from '../../shared/composers';
import Input from '../form/input';
import Select from '../form/select';
import { TopologyGraph } from './';
-import data from './data';
+import data from './wp-data';
import React from 'react';
const StyledForm = styled.form`
diff --git a/ui/src/components/topology/story.js b/ui/src/components/topology/story.js
index cf58e4cf..a526e6f0 100644
--- a/ui/src/components/topology/story.js
+++ b/ui/src/components/topology/story.js
@@ -6,11 +6,16 @@ import README from './readme.md';
import StoryHelper from './story-helper';
import GraphNode from './graph-node';
+import TopologyGraph from './topology-graph';
+import data from './big-data';
storiesOf('Topology', module)
-.add('5 services', withReadme(README, () => (
+.add('Wordpress example', withReadme(README, () => (
)))
+.add('Many services example', withReadme(README, () => (
+
+)))
.add('Consul', withReadme(README, () => (