diff --git a/packages/grafana-data/src/utils/valueMappings.ts b/packages/grafana-data/src/utils/valueMappings.ts index 61ef4403692..f8095d49a01 100644 --- a/packages/grafana-data/src/utils/valueMappings.ts +++ b/packages/grafana-data/src/utils/valueMappings.ts @@ -172,7 +172,7 @@ export function getMappedValue(valueMappings: LegacyValueMapping[], value: any): * @alpha * Converts the old Angular value mappings to new react style */ -export function convertOldAngularValueMappings(panel: any): ValueMapping[] { +export function convertOldAngularValueMappings(panel: any, migratedThresholds?: ThresholdsConfig): ValueMapping[] { const mappings: ValueMapping[] = []; // Guess the right type based on options @@ -184,7 +184,6 @@ export function convertOldAngularValueMappings(panel: any): ValueMapping[] { mappingType = 2; } } - if (mappingType === 1) { for (let i = 0; i < panel.valueMaps.length; i++) { const map = panel.valueMaps[i]; @@ -195,7 +194,7 @@ export function convertOldAngularValueMappings(panel: any): ValueMapping[] { id: i, // used for order type: MappingType.ValueToText, }, - panel.fieldConfig?.defaults?.thresholds + panel.fieldConfig?.defaults?.thresholds || migratedThresholds ) ); } @@ -209,7 +208,7 @@ export function convertOldAngularValueMappings(panel: any): ValueMapping[] { id: i, // used for order type: MappingType.RangeToText, }, - panel.fieldConfig?.defaults?.thresholds + panel.fieldConfig?.defaults?.thresholds || migratedThresholds ) ); } diff --git a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts index 014b03ce607..4ef51e62b29 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts +++ b/packages/grafana-ui/src/components/SingleStatShared/SingleStatBaseOptions.ts @@ -107,7 +107,7 @@ function migrateFromAngularSinglestat(panel: PanelModel { `); }); }); + + describe('when migrating singlestat value mappings', () => { + it('should migrate value mapping', () => { + const model = new DashboardModel({ + panels: [ + { + type: 'singlestat', + legend: true, + thresholds: '10,20,30', + colors: ['#FF0000', 'green', 'orange'], + aliasYAxis: { test: 2 }, + grid: { min: 1, max: 10 }, + targets: [{ refId: 'A' }, {}], + mappingType: 1, + mappingTypes: [ + { + name: 'value to text', + value: 1, + }, + ], + valueMaps: [ + { + op: '=', + text: 'test', + value: '20', + }, + { + op: '=', + text: 'test1', + value: '30', + }, + { + op: '=', + text: '50', + value: '40', + }, + ], + }, + ], + }); + expect(model.panels[0].fieldConfig.defaults.mappings).toMatchInlineSnapshot(` + Array [ + Object { + "options": Object { + "20": Object { + "color": undefined, + "text": "test", + }, + "30": Object { + "color": undefined, + "text": "test1", + }, + "40": Object { + "color": "orange", + "text": "50", + }, + }, + "type": "value", + }, + ] + `); + }); + + it('should migrate range mapping', () => { + const model = new DashboardModel({ + panels: [ + { + type: 'singlestat', + legend: true, + thresholds: '10,20,30', + colors: ['#FF0000', 'green', 'orange'], + aliasYAxis: { test: 2 }, + grid: { min: 1, max: 10 }, + targets: [{ refId: 'A' }, {}], + mappingType: 2, + mappingTypes: [ + { + name: 'range to text', + value: 2, + }, + ], + rangeMaps: [ + { + from: '20', + to: '25', + text: 'text1', + }, + { + from: '1', + to: '5', + text: 'text2', + }, + { + from: '5', + to: '10', + text: '50', + }, + ], + }, + ], + }); + expect(model.panels[0].fieldConfig.defaults.mappings).toMatchInlineSnapshot(` + Array [ + Object { + "options": Object { + "from": 20, + "result": Object { + "color": undefined, + "text": "text1", + }, + "to": 25, + }, + "type": "range", + }, + Object { + "options": Object { + "from": 1, + "result": Object { + "color": undefined, + "text": "text2", + }, + "to": 5, + }, + "type": "range", + }, + Object { + "options": Object { + "from": 5, + "result": Object { + "color": "orange", + "text": "50", + }, + "to": 10, + }, + "type": "range", + }, + ] + `); + }); + }); }); function createRow(options: any, panelDescriptions: any[]) { diff --git a/public/app/features/dashboard/state/DashboardMigrator.ts b/public/app/features/dashboard/state/DashboardMigrator.ts index ed0d87a0457..7c0acd29ff3 100644 --- a/public/app/features/dashboard/state/DashboardMigrator.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.ts @@ -977,6 +977,20 @@ function upgradeValueMappings(oldMappings: any, thresholds?: ThresholdsConfig): const newMappings: ValueMapping[] = []; for (const old of oldMappings) { + // when migrating singlestat to stat/gauge, mappings are handled by panel type change handler used in that migration + if (old.type && old.options) { + // collect al value->text mappings in a single value map object. These are migrated by panel change handler as a separate value maps + if (old.type === MappingType.ValueToText) { + valueMaps.options = { + ...valueMaps.options, + ...old.options, + }; + } else { + newMappings.push(old); + } + continue; + } + // Use the color we would have picked from thesholds let color: string | undefined = undefined; const numeric = parseFloat(old.text);