mirror of
https://github.com/yldio/copilot.git
synced 2024-11-11 05:40:11 +02:00
Topology data and component with new data
This commit is contained in:
parent
561b00b73a
commit
78312f7a68
@ -18,7 +18,8 @@ const {
|
|||||||
const {
|
const {
|
||||||
orgByIdSelector,
|
orgByIdSelector,
|
||||||
projectByIdSelector,
|
projectByIdSelector,
|
||||||
servicesByProjectIdSelector
|
servicesByProjectIdSelector,
|
||||||
|
servicesForTopologySelector
|
||||||
} = selectors;
|
} = selectors;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -28,7 +29,8 @@ const {
|
|||||||
const Services = ({
|
const Services = ({
|
||||||
org = {},
|
org = {},
|
||||||
project = {},
|
project = {},
|
||||||
services = []
|
services = [],
|
||||||
|
servicesForTopology = []
|
||||||
}) => {
|
}) => {
|
||||||
const empty = services.length ? null : (
|
const empty = services.length ? null : (
|
||||||
<EmptyServices />
|
<EmptyServices />
|
||||||
@ -60,7 +62,8 @@ const Services = ({
|
|||||||
Services.propTypes = {
|
Services.propTypes = {
|
||||||
org: PropTypes.org,
|
org: PropTypes.org,
|
||||||
project: PropTypes.project,
|
project: PropTypes.project,
|
||||||
services: React.PropTypes.arrayOf(PropTypes.service)
|
services: React.PropTypes.arrayOf(PropTypes.service),
|
||||||
|
servicesForTopology: React.PropTypes.arrayOf(React.PropTypes.object)
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, {
|
const mapStateToProps = (state, {
|
||||||
@ -70,7 +73,9 @@ const mapStateToProps = (state, {
|
|||||||
}) => ({
|
}) => ({
|
||||||
org: orgByIdSelector(match.params.org)(state),
|
org: orgByIdSelector(match.params.org)(state),
|
||||||
project: projectByIdSelector(match.params.projectId)(state),
|
project: projectByIdSelector(match.params.projectId)(state),
|
||||||
services: servicesByProjectIdSelector(match.params.projectId)(state)
|
services: servicesByProjectIdSelector(match.params.projectId)(state),
|
||||||
|
servicesForTopology:
|
||||||
|
servicesForTopologySelector(match.params.projectId)(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = connect(
|
module.exports = connect(
|
||||||
|
@ -642,7 +642,10 @@
|
|||||||
}, {
|
}, {
|
||||||
"type": "dca08514-72e5-46ce-ad92-e68b3b0914d4",
|
"type": "dca08514-72e5-46ce-ad92-e68b3b0914d4",
|
||||||
"dataset": "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec"
|
"dataset": "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec"
|
||||||
}]
|
}],
|
||||||
|
"connections": [
|
||||||
|
"be227788-74f1-4e5b-a85f-b5c71cbae8d8"
|
||||||
|
]
|
||||||
}, {
|
}, {
|
||||||
"uuid": "be227788-74f1-4e5b-a85f-b5c71cbae8d8",
|
"uuid": "be227788-74f1-4e5b-a85f-b5c71cbae8d8",
|
||||||
"id": "wordpress",
|
"id": "wordpress",
|
||||||
@ -658,7 +661,12 @@
|
|||||||
}, {
|
}, {
|
||||||
"type": "dca08514-72e5-46ce-ad92-e68b3b0914d4",
|
"type": "dca08514-72e5-46ce-ad92-e68b3b0914d4",
|
||||||
"dataset": "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec"
|
"dataset": "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec"
|
||||||
}]
|
}],
|
||||||
|
"connections": [
|
||||||
|
"6a0eee76-c019-413b-9d5f-44712b55b993",
|
||||||
|
"6d31aff4-de1e-4042-a983-fbd23d5c530c",
|
||||||
|
"9572d367-c4ae-4fb1-8ad5-f5e3830e7034"
|
||||||
|
]
|
||||||
}, {
|
}, {
|
||||||
"uuid": "6a0eee76-c019-413b-9d5f-44712b55b993",
|
"uuid": "6a0eee76-c019-413b-9d5f-44712b55b993",
|
||||||
"id": "nfs",
|
"id": "nfs",
|
||||||
|
@ -110,6 +110,37 @@ const instancesByServiceId = (serviceId) => createSelector(
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const servicesForTopology = (projectId) => createSelector(
|
||||||
|
[services, projectById(projectId)],
|
||||||
|
(services, project) =>
|
||||||
|
services.filter((s) => s.project === project.uuid)
|
||||||
|
.map((service) => ({
|
||||||
|
...service,
|
||||||
|
uuid: service.uuid,
|
||||||
|
id: service.id,
|
||||||
|
name: service.name,
|
||||||
|
instances: instancesByServiceId(service.uuid).length,
|
||||||
|
connections: service.connections,
|
||||||
|
// tmp below
|
||||||
|
datacentres: 2,
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
name: 'CPU',
|
||||||
|
value: '50%'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Memory',
|
||||||
|
value: '20%'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Network',
|
||||||
|
value: '2.9Kb/sec'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
healthy: true
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
const metricsByServiceId = (serviceId) => createSelector(
|
const metricsByServiceId = (serviceId) => createSelector(
|
||||||
[serviceById(serviceId), metricsData, metricsUI],
|
[serviceById(serviceId), metricsData, metricsUI],
|
||||||
(service, metrics, metricsUI) => datasets(metrics, service.metrics, metricsUI)
|
(service, metrics, metricsUI) => datasets(metrics, service.metrics, metricsUI)
|
||||||
@ -185,6 +216,7 @@ module.exports = {
|
|||||||
projectsByOrgIdSelector: projectsByOrgId,
|
projectsByOrgIdSelector: projectsByOrgId,
|
||||||
projectByIdSelector: projectById,
|
projectByIdSelector: projectById,
|
||||||
servicesByProjectIdSelector: servicesByProjectId,
|
servicesByProjectIdSelector: servicesByProjectId,
|
||||||
|
servicesForTopologySelector: servicesForTopology,
|
||||||
instancesByServiceIdSelector: instancesByServiceId,
|
instancesByServiceIdSelector: instancesByServiceId,
|
||||||
metricsByServiceIdSelector: metricsByServiceId,
|
metricsByServiceIdSelector: metricsByServiceId,
|
||||||
metricTypesSelector: metricTypes,
|
metricTypesSelector: metricTypes,
|
||||||
|
@ -1,6 +1,155 @@
|
|||||||
/*eslint-disable */
|
/*eslint-disable */
|
||||||
|
|
||||||
module.exports = {
|
module.exports = [
|
||||||
|
{
|
||||||
|
"uuid":"081a792c-47e0-4439-924b-2efa9788ae9e",
|
||||||
|
"id":"nginx",
|
||||||
|
"name":"Nginx",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":1,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections":[
|
||||||
|
"be227788-74f1-4e5b-a85f-b5c71cbae8d8"
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid":"be227788-74f1-4e5b-a85f-b5c71cbae8d8",
|
||||||
|
"id":"wordpress",
|
||||||
|
"name":"Wordpress",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":2,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections":[
|
||||||
|
"6a0eee76-c019-413b-9d5f-44712b55b993",
|
||||||
|
"6d31aff4-de1e-4042-a983-fbd23d5c530c",
|
||||||
|
"4ee4103e-1a52-4099-a48e-01588f597c70"
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid":"6a0eee76-c019-413b-9d5f-44712b55b993",
|
||||||
|
"id":"nfs",
|
||||||
|
"name":"NFS",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":2,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid":"6d31aff4-de1e-4042-a983-fbd23d5c530c",
|
||||||
|
"id":"memcached",
|
||||||
|
"name":"Memcached",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":2,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid":"4ee4103e-1a52-4099-a48e-01588f597c70",
|
||||||
|
"id":"percona",
|
||||||
|
"name":"Percona",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":2,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid":"97c68055-db88-45c9-ad49-f26da4264777",
|
||||||
|
"id":"consul",
|
||||||
|
"name":"Consul",
|
||||||
|
"project":"e0ea0c02-55cc-45fe-8064-3e5176a59401",
|
||||||
|
"instances":2,
|
||||||
|
"metrics":[
|
||||||
|
{
|
||||||
|
"name":"CPU",
|
||||||
|
"value":"50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Memory",
|
||||||
|
"value":"20%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Network",
|
||||||
|
"value":"2.9Kb/sec"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"healthy":true,
|
||||||
|
"datacentres":2
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/*module.exports = {
|
||||||
nodes: [
|
nodes: [
|
||||||
{
|
{
|
||||||
id: 'Nginx',
|
id: 'Nginx',
|
||||||
@ -131,4 +280,4 @@ module.exports = {
|
|||||||
target: 'Percona',
|
target: 'Percona',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};*/
|
||||||
|
@ -35,15 +35,12 @@ const StyledDataCentresIcon = styled(DataCentresIcon)`
|
|||||||
|
|
||||||
const GraphNodeInfo = ({
|
const GraphNodeInfo = ({
|
||||||
connected,
|
connected,
|
||||||
attrs,
|
datacentres,
|
||||||
|
instances,
|
||||||
|
healthy,
|
||||||
infoPosition
|
infoPosition
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const {
|
|
||||||
dcs,
|
|
||||||
instances
|
|
||||||
} = attrs;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g transform={`translate(${infoPosition.x}, ${infoPosition.y})`}>
|
<g transform={`translate(${infoPosition.x}, ${infoPosition.y})`}>
|
||||||
<g transform={'translate(0, 2)'}>
|
<g transform={'translate(0, 2)'}>
|
||||||
@ -54,7 +51,7 @@ const GraphNodeInfo = ({
|
|||||||
y={12}
|
y={12}
|
||||||
connected={connected}
|
connected={connected}
|
||||||
>
|
>
|
||||||
{`${dcs} inst.`}
|
{`${datacentres} inst.`}
|
||||||
</StyledText>
|
</StyledText>
|
||||||
<g transform={'translate(82, 0)'}>
|
<g transform={'translate(82, 0)'}>
|
||||||
<StyledDataCentresIcon connected={connected} />
|
<StyledDataCentresIcon connected={connected} />
|
||||||
@ -71,16 +68,14 @@ const GraphNodeInfo = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
GraphNodeInfo.propTypes = {
|
GraphNodeInfo.propTypes = {
|
||||||
attrs: React.PropTypes.shape({
|
|
||||||
dcs: React.PropTypes.number,
|
|
||||||
instances: React.PropTypes.number,
|
|
||||||
healthy: React.PropTypes.bool
|
|
||||||
}),
|
|
||||||
connected: React.PropTypes.bool,
|
connected: React.PropTypes.bool,
|
||||||
|
datacentres: React.PropTypes.number,
|
||||||
|
healthy: React.PropTypes.bool,
|
||||||
infoPosition: React.PropTypes.shape({
|
infoPosition: React.PropTypes.shape({
|
||||||
x: React.PropTypes.number,
|
x: React.PropTypes.number,
|
||||||
y: React.PropTypes.number
|
y: React.PropTypes.number
|
||||||
})
|
}),
|
||||||
|
instances: React.PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Baseline(
|
module.exports = Baseline(
|
||||||
|
@ -30,7 +30,7 @@ const GraphNodeMetrics = ({
|
|||||||
y={12 + metricSpacing*index}
|
y={12 + metricSpacing*index}
|
||||||
connected={connected}
|
connected={connected}
|
||||||
>
|
>
|
||||||
{`${metric.name}: ${metric.stat}`}
|
{`${metric.name}: ${metric.value}`}
|
||||||
</StyledText>
|
</StyledText>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ const GraphNode = ({
|
|||||||
y={30}
|
y={30}
|
||||||
connected={connected}
|
connected={connected}
|
||||||
>
|
>
|
||||||
{data.id}
|
{data.name}
|
||||||
</StyledText>
|
</StyledText>
|
||||||
<g transform={`translate(${115}, ${15})`}>
|
<g transform={`translate(${115}, ${15})`}>
|
||||||
<HeartCircle
|
<HeartCircle
|
||||||
@ -164,7 +164,9 @@ const GraphNode = ({
|
|||||||
connected={connected}
|
connected={connected}
|
||||||
/>
|
/>
|
||||||
<GraphNodeInfo
|
<GraphNodeInfo
|
||||||
attrs={data.attrs}
|
datacentres={data.datacentres}
|
||||||
|
instances={data.instances}
|
||||||
|
healthy
|
||||||
infoPosition={infoPosition}
|
infoPosition={infoPosition}
|
||||||
connected={connected}
|
connected={connected}
|
||||||
/>
|
/>
|
||||||
|
@ -13,9 +13,19 @@ const rectRadius = (size) => {
|
|||||||
return Math.round(hypotenuse(width, height)/2);
|
return Math.round(hypotenuse(width, height)/2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createLinks = (services) =>
|
||||||
|
services.reduce((acc, service, index) =>
|
||||||
|
service.connections ?
|
||||||
|
acc.concat(
|
||||||
|
service.connections.map((connection, index) => ({
|
||||||
|
source: service.uuid,
|
||||||
|
target: connection
|
||||||
|
}))
|
||||||
|
) : acc
|
||||||
|
, []);
|
||||||
|
|
||||||
const createSimulation = (
|
const createSimulation = (
|
||||||
nodes,
|
services,
|
||||||
links,
|
|
||||||
nodeSize,
|
nodeSize,
|
||||||
svgSize,
|
svgSize,
|
||||||
onTick,
|
onTick,
|
||||||
@ -23,13 +33,12 @@ const createSimulation = (
|
|||||||
) => {
|
) => {
|
||||||
// This is not going to work given that as well as the d3 layout stuff, other things might be at play too
|
// 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
|
// We should pass two objects to the components - one for positioning and one for data
|
||||||
const mappedNodes = nodes.map((node, index) => ({
|
const nodes = services.map((service, index) => ({
|
||||||
id: node.id,
|
id: service.uuid,
|
||||||
index: index
|
index: index
|
||||||
}));
|
}));
|
||||||
const mappedLinks = links.map((link, index) => ({
|
|
||||||
...link
|
const links = createLinks(services);
|
||||||
}));
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
width,
|
width,
|
||||||
@ -39,22 +48,21 @@ const createSimulation = (
|
|||||||
const nodeRadius = rectRadius(nodeSize);
|
const nodeRadius = rectRadius(nodeSize);
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
simulation: d3.forceSimulation(mappedNodes)
|
simulation: d3.forceSimulation(nodes)
|
||||||
.force('link', d3.forceLink(mappedLinks).id(d => d.id))
|
.force('link', d3.forceLink(links).id(d => d.id))
|
||||||
.force('collide', d3.forceCollide(nodeRadius))
|
.force('collide', d3.forceCollide(nodeRadius))
|
||||||
.force('center', d3.forceCenter(width/2, height/2))
|
.force('center', d3.forceCenter(width/2, height/2))
|
||||||
.on('tick', onTick)
|
.on('tick', onTick)
|
||||||
.on('end', onEnd),
|
.on('end', onEnd),
|
||||||
nodes: mappedNodes,
|
nodes: nodes,
|
||||||
links: mappedLinks
|
links: links
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO we need to kill the previous simulation
|
// TODO we need to kill the previous simulation
|
||||||
const updateSimulation = (
|
const updateSimulation = (
|
||||||
simulation,
|
simulation,
|
||||||
nextNodes,
|
services,
|
||||||
nextLinks,
|
|
||||||
simNodes,
|
simNodes,
|
||||||
simLinks,
|
simLinks,
|
||||||
nodeSize,
|
nodeSize,
|
||||||
@ -62,9 +70,9 @@ const updateSimulation = (
|
|||||||
onTick,
|
onTick,
|
||||||
onEnd
|
onEnd
|
||||||
) => {
|
) => {
|
||||||
const mappedNodes = nextNodes.map((nextNode, index) => {
|
const nodes = services.map((service, index) => {
|
||||||
const simNode = simNodes.reduce((acc, n, i) => {
|
const simNode = simNodes.reduce((acc, n, i) => {
|
||||||
return nextNode.id === n.id ? n : acc;
|
return service.uuid === n.id ? n : acc;
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
return simNode ? {
|
return simNode ? {
|
||||||
@ -73,14 +81,12 @@ const updateSimulation = (
|
|||||||
// fy: simNode.y,
|
// fy: simNode.y,
|
||||||
index: index
|
index: index
|
||||||
} : {
|
} : {
|
||||||
id: nextNode.id,
|
id: service.uuid,
|
||||||
index: index
|
index: index
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const mappedLinks = nextLinks.map((nextLink, index) => ({
|
const links = createLinks(services);
|
||||||
...nextLink
|
|
||||||
}));
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
width,
|
width,
|
||||||
@ -90,14 +96,14 @@ const updateSimulation = (
|
|||||||
const nodeRadius = rectRadius(nodeSize);
|
const nodeRadius = rectRadius(nodeSize);
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
simulation: d3.forceSimulation(mappedNodes)
|
simulation: d3.forceSimulation(nodes)
|
||||||
.force('link', d3.forceLink(mappedLinks).id(d => d.id))
|
.force('link', d3.forceLink(links).id(d => d.id))
|
||||||
.force('collide', d3.forceCollide(nodeRadius))
|
.force('collide', d3.forceCollide(nodeRadius))
|
||||||
.force('center', d3.forceCenter(width/2, height/2))
|
.force('center', d3.forceCenter(width/2, height/2))
|
||||||
.on('tick', onTick)
|
.on('tick', onTick)
|
||||||
.on('end', onEnd),
|
.on('end', onEnd),
|
||||||
nodes: mappedNodes,
|
nodes: nodes,
|
||||||
links: mappedLinks
|
links: links
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
const Styled = require('styled-components');
|
const Styled = require('styled-components');
|
||||||
const composers = require('../../shared/composers');
|
const composers = require('../../shared/composers');
|
||||||
|
const fns = require('../../shared/functions');
|
||||||
const Input = require('../form/input');
|
const Input = require('../form/input');
|
||||||
const Select = require('../form/select');
|
const Select = require('../form/select');
|
||||||
const Topology = require('./');
|
const Topology = require('./');
|
||||||
@ -10,6 +11,10 @@ const {
|
|||||||
default: styled
|
default: styled
|
||||||
} = Styled;
|
} = Styled;
|
||||||
|
|
||||||
|
const {
|
||||||
|
rndId
|
||||||
|
} = fns;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Baseline
|
Baseline
|
||||||
} = composers;
|
} = composers;
|
||||||
@ -51,56 +56,60 @@ class StoryHelper extends React.Component {
|
|||||||
const target = evt.target.target.value;
|
const target = evt.target.target.value;
|
||||||
const source = evt.target.source.value;
|
const source = evt.target.source.value;
|
||||||
|
|
||||||
const links = [];
|
const node = {
|
||||||
|
...data[0],
|
||||||
|
id: rndId(),
|
||||||
|
uuid: rndId(),
|
||||||
|
name: service
|
||||||
|
};
|
||||||
|
|
||||||
|
delete node.connections;
|
||||||
|
|
||||||
if(target) {
|
if(target) {
|
||||||
links.push({
|
node.connections = [
|
||||||
target: target,
|
data.reduce((acc, s, i) => s.id === target ? s.uuid : acc, '')
|
||||||
source: service
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const d = this.state.data.map((data, index) => {
|
||||||
|
|
||||||
|
if(data.id === source) {
|
||||||
|
const connections = data.connections ?
|
||||||
|
data.connections.concat(node.uuid) : [node.uuid];
|
||||||
|
|
||||||
|
return ({
|
||||||
|
...data,
|
||||||
|
connections: connections
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(source) {
|
return ({
|
||||||
links.push({
|
...data
|
||||||
target: service,
|
});
|
||||||
source: source
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if(links.length) {
|
d.push(node);
|
||||||
const data = this.state.data;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
data: {
|
data: d
|
||||||
nodes: [
|
|
||||||
...data.nodes,
|
|
||||||
{
|
|
||||||
...data.nodes[0],
|
|
||||||
id: service
|
|
||||||
}
|
|
||||||
],
|
|
||||||
links: [
|
|
||||||
...data.links,
|
|
||||||
...links
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<StyledForm onSubmit={onAddService}>
|
{<StyledForm onSubmit={onAddService}>
|
||||||
<Input name='service' placeholder='Service name' />
|
<Input name='service' placeholder='Service name' />
|
||||||
<Select name='target'>
|
<Select name='target'>
|
||||||
<option value=''>Select a service to link to (optional)</option>
|
<option value=''>Select a service to link to (optional)</option>
|
||||||
{linkOptions(data.nodes)}
|
{linkOptions(data)}
|
||||||
</Select>
|
</Select>
|
||||||
<Select name='source'>
|
<Select name='source'>
|
||||||
<option value=''>Select a service to link from (optional)</option>
|
<option value=''>Select a service to link from (optional)</option>
|
||||||
{linkOptions(data.nodes)}
|
{linkOptions(data)}
|
||||||
</Select>
|
</Select>
|
||||||
<Input name='Add service' type='submit' />
|
<Input name='Add service' type='submit' />
|
||||||
</StyledForm>
|
</StyledForm>}
|
||||||
<TopologyGraph data={data} />
|
<TopologyGraph services={data} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -42,14 +42,10 @@ let dragInfo = {
|
|||||||
|
|
||||||
class TopologyGraph extends React.Component {
|
class TopologyGraph extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const {
|
const services = this.props.services;
|
||||||
nodes,
|
|
||||||
links
|
|
||||||
} = this.props.data;
|
|
||||||
|
|
||||||
const simulationData = createSimulation(
|
const simulationData = createSimulation(
|
||||||
nodes,
|
services,
|
||||||
links,
|
|
||||||
nodeSize,
|
nodeSize,
|
||||||
svgSize//,
|
svgSize//,
|
||||||
//() => this.forceUpdate(),
|
//() => this.forceUpdate(),
|
||||||
@ -78,25 +74,21 @@ class TopologyGraph extends React.Component {
|
|||||||
// try freezing exisiting ones... then adding another
|
// try freezing exisiting ones... then adding another
|
||||||
|
|
||||||
const {
|
const {
|
||||||
nodes: simNodes,
|
nodes,
|
||||||
links: simLinks
|
links
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const {
|
const services = nextProps.services;
|
||||||
nodes: nextNodes,
|
// TODO this here means we'll need to evaluate whether to we have more links!
|
||||||
links: nextLinks
|
|
||||||
} = nextProps.data;
|
|
||||||
|
|
||||||
// this is tmp for the compare above
|
// this is tmp for the compare above
|
||||||
if(nextNodes.length !== simNodes.length ||
|
if(services !== nodes.length) {
|
||||||
nextLinks.length !== simLinks.length) {
|
|
||||||
const simulation = this.state.simulation;
|
const simulation = this.state.simulation;
|
||||||
const nextSimulationData = updateSimulation(
|
const nextSimulationData = updateSimulation(
|
||||||
simulation,
|
simulation,
|
||||||
nextNodes,
|
services,
|
||||||
nextLinks,
|
nodes,
|
||||||
simNodes,
|
links,
|
||||||
simLinks,
|
|
||||||
nodeSize,
|
nodeSize,
|
||||||
svgSize,
|
svgSize,
|
||||||
() => this.forceUpdate(),
|
() => this.forceUpdate(),
|
||||||
@ -114,10 +106,10 @@ class TopologyGraph extends React.Component {
|
|||||||
nextSimulation.tick();
|
nextSimulation.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*this.state.simulation.nodes().forEach((node, index) => {
|
//this.state.simulation.nodes().forEach((node, index) => {
|
||||||
delete node.fx;
|
// delete node.fx;
|
||||||
delete node.fy;
|
// delete node.fy;
|
||||||
});*/
|
//});
|
||||||
|
|
||||||
this.setState(nextSimulationData);
|
this.setState(nextSimulationData);
|
||||||
}
|
}
|
||||||
@ -125,26 +117,26 @@ class TopologyGraph extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
|
const services = this.props.services;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
nodes,
|
nodes,
|
||||||
links
|
links
|
||||||
} = this.props.data;
|
} = this.state;
|
||||||
|
|
||||||
const simulationNodes = this.state.nodes;
|
const node = (nodeId) =>
|
||||||
|
nodes.reduce((acc, simNode, index) => {
|
||||||
const simulationNode = (nodeId) =>
|
|
||||||
simulationNodes.reduce((acc, simNode, index) => {
|
|
||||||
return simNode.id === nodeId ? simNode : acc;
|
return simNode.id === nodeId ? simNode : acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const nodesData = nodes.map((node, index) => ({
|
const nodesData = services.map((service, index) => ({
|
||||||
...node,
|
...service,
|
||||||
...simulationNode(node.id)
|
...node(service.uuid)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const linksData = links.map((link, index) => ({
|
const linksData = links.map((link, index) => ({
|
||||||
source: simulationNode(link.source),
|
source: node(link.source.id),
|
||||||
target: simulationNode(link.target)
|
target: node(link.target.id)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onDragStart = (evt, nodeId) => {
|
const onDragStart = (evt, nodeId) => {
|
||||||
@ -183,7 +175,7 @@ class TopologyGraph extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const dragNodes = simulationNodes.map((simNode, index) => {
|
const dragNodes = nodes.map((simNode, index) => {
|
||||||
if(simNode.id === dragInfo.nodeId) {
|
if(simNode.id === dragInfo.nodeId) {
|
||||||
return ({
|
return ({
|
||||||
...simNode,
|
...simNode,
|
||||||
@ -263,10 +255,7 @@ class TopologyGraph extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TopologyGraph.propTypes = {
|
TopologyGraph.propTypes = {
|
||||||
data: React.PropTypes.shape({
|
services: React.PropTypes.array
|
||||||
nodes: React.PropTypes.array,
|
|
||||||
links: React.PropTypes.array
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Baseline(
|
module.exports = Baseline(
|
||||||
|
Loading…
Reference in New Issue
Block a user