mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
[Gauge] Vis Type (#126048)
* Added transparent background * Added gauge/goal visType. * Fixed palette, scale, and types. * Set legacy chart as default. * Removed deprecation message. * Added percent format params, coming from visdimensions. * Added support of labels/sublabels. * Updated i18n label. * Added support of showElasticChartsOptions * Added autoextend ranges elastic charts tooltip. * The outline elastic-charts message added. * outline renaming and metric/buckets limitations * reverted mistaken change of sample_vis.test.mocks. * Warning message added to gauge split chart. * Added warning message to the splitChart button at goal/gauge. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
6c0526b67c
commit
2b6885a74c
45 changed files with 1228 additions and 378 deletions
|
@ -68,6 +68,7 @@
|
|||
"usageCollection": "src/plugins/usage_collection",
|
||||
"utils": "packages/kbn-securitysolution-utils/src",
|
||||
"visDefaultEditor": "src/plugins/vis_default_editor",
|
||||
"visTypeGauge": "src/plugins/vis_types/gauge",
|
||||
"visTypeHeatmap": "src/plugins/vis_types/heatmap",
|
||||
"visTypeMarkdown": "src/plugins/vis_type_markdown",
|
||||
"visTypeMetric": "src/plugins/vis_types/metric",
|
||||
|
|
|
@ -297,6 +297,10 @@ It acts as a container for a particular visualization and options tabs. Contains
|
|||
The plugin exposes the static DefaultEditorController class to consume.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/vis_types/gauge[visTypeGauge]
|
||||
|WARNING: Missing README.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/vis_types/heatmap[visTypeHeatmap]
|
||||
|WARNING: Missing README.
|
||||
|
||||
|
|
|
@ -121,4 +121,5 @@ pageLoadAssetSize:
|
|||
expressionPartitionVis: 26338
|
||||
sharedUX: 16225
|
||||
ux: 20784
|
||||
visTypeGauge: 24113
|
||||
cloudSecurityPosture: 19109
|
||||
|
|
|
@ -10,6 +10,7 @@ export const PLUGIN_ID = 'expressionGauge';
|
|||
export const PLUGIN_NAME = 'expressionGauge';
|
||||
|
||||
export type {
|
||||
GaugeExpressionFunctionDefinition,
|
||||
GaugeExpressionProps,
|
||||
FormatFactory,
|
||||
GaugeRenderProps,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { Chart, Goal, Settings } from '@elastic/charts';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import type { CustomPaletteState } from '../../../../charts/public';
|
||||
import { EmptyPlaceholder } from '../../../../charts/public';
|
||||
import { isVisDimension } from '../../../../visualizations/common/utils';
|
||||
import {
|
||||
GaugeRenderProps,
|
||||
GaugeLabelMajorMode,
|
||||
|
@ -234,17 +235,22 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const tickFormatter = formatFactory(
|
||||
metricColumn?.meta?.params?.params
|
||||
const customMetricFormatParams = isVisDimension(args.metric) ? args.metric.format : undefined;
|
||||
const tableMetricFormatParams = metricColumn?.meta?.params?.params
|
||||
? metricColumn?.meta?.params
|
||||
: {
|
||||
: undefined;
|
||||
|
||||
const defaultMetricFormatParams = {
|
||||
id: 'number',
|
||||
params: {
|
||||
pattern: max - min > 5 ? `0,0` : `0,0.0`,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const tickFormatter = formatFactory(
|
||||
customMetricFormatParams ?? tableMetricFormatParams ?? defaultMetricFormatParams
|
||||
);
|
||||
|
||||
const colors = palette?.params?.colors ? normalizeColors(palette.params, min, max) : undefined;
|
||||
const bands: number[] = (palette?.params as CustomPaletteState)
|
||||
? normalizeBands(args.palette?.params as CustomPaletteState, { min, max })
|
||||
|
|
9
src/plugins/vis_types/gauge/common/index.ts
Executable file
9
src/plugins/vis_types/gauge/common/index.ts
Executable file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const LEGACY_GAUGE_CHARTS_LIBRARY = 'visualization:visualize:legacyGaugeChartsLibrary';
|
|
@ -6,13 +6,10 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { VisTypeDefinition } from 'src/plugins/visualizations/public';
|
||||
import { gaugeVisTypeDefinition } from './gauge';
|
||||
import { goalVisTypeDefinition } from './goal';
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
|
||||
export { pieVisTypeDefinition } from './pie';
|
||||
export const configSchema = schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
});
|
||||
|
||||
export const visLibVisTypeDefinitions: Array<VisTypeDefinition<any>> = [
|
||||
gaugeVisTypeDefinition,
|
||||
goalVisTypeDefinition,
|
||||
];
|
||||
export type ConfigSchema = TypeOf<typeof configSchema>;
|
18
src/plugins/vis_types/gauge/jest.config.js
Normal file
18
src/plugins/vis_types/gauge/jest.config.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../../..',
|
||||
roots: ['<rootDir>/src/plugins/vis_types/gauge'],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/vis_types/gauge',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: [
|
||||
'<rootDir>/src/plugins/vis_types/gauge/{common,public,server}/**/*.{ts,tsx}',
|
||||
],
|
||||
};
|
16
src/plugins/vis_types/gauge/kibana.json
Executable file
16
src/plugins/vis_types/gauge/kibana.json
Executable file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"id": "visTypeGauge",
|
||||
"version": "1.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
|
||||
"requiredBundles": ["visDefaultEditor"],
|
||||
"optionalPlugins": ["expressionGauge"],
|
||||
"extraPublicDirs": ["common/index"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
},
|
||||
"description": "Contains the gauge chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting."
|
||||
}
|
63
src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap
generated
Normal file
63
src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap
generated
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`gauge vis toExpressionAst function with minimal params 1`] = `
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"aggs": Array [],
|
||||
"index": Array [
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"id": Array [
|
||||
"123",
|
||||
],
|
||||
},
|
||||
"function": "indexPatternLoad",
|
||||
"type": "function",
|
||||
},
|
||||
],
|
||||
"type": "expression",
|
||||
},
|
||||
],
|
||||
"metricsAtAllLevels": Array [
|
||||
false,
|
||||
],
|
||||
"partialRows": Array [
|
||||
false,
|
||||
],
|
||||
},
|
||||
"function": "esaggs",
|
||||
"type": "function",
|
||||
},
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"centralMajorMode": Array [
|
||||
"custom",
|
||||
],
|
||||
"colorMode": Array [
|
||||
"palette",
|
||||
],
|
||||
"labelMajorMode": Array [
|
||||
"auto",
|
||||
],
|
||||
"labelMinor": Array [
|
||||
"some custom sublabel",
|
||||
],
|
||||
"metric": Array [],
|
||||
"shape": Array [
|
||||
"circle",
|
||||
],
|
||||
"ticksPosition": Array [
|
||||
"hidden",
|
||||
],
|
||||
},
|
||||
"function": "gauge",
|
||||
"type": "function",
|
||||
},
|
||||
],
|
||||
"type": "expression",
|
||||
}
|
||||
`;
|
|
@ -7,21 +7,18 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { colorSchemas } from '../../../../charts/public';
|
||||
import { getPositions, getScaleTypes } from '../../../xy/public';
|
||||
|
||||
import { Alignment, GaugeType } from '../types';
|
||||
|
||||
export const getGaugeTypes = () => [
|
||||
{
|
||||
text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', {
|
||||
text: i18n.translate('visTypeGauge.gauge.gaugeTypes.arcText', {
|
||||
defaultMessage: 'Arc',
|
||||
}),
|
||||
value: GaugeType.Arc,
|
||||
},
|
||||
{
|
||||
text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', {
|
||||
text: i18n.translate('visTypeGauge.gauge.gaugeTypes.circleText', {
|
||||
defaultMessage: 'Circle',
|
||||
}),
|
||||
value: GaugeType.Circle,
|
||||
|
@ -30,19 +27,19 @@ export const getGaugeTypes = () => [
|
|||
|
||||
export const getAlignments = () => [
|
||||
{
|
||||
text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', {
|
||||
text: i18n.translate('visTypeGauge.gauge.alignmentAutomaticTitle', {
|
||||
defaultMessage: 'Automatic',
|
||||
}),
|
||||
value: Alignment.Automatic,
|
||||
},
|
||||
{
|
||||
text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', {
|
||||
text: i18n.translate('visTypeGauge.gauge.alignmentHorizontalTitle', {
|
||||
defaultMessage: 'Horizontal',
|
||||
}),
|
||||
value: Alignment.Horizontal,
|
||||
},
|
||||
{
|
||||
text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', {
|
||||
text: i18n.translate('visTypeGauge.gauge.alignmentVerticalTitle', {
|
||||
defaultMessage: 'Vertical',
|
||||
}),
|
||||
value: Alignment.Vertical,
|
||||
|
@ -54,9 +51,3 @@ export const getGaugeCollections = () => ({
|
|||
alignments: getAlignments(),
|
||||
colorSchemas,
|
||||
});
|
||||
|
||||
export const getHeatmapCollections = () => ({
|
||||
legendPositions: getPositions(),
|
||||
scales: getScaleTypes(),
|
||||
colorSchemas,
|
||||
});
|
|
@ -10,19 +10,21 @@ import React, { useCallback } from 'react';
|
|||
import { EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import { VisEditorOptionsProps } from 'src/plugins/visualizations/public';
|
||||
import { GaugeVisParams } from '../../../gauge';
|
||||
import { GaugeTypeProps, GaugeVisParams } from '../../../types';
|
||||
import { RangesPanel } from './ranges_panel';
|
||||
import { StylePanel } from './style_panel';
|
||||
import { LabelsPanel } from './labels_panel';
|
||||
|
||||
export type GaugeOptionsInternalProps = VisEditorOptionsProps<GaugeVisParams> & {
|
||||
export interface GaugeOptionsProps extends VisEditorOptionsProps<GaugeVisParams>, GaugeTypeProps {}
|
||||
|
||||
export type GaugeOptionsInternalProps = GaugeOptionsProps & {
|
||||
setGaugeValue: <T extends keyof GaugeVisParams['gauge']>(
|
||||
paramName: T,
|
||||
value: GaugeVisParams['gauge'][T]
|
||||
) => void;
|
||||
};
|
||||
|
||||
function GaugeOptions(props: VisEditorOptionsProps<GaugeVisParams>) {
|
||||
function GaugeOptions(props: GaugeOptionsProps) {
|
||||
const { stateParams, setValue } = props;
|
||||
|
||||
const setGaugeValue: GaugeOptionsInternalProps['setGaugeValue'] = useCallback(
|
||||
|
@ -37,13 +39,9 @@ function GaugeOptions(props: VisEditorOptionsProps<GaugeVisParams>) {
|
|||
return (
|
||||
<>
|
||||
<StylePanel {...props} setGaugeValue={setGaugeValue} />
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<RangesPanel {...props} setGaugeValue={setGaugeValue} />
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<LabelsPanel {...props} setGaugeValue={setGaugeValue} />
|
||||
</>
|
||||
);
|
|
@ -19,7 +19,7 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter
|
|||
<EuiTitle size="xs">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="visTypeVislib.controls.gaugeOptions.labelsTitle"
|
||||
id="visTypeGauge.controls.gaugeOptions.labelsTitle"
|
||||
defaultMessage="Labels"
|
||||
/>
|
||||
</h3>
|
||||
|
@ -27,7 +27,7 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter
|
|||
<EuiSpacer size="s" />
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.showLabelsLabel', {
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.showLabelsLabel', {
|
||||
defaultMessage: 'Show labels',
|
||||
})}
|
||||
paramName="show"
|
||||
|
@ -40,7 +40,7 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter
|
|||
|
||||
<TextInputOption
|
||||
disabled={!stateParams.gauge.labels.show}
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.subTextLabel', {
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.subTextLabel', {
|
||||
defaultMessage: 'Sub label',
|
||||
})}
|
||||
paramName="subText"
|
|
@ -19,9 +19,10 @@ import {
|
|||
} from '../../../../../../vis_default_editor/public';
|
||||
import { ColorSchemaParams, ColorSchemas, colorSchemas } from '../../../../../../charts/public';
|
||||
import { GaugeOptionsInternalProps } from '../gauge';
|
||||
import { Gauge } from '../../../gauge';
|
||||
import { Gauge } from '../../../types';
|
||||
|
||||
function RangesPanel({
|
||||
showElasticChartsOptions,
|
||||
setGaugeValue,
|
||||
setTouched,
|
||||
setValidity,
|
||||
|
@ -50,7 +51,7 @@ function RangesPanel({
|
|||
<EuiTitle size="xs">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="visTypeVislib.controls.gaugeOptions.rangesTitle"
|
||||
id="visTypeGauge.controls.gaugeOptions.rangesTitle"
|
||||
defaultMessage="Ranges"
|
||||
/>
|
||||
</h3>
|
||||
|
@ -66,13 +67,20 @@ function RangesPanel({
|
|||
/>
|
||||
|
||||
<SwitchOption
|
||||
disabled={stateParams.gauge.colorsRange.length < 2}
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel', {
|
||||
disabled={showElasticChartsOptions || stateParams.gauge.colorsRange.length < 2}
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.autoExtendRangeLabel', {
|
||||
defaultMessage: 'Auto extend range',
|
||||
})}
|
||||
tooltip={i18n.translate('visTypeVislib.controls.gaugeOptions.extendRangeTooltip', {
|
||||
tooltip={
|
||||
showElasticChartsOptions
|
||||
? i18n.translate('visTypeGauge.controls.gaugeOptions.extendRangeTooltipNotAvailable', {
|
||||
defaultMessage:
|
||||
'The new charts library supports only extended ranges. To disable it, please, enable the gauge legacy charts library advanced setting.',
|
||||
})
|
||||
: i18n.translate('visTypeGauge.controls.gaugeOptions.extendRangeTooltip', {
|
||||
defaultMessage: 'Extends range to the maximum value in your data.',
|
||||
})}
|
||||
})
|
||||
}
|
||||
paramName="extendRange"
|
||||
value={stateParams.gauge.extendRange}
|
||||
setValue={setGaugeValue}
|
||||
|
@ -95,25 +103,46 @@ function RangesPanel({
|
|||
/>
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.showOutline', {
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.showOutline', {
|
||||
defaultMessage: 'Show outline',
|
||||
})}
|
||||
paramName="outline"
|
||||
value={stateParams.gauge.outline}
|
||||
setValue={setGaugeValue}
|
||||
disabled={showElasticChartsOptions}
|
||||
{...(showElasticChartsOptions
|
||||
? {
|
||||
tooltip: i18n.translate(
|
||||
'visTypeGauge.controls.gaugeOptions.showOutlineNotAvailable',
|
||||
{
|
||||
defaultMessage:
|
||||
'The outline is not supported with the new charts library. Please, enable the gauge legacy charts library advanced setting.',
|
||||
}
|
||||
),
|
||||
}
|
||||
: {})}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.showLegendLabel', {
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.showLegendLabel', {
|
||||
defaultMessage: 'Show legend',
|
||||
})}
|
||||
paramName="addLegend"
|
||||
value={stateParams.addLegend}
|
||||
setValue={setValue}
|
||||
disabled={showElasticChartsOptions}
|
||||
{...(showElasticChartsOptions
|
||||
? {
|
||||
tooltip: i18n.translate('visTypeGauge.controls.gaugeOptions.showLegendNotAvailable', {
|
||||
defaultMessage:
|
||||
'The legend is not supported with the new charts library. Please, enable the gauge legacy charts library advanced setting.',
|
||||
}),
|
||||
}
|
||||
: {})}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.showScaleLabel', {
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.showScaleLabel', {
|
||||
defaultMessage: 'Show scale',
|
||||
})}
|
||||
paramName="show"
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import { EuiPanel, EuiSpacer, EuiTitle, EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
|
@ -18,35 +18,19 @@ import { getGaugeCollections } from './../../collections';
|
|||
|
||||
const gaugeCollections = getGaugeCollections();
|
||||
|
||||
function StylePanel({ aggs, setGaugeValue, stateParams }: GaugeOptionsInternalProps) {
|
||||
const diasableAlignment =
|
||||
function StylePanel({
|
||||
aggs,
|
||||
setGaugeValue,
|
||||
stateParams,
|
||||
showElasticChartsOptions,
|
||||
}: GaugeOptionsInternalProps) {
|
||||
const disableAlignment =
|
||||
aggs.byType(AggGroupNames.Metrics).length === 1 && !aggs.byType(AggGroupNames.Buckets);
|
||||
|
||||
return (
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="visTypeVislib.controls.gaugeOptions.styleTitle"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
const alignmentSelect = (
|
||||
<SelectOption
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.gaugeTypeLabel', {
|
||||
defaultMessage: 'Gauge type',
|
||||
})}
|
||||
options={gaugeCollections.gaugeTypes}
|
||||
paramName="gaugeType"
|
||||
value={stateParams.gauge.gaugeType}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
|
||||
<SelectOption
|
||||
disabled={diasableAlignment}
|
||||
label={i18n.translate('visTypeVislib.controls.gaugeOptions.alignmentLabel', {
|
||||
disabled={showElasticChartsOptions || disableAlignment}
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.alignmentLabel', {
|
||||
defaultMessage: 'Alignment',
|
||||
})}
|
||||
options={gaugeCollections.alignments}
|
||||
|
@ -54,6 +38,47 @@ function StylePanel({ aggs, setGaugeValue, stateParams }: GaugeOptionsInternalPr
|
|||
value={stateParams.gauge.alignment}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="visTypeGauge.controls.gaugeOptions.styleTitle"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<SelectOption
|
||||
label={i18n.translate('visTypeGauge.controls.gaugeOptions.gaugeTypeLabel', {
|
||||
defaultMessage: 'Gauge type',
|
||||
})}
|
||||
options={gaugeCollections.gaugeTypes}
|
||||
paramName="gaugeType"
|
||||
value={stateParams.gauge.gaugeType}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
{showElasticChartsOptions ? (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiToolTip
|
||||
content={i18n.translate('visTypeGauge.editors.gauge.alignmentNotAvailable', {
|
||||
defaultMessage:
|
||||
'The alignment is not yet supported with the new charts library. Please, enable the gauge legacy charts library advanced setting.',
|
||||
})}
|
||||
delay="long"
|
||||
position="right"
|
||||
>
|
||||
{alignmentSelect}
|
||||
</EuiToolTip>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
) : (
|
||||
alignmentSelect
|
||||
)}
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
|
@ -9,10 +9,11 @@
|
|||
import React, { lazy } from 'react';
|
||||
|
||||
import { VisEditorOptionsProps } from 'src/plugins/visualizations/public';
|
||||
import { GaugeVisParams } from '../../gauge';
|
||||
import { GaugeTypeProps, GaugeVisParams } from '../../types';
|
||||
|
||||
const GaugeOptionsLazy = lazy(() => import('./gauge'));
|
||||
|
||||
export const GaugeOptions = (props: VisEditorOptionsProps<GaugeVisParams>) => (
|
||||
<GaugeOptionsLazy {...props} />
|
||||
);
|
||||
export const getGaugeOptions =
|
||||
({ showElasticChartsOptions }: GaugeTypeProps) =>
|
||||
(props: VisEditorOptionsProps<GaugeVisParams>) =>
|
||||
<GaugeOptionsLazy {...props} showElasticChartsOptions={showElasticChartsOptions} />;
|
17
src/plugins/vis_types/gauge/public/index.ts
Executable file
17
src/plugins/vis_types/gauge/public/index.ts
Executable file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { VisTypeGaugePlugin } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new VisTypeGaugePlugin();
|
||||
}
|
||||
|
||||
export type { VisTypeGaugePluginSetup, VisTypeGaugePluginStart } from './types';
|
||||
|
||||
export { gaugeVisType, goalVisType } from './vis_type';
|
41
src/plugins/vis_types/gauge/public/plugin.ts
Executable file
41
src/plugins/vis_types/gauge/public/plugin.ts
Executable file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { VisualizationsSetup } from '../../../../plugins/visualizations/public';
|
||||
import { DataPublicPluginStart } from '../../../../plugins/data/public';
|
||||
import { CoreSetup } from '../../../../core/public';
|
||||
import { LEGACY_GAUGE_CHARTS_LIBRARY } from '../common';
|
||||
import { VisTypeGaugePluginSetup } from './types';
|
||||
import { gaugeVisType, goalVisType } from './vis_type';
|
||||
|
||||
/** @internal */
|
||||
export interface VisTypeGaugeSetupDependencies {
|
||||
visualizations: VisualizationsSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface VisTypePiePluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
}
|
||||
|
||||
export class VisTypeGaugePlugin {
|
||||
public setup(
|
||||
core: CoreSetup<VisTypePiePluginStartDependencies>,
|
||||
{ visualizations }: VisTypeGaugeSetupDependencies
|
||||
): VisTypeGaugePluginSetup {
|
||||
if (!core.uiSettings.get(LEGACY_GAUGE_CHARTS_LIBRARY)) {
|
||||
const visTypeProps = { showElasticChartsOptions: true };
|
||||
visualizations.createBaseVisualization(gaugeVisType(visTypeProps));
|
||||
visualizations.createBaseVisualization(goalVisType(visTypeProps));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
public start() {}
|
||||
}
|
53
src/plugins/vis_types/gauge/public/to_ast.test.ts
Normal file
53
src/plugins/vis_types/gauge/public/to_ast.test.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { TimefilterContract } from 'src/plugins/data/public';
|
||||
import { Vis } from 'src/plugins/visualizations/public';
|
||||
import { toExpressionAst } from './to_ast';
|
||||
import { GaugeVisParams } from './types';
|
||||
|
||||
describe('gauge vis toExpressionAst function', () => {
|
||||
let vis: Vis<GaugeVisParams>;
|
||||
|
||||
beforeEach(() => {
|
||||
vis = {
|
||||
isHierarchical: () => false,
|
||||
type: {},
|
||||
params: {
|
||||
gauge: {
|
||||
gaugeType: 'Circle',
|
||||
scale: {
|
||||
show: false,
|
||||
labels: false,
|
||||
color: 'rgba(105,112,125,0.2)',
|
||||
},
|
||||
labels: {
|
||||
show: true,
|
||||
},
|
||||
style: {
|
||||
subText: 'some custom sublabel',
|
||||
},
|
||||
},
|
||||
},
|
||||
data: {
|
||||
indexPattern: { id: '123' } as any,
|
||||
aggs: {
|
||||
getResponseAggs: () => [],
|
||||
aggs: [],
|
||||
} as any,
|
||||
},
|
||||
} as unknown as Vis<GaugeVisParams>;
|
||||
});
|
||||
|
||||
it('with minimal params', () => {
|
||||
const actual = toExpressionAst(vis, {
|
||||
timefilter: {} as TimefilterContract,
|
||||
});
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
93
src/plugins/vis_types/gauge/public/to_ast.ts
Normal file
93
src/plugins/vis_types/gauge/public/to_ast.ts
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '../../../visualizations/public';
|
||||
import { buildExpression, buildExpressionFunction } from '../../../expressions/public';
|
||||
import type {
|
||||
GaugeExpressionFunctionDefinition,
|
||||
GaugeShape,
|
||||
} from '../../../chart_expressions/expression_gauge/common';
|
||||
import { GaugeType, GaugeVisParams } from './types';
|
||||
import { getStopsWithColorsFromRanges } from './utils';
|
||||
import { getEsaggsFn } from './to_ast_esaggs';
|
||||
|
||||
const prepareDimension = (params: SchemaConfig) => {
|
||||
const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor });
|
||||
|
||||
if (params.format) {
|
||||
visdimension.addArgument('format', params.format.id);
|
||||
visdimension.addArgument('formatParams', JSON.stringify(params.format.params));
|
||||
}
|
||||
|
||||
return buildExpression([visdimension]);
|
||||
};
|
||||
|
||||
const gaugeTypeToShape = (type: GaugeType): GaugeShape => {
|
||||
const arc: GaugeShape = 'arc';
|
||||
const circle: GaugeShape = 'circle';
|
||||
|
||||
return {
|
||||
[GaugeType.Arc]: arc,
|
||||
[GaugeType.Circle]: circle,
|
||||
}[type];
|
||||
};
|
||||
|
||||
export const toExpressionAst: VisToExpressionAst<GaugeVisParams> = (vis, params) => {
|
||||
const schemas = getVisSchemas(vis, params);
|
||||
|
||||
const {
|
||||
gaugeType,
|
||||
percentageMode,
|
||||
percentageFormatPattern,
|
||||
colorSchema,
|
||||
colorsRange,
|
||||
invertColors,
|
||||
scale,
|
||||
style,
|
||||
labels,
|
||||
} = vis.params.gauge;
|
||||
|
||||
// fix formatter for percentage mode
|
||||
if (percentageMode === true) {
|
||||
schemas.metric.forEach((metric: SchemaConfig) => {
|
||||
metric.format = {
|
||||
id: 'percent',
|
||||
params: { pattern: percentageFormatPattern },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const centralMajorMode = labels.show ? (style.subText ? 'custom' : 'auto') : 'none';
|
||||
const gauge = buildExpressionFunction<GaugeExpressionFunctionDefinition>('gauge', {
|
||||
shape: gaugeTypeToShape(gaugeType),
|
||||
metric: schemas.metric.map(prepareDimension),
|
||||
ticksPosition: scale.show ? 'auto' : 'hidden',
|
||||
labelMajorMode: 'auto',
|
||||
colorMode: 'palette',
|
||||
centralMajorMode,
|
||||
...(centralMajorMode === 'custom' ? { labelMinor: style.subText } : {}),
|
||||
});
|
||||
|
||||
if (colorsRange && colorsRange.length) {
|
||||
const stopsWithColors = getStopsWithColorsFromRanges(colorsRange, colorSchema, invertColors);
|
||||
const palette = buildExpressionFunction('palette', {
|
||||
...stopsWithColors,
|
||||
range: percentageMode ? 'percent' : 'number',
|
||||
continuity: 'none',
|
||||
gradient: true,
|
||||
rangeMax: percentageMode ? 100 : Infinity,
|
||||
rangeMin: 0,
|
||||
});
|
||||
|
||||
gauge.addArgument('palette', buildExpression([palette]));
|
||||
}
|
||||
|
||||
const ast = buildExpression([getEsaggsFn(vis), gauge]);
|
||||
|
||||
return ast.toAst();
|
||||
};
|
33
src/plugins/vis_types/gauge/public/to_ast_esaggs.ts
Normal file
33
src/plugins/vis_types/gauge/public/to_ast_esaggs.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Vis } from '../../../visualizations/public';
|
||||
import { buildExpression, buildExpressionFunction } from '../../../expressions/public';
|
||||
import {
|
||||
EsaggsExpressionFunctionDefinition,
|
||||
IndexPatternLoadExpressionFunctionDefinition,
|
||||
} from '../../../data/public';
|
||||
|
||||
import { GaugeVisParams } from './types';
|
||||
|
||||
/**
|
||||
* Get esaggs expressions function
|
||||
* @param vis
|
||||
*/
|
||||
export function getEsaggsFn(vis: Vis<GaugeVisParams>) {
|
||||
return buildExpressionFunction<EsaggsExpressionFunctionDefinition>('esaggs', {
|
||||
index: buildExpression([
|
||||
buildExpressionFunction<IndexPatternLoadExpressionFunctionDefinition>('indexPatternLoad', {
|
||||
id: vis.data.indexPattern!.id!,
|
||||
}),
|
||||
]),
|
||||
metricsAtAllLevels: vis.isHierarchical(),
|
||||
partialRows: false,
|
||||
aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())),
|
||||
});
|
||||
}
|
68
src/plugins/vis_types/gauge/public/types.ts
Executable file
68
src/plugins/vis_types/gauge/public/types.ts
Executable file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { $Values } from '@kbn/utility-types';
|
||||
import { Range } from '../../../expressions/public';
|
||||
import { ColorSchemaParams, Labels, Style } from '../../../charts/public';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface VisTypeGaugePluginSetup {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface VisTypeGaugePluginStart {}
|
||||
|
||||
/**
|
||||
* Gauge title alignment
|
||||
*/
|
||||
export const Alignment = {
|
||||
Automatic: 'automatic',
|
||||
Horizontal: 'horizontal',
|
||||
Vertical: 'vertical',
|
||||
} as const;
|
||||
|
||||
export type Alignment = $Values<typeof Alignment>;
|
||||
|
||||
export const GaugeType = {
|
||||
Arc: 'Arc',
|
||||
Circle: 'Circle',
|
||||
} as const;
|
||||
|
||||
export type GaugeType = $Values<typeof GaugeType>;
|
||||
|
||||
export interface Gauge extends ColorSchemaParams {
|
||||
backStyle: 'Full';
|
||||
gaugeStyle: 'Full';
|
||||
orientation: 'vertical';
|
||||
type: 'meter';
|
||||
alignment: Alignment;
|
||||
colorsRange: Range[];
|
||||
extendRange: boolean;
|
||||
gaugeType: GaugeType;
|
||||
labels: Labels;
|
||||
percentageMode: boolean;
|
||||
percentageFormatPattern?: string;
|
||||
outline?: boolean;
|
||||
scale: {
|
||||
show: boolean;
|
||||
labels: false;
|
||||
color: 'rgba(105,112,125,0.2)';
|
||||
};
|
||||
style: Style;
|
||||
}
|
||||
|
||||
export interface GaugeVisParams {
|
||||
type: 'gauge';
|
||||
addTooltip: boolean;
|
||||
addLegend: boolean;
|
||||
isDisplayWarning: boolean;
|
||||
gauge: Gauge;
|
||||
}
|
||||
|
||||
export interface GaugeTypeProps {
|
||||
showElasticChartsOptions?: boolean;
|
||||
}
|
9
src/plugins/vis_types/gauge/public/utils/index.ts
Normal file
9
src/plugins/vis_types/gauge/public/utils/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { getStopsWithColorsFromRanges } from './palette';
|
49
src/plugins/vis_types/gauge/public/utils/palette.ts
Normal file
49
src/plugins/vis_types/gauge/public/utils/palette.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ColorSchemas, getHeatmapColors } from '../../../../charts/common';
|
||||
import { Range } from '../../../../expressions';
|
||||
|
||||
export interface PaletteConfig {
|
||||
color: Array<string | undefined>;
|
||||
stop: number[];
|
||||
}
|
||||
|
||||
const TRANSPARENT = 'rgb(0, 0, 0, 0)';
|
||||
|
||||
const getColor = (
|
||||
index: number,
|
||||
elementsCount: number,
|
||||
colorSchema: ColorSchemas,
|
||||
invertColors: boolean = false
|
||||
) => {
|
||||
const divider = Math.max(elementsCount - 1, 1);
|
||||
const value = invertColors ? 1 - index / divider : index / divider;
|
||||
return getHeatmapColors(value, colorSchema);
|
||||
};
|
||||
|
||||
export const getStopsWithColorsFromRanges = (
|
||||
ranges: Range[],
|
||||
colorSchema: ColorSchemas,
|
||||
invertColors: boolean = false
|
||||
) => {
|
||||
return ranges.reduce<PaletteConfig>(
|
||||
(acc, range, index, rangesArr) => {
|
||||
if (index && range.from !== rangesArr[index - 1].to) {
|
||||
acc.color.push(TRANSPARENT);
|
||||
acc.stop.push(range.from);
|
||||
}
|
||||
|
||||
acc.color.push(getColor(index, rangesArr.length, colorSchema, invertColors));
|
||||
acc.stop.push(range.to);
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ color: [], stop: [] }
|
||||
);
|
||||
};
|
130
src/plugins/vis_types/gauge/public/vis_type/gauge.tsx
Normal file
130
src/plugins/vis_types/gauge/public/vis_type/gauge.tsx
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { ColorMode, ColorSchemas } from '../../../../charts/public';
|
||||
import { AggGroupNames } from '../../../../data/public';
|
||||
import { VisTypeDefinition, VIS_EVENT_TO_TRIGGER } from '../../../../visualizations/public';
|
||||
|
||||
import { Alignment, GaugeType, GaugeTypeProps } from '../types';
|
||||
import { toExpressionAst } from '../to_ast';
|
||||
import { getGaugeOptions } from '../editor/components';
|
||||
import { GaugeVisParams } from '../types';
|
||||
import { SplitTooltip } from './split_tooltip';
|
||||
|
||||
export const getGaugeVisTypeDefinition = (
|
||||
props: GaugeTypeProps
|
||||
): VisTypeDefinition<GaugeVisParams> => ({
|
||||
name: 'gauge',
|
||||
title: i18n.translate('visTypeGauge.gauge.gaugeTitle', { defaultMessage: 'Gauge' }),
|
||||
icon: 'visGauge',
|
||||
description: i18n.translate('visTypeGauge.gauge.gaugeDescription', {
|
||||
defaultMessage: 'Show the status of a metric.',
|
||||
}),
|
||||
getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter],
|
||||
toExpressionAst,
|
||||
visConfig: {
|
||||
defaults: {
|
||||
type: 'gauge',
|
||||
addTooltip: true,
|
||||
addLegend: true,
|
||||
isDisplayWarning: false,
|
||||
gauge: {
|
||||
alignment: Alignment.Automatic,
|
||||
extendRange: true,
|
||||
percentageMode: false,
|
||||
gaugeType: GaugeType.Arc,
|
||||
gaugeStyle: 'Full',
|
||||
backStyle: 'Full',
|
||||
orientation: 'vertical',
|
||||
colorSchema: ColorSchemas.GreenToRed,
|
||||
gaugeColorMode: ColorMode.Labels,
|
||||
colorsRange: [
|
||||
{ from: 0, to: 50 },
|
||||
{ from: 50, to: 75 },
|
||||
{ from: 75, to: 100 },
|
||||
],
|
||||
invertColors: false,
|
||||
labels: {
|
||||
show: true,
|
||||
color: 'black',
|
||||
},
|
||||
scale: {
|
||||
show: true,
|
||||
labels: false,
|
||||
color: 'rgba(105,112,125,0.2)',
|
||||
},
|
||||
type: 'meter',
|
||||
style: {
|
||||
bgWidth: 0.9,
|
||||
width: 0.9,
|
||||
mask: false,
|
||||
bgMask: false,
|
||||
maskBars: 50,
|
||||
bgFill: 'rgba(105,112,125,0.2)',
|
||||
bgColor: true,
|
||||
subText: '',
|
||||
fontSize: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
optionsTemplate: getGaugeOptions(props),
|
||||
schemas: [
|
||||
{
|
||||
group: AggGroupNames.Metrics,
|
||||
name: 'metric',
|
||||
title: i18n.translate('visTypeGauge.gauge.metricTitle', { defaultMessage: 'Metric' }),
|
||||
min: 1,
|
||||
...(props.showElasticChartsOptions ? { max: 1 } : {}),
|
||||
aggFilter: [
|
||||
'!std_dev',
|
||||
'!geo_centroid',
|
||||
'!percentiles',
|
||||
'!percentile_ranks',
|
||||
'!derivative',
|
||||
'!serial_diff',
|
||||
'!moving_avg',
|
||||
'!cumulative_sum',
|
||||
'!geo_bounds',
|
||||
'!filtered_metric',
|
||||
'!single_percentile',
|
||||
],
|
||||
defaults: [{ schema: 'metric', type: 'count' }],
|
||||
},
|
||||
{
|
||||
group: AggGroupNames.Buckets,
|
||||
name: 'group',
|
||||
// TODO: Remove when split chart aggs are supported
|
||||
...(props.showElasticChartsOptions && {
|
||||
disabled: true,
|
||||
tooltip: <SplitTooltip />,
|
||||
}),
|
||||
title: i18n.translate('visTypeGauge.gauge.groupTitle', {
|
||||
defaultMessage: 'Split group',
|
||||
}),
|
||||
min: 0,
|
||||
max: 1,
|
||||
aggFilter: [
|
||||
'!geohash_grid',
|
||||
'!geotile_grid',
|
||||
'!filter',
|
||||
'!sampler',
|
||||
'!diversified_sampler',
|
||||
'!rare_terms',
|
||||
'!multi_terms',
|
||||
'!significant_text',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
requiresSearch: true,
|
||||
});
|
122
src/plugins/vis_types/gauge/public/vis_type/goal.tsx
Normal file
122
src/plugins/vis_types/gauge/public/vis_type/goal.tsx
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { AggGroupNames } from '../../../../data/public';
|
||||
import { ColorMode, ColorSchemas } from '../../../../charts/public';
|
||||
import { VisTypeDefinition } from '../../../../visualizations/public';
|
||||
|
||||
import { getGaugeOptions } from '../editor/components';
|
||||
import { toExpressionAst } from '../to_ast';
|
||||
import { GaugeVisParams, GaugeType, GaugeTypeProps } from '../types';
|
||||
import { SplitTooltip } from './split_tooltip';
|
||||
|
||||
export const getGoalVisTypeDefinition = (
|
||||
props: GaugeTypeProps
|
||||
): VisTypeDefinition<GaugeVisParams> => ({
|
||||
name: 'goal',
|
||||
title: i18n.translate('visTypeGauge.goal.goalTitle', { defaultMessage: 'Goal' }),
|
||||
icon: 'visGoal',
|
||||
description: i18n.translate('visTypeGauge.goal.goalDescription', {
|
||||
defaultMessage: 'Track how a metric progresses to a goal.',
|
||||
}),
|
||||
toExpressionAst,
|
||||
visConfig: {
|
||||
defaults: {
|
||||
addTooltip: true,
|
||||
addLegend: false,
|
||||
isDisplayWarning: false,
|
||||
type: 'gauge',
|
||||
gauge: {
|
||||
verticalSplit: false,
|
||||
autoExtend: false,
|
||||
percentageMode: true,
|
||||
gaugeType: GaugeType.Arc,
|
||||
gaugeStyle: 'Full',
|
||||
backStyle: 'Full',
|
||||
orientation: 'vertical',
|
||||
useRanges: false,
|
||||
colorSchema: ColorSchemas.GreenToRed,
|
||||
gaugeColorMode: ColorMode.None,
|
||||
colorsRange: [{ from: 0, to: 10000 }],
|
||||
invertColors: false,
|
||||
labels: {
|
||||
show: true,
|
||||
color: 'black',
|
||||
},
|
||||
scale: {
|
||||
show: false,
|
||||
labels: false,
|
||||
color: 'rgba(105,112,125,0.2)',
|
||||
width: 2,
|
||||
},
|
||||
type: 'meter',
|
||||
style: {
|
||||
bgFill: 'rgba(105,112,125,0.2)',
|
||||
bgColor: false,
|
||||
labelColor: false,
|
||||
subText: '',
|
||||
fontSize: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
optionsTemplate: getGaugeOptions(props),
|
||||
schemas: [
|
||||
{
|
||||
group: AggGroupNames.Metrics,
|
||||
name: 'metric',
|
||||
title: i18n.translate('visTypeGauge.goal.metricTitle', { defaultMessage: 'Metric' }),
|
||||
min: 1,
|
||||
...(props.showElasticChartsOptions ? { max: 1 } : {}),
|
||||
aggFilter: [
|
||||
'!std_dev',
|
||||
'!geo_centroid',
|
||||
'!percentiles',
|
||||
'!percentile_ranks',
|
||||
'!derivative',
|
||||
'!serial_diff',
|
||||
'!moving_avg',
|
||||
'!cumulative_sum',
|
||||
'!geo_bounds',
|
||||
'!filtered_metric',
|
||||
'!single_percentile',
|
||||
],
|
||||
defaults: [{ schema: 'metric', type: 'count' }],
|
||||
},
|
||||
{
|
||||
group: AggGroupNames.Buckets,
|
||||
name: 'group',
|
||||
// TODO: Remove when split chart aggs are supported
|
||||
...(props.showElasticChartsOptions && {
|
||||
disabled: true,
|
||||
tooltip: <SplitTooltip />,
|
||||
}),
|
||||
title: i18n.translate('visTypeGauge.goal.groupTitle', {
|
||||
defaultMessage: 'Split group',
|
||||
}),
|
||||
min: 0,
|
||||
max: 1,
|
||||
aggFilter: [
|
||||
'!geohash_grid',
|
||||
'!geotile_grid',
|
||||
'!filter',
|
||||
'!sampler',
|
||||
'!diversified_sampler',
|
||||
'!rare_terms',
|
||||
'!multi_terms',
|
||||
'!significant_text',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
requiresSearch: true,
|
||||
});
|
19
src/plugins/vis_types/gauge/public/vis_type/index.ts
Normal file
19
src/plugins/vis_types/gauge/public/vis_type/index.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { GaugeTypeProps } from '../types';
|
||||
import { getGaugeVisTypeDefinition } from './gauge';
|
||||
import { getGoalVisTypeDefinition } from './goal';
|
||||
|
||||
export const gaugeVisType = (props: GaugeTypeProps) => {
|
||||
return getGaugeVisTypeDefinition(props);
|
||||
};
|
||||
|
||||
export const goalVisType = (props: GaugeTypeProps) => {
|
||||
return getGoalVisTypeDefinition(props);
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import React from 'react';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
export function SplitTooltip() {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="visTypeGauge.splitTitle.tooltip"
|
||||
defaultMessage="Split chart aggregation is not yet supported with the new charts library. Please, enable the gauge legacy charts library advanced setting to use split chart aggregation."
|
||||
/>
|
||||
);
|
||||
}
|
17
src/plugins/vis_types/gauge/server/index.ts
Executable file
17
src/plugins/vis_types/gauge/server/index.ts
Executable file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginConfigDescriptor } from 'src/core/server';
|
||||
import { configSchema, ConfigSchema } from '../config';
|
||||
import { VisTypeGaugeServerPlugin } from './plugin';
|
||||
|
||||
export const config: PluginConfigDescriptor<ConfigSchema> = {
|
||||
schema: configSchema,
|
||||
};
|
||||
|
||||
export const plugin = () => new VisTypeGaugeServerPlugin();
|
47
src/plugins/vis_types/gauge/server/plugin.ts
Executable file
47
src/plugins/vis_types/gauge/server/plugin.ts
Executable file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { CoreSetup, Plugin, UiSettingsParams } from 'kibana/server';
|
||||
|
||||
import { LEGACY_GAUGE_CHARTS_LIBRARY } from '../common';
|
||||
|
||||
export const getUiSettingsConfig: () => Record<string, UiSettingsParams<boolean>> = () => ({
|
||||
[LEGACY_GAUGE_CHARTS_LIBRARY]: {
|
||||
name: i18n.translate(
|
||||
'visTypeGauge.advancedSettings.visualization.legacyGaugeChartsLibrary.name',
|
||||
{
|
||||
defaultMessage: 'Gauge legacy charts library',
|
||||
}
|
||||
),
|
||||
requiresPageReload: true,
|
||||
value: true,
|
||||
description: i18n.translate(
|
||||
'visTypeGauge.advancedSettings.visualization.legacyGaugeChartsLibrary.description',
|
||||
{
|
||||
defaultMessage: 'Enables legacy charts library for gauge charts in visualize.',
|
||||
}
|
||||
),
|
||||
category: ['visualization'],
|
||||
schema: schema.boolean(),
|
||||
},
|
||||
});
|
||||
|
||||
export class VisTypeGaugeServerPlugin implements Plugin<object, object> {
|
||||
public setup(core: CoreSetup) {
|
||||
core.uiSettings.register(getUiSettingsConfig());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
public start() {
|
||||
return {};
|
||||
}
|
||||
}
|
27
src/plugins/vis_types/gauge/tsconfig.json
Normal file
27
src/plugins/vis_types/gauge/tsconfig.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target/types",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": [
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*",
|
||||
"*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
{ "path": "../../data/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../chart_expressions/expression_gauge/tsconfig.json" },
|
||||
{ "path": "../../visualizations/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../vis_default_editor/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
{ "path": "../../chart_expressions/expression_partition_vis/tsconfig.json" }
|
||||
]
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
|
||||
"requiredBundles": ["kibanaUtils", "visDefaultEditor", "visTypeXy", "visTypePie", "visTypeHeatmap", "fieldFormats", "kibanaReact"],
|
||||
"requiredBundles": ["kibanaUtils", "visTypeXy", "visTypePie", "visTypeHeatmap", "visTypeGauge", "fieldFormats", "kibanaReact"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
|
|
|
@ -6,16 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { ColorMode, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../../charts/public';
|
||||
import { ColorSchemaParams, Labels, Style } from '../../../charts/public';
|
||||
import { RangeValues } from '../../../vis_default_editor/public';
|
||||
import { AggGroupNames } from '../../../data/public';
|
||||
import { VisTypeDefinition, VIS_EVENT_TO_TRIGGER } from '../../../visualizations/public';
|
||||
import { gaugeVisType } from '../../gauge/public';
|
||||
import { VisTypeDefinition } from '../../../visualizations/public';
|
||||
|
||||
import { Alignment, GaugeType, VislibChartType } from './types';
|
||||
import { Alignment, GaugeType } from './types';
|
||||
import { toExpressionAst } from './to_ast';
|
||||
import { GaugeOptions } from './editor/components';
|
||||
|
||||
export interface Gauge extends ColorSchemaParams {
|
||||
backStyle: 'Full';
|
||||
|
@ -46,104 +43,7 @@ export interface GaugeVisParams {
|
|||
gauge: Gauge;
|
||||
}
|
||||
|
||||
export const gaugeVisTypeDefinition: VisTypeDefinition<GaugeVisParams> = {
|
||||
name: 'gauge',
|
||||
title: i18n.translate('visTypeVislib.gauge.gaugeTitle', { defaultMessage: 'Gauge' }),
|
||||
icon: 'visGauge',
|
||||
description: i18n.translate('visTypeVislib.gauge.gaugeDescription', {
|
||||
defaultMessage: 'Show the status of a metric.',
|
||||
}),
|
||||
getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter],
|
||||
export const gaugeVisTypeDefinition = {
|
||||
...gaugeVisType({}),
|
||||
toExpressionAst,
|
||||
visConfig: {
|
||||
defaults: {
|
||||
type: VislibChartType.Gauge,
|
||||
addTooltip: true,
|
||||
addLegend: true,
|
||||
isDisplayWarning: false,
|
||||
gauge: {
|
||||
alignment: Alignment.Automatic,
|
||||
extendRange: true,
|
||||
percentageMode: false,
|
||||
gaugeType: GaugeType.Arc,
|
||||
gaugeStyle: 'Full',
|
||||
backStyle: 'Full',
|
||||
orientation: 'vertical',
|
||||
colorSchema: ColorSchemas.GreenToRed,
|
||||
gaugeColorMode: ColorMode.Labels,
|
||||
colorsRange: [
|
||||
{ from: 0, to: 50 },
|
||||
{ from: 50, to: 75 },
|
||||
{ from: 75, to: 100 },
|
||||
],
|
||||
invertColors: false,
|
||||
labels: {
|
||||
show: true,
|
||||
color: 'black',
|
||||
},
|
||||
scale: {
|
||||
show: true,
|
||||
labels: false,
|
||||
color: 'rgba(105,112,125,0.2)',
|
||||
},
|
||||
type: 'meter',
|
||||
style: {
|
||||
bgWidth: 0.9,
|
||||
width: 0.9,
|
||||
mask: false,
|
||||
bgMask: false,
|
||||
maskBars: 50,
|
||||
bgFill: 'rgba(105,112,125,0.2)',
|
||||
bgColor: true,
|
||||
subText: '',
|
||||
fontSize: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
optionsTemplate: GaugeOptions,
|
||||
schemas: [
|
||||
{
|
||||
group: AggGroupNames.Metrics,
|
||||
name: 'metric',
|
||||
title: i18n.translate('visTypeVislib.gauge.metricTitle', { defaultMessage: 'Metric' }),
|
||||
min: 1,
|
||||
aggFilter: [
|
||||
'!std_dev',
|
||||
'!geo_centroid',
|
||||
'!percentiles',
|
||||
'!percentile_ranks',
|
||||
'!derivative',
|
||||
'!serial_diff',
|
||||
'!moving_avg',
|
||||
'!cumulative_sum',
|
||||
'!geo_bounds',
|
||||
'!filtered_metric',
|
||||
'!single_percentile',
|
||||
],
|
||||
defaults: [{ schema: 'metric', type: 'count' }],
|
||||
},
|
||||
{
|
||||
group: AggGroupNames.Buckets,
|
||||
name: 'group',
|
||||
title: i18n.translate('visTypeVislib.gauge.groupTitle', {
|
||||
defaultMessage: 'Split group',
|
||||
}),
|
||||
min: 0,
|
||||
max: 1,
|
||||
aggFilter: [
|
||||
'!geohash_grid',
|
||||
'!geotile_grid',
|
||||
'!filter',
|
||||
'!sampler',
|
||||
'!diversified_sampler',
|
||||
'!rare_terms',
|
||||
'!multi_terms',
|
||||
'!significant_text',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
requiresSearch: true,
|
||||
};
|
||||
} as VisTypeDefinition<GaugeVisParams>;
|
||||
|
|
|
@ -6,108 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { AggGroupNames } from '../../../data/public';
|
||||
import { ColorMode, ColorSchemas } from '../../../charts/public';
|
||||
import { VisTypeDefinition } from '../../../visualizations/public';
|
||||
import { goalVisType } from '../../gauge/public';
|
||||
|
||||
import { GaugeOptions } from './editor';
|
||||
import { toExpressionAst } from './to_ast';
|
||||
import { GaugeType } from './types';
|
||||
import { GaugeVisParams } from './gauge';
|
||||
|
||||
export const goalVisTypeDefinition: VisTypeDefinition<GaugeVisParams> = {
|
||||
name: 'goal',
|
||||
title: i18n.translate('visTypeVislib.goal.goalTitle', { defaultMessage: 'Goal' }),
|
||||
icon: 'visGoal',
|
||||
description: i18n.translate('visTypeVislib.goal.goalDescription', {
|
||||
defaultMessage: 'Track how a metric progresses to a goal.',
|
||||
}),
|
||||
export const goalVisTypeDefinition = {
|
||||
...goalVisType({}),
|
||||
toExpressionAst,
|
||||
visConfig: {
|
||||
defaults: {
|
||||
addTooltip: true,
|
||||
addLegend: false,
|
||||
isDisplayWarning: false,
|
||||
type: 'gauge',
|
||||
gauge: {
|
||||
verticalSplit: false,
|
||||
autoExtend: false,
|
||||
percentageMode: true,
|
||||
gaugeType: GaugeType.Arc,
|
||||
gaugeStyle: 'Full',
|
||||
backStyle: 'Full',
|
||||
orientation: 'vertical',
|
||||
useRanges: false,
|
||||
colorSchema: ColorSchemas.GreenToRed,
|
||||
gaugeColorMode: ColorMode.None,
|
||||
colorsRange: [{ from: 0, to: 10000 }],
|
||||
invertColors: false,
|
||||
labels: {
|
||||
show: true,
|
||||
color: 'black',
|
||||
},
|
||||
scale: {
|
||||
show: false,
|
||||
labels: false,
|
||||
color: 'rgba(105,112,125,0.2)',
|
||||
width: 2,
|
||||
},
|
||||
type: 'meter',
|
||||
style: {
|
||||
bgFill: 'rgba(105,112,125,0.2)',
|
||||
bgColor: false,
|
||||
labelColor: false,
|
||||
subText: '',
|
||||
fontSize: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
editorConfig: {
|
||||
optionsTemplate: GaugeOptions,
|
||||
schemas: [
|
||||
{
|
||||
group: AggGroupNames.Metrics,
|
||||
name: 'metric',
|
||||
title: i18n.translate('visTypeVislib.goal.metricTitle', { defaultMessage: 'Metric' }),
|
||||
min: 1,
|
||||
aggFilter: [
|
||||
'!std_dev',
|
||||
'!geo_centroid',
|
||||
'!percentiles',
|
||||
'!percentile_ranks',
|
||||
'!derivative',
|
||||
'!serial_diff',
|
||||
'!moving_avg',
|
||||
'!cumulative_sum',
|
||||
'!geo_bounds',
|
||||
'!filtered_metric',
|
||||
'!single_percentile',
|
||||
],
|
||||
defaults: [{ schema: 'metric', type: 'count' }],
|
||||
},
|
||||
{
|
||||
group: AggGroupNames.Buckets,
|
||||
name: 'group',
|
||||
title: i18n.translate('visTypeVislib.goal.groupTitle', {
|
||||
defaultMessage: 'Split group',
|
||||
}),
|
||||
min: 0,
|
||||
max: 1,
|
||||
aggFilter: [
|
||||
'!geohash_grid',
|
||||
'!geotile_grid',
|
||||
'!filter',
|
||||
'!sampler',
|
||||
'!diversified_sampler',
|
||||
'!rare_terms',
|
||||
'!multi_terms',
|
||||
'!significant_text',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
requiresSearch: true,
|
||||
};
|
||||
} as VisTypeDefinition<GaugeVisParams>;
|
||||
|
|
|
@ -14,13 +14,16 @@ import { ChartsPluginSetup } from '../../../charts/public';
|
|||
import { DataPublicPluginStart } from '../../../data/public';
|
||||
import { LEGACY_PIE_CHARTS_LIBRARY } from '../../pie/common/index';
|
||||
import { LEGACY_HEATMAP_CHARTS_LIBRARY } from '../../heatmap/common/index';
|
||||
import { LEGACY_GAUGE_CHARTS_LIBRARY } from '../../gauge/common/index';
|
||||
import { heatmapVisTypeDefinition } from './heatmap';
|
||||
|
||||
import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn';
|
||||
import { createPieVisFn } from './pie_fn';
|
||||
import { visLibVisTypeDefinitions, pieVisTypeDefinition } from './vis_type_vislib_vis_types';
|
||||
import { pieVisTypeDefinition } from './pie';
|
||||
import { setFormatService, setDataActions, setTheme } from './services';
|
||||
import { getVislibVisRenderer } from './vis_renderer';
|
||||
import { gaugeVisTypeDefinition } from './gauge';
|
||||
import { goalVisTypeDefinition } from './goal';
|
||||
|
||||
/** @internal */
|
||||
export interface VisTypeVislibPluginSetupDependencies {
|
||||
|
@ -48,7 +51,7 @@ export class VisTypeVislibPlugin
|
|||
{ expressions, visualizations, charts }: VisTypeVislibPluginSetupDependencies
|
||||
) {
|
||||
// register vislib XY axis charts
|
||||
visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization);
|
||||
|
||||
expressions.registerRenderer(getVislibVisRenderer(core, charts));
|
||||
expressions.registerFunction(createVisTypeVislibVisFn());
|
||||
|
||||
|
@ -57,10 +60,16 @@ export class VisTypeVislibPlugin
|
|||
visualizations.createBaseVisualization(pieVisTypeDefinition);
|
||||
expressions.registerFunction(createPieVisFn());
|
||||
}
|
||||
|
||||
if (core.uiSettings.get(LEGACY_HEATMAP_CHARTS_LIBRARY)) {
|
||||
// register vislib heatmap chart
|
||||
visualizations.createBaseVisualization(heatmapVisTypeDefinition);
|
||||
expressions.registerFunction(createVisTypeVislibVisFn());
|
||||
}
|
||||
|
||||
if (core.uiSettings.get(LEGACY_GAUGE_CHARTS_LIBRARY)) {
|
||||
// register vislib gauge and goal charts
|
||||
visualizations.createBaseVisualization(gaugeVisTypeDefinition);
|
||||
visualizations.createBaseVisualization(goalVisTypeDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../visualizations/tsconfig.json" },
|
||||
{ "path": "../../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../../vis_default_editor/tsconfig.json" },
|
||||
{ "path": "../../vis_types/gauge/tsconfig.json" },
|
||||
{ "path": "../../vis_types/xy/tsconfig.json" },
|
||||
{ "path": "../../vis_types/pie/tsconfig.json" },
|
||||
{ "path": "../../vis_types/heatmap/tsconfig.json" },
|
||||
|
|
|
@ -37,7 +37,7 @@ export const getAccessorByDimension = (
|
|||
dimension: string | ExpressionValueVisDimension,
|
||||
columns: DatatableColumn[]
|
||||
) => {
|
||||
if (typeof dimension === 'string') {
|
||||
if (!isVisDimension(dimension)) {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
|
@ -48,3 +48,13 @@ export const getAccessorByDimension = (
|
|||
|
||||
return accessor.id;
|
||||
};
|
||||
|
||||
export function isVisDimension(
|
||||
accessor: string | ExpressionValueVisDimension | undefined
|
||||
): accessor is ExpressionValueVisDimension {
|
||||
if (typeof accessor === 'string' || accessor === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
|
||||
export { prepareLogTable } from './prepare_log_table';
|
||||
export type { Dimension } from './prepare_log_table';
|
||||
export { findAccessorOrFail, getAccessorByDimension } from './accessors';
|
||||
export { findAccessorOrFail, getAccessorByDimension, isVisDimension } from './accessors';
|
||||
|
|
|
@ -6,40 +6,39 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { FC } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiCallOut, EuiLink } from '@elastic/eui';
|
||||
import { useKibana } from '../../../../kibana_react/public';
|
||||
import { VisualizeServices } from '../types';
|
||||
import { CHARTS_WITHOUT_SMALL_MULTIPLES } from '../utils/split_chart_warning_helpers';
|
||||
import type { CHARTS_WITHOUT_SMALL_MULTIPLES as CHART_WITHOUT_SMALL_MULTIPLES } from '../utils/split_chart_warning_helpers';
|
||||
|
||||
export const NEW_HEATMAP_CHARTS_LIBRARY = 'visualization:visualize:legacyHeatmapChartsLibrary';
|
||||
interface Props {
|
||||
chartType: CHART_WITHOUT_SMALL_MULTIPLES;
|
||||
chartConfigToken: string;
|
||||
}
|
||||
|
||||
export const SplitChartWarning = () => {
|
||||
const { services } = useKibana<VisualizeServices>();
|
||||
const canEditAdvancedSettings = services.application.capabilities.advancedSettings.save;
|
||||
const advancedSettingsLink = services.application.getUrlForApp('management', {
|
||||
path: `/kibana/settings?query=${NEW_HEATMAP_CHARTS_LIBRARY}`,
|
||||
});
|
||||
interface WarningMessageProps {
|
||||
canEditAdvancedSettings: boolean | Readonly<{ [x: string]: boolean }>;
|
||||
advancedSettingsLink: string;
|
||||
}
|
||||
|
||||
const SwitchToOldLibraryMessage: FC<WarningMessageProps> = ({
|
||||
canEditAdvancedSettings,
|
||||
advancedSettingsLink,
|
||||
}) => {
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="vizSplitChartWarning"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="visualizations.newHeatmapChart.notificationMessage"
|
||||
defaultMessage="The new heatmap charts library does not yet support split chart aggregation. {conditionalMessage}"
|
||||
values={{
|
||||
conditionalMessage: (
|
||||
<>
|
||||
{canEditAdvancedSettings && (
|
||||
<FormattedMessage
|
||||
id="visualizations.newHeatmapChart.conditionalMessage.newLibrary"
|
||||
id="visualizations.newChart.conditionalMessage.newLibrary"
|
||||
defaultMessage="Switch to the old library in {link}"
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink href={advancedSettingsLink}>
|
||||
<FormattedMessage
|
||||
id="visualizations.newHeatmapChart.conditionalMessage.advancedSettingsLink"
|
||||
id="visualizations.newChart.conditionalMessage.advancedSettingsLink"
|
||||
defaultMessage="Advanced Settings."
|
||||
/>
|
||||
</EuiLink>
|
||||
|
@ -47,6 +46,13 @@ export const SplitChartWarning = () => {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const ContactAdminMessage: FC<WarningMessageProps> = ({ canEditAdvancedSettings }) => {
|
||||
return (
|
||||
<>
|
||||
{!canEditAdvancedSettings && (
|
||||
<FormattedMessage
|
||||
id="visualizations.legacyCharts.conditionalMessage.noPermissions"
|
||||
|
@ -54,9 +60,64 @@ export const SplitChartWarning = () => {
|
|||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GaugeWarningFormatMessage: FC<WarningMessageProps> = (props) => {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="visualizations.newGaugeChart.notificationMessage"
|
||||
defaultMessage="The new gauge charts library does not yet support split chart aggregation. {conditionalMessage}"
|
||||
values={{
|
||||
conditionalMessage: (
|
||||
<>
|
||||
<SwitchToOldLibraryMessage {...props} />
|
||||
<ContactAdminMessage {...props} />
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const HeatmapWarningFormatMessage: FC<WarningMessageProps> = (props) => {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="visualizations.newHeatmapChart.notificationMessage"
|
||||
defaultMessage="The new heatmap charts library does not yet support split chart aggregation. {conditionalMessage}"
|
||||
values={{
|
||||
conditionalMessage: (
|
||||
<>
|
||||
<SwitchToOldLibraryMessage {...props} />
|
||||
<ContactAdminMessage {...props} />
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const warningMessages = {
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.heatmap]: HeatmapWarningFormatMessage,
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.gauge]: GaugeWarningFormatMessage,
|
||||
};
|
||||
|
||||
export const SplitChartWarning: FC<Props> = ({ chartType, chartConfigToken }) => {
|
||||
const { services } = useKibana<VisualizeServices>();
|
||||
const canEditAdvancedSettings = services.application.capabilities.advancedSettings.save;
|
||||
const advancedSettingsLink = services.application.getUrlForApp('management', {
|
||||
path: `/kibana/settings?query=${chartConfigToken}`,
|
||||
});
|
||||
|
||||
const WarningMessage = warningMessages[chartType];
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="vizSplitChartWarning"
|
||||
title={
|
||||
<WarningMessage
|
||||
advancedSettingsLink={advancedSettingsLink}
|
||||
canEditAdvancedSettings={canEditAdvancedSettings}
|
||||
/>
|
||||
}
|
||||
iconType="alert"
|
||||
color="warning"
|
||||
|
|
|
@ -17,7 +17,7 @@ import { ExperimentalVisInfo } from './experimental_vis_info';
|
|||
import { useKibana } from '../../../../kibana_react/public';
|
||||
import { urlFor } from '../../../../visualizations/public';
|
||||
import { getUISettings } from '../../services';
|
||||
import { SplitChartWarning, NEW_HEATMAP_CHARTS_LIBRARY } from './split_chart_warning';
|
||||
import { SplitChartWarning } from './split_chart_warning';
|
||||
import {
|
||||
SavedVisInstance,
|
||||
VisualizeAppState,
|
||||
|
@ -25,6 +25,11 @@ import {
|
|||
VisualizeAppStateContainer,
|
||||
VisualizeEditorVisInstance,
|
||||
} from '../types';
|
||||
import {
|
||||
CHARTS_CONFIG_TOKENS,
|
||||
CHARTS_WITHOUT_SMALL_MULTIPLES,
|
||||
isSplitChart as isSplitChartFn,
|
||||
} from '../utils/split_chart_warning_helpers';
|
||||
|
||||
interface VisualizeEditorCommonProps {
|
||||
visInstance?: VisualizeEditorVisInstance;
|
||||
|
@ -110,8 +115,17 @@ export const VisualizeEditorCommon = ({
|
|||
return null;
|
||||
}, [visInstance?.savedVis, services, visInstance?.vis?.type.title]);
|
||||
// Adds a notification for split chart on the new implementation as it is not supported yet
|
||||
const isSplitChart = visInstance?.vis?.data?.aggs?.aggs.some((agg) => agg.schema === 'split');
|
||||
const hasHeatmapLegacyhartsEnabled = getUISettings().get(NEW_HEATMAP_CHARTS_LIBRARY);
|
||||
const chartName = visInstance?.vis.type.name;
|
||||
const isSplitChart = isSplitChartFn(chartName, visInstance?.vis?.data?.aggs);
|
||||
|
||||
const chartsWithoutSmallMultiples: string[] = Object.values(CHARTS_WITHOUT_SMALL_MULTIPLES);
|
||||
const chartNeedsWarning = chartName ? chartsWithoutSmallMultiples.includes(chartName) : false;
|
||||
const chartToken =
|
||||
chartName && chartNeedsWarning
|
||||
? CHARTS_CONFIG_TOKENS[chartName as CHARTS_WITHOUT_SMALL_MULTIPLES]
|
||||
: undefined;
|
||||
|
||||
const hasLegacyChartsEnabled = chartToken ? getUISettings().get(chartToken) : true;
|
||||
|
||||
return (
|
||||
<div className={`app-container visEditor visEditor--${visInstance?.vis.type.name}`}>
|
||||
|
@ -134,9 +148,12 @@ export const VisualizeEditorCommon = ({
|
|||
/>
|
||||
)}
|
||||
{visInstance?.vis?.type?.stage === 'experimental' && <ExperimentalVisInfo />}
|
||||
{!hasHeatmapLegacyhartsEnabled &&
|
||||
isSplitChart &&
|
||||
visInstance?.vis.type.name === 'heatmap' && <SplitChartWarning />}
|
||||
{!hasLegacyChartsEnabled && isSplitChart && chartNeedsWarning && chartToken && chartName && (
|
||||
<SplitChartWarning
|
||||
chartType={chartName as CHARTS_WITHOUT_SMALL_MULTIPLES}
|
||||
chartConfigToken={chartToken}
|
||||
/>
|
||||
)}
|
||||
{visInstance?.vis?.type?.getInfoMessage?.(visInstance.vis)}
|
||||
{getLegacyUrlConflictCallout()}
|
||||
{visInstance && (
|
||||
|
|
10
src/plugins/visualizations/public/visualize_app/constants.ts
Normal file
10
src/plugins/visualizations/public/visualize_app/constants.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const NEW_HEATMAP_CHARTS_LIBRARY = 'visualization:visualize:legacyHeatmapChartsLibrary';
|
||||
export const NEW_GAUGE_CHARTS_LIBRARY = 'visualization:visualize:legacyGaugeChartsLibrary';
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { $Values } from '@kbn/utility-types';
|
||||
import { AggConfigs } from '../../../../data/common';
|
||||
import { NEW_HEATMAP_CHARTS_LIBRARY, NEW_GAUGE_CHARTS_LIBRARY } from '../constants';
|
||||
|
||||
export const CHARTS_WITHOUT_SMALL_MULTIPLES = {
|
||||
heatmap: 'heatmap',
|
||||
gauge: 'gauge',
|
||||
} as const;
|
||||
|
||||
export type CHARTS_WITHOUT_SMALL_MULTIPLES = $Values<typeof CHARTS_WITHOUT_SMALL_MULTIPLES>;
|
||||
|
||||
export const CHARTS_CONFIG_TOKENS = {
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.heatmap]: NEW_HEATMAP_CHARTS_LIBRARY,
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.gauge]: NEW_GAUGE_CHARTS_LIBRARY,
|
||||
} as const;
|
||||
|
||||
export const isSplitChart = (chartType: string | undefined, aggs?: AggConfigs) => {
|
||||
const defaultIsSplitChart = () => aggs?.aggs.some((agg) => agg.schema === 'split');
|
||||
|
||||
const knownCheckers = {
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.heatmap]: defaultIsSplitChart,
|
||||
[CHARTS_WITHOUT_SMALL_MULTIPLES.gauge]: () => aggs?.aggs.some((agg) => agg.schema === 'group'),
|
||||
};
|
||||
|
||||
return (knownCheckers[chartType as CHARTS_WITHOUT_SMALL_MULTIPLES] ?? defaultIsSplitChart)();
|
||||
};
|
|
@ -6285,33 +6285,33 @@
|
|||
"visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsText": "1つのデータソースが返せるバケットの最大数です。値が大きいとブラウザのレンダリング速度が下がる可能性があります。",
|
||||
"visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsTitle": "ヒートマップの最大バケット数",
|
||||
"visTypeVislib.aggResponse.allDocsTitle": "すべてのドキュメント",
|
||||
"visTypeVislib.controls.gaugeOptions.alignmentLabel": "アラインメント",
|
||||
"visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張",
|
||||
"visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。",
|
||||
"visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ",
|
||||
"visTypeVislib.controls.gaugeOptions.labelsTitle": "ラベル",
|
||||
"visTypeVislib.controls.gaugeOptions.rangesTitle": "範囲",
|
||||
"visTypeVislib.controls.gaugeOptions.showLabelsLabel": "ラベルを表示",
|
||||
"visTypeVislib.controls.gaugeOptions.showLegendLabel": "凡例を表示",
|
||||
"visTypeVislib.controls.gaugeOptions.showOutline": "アウトラインを表示",
|
||||
"visTypeVislib.controls.gaugeOptions.showScaleLabel": "縮尺を表示",
|
||||
"visTypeVislib.controls.gaugeOptions.styleTitle": "スタイル",
|
||||
"visTypeVislib.controls.gaugeOptions.subTextLabel": "サブラベル",
|
||||
"visTypeGauge.controls.gaugeOptions.alignmentLabel": "アラインメント",
|
||||
"visTypeGauge.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張",
|
||||
"visTypeGauge.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。",
|
||||
"visTypeGauge.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ",
|
||||
"visTypeGauge.controls.gaugeOptions.labelsTitle": "ラベル",
|
||||
"visTypeGauge.controls.gaugeOptions.rangesTitle": "範囲",
|
||||
"visTypeGauge.controls.gaugeOptions.showLabelsLabel": "ラベルを表示",
|
||||
"visTypeGauge.controls.gaugeOptions.showLegendLabel": "凡例を表示",
|
||||
"visTypeGauge.controls.gaugeOptions.showOutline": "アウトラインを表示",
|
||||
"visTypeGauge.controls.gaugeOptions.showScaleLabel": "縮尺を表示",
|
||||
"visTypeGauge.controls.gaugeOptions.styleTitle": "スタイル",
|
||||
"visTypeGauge.controls.gaugeOptions.subTextLabel": "サブラベル",
|
||||
"visTypeVislib.functions.pie.help": "パイビジュアライゼーション",
|
||||
"visTypeVislib.functions.vislib.help": "Vislib ビジュアライゼーション",
|
||||
"visTypeVislib.gauge.alignmentAutomaticTitle": "自動",
|
||||
"visTypeVislib.gauge.alignmentHorizontalTitle": "横",
|
||||
"visTypeVislib.gauge.alignmentVerticalTitle": "縦",
|
||||
"visTypeVislib.gauge.gaugeDescription": "メトリックのステータスを示します。",
|
||||
"visTypeVislib.gauge.gaugeTitle": "ゲージ",
|
||||
"visTypeVislib.gauge.gaugeTypes.arcText": "弧形",
|
||||
"visTypeVislib.gauge.gaugeTypes.circleText": "円",
|
||||
"visTypeVislib.gauge.groupTitle": "グループを分割",
|
||||
"visTypeVislib.gauge.metricTitle": "メトリック",
|
||||
"visTypeVislib.goal.goalDescription": "メトリックがどのように目標まで進むのかを追跡します。",
|
||||
"visTypeVislib.goal.goalTitle": "ゴール",
|
||||
"visTypeVislib.goal.groupTitle": "グループを分割",
|
||||
"visTypeVislib.goal.metricTitle": "メトリック",
|
||||
"visTypeGauge.gauge.alignmentAutomaticTitle": "自動",
|
||||
"visTypeGauge.gauge.alignmentHorizontalTitle": "横",
|
||||
"visTypeGauge.gauge.alignmentVerticalTitle": "縦",
|
||||
"visTypeGauge.gauge.gaugeDescription": "メトリックのステータスを示します。",
|
||||
"visTypeGauge.gauge.gaugeTitle": "ゲージ",
|
||||
"visTypeGauge.gauge.gaugeTypes.arcText": "弧形",
|
||||
"visTypeGauge.gauge.gaugeTypes.circleText": "円",
|
||||
"visTypeGauge.gauge.groupTitle": "グループを分割",
|
||||
"visTypeGauge.gauge.metricTitle": "メトリック",
|
||||
"visTypeGauge.goal.goalDescription": "メトリックがどのように目標まで進むのかを追跡します。",
|
||||
"visTypeGauge.goal.goalTitle": "ゴール",
|
||||
"visTypeGauge.goal.groupTitle": "グループを分割",
|
||||
"visTypeGauge.goal.metricTitle": "メトリック",
|
||||
"visTypeVislib.vislib.errors.noResultsFoundTitle": "結果が見つかりませんでした",
|
||||
"visTypeVislib.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます({nr})。構成されている最大値は {max} です。",
|
||||
"visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "値 {legendDataLabel} でフィルタリング",
|
||||
|
@ -6587,8 +6587,8 @@
|
|||
"visualizations.listing.table.titleColumnName": "タイトル",
|
||||
"visualizations.listing.table.typeColumnName": "型",
|
||||
"visualizations.listingPageTitle": "Visualizeライブラリ",
|
||||
"visualizations.newHeatmapChart.conditionalMessage.advancedSettingsLink": "高度な設定",
|
||||
"visualizations.newHeatmapChart.conditionalMessage.newLibrary": "{link}で古いライブラリに切り替える",
|
||||
"visualizations.newChart.conditionalMessage.advancedSettingsLink": "高度な設定",
|
||||
"visualizations.newChart.conditionalMessage.newLibrary": "{link}で古いライブラリに切り替える",
|
||||
"visualizations.newHeatmapChart.notificationMessage": "新しいヒートマップグラフライブラリはまだ分割グラフアグリゲーションをサポートしていません。{conditionalMessage}",
|
||||
"visualizations.newVisWizard.aggBasedGroupDescription": "クラシック Visualize ライブラリを使用して、アグリゲーションに基づいてグラフを作成します。",
|
||||
"visualizations.newVisWizard.aggBasedGroupTitle": "アグリゲーションに基づく",
|
||||
|
|
|
@ -6296,33 +6296,33 @@
|
|||
"visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsText": "单个数据源可以返回的最大存储桶数目。较高的数目可能对浏览器呈现性能有负面影响",
|
||||
"visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsTitle": "热图最大存储桶数",
|
||||
"visTypeVislib.aggResponse.allDocsTitle": "所有文档",
|
||||
"visTypeVislib.controls.gaugeOptions.alignmentLabel": "对齐方式",
|
||||
"visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围",
|
||||
"visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "将数据范围扩展到数据中的最大值。",
|
||||
"visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "仪表类型",
|
||||
"visTypeVislib.controls.gaugeOptions.labelsTitle": "标签",
|
||||
"visTypeVislib.controls.gaugeOptions.rangesTitle": "范围",
|
||||
"visTypeVislib.controls.gaugeOptions.showLabelsLabel": "显示标签",
|
||||
"visTypeVislib.controls.gaugeOptions.showLegendLabel": "显示图例",
|
||||
"visTypeVislib.controls.gaugeOptions.showOutline": "显示轮廓",
|
||||
"visTypeVislib.controls.gaugeOptions.showScaleLabel": "显示比例",
|
||||
"visTypeVislib.controls.gaugeOptions.styleTitle": "样式",
|
||||
"visTypeVislib.controls.gaugeOptions.subTextLabel": "子标签",
|
||||
"visTypeGauge.controls.gaugeOptions.alignmentLabel": "对齐方式",
|
||||
"visTypeGauge.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围",
|
||||
"visTypeGauge.controls.gaugeOptions.extendRangeTooltip": "将数据范围扩展到数据中的最大值。",
|
||||
"visTypeGauge.controls.gaugeOptions.gaugeTypeLabel": "仪表类型",
|
||||
"visTypeGauge.controls.gaugeOptions.labelsTitle": "标签",
|
||||
"visTypeGauge.controls.gaugeOptions.rangesTitle": "范围",
|
||||
"visTypeGauge.controls.gaugeOptions.showLabelsLabel": "显示标签",
|
||||
"visTypeGauge.controls.gaugeOptions.showLegendLabel": "显示图例",
|
||||
"visTypeGauge.controls.gaugeOptions.showOutline": "显示轮廓",
|
||||
"visTypeGauge.controls.gaugeOptions.showScaleLabel": "显示比例",
|
||||
"visTypeGauge.controls.gaugeOptions.styleTitle": "样式",
|
||||
"visTypeGauge.controls.gaugeOptions.subTextLabel": "子标签",
|
||||
"visTypeVislib.functions.pie.help": "饼图可视化",
|
||||
"visTypeVislib.functions.vislib.help": "Vislib 可视化",
|
||||
"visTypeVislib.gauge.alignmentAutomaticTitle": "自动",
|
||||
"visTypeVislib.gauge.alignmentHorizontalTitle": "水平",
|
||||
"visTypeVislib.gauge.alignmentVerticalTitle": "垂直",
|
||||
"visTypeVislib.gauge.gaugeDescription": "显示指标的状态。",
|
||||
"visTypeVislib.gauge.gaugeTitle": "仪表盘",
|
||||
"visTypeVislib.gauge.gaugeTypes.arcText": "弧形",
|
||||
"visTypeVislib.gauge.gaugeTypes.circleText": "圆形",
|
||||
"visTypeVislib.gauge.groupTitle": "拆分组",
|
||||
"visTypeVislib.gauge.metricTitle": "指标",
|
||||
"visTypeVislib.goal.goalDescription": "跟踪指标如何达到目标。",
|
||||
"visTypeVislib.goal.goalTitle": "目标图",
|
||||
"visTypeVislib.goal.groupTitle": "拆分组",
|
||||
"visTypeVislib.goal.metricTitle": "指标",
|
||||
"visTypeGauge.gauge.alignmentAutomaticTitle": "自动",
|
||||
"visTypeGauge.gauge.alignmentHorizontalTitle": "水平",
|
||||
"visTypeGauge.gauge.alignmentVerticalTitle": "垂直",
|
||||
"visTypeGauge.gauge.gaugeDescription": "显示指标的状态。",
|
||||
"visTypeGauge.gauge.gaugeTitle": "仪表盘",
|
||||
"visTypeGauge.gauge.gaugeTypes.arcText": "弧形",
|
||||
"visTypeGauge.gauge.gaugeTypes.circleText": "圆形",
|
||||
"visTypeGauge.gauge.groupTitle": "拆分组",
|
||||
"visTypeGauge.gauge.metricTitle": "指标",
|
||||
"visTypeGauge.goal.goalDescription": "跟踪指标如何达到目标。",
|
||||
"visTypeGauge.goal.goalTitle": "目标图",
|
||||
"visTypeGauge.goal.groupTitle": "拆分组",
|
||||
"visTypeGauge.goal.metricTitle": "指标",
|
||||
"visTypeVislib.vislib.errors.noResultsFoundTitle": "找不到结果",
|
||||
"visTypeVislib.vislib.heatmap.maxBucketsText": "定义了过多的序列 ({nr})。配置的最大值为 {max}。",
|
||||
"visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "筛留值 {legendDataLabel}",
|
||||
|
@ -6598,8 +6598,8 @@
|
|||
"visualizations.listing.table.titleColumnName": "标题",
|
||||
"visualizations.listing.table.typeColumnName": "类型",
|
||||
"visualizations.listingPageTitle": "Visualize 库",
|
||||
"visualizations.newHeatmapChart.conditionalMessage.advancedSettingsLink": "免费的 API 密钥。",
|
||||
"visualizations.newHeatmapChart.conditionalMessage.newLibrary": "切换到{link}中的旧库",
|
||||
"visualizations.newChart.conditionalMessage.advancedSettingsLink": "免费的 API 密钥。",
|
||||
"visualizations.newChart.conditionalMessage.newLibrary": "切换到{link}中的旧库",
|
||||
"visualizations.newHeatmapChart.notificationMessage": "新的热图图表库尚不支持拆分图表聚合。{conditionalMessage}",
|
||||
"visualizations.newVisWizard.aggBasedGroupDescription": "使用我们的经典可视化库,基于聚合创建图表。",
|
||||
"visualizations.newVisWizard.aggBasedGroupTitle": "基于聚合",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue