Merge pull request #336 from yldio/feature/add-topology-view

Add topology view
This commit is contained in:
Alex Windett 2017-03-01 10:38:53 +00:00 committed by GitHub
commit 08acbe5944
8 changed files with 183 additions and 75 deletions

View 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;

View File

@ -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?'

View File

@ -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(

View 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);

View File

@ -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';

View File

@ -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

View File

@ -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}

View File

@ -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;