mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SingleStat: add a gauge migration call to action button in the editor (#18604)
This commit is contained in:
parent
d1860df8d8
commit
21948e80e0
@ -1,6 +1,6 @@
|
||||
import { sharedSingleStatMigrationCheck } from './SingleStatBaseOptions';
|
||||
import { sharedSingleStatMigrationHandler } from './SingleStatBaseOptions';
|
||||
|
||||
describe('sharedSingleStatMigrationCheck', () => {
|
||||
describe('sharedSingleStatMigrationHandler', () => {
|
||||
it('from old valueOptions model without pluginVersion', () => {
|
||||
const panel = {
|
||||
options: {
|
||||
@ -34,6 +34,6 @@ describe('sharedSingleStatMigrationCheck', () => {
|
||||
type: 'bargauge',
|
||||
};
|
||||
|
||||
expect(sharedSingleStatMigrationCheck(panel as any)).toMatchSnapshot();
|
||||
expect(sharedSingleStatMigrationHandler(panel as any)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -3,7 +3,15 @@ import omit from 'lodash/omit';
|
||||
|
||||
import { VizOrientation, PanelModel } from '../../types/panel';
|
||||
import { FieldDisplayOptions } from '../../utils/fieldDisplay';
|
||||
import { fieldReducers, Threshold, sortThresholds } from '@grafana/data';
|
||||
import {
|
||||
fieldReducers,
|
||||
Threshold,
|
||||
sortThresholds,
|
||||
FieldConfig,
|
||||
ReducerID,
|
||||
ValueMapping,
|
||||
MappingType,
|
||||
} from '@grafana/data';
|
||||
|
||||
export interface SingleStatBaseOptions {
|
||||
fieldOptions: FieldDisplayOptions;
|
||||
@ -12,23 +20,82 @@ export interface SingleStatBaseOptions {
|
||||
|
||||
const optionsToKeep = ['fieldOptions', 'orientation'];
|
||||
|
||||
export const sharedSingleStatOptionsCheck = (
|
||||
export function sharedSingleStatPanelChangedHandler(
|
||||
options: Partial<SingleStatBaseOptions> | any,
|
||||
prevPluginId: string,
|
||||
prevOptions: any
|
||||
) => {
|
||||
) {
|
||||
// Migrating from angular singlestat
|
||||
if (prevPluginId === 'singlestat' && prevOptions.angular) {
|
||||
const panel = prevOptions.angular;
|
||||
const reducer = fieldReducers.getIfExists(panel.valueName);
|
||||
const options = {
|
||||
fieldOptions: {
|
||||
defaults: {} as FieldConfig,
|
||||
override: {} as FieldConfig,
|
||||
calcs: [reducer ? reducer.id : ReducerID.mean],
|
||||
},
|
||||
orientation: VizOrientation.Horizontal,
|
||||
};
|
||||
|
||||
const defaults = options.fieldOptions.defaults;
|
||||
if (panel.format) {
|
||||
defaults.unit = panel.format;
|
||||
}
|
||||
if (panel.nullPointMode) {
|
||||
defaults.nullValueMode = panel.nullPointMode;
|
||||
}
|
||||
if (panel.nullText) {
|
||||
defaults.noValue = panel.nullText;
|
||||
}
|
||||
if (panel.decimals || panel.decimals === 0) {
|
||||
defaults.decimals = panel.decimals;
|
||||
}
|
||||
|
||||
// Convert thresholds and color values
|
||||
if (panel.thresholds && panel.colors) {
|
||||
const levels = panel.thresholds.split(',').map((strVale: string) => {
|
||||
return Number(strVale.trim());
|
||||
});
|
||||
|
||||
// One more color than threshold
|
||||
const thresholds: Threshold[] = [];
|
||||
for (const color of panel.colors) {
|
||||
const idx = thresholds.length - 1;
|
||||
if (idx >= 0) {
|
||||
thresholds.push({ value: levels[idx], color });
|
||||
} else {
|
||||
thresholds.push({ value: -Infinity, color });
|
||||
}
|
||||
}
|
||||
defaults.thresholds = thresholds;
|
||||
}
|
||||
|
||||
// Convert value mappings
|
||||
const mappings = convertOldAngulrValueMapping(panel);
|
||||
if (mappings && mappings.length) {
|
||||
defaults.mappings = mappings;
|
||||
}
|
||||
|
||||
if (panel.gauge) {
|
||||
defaults.min = panel.gauge.minValue;
|
||||
defaults.max = panel.gauge.maxValue;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
for (const k of optionsToKeep) {
|
||||
if (prevOptions.hasOwnProperty(k)) {
|
||||
options[k] = cloneDeep(prevOptions[k]);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
}
|
||||
|
||||
export function sharedSingleStatMigrationCheck(panel: PanelModel<SingleStatBaseOptions>) {
|
||||
export function sharedSingleStatMigrationHandler(panel: PanelModel<SingleStatBaseOptions>): SingleStatBaseOptions {
|
||||
if (!panel.options) {
|
||||
// This happens on the first load or when migrating from angular
|
||||
return {};
|
||||
return {} as any;
|
||||
}
|
||||
|
||||
const previousVersion = parseFloat(panel.pluginVersion || '6.1');
|
||||
@ -121,3 +188,43 @@ export function migrateOldThresholds(thresholds?: any[]): Threshold[] | undefine
|
||||
copy[0].value = -Infinity;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the angular single stat mapping to new react style
|
||||
*/
|
||||
function convertOldAngulrValueMapping(panel: any): ValueMapping[] {
|
||||
const mappings: ValueMapping[] = [];
|
||||
|
||||
// Guess the right type based on options
|
||||
let mappingType = panel.mappingType;
|
||||
if (!panel.mappingType) {
|
||||
if (panel.valueMaps && panel.valueMaps.length) {
|
||||
mappingType = 1;
|
||||
} else if (panel.rangeMaps && panel.rangeMaps.length) {
|
||||
mappingType = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// check value to text mappings if its enabled
|
||||
if (mappingType === 1) {
|
||||
for (let i = 0; i < panel.valueMaps.length; i++) {
|
||||
const map = panel.valueMaps[i];
|
||||
mappings.push({
|
||||
...map,
|
||||
id: i, // used for order
|
||||
type: MappingType.ValueToText,
|
||||
});
|
||||
}
|
||||
} else if (mappingType === 2) {
|
||||
for (let i = 0; i < panel.rangeMaps.length; i++) {
|
||||
const map = panel.rangeMaps[i];
|
||||
mappings.push({
|
||||
...map,
|
||||
id: i, // used for order
|
||||
type: MappingType.RangeToText,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sharedSingleStatMigrationCheck from old valueOptions model without pluginVersion 1`] = `
|
||||
exports[`sharedSingleStatMigrationHandler from old valueOptions model without pluginVersion 1`] = `
|
||||
Object {
|
||||
"fieldOptions": Object {
|
||||
"calcs": Array [
|
||||
|
@ -3,6 +3,6 @@ export { FieldPropertiesEditor } from './FieldPropertiesEditor';
|
||||
|
||||
export {
|
||||
SingleStatBaseOptions,
|
||||
sharedSingleStatOptionsCheck,
|
||||
sharedSingleStatMigrationCheck,
|
||||
sharedSingleStatPanelChangedHandler,
|
||||
sharedSingleStatMigrationHandler,
|
||||
} from './SingleStatBaseOptions';
|
||||
|
@ -61,7 +61,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
|
||||
return <AddPanelWidget panel={this.props.panel} dashboard={this.props.dashboard} />;
|
||||
}
|
||||
|
||||
onPluginTypeChanged = (plugin: PanelPluginMeta) => {
|
||||
onPluginTypeChange = (plugin: PanelPluginMeta) => {
|
||||
this.loadPlugin(plugin.id);
|
||||
};
|
||||
|
||||
@ -211,7 +211,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
|
||||
plugin={plugin}
|
||||
dashboard={dashboard}
|
||||
angularPanel={angularPanel}
|
||||
onTypeChanged={this.onPluginTypeChanged}
|
||||
onPluginTypeChange={this.onPluginTypeChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -20,7 +20,7 @@ interface PanelEditorProps {
|
||||
dashboard: DashboardModel;
|
||||
plugin: PanelPlugin;
|
||||
angularPanel?: AngularComponent;
|
||||
onTypeChanged: (newType: PanelPluginMeta) => void;
|
||||
onPluginTypeChange: (newType: PanelPluginMeta) => void;
|
||||
}
|
||||
|
||||
interface PanelEditorTab {
|
||||
@ -70,7 +70,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
|
||||
};
|
||||
|
||||
renderCurrentTab(activeTab: string) {
|
||||
const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props;
|
||||
const { panel, dashboard, onPluginTypeChange, plugin, angularPanel } = this.props;
|
||||
|
||||
switch (activeTab) {
|
||||
case 'advanced':
|
||||
@ -85,7 +85,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
|
||||
panel={panel}
|
||||
dashboard={dashboard}
|
||||
plugin={plugin}
|
||||
onTypeChanged={onTypeChanged}
|
||||
onPluginTypeChange={onPluginTypeChange}
|
||||
angularPanel={angularPanel}
|
||||
/>
|
||||
);
|
||||
|
@ -19,13 +19,14 @@ import { DashboardModel } from '../state';
|
||||
import { VizPickerSearch } from './VizPickerSearch';
|
||||
import PluginStateinfo from 'app/features/plugins/PluginStateInfo';
|
||||
import { PanelPlugin, PanelPluginMeta } from '@grafana/ui';
|
||||
import { PanelCtrl } from 'app/plugins/sdk';
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
dashboard: DashboardModel;
|
||||
plugin: PanelPlugin;
|
||||
angularPanel?: AngularComponent;
|
||||
onTypeChanged: (newType: PanelPluginMeta) => void;
|
||||
onPluginTypeChange: (newType: PanelPluginMeta) => void;
|
||||
updateLocation: typeof updateLocation;
|
||||
urlOpenVizPicker: boolean;
|
||||
}
|
||||
@ -104,8 +105,9 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
return;
|
||||
}
|
||||
|
||||
const panelCtrl = scope.$$childHead.ctrl;
|
||||
const panelCtrl: PanelCtrl = scope.$$childHead.ctrl;
|
||||
panelCtrl.initEditMode();
|
||||
panelCtrl.onPluginTypeChange = this.onPluginTypeChange;
|
||||
|
||||
let template = '';
|
||||
for (let i = 0; i < panelCtrl.editorTabs.length; i++) {
|
||||
@ -197,11 +199,11 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
onTypeChanged = (plugin: PanelPluginMeta) => {
|
||||
onPluginTypeChange = (plugin: PanelPluginMeta) => {
|
||||
if (plugin.id === this.props.plugin.meta.id) {
|
||||
this.setState({ isVizPickerOpen: false });
|
||||
} else {
|
||||
this.props.onTypeChanged(plugin);
|
||||
this.props.onPluginTypeChange(plugin);
|
||||
}
|
||||
};
|
||||
|
||||
@ -235,7 +237,7 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
<FadeIn in={isVizPickerOpen} duration={200} unmountOnExit={true} onExited={this.clearQuery}>
|
||||
<VizTypePicker
|
||||
current={meta}
|
||||
onTypeChanged={this.onTypeChanged}
|
||||
onTypeChange={this.onPluginTypeChange}
|
||||
searchQuery={searchQuery}
|
||||
onClose={this.onCloseVizPicker}
|
||||
/>
|
||||
|
@ -6,7 +6,7 @@ import { PanelPluginMeta, EmptySearchResult } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
current: PanelPluginMeta;
|
||||
onTypeChanged: (newType: PanelPluginMeta) => void;
|
||||
onTypeChange: (newType: PanelPluginMeta) => void;
|
||||
searchQuery: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
@ -34,16 +34,11 @@ export class VizTypePicker extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
renderVizPlugin = (plugin: PanelPluginMeta, index: number) => {
|
||||
const { onTypeChanged } = this.props;
|
||||
const { onTypeChange } = this.props;
|
||||
const isCurrent = plugin.id === this.props.current.id;
|
||||
|
||||
return (
|
||||
<VizTypePickerPlugin
|
||||
key={plugin.id}
|
||||
isCurrent={isCurrent}
|
||||
plugin={plugin}
|
||||
onClick={() => onTypeChanged(plugin)}
|
||||
/>
|
||||
<VizTypePickerPlugin key={plugin.id} isCurrent={isCurrent} plugin={plugin} onClick={() => onTypeChange(plugin)} />
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -165,7 +165,7 @@ describe('PanelModel', () => {
|
||||
it('should call react onPanelTypeChanged', () => {
|
||||
expect(onPanelTypeChanged.mock.calls.length).toBe(1);
|
||||
expect(onPanelTypeChanged.mock.calls[0][1]).toBe('table');
|
||||
expect(onPanelTypeChanged.mock.calls[0][2].fieldOptions).toBeDefined();
|
||||
expect(onPanelTypeChanged.mock.calls[0][2].angular).toBeDefined();
|
||||
});
|
||||
|
||||
it('getQueryRunner() should return same instance after changing to another react panel', () => {
|
||||
|
@ -262,9 +262,10 @@ export class PanelModel {
|
||||
const pluginId = newPlugin.meta.id;
|
||||
const oldOptions: any = this.getOptionsToRemember();
|
||||
const oldPluginId = this.type;
|
||||
const wasAngular = !!this.plugin.angularPanelCtrl;
|
||||
|
||||
// for angular panels we must remove all events and let angular panels do some cleanup
|
||||
if (this.plugin.angularPanelCtrl) {
|
||||
if (wasAngular) {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
@ -280,16 +281,24 @@ export class PanelModel {
|
||||
this.cachedPluginOptions[oldPluginId] = oldOptions;
|
||||
this.restorePanelOptions(pluginId);
|
||||
|
||||
// Let panel plugins inspect options from previous panel and keep any that it can use
|
||||
if (newPlugin.onPanelTypeChanged) {
|
||||
let old: any = {};
|
||||
|
||||
if (wasAngular) {
|
||||
old = { angular: oldOptions };
|
||||
} else if (oldOptions && oldOptions.options) {
|
||||
old = oldOptions.options;
|
||||
}
|
||||
|
||||
this.options = this.options || {};
|
||||
Object.assign(this.options, newPlugin.onPanelTypeChanged(this.options, oldPluginId, old));
|
||||
}
|
||||
|
||||
// switch
|
||||
this.type = pluginId;
|
||||
this.plugin = newPlugin;
|
||||
this.applyPluginOptionDefaults(newPlugin);
|
||||
// Let panel plugins inspect options from previous panel and keep any that it can use
|
||||
if (newPlugin.onPanelTypeChanged) {
|
||||
this.options = this.options || {};
|
||||
const old = oldOptions && oldOptions.options ? oldOptions.options : {};
|
||||
Object.assign(this.options, newPlugin.onPanelTypeChanged(this.options, oldPluginId, old));
|
||||
}
|
||||
|
||||
if (newPlugin.onPanelMigration) {
|
||||
this.pluginVersion = getPluginVersion(newPlugin);
|
||||
|
@ -19,6 +19,7 @@ import { GRID_COLUMN_COUNT } from 'app/core/constants';
|
||||
import { auto } from 'angular';
|
||||
import { TemplateSrv } from '../templating/template_srv';
|
||||
import { LinkSrv } from './panellinks/link_srv';
|
||||
import { PanelPluginMeta } from '@grafana/ui/src/types/panel';
|
||||
|
||||
export class PanelCtrl {
|
||||
panel: any;
|
||||
@ -281,4 +282,7 @@ export class PanelCtrl {
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
// overriden from react
|
||||
onPluginTypeChange = (plugin: PanelPluginMeta) => {};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import { barGaugePanelMigrationCheck } from './BarGaugeMigrations';
|
||||
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
||||
|
||||
describe('BarGauge Panel Migrations', () => {
|
||||
it('from 6.2', () => {
|
||||
@ -45,6 +45,6 @@ describe('BarGauge Panel Migrations', () => {
|
||||
type: 'bargauge',
|
||||
} as PanelModel;
|
||||
|
||||
expect(barGaugePanelMigrationCheck(panel)).toMatchSnapshot();
|
||||
expect(barGaugePanelMigrationHandler(panel)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
import { PanelModel, sharedSingleStatMigrationHandler } from '@grafana/ui';
|
||||
import { BarGaugeOptions } from './types';
|
||||
|
||||
export const barGaugePanelMigrationCheck = (panel: PanelModel<BarGaugeOptions>): Partial<BarGaugeOptions> => {
|
||||
return sharedSingleStatMigrationCheck(panel);
|
||||
export const barGaugePanelMigrationHandler = (panel: PanelModel<BarGaugeOptions>): Partial<BarGaugeOptions> => {
|
||||
return sharedSingleStatMigrationHandler(panel);
|
||||
};
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { PanelPlugin, sharedSingleStatOptionsCheck } from '@grafana/ui';
|
||||
import { PanelPlugin, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
||||
import { BarGaugeOptions, defaults } from './types';
|
||||
import { barGaugePanelMigrationCheck } from './BarGaugeMigrations';
|
||||
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
||||
|
||||
export const plugin = new PanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
||||
.setDefaults(defaults)
|
||||
.setEditor(BarGaugePanelEditor)
|
||||
.setPanelChangeHandler(sharedSingleStatOptionsCheck)
|
||||
.setMigrationHandler(barGaugePanelMigrationCheck);
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
.setMigrationHandler(barGaugePanelMigrationHandler);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import { gaugePanelMigrationCheck } from './GaugeMigrations';
|
||||
import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations';
|
||||
|
||||
describe('Gauge Panel Migrations', () => {
|
||||
it('from 6.1.1', () => {
|
||||
@ -77,6 +77,30 @@ describe('Gauge Panel Migrations', () => {
|
||||
type: 'gauge',
|
||||
} as PanelModel;
|
||||
|
||||
expect(gaugePanelMigrationCheck(panel)).toMatchSnapshot();
|
||||
expect(gaugePanelMigrationHandler(panel)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('change from angular singlestat to gauge', () => {
|
||||
const old: any = {
|
||||
angular: {
|
||||
format: 'ms',
|
||||
decimals: 7,
|
||||
gauge: {
|
||||
maxValue: 150,
|
||||
minValue: -10,
|
||||
show: true,
|
||||
thresholdLabels: true,
|
||||
thresholdMarkers: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const newOptions = gaugePanelChangedHandler({} as any, 'singlestat', old);
|
||||
expect(newOptions.fieldOptions.defaults.unit).toBe('ms');
|
||||
expect(newOptions.fieldOptions.defaults.min).toBe(-10);
|
||||
expect(newOptions.fieldOptions.defaults.max).toBe(150);
|
||||
expect(newOptions.fieldOptions.defaults.decimals).toBe(7);
|
||||
expect(newOptions.showThresholdMarkers).toBe(true);
|
||||
expect(newOptions.showThresholdLabels).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,27 @@
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import { PanelModel, sharedSingleStatPanelChangedHandler, sharedSingleStatMigrationHandler } from '@grafana/ui';
|
||||
import { GaugeOptions } from './types';
|
||||
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
|
||||
export const gaugePanelMigrationCheck = (panel: PanelModel<GaugeOptions>): Partial<GaugeOptions> => {
|
||||
return sharedSingleStatMigrationCheck(panel);
|
||||
// This is called when the panel first loads
|
||||
export const gaugePanelMigrationHandler = (panel: PanelModel<GaugeOptions>): Partial<GaugeOptions> => {
|
||||
return sharedSingleStatMigrationHandler(panel);
|
||||
};
|
||||
|
||||
// This is called when the panel changes from another panel
|
||||
export const gaugePanelChangedHandler = (
|
||||
options: Partial<GaugeOptions> | any,
|
||||
prevPluginId: string,
|
||||
prevOptions: any
|
||||
) => {
|
||||
// This handles most config changes
|
||||
const opts = sharedSingleStatPanelChangedHandler(options, prevPluginId, prevOptions) as GaugeOptions;
|
||||
|
||||
// Changing from angular singlestat
|
||||
if (prevPluginId === 'singlestat' && prevOptions.angular) {
|
||||
const gauge = prevOptions.angular.gauge;
|
||||
if (gauge) {
|
||||
opts.showThresholdMarkers = gauge.thresholdMarkers;
|
||||
opts.showThresholdLabels = gauge.thresholdLabels;
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
};
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui';
|
||||
import { PanelPlugin } from '@grafana/ui';
|
||||
import { GaugePanelEditor } from './GaugePanelEditor';
|
||||
import { GaugePanel } from './GaugePanel';
|
||||
import { GaugeOptions, defaults } from './types';
|
||||
import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations';
|
||||
|
||||
export const plugin = new PanelPlugin<GaugeOptions>(GaugePanel)
|
||||
.setDefaults(defaults)
|
||||
.setEditor(GaugePanelEditor)
|
||||
.setPanelChangeHandler(sharedSingleStatOptionsCheck)
|
||||
.setMigrationHandler(sharedSingleStatMigrationCheck);
|
||||
.setPanelChangeHandler(gaugePanelChangedHandler)
|
||||
.setMigrationHandler(gaugePanelMigrationHandler);
|
||||
|
@ -1,4 +1,41 @@
|
||||
<div class="editor-row">
|
||||
|
||||
<div class="grafana-info-box" ng-if="ctrl.panel.gauge.show">
|
||||
<h5>Gauge Migration</h5>
|
||||
<p>
|
||||
Gauge visualizations within the Singlestat panel are deprecated. Please
|
||||
migrate this panel to use the Gauge panel
|
||||
|
||||
<div class="gf-form-button-row">
|
||||
<button class="btn btn-primary" ng-click="ctrl.migrateToGaugePanel(true)">
|
||||
Migrate to Gauge Panel
|
||||
</button>
|
||||
<button class="btn btn-inverse" ng-click="ctrl.migrateToGaugePanel(false)">
|
||||
Show as single stat
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div ng-if="ctrl.panel.sparkline.show">
|
||||
<b>NOTE:</b> Sparklines are not supported in the gauge panel
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.panel.prefix">
|
||||
<b>NOTE:</b> Prefix will not be show in the gauge panel
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.panel.postfix">
|
||||
<b>NOTE:</b> Postfix will not be show in the gauge panel
|
||||
</div>
|
||||
|
||||
<div ng-if="ctrl.panel.links && ctrl.panel.links.length">
|
||||
<b>NOTE:</b> Links will be in the upper left corner, rather than anywhere on the gauge
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section gf-form-group">
|
||||
<h5 class="section-heading">Value</h5>
|
||||
|
||||
|
@ -113,6 +113,15 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
||||
this.unitFormats = kbn.getUnitFormats();
|
||||
}
|
||||
|
||||
migrateToGaugePanel(migrate: boolean) {
|
||||
if (migrate) {
|
||||
this.onPluginTypeChange(config.panels['gauge']);
|
||||
} else {
|
||||
this.panel.gauge.show = false;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
setUnitFormat(subItem: { value: any }) {
|
||||
this.panel.format = subItem.value;
|
||||
this.refresh();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui';
|
||||
import { PanelPlugin, sharedSingleStatMigrationHandler, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||
import { SingleStatOptions, defaults } from './types';
|
||||
import { SingleStatPanel } from './SingleStatPanel';
|
||||
import { SingleStatEditor } from './SingleStatEditor';
|
||||
@ -6,5 +6,5 @@ import { SingleStatEditor } from './SingleStatEditor';
|
||||
export const plugin = new PanelPlugin<SingleStatOptions>(SingleStatPanel)
|
||||
.setDefaults(defaults)
|
||||
.setEditor(SingleStatEditor)
|
||||
.setPanelChangeHandler(sharedSingleStatOptionsCheck)
|
||||
.setMigrationHandler(sharedSingleStatMigrationCheck);
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
.setMigrationHandler(sharedSingleStatMigrationHandler);
|
||||
|
Loading…
Reference in New Issue
Block a user