mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into redux-poc2
This commit is contained in:
@@ -16,7 +16,7 @@ export function parseTime(value, isUtc = false, asString = false) {
|
||||
return value;
|
||||
}
|
||||
if (!isNaN(value)) {
|
||||
const epoch = parseInt(value);
|
||||
const epoch = parseInt(value, 10);
|
||||
const m = isUtc ? moment.utc(epoch) : moment(epoch);
|
||||
return asString ? m.format(DATE_FORMAT) : m;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import CustomScrollbar from './CustomScrollbar';
|
||||
|
||||
describe('CustomScrollbar', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer
|
||||
.create(
|
||||
<CustomScrollbar>
|
||||
<p>Scrollable content</p>
|
||||
</CustomScrollbar>
|
||||
)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import Scrollbars from 'react-custom-scrollbars';
|
||||
|
||||
interface Props {
|
||||
customClassName?: string;
|
||||
autoHide?: boolean;
|
||||
autoHideTimeout?: number;
|
||||
autoHideDuration?: number;
|
||||
hideTracksWhenNotNeeded?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps component into <Scrollbars> component from `react-custom-scrollbars`
|
||||
*/
|
||||
class CustomScrollbar extends PureComponent<Props> {
|
||||
|
||||
static defaultProps: Partial<Props> = {
|
||||
customClassName: 'custom-scrollbars',
|
||||
autoHide: true,
|
||||
autoHideTimeout: 200,
|
||||
autoHideDuration: 200,
|
||||
hideTracksWhenNotNeeded: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { customClassName, children, ...scrollProps } = this.props;
|
||||
|
||||
return (
|
||||
<Scrollbars
|
||||
className={customClassName}
|
||||
autoHeight={true}
|
||||
autoHeightMin={'100%'}
|
||||
autoHeightMax={'100%'}
|
||||
renderTrackHorizontal={props => <div {...props} className="track-horizontal" />}
|
||||
renderTrackVertical={props => <div {...props} className="track-vertical" />}
|
||||
renderThumbHorizontal={props => <div {...props} className="thumb-horizontal" />}
|
||||
renderThumbVertical={props => <div {...props} className="thumb-vertical" />}
|
||||
renderView={props => <div {...props} className="view" />}
|
||||
{...scrollProps}
|
||||
>
|
||||
{children}
|
||||
</Scrollbars>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CustomScrollbar;
|
||||
@@ -0,0 +1,86 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CustomScrollbar renders correctly 1`] = `
|
||||
<div
|
||||
className="custom-scrollbars"
|
||||
style={
|
||||
Object {
|
||||
"height": "auto",
|
||||
"maxHeight": "100%",
|
||||
"minHeight": "100%",
|
||||
"overflow": "hidden",
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="view"
|
||||
style={
|
||||
Object {
|
||||
"WebkitOverflowScrolling": "touch",
|
||||
"bottom": undefined,
|
||||
"left": undefined,
|
||||
"marginBottom": 0,
|
||||
"marginRight": 0,
|
||||
"maxHeight": "calc(100% + 0px)",
|
||||
"minHeight": "calc(100% + 0px)",
|
||||
"overflow": "scroll",
|
||||
"position": "relative",
|
||||
"right": undefined,
|
||||
"top": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<p>
|
||||
Scrollable content
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="track-horizontal"
|
||||
style={
|
||||
Object {
|
||||
"display": "none",
|
||||
"height": 6,
|
||||
"opacity": 0,
|
||||
"position": "absolute",
|
||||
"transition": "opacity 200ms",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="thumb-horizontal"
|
||||
style={
|
||||
Object {
|
||||
"display": "block",
|
||||
"height": "100%",
|
||||
"position": "relative",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="track-vertical"
|
||||
style={
|
||||
Object {
|
||||
"display": "none",
|
||||
"opacity": 0,
|
||||
"position": "absolute",
|
||||
"transition": "opacity 200ms",
|
||||
"width": 6,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="thumb-vertical"
|
||||
style={
|
||||
Object {
|
||||
"display": "block",
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -55,7 +55,7 @@ export function sqlPartEditorDirective($compile, templateSrv) {
|
||||
}
|
||||
|
||||
function inputBlur($input, paramIndex) {
|
||||
cancelBlur = setTimeout(function() {
|
||||
cancelBlur = setTimeout(() => {
|
||||
switchToLink($input, paramIndex);
|
||||
}, 200);
|
||||
}
|
||||
@@ -95,20 +95,20 @@ export function sqlPartEditorDirective($compile, templateSrv) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeaheadSource = function(query, callback) {
|
||||
const typeaheadSource = (query, callback) => {
|
||||
if (param.options) {
|
||||
let options = param.options;
|
||||
if (param.type === 'int') {
|
||||
options = _.map(options, function(val) {
|
||||
options = _.map(options, val => {
|
||||
return val.toString();
|
||||
});
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
$scope.$apply(function() {
|
||||
$scope.handleEvent({ $event: { name: 'get-param-options', param: param } }).then(function(result) {
|
||||
const dynamicOptions = _.map(result, function(op) {
|
||||
$scope.$apply(() => {
|
||||
$scope.handleEvent({ $event: { name: 'get-param-options', param: param } }).then(result => {
|
||||
const dynamicOptions = _.map(result, op => {
|
||||
return op.value;
|
||||
});
|
||||
|
||||
@@ -128,7 +128,7 @@ export function sqlPartEditorDirective($compile, templateSrv) {
|
||||
source: typeaheadSource,
|
||||
minLength: 0,
|
||||
items: 1000,
|
||||
updater: function(value) {
|
||||
updater: value => {
|
||||
if (value === part.params[paramIndex]) {
|
||||
clearTimeout(cancelBlur);
|
||||
$input.focus();
|
||||
@@ -150,18 +150,18 @@ export function sqlPartEditorDirective($compile, templateSrv) {
|
||||
}
|
||||
}
|
||||
|
||||
$scope.showActionsMenu = function() {
|
||||
$scope.showActionsMenu = () => {
|
||||
$scope.handleEvent({ $event: { name: 'get-part-actions' } }).then(res => {
|
||||
$scope.partActions = res;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.triggerPartAction = function(action) {
|
||||
$scope.triggerPartAction = action => {
|
||||
$scope.handleEvent({ $event: { name: 'action', action: action } });
|
||||
};
|
||||
|
||||
function addElementsAndCompile() {
|
||||
_.each(partDef.params, function(param, index) {
|
||||
_.each(partDef.params, (param, index) => {
|
||||
if (param.optional && part.params.length <= index) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ export class Settings {
|
||||
disableLoginForm: boolean;
|
||||
defaultDatasource: string;
|
||||
alertingEnabled: boolean;
|
||||
alertingErrorOrTimeout: string;
|
||||
alertingNoDataOrNullValues: string;
|
||||
authProxyEnabled: boolean;
|
||||
exploreEnabled: boolean;
|
||||
ldapEnabled: boolean;
|
||||
|
||||
@@ -14,8 +14,8 @@ export class Analytics {
|
||||
});
|
||||
const ga = ((window as any).ga =
|
||||
(window as any).ga ||
|
||||
//tslint:disable-next-line:only-arrow-functions
|
||||
function() {
|
||||
//tslint:disable-line:only-arrow-functions
|
||||
(ga.q = ga.q || []).push(arguments);
|
||||
});
|
||||
ga.l = +new Date();
|
||||
|
||||
@@ -52,8 +52,8 @@ function applied(fn, scope) {
|
||||
if (fn.wrappedInApply) {
|
||||
return fn;
|
||||
}
|
||||
//tslint:disable-next-line:only-arrow-functions
|
||||
const wrapped: any = function() {
|
||||
//tslint:disable-line:only-arrow-functions
|
||||
const args = arguments;
|
||||
const phase = scope.$root.$$phase;
|
||||
if (phase === '$apply' || phase === '$digest') {
|
||||
|
||||
@@ -111,7 +111,7 @@ export function describeTextRange(expr: any) {
|
||||
const parts = /^now([-+])(\d+)(\w)/.exec(expr);
|
||||
if (parts) {
|
||||
const unit = parts[3];
|
||||
const amount = parseInt(parts[2]);
|
||||
const amount = parseInt(parts[2], 10);
|
||||
const span = spans[unit];
|
||||
if (span) {
|
||||
opt.display = isLast ? 'Last ' : 'Next ';
|
||||
|
||||
@@ -164,8 +164,8 @@ export class AlertTabCtrl {
|
||||
alert.conditions.push(this.buildDefaultCondition());
|
||||
}
|
||||
|
||||
alert.noDataState = alert.noDataState || 'no_data';
|
||||
alert.executionErrorState = alert.executionErrorState || 'alerting';
|
||||
alert.noDataState = alert.noDataState || config.alertingNoDataOrNullValues;
|
||||
alert.executionErrorState = alert.executionErrorState || config.alertingErrorOrTimeout;
|
||||
alert.frequency = alert.frequency || '60s';
|
||||
alert.handler = alert.handler || 1;
|
||||
alert.notifications = alert.notifications || [];
|
||||
|
||||
@@ -70,7 +70,7 @@ export class TimeSrv {
|
||||
}
|
||||
|
||||
if (!isNaN(value)) {
|
||||
const epoch = parseInt(value);
|
||||
const epoch = parseInt(value, 10);
|
||||
return moment.utc(epoch);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ export class DashboardViewState {
|
||||
|
||||
getQueryStringState() {
|
||||
const state = this.$location.search();
|
||||
state.panelId = parseInt(state.panelId) || null;
|
||||
state.panelId = parseInt(state.panelId, 10) || null;
|
||||
state.fullscreen = state.fullscreen ? true : null;
|
||||
state.edit = state.edit === 'true' || state.edit === true || null;
|
||||
state.editview = state.editview || null;
|
||||
|
||||
@@ -12,7 +12,7 @@ export class SoloPanelCtrl {
|
||||
appEvents.emit('toggle-sidemenu-hidden');
|
||||
|
||||
const params = $location.search();
|
||||
panelId = parseInt(params.panelId);
|
||||
panelId = parseInt(params.panelId, 10);
|
||||
|
||||
$scope.onAppEvent('dashboard-initialized', $scope.initPanelScope);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export class PlaylistEditCtrl {
|
||||
filterFoundPlaylistItems() {
|
||||
this.filteredDashboards = _.reject(this.dashboardresult, playlistItem => {
|
||||
return _.find(this.playlistItems, listPlaylistItem => {
|
||||
return parseInt(listPlaylistItem.value) === playlistItem.id;
|
||||
return parseInt(listPlaylistItem.value, 10) === playlistItem.id;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ export class ElasticBucketAggCtrl {
|
||||
const id = _.reduce(
|
||||
$scope.target.bucketAggs.concat($scope.target.metrics),
|
||||
(max, val) => {
|
||||
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
||||
return parseInt(val.id, 10) > max ? parseInt(val.id, 10) : max;
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
@@ -177,7 +177,7 @@ export class ElasticMetricAggCtrl {
|
||||
const id = _.reduce(
|
||||
$scope.target.bucketAggs.concat($scope.target.metrics),
|
||||
(max, val) => {
|
||||
return parseInt(val.id) > max ? parseInt(val.id) : max;
|
||||
return parseInt(val.id, 10) > max ? parseInt(val.id, 10) : max;
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
@@ -314,7 +314,7 @@ export default class InfluxDatasource {
|
||||
|
||||
const parts = /^now-(\d+)([d|h|m|s])$/.exec(date);
|
||||
if (parts) {
|
||||
const amount = parseInt(parts[1]);
|
||||
const amount = parseInt(parts[1], 10);
|
||||
const unit = parts[2];
|
||||
return 'now() - ' + amount + unit;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ export class MssqlDatasource {
|
||||
id: any;
|
||||
name: any;
|
||||
responseParser: ResponseParser;
|
||||
interval: string;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings, private backendSrv, private $q, private templateSrv) {
|
||||
this.name = instanceSettings.name;
|
||||
this.id = instanceSettings.id;
|
||||
this.responseParser = new ResponseParser(this.$q);
|
||||
this.interval = (instanceSettings.jsonData || {}).timeInterval;
|
||||
}
|
||||
|
||||
interpolateVariable(value, variable) {
|
||||
|
||||
@@ -29,6 +29,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="page-heading">MSSQL details</h3>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-9">Min time interval</span>
|
||||
<input type="text" class="gf-form-input width-6" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="1m"></input>
|
||||
<info-popover mode="right-absolute">
|
||||
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
|
||||
for example <code>1m</code> if your data is written every minute.
|
||||
</info-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="grafana-info-box">
|
||||
<h5>User Permission</h5>
|
||||
|
||||
@@ -17,5 +17,10 @@
|
||||
|
||||
"alerting": true,
|
||||
"annotations": true,
|
||||
"metrics": true
|
||||
"metrics": true,
|
||||
|
||||
"queryOptions": {
|
||||
"minInterval": true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ export class MysqlDatasource {
|
||||
id: any;
|
||||
name: any;
|
||||
responseParser: ResponseParser;
|
||||
interval: string;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings, private backendSrv, private $q, private templateSrv) {
|
||||
this.name = instanceSettings.name;
|
||||
this.id = instanceSettings.id;
|
||||
this.responseParser = new ResponseParser(this.$q);
|
||||
this.interval = (instanceSettings.jsonData || {}).timeInterval;
|
||||
}
|
||||
|
||||
interpolateVariable(value, variable) {
|
||||
|
||||
@@ -24,6 +24,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="page-heading">MySQL details</h3>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-9">Min time interval</span>
|
||||
<input type="text" class="gf-form-input width-6" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="1m"></input>
|
||||
<info-popover mode="right-absolute">
|
||||
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
|
||||
for example <code>1m</code> if your data is written every minute.
|
||||
</info-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="grafana-info-box">
|
||||
<h5>User Permission</h5>
|
||||
|
||||
@@ -18,5 +18,10 @@
|
||||
|
||||
"alerting": true,
|
||||
"annotations": true,
|
||||
"metrics": true
|
||||
"metrics": true,
|
||||
|
||||
"queryOptions": {
|
||||
"minInterval": true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -408,11 +408,11 @@ export default class OpenTsDatasource {
|
||||
};
|
||||
|
||||
if (target.counterMax && target.counterMax.length) {
|
||||
query.rateOptions.counterMax = parseInt(target.counterMax);
|
||||
query.rateOptions.counterMax = parseInt(target.counterMax, 10);
|
||||
}
|
||||
|
||||
if (target.counterResetValue && target.counterResetValue.length) {
|
||||
query.rateOptions.resetValue = parseInt(target.counterResetValue);
|
||||
query.rateOptions.resetValue = parseInt(target.counterResetValue, 10);
|
||||
}
|
||||
|
||||
if (tsdbVersion >= 2) {
|
||||
|
||||
@@ -8,6 +8,7 @@ export class PostgresDatasource {
|
||||
jsonData: any;
|
||||
responseParser: ResponseParser;
|
||||
queryModel: PostgresQuery;
|
||||
interval: string;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings, private backendSrv, private $q, private templateSrv, private timeSrv) {
|
||||
@@ -16,6 +17,7 @@ export class PostgresDatasource {
|
||||
this.jsonData = instanceSettings.jsonData;
|
||||
this.responseParser = new ResponseParser(this.$q);
|
||||
this.queryModel = new PostgresQuery({});
|
||||
this.interval = (instanceSettings.jsonData || {}).timeInterval;
|
||||
}
|
||||
|
||||
interpolateVariable(value, variable) {
|
||||
|
||||
@@ -61,6 +61,16 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-9">Min time interval</span>
|
||||
<input type="text" class="gf-form-input width-6" ng-model="ctrl.current.jsonData.timeInterval" spellcheck='false' placeholder="1m"></input>
|
||||
<info-popover mode="right-absolute">
|
||||
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
|
||||
for example <code>1m</code> if your data is written every minute.
|
||||
</info-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grafana-info-box alert alert-info" ng-show="ctrl.showTimescaleDBHelp">
|
||||
<div class="alert-body">
|
||||
<p>
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
"alerting": true,
|
||||
"annotations": true,
|
||||
"metrics": true
|
||||
"metrics": true,
|
||||
|
||||
"queryOptions": {
|
||||
"minInterval": true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
|
||||
updateProjection() {
|
||||
this.selectParts = _.map(this.target.select, function(parts: any) {
|
||||
this.selectParts = _.map(this.target.select, (parts: any) => {
|
||||
return _.map(parts, sqlPart.create).filter(n => n);
|
||||
});
|
||||
this.whereParts = _.map(this.target.where, sqlPart.create).filter(n => n);
|
||||
@@ -104,15 +104,15 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
|
||||
updatePersistedParts() {
|
||||
this.target.select = _.map(this.selectParts, function(selectParts) {
|
||||
return _.map(selectParts, function(part: any) {
|
||||
this.target.select = _.map(this.selectParts, selectParts => {
|
||||
return _.map(selectParts, (part: any) => {
|
||||
return { type: part.def.type, datatype: part.datatype, params: part.params };
|
||||
});
|
||||
});
|
||||
this.target.where = _.map(this.whereParts, function(part: any) {
|
||||
this.target.where = _.map(this.whereParts, (part: any) => {
|
||||
return { type: part.def.type, datatype: part.datatype, name: part.name, params: part.params };
|
||||
});
|
||||
this.target.group = _.map(this.groupParts, function(part: any) {
|
||||
this.target.group = _.map(this.groupParts, (part: any) => {
|
||||
return { type: part.def.type, datatype: part.datatype, params: part.params };
|
||||
});
|
||||
}
|
||||
@@ -355,7 +355,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
|
||||
switch (partType) {
|
||||
case 'column':
|
||||
const parts = _.map(selectParts, function(part: any) {
|
||||
const parts = _.map(selectParts, (part: any) => {
|
||||
return sqlPart.create({ type: part.def.type, params: _.clone(part.params) });
|
||||
});
|
||||
this.selectParts.push(parts);
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import PostgresQuery from '../postgres_query';
|
||||
|
||||
describe('PostgresQuery', function() {
|
||||
describe('PostgresQuery', () => {
|
||||
const templateSrv = {
|
||||
replace: jest.fn(text => text),
|
||||
};
|
||||
|
||||
describe('When initializing', function() {
|
||||
it('should not be in SQL mode', function() {
|
||||
describe('When initializing', () => {
|
||||
it('should not be in SQL mode', () => {
|
||||
const query = new PostgresQuery({}, templateSrv);
|
||||
expect(query.target.rawQuery).toBe(false);
|
||||
});
|
||||
it('should be in SQL mode for pre query builder queries', function() {
|
||||
it('should be in SQL mode for pre query builder queries', () => {
|
||||
const query = new PostgresQuery({ rawSql: 'SELECT 1' }, templateSrv);
|
||||
expect(query.target.rawQuery).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When generating time column SQL', function() {
|
||||
describe('When generating time column SQL', () => {
|
||||
const query = new PostgresQuery({}, templateSrv);
|
||||
|
||||
query.target.timeColumn = 'time';
|
||||
@@ -25,7 +25,7 @@ describe('PostgresQuery', function() {
|
||||
expect(query.buildTimeColumn()).toBe('"time" AS "time"');
|
||||
});
|
||||
|
||||
describe('When generating time column SQL with group by time', function() {
|
||||
describe('When generating time column SQL with group by time', () => {
|
||||
let query = new PostgresQuery(
|
||||
{ timeColumn: 'time', group: [{ type: 'time', params: ['5m', 'none'] }] },
|
||||
templateSrv
|
||||
@@ -44,7 +44,7 @@ describe('PostgresQuery', function() {
|
||||
expect(query.buildTimeColumn(false)).toBe('$__unixEpochGroup(time,5m)');
|
||||
});
|
||||
|
||||
describe('When generating metric column SQL', function() {
|
||||
describe('When generating metric column SQL', () => {
|
||||
const query = new PostgresQuery({}, templateSrv);
|
||||
|
||||
query.target.metricColumn = 'host';
|
||||
@@ -53,7 +53,7 @@ describe('PostgresQuery', function() {
|
||||
expect(query.buildMetricColumn()).toBe('"host" AS metric');
|
||||
});
|
||||
|
||||
describe('When generating value column SQL', function() {
|
||||
describe('When generating value column SQL', () => {
|
||||
const query = new PostgresQuery({}, templateSrv);
|
||||
|
||||
let column = [{ type: 'column', params: ['value'] }];
|
||||
@@ -76,7 +76,7 @@ describe('PostgresQuery', function() {
|
||||
);
|
||||
});
|
||||
|
||||
describe('When generating value column SQL with metric column', function() {
|
||||
describe('When generating value column SQL with metric column', () => {
|
||||
const query = new PostgresQuery({}, templateSrv);
|
||||
query.target.metricColumn = 'host';
|
||||
|
||||
@@ -110,7 +110,7 @@ describe('PostgresQuery', function() {
|
||||
);
|
||||
});
|
||||
|
||||
describe('When generating WHERE clause', function() {
|
||||
describe('When generating WHERE clause', () => {
|
||||
const query = new PostgresQuery({ where: [] }, templateSrv);
|
||||
|
||||
expect(query.buildWhereClause()).toBe('');
|
||||
@@ -126,7 +126,7 @@ describe('PostgresQuery', function() {
|
||||
expect(query.buildWhereClause()).toBe('\nWHERE\n $__timeFilter(t) AND\n v = 1');
|
||||
});
|
||||
|
||||
describe('When generating GROUP BY clause', function() {
|
||||
describe('When generating GROUP BY clause', () => {
|
||||
const query = new PostgresQuery({ group: [], metricColumn: 'none' }, templateSrv);
|
||||
|
||||
expect(query.buildGroupClause()).toBe('');
|
||||
@@ -136,7 +136,7 @@ describe('PostgresQuery', function() {
|
||||
expect(query.buildGroupClause()).toBe('\nGROUP BY 1,2');
|
||||
});
|
||||
|
||||
describe('When generating complete statement', function() {
|
||||
describe('When generating complete statement', () => {
|
||||
const target = {
|
||||
timeColumn: 't',
|
||||
table: 'table',
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ResultTransformer {
|
||||
|
||||
metricLabel = this.createMetricLabel(metricData.metric, options);
|
||||
|
||||
const stepMs = parseInt(options.step) * 1000;
|
||||
const stepMs = parseInt(options.step, 10) * 1000;
|
||||
let baseTimestamp = start * 1000;
|
||||
|
||||
if (metricData.values === undefined) {
|
||||
|
||||
@@ -53,7 +53,7 @@ export class ThresholdManager {
|
||||
function stopped() {
|
||||
// calculate graph level
|
||||
let graphValue = plot.c2p({ left: 0, top: posTop }).y;
|
||||
graphValue = parseInt(graphValue.toFixed(0));
|
||||
graphValue = parseInt(graphValue.toFixed(0), 10);
|
||||
model.value = graphValue;
|
||||
|
||||
handleElem.off('mousemove', dragging);
|
||||
|
||||
@@ -271,7 +271,7 @@ function pushToYBuckets(buckets, bucketNum, value, point, bounds) {
|
||||
let count = 1;
|
||||
// Use the 3rd argument as scale/count
|
||||
if (point.length > 3) {
|
||||
count = parseInt(point[2]);
|
||||
count = parseInt(point[2], 10);
|
||||
}
|
||||
if (buckets[bucketNum]) {
|
||||
buckets[bucketNum].values.push(value);
|
||||
|
||||
@@ -493,7 +493,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
||||
|
||||
const bgColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)';
|
||||
|
||||
const fontScale = parseInt(panel.valueFontSize) / 100;
|
||||
const fontScale = parseInt(panel.valueFontSize, 10) / 100;
|
||||
const fontSize = Math.min(dimension / 5, 100) * fontScale;
|
||||
// Reduce gauge width if threshold labels enabled
|
||||
const gaugeWidthReduceRatio = panel.gauge.thresholdLabels ? 1.5 : 1;
|
||||
|
||||
@@ -294,3 +294,46 @@
|
||||
padding-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// Custom styles for 'react-custom-scrollbars'
|
||||
|
||||
.custom-scrollbars {
|
||||
// Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to
|
||||
// make scroll working it should fit outer container size (scroll appears only when inner container size is
|
||||
// greater than outer one).
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
|
||||
.view {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.track-vertical {
|
||||
border-radius: 3px;
|
||||
width: 6px !important;
|
||||
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.track-horizontal {
|
||||
border-radius: 3px;
|
||||
height: 6px !important;
|
||||
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
left: 2px;
|
||||
}
|
||||
|
||||
.thumb-vertical {
|
||||
@include gradient-vertical($scrollbarBackground, $scrollbarBackground2);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.thumb-horizontal {
|
||||
@include gradient-horizontal($scrollbarBackground, $scrollbarBackground2);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user