Query redux apollo, nav and menu, load .gql, fragments
This commit is contained in:
parent
baaebb4085
commit
63d16e6f98
@ -4,22 +4,25 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"apollo": "^0.2.2",
|
"apollo": "^0.2.2",
|
||||||
|
"graphql-tag": "^2.0.0",
|
||||||
"immutability-helper": "^2.2.0",
|
"immutability-helper": "^2.2.0",
|
||||||
|
"proxyquire": "^1.7.11",
|
||||||
"react": "^15.5.4",
|
"react": "^15.5.4",
|
||||||
"react-apollo": "^1.2.0",
|
"react-apollo": "^1.2.0",
|
||||||
"react-dom": "^15.5.4",
|
"react-dom": "^15.5.4",
|
||||||
"react-redux": "^5.0.4",
|
"react-redux": "^5.0.4",
|
||||||
"react-router": "^4.1.1",
|
"react-router": "^4.1.1",
|
||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"redux": "^3.6.0"
|
"redux": "^3.6.0",
|
||||||
|
"rewire": "^2.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"react-scripts": "0.9.5"
|
"react-scripts": "0.9.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "PORT=3006 react-scripts start",
|
"start": "PORT=3006 node scripts/customized-config start",
|
||||||
"build": "react-scripts build",
|
"build": "node scripts/customized-config build",
|
||||||
"test": "react-scripts test --env=jsdom",
|
"test": "node scripts/customized-config test --env=jsdom",
|
||||||
"eject": "react-scripts eject"
|
"eject": "node scripts/customized-config eject"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
spikes/graphql/apollo-redux/scripts/config-overrides.dev.js
Normal file
14
spikes/graphql/apollo-redux/scripts/config-overrides.dev.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = function(config) {
|
||||||
|
// Add support for loading .graphql files
|
||||||
|
config.module.loaders[0].exclude.push(/\.(graphql|gql)$/);
|
||||||
|
|
||||||
|
config.module.loaders.push({
|
||||||
|
test: /\.(graphql|gql)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: require.resolve('graphql-tag/loader'),
|
||||||
|
});
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
72
spikes/graphql/apollo-redux/scripts/customized-config.js
Normal file
72
spikes/graphql/apollo-redux/scripts/customized-config.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
This module runs the scripts from react-scripts (Create React App)
|
||||||
|
and gives an opportunity to override the Webpack config by creating
|
||||||
|
a "config-overrides.dev.js" or "config-overrides.prod.js" file in the
|
||||||
|
root of the project.
|
||||||
|
|
||||||
|
The config-override file should export a single function that takes a
|
||||||
|
config and returns the modified config, like this:
|
||||||
|
|
||||||
|
module.exports = function(webpackConfig) {
|
||||||
|
return webpackConfig;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
var rewire = require('rewire');
|
||||||
|
var proxyquire = require('proxyquire');
|
||||||
|
|
||||||
|
switch(process.argv[2]) {
|
||||||
|
// The "start" script is run during development mode
|
||||||
|
case 'start':
|
||||||
|
rewireModule('react-scripts/scripts/start.js', loadCustomizer('./config-overrides.dev'));
|
||||||
|
break;
|
||||||
|
// The "build" script is run to produce a production bundle
|
||||||
|
case 'build':
|
||||||
|
rewireModule('react-scripts/scripts/build.js', loadCustomizer('./config-overrides.prod'));
|
||||||
|
break;
|
||||||
|
// The "test" script runs all the tests with Jest
|
||||||
|
case 'test':
|
||||||
|
// Load customizations from the config-overrides.testing file.
|
||||||
|
// That file should export a single function that takes a config and returns a config
|
||||||
|
let customizer = loadCustomizer('./config-overrides.testing');
|
||||||
|
proxyquire('react-scripts/scripts/test.js', {
|
||||||
|
// When test.js asks for '../utils/createJestConfig' it will get this instead:
|
||||||
|
'../utils/createJestConfig': (...args) => {
|
||||||
|
// Use the existing createJestConfig function to create a config, then pass
|
||||||
|
// it through the customizer
|
||||||
|
var createJestConfig = require('react-scripts/utils/createJestConfig');
|
||||||
|
return customizer(createJestConfig(...args));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('customized-config only supports "start", "build", and "test" options.');
|
||||||
|
process.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to load the given module and return null if it fails.
|
||||||
|
function loadCustomizer(module) {
|
||||||
|
try {
|
||||||
|
return require(module);
|
||||||
|
} catch(e) {
|
||||||
|
if(e.code !== "MODULE_NOT_FOUND") {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the module doesn't exist, return a
|
||||||
|
// noop that simply returns the config it's given.
|
||||||
|
return config => config;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewireModule(modulePath, customizer) {
|
||||||
|
// Load the module with `rewire`, which allows modifying the
|
||||||
|
// script's internal variables.
|
||||||
|
let defaults = rewire(modulePath);
|
||||||
|
|
||||||
|
// Reach into the module, grab its global 'config' variable,
|
||||||
|
// pass it through the customizer function, and then set it back.
|
||||||
|
// 'config' is Create React App's built-in Webpack config.
|
||||||
|
let config = defaults.__get__('config');
|
||||||
|
config = customizer(Object.assign({}, config));
|
||||||
|
defaults.__set__('config', config);
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { gql, graphql } from 'react-apollo';
|
import { graphql } from 'react-apollo';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import update from 'immutability-helper';
|
import DeploymentGroupsQuery from '../../graphql/DeploymentGroups.gql';
|
||||||
|
|
||||||
class DeploymentGroupList extends Component {
|
class DeploymentGroupList extends Component {
|
||||||
|
|
||||||
@ -38,17 +38,7 @@ class DeploymentGroupList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deploymentGroups = gql`
|
const DeploymentGroupListWithData = graphql(DeploymentGroupsQuery, {
|
||||||
query {
|
|
||||||
deploymentGroups {
|
|
||||||
uuid
|
|
||||||
name
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DeploymentGroupListWithData = graphql(deploymentGroups, {
|
|
||||||
props: ({ data: { deploymentGroups, loading, error }}) => ({
|
props: ({ data: { deploymentGroups, loading, error }}) => ({
|
||||||
deploymentGroups,
|
deploymentGroups,
|
||||||
loading,
|
loading,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { gql, graphql } from 'react-apollo';
|
import { graphql } from 'react-apollo';
|
||||||
|
import InstancesQuery from '../../graphql/Instances.gql';
|
||||||
|
|
||||||
class InstanceList extends Component {
|
class InstanceList extends Component {
|
||||||
|
|
||||||
@ -28,20 +29,7 @@ class InstanceList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const instances = gql`
|
const InstanceListWithData = graphql(InstancesQuery, {
|
||||||
query Instances($deploymentGroupId: String!){
|
|
||||||
deploymentGroup(id: $deploymentGroupId) {
|
|
||||||
services {
|
|
||||||
instances {
|
|
||||||
uuid
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const InstanceListWithData = graphql(instances, {
|
|
||||||
options(props) {
|
options(props) {
|
||||||
return {
|
return {
|
||||||
variables: {
|
variables: {
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
class Breadcrumb extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const {
|
||||||
|
deploymentGroup,
|
||||||
|
service,
|
||||||
|
match,
|
||||||
|
location
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const dgLink = deploymentGroup ?
|
||||||
|
<Link to={`/deployment-groups/${deploymentGroup.id}`}>
|
||||||
|
{deploymentGroup.name}
|
||||||
|
</Link> : null;
|
||||||
|
const sLink = service ?
|
||||||
|
<Link to={`/deployment-groups/${deploymentGroup.id}/services/${service.id}`}>
|
||||||
|
{service.name}
|
||||||
|
</Link> : null;
|
||||||
|
let breadcrumb = dgLink && sLink ?
|
||||||
|
<p>{dgLink} / {sLink}</p> : dgLink ?
|
||||||
|
<p>{dgLink}</p> : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h3>{breadcrumb}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConnectedBreadcrumb = connect(
|
||||||
|
(state, ownProps) => {
|
||||||
|
|
||||||
|
const params = ownProps.match.params;
|
||||||
|
const deploymentGroupId = params.deploymentGroup;
|
||||||
|
const serviceId = params.service;
|
||||||
|
const apolloData = state.apollo.data;
|
||||||
|
const keys = Object.keys(apolloData);
|
||||||
|
|
||||||
|
let deploymentGroup, service;
|
||||||
|
if(keys.length) {
|
||||||
|
// These should be selectors
|
||||||
|
if(deploymentGroupId) {
|
||||||
|
deploymentGroup = keys.reduce((dg, k) =>
|
||||||
|
apolloData[k].__typename === 'DeploymentGroup' &&
|
||||||
|
apolloData[k].id === deploymentGroupId ?
|
||||||
|
apolloData[k] : dg, {});
|
||||||
|
if(serviceId) {
|
||||||
|
service = keys.reduce((s, k) =>
|
||||||
|
apolloData[k].__typename === 'Service' &&
|
||||||
|
apolloData[k].id === serviceId ?
|
||||||
|
apolloData[k] : s, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
deploymentGroup,
|
||||||
|
service
|
||||||
|
};
|
||||||
|
},
|
||||||
|
(dispatch) => ({})
|
||||||
|
)(Breadcrumb);
|
||||||
|
|
||||||
|
export default ConnectedBreadcrumb;
|
@ -0,0 +1,2 @@
|
|||||||
|
export { default as Breadcrumb } from './breadcrumb';
|
||||||
|
export { default as Menu } from './menu';
|
@ -0,0 +1,68 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
class Menu extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const {
|
||||||
|
sections,
|
||||||
|
matchUrl
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const menu = sections ?
|
||||||
|
sections.map((s, i) =>
|
||||||
|
<Link key={i} to={`${matchUrl}/${s.id}`}> {s.name} </Link>) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h4>{menu}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConnectedMenu = connect(
|
||||||
|
(state, ownProps) => {
|
||||||
|
|
||||||
|
const params = ownProps.match.params;
|
||||||
|
const matchUrl = ownProps.match.url;
|
||||||
|
const deploymentGroupId = params.deploymentGroup;
|
||||||
|
const serviceId = params.service;
|
||||||
|
|
||||||
|
let sections;
|
||||||
|
// To come from Redux store
|
||||||
|
if(deploymentGroupId && serviceId) {
|
||||||
|
sections = [{
|
||||||
|
name: 'Metrics',
|
||||||
|
id: 'metrics'
|
||||||
|
}, {
|
||||||
|
name: 'Single Metrics',
|
||||||
|
id: 'single-metrics'
|
||||||
|
}, {
|
||||||
|
name: 'Instances',
|
||||||
|
id: 'instances'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
else if(deploymentGroupId) {
|
||||||
|
sections = [{
|
||||||
|
name: 'Services',
|
||||||
|
id: 'services'
|
||||||
|
}, {
|
||||||
|
name: 'Instances',
|
||||||
|
id: 'instances'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sections,
|
||||||
|
matchUrl
|
||||||
|
};
|
||||||
|
},
|
||||||
|
(dispatch) => ({})
|
||||||
|
)(Menu);
|
||||||
|
|
||||||
|
export default ConnectedMenu;
|
@ -0,0 +1,2 @@
|
|||||||
|
export { default as ServiceMetrics } from './metrics';
|
||||||
|
export { default as SingleMetrics } from './single-metrics';
|
@ -0,0 +1,56 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { graphql } from 'react-apollo';
|
||||||
|
import MetricsQuery from '../../graphql/Metrics.gql';
|
||||||
|
|
||||||
|
class Metrics extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const {
|
||||||
|
instances,
|
||||||
|
metrics
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h4>Metrics</h4>
|
||||||
|
<p>{JSON.stringify(metrics)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MetricsWithData = graphql(MetricsQuery, {
|
||||||
|
options(props) {
|
||||||
|
return {
|
||||||
|
variables: {
|
||||||
|
deploymentGroupId: props.match.params.deploymentGroup
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: ({ data: { deploymentGroup, loading, error } }) => {
|
||||||
|
|
||||||
|
const instances = deploymentGroup && deploymentGroup.services ?
|
||||||
|
deploymentGroup.services.reduce((instances, service) =>
|
||||||
|
instances.concat(service.instances), []) : null;
|
||||||
|
|
||||||
|
const metrics = instances ? instances.reduce((metrics, instance) =>
|
||||||
|
metrics.concat(instance.metrics.map((m) =>
|
||||||
|
Object.assign({}, m, {
|
||||||
|
instance: {
|
||||||
|
uuid: instance.uuid,
|
||||||
|
name: instance.name
|
||||||
|
}}))), []) : null;
|
||||||
|
|
||||||
|
return ({
|
||||||
|
instances,
|
||||||
|
metrics,
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})(Metrics)
|
||||||
|
|
||||||
|
export default MetricsWithData;
|
@ -0,0 +1,35 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { graphql } from 'react-apollo';
|
||||||
|
import SingleMetricsQuery from '../../graphql/SingleMetrics.gql';
|
||||||
|
|
||||||
|
class SingleMetrics extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const {
|
||||||
|
metrics
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h4>Metrics</h4>
|
||||||
|
<p>{JSON.stringify(metrics)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SingleMetricsWithData = graphql(SingleMetricsQuery, {
|
||||||
|
options: {
|
||||||
|
pollInterval: 15*1000
|
||||||
|
},
|
||||||
|
props: ({ data: { instanceMetric, loading, error } }) => ({
|
||||||
|
metrics: instanceMetric,
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
})(SingleMetrics)
|
||||||
|
|
||||||
|
export default SingleMetricsWithData;
|
@ -1,6 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { gql, graphql } from 'react-apollo';
|
import { graphql } from 'react-apollo';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import ServicesQuery from '../../graphql/Services.gql';
|
||||||
|
|
||||||
class ServiceList extends Component {
|
class ServiceList extends Component {
|
||||||
|
|
||||||
@ -36,19 +37,7 @@ class ServiceList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const services = gql`
|
const ServiceListWithData = graphql(ServicesQuery, {
|
||||||
query Services($deploymentGroupId: String!){
|
|
||||||
deploymentGroup(id: $deploymentGroupId) {
|
|
||||||
services {
|
|
||||||
uuid
|
|
||||||
name
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ServiceListWithData = graphql(services, {
|
|
||||||
options(props) {
|
options(props) {
|
||||||
return {
|
return {
|
||||||
variables: {
|
variables: {
|
||||||
|
11
spikes/graphql/apollo-redux/src/graphql/DeploymentGroups.gql
Normal file
11
spikes/graphql/apollo-redux/src/graphql/DeploymentGroups.gql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
query DeploymentGroups {
|
||||||
|
deploymentGroups {
|
||||||
|
...DeploymentGroupInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment DeploymentGroupInfo on DeploymentGroup {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
16
spikes/graphql/apollo-redux/src/graphql/Instances.gql
Normal file
16
spikes/graphql/apollo-redux/src/graphql/Instances.gql
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
query Instances($deploymentGroupId: String!){
|
||||||
|
deploymentGroup(id: $deploymentGroupId) {
|
||||||
|
uuid
|
||||||
|
id
|
||||||
|
name
|
||||||
|
services {
|
||||||
|
uuid
|
||||||
|
id
|
||||||
|
name
|
||||||
|
instances {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
spikes/graphql/apollo-redux/src/graphql/Metrics.gql
Normal file
25
spikes/graphql/apollo-redux/src/graphql/Metrics.gql
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
query Instances($deploymentGroupId: String!){
|
||||||
|
deploymentGroup(id: $deploymentGroupId) {
|
||||||
|
uuid
|
||||||
|
id
|
||||||
|
name
|
||||||
|
services {
|
||||||
|
uuid
|
||||||
|
id
|
||||||
|
name
|
||||||
|
instances {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
metrics {
|
||||||
|
type {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
timestamp
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
fragment MetricsData {
|
||||||
|
timestamp
|
||||||
|
value
|
||||||
|
}
|
12
spikes/graphql/apollo-redux/src/graphql/Services.gql
Normal file
12
spikes/graphql/apollo-redux/src/graphql/Services.gql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
query Services($deploymentGroupId: String!){
|
||||||
|
deploymentGroup(id: $deploymentGroupId) {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
id
|
||||||
|
services {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
spikes/graphql/apollo-redux/src/graphql/SingleMetrics.gql
Normal file
13
spikes/graphql/apollo-redux/src/graphql/SingleMetrics.gql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
query SingleMetrics {
|
||||||
|
instanceMetric {
|
||||||
|
type {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
timestamp
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,10 +7,15 @@ import {
|
|||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import { Container } from '../components/layout';
|
import { Container } from '../components/layout';
|
||||||
|
|
||||||
|
import { Breadcrumb, Menu } from '../containers/navigation';
|
||||||
|
|
||||||
import { DeploymentGroupList } from '../containers/deployment-groups';
|
import { DeploymentGroupList } from '../containers/deployment-groups';
|
||||||
import { ServiceList } from '../containers/services';
|
import { ServiceList } from '../containers/services';
|
||||||
import { InstanceList } from '../containers/instances';
|
import { InstanceList } from '../containers/instances';
|
||||||
|
|
||||||
|
import { ServiceMetrics, SingleMetrics } from '../containers/service';
|
||||||
|
|
||||||
const rootRedirect = (p) => (
|
const rootRedirect = (p) => (
|
||||||
<Redirect to='/deployment-groups' />
|
<Redirect to='/deployment-groups' />
|
||||||
);
|
);
|
||||||
@ -23,6 +28,15 @@ const Router = (
|
|||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Container>
|
<Container>
|
||||||
|
|
||||||
|
<Switch>
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup/services/:service' component={Breadcrumb} />
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup' component={Breadcrumb} />
|
||||||
|
</Switch>
|
||||||
|
<Switch>
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup/services/:service' component={Menu} />
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup' component={Menu} />
|
||||||
|
</Switch>
|
||||||
|
|
||||||
<Route path='/' exact component={rootRedirect} />
|
<Route path='/' exact component={rootRedirect} />
|
||||||
<Route path='/deployment-groups' exact component={DeploymentGroupList} />
|
<Route path='/deployment-groups' exact component={DeploymentGroupList} />
|
||||||
|
|
||||||
@ -30,6 +44,8 @@ const Router = (
|
|||||||
<Route path='/deployment-groups/:deploymentGroup/services' exact component={ServiceList} />
|
<Route path='/deployment-groups/:deploymentGroup/services' exact component={ServiceList} />
|
||||||
|
|
||||||
<Route path='/deployment-groups/:deploymentGroup/services/:service/instances' exact component={InstanceList} />
|
<Route path='/deployment-groups/:deploymentGroup/services/:service/instances' exact component={InstanceList} />
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup/services/:service/metrics' exact component={ServiceMetrics} />
|
||||||
|
<Route path='/deployment-groups/:deploymentGroup/services/:service/single-metrics' exact component={SingleMetrics} />
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
@ -2,6 +2,10 @@ import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
|
|||||||
import { ApolloClient, createNetworkInterface } from 'react-apollo';
|
import { ApolloClient, createNetworkInterface } from 'react-apollo';
|
||||||
|
|
||||||
export const client = new ApolloClient({
|
export const client = new ApolloClient({
|
||||||
|
dataIdFromObject: o => {
|
||||||
|
const id = o.id ? o.id : o.uuid ? o.uuid : o.timestamp ? o.timestamp : 'apollo-cache-key-not-defined';
|
||||||
|
return `${o.__typename}:${id}`;
|
||||||
|
},
|
||||||
networkInterface: createNetworkInterface({
|
networkInterface: createNetworkInterface({
|
||||||
uri: 'http://localhost:3000/graphql'
|
uri: 'http://localhost:3000/graphql'
|
||||||
})
|
})
|
||||||
|
@ -2154,6 +2154,13 @@ filesize@3.3.0:
|
|||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.3.0.tgz#53149ea3460e3b2e024962a51648aa572cf98122"
|
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.3.0.tgz#53149ea3460e3b2e024962a51648aa572cf98122"
|
||||||
|
|
||||||
|
fill-keys@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20"
|
||||||
|
dependencies:
|
||||||
|
is-object "~1.0.1"
|
||||||
|
merge-descriptors "~1.0.0"
|
||||||
|
|
||||||
fill-range@^2.1.0:
|
fill-range@^2.1.0:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
|
||||||
@ -2761,6 +2768,10 @@ is-number@^2.0.2, is-number@^2.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
kind-of "^3.0.2"
|
kind-of "^3.0.2"
|
||||||
|
|
||||||
|
is-object@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
|
||||||
|
|
||||||
is-path-cwd@^1.0.0:
|
is-path-cwd@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
||||||
@ -3444,7 +3455,7 @@ memory-fs@~0.4.1:
|
|||||||
errno "^0.1.3"
|
errno "^0.1.3"
|
||||||
readable-stream "^2.0.1"
|
readable-stream "^2.0.1"
|
||||||
|
|
||||||
merge-descriptors@1.0.1:
|
merge-descriptors@1.0.1, merge-descriptors@~1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||||
|
|
||||||
@ -3512,6 +3523,10 @@ minimist@^1.1.1, minimist@^1.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimist "0.0.8"
|
minimist "0.0.8"
|
||||||
|
|
||||||
|
module-not-found-error@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0"
|
||||||
|
|
||||||
ms@0.7.1:
|
ms@0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
|
||||||
@ -4221,6 +4236,14 @@ proxy-addr@~1.1.3:
|
|||||||
forwarded "~0.1.0"
|
forwarded "~0.1.0"
|
||||||
ipaddr.js "1.3.0"
|
ipaddr.js "1.3.0"
|
||||||
|
|
||||||
|
proxyquire@^1.7.11:
|
||||||
|
version "1.7.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.7.11.tgz#13b494eb1e71fb21cc3ebe3699e637d3bec1af9e"
|
||||||
|
dependencies:
|
||||||
|
fill-keys "^1.0.2"
|
||||||
|
module-not-found-error "^1.0.0"
|
||||||
|
resolve "~1.1.7"
|
||||||
|
|
||||||
prr@~0.0.0:
|
prr@~0.0.0:
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
|
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
|
||||||
@ -4650,7 +4673,7 @@ resolve-pathname@^2.0.0:
|
|||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944"
|
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944"
|
||||||
|
|
||||||
resolve@1.1.7:
|
resolve@1.1.7, resolve@~1.1.7:
|
||||||
version "1.1.7"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||||
|
|
||||||
@ -4667,6 +4690,10 @@ restore-cursor@^1.0.1:
|
|||||||
exit-hook "^1.0.0"
|
exit-hook "^1.0.0"
|
||||||
onetime "^1.0.0"
|
onetime "^1.0.0"
|
||||||
|
|
||||||
|
rewire@^2.5.2:
|
||||||
|
version "2.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rewire/-/rewire-2.5.2.tgz#6427de7b7feefa7d36401507eb64a5385bc58dc7"
|
||||||
|
|
||||||
right-align@^0.1.1:
|
right-align@^0.1.1:
|
||||||
version "0.1.3"
|
version "0.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
|
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"graphql": "^0.9.6",
|
"graphql": "^0.9.6",
|
||||||
"graphql-server-hapi": "^0.7.2",
|
"graphql-server-hapi": "^0.7.2",
|
||||||
|
"graphql-subscriptions": "^0.3.1",
|
||||||
"graphql-tools": "^0.11.0",
|
"graphql-tools": "^0.11.0",
|
||||||
"hapi": "^16.1.1",
|
"hapi": "^16.1.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
|
128636
spikes/graphql/graphql-server/src/mock-data/datasets/dataset-leak.json
Normal file
128636
spikes/graphql/graphql-server/src/mock-data/datasets/dataset-leak.json
Normal file
File diff suppressed because it is too large
Load Diff
126384
spikes/graphql/graphql-server/src/mock-data/datasets/dataset-normal.json
Normal file
126384
spikes/graphql/graphql-server/src/mock-data/datasets/dataset-normal.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
|||||||
|
node_memory_rss_bytes
|
||||||
|
node_memory_heap_total_bytes
|
||||||
|
node_memory_heap_used_bytes
|
||||||
|
process_heap_bytes
|
||||||
|
process_resident_memory_bytes
|
||||||
|
process_virtual_memory_bytes
|
||||||
|
process_cpu_seconds_total
|
||||||
|
process_cpu_system_seconds_total
|
||||||
|
process_cpu_user_seconds_total
|
||||||
|
node_lag_duration_milliseconds
|
||||||
|
http_request_duration_milliseconds
|
20
spikes/graphql/graphql-server/src/mock-data/metrics.js
Normal file
20
spikes/graphql/graphql-server/src/mock-data/metrics.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import normalMetricDataJson from './datasets/dataset-normal.json';
|
||||||
|
import leakMetricDataJson from './datasets/dataset-leak.json';
|
||||||
|
|
||||||
|
const normaliseMetricDataset = (metricDataset) => {
|
||||||
|
return Object.keys(metricDataset).reduce((dataset, type) => {
|
||||||
|
dataset[type] = metricDataset[type].map((ds) => ({
|
||||||
|
timestamp: ds[0],
|
||||||
|
value: ds[1]
|
||||||
|
}))
|
||||||
|
return dataset;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalMetricData = normaliseMetricDataset(normalMetricDataJson);
|
||||||
|
const leakMetricData = normaliseMetricDataset(leakMetricDataJson);
|
||||||
|
|
||||||
|
export {
|
||||||
|
normalMetricData,
|
||||||
|
leakMetricData
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { find, filter } from 'lodash';
|
import { find, filter } from 'lodash';
|
||||||
import paramCase from 'param-case';
|
|
||||||
import data from './mock-data';
|
import data from './mock-data';
|
||||||
|
import { normalMetricData, leakMetricData } from './mock-data/metrics';
|
||||||
|
|
||||||
const portal = { username: 'juditgreskovits', host: 'dockerhost'};
|
const portal = { username: 'juditgreskovits', host: 'dockerhost'};
|
||||||
const deploymentGroups = data.projects.data;
|
const deploymentGroups = data.projects.data;
|
||||||
@ -9,6 +9,14 @@ const instances = data.instances.data;
|
|||||||
const metricTypes = data.metrics.data.types;
|
const metricTypes = data.metrics.data.types;
|
||||||
const datacenters = data.datacenters.data;
|
const datacenters = data.datacenters.data;
|
||||||
|
|
||||||
|
const count = 10;
|
||||||
|
let index = 0;
|
||||||
|
const getInstanceMetricData = (dataset, type) => {
|
||||||
|
return dataset[type].slice(index, index + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tick = setInterval(() => index++, 15*1000);
|
||||||
|
|
||||||
const resolveFunctions = {
|
const resolveFunctions = {
|
||||||
Query: {
|
Query: {
|
||||||
portal() {
|
portal() {
|
||||||
@ -67,6 +75,17 @@ const resolveFunctions = {
|
|||||||
datacenters() {
|
datacenters() {
|
||||||
return datacenters;
|
return datacenters;
|
||||||
},
|
},
|
||||||
|
// tmp test
|
||||||
|
instanceMetric() {
|
||||||
|
return {
|
||||||
|
type: {
|
||||||
|
uuid: 'node_memory_rss_bytes',
|
||||||
|
id: 'node_memory_rss_bytes',
|
||||||
|
name: 'node_memory_rss_bytes',
|
||||||
|
},
|
||||||
|
data: getInstanceMetricData(leakMetricData, 'node_memory_rss_bytes')
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
DeploymentGroup: {
|
DeploymentGroup: {
|
||||||
services(deploymentGroup) {
|
services(deploymentGroup) {
|
||||||
@ -83,6 +102,18 @@ const resolveFunctions = {
|
|||||||
find(metricTypes, { uuid: metric.type })) : []
|
find(metricTypes, { uuid: metric.type })) : []
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Instance: {
|
||||||
|
metrics(instance) {
|
||||||
|
return ([{
|
||||||
|
type: {
|
||||||
|
uuid: 'metric-type-uuid',
|
||||||
|
id: 'metric-type-id',
|
||||||
|
name: 'metric-type-name'
|
||||||
|
},
|
||||||
|
data: normalMetricData.node_memory_rss_bytes
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default resolveFunctions;
|
export default resolveFunctions;
|
||||||
|
@ -77,6 +77,7 @@ type Package {
|
|||||||
type Instance {
|
type Instance {
|
||||||
uuid: String!
|
uuid: String!
|
||||||
name: String!
|
name: String!
|
||||||
|
id: String!
|
||||||
deploymentGoup: String!
|
deploymentGoup: String!
|
||||||
service: String!
|
service: String!
|
||||||
metrics: [InstanceMetric]!
|
metrics: [InstanceMetric]!
|
||||||
@ -88,9 +89,8 @@ type InstanceMetric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MetricData {
|
type MetricData {
|
||||||
type: MetricType!
|
timestamp: Int!
|
||||||
timestamp: Date!
|
value: Float!
|
||||||
value: Int!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Datacenter {
|
type Datacenter {
|
||||||
@ -108,8 +108,11 @@ type Query {
|
|||||||
instances(serviceUuid: String, serviceId: String): [Instance]
|
instances(serviceUuid: String, serviceId: String): [Instance]
|
||||||
instance(uuid: String, id: String): Instance
|
instance(uuid: String, id: String): Instance
|
||||||
metricTypes: [MetricType]
|
metricTypes: [MetricType]
|
||||||
|
metricData(instanceUuid: String!, metricType: String!, from: Date!, to: Date!): [InstanceMetric]!
|
||||||
package: Package
|
package: Package
|
||||||
datacenters: [Datacenter]
|
datacenters: [Datacenter]
|
||||||
|
# tmp test
|
||||||
|
instanceMetric: InstanceMetric!
|
||||||
}
|
}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
@ -775,7 +775,7 @@ end-of-stream@1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
once "~1.3.0"
|
once "~1.3.0"
|
||||||
|
|
||||||
es6-promise@^3.0.2:
|
es6-promise@^3.0.2, es6-promise@^3.2.1:
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
|
||||||
|
|
||||||
@ -988,6 +988,12 @@ graphql-server-module-graphiql@^0.7.2:
|
|||||||
version "0.7.2"
|
version "0.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.7.2.tgz#aa1f2a26eadbf7127c1b077e633d5086da52b330"
|
resolved "https://registry.yarnpkg.com/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.7.2.tgz#aa1f2a26eadbf7127c1b077e633d5086da52b330"
|
||||||
|
|
||||||
|
graphql-subscriptions@^0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.3.1.tgz#0cedc2d507420cf26cf414080b079f05402f0303"
|
||||||
|
dependencies:
|
||||||
|
es6-promise "^3.2.1"
|
||||||
|
|
||||||
graphql-tools@^0.11.0:
|
graphql-tools@^0.11.0:
|
||||||
version "0.11.0"
|
version "0.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-0.11.0.tgz#14c372f6ddad7e63a757094d541a937d6b31b7da"
|
resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-0.11.0.tgz#14c372f6ddad7e63a757094d541a937d6b31b7da"
|
||||||
|
Loading…
Reference in New Issue
Block a user