Merge pull request #336 from yldio/feature/add-topology-view
Add topology view
This commit is contained in:
commit
08acbe5944
71
frontend/src/components/services/view.js
Normal file
71
frontend/src/components/services/view.js
Normal file
@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import EmptyServices from '@components/empty/services';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import Row from '@ui/components/row';
|
||||
import Column from '@ui/components/column';
|
||||
import { H2 } from '@ui/components/base-elements';
|
||||
import {
|
||||
FormGroup,
|
||||
Toggle,
|
||||
ToggleList
|
||||
} from '@ui/components/form';
|
||||
|
||||
const ServicesView = ({
|
||||
children,
|
||||
org = {},
|
||||
match = {},
|
||||
project = {},
|
||||
routerPush = {},
|
||||
services = []
|
||||
}) => {
|
||||
const toggle = () => {
|
||||
if(!services) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const value = match.path === '/:org/projects/:projectId/services' ?
|
||||
'topology' : 'list';
|
||||
|
||||
const onToggleChange = (evt) => {
|
||||
evt.preventDefault();
|
||||
const value = evt.target.value;
|
||||
const path = `/${org.id}/projects/${project.id}/services${
|
||||
value === 'list' ? '/list' : ''
|
||||
}`;
|
||||
routerPush(path);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormGroup name='service-view' value={value}>
|
||||
<ToggleList>
|
||||
<Toggle value='topology' onChange={onToggleChange}>Topology</Toggle>
|
||||
<Toggle value='list' onChange={onToggleChange}>List</Toggle>
|
||||
</ToggleList>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const content = services.length ?
|
||||
children : <EmptyServices />;
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Column xs={12}>
|
||||
<H2>Services</H2>
|
||||
{ toggle() }
|
||||
{ content }
|
||||
</Column>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
ServicesView.propTypes = {
|
||||
children: React.PropTypes.node,
|
||||
match: React.PropTypes.object.isRequired,
|
||||
org: PropTypes.org,
|
||||
project: PropTypes.project,
|
||||
routerPush: React.PropTypes.func.isRequired,
|
||||
services: React.PropTypes.arrayOf(PropTypes.service)
|
||||
};
|
||||
|
||||
export default ServicesView;
|
@ -1,23 +1,35 @@
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import Section from './section';
|
||||
import Services from '@containers/services';
|
||||
import ServicesTopology from '@containers/services';
|
||||
import ServicesList from '@containers/services/list';
|
||||
import Service from '@containers/service';
|
||||
|
||||
export default () => {
|
||||
const topology = (props) => (
|
||||
<Section {...props}>
|
||||
<ServicesTopology {...props} />
|
||||
</Section>
|
||||
);
|
||||
|
||||
const list = (props) => (
|
||||
<Section {...props}>
|
||||
<Services {...props} />
|
||||
<ServicesList {...props} />
|
||||
</Section>
|
||||
);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
component={list}
|
||||
component={topology}
|
||||
exact
|
||||
path='/:org/projects/:projectId/services'
|
||||
/>
|
||||
<Route
|
||||
component={list}
|
||||
exact
|
||||
path='/:org/projects/:projectId/services/list'
|
||||
/>
|
||||
<Route
|
||||
component={Service}
|
||||
path='/:org/projects/:projectId/services/:serviceId/:section?'
|
||||
|
@ -1,68 +1,42 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import EmptyServices from '@components/empty/services';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import ServiceItem from '@components/service/item';
|
||||
import ServiceViewToggle from '@components/service/view-toggle';
|
||||
import Row from '@ui/components/row';
|
||||
import Column from '@ui/components/column';
|
||||
import { H2 } from '@ui/components/base-elements';
|
||||
import { TopologyGraph } from '@ui/components/topology';
|
||||
import ServicesView from '@components/services/view';
|
||||
|
||||
import {
|
||||
orgByIdSelector,
|
||||
projectByIdSelector,
|
||||
servicesByProjectIdSelector,
|
||||
servicesForTopologySelector
|
||||
} from '@state/selectors';
|
||||
|
||||
const Services = ({
|
||||
org = {},
|
||||
project = {},
|
||||
services = [],
|
||||
servicesForTopology = []
|
||||
}) => {
|
||||
const empty = services.length ? null : (
|
||||
<EmptyServices />
|
||||
);
|
||||
const Services = (props) => {
|
||||
|
||||
const serviceList = services.map((service) => (
|
||||
<ServiceItem
|
||||
key={service.uuid}
|
||||
org={org.id}
|
||||
project={project.id}
|
||||
service={service}
|
||||
/>
|
||||
));
|
||||
const {
|
||||
services = []
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Column xs={12}>
|
||||
<H2>Services</H2>
|
||||
<ServiceViewToggle />
|
||||
{empty}
|
||||
{serviceList}
|
||||
</Column>
|
||||
</Row>
|
||||
<ServicesView {...props}>
|
||||
<TopologyGraph services={services} />
|
||||
</ServicesView>
|
||||
);
|
||||
};
|
||||
|
||||
Services.propTypes = {
|
||||
org: PropTypes.org,
|
||||
project: PropTypes.project,
|
||||
services: React.PropTypes.arrayOf(PropTypes.service),
|
||||
servicesForTopology: React.PropTypes.arrayOf(React.PropTypes.object)
|
||||
services: React.PropTypes.arrayOf(PropTypes.service)
|
||||
};
|
||||
|
||||
const mapStateToProps = (state, {
|
||||
match = {
|
||||
params: {}
|
||||
}
|
||||
},
|
||||
push
|
||||
}) => ({
|
||||
org: orgByIdSelector(match.params.org)(state),
|
||||
project: projectByIdSelector(match.params.projectId)(state),
|
||||
services: servicesByProjectIdSelector(match.params.projectId)(state),
|
||||
servicesForTopology:
|
||||
servicesForTopologySelector(match.params.projectId)(state)
|
||||
routerPush: push,
|
||||
services: servicesForTopologySelector(match.params.projectId)(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
56
frontend/src/containers/services/list.js
Normal file
56
frontend/src/containers/services/list.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from '@root/prop-types';
|
||||
import ServiceItem from '@components/service/item';
|
||||
import ServicesView from '@components/services/view';
|
||||
|
||||
import {
|
||||
orgByIdSelector,
|
||||
projectByIdSelector,
|
||||
servicesByProjectIdSelector
|
||||
} from '@state/selectors';
|
||||
|
||||
const Services = (props) => {
|
||||
const {
|
||||
org = {},
|
||||
project = {},
|
||||
services = []
|
||||
} = props;
|
||||
|
||||
const serviceList = services.map((service) => (
|
||||
<ServiceItem
|
||||
key={service.uuid}
|
||||
org={org.id}
|
||||
project={project.id}
|
||||
service={service}
|
||||
/>
|
||||
));
|
||||
|
||||
return (
|
||||
<ServicesView {...props}>
|
||||
{serviceList}
|
||||
</ServicesView>
|
||||
);
|
||||
};
|
||||
|
||||
Services.propTypes = {
|
||||
org: PropTypes.org,
|
||||
project: PropTypes.project,
|
||||
services: React.PropTypes.arrayOf(PropTypes.service)
|
||||
};
|
||||
|
||||
const mapStateToProps = (state, {
|
||||
match = {
|
||||
params: {}
|
||||
},
|
||||
push
|
||||
}) => ({
|
||||
org: orgByIdSelector(match.params.org)(state),
|
||||
project: projectByIdSelector(match.params.projectId)(state),
|
||||
routerPush: push,
|
||||
services: servicesByProjectIdSelector(match.params.projectId)(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps
|
||||
)(Services);
|
@ -1,22 +1,12 @@
|
||||
import Checkbox from './checkbox';
|
||||
import Fieldset from './fieldset';
|
||||
import FormGroup from './group';
|
||||
import Input from './input';
|
||||
import FormLabel from './label';
|
||||
import Legend from './legend';
|
||||
import FormMeta from './meta';
|
||||
import Radio, { RadioList } from './radio';
|
||||
import Select from './select';
|
||||
|
||||
export {
|
||||
Checkbox,
|
||||
Fieldset,
|
||||
FormGroup,
|
||||
Input,
|
||||
FormLabel,
|
||||
Legend,
|
||||
FormMeta,
|
||||
Radio,
|
||||
RadioList,
|
||||
Select
|
||||
};
|
||||
export { default as Checkbox } from './checkbox';
|
||||
export { default as Fieldset } from './fieldset';
|
||||
export { default as FormGroup } from './group';
|
||||
export { default as Input } from './input';
|
||||
export { default as FormLabel } from './label';
|
||||
export { default as Legend } from './legend';
|
||||
export { default as FormMeta } from './meta';
|
||||
export { default as Radio } from './radio';
|
||||
export { RadioList as RadioList } from './radio';
|
||||
export { default as Select } from './select';
|
||||
export { default as Toggle } from './toggle';
|
||||
export { ToggleList as ToggleList } from './toggle';
|
||||
|
@ -5,6 +5,7 @@ import { Subscriber } from 'react-broadcast';
|
||||
import { Baseline } from '../../../shared/composers';
|
||||
import BaseInput from '../base-input';
|
||||
import { boxes, colors } from '../../../shared/constants';
|
||||
import { rndId } from '../../../shared/functions';
|
||||
|
||||
const Input = styled.input`
|
||||
display: none;
|
||||
@ -91,16 +92,20 @@ const Toggle = BaseInput(({
|
||||
...props
|
||||
}) => {
|
||||
const render = (value) => {
|
||||
const id = rndId();
|
||||
return (
|
||||
<StyledLi>
|
||||
<InputContainer>
|
||||
<Input
|
||||
{...props}
|
||||
// eslint-disable-next-line react/prop-types
|
||||
checked={value.value === props.value}
|
||||
{...value}
|
||||
{...props}
|
||||
id={id}
|
||||
type='radio'
|
||||
/>
|
||||
<Label
|
||||
htmlFor={value.id}
|
||||
htmlFor={id}
|
||||
// eslint-disable-next-line react/prop-types
|
||||
error={props.error}
|
||||
// eslint-disable-next-line react/prop-types
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Baseline } from '../../shared/composers';
|
||||
import PropTypes from './prop-types';
|
||||
import HeartIcon from './icon-heart.svg';
|
||||
// import HeartIcon from './icon-heart.svg';
|
||||
import GraphNodeButton from './graph-node-button';
|
||||
import GraphNodeInfo from './graph-node-info';
|
||||
// import GraphNodeInfo from './graph-node-info';
|
||||
import GraphNodeMetrics from './graph-node-metrics';
|
||||
import styled from 'styled-components';
|
||||
import React from 'react';
|
||||
@ -65,10 +65,10 @@ const GraphNode = ({
|
||||
};
|
||||
|
||||
const paddingLeft = 18;
|
||||
const infoPosition = {
|
||||
/*const infoPosition = {
|
||||
x: paddingLeft,
|
||||
y: 59
|
||||
};
|
||||
};*/
|
||||
const metricsPosition = {
|
||||
x: paddingLeft,
|
||||
y: 89
|
||||
@ -145,20 +145,20 @@ const GraphNode = ({
|
||||
cy={9}
|
||||
r={9}
|
||||
/>
|
||||
<HeartIcon />
|
||||
{/*<HeartIcon />*/}
|
||||
</g>
|
||||
<GraphNodeButton
|
||||
buttonRect={buttonRect}
|
||||
onButtonClick={onButtonClick}
|
||||
connected={connected}
|
||||
/>
|
||||
<GraphNodeInfo
|
||||
{/*<GraphNodeInfo
|
||||
datacentres={data.datacentres}
|
||||
instances={data.instances}
|
||||
healthy
|
||||
infoPosition={infoPosition}
|
||||
connected={connected}
|
||||
/>
|
||||
/>*/}
|
||||
<GraphNodeMetrics
|
||||
metrics={data.metrics}
|
||||
metricsPosition={metricsPosition}
|
||||
|
@ -8,7 +8,6 @@ import React from 'react';
|
||||
const StyledSvg = styled.svg`
|
||||
width: 1024px;
|
||||
height: 860px;
|
||||
border: 1px solid #ff0000;
|
||||
`;
|
||||
|
||||
const nodeSize = {
|
||||
@ -28,6 +27,7 @@ let dragInfo = {
|
||||
};
|
||||
|
||||
class TopologyGraph extends React.Component {
|
||||
|
||||
componentWillMount() {
|
||||
const services = this.props.services;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user