Make LayoutRenderer host agnostic and shared

pull/549/head
Andrew Watkins 2016-11-14 15:16:33 -08:00
parent 01ae8b1b82
commit f5c58f70cd
8 changed files with 21 additions and 157 deletions

View File

@ -81,10 +81,3 @@ export function getAppsForHosts(proxyLink, hosts, appMappings) {
return newHosts;
});
}
export function fetchLayouts() {
return AJAX({
url: `/chronograf/v1/layouts`,
method: 'GET',
});
}

View File

@ -1,101 +0,0 @@
import React, {PropTypes} from 'react';
import AutoRefresh from 'shared/components/AutoRefresh';
import LineGraph from 'shared/components/LineGraph';
import ReactGridLayout from 'react-grid-layout';
import _ from 'lodash';
const RefreshingLineGraph = AutoRefresh(LineGraph);
export const LayoutRenderer = React.createClass({
propTypes: {
timeRange: PropTypes.shape({
defaultGroupBy: PropTypes.string.isRequired,
queryValue: PropTypes.string.isRequired,
}).isRequired,
cells: PropTypes.arrayOf(
PropTypes.shape({
queries: PropTypes.arrayOf(
PropTypes.shape({
rp: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
database: PropTypes.string.isRequired,
groupbys: PropTypes.arrayOf(PropTypes.string),
wheres: PropTypes.arrayOf(PropTypes.string),
}).isRequired
).isRequired,
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
w: PropTypes.number.isRequired,
h: PropTypes.number.isRequired,
i: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}).isRequired
),
autoRefreshMs: PropTypes.number.isRequired,
host: PropTypes.string.isRequired,
source: PropTypes.string,
},
getInitialState() {
return ({
layout: _.without(this.props.cells, ['queries']),
});
},
buildQuery(q) {
const {timeRange, host} = this.props;
const {wheres, groupbys} = q;
let text = q.text;
text += ` where \"host\" = '${host}' and time > ${timeRange.queryValue}`;
if (wheres && wheres.length > 0) {
text += ` and ${wheres.join(' and ')}`;
}
if (groupbys) {
if (groupbys.find((g) => g.includes("time"))) {
text += ` group by ${groupbys.join(',')}`;
} else if (groupbys.length > 0) {
text += ` group by time(${timeRange.defaultGroupBy}),${groupbys.join(',')}`;
} else {
text += ` group by time(${timeRange.defaultGroupBy})`;
}
} else {
text += ` group by time(${timeRange.defaultGroupBy})`;
}
return text;
},
generateGraphs() {
const {autoRefreshMs, source} = this.props;
return this.props.cells.map((cell) => {
const qs = cell.queries.map((q) => {
return Object.assign({}, q, {
host: source,
text: this.buildQuery(q),
});
});
return (
<div key={cell.i}>
<h2 className="hosts-graph-heading">{cell.name}</h2>
<div className="hosts-graph graph-panel__graph-container">
<RefreshingLineGraph
queries={qs}
autoRefresh={autoRefreshMs}
/>
</div>
</div>
);
});
},
render() {
return (
<ReactGridLayout layout={this.state.layout} isDraggable={false} isResizable={false} cols={12} rowHeight={90} width={1200}>
{this.generateGraphs()}
</ReactGridLayout>
);
},
});
export default LayoutRenderer;

View File

@ -1,8 +1,9 @@
import React, {PropTypes} from 'react';
import LayoutRenderer from '../components/LayoutRenderer';
import LayoutRenderer from 'shared/components/LayoutRenderer';
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
import {getMappings, getAppsForHosts, fetchLayouts} from '../apis';
import {getMappings, getAppsForHosts} from '../apis';
import {fetchLayouts} from 'shared/apis';
export const HostPage = React.createClass({
propTypes: {

View File

@ -1,41 +0,0 @@
import {proxy} from 'utils/queryUrlGenerator';
import AJAX from 'utils/ajax';
import _ from 'lodash';
export function getAppsForHosts(proxyLink, hosts, appMappings) {
const measurements = appMappings.map((m) => `^${m.measurement}$`).join('|');
const measurementsToApps = _.zipObject(appMappings.map(m => m.measurement), appMappings.map(m => m.name));
return proxy({
source: proxyLink,
query: `show series from /${measurements}/`,
db: 'telegraf',
}).then((resp) => {
const newHosts = Object.assign({}, hosts);
const allSeries = _.get(resp, ['data', 'results', '0', 'series', '0', 'values'], []);
allSeries.forEach(([series]) => {
const matches = series.match(/(\w*).*,host=([^,]*)/);
if (!matches || matches.length !== 3) { // eslint-disable-line no-magic-numbers
return;
}
const measurement = matches[1];
const host = matches[2];
if (!newHosts[host]) {
return;
}
if (!newHosts[host].apps) {
newHosts[host].apps = [];
}
newHosts[host].apps = _.uniq(newHosts[host].apps.concat(measurementsToApps[measurement]));
});
return newHosts;
});
}
export function fetchLayouts() {
return AJAX({
url: `/chronograf/v1/layouts`,
method: 'GET',
});
}

View File

@ -1,5 +1,5 @@
import React, {PropTypes} from 'react';
import LayoutRenderer from '../components/LayoutRenderer';
import LayoutRenderer from 'shared/components/LayoutRenderer';
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
@ -57,13 +57,19 @@ export const KubernetesPage = React.createClass({
render() {
const {layouts} = this.props;
const {timeRange} = this.state;
const emptyState = (
<div className="generic-empty-state">
<span className="icon alert-triangle"></span>
<h4>No Kubernetes configuration found</h4>
</div>
);
return (
<div className="host-dashboard hosts-page">
<div className="enterprise-header hosts-dashboard-header">
<div className="enterprise-header__container">
<div className="enterprise-header__left">
<h2>Kubernetes Dashboard</h2>
<h1>Kubernetes Dashboard</h1>
</div>
<div className="enterprise-header__right">
<h1>Range:</h1>
@ -74,7 +80,7 @@ export const KubernetesPage = React.createClass({
<div className="hosts-page-scroll-container">
<div className="container-fluid hosts-dashboard">
<div className="row">
{ (layouts.length > 0) ? this.renderLayouts(layouts) : '' }
{layouts.length ? this.renderLayouts(layouts) : emptyState}
</div>
</div>
</div>

View File

@ -1,5 +1,5 @@
import React, {PropTypes} from 'react';
import {fetchLayouts} from '../apis';
import {fetchLayouts} from 'shared/apis';
import KubernetesDashboard from 'src/kubernetes/components/KubernetesDashboard';
export const KubernetesPage = React.createClass({

View File

@ -1,5 +1,11 @@
import AJAX from 'utils/ajax';
import {proxy} from 'utils/queryUrlGenerator';
export function fetchLayouts() {
return AJAX({
url: `/chronograf/v1/layouts`,
method: 'GET',
});
}
export function getSources() {
return AJAX({

View File

@ -48,7 +48,7 @@ export const LayoutRenderer = React.createClass({
let text = q.text;
text += ` where time > ${timeRange.queryValue}`
text += ` where time > ${timeRange.queryValue}`;
if (host) {
text += ` and \"host\" = '${host}'`;