diff --git a/packages/grafana-data/src/field/getFieldDisplayValuesProxt.test.tsx b/packages/grafana-data/src/field/getFieldDisplayValuesProxt.test.tsx new file mode 100644 index 00000000000..a821cb2412b --- /dev/null +++ b/packages/grafana-data/src/field/getFieldDisplayValuesProxt.test.tsx @@ -0,0 +1,68 @@ +import { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy'; +import { applyFieldOverrides } from './fieldOverrides'; +import { toDataFrame } from '../dataframe'; +import { GrafanaTheme } from '../types'; + +describe('getFieldDisplayValuesProxy', () => { + const data = applyFieldOverrides({ + data: [ + toDataFrame({ + fields: [ + { name: 'Time', values: [1, 2, 3] }, + { + name: 'power', + values: [100, 200, 300], + config: { + title: 'The Power', + }, + }, + { + name: 'Last', + values: ['a', 'b', 'c'], + }, + ], + }), + ], + fieldConfig: { + defaults: {}, + overrides: [], + }, + replaceVariables: (val: string) => val, + timeZone: 'utc', + theme: {} as GrafanaTheme, + autoMinMax: true, + })[0]; + + it('should define all display functions', () => { + // Field display should be set + for (const field of data.fields) { + expect(field.display).toBeDefined(); + } + }); + + it('should format the time values in UTC', () => { + // Test Proxies in general + const p = getFieldDisplayValuesProxy(data, 0); + const time = p.Time; + expect(time.numeric).toEqual(1); + expect(time.text).toEqual('1970-01-01 00:00:00'); + + // Should get to the same values by name or index + const time2 = p[0]; + expect(time2.toString()).toEqual(time.toString()); + }); + + it('Lookup by name, index, or title', () => { + const p = getFieldDisplayValuesProxy(data, 2); + expect(p.power.numeric).toEqual(300); + expect(p['power'].numeric).toEqual(300); + expect(p['The Power'].numeric).toEqual(300); + expect(p[1].numeric).toEqual(300); + }); + + it('should return undefined when missing', () => { + const p = getFieldDisplayValuesProxy(data, 0); + expect(p.xyz).toBeUndefined(); + expect(p[100]).toBeUndefined(); + }); +}); diff --git a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts new file mode 100644 index 00000000000..bfc70aec755 --- /dev/null +++ b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts @@ -0,0 +1,49 @@ +import toNumber from 'lodash/toNumber'; +import { DataFrame, DisplayValue, GrafanaTheme } from '../types'; +import { getDisplayProcessor } from './displayProcessor'; +import { formattedValueToString } from '../valueFormats'; + +/** + * + * @param frame + * @param rowIndex + * @param options + * @internal + */ +export function getFieldDisplayValuesProxy( + frame: DataFrame, + rowIndex: number, + options: { + theme: GrafanaTheme; + } +): Record { + return new Proxy({} as Record, { + get: (obj: any, key: string) => { + // 1. Match the name + let field = frame.fields.find(f => key === f.name); + if (!field) { + // 2. Match the array index + const k = toNumber(key); + field = frame.fields[k]; + } + if (!field) { + // 3. Match the title + field = frame.fields.find(f => key === f.config.title); + } + if (!field) { + return undefined; + } + if (!field.display) { + // Lazy load the display processor + field.display = getDisplayProcessor({ + field, + theme: options.theme, + }); + } + const raw = field.values.get(rowIndex); + const disp = field.display(raw); + disp.toString = () => formattedValueToString(disp); + return disp; + }, + }); +} diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts new file mode 100644 index 00000000000..987eff39a7b --- /dev/null +++ b/packages/grafana-data/src/types/config.ts @@ -0,0 +1,70 @@ +import { DataSourceInstanceSettings } from './datasource'; +import { PanelPluginMeta } from './panel'; +import { GrafanaTheme } from './theme'; + +export interface BuildInfo { + version: string; + commit: string; + isEnterprise: boolean; // deprecated: use licenseInfo.hasLicense instead + env: string; + edition: string; + latestVersion: string; + hasUpdate: boolean; +} + +export interface FeatureToggles { + transformations: boolean; + expressions: boolean; + newEdit: boolean; + meta: boolean; // enterprise + newVariables: boolean; + tracingIntegration: boolean; +} + +export interface LicenseInfo { + hasLicense: boolean; + expiry: number; + licenseUrl: string; + stateInfo: string; +} + +export interface GrafanaConfig { + datasources: { [str: string]: DataSourceInstanceSettings }; + panels: { [key: string]: PanelPluginMeta }; + minRefreshInterval: string; + appSubUrl: string; + windowTitlePrefix: string; + buildInfo: BuildInfo; + newPanelTitle: string; + bootData: any; + externalUserMngLinkUrl: string; + externalUserMngLinkName: string; + externalUserMngInfo: string; + allowOrgCreate: boolean; + disableLoginForm: boolean; + defaultDatasource: string; + alertingEnabled: boolean; + alertingErrorOrTimeout: string; + alertingNoDataOrNullValues: string; + alertingMinInterval: number; + authProxyEnabled: boolean; + exploreEnabled: boolean; + ldapEnabled: boolean; + samlEnabled: boolean; + autoAssignOrg: boolean; + verifyEmailEnabled: boolean; + oauth: any; + disableUserSignUp: boolean; + loginHint: any; + passwordHint: any; + loginError: any; + navTree: any; + viewersCanEdit: boolean; + editorsCanAdmin: boolean; + disableSanitizeHtml: boolean; + theme: GrafanaTheme; + pluginsToPreload: string[]; + featureToggles: FeatureToggles; + licenseInfo: LicenseInfo; + phantomJSRenderer: boolean; +} diff --git a/packages/grafana-data/src/types/index.ts b/packages/grafana-data/src/types/index.ts index 66af316e931..00e6547812f 100644 --- a/packages/grafana-data/src/types/index.ts +++ b/packages/grafana-data/src/types/index.ts @@ -31,3 +31,4 @@ export { AppEvent, AppEvents }; import * as PanelEvents from './panelEvents'; export { PanelEvents }; +export { GrafanaConfig, BuildInfo, FeatureToggles, LicenseInfo } from './config'; diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 406a741b119..61417149332 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -1,34 +1,17 @@ import extend from 'lodash/extend'; import { getTheme } from '@grafana/ui'; -import { DataSourceInstanceSettings, GrafanaTheme, GrafanaThemeType, PanelPluginMeta } from '@grafana/data'; +import { + DataSourceInstanceSettings, + GrafanaTheme, + GrafanaThemeType, + PanelPluginMeta, + GrafanaConfig, + LicenseInfo, + BuildInfo, + FeatureToggles, +} from '@grafana/data'; -export interface BuildInfo { - version: string; - commit: string; - isEnterprise: boolean; // deprecated: use licenseInfo.hasLicense instead - env: string; - edition: string; - latestVersion: string; - hasUpdate: boolean; -} - -interface FeatureToggles { - transformations: boolean; - expressions: boolean; - newEdit: boolean; - meta: boolean; // enterprise - newVariables: boolean; - tracingIntegration: boolean; -} - -interface LicenseInfo { - hasLicense: boolean; - expiry: number; - licenseUrl: string; - stateInfo: string; -} - -export class GrafanaBootConfig { +export class GrafanaBootConfig implements GrafanaConfig { datasources: { [str: string]: DataSourceInstanceSettings } = {}; panels: { [key: string]: PanelPluginMeta } = {}; minRefreshInterval = '';