link service
This commit is contained in:
parent
af4d26b5a5
commit
355c7d59d9
@ -3,15 +3,16 @@ const ReactRedux = require('react-redux');
|
|||||||
const ReactRouter = require('react-router');
|
const ReactRouter = require('react-router');
|
||||||
const Styled = require('styled-components');
|
const Styled = require('styled-components');
|
||||||
|
|
||||||
const selectors = require('@state/selectors');
|
|
||||||
|
|
||||||
const Container = require('@ui/components/container');
|
const Container = require('@ui/components/container');
|
||||||
const Li = require('@ui/components/horizontal-list/li');
|
const Li = require('@ui/components/horizontal-list/li');
|
||||||
const Org = require('@containers/org');
|
const Org = require('@containers/org');
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
const Redirect = require('@components/redirect');
|
const Redirect = require('@components/redirect');
|
||||||
|
const selectors = require('@state/selectors');
|
||||||
const Ul = require('@ui/components/horizontal-list/ul');
|
const Ul = require('@ui/components/horizontal-list/ul');
|
||||||
const NotFound = require('@containers/not-found');
|
const NotFound = require('@containers/not-found');
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
connect
|
connect
|
||||||
} = ReactRedux;
|
} = ReactRedux;
|
||||||
@ -74,14 +75,7 @@ const Home = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
Home.propTypes = {
|
Home.propTypes = {
|
||||||
orgs: React.PropTypes.arrayOf(
|
orgs: React.PropTypes.arrayOf(PropTypes.org)
|
||||||
React.PropTypes.shape({
|
|
||||||
owner: React.PropTypes.string,
|
|
||||||
uuid: React.PropTypes.string,
|
|
||||||
id: React.PropTypes.string,
|
|
||||||
name: React.PropTypes.string
|
|
||||||
})
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
|
@ -4,6 +4,7 @@ const ReactRedux = require('react-redux');
|
|||||||
const ReactRouter = require('react-router');
|
const ReactRouter = require('react-router');
|
||||||
|
|
||||||
const NotFound = require('@containers/not-found');
|
const NotFound = require('@containers/not-found');
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
const Redirect = require('@components/redirect');
|
const Redirect = require('@components/redirect');
|
||||||
const selectors = require('@state/selectors');
|
const selectors = require('@state/selectors');
|
||||||
|
|
||||||
@ -58,15 +59,8 @@ const Org = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
Org.propTypes = {
|
Org.propTypes = {
|
||||||
org: React.PropTypes.shape({
|
org: PropTypes.org,
|
||||||
owner: React.PropTypes.string,
|
sections: PropTypes.sections
|
||||||
uuid: React.PropTypes.string,
|
|
||||||
id: React.PropTypes.string,
|
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
sections: React.PropTypes.arrayOf(
|
|
||||||
React.PropTypes.string
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => ({
|
const mapStateToProps = (state, ownProps) => ({
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
const ReactRedux = require('react-redux');
|
const ReactRedux = require('react-redux');
|
||||||
|
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
const selectors = require('@state/selectors');
|
const selectors = require('@state/selectors');
|
||||||
const Section = require('@components/section');
|
const Section = require('@components/section');
|
||||||
|
|
||||||
@ -32,13 +33,8 @@ const OrgSection = ({
|
|||||||
|
|
||||||
OrgSection.propTypes = {
|
OrgSection.propTypes = {
|
||||||
children: React.PropTypes.node,
|
children: React.PropTypes.node,
|
||||||
org: React.PropTypes.shape({
|
org: PropTypes.org,
|
||||||
id: React.PropTypes.string,
|
sections: PropTypes.sections
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
sections: React.PropTypes.arrayOf(
|
|
||||||
React.PropTypes.string
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => ({
|
const mapStateToProps = (state, ownProps) => ({
|
||||||
@ -46,4 +42,6 @@ const mapStateToProps = (state, ownProps) => ({
|
|||||||
sections: orgSectionsSelector(ownProps.params.org)(state)
|
sections: orgSectionsSelector(ownProps.params.org)(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps)(OrgSection);
|
module.exports = connect(
|
||||||
|
mapStateToProps
|
||||||
|
)(OrgSection);
|
||||||
|
@ -2,8 +2,8 @@ const React = require('react');
|
|||||||
const ReactRedux = require('react-redux');
|
const ReactRedux = require('react-redux');
|
||||||
const ReactRouter = require('react-router');
|
const ReactRouter = require('react-router');
|
||||||
|
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
const Redirect = require('@components/redirect');
|
const Redirect = require('@components/redirect');
|
||||||
const Section = require('@components/section');
|
|
||||||
const selectors = require('@state/selectors');
|
const selectors = require('@state/selectors');
|
||||||
|
|
||||||
const SectionComponents = {
|
const SectionComponents = {
|
||||||
@ -34,67 +34,30 @@ const Project = ({
|
|||||||
project = {},
|
project = {},
|
||||||
sections = []
|
sections = []
|
||||||
}) => {
|
}) => {
|
||||||
const pathname = (props) => (
|
const navMatches = sections.map((name) => (
|
||||||
`/${props.org}/projects/${props.project}/${props.section}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const name = `${org.name} / ${project.name}`;
|
|
||||||
|
|
||||||
const links = sections.map((name) => ({
|
|
||||||
pathname: pathname({
|
|
||||||
org: org.id,
|
|
||||||
project: project.id,
|
|
||||||
section: name
|
|
||||||
}),
|
|
||||||
name
|
|
||||||
}));
|
|
||||||
|
|
||||||
const navMatches = sections.map((name) => {
|
|
||||||
const pattern = pathname({
|
|
||||||
org: org.id,
|
|
||||||
project: project.id,
|
|
||||||
section: name
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Match
|
<Match
|
||||||
component={SectionComponents[name]}
|
component={SectionComponents[name]}
|
||||||
key={name}
|
key={name}
|
||||||
pattern={pattern}
|
pattern={`/:org/projects/:projectId/${name}`}
|
||||||
/>
|
/>
|
||||||
);
|
));
|
||||||
});
|
|
||||||
|
|
||||||
const missPathname = pathname({
|
|
||||||
org: org.id,
|
|
||||||
project: project.id,
|
|
||||||
section: sections[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
const missMatch = !sections.length ? null : (
|
const missMatch = !sections.length ? null : (
|
||||||
<Miss component={Redirect(missPathname)} />
|
<Miss component={Redirect(`/${org.id}/projects/${project.id}/services`)} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section links={links} name={name}>
|
<div>
|
||||||
{navMatches}
|
{navMatches}
|
||||||
{missMatch}
|
{missMatch}
|
||||||
</Section>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Project.propTypes = {
|
Project.propTypes = {
|
||||||
org: React.PropTypes.shape({
|
org: PropTypes.org,
|
||||||
id: React.PropTypes.string,
|
project: PropTypes.project,
|
||||||
name: React.PropTypes.string
|
sections: PropTypes.sections
|
||||||
}),
|
|
||||||
project: React.PropTypes.shape({
|
|
||||||
id: React.PropTypes.string,
|
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
sections: React.PropTypes.arrayOf(
|
|
||||||
React.PropTypes.string
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, {
|
const mapStateToProps = (state, {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
|
||||||
module.exports = () => (
|
const Section = require('./section');
|
||||||
|
|
||||||
|
module.exports = (props) => (
|
||||||
|
<Section {...props}>
|
||||||
<p>instances</p>
|
<p>instances</p>
|
||||||
|
</Section>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
|
||||||
module.exports = () => (
|
const Section = require('./section');
|
||||||
|
|
||||||
|
module.exports = (props) => (
|
||||||
|
<Section {...props}>
|
||||||
<p>manifest</p>
|
<p>manifest</p>
|
||||||
|
</Section>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
|
||||||
module.exports = () => (
|
const Section = require('./section');
|
||||||
|
|
||||||
|
module.exports = (props) => (
|
||||||
|
<Section {...props}>
|
||||||
<p>people</p>
|
<p>people</p>
|
||||||
|
</Section>
|
||||||
);
|
);
|
||||||
|
63
frontend/src/containers/project/section.js
Normal file
63
frontend/src/containers/project/section.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
const React = require('react');
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
|
const selectors = require('@state/selectors');
|
||||||
|
const Section = require('@components/section');
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
orgByIdSelector,
|
||||||
|
projectByIdSelector,
|
||||||
|
projectSectionsSelector
|
||||||
|
} = selectors;
|
||||||
|
|
||||||
|
const OrgSection = ({
|
||||||
|
children,
|
||||||
|
org = {},
|
||||||
|
project = {},
|
||||||
|
sections = []
|
||||||
|
}) => {
|
||||||
|
const name = `${org.name} / ${project.name}`;
|
||||||
|
|
||||||
|
const pathname = (props) => (
|
||||||
|
`/${props.org}/projects/${props.project}/${props.section}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const links = sections.map((name) => ({
|
||||||
|
pathname: pathname({
|
||||||
|
org: org.id,
|
||||||
|
project: project.id,
|
||||||
|
section: name
|
||||||
|
}),
|
||||||
|
name
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section links={links} name={name}>
|
||||||
|
{children}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
OrgSection.propTypes = {
|
||||||
|
children: React.PropTypes.node,
|
||||||
|
org: PropTypes.org,
|
||||||
|
project: PropTypes.project,
|
||||||
|
sections: PropTypes.sections
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state, {
|
||||||
|
params = {}
|
||||||
|
}) => ({
|
||||||
|
org: orgByIdSelector(params.org)(state),
|
||||||
|
project: projectByIdSelector(params.projectId)(state),
|
||||||
|
sections: projectSectionsSelector(state)
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps
|
||||||
|
)(OrgSection);
|
@ -1,5 +1,32 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
const ReactRouter = require('react-router');
|
||||||
|
|
||||||
module.exports = () => (
|
const Section = require('./section');
|
||||||
<p>services</p>
|
const Services = require('@containers/services');
|
||||||
|
const Service = require('@containers/service');
|
||||||
|
|
||||||
|
const {
|
||||||
|
Match
|
||||||
|
} = ReactRouter;
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
const list = (props) => (
|
||||||
|
<Section {...props}>
|
||||||
|
<Services {...props} />
|
||||||
|
</Section>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Match
|
||||||
|
component={list}
|
||||||
|
exactly
|
||||||
|
pattern='/:org/projects/:projectId/services'
|
||||||
|
/>
|
||||||
|
<Match
|
||||||
|
component={Service}
|
||||||
|
pattern='/:org/projects/:projectId/services/:serviceId/:section?'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
|
||||||
module.exports = () => (
|
const Section = require('./section');
|
||||||
|
|
||||||
|
module.exports = (props) => (
|
||||||
|
<Section {...props}>
|
||||||
<p>settings</p>
|
<p>settings</p>
|
||||||
|
</Section>
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ const ReactRouter = require('react-router');
|
|||||||
|
|
||||||
const Button = require('@ui/components/button');
|
const Button = require('@ui/components/button');
|
||||||
const Column = require('@ui/components/column');
|
const Column = require('@ui/components/column');
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
const Row = require('@ui/components/row');
|
const Row = require('@ui/components/row');
|
||||||
const selectors = require('@state/selectors');
|
const selectors = require('@state/selectors');
|
||||||
|
|
||||||
@ -67,16 +68,8 @@ const Projects = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
Projects.propTypes = {
|
Projects.propTypes = {
|
||||||
org: React.PropTypes.shape({
|
org: PropTypes.org,
|
||||||
id: React.PropTypes.string,
|
projects: React.PropTypes.arrayOf(PropTypes.project)
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
projects: React.PropTypes.arrayOf(
|
|
||||||
React.PropTypes.shape({
|
|
||||||
id: React.PropTypes.string,
|
|
||||||
name: React.PropTypes.string
|
|
||||||
})
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state, {
|
const mapStateToProps = (state, {
|
||||||
|
5
frontend/src/containers/service/activity-feed.js
Normal file
5
frontend/src/containers/service/activity-feed.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>activity-feed</p>
|
||||||
|
);
|
5
frontend/src/containers/service/firewall.js
Normal file
5
frontend/src/containers/service/firewall.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>firewall</p>
|
||||||
|
);
|
109
frontend/src/containers/service/index.js
Normal file
109
frontend/src/containers/service/index.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
const React = require('react');
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactRouter = require('react-router');
|
||||||
|
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
|
const Redirect = require('@components/redirect');
|
||||||
|
const Section = require('@components/section');
|
||||||
|
const selectors = require('@state/selectors');
|
||||||
|
|
||||||
|
const SectionComponents = {
|
||||||
|
summary: require('./summary'),
|
||||||
|
instances: require('./instances'),
|
||||||
|
metrics: require('./metrics'),
|
||||||
|
networks: require('./networks'),
|
||||||
|
'tags-metadata': require('./tags-metadata'),
|
||||||
|
'activity-feed': require('./activity-feed'),
|
||||||
|
'service-manifest': require('./service-manifest'),
|
||||||
|
firewall: require('./firewall')
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Match,
|
||||||
|
Miss
|
||||||
|
} = ReactRouter;
|
||||||
|
|
||||||
|
const {
|
||||||
|
orgByIdSelector,
|
||||||
|
serviceSectionsSelector,
|
||||||
|
projectByIdSelector,
|
||||||
|
serviceByIdSelector
|
||||||
|
} = selectors;
|
||||||
|
|
||||||
|
const Service = ({
|
||||||
|
org = {},
|
||||||
|
project = {},
|
||||||
|
sections = [],
|
||||||
|
service = {}
|
||||||
|
}) => {
|
||||||
|
const name = `${org.name} / ${project.name} / ${service.name}`;
|
||||||
|
|
||||||
|
const pathname = ({
|
||||||
|
org,
|
||||||
|
project,
|
||||||
|
service,
|
||||||
|
section
|
||||||
|
}) => (
|
||||||
|
`/${org}/projects/${project}/services/${service}/${section}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const links = sections.map((name) => ({
|
||||||
|
pathname: pathname({
|
||||||
|
org: org.id,
|
||||||
|
project: project.id,
|
||||||
|
service: service.id,
|
||||||
|
section: name
|
||||||
|
}),
|
||||||
|
name
|
||||||
|
}));
|
||||||
|
|
||||||
|
const navMatches = sections.map((name) => (
|
||||||
|
<Match
|
||||||
|
component={SectionComponents[name]}
|
||||||
|
key={name}
|
||||||
|
pattern={`/:org/projects/:projectId/services/:serviceId/${name}`}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
const redirectHref = pathname({
|
||||||
|
org: org.id,
|
||||||
|
project: project.id,
|
||||||
|
service: service.id,
|
||||||
|
section: 'summary'
|
||||||
|
});
|
||||||
|
|
||||||
|
const missMatch = !sections.length ? null : (
|
||||||
|
<Miss component={Redirect(redirectHref)} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section links={links} name={name}>
|
||||||
|
{navMatches}
|
||||||
|
{missMatch}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Service.propTypes = {
|
||||||
|
org: PropTypes.org,
|
||||||
|
project: PropTypes.project,
|
||||||
|
sections: PropTypes.sections,
|
||||||
|
service: PropTypes.service
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state, {
|
||||||
|
params = {}
|
||||||
|
}) => ({
|
||||||
|
org: orgByIdSelector(params.org)(state),
|
||||||
|
project: projectByIdSelector(params.projectId)(state),
|
||||||
|
sections: serviceSectionsSelector(state),
|
||||||
|
service: serviceByIdSelector(params.serviceId)(state)
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps
|
||||||
|
)(Service);
|
5
frontend/src/containers/service/instances.js
Normal file
5
frontend/src/containers/service/instances.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>instances</p>
|
||||||
|
);
|
5
frontend/src/containers/service/metrics.js
Normal file
5
frontend/src/containers/service/metrics.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>metrics</p>
|
||||||
|
);
|
5
frontend/src/containers/service/networks.js
Normal file
5
frontend/src/containers/service/networks.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>networks</p>
|
||||||
|
);
|
5
frontend/src/containers/service/service-manifest.js
Normal file
5
frontend/src/containers/service/service-manifest.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>service-manifest</p>
|
||||||
|
);
|
5
frontend/src/containers/service/summary.js
Normal file
5
frontend/src/containers/service/summary.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>summary</p>
|
||||||
|
);
|
5
frontend/src/containers/service/tags-metadata.js
Normal file
5
frontend/src/containers/service/tags-metadata.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
module.exports = () => (
|
||||||
|
<p>tags-metadata</p>
|
||||||
|
);
|
95
frontend/src/containers/services/index.js
Normal file
95
frontend/src/containers/services/index.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
const React = require('react');
|
||||||
|
const ReactIntl = require('react-intl');
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactRouter = require('react-router');
|
||||||
|
|
||||||
|
const Column = require('@ui/components/column');
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
|
const Row = require('@ui/components/row');
|
||||||
|
const selectors = require('@state/selectors');
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
FormattedMessage
|
||||||
|
} = ReactIntl;
|
||||||
|
|
||||||
|
const {
|
||||||
|
orgByIdSelector,
|
||||||
|
projectByIdSelector,
|
||||||
|
servicesByProjectIdSelector
|
||||||
|
} = selectors;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Link
|
||||||
|
} = ReactRouter;
|
||||||
|
|
||||||
|
const Services = ({
|
||||||
|
org = {},
|
||||||
|
project = {},
|
||||||
|
services = []
|
||||||
|
}) => {
|
||||||
|
const empty = services.length ? null : (
|
||||||
|
<Row>
|
||||||
|
<Column xs={12}>
|
||||||
|
<p name='empty'>
|
||||||
|
<FormattedMessage id='no-personal-projects' />
|
||||||
|
</p>
|
||||||
|
</Column>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
|
||||||
|
const serviceList = (services) => {
|
||||||
|
if (!services || !services.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = services.map((service) => {
|
||||||
|
const to = `/${org.id}/projects/${project.id}/services/${service.id}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={service.id}>
|
||||||
|
<Link activeClassName='active' to={to}>
|
||||||
|
{service.name}
|
||||||
|
</Link>
|
||||||
|
{serviceList(service.services)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{list}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{empty}
|
||||||
|
<Row>
|
||||||
|
{serviceList(services)}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.propTypes = {
|
||||||
|
org: PropTypes.org,
|
||||||
|
project: PropTypes.project,
|
||||||
|
services: React.PropTypes.arrayOf(PropTypes.service)
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state, {
|
||||||
|
params = {}
|
||||||
|
}) => ({
|
||||||
|
org: orgByIdSelector(params.org)(state),
|
||||||
|
project: projectByIdSelector(params.projectId)(state),
|
||||||
|
services: servicesByProjectIdSelector(params.projectId)(state)
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps
|
||||||
|
)(Services);
|
@ -155,36 +155,44 @@
|
|||||||
},
|
},
|
||||||
"data": [{
|
"data": [{
|
||||||
"uuid": "081a792c-47e0-4439-924b-2efa9788ae9e",
|
"uuid": "081a792c-47e0-4439-924b-2efa9788ae9e",
|
||||||
|
"id": "nginx",
|
||||||
"name": "Nginx",
|
"name": "Nginx",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "be227788-74f1-4e5b-a85f-b5c71cbae8d8",
|
"uuid": "be227788-74f1-4e5b-a85f-b5c71cbae8d8",
|
||||||
|
"id": "wordpress",
|
||||||
"name": "Wordpress",
|
"name": "Wordpress",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "6a0eee76-c019-413b-9d5f-44712b55b993",
|
"uuid": "6a0eee76-c019-413b-9d5f-44712b55b993",
|
||||||
|
"id": "nfs",
|
||||||
"name": "NFS",
|
"name": "NFS",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "6d31aff4-de1e-4042-a983-fbd23d5c530c",
|
"uuid": "6d31aff4-de1e-4042-a983-fbd23d5c530c",
|
||||||
|
"id": "memcached",
|
||||||
"name": "Memcached",
|
"name": "Memcached",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "4ee4103e-1a52-4099-a48e-01588f597c70",
|
"uuid": "4ee4103e-1a52-4099-a48e-01588f597c70",
|
||||||
|
"id": "percona",
|
||||||
"name": "Percona",
|
"name": "Percona",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034",
|
"uuid": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034",
|
||||||
|
"id": "primary",
|
||||||
"name": "Primary",
|
"name": "Primary",
|
||||||
"parent": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034",
|
"parent": "4ee4103e-1a52-4099-a48e-01588f597c70",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "c8411ef0-ab39-42cb-a704-d20b170eff31",
|
"uuid": "c8411ef0-ab39-42cb-a704-d20b170eff31",
|
||||||
|
"id": "secondaries",
|
||||||
"name": "Secondaries",
|
"name": "Secondaries",
|
||||||
"parent": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034",
|
"parent": "4ee4103e-1a52-4099-a48e-01588f597c70",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}, {
|
}, {
|
||||||
"uuid": "97c68055-db88-45c9-ad49-f26da4264777",
|
"uuid": "97c68055-db88-45c9-ad49-f26da4264777",
|
||||||
|
"id": "consul",
|
||||||
"name": "Consul",
|
"name": "Consul",
|
||||||
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
"project": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
|
||||||
}]
|
}]
|
||||||
|
31
frontend/src/prop-types.js
Normal file
31
frontend/src/prop-types.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const BaseObject = {
|
||||||
|
uuid: React.PropTypes.string,
|
||||||
|
id: React.PropTypes.string,
|
||||||
|
name: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
const Org = React.PropTypes.shape({
|
||||||
|
...BaseObject,
|
||||||
|
owner: React.PropTypes.string
|
||||||
|
});
|
||||||
|
|
||||||
|
const Project = React.PropTypes.shape({
|
||||||
|
...BaseObject
|
||||||
|
});
|
||||||
|
|
||||||
|
const Service = React.PropTypes.shape({
|
||||||
|
...BaseObject
|
||||||
|
});
|
||||||
|
|
||||||
|
const Sections = React.PropTypes.arrayOf(
|
||||||
|
React.PropTypes.string
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
org: Org,
|
||||||
|
project: Project,
|
||||||
|
sections: Sections,
|
||||||
|
service: Service
|
||||||
|
};
|
@ -10,6 +10,7 @@ module.exports = () => {
|
|||||||
app: require('@state/reducers/app'),
|
app: require('@state/reducers/app'),
|
||||||
intl: require('@state/reducers/intl'),
|
intl: require('@state/reducers/intl'),
|
||||||
orgs: require('@state/reducers/orgs'),
|
orgs: require('@state/reducers/orgs'),
|
||||||
projects: require('@state/reducers/projects')
|
projects: require('@state/reducers/projects'),
|
||||||
|
services: require('@state/reducers/services')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
9
frontend/src/state/reducers/services.js
Normal file
9
frontend/src/state/reducers/services.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const ReduxActions = require('redux-actions');
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleActions
|
||||||
|
} = ReduxActions;
|
||||||
|
|
||||||
|
module.exports = handleActions({
|
||||||
|
'x': (state) => state // somehow handleActions needs at least one reducer
|
||||||
|
}, {});
|
@ -11,17 +11,24 @@ const account = (state) => get(state, 'account.data', {});
|
|||||||
const accountUi = (state) => get(state, 'account.ui', {});
|
const accountUi = (state) => get(state, 'account.ui', {});
|
||||||
const orgUiSections = (state) => get(state, 'orgs.ui.sections', []);
|
const orgUiSections = (state) => get(state, 'orgs.ui.sections', []);
|
||||||
const projectUiSections = (state) => get(state, 'projects.ui.sections', []);
|
const projectUiSections = (state) => get(state, 'projects.ui.sections', []);
|
||||||
|
const serviceUiSections = (state) => get(state, 'services.ui.sections', []);
|
||||||
const orgs = (state) => get(state, 'orgs.data', []);
|
const orgs = (state) => get(state, 'orgs.data', []);
|
||||||
const projects = (state) => get(state, 'projects.data', []);
|
const projects = (state) => get(state, 'projects.data', []);
|
||||||
|
const services = (state) => get(state, 'services.data', []);
|
||||||
|
|
||||||
const projectById= (id) => createSelector(
|
const projectById = (projectId) => createSelector(
|
||||||
projects,
|
projects,
|
||||||
(projects) => find(projects, ['id', id])
|
(projects) => find(projects, ['id', projectId])
|
||||||
);
|
);
|
||||||
|
|
||||||
const orgById = (id) => createSelector(
|
const orgById = (orgId) => createSelector(
|
||||||
orgs,
|
orgs,
|
||||||
(orgs) => find(orgs, ['id', id])
|
(orgs) => find(orgs, ['id', orgId])
|
||||||
|
);
|
||||||
|
|
||||||
|
const serviceById = (serviceId) => createSelector(
|
||||||
|
[services],
|
||||||
|
(services) => find(services, ['id', serviceId])
|
||||||
);
|
);
|
||||||
|
|
||||||
const projectsByOrgId = (orgId) => createSelector(
|
const projectsByOrgId = (orgId) => createSelector(
|
||||||
@ -36,13 +43,28 @@ const orgSections = (orgId) => createSelector(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const servicesByProjectId = (projectId) => createSelector(
|
||||||
|
[services, projectById(projectId)],
|
||||||
|
(services, project) =>
|
||||||
|
services.filter((s) => s.project === project.uuid)
|
||||||
|
.map((service) => ({
|
||||||
|
...service,
|
||||||
|
services: services.filter((s) => s.parent === service.uuid)
|
||||||
|
}))
|
||||||
|
.filter((s) => !s.parent)
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
accountSelector: account,
|
accountSelector: account,
|
||||||
accountUISelector: accountUi,
|
accountUISelector: accountUi,
|
||||||
orgByIdSelector: orgById,
|
orgByIdSelector: orgById,
|
||||||
orgsSelector: orgs,
|
orgsSelector: orgs,
|
||||||
|
servicesSelector: services,
|
||||||
|
serviceByIdSelector: serviceById,
|
||||||
orgSectionsSelector: orgSections,
|
orgSectionsSelector: orgSections,
|
||||||
projectSectionsSelector: projectUiSections,
|
projectSectionsSelector: projectUiSections,
|
||||||
|
serviceSectionsSelector: serviceUiSections,
|
||||||
projectsByOrgIdSelector: projectsByOrgId,
|
projectsByOrgIdSelector: projectsByOrgId,
|
||||||
projectByIdSelector: projectById
|
projectByIdSelector: projectById,
|
||||||
|
servicesByProjectIdSelector: servicesByProjectId
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user