Make LayoutRenderer host agnostic and shared
parent
01ae8b1b82
commit
f5c58f70cd
|
@ -81,10 +81,3 @@ export function getAppsForHosts(proxyLink, hosts, appMappings) {
|
||||||
return newHosts;
|
return newHosts;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchLayouts() {
|
|
||||||
return AJAX({
|
|
||||||
url: `/chronograf/v1/layouts`,
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, {PropTypes} from 'react';
|
import React, {PropTypes} from 'react';
|
||||||
import LayoutRenderer from '../components/LayoutRenderer';
|
import LayoutRenderer from 'shared/components/LayoutRenderer';
|
||||||
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
|
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
|
||||||
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
|
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({
|
export const HostPage = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
|
|
@ -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',
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, {PropTypes} from 'react';
|
import React, {PropTypes} from 'react';
|
||||||
import LayoutRenderer from '../components/LayoutRenderer';
|
import LayoutRenderer from 'shared/components/LayoutRenderer';
|
||||||
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
|
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
|
||||||
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
|
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
|
||||||
|
|
||||||
|
@ -57,13 +57,19 @@ export const KubernetesPage = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
const {layouts} = this.props;
|
const {layouts} = this.props;
|
||||||
const {timeRange} = this.state;
|
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 (
|
return (
|
||||||
<div className="host-dashboard hosts-page">
|
<div className="host-dashboard hosts-page">
|
||||||
<div className="enterprise-header hosts-dashboard-header">
|
<div className="enterprise-header hosts-dashboard-header">
|
||||||
<div className="enterprise-header__container">
|
<div className="enterprise-header__container">
|
||||||
<div className="enterprise-header__left">
|
<div className="enterprise-header__left">
|
||||||
<h2>Kubernetes Dashboard</h2>
|
<h1>Kubernetes Dashboard</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="enterprise-header__right">
|
<div className="enterprise-header__right">
|
||||||
<h1>Range:</h1>
|
<h1>Range:</h1>
|
||||||
|
@ -74,7 +80,7 @@ export const KubernetesPage = React.createClass({
|
||||||
<div className="hosts-page-scroll-container">
|
<div className="hosts-page-scroll-container">
|
||||||
<div className="container-fluid hosts-dashboard">
|
<div className="container-fluid hosts-dashboard">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{ (layouts.length > 0) ? this.renderLayouts(layouts) : '' }
|
{layouts.length ? this.renderLayouts(layouts) : emptyState}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, {PropTypes} from 'react';
|
import React, {PropTypes} from 'react';
|
||||||
import {fetchLayouts} from '../apis';
|
import {fetchLayouts} from 'shared/apis';
|
||||||
import KubernetesDashboard from 'src/kubernetes/components/KubernetesDashboard';
|
import KubernetesDashboard from 'src/kubernetes/components/KubernetesDashboard';
|
||||||
|
|
||||||
export const KubernetesPage = React.createClass({
|
export const KubernetesPage = React.createClass({
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import AJAX from 'utils/ajax';
|
import AJAX from 'utils/ajax';
|
||||||
import {proxy} from 'utils/queryUrlGenerator';
|
|
||||||
|
export function fetchLayouts() {
|
||||||
|
return AJAX({
|
||||||
|
url: `/chronograf/v1/layouts`,
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getSources() {
|
export function getSources() {
|
||||||
return AJAX({
|
return AJAX({
|
||||||
|
|
|
@ -48,7 +48,7 @@ export const LayoutRenderer = React.createClass({
|
||||||
|
|
||||||
let text = q.text;
|
let text = q.text;
|
||||||
|
|
||||||
text += ` where time > ${timeRange.queryValue}`
|
text += ` where time > ${timeRange.queryValue}`;
|
||||||
|
|
||||||
if (host) {
|
if (host) {
|
||||||
text += ` and \"host\" = '${host}'`;
|
text += ` and \"host\" = '${host}'`;
|
Loading…
Reference in New Issue