Merge branch 'master' into react-query-editor
This commit is contained in:
@@ -22,7 +22,7 @@ import { binarySIPrefix, currency, decimalSIPrefix } from './symbolFormatters';
|
||||
|
||||
export const getCategories = (): ValueFormatCategory[] => [
|
||||
{
|
||||
name: 'none',
|
||||
name: 'Misc',
|
||||
formats: [
|
||||
{ name: 'none', id: 'none', fn: toFixed },
|
||||
{
|
||||
@@ -41,7 +41,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'acceleration',
|
||||
name: 'Acceleration',
|
||||
formats: [
|
||||
{ name: 'Meters/sec²', id: 'accMS2', fn: toFixedUnit('m/sec²') },
|
||||
{ name: 'Feet/sec²', id: 'accFS2', fn: toFixedUnit('f/sec²') },
|
||||
@@ -49,7 +49,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'angle',
|
||||
name: 'Angle',
|
||||
formats: [
|
||||
{ name: 'Degrees (°)', id: 'degree', fn: toFixedUnit('°') },
|
||||
{ name: 'Radians', id: 'radian', fn: toFixedUnit('rad') },
|
||||
@@ -57,7 +57,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'area',
|
||||
name: 'Area',
|
||||
formats: [
|
||||
{ name: 'Square Meters (m²)', id: 'areaM2', fn: toFixedUnit('m²') },
|
||||
{ name: 'Square Feet (ft²)', id: 'areaF2', fn: toFixedUnit('ft²') },
|
||||
@@ -65,7 +65,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'computation throughput',
|
||||
name: 'Computation',
|
||||
formats: [
|
||||
{ name: 'FLOP/s', id: 'flops', fn: decimalSIPrefix('FLOP/s') },
|
||||
{ name: 'MFLOP/s', id: 'mflops', fn: decimalSIPrefix('FLOP/s', 2) },
|
||||
@@ -76,7 +76,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'concentration',
|
||||
name: 'Concentration',
|
||||
formats: [
|
||||
{ name: 'parts-per-million (ppm)', id: 'ppm', fn: toFixedUnit('ppm') },
|
||||
{ name: 'parts-per-billion (ppb)', id: 'conppb', fn: toFixedUnit('ppb') },
|
||||
@@ -93,7 +93,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'currency',
|
||||
name: 'Currency',
|
||||
formats: [
|
||||
{ name: 'Dollars ($)', id: 'currencyUSD', fn: currency('$') },
|
||||
{ name: 'Pounds (£)', id: 'currencyGBP', fn: currency('£') },
|
||||
@@ -113,7 +113,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'data (IEC)',
|
||||
name: 'Data (IEC)',
|
||||
formats: [
|
||||
{ name: 'bits', id: 'bits', fn: binarySIPrefix('b') },
|
||||
{ name: 'bytes', id: 'bytes', fn: binarySIPrefix('B') },
|
||||
@@ -123,7 +123,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'data (Metric)',
|
||||
name: 'Data (Metric)',
|
||||
formats: [
|
||||
{ name: 'bits', id: 'decbits', fn: decimalSIPrefix('d') },
|
||||
{ name: 'bytes', id: 'decbytes', fn: decimalSIPrefix('B') },
|
||||
@@ -133,7 +133,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'data rate',
|
||||
name: 'Data Rate',
|
||||
formats: [
|
||||
{ name: 'packets/sec', id: 'pps', fn: decimalSIPrefix('pps') },
|
||||
{ name: 'bits/sec', id: 'bps', fn: decimalSIPrefix('bps') },
|
||||
@@ -147,7 +147,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'date & time',
|
||||
name: 'Date & Time',
|
||||
formats: [
|
||||
{ name: 'YYYY-MM-DD HH:mm:ss', id: 'dateTimeAsIso', fn: dateTimeAsIso },
|
||||
{ name: 'DD/MM/YYYY h:mm:ss a', id: 'dateTimeAsUS', fn: dateTimeAsUS },
|
||||
@@ -155,7 +155,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'energy',
|
||||
name: 'Energy',
|
||||
formats: [
|
||||
{ name: 'Watt (W)', id: 'watt', fn: decimalSIPrefix('W') },
|
||||
{ name: 'Kilowatt (kW)', id: 'kwatt', fn: decimalSIPrefix('W', 1) },
|
||||
@@ -182,7 +182,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'flow',
|
||||
name: 'Flow',
|
||||
formats: [
|
||||
{ name: 'Gallons/min (gpm)', id: 'flowgpm', fn: toFixedUnit('gpm') },
|
||||
{ name: 'Cubic meters/sec (cms)', id: 'flowcms', fn: toFixedUnit('cms') },
|
||||
@@ -194,7 +194,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'force',
|
||||
name: 'Force',
|
||||
formats: [
|
||||
{ name: 'Newton-meters (Nm)', id: 'forceNm', fn: decimalSIPrefix('Nm') },
|
||||
{ name: 'Kilonewton-meters (kNm)', id: 'forcekNm', fn: decimalSIPrefix('Nm', 1) },
|
||||
@@ -203,7 +203,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'hash rate',
|
||||
name: 'Hash Rate',
|
||||
formats: [
|
||||
{ name: 'hashes/sec', id: 'Hs', fn: decimalSIPrefix('H/s') },
|
||||
{ name: 'kilohashes/sec', id: 'KHs', fn: decimalSIPrefix('H/s', 1) },
|
||||
@@ -215,7 +215,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'mass',
|
||||
name: 'Mass',
|
||||
formats: [
|
||||
{ name: 'milligram (mg)', id: 'massmg', fn: decimalSIPrefix('g', -1) },
|
||||
{ name: 'gram (g)', id: 'massg', fn: decimalSIPrefix('g') },
|
||||
@@ -234,7 +234,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'pressure',
|
||||
name: 'Pressure',
|
||||
formats: [
|
||||
{ name: 'Millibars', id: 'pressurembar', fn: decimalSIPrefix('bar', -1) },
|
||||
{ name: 'Bars', id: 'pressurebar', fn: decimalSIPrefix('bar') },
|
||||
@@ -246,7 +246,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'radiation',
|
||||
name: 'Radiation',
|
||||
formats: [
|
||||
{ name: 'Becquerel (Bq)', id: 'radbq', fn: decimalSIPrefix('Bq') },
|
||||
{ name: 'curie (Ci)', id: 'radci', fn: decimalSIPrefix('Ci') },
|
||||
@@ -260,7 +260,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'temperature',
|
||||
name: 'Temperature',
|
||||
formats: [
|
||||
{ name: 'Celsius (°C)', id: 'celsius', fn: toFixedUnit('°C') },
|
||||
{ name: 'Farenheit (°F)', id: 'farenheit', fn: toFixedUnit('°F') },
|
||||
@@ -268,7 +268,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
name: 'Time',
|
||||
formats: [
|
||||
{ name: 'Hertz (1/s)', id: 'hertz', fn: decimalSIPrefix('Hz') },
|
||||
{ name: 'nanoseconds (ns)', id: 'ns', fn: toNanoSeconds },
|
||||
@@ -287,7 +287,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'throughput',
|
||||
name: 'Throughput',
|
||||
formats: [
|
||||
{ name: 'ops/sec (ops)', id: 'ops', fn: simpleCountUnit('ops') },
|
||||
{ name: 'requests/sec (rps)', id: 'reqps', fn: simpleCountUnit('reqps') },
|
||||
@@ -300,7 +300,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'velocity',
|
||||
name: 'Velocity',
|
||||
formats: [
|
||||
{ name: 'metres/second (m/s)', id: 'velocityms', fn: toFixedUnit('m/s') },
|
||||
{ name: 'kilometers/hour (km/h)', id: 'velocitykmh', fn: toFixedUnit('km/h') },
|
||||
@@ -309,7 +309,7 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'volume',
|
||||
name: 'Volume',
|
||||
formats: [
|
||||
{ name: 'millilitre (mL)', id: 'mlitre', fn: decimalSIPrefix('L', -1) },
|
||||
{ name: 'litre (L)', id: 'litre', fn: decimalSIPrefix('L') },
|
||||
@@ -318,5 +318,5 @@ export const getCategories = (): ValueFormatCategory[] => [
|
||||
{ name: 'cubic decimetre', id: 'dm3', fn: toFixedUnit('dm³') },
|
||||
{ name: 'gallons', id: 'gallons', fn: toFixedUnit('gal') },
|
||||
],
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
@@ -6,7 +6,7 @@ import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoa
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
// Components
|
||||
import { EditorTabBody, EditorToolbarView } from '../dashboard/dashgrid/EditorTabBody';
|
||||
import { EditorTabBody, EditorToolbarView } from '../dashboard/panel_editor/EditorTabBody';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import StateHistory from './StateHistory';
|
||||
import 'app/features/alerting/AlertTabCtrl';
|
||||
|
||||
@@ -9,7 +9,7 @@ import { AddPanelPanel } from './AddPanelPanel';
|
||||
import { getPanelPluginNotFound } from './PanelPluginNotFound';
|
||||
import { DashboardRow } from './DashboardRow';
|
||||
import { PanelChrome } from './PanelChrome';
|
||||
import { PanelEditor } from './PanelEditor';
|
||||
import { PanelEditor } from '../panel_editor/PanelEditor';
|
||||
|
||||
import { PanelModel } from '../panel_model';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import React, { KeyboardEvent, Component } from 'react';
|
||||
|
||||
interface State {
|
||||
selected: number;
|
||||
}
|
||||
|
||||
export interface KeyboardNavigationProps {
|
||||
onKeyDown: (evt: KeyboardEvent<EventTarget>, maxSelectedIndex: number, onEnterAction: () => void) => void;
|
||||
onMouseEnter: (select: number) => void;
|
||||
selected: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
render: (injectProps: any) => void;
|
||||
}
|
||||
|
||||
class KeyboardNavigation extends Component<Props, State> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
selected: 0,
|
||||
};
|
||||
}
|
||||
|
||||
goToNext = (maxSelectedIndex: number) => {
|
||||
const nextIndex = this.state.selected >= maxSelectedIndex ? 0 : this.state.selected + 1;
|
||||
this.setState({
|
||||
selected: nextIndex,
|
||||
});
|
||||
};
|
||||
|
||||
goToPrev = (maxSelectedIndex: number) => {
|
||||
const nextIndex = this.state.selected <= 0 ? maxSelectedIndex : this.state.selected - 1;
|
||||
this.setState({
|
||||
selected: nextIndex,
|
||||
});
|
||||
};
|
||||
|
||||
onKeyDown = (evt: KeyboardEvent, maxSelectedIndex: number, onEnterAction: any) => {
|
||||
if (evt.key === 'ArrowDown') {
|
||||
evt.preventDefault();
|
||||
this.goToNext(maxSelectedIndex);
|
||||
}
|
||||
if (evt.key === 'ArrowUp') {
|
||||
evt.preventDefault();
|
||||
this.goToPrev(maxSelectedIndex);
|
||||
}
|
||||
if (evt.key === 'Enter' && onEnterAction) {
|
||||
onEnterAction();
|
||||
}
|
||||
};
|
||||
|
||||
onMouseEnter = (mouseEnterIndex: number) => {
|
||||
this.setState({
|
||||
selected: mouseEnterIndex,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const injectProps = {
|
||||
onKeyDown: this.onKeyDown,
|
||||
onMouseEnter: this.onMouseEnter,
|
||||
selected: this.state.selected,
|
||||
};
|
||||
|
||||
return <>{this.props.render({ ...injectProps })}</>;
|
||||
}
|
||||
}
|
||||
|
||||
export default KeyboardNavigation;
|
||||
@@ -19,6 +19,8 @@ import { DashboardModel } from '../dashboard_model';
|
||||
import { PanelPlugin } from 'app/types';
|
||||
import { TimeRange } from '@grafana/ui';
|
||||
|
||||
import variables from 'sass/_variables.scss';
|
||||
|
||||
export interface Props {
|
||||
panel: PanelModel;
|
||||
dashboard: DashboardModel;
|
||||
@@ -122,8 +124,8 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
timeSeries={timeSeries}
|
||||
timeRange={timeRange}
|
||||
options={panel.getOptions(plugin.exports.PanelDefaults)}
|
||||
width={width}
|
||||
height={height - PANEL_HEADER_HEIGHT}
|
||||
width={width - 2 * variables.panelHorizontalPadding }
|
||||
height={height - PANEL_HEADER_HEIGHT - variables.panelVerticalPadding}
|
||||
renderCounter={renderCounter}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import angular from 'angular';
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
export interface AttachedPanel {
|
||||
destroy();
|
||||
}
|
||||
|
||||
export class PanelLoader {
|
||||
/** @ngInject */
|
||||
constructor(private $compile, private $rootScope) {}
|
||||
|
||||
load(elem, panel, dashboard): AttachedPanel {
|
||||
const template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
|
||||
const panelScope = this.$rootScope.$new();
|
||||
panelScope.panel = panel;
|
||||
panelScope.dashboard = dashboard;
|
||||
|
||||
const compiledElem = this.$compile(template)(panelScope);
|
||||
const rootNode = angular.element(elem);
|
||||
rootNode.append(compiledElem);
|
||||
|
||||
return {
|
||||
destroy: () => {
|
||||
panelScope.$destroy();
|
||||
compiledElem.remove();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.service('panelLoader', PanelLoader);
|
||||
@@ -1,7 +1,6 @@
|
||||
import './plugin_edit_ctrl';
|
||||
import './plugin_page_ctrl';
|
||||
import './import_list/import_list';
|
||||
import './ds_edit_ctrl';
|
||||
import './datasource_srv';
|
||||
import './plugin_component';
|
||||
import './VariableQueryComponentLoader';
|
||||
import './variableQueryEditorLoader';
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import { coreModule } from 'app/core/core';
|
||||
import { store } from 'app/store/store';
|
||||
import { getNavModel } from 'app/core/selectors/navModel';
|
||||
import { buildNavModel } from './state/navModel';
|
||||
|
||||
export class DataSourceDashboardsCtrl {
|
||||
datasourceMeta: any;
|
||||
navModel: any;
|
||||
current: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, private $routeParams) {
|
||||
const state = store.getState();
|
||||
this.navModel = getNavModel(state.navIndex, 'datasources');
|
||||
|
||||
if (this.$routeParams.id) {
|
||||
this.getDatasourceById(this.$routeParams.id);
|
||||
}
|
||||
}
|
||||
|
||||
getDatasourceById(id) {
|
||||
this.backendSrv
|
||||
.get('/api/datasources/' + id)
|
||||
.then(ds => {
|
||||
this.current = ds;
|
||||
})
|
||||
.then(this.getPluginInfo.bind(this));
|
||||
}
|
||||
|
||||
updateNav() {
|
||||
this.navModel = buildNavModel(this.current, this.datasourceMeta, 'datasource-dashboards');
|
||||
}
|
||||
|
||||
getPluginInfo() {
|
||||
return this.backendSrv.get('/api/plugins/' + this.current.type + '/settings').then(pluginInfo => {
|
||||
this.datasourceMeta = pluginInfo;
|
||||
this.updateNav();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.controller('DataSourceDashboardsCtrl', DataSourceDashboardsCtrl);
|
||||
@@ -1,223 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import config from 'app/core/config';
|
||||
import { coreModule, appEvents } from 'app/core/core';
|
||||
import { store } from 'app/store/store';
|
||||
import { getNavModel } from 'app/core/selectors/navModel';
|
||||
import { buildNavModel } from './state/navModel';
|
||||
|
||||
let datasourceTypes = [];
|
||||
|
||||
const defaults = {
|
||||
name: '',
|
||||
type: 'graphite',
|
||||
url: '',
|
||||
access: 'proxy',
|
||||
jsonData: {},
|
||||
secureJsonFields: {},
|
||||
secureJsonData: {},
|
||||
};
|
||||
|
||||
let datasourceCreated = false;
|
||||
|
||||
export class DataSourceEditCtrl {
|
||||
isNew: boolean;
|
||||
datasources: any[];
|
||||
current: any;
|
||||
types: any;
|
||||
testing: any;
|
||||
datasourceMeta: any;
|
||||
editForm: any;
|
||||
gettingStarted: boolean;
|
||||
navModel: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $q, private backendSrv, private $routeParams, private $location, private datasourceSrv) {
|
||||
const state = store.getState();
|
||||
this.navModel = getNavModel(state.navIndex, 'datasources');
|
||||
this.datasources = [];
|
||||
|
||||
this.loadDatasourceTypes().then(() => {
|
||||
if (this.$routeParams.id) {
|
||||
this.getDatasourceById(this.$routeParams.id);
|
||||
} else {
|
||||
this.initNewDatasourceModel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initNewDatasourceModel() {
|
||||
this.isNew = true;
|
||||
this.current = _.cloneDeep(defaults);
|
||||
|
||||
// We are coming from getting started
|
||||
if (this.$location.search().gettingstarted) {
|
||||
this.gettingStarted = true;
|
||||
this.current.isDefault = true;
|
||||
}
|
||||
|
||||
this.typeChanged();
|
||||
}
|
||||
|
||||
loadDatasourceTypes() {
|
||||
if (datasourceTypes.length > 0) {
|
||||
this.types = datasourceTypes;
|
||||
return this.$q.when(null);
|
||||
}
|
||||
|
||||
return this.backendSrv.get('/api/plugins', { enabled: 1, type: 'datasource' }).then(plugins => {
|
||||
datasourceTypes = plugins;
|
||||
this.types = plugins;
|
||||
});
|
||||
}
|
||||
|
||||
getDatasourceById(id) {
|
||||
this.backendSrv.get('/api/datasources/' + id).then(ds => {
|
||||
this.isNew = false;
|
||||
this.current = ds;
|
||||
|
||||
if (datasourceCreated) {
|
||||
datasourceCreated = false;
|
||||
this.testDatasource();
|
||||
}
|
||||
|
||||
return this.typeChanged();
|
||||
});
|
||||
}
|
||||
|
||||
userChangedType() {
|
||||
// reset model but keep name & default flag
|
||||
this.current = _.defaults(
|
||||
{
|
||||
id: this.current.id,
|
||||
name: this.current.name,
|
||||
isDefault: this.current.isDefault,
|
||||
type: this.current.type,
|
||||
},
|
||||
_.cloneDeep(defaults)
|
||||
);
|
||||
this.typeChanged();
|
||||
}
|
||||
|
||||
updateNav() {
|
||||
this.navModel = buildNavModel(this.current, this.datasourceMeta, 'datasource-settings');
|
||||
}
|
||||
|
||||
typeChanged() {
|
||||
return this.backendSrv.get('/api/plugins/' + this.current.type + '/settings').then(pluginInfo => {
|
||||
this.datasourceMeta = pluginInfo;
|
||||
this.updateNav();
|
||||
});
|
||||
}
|
||||
|
||||
updateFrontendSettings() {
|
||||
return this.backendSrv.get('/api/frontend/settings').then(settings => {
|
||||
config.datasources = settings.datasources;
|
||||
config.defaultDatasource = settings.defaultDatasource;
|
||||
this.datasourceSrv.init();
|
||||
});
|
||||
}
|
||||
|
||||
testDatasource() {
|
||||
return this.datasourceSrv.get(this.current.name).then(datasource => {
|
||||
if (!datasource.testDatasource) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.testing = { done: false, status: 'error' };
|
||||
|
||||
// make test call in no backend cache context
|
||||
return this.backendSrv
|
||||
.withNoBackendCache(() => {
|
||||
return datasource
|
||||
.testDatasource()
|
||||
.then(result => {
|
||||
this.testing.message = result.message;
|
||||
this.testing.status = result.status;
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.statusText) {
|
||||
this.testing.message = 'HTTP Error ' + err.statusText;
|
||||
} else {
|
||||
this.testing.message = err.message;
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.testing.done = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
saveChanges() {
|
||||
if (!this.editForm.$valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.current.readOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.current.id) {
|
||||
return this.backendSrv.put('/api/datasources/' + this.current.id, this.current).then(result => {
|
||||
this.current = result.datasource;
|
||||
this.updateNav();
|
||||
return this.updateFrontendSettings().then(() => {
|
||||
return this.testDatasource();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return this.backendSrv.post('/api/datasources', this.current).then(result => {
|
||||
this.current = result.datasource;
|
||||
this.updateFrontendSettings();
|
||||
|
||||
datasourceCreated = true;
|
||||
this.$location.path('datasources/edit/' + result.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
confirmDelete() {
|
||||
this.backendSrv.delete('/api/datasources/' + this.current.id).then(() => {
|
||||
this.$location.path('datasources');
|
||||
});
|
||||
}
|
||||
|
||||
delete(s) {
|
||||
appEvents.emit('confirm-modal', {
|
||||
title: 'Delete',
|
||||
text: 'Are you sure you want to delete this datasource?',
|
||||
yesText: 'Delete',
|
||||
icon: 'fa-trash',
|
||||
onConfirm: () => {
|
||||
this.confirmDelete();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.controller('DataSourceEditCtrl', DataSourceEditCtrl);
|
||||
|
||||
coreModule.directive('datasourceHttpSettings', () => {
|
||||
return {
|
||||
scope: {
|
||||
current: '=',
|
||||
suggestUrl: '@',
|
||||
noDirectAccess: '@',
|
||||
},
|
||||
templateUrl: 'public/app/features/plugins/partials/ds_http_settings.html',
|
||||
link: {
|
||||
pre: ($scope, elem, attrs) => {
|
||||
// do not show access option if direct access is disabled
|
||||
$scope.showAccessOption = $scope.noDirectAccess !== 'true';
|
||||
$scope.showAccessHelp = false;
|
||||
$scope.toggleAccessHelp = () => {
|
||||
$scope.showAccessHelp = !$scope.showAccessHelp;
|
||||
};
|
||||
|
||||
$scope.getSuggestUrls = () => {
|
||||
return [$scope.suggestUrl];
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -15,6 +15,13 @@ export class GaugePanel extends PureComponent<Props> {
|
||||
nullValueMode: NullValueMode.Ignore,
|
||||
});
|
||||
|
||||
return <Gauge timeSeries={vmSeries} {...this.props.options} width={width} height={height} />;
|
||||
return (
|
||||
<Gauge
|
||||
timeSeries={vmSeries}
|
||||
{...this.props.options}
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,14 +312,20 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
||||
const formatFunc = kbn.valueFormats[this.panel.format];
|
||||
data.value = lastPoint[1];
|
||||
data.valueRounded = data.value;
|
||||
data.valueFormatted = formatFunc(data.value, this.dashboard.isTimezoneUtc());
|
||||
data.valueFormatted = formatFunc(data.value, 0, 0, this.dashboard.isTimezoneUtc());
|
||||
} else {
|
||||
data.value = this.series[0].stats[this.panel.valueName];
|
||||
data.flotpairs = this.series[0].flotpairs;
|
||||
|
||||
const decimalInfo = this.getDecimalsForValue(data.value);
|
||||
const formatFunc = kbn.valueFormats[this.panel.format];
|
||||
data.valueFormatted = formatFunc(data.value, decimalInfo.decimals, decimalInfo.scaledDecimals);
|
||||
|
||||
data.valueFormatted = formatFunc(
|
||||
data.value,
|
||||
decimalInfo.decimals,
|
||||
decimalInfo.scaledDecimals,
|
||||
this.dashboard.isTimezoneUtc()
|
||||
);
|
||||
data.valueRounded = kbn.roundValue(data.value, decimalInfo.decimals);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,9 @@ $side-menu-width: 60px;
|
||||
// dashboard
|
||||
$panel-margin: 10px;
|
||||
$dashboard-padding: $panel-margin * 2;
|
||||
$panel-padding: 0px 10px 5px 10px;
|
||||
$panel-horizontal-padding: 10;
|
||||
$panel-vertical-padding: 5;
|
||||
$panel-padding: 0px $panel-horizontal-padding+0px $panel-vertical-padding+0px $panel-horizontal-padding+0px;
|
||||
|
||||
// tabs
|
||||
$tabs-padding: 10px 15px 9px;
|
||||
@@ -202,3 +204,8 @@ $external-services: (
|
||||
oauth: (bgColor: #262628, borderColor: #393939, icon: '')
|
||||
)
|
||||
!default;
|
||||
|
||||
:export {
|
||||
panelHorizontalPadding: $panel-horizontal-padding;
|
||||
panelVerticalPadding: $panel-vertical-padding;
|
||||
}
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
export interface GrafanaVariables {
|
||||
'panelHorizontalPadding': number;
|
||||
'panelVerticalPadding': number;
|
||||
}
|
||||
|
||||
declare const variables: GrafanaVariables;
|
||||
|
||||
export default variables;
|
||||
+2
-1
@@ -28,7 +28,8 @@
|
||||
"pretty": true,
|
||||
"typeRoots": ["node_modules/@types", "types"],
|
||||
"paths": {
|
||||
"app": ["app"]
|
||||
"app": ["app"],
|
||||
"sass": ["sass"]
|
||||
}
|
||||
},
|
||||
"include": ["public/app/**/*.ts", "public/app/**/*.tsx", "public/test/**/*.ts"]
|
||||
|
||||
Reference in New Issue
Block a user