Internationalisation: Mark up panel edit options (#107051)

* markup timeseries panel edit

* mark up matchers ui

* mark up bar chart

* mark up stat panel

* mark up gauge

* mark up bar gauge

* mark up table component

* mark up pie chart

* mark up state timeline

* mark up heatmap

* mark up status history

* mark up histogram

* mark up text panel

* mark up alert list

* mark up dashboard list

* mark up news panel

* mark up annolist

* mark up logs panel

* mark up node-graph

* mark up traces

* mark up trend

* mark up xychart

* fix build
This commit is contained in:
Ashley Harrison
2025-06-24 12:55:55 +01:00
committed by GitHub
parent bdb1891431
commit 38fc06a6ff
58 changed files with 2378 additions and 903 deletions
@@ -170,8 +170,8 @@
"label-query-overlap-window": "Query overlap window",
"label-query-timeout": "Query timeout",
"label-scrape-interval": "Scrape interval",
"label-use-series-endpoint": "Use series endpoint",
"label-series-limit": "Series limit",
"label-use-series-endpoint": "Use series endpoint",
"more-info": "For more information on configuring prometheus type and version in data sources, see the <2>provisioning documentation</2>.",
"placeholder-example-maxsourceresolutionmtimeout": "Example: {{example}}",
"title-interval-behaviour": "Interval behaviour",
@@ -191,8 +191,8 @@
"tooltip-query-overlap-window": "Set a duration like {{example1}} or {{example2}} or {{example3}}. Default of {{default}}. This duration will be added to the duration of each incremental request.",
"tooltip-query-timeout": "Set the Prometheus query timeout.",
"tooltip-scrape-interval": "This interval is how frequently Prometheus scrapes targets. Set this to the typical scrape and evaluation interval configured in your Prometheus config file. If you set this to a greater value than your Prometheus config file interval, Grafana will evaluate the data according to this interval and you will see less data points. Defaults to {{default}}.",
"tooltip-use-series-endpoint": "Checking this option will favor the series endpoint with {{exampleParameter}} parameter over the label values endpoint with {{exampleParameter}} parameter. While the label values endpoint is considered more performant, some users may prefer the series because it has a POST method while the label values endpoint only has a GET method.",
"tooltip-series-limit": "The limit applies to all resources (metrics, labels, and values) for both endpoints (series and labels). Leave the field empty to use the default limit (40000). Set to 0 to disable the limit and fetch everything — this may cause performance issues. Default limit is 40000."
"tooltip-series-limit": "The limit applies to all resources (metrics, labels, and values) for both endpoints (series and labels). Leave the field empty to use the default limit (40000). Set to 0 to disable the limit and fetch everything — this may cause performance issues. Default limit is 40000.",
"tooltip-use-series-endpoint": "Checking this option will favor the series endpoint with {{exampleParameter}} parameter over the label values endpoint with {{exampleParameter}} parameter. While the label values endpoint is considered more performant, some users may prefer the series because it has a POST method while the label values endpoint only has a GET method."
}
},
"querybuilder": {
@@ -28,11 +28,14 @@ export const FieldNameByRegexMatcherEditor = memo<MatcherUIProps<string>>((props
});
FieldNameByRegexMatcherEditor.displayName = 'FieldNameByRegexMatcherEditor';
export const fieldNameByRegexMatcherItem: FieldMatcherUIRegistryItem<string> = {
export const getFieldNameByRegexMatcherItem: () => FieldMatcherUIRegistryItem<string> = () => ({
id: FieldMatcherID.byRegexp,
component: FieldNameByRegexMatcherEditor,
matcher: fieldMatchers.get(FieldMatcherID.byRegexp),
name: 'Fields with name matching regex',
description: 'Set properties for fields with names matching a regex',
name: t('grafana-ui.matchers-ui.name-field-name-by-regex-matcher', 'Fields with name matching regex'),
description: t(
'grafana-ui.matchers-ui.description-field-name-by-regex-matcher',
'Set properties for fields with names matching a regex'
),
optionsToLabel: (options) => options,
};
});
@@ -1,6 +1,7 @@
import { memo, useCallback } from 'react';
import { FieldMatcherID, fieldMatchers, SelectableValue } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Select } from '../Select/Select';
@@ -27,11 +28,11 @@ export const FieldNameMatcherEditor = memo<MatcherUIProps<string>>((props) => {
});
FieldNameMatcherEditor.displayName = 'FieldNameMatcherEditor';
export const fieldNameMatcherItem: FieldMatcherUIRegistryItem<string> = {
export const getFieldNameMatcherItem: () => FieldMatcherUIRegistryItem<string> = () => ({
id: FieldMatcherID.byName,
component: FieldNameMatcherEditor,
matcher: fieldMatchers.get(FieldMatcherID.byName),
name: 'Fields with name',
description: 'Set properties for a specific field',
name: t('grafana-ui.matchers-ui.name-fields-with-name', 'Fields with name'),
description: t('grafana-ui.matchers-ui.description-fields-with-name', 'Set properties for a specific field'),
optionsToLabel: (options) => options,
};
});
@@ -1,6 +1,7 @@
import { useCallback } from 'react';
import { FieldNamePickerConfigSettings, SelectableValue, StandardEditorProps } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Select } from '../Select/Select';
@@ -29,7 +30,9 @@ export const FieldNamePicker = ({ value, onChange, context, item }: Props) => {
<>
<Select
value={selectedOption}
placeholder={settings.placeholderText ?? 'Select field'}
placeholder={
settings.placeholderText ?? t('grafana-ui.matchers-ui.field-name-picker.placeholder', 'Select field')
}
options={selectOptions}
onChange={onSelectChange}
noOptionsMessage={settings.noFieldsMessage}
@@ -1,6 +1,7 @@
import { memo, useCallback } from 'react';
import { FieldMatcherID, fieldMatchers, SelectableValue, ByNamesMatcherOptions } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Input } from '../Input/Input';
import { MultiSelect } from '../Select/Select';
@@ -43,12 +44,12 @@ export const FieldNamesMatcherEditor = memo<MatcherUIProps<ByNamesMatcherOptions
});
FieldNamesMatcherEditor.displayName = 'FieldNameMatcherEditor';
export const fieldNamesMatcherItem: FieldMatcherUIRegistryItem<ByNamesMatcherOptions> = {
export const getFieldNamesMatcherItem: () => FieldMatcherUIRegistryItem<ByNamesMatcherOptions> = () => ({
id: FieldMatcherID.byNames,
component: FieldNamesMatcherEditor,
matcher: fieldMatchers.get(FieldMatcherID.byNames),
name: 'Fields with name',
description: 'Set properties for a specific field',
name: t('grafana-ui.matchers-ui.name-fields-with-name', 'Fields with name'),
description: t('grafana-ui.matchers-ui.description-fields-with-name', 'Set properties for a specific field'),
optionsToLabel: (options) => (options.names ?? []).join(', '),
excludeFromPicker: true,
};
});
@@ -1,6 +1,7 @@
import { memo, useMemo, useCallback } from 'react';
import { FieldMatcherID, fieldMatchers, SelectableValue, FieldType, DataFrame } from '@grafana/data';
import { t } from '@grafana/i18n';
import { getFieldTypeIconName } from '../../types/icon';
import { Select } from '../Select/Select';
@@ -83,11 +84,14 @@ const useSelectOptions = (counts: Map<string, number>, opt?: string): Array<Sele
}, [counts, opt]);
};
export const fieldTypeMatcherItem: FieldMatcherUIRegistryItem<string> = {
export const getFieldTypeMatcherItem: () => FieldMatcherUIRegistryItem<string> = () => ({
id: FieldMatcherID.byType,
component: FieldTypeMatcherEditor,
matcher: fieldMatchers.get(FieldMatcherID.byType),
name: 'Fields with type',
description: 'Set properties for fields of a specific type (number, string, boolean)',
name: t('grafana-ui.matchers-ui.name-fields-with-type', 'Fields with type'),
description: t(
'grafana-ui.matchers-ui.description-fields-with-type',
'Set properties for fields of a specific type (number, string, boolean)'
),
optionsToLabel: (options) => options,
};
});
@@ -102,11 +102,14 @@ const getStyles = (theme: GrafanaTheme2) => {
};
};
export const fieldValueMatcherItem: FieldMatcherUIRegistryItem<FieldValueMatcherConfig> = {
export const getFieldValueMatcherItem: () => FieldMatcherUIRegistryItem<FieldValueMatcherConfig> = () => ({
id: FieldMatcherID.byValue,
component: FieldValueMatcherEditor,
matcher: fieldMatchers.get(FieldMatcherID.byValue),
name: 'Fields with values',
description: 'Set properties for fields with reducer condition',
name: t('grafana-ui.matchers-ui.name-fields-with-value', 'Fields with values'),
description: t(
'grafana-ui.matchers-ui.description-fields-with-value',
'Set properties for fields with reducer condition'
),
optionsToLabel: (options) => `${options?.reducer} ${options?.op} ${options?.value}`,
};
});
@@ -8,6 +8,7 @@ import {
SelectableValue,
toOption,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { MultiSelect, Select } from '../Select/Select';
@@ -216,18 +217,20 @@ function getFramesDescription(frames: DataFrame[]): string {
/**
* Registry item for UI to configure "fields by frame refId"-matcher.
* @public
*/
export const fieldsByFrameRefIdItem: FieldMatcherUIRegistryItem<string> = {
export const getFieldsByFrameRefIdItem: () => FieldMatcherUIRegistryItem<string> = () => ({
id: FieldMatcherID.byFrameRefID,
component: (props: MatcherUIProps<string>) => {
return <RefIDPicker value={props.options} data={props.data} onChange={props.onChange} />;
},
matcher: fieldMatchers.get(FieldMatcherID.byFrameRefID),
name: 'Fields returned by query',
description: 'Set properties for fields from a specific query',
name: t('grafana-ui.matchers-ui.name-fields-by-query', 'Fields returned by query'),
description: t(
'grafana-ui.matchers-ui.description-fields-by-query',
'Set properties for fields from a specific query'
),
optionsToLabel: (options) => options,
};
});
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping
function escapeRegExp(string: string) {
@@ -1,18 +1,18 @@
import { Registry } from '@grafana/data';
import { fieldNameByRegexMatcherItem } from './FieldNameByRegexMatcherEditor';
import { fieldNameMatcherItem } from './FieldNameMatcherEditor';
import { fieldNamesMatcherItem } from './FieldNamesMatcherEditor';
import { fieldTypeMatcherItem } from './FieldTypeMatcherEditor';
import { fieldValueMatcherItem } from './FieldValueMatcher';
import { fieldsByFrameRefIdItem } from './FieldsByFrameRefIdMatcher';
import { getFieldNameByRegexMatcherItem } from './FieldNameByRegexMatcherEditor';
import { getFieldNameMatcherItem } from './FieldNameMatcherEditor';
import { getFieldNamesMatcherItem } from './FieldNamesMatcherEditor';
import { getFieldTypeMatcherItem } from './FieldTypeMatcherEditor';
import { getFieldValueMatcherItem } from './FieldValueMatcher';
import { getFieldsByFrameRefIdItem } from './FieldsByFrameRefIdMatcher';
import { FieldMatcherUIRegistryItem } from './types';
export const fieldMatchersUI = new Registry<FieldMatcherUIRegistryItem<any>>(() => [
fieldNameMatcherItem,
fieldNameByRegexMatcherItem,
fieldTypeMatcherItem,
fieldsByFrameRefIdItem,
fieldNamesMatcherItem,
fieldValueMatcherItem,
getFieldNameMatcherItem(),
getFieldNameByRegexMatcherItem(),
getFieldTypeMatcherItem(),
getFieldsByFrameRefIdItem(),
getFieldNamesMatcherItem(),
getFieldValueMatcherItem(),
]);
@@ -1,4 +1,5 @@
import { SelectableValue } from '@grafana/data';
import { t } from '@grafana/i18n';
import {
AxisPlacement,
BarAlignment,
@@ -10,10 +11,7 @@ import {
StackingMode,
} from '@grafana/schema';
/**
* @alpha
*/
export const graphFieldOptions: {
export const getGraphFieldOptions: () => {
drawStyle: Array<SelectableValue<GraphDrawStyle>>;
lineInterpolation: Array<SelectableValue<LineInterpolation>>;
barAlignment: Array<SelectableValue<BarAlignment>>;
@@ -22,62 +20,204 @@ export const graphFieldOptions: {
fillGradient: Array<SelectableValue<GraphGradientMode>>;
stacking: Array<SelectableValue<StackingMode>>;
thresholdsDisplayModes: Array<SelectableValue<GraphThresholdsStyleMode>>;
} = {
} = () => ({
drawStyle: [
{ label: 'Lines', value: GraphDrawStyle.Line },
{ label: 'Bars', value: GraphDrawStyle.Bars },
{ label: 'Points', value: GraphDrawStyle.Points },
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.draw-style.label-lines', 'Lines'),
value: GraphDrawStyle.Line,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.draw-style.label-bars', 'Bars'),
value: GraphDrawStyle.Bars,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.draw-style.label-points', 'Points'),
value: GraphDrawStyle.Points,
},
],
lineInterpolation: [
{ description: 'Linear', value: LineInterpolation.Linear, icon: 'gf-interpolation-linear' },
{ description: 'Smooth', value: LineInterpolation.Smooth, icon: 'gf-interpolation-smooth' },
{ description: 'Step before', value: LineInterpolation.StepBefore, icon: 'gf-interpolation-step-before' },
{ description: 'Step after', value: LineInterpolation.StepAfter, icon: 'gf-interpolation-step-after' },
{
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.line-interpolation.description-linear',
'Linear'
),
value: LineInterpolation.Linear,
icon: 'gf-interpolation-linear',
},
{
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.line-interpolation.description-smooth',
'Smooth'
),
value: LineInterpolation.Smooth,
icon: 'gf-interpolation-smooth',
},
{
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.line-interpolation.description-step-before',
'Step before'
),
value: LineInterpolation.StepBefore,
icon: 'gf-interpolation-step-before',
},
{
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.line-interpolation.description-step-after',
'Step after'
),
value: LineInterpolation.StepAfter,
icon: 'gf-interpolation-step-after',
},
],
barAlignment: [
{ description: 'Before', value: BarAlignment.Before, icon: 'gf-bar-alignment-before' },
{ description: 'Center', value: BarAlignment.Center, icon: 'gf-bar-alignment-center' },
{ description: 'After', value: BarAlignment.After, icon: 'gf-bar-alignment-after' },
{
description: t('grafana-ui.u-plot.config.get-graph-field-options.bar-alignment.description-before', 'Before'),
value: BarAlignment.Before,
icon: 'gf-bar-alignment-before',
},
{
description: t('grafana-ui.u-plot.config.get-graph-field-options.bar-alignment.description-center', 'Center'),
value: BarAlignment.Center,
icon: 'gf-bar-alignment-center',
},
{
description: t('grafana-ui.u-plot.config.get-graph-field-options.bar-alignment.description-after', 'After'),
value: BarAlignment.After,
icon: 'gf-bar-alignment-after',
},
],
showPoints: [
{ label: 'Auto', value: VisibilityMode.Auto, description: 'Show points when the density is low' },
{ label: 'Always', value: VisibilityMode.Always },
{ label: 'Never', value: VisibilityMode.Never },
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.show-points.label-auto', 'Auto'),
value: VisibilityMode.Auto,
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.show-points.description-auto',
'Show points when the density is low'
),
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.show-points.label-always', 'Always'),
value: VisibilityMode.Always,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.show-points.label-never', 'Never'),
value: VisibilityMode.Never,
},
],
axisPlacement: [
{ label: 'Auto', value: AxisPlacement.Auto, description: 'First field on the left, everything else on the right' },
{ label: 'Left', value: AxisPlacement.Left },
{ label: 'Right', value: AxisPlacement.Right },
{ label: 'Hidden', value: AxisPlacement.Hidden },
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.axis-placement.label-auto', 'Auto'),
value: AxisPlacement.Auto,
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.axis-placement.description-auto',
'First field on the left, everything else on the right'
),
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.axis-placement.label-left', 'Left'),
value: AxisPlacement.Left,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.axis-placement.label-right', 'Right'),
value: AxisPlacement.Right,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.axis-placement.label-hidden', 'Hidden'),
value: AxisPlacement.Hidden,
},
],
fillGradient: [
{ label: 'None', value: GraphGradientMode.None },
{ label: 'Opacity', value: GraphGradientMode.Opacity, description: 'Enable fill opacity gradient' },
{ label: 'Hue', value: GraphGradientMode.Hue, description: 'Small color hue gradient' },
{
label: 'Scheme',
label: t('grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.label-none', 'None'),
value: GraphGradientMode.None,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.label-opacity', 'Opacity'),
value: GraphGradientMode.Opacity,
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.description-opacity',
'Enable fill opacity gradient'
),
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.label-hue', 'Hue'),
value: GraphGradientMode.Hue,
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.description-hue',
'Small color hue gradient'
),
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.label-scheme', 'Scheme'),
value: GraphGradientMode.Scheme,
description: 'Use color scheme to define gradient',
description: t(
'grafana-ui.u-plot.config.get-graph-field-options.fill-gradient.description-scheme',
'Use color scheme to define gradient'
),
},
],
stacking: [
{ label: 'Off', value: StackingMode.None },
{ label: 'Normal', value: StackingMode.Normal },
{ label: '100%', value: StackingMode.Percent },
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.stacking.label-off', 'Off'),
value: StackingMode.None,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.stacking.label-normal', 'Normal'),
value: StackingMode.Normal,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.stacking.label-100', '100%'),
value: StackingMode.Percent,
},
],
thresholdsDisplayModes: [
{ label: 'Off', value: GraphThresholdsStyleMode.Off },
{ label: 'As lines', value: GraphThresholdsStyleMode.Line },
{ label: 'As lines (dashed)', value: GraphThresholdsStyleMode.Dashed },
{ label: 'As filled regions', value: GraphThresholdsStyleMode.Area },
{ label: 'As filled regions and lines', value: GraphThresholdsStyleMode.LineAndArea },
{ label: 'As filled regions and lines (dashed)', value: GraphThresholdsStyleMode.DashedAndArea },
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-off', 'Off'),
value: GraphThresholdsStyleMode.Off,
},
{
label: t('grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-lines', 'As lines'),
value: GraphThresholdsStyleMode.Line,
},
{
label: t(
'grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-dashed-lines',
'As lines (dashed)'
),
value: GraphThresholdsStyleMode.Dashed,
},
{
label: t(
'grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-filled-regions',
'As filled regions'
),
value: GraphThresholdsStyleMode.Area,
},
{
label: t(
'grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-filled-regions-and-lines',
'As filled regions and lines'
),
value: GraphThresholdsStyleMode.LineAndArea,
},
{
label: t(
'grafana-ui.u-plot.config.get-graph-field-options.thresholds-display-mode.label-filled-regions-and-dashed-lines',
'As filled regions and lines (dashed)'
),
value: GraphThresholdsStyleMode.DashedAndArea,
},
],
};
});
/**
* @deprecated Use `getGraphFieldOptions` instead so translations load correctly.
*/
export const graphFieldOptions = getGraphFieldOptions();
+1 -1
View File
@@ -341,7 +341,7 @@ const LegacyForms = {
export { LegacyForms, LegacyInputStatus };
// WIP, need renames and exports cleanup
export { graphFieldOptions } from './components/uPlot/config';
export { graphFieldOptions, getGraphFieldOptions } from './components/uPlot/config';
export { UPlotConfigBuilder } from './components/uPlot/config/UPlotConfigBuilder';
export { UPLOT_AXIS_FONT_SIZE } from './components/uPlot/config/UPlotAxisBuilder';
export { UPlotChart } from './components/uPlot/Plot';
@@ -13,9 +13,7 @@ import { RadioButtonGroup } from '../../components/Forms/RadioButtonGroup/RadioB
import { Input } from '../../components/Input/Input';
import { Stack } from '../../components/Layout/Stack/Stack';
import { Select } from '../../components/Select/Select';
import { graphFieldOptions } from '../../components/uPlot/config';
const category = ['Axis'];
import { getGraphFieldOptions } from '../../components/uPlot/config';
/**
* @alpha
@@ -23,14 +21,15 @@ const category = ['Axis'];
export function addAxisConfig(builder: FieldConfigEditorBuilder<AxisConfig>, defaultConfig: AxisConfig) {
// options for axis appearance
addAxisPlacement(builder);
const category = [t('grafana-ui.builder.axis.category-axis', 'Axis')];
builder.addTextInput({
path: 'axisLabel',
name: 'Label',
name: t('grafana-ui.builder.axis.name-label', 'Label'),
category,
defaultValue: '',
settings: {
placeholder: 'Optional text',
placeholder: t('grafana-ui.builder.axis.placeholder-label', 'Optional text'),
expandTemplateVars: true,
},
showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden,
@@ -43,34 +42,34 @@ export function addAxisConfig(builder: FieldConfigEditorBuilder<AxisConfig>, def
builder
.addRadio({
path: 'axisGridShow',
name: 'Show grid lines',
name: t('grafana-ui.builder.axis.name-grid-lines', 'Show grid lines'),
category,
defaultValue: undefined,
settings: {
options: [
{ value: undefined, label: 'Auto' },
{ value: true, label: 'On' },
{ value: false, label: 'Off' },
{ value: undefined, label: t('grafana-ui.builder.axis.grid-line-options.label-auto', 'Auto') },
{ value: true, label: t('grafana-ui.builder.axis.grid-line-options.label-on', 'On') },
{ value: false, label: t('grafana-ui.builder.axis.grid-line-options.label-off', 'Off') },
],
},
showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden,
})
.addRadio({
path: 'axisColorMode',
name: 'Color',
name: t('grafana-ui.builder.axis.color-label', 'Color'),
category,
defaultValue: AxisColorMode.Text,
settings: {
options: [
{ value: AxisColorMode.Text, label: 'Text' },
{ value: AxisColorMode.Series, label: 'Series' },
{ value: AxisColorMode.Text, label: t('grafana-ui.builder.axis.color-options.label-text', 'Text') },
{ value: AxisColorMode.Series, label: t('grafana-ui.builder.axis.color-options.label-series', 'Series') },
],
},
showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden,
})
.addBooleanSwitch({
path: 'axisBorderShow',
name: 'Show border',
name: t('grafana-ui.builder.axis.name-show-border', 'Show border'),
category,
defaultValue: false,
showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden,
@@ -81,7 +80,7 @@ export function addAxisConfig(builder: FieldConfigEditorBuilder<AxisConfig>, def
.addCustomEditor<void, ScaleDistributionConfig>({
id: 'scaleDistribution',
path: 'scaleDistribution',
name: 'Scale',
name: t('grafana-ui.builder.axis.name-scale', 'Scale'),
category,
editor: ScaleDistributionEditor,
override: ScaleDistributionEditor,
@@ -91,46 +90,31 @@ export function addAxisConfig(builder: FieldConfigEditorBuilder<AxisConfig>, def
})
.addBooleanSwitch({
path: 'axisCenteredZero',
name: 'Centered zero',
name: t('grafana-ui.builder.axis.name-centered-zero', 'Centered zero'),
category,
defaultValue: false,
showIf: (c) => c.scaleDistribution?.type !== ScaleDistribution.Log,
})
.addNumberInput({
path: 'axisSoftMin',
name: 'Soft min',
name: t('grafana-ui.builder.axis.name-soft-min', 'Soft min'),
defaultValue: defaultConfig.axisSoftMin,
category,
settings: {
placeholder: 'See: Standard options > Min',
placeholder: t('grafana-ui.builder.axis.placeholder-soft-min', 'See: Standard options > Min'),
},
})
.addNumberInput({
path: 'axisSoftMax',
name: 'Soft max',
name: t('grafana-ui.builder.axis.name-soft-max', 'Soft max'),
defaultValue: defaultConfig.axisSoftMax,
category,
settings: {
placeholder: 'See: Standard options > Max',
placeholder: t('grafana-ui.builder.axis.placeholder-soft-max', 'See: Standard options > Max'),
},
});
}
const DISTRIBUTION_OPTIONS: Array<SelectableValue<ScaleDistribution>> = [
{
label: 'Linear',
value: ScaleDistribution.Linear,
},
{
label: 'Logarithmic',
value: ScaleDistribution.Log,
},
{
label: 'Symlog',
value: ScaleDistribution.Symlog,
},
];
const LOG_DISTRIBUTION_OPTIONS: Array<SelectableValue<number>> = [
{
label: '2',
@@ -148,6 +132,20 @@ const LOG_DISTRIBUTION_OPTIONS: Array<SelectableValue<number>> = [
export const ScaleDistributionEditor = ({ value, onChange }: StandardEditorProps<ScaleDistributionConfig>) => {
const type = value?.type ?? ScaleDistribution.Linear;
const log = value?.log ?? 2;
const DISTRIBUTION_OPTIONS: Array<SelectableValue<ScaleDistribution>> = [
{
label: t('grafana-ui.builder.axis.scale-distribution-editor.distribution-options.label-linear', 'Linear'),
value: ScaleDistribution.Linear,
},
{
label: t('grafana-ui.builder.axis.scale-distribution-editor.distribution-options.label-log', 'Logarithmic'),
value: ScaleDistribution.Log,
},
{
label: t('grafana-ui.builder.axis.scale-distribution-editor.distribution-options.label-symlog', 'Symlog'),
value: ScaleDistribution.Symlog,
},
];
return (
<Stack direction="column" gap={2}>
@@ -199,10 +197,10 @@ export const ScaleDistributionEditor = ({ value, onChange }: StandardEditorProps
export function addAxisWidth(builder: FieldConfigEditorBuilder<AxisConfig>) {
builder.addNumberInput({
path: 'axisWidth',
name: 'Width',
category,
name: t('grafana-ui.builder.axis.name-width', 'Width'),
category: [t('grafana-ui.builder.axis.category-axis', 'Axis')],
settings: {
placeholder: 'Auto',
placeholder: t('grafana-ui.builder.axis.placeholder-width', 'Auto'),
},
showIf: (c) => c.axisPlacement !== AxisPlacement.Hidden,
});
@@ -213,10 +211,11 @@ export function addAxisPlacement(
builder: FieldConfigEditorBuilder<AxisConfig>,
optionsFilter = (placement: AxisPlacement) => true
) {
const graphFieldOptions = getGraphFieldOptions();
builder.addRadio({
path: 'axisPlacement',
name: 'Placement',
category,
name: t('grafana-ui.builder.axis.name-placement', 'Placement'),
category: [t('grafana-ui.builder.axis.category-axis', 'Axis')],
defaultValue: graphFieldOptions.axisPlacement[0].value,
settings: {
options: graphFieldOptions.axisPlacement.filter((placement) => optionsFilter(placement.value!)),
@@ -1,4 +1,5 @@
import { PanelOptionsEditorBuilder, standardEditorsRegistry, StatsPickerConfigSettings } from '@grafana/data';
import { t } from '@grafana/i18n';
import { LegendDisplayMode, OptionsWithLegend } from '@grafana/schema';
/**
@@ -9,46 +10,47 @@ export function addLegendOptions<T extends OptionsWithLegend>(
includeLegendCalcs = true,
showLegend = true
) {
const category = [t('grafana-ui.builder.legend.category', 'Legend')];
builder
.addBooleanSwitch({
path: 'legend.showLegend',
name: 'Visibility',
category: ['Legend'],
name: t('grafana-ui.builder.legend.name-visibility', 'Visibility'),
category,
description: '',
defaultValue: showLegend,
})
.addRadio({
path: 'legend.displayMode',
name: 'Mode',
category: ['Legend'],
name: t('grafana-ui.builder.legend.name-mode', 'Mode'),
category,
description: '',
defaultValue: LegendDisplayMode.List,
settings: {
options: [
{ value: LegendDisplayMode.List, label: 'List' },
{ value: LegendDisplayMode.Table, label: 'Table' },
{ value: LegendDisplayMode.List, label: t('grafana-ui.builder.legend.mode-options.label-list', 'List') },
{ value: LegendDisplayMode.Table, label: t('grafana-ui.builder.legend.mode-options.label-table', 'Table') },
],
},
showIf: (c) => c.legend.showLegend,
})
.addRadio({
path: 'legend.placement',
name: 'Placement',
category: ['Legend'],
name: t('grafana-ui.builder.legend.name-placement', 'Placement'),
category,
description: '',
defaultValue: 'bottom',
settings: {
options: [
{ value: 'bottom', label: 'Bottom' },
{ value: 'right', label: 'Right' },
{ value: 'bottom', label: t('grafana-ui.builder.legend.placement-options.label-bottom', 'Bottom') },
{ value: 'right', label: t('grafana-ui.builder.legend.placement-options.label-right', 'Right') },
],
},
showIf: (c) => c.legend.showLegend,
})
.addNumberInput({
path: 'legend.width',
name: 'Width',
category: ['Legend'],
name: t('grafana-ui.builder.legend.name-width', 'Width'),
category,
settings: {
placeholder: 'Auto',
},
@@ -59,9 +61,9 @@ export function addLegendOptions<T extends OptionsWithLegend>(
builder.addCustomEditor<StatsPickerConfigSettings, string[]>({
id: 'legend.calcs',
path: 'legend.calcs',
name: 'Values',
category: ['Legend'],
description: 'Select values or calculations to show in legend',
name: t('grafana-ui.builder.legend.name-values', 'Values'),
category,
description: t('grafana-ui.builder.legend.description-values', 'Select values or calculations to show in legend'),
editor: standardEditorsRegistry.get('stats-picker').editor,
defaultValue: [],
settings: {
@@ -12,7 +12,7 @@ import { RadioButtonGroup } from '../../components/Forms/RadioButtonGroup/RadioB
import { IconButton } from '../../components/IconButton/IconButton';
import { Input } from '../../components/Input/Input';
import { Stack } from '../../components/Layout/Stack/Stack';
import { graphFieldOptions } from '../../components/uPlot/config';
import { getGraphFieldOptions } from '../../components/uPlot/config';
export const StackingEditor = ({
value,
@@ -61,10 +61,11 @@ export function addStackingConfig(
defaultConfig?: StackingConfig,
category = ['Graph styles']
) {
const graphFieldOptions = getGraphFieldOptions();
builder.addCustomEditor({
id: 'stacking',
path: 'stacking',
name: 'Stack series',
name: t('grafana-ui.builder.stacking.name-stack-series', 'Stack series'),
category: category,
defaultValue: defaultConfig,
editor: StackingEditor,
@@ -1,4 +1,5 @@
import { PanelOptionsEditorBuilder } from '@grafana/data';
import { t } from '@grafana/i18n';
import { OptionsWithTextFormatting } from '@grafana/schema';
/**
@@ -11,13 +12,14 @@ export function addTextSizeOptions<T extends OptionsWithTextFormatting>(
builder: PanelOptionsEditorBuilder<T>,
withTitle = true
) {
const category = [t('grafana-ui.builder.text.category-text-size', 'Text size')];
if (withTitle) {
builder.addNumberInput({
path: 'text.titleSize',
category: ['Text size'],
name: 'Title',
category,
name: t('grafana-ui.builder.text.name-title', 'Title'),
settings: {
placeholder: 'Auto',
placeholder: t('grafana-ui.builder.text.placeholder-title', 'Auto'),
integer: false,
min: 1,
max: 200,
@@ -28,10 +30,10 @@ export function addTextSizeOptions<T extends OptionsWithTextFormatting>(
builder.addNumberInput({
path: 'text.valueSize',
category: ['Text size'],
name: 'Value',
category,
name: t('grafana-ui.builder.text.name-value', 'Value'),
settings: {
placeholder: 'Auto',
placeholder: t('grafana-ui.builder.text.placeholder-value', 'Auto'),
integer: false,
min: 1,
max: 200,
@@ -41,10 +43,10 @@ export function addTextSizeOptions<T extends OptionsWithTextFormatting>(
builder.addNumberInput({
path: 'text.percentSize',
category: ['Text size'],
name: 'Percent change',
category,
name: t('grafana-ui.builder.text.name-percent-change', 'Percent change'),
settings: {
placeholder: 'Auto',
placeholder: t('grafana-ui.builder.text.placeholder-percent-change', 'Auto'),
integer: false,
min: 1,
max: 200,
@@ -1,4 +1,5 @@
import { DataFrame, PanelOptionsEditorBuilder } from '@grafana/data';
import { t } from '@grafana/i18n';
import { OptionsWithTooltip, TooltipDisplayMode, SortOrder } from '@grafana/schema';
/** @internal */
@@ -16,28 +17,28 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
setProximity = false,
defaultOptions?: Partial<OptionsWithTooltip>
) {
const category = ['Tooltip'];
const category = [t('grafana-ui.builder.tooltip.category', 'Tooltip')];
const modeOptions = singleOnly
? [
{ value: TooltipDisplayMode.Single, label: 'Single' },
{ value: TooltipDisplayMode.None, label: 'Hidden' },
{ value: TooltipDisplayMode.Single, label: t('grafana-ui.builder.tooltip.modeOptions.label-single', 'Single') },
{ value: TooltipDisplayMode.None, label: t('grafana-ui.builder.tooltip.modeOptions.label-hidden', 'Hidden') },
]
: [
{ value: TooltipDisplayMode.Single, label: 'Single' },
{ value: TooltipDisplayMode.Multi, label: 'All' },
{ value: TooltipDisplayMode.None, label: 'Hidden' },
{ value: TooltipDisplayMode.Single, label: t('grafana-ui.builder.tooltip.modeOptions.label-single', 'Single') },
{ value: TooltipDisplayMode.Multi, label: t('grafana-ui.builder.tooltip.modeOptions.label-all', 'All') },
{ value: TooltipDisplayMode.None, label: t('grafana-ui.builder.tooltip.modeOptions.label-hidden', 'Hidden') },
];
const sortOptions = [
{ value: SortOrder.None, label: 'None' },
{ value: SortOrder.Ascending, label: 'Ascending' },
{ value: SortOrder.Descending, label: 'Descending' },
{ value: SortOrder.None, label: t('grafana-ui.builder.tooltip.sortOptions.label-none', 'None') },
{ value: SortOrder.Ascending, label: t('grafana-ui.builder.tooltip.sortOptions.label-ascending', 'Ascending') },
{ value: SortOrder.Descending, label: t('grafana-ui.builder.tooltip.sortOptions.label-descending', 'Descending') },
];
builder
.addRadio({
path: 'tooltip.mode',
name: 'Tooltip mode',
name: t('grafana-ui.builder.tooltip.name-tooltip-mode', 'Tooltip mode'),
category,
defaultValue: defaultOptions?.tooltip?.mode ?? TooltipDisplayMode.Single,
settings: {
@@ -46,7 +47,7 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
})
.addRadio({
path: 'tooltip.sort',
name: 'Values sort order',
name: t('grafana-ui.builder.tooltip.name-values-sort-order', 'Values sort order'),
category,
defaultValue: defaultOptions?.tooltip?.sort ?? SortOrder.None,
showIf: (options: T) => options.tooltip?.mode === TooltipDisplayMode.Multi,
@@ -56,7 +57,7 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
})
.addBooleanSwitch({
path: 'tooltip.hideZeros',
name: 'Hide zeros',
name: t('grafana-ui.builder.tooltip.name-hide-zeros', 'Hide zeros'),
category,
defaultValue: false,
showIf: (options: T) =>
@@ -66,8 +67,11 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
if (setProximity) {
builder.addNumberInput({
path: 'tooltip.hoverProximity',
name: 'Hover proximity',
description: 'How close the cursor must be to a point to trigger the tooltip, in pixels',
name: t('grafana-ui.builder.tooltip.name-hover-proximity', 'Hover proximity'),
description: t(
'grafana-ui.builder.tooltip.description-hover-proximity',
'How close the cursor must be to a point to trigger the tooltip, in pixels'
),
category,
settings: {
integer: true,
@@ -79,7 +83,7 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
builder
.addNumberInput({
path: 'tooltip.maxWidth',
name: 'Max width',
name: t('grafana-ui.builder.tooltip.name-max-width', 'Max width'),
category,
settings: {
integer: true,
@@ -88,7 +92,7 @@ export function addTooltipOptions<T extends OptionsWithTooltip>(
})
.addNumberInput({
path: 'tooltip.maxHeight',
name: 'Max height',
name: t('grafana-ui.builder.tooltip.name-max-height', 'Max height'),
category,
defaultValue: undefined,
settings: {
@@ -30,6 +30,7 @@ import {
DataLinksFieldConfigSettings,
} from '@grafana/data';
import { actionsOverrideProcessor } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { FieldConfig } from '@grafana/schema';
import { RadioButtonGroup, TimeZonePicker, Switch } from '@grafana/ui';
import { FieldNamePicker } from '@grafana/ui/internal';
@@ -162,8 +163,8 @@ export const getAllOptionEditors = () => {
const timeZone: StandardEditorsRegistryItem<TimeZone> = {
id: 'timezone',
name: 'Time zone',
description: 'Time zone selection',
name: t('options-ui.registry.get-all-option-editors.name-time-zone', 'Time zone'),
description: t('options-ui.registry.get-all-option-editors.description-time-zone', 'Time zone selection'),
editor: TimeZonePicker,
};
@@ -222,17 +223,20 @@ export const getAllOptionEditors = () => {
* Returns collection of common field config properties definitions
*/
export const getAllStandardFieldConfigs = () => {
const category = ['Standard options'];
const category = [t('options-ui.registry.standard-field-configs.category', 'Standard options')];
const displayName: FieldConfigPropertyItem<FieldConfig, string, StringFieldConfigSettings> = {
id: 'displayName',
path: 'displayName',
name: 'Display name',
description: 'Change the field or series name',
name: t('options-ui.registry.standard-field-configs.name-display-name', 'Display name'),
description: t(
'options-ui.registry.standard-field-configs.description-display-name',
'Change the field or series name'
),
editor: standardEditorsRegistry.get('text').editor,
override: standardEditorsRegistry.get('text').editor,
process: displayNameOverrideProcessor,
settings: {
placeholder: 'none',
placeholder: t('options-ui.registry.standard-field-configs.placeholder-display-name', 'none'),
expandTemplateVars: true,
},
shouldApply: () => true,
@@ -242,7 +246,7 @@ export const getAllStandardFieldConfigs = () => {
const unit: FieldConfigPropertyItem<FieldConfig, string, StringFieldConfigSettings> = {
id: 'unit',
path: 'unit',
name: 'Unit',
name: t('options-ui.registry.standard-field-configs.name-unit', 'Unit'),
description: '',
editor: standardEditorsRegistry.get('unit').editor,
@@ -250,7 +254,7 @@ export const getAllStandardFieldConfigs = () => {
process: stringOverrideProcessor,
settings: {
placeholder: 'none',
placeholder: t('options-ui.registry.standard-field-configs.placeholder-unit', 'none'),
},
shouldApply: () => true,
@@ -260,8 +264,11 @@ export const getAllStandardFieldConfigs = () => {
const fieldMinMax: FieldConfigPropertyItem<FieldConfig, boolean, BooleanFieldSettings> = {
id: 'fieldMinMax',
path: 'fieldMinMax',
name: 'Field min/max',
description: 'Calculate min max per field',
name: t('options-ui.registry.standard-field-configs.name-field-min-max', 'Field min/max'),
description: t(
'options-ui.registry.standard-field-configs.description-field-min-max',
'Calculate min max per field'
),
editor: standardEditorsRegistry.get('boolean').editor,
override: standardEditorsRegistry.get('boolean').editor,
@@ -277,15 +284,18 @@ export const getAllStandardFieldConfigs = () => {
const min: FieldConfigPropertyItem<FieldConfig, number, NumberFieldConfigSettings> = {
id: 'min',
path: 'min',
name: 'Min',
description: 'Leave empty to calculate based on all values',
name: t('options-ui.registry.standard-field-configs.name-min', 'Min'),
description: t(
'options-ui.registry.standard-field-configs.description-min',
'Leave empty to calculate based on all values'
),
editor: standardEditorsRegistry.get('number').editor,
override: standardEditorsRegistry.get('number').editor,
process: numberOverrideProcessor,
settings: {
placeholder: 'auto',
placeholder: t('options-ui.registry.standard-field-configs.placeholder-min', 'auto'),
},
shouldApply: (field) => field.type === FieldType.number,
category,
@@ -294,15 +304,18 @@ export const getAllStandardFieldConfigs = () => {
const max: FieldConfigPropertyItem<FieldConfig, number, NumberFieldConfigSettings> = {
id: 'max',
path: 'max',
name: 'Max',
description: 'Leave empty to calculate based on all values',
name: t('options-ui.registry.standard-field-configs.name-max', 'Max'),
description: t(
'options-ui.registry.standard-field-configs.description-max',
'Leave empty to calculate based on all values'
),
editor: standardEditorsRegistry.get('number').editor,
override: standardEditorsRegistry.get('number').editor,
process: numberOverrideProcessor,
settings: {
placeholder: 'auto',
placeholder: t('options-ui.registry.standard-field-configs.placeholder-max', 'auto'),
},
shouldApply: (field) => field.type === FieldType.number,
@@ -312,14 +325,14 @@ export const getAllStandardFieldConfigs = () => {
const decimals: FieldConfigPropertyItem<FieldConfig, number, NumberFieldConfigSettings> = {
id: 'decimals',
path: 'decimals',
name: 'Decimals',
name: t('options-ui.registry.standard-field-configs.name-decimals', 'Decimals'),
editor: standardEditorsRegistry.get('number').editor,
override: standardEditorsRegistry.get('number').editor,
process: numberOverrideProcessor,
settings: {
placeholder: 'auto',
placeholder: t('options-ui.registry.standard-field-configs.placeholder-decimals', 'auto'),
min: 0,
max: 15,
integer: true,
@@ -332,8 +345,11 @@ export const getAllStandardFieldConfigs = () => {
const noValue: FieldConfigPropertyItem<FieldConfig, string, StringFieldConfigSettings> = {
id: 'noValue',
path: 'noValue',
name: 'No value',
description: 'What to show when there is no value',
name: t('options-ui.registry.standard-field-configs.name-no-value', 'No value'),
description: t(
'options-ui.registry.standard-field-configs.description-no-value',
'What to show when there is no value'
),
editor: standardEditorsRegistry.get('text').editor,
override: standardEditorsRegistry.get('text').editor,
@@ -347,12 +363,15 @@ export const getAllStandardFieldConfigs = () => {
category,
};
const dataLinksCategory = 'Data links and actions';
const dataLinksCategory = t(
'options-ui.registry.standard-field-condigs.category-data-links',
'Data links and actions'
);
const links: FieldConfigPropertyItem<FieldConfig, DataLink[], DataLinksFieldConfigSettings> = {
id: 'links',
path: 'links',
name: 'Data links',
name: t('options-ui.registry.standard-field-configs.name-data-links', 'Data links'),
editor: standardEditorsRegistry.get('links').editor,
override: standardEditorsRegistry.get('links').editor,
process: dataLinksOverrideProcessor,
@@ -367,7 +386,7 @@ export const getAllStandardFieldConfigs = () => {
const actions: FieldConfigPropertyItem<FieldConfig, Action[], DataLinksFieldConfigSettings> = {
id: 'actions',
path: 'actions',
name: 'Actions',
name: t('options-ui.registry.standard-field-configs.name-actions', 'Actions'),
editor: standardEditorsRegistry.get('actions').editor,
override: standardEditorsRegistry.get('actions').editor,
process: actionsOverrideProcessor,
@@ -383,7 +402,7 @@ export const getAllStandardFieldConfigs = () => {
const color: FieldConfigPropertyItem<FieldConfig, FieldColor | undefined, FieldColorConfigSettings> = {
id: 'color',
path: 'color',
name: 'Color scheme',
name: t('options-ui.registry.standard-field-configs.name-color-scheme', 'Color scheme'),
editor: standardEditorsRegistry.get('fieldColor').editor,
override: standardEditorsRegistry.get('fieldColor').editor,
process: identityOverrideProcessor,
@@ -398,8 +417,11 @@ export const getAllStandardFieldConfigs = () => {
const mappings: FieldConfigPropertyItem<FieldConfig, ValueMapping[], ValueMappingFieldConfigSettings> = {
id: 'mappings',
path: 'mappings',
name: 'Value mappings',
description: 'Modify the display text based on input value',
name: t('options-ui.registry.standard-field-configs.name-value-mappings', 'Value mappings'),
description: t(
'options-ui.registry.standard-field-configs.description-value-mappings',
'Modify the display text based on input value'
),
editor: standardEditorsRegistry.get('mappings').editor,
override: standardEditorsRegistry.get('mappings').editor,
@@ -407,14 +429,14 @@ export const getAllStandardFieldConfigs = () => {
settings: {},
defaultValue: [],
shouldApply: (x) => x.type !== FieldType.time,
category: ['Value mappings'],
category: [t('options-ui.registry.standard-field-configs.category-value-mappings', 'Value mappings')],
getItemsCount: (value?) => (value ? value.length : 0),
};
const thresholds: FieldConfigPropertyItem<FieldConfig, ThresholdsConfig, ThresholdsFieldConfigSettings> = {
id: 'thresholds',
path: 'thresholds',
name: 'Thresholds',
name: t('options-ui.registry.standard-field-configs.name-thresholds', 'Thresholds'),
editor: standardEditorsRegistry.get('thresholds').editor,
override: standardEditorsRegistry.get('thresholds').editor,
process: thresholdsOverrideProcessor,
@@ -427,14 +449,14 @@ export const getAllStandardFieldConfigs = () => {
],
},
shouldApply: () => true,
category: ['Thresholds'],
category: [t('options-ui.registry.standard-field-configs.category-thresholds', 'Thresholds')],
getItemsCount: (value) => (value ? value.steps.length : 0),
};
const filterable: FieldConfigPropertyItem<FieldConfig, boolean | undefined, {}> = {
id: 'filterable',
path: 'filterable',
name: 'Ad-hoc filterable',
name: t('options-ui.registry.standard-field-configs.name-ad-hoc', 'Ad-hoc filterable'),
hideFromDefaults: true,
editor: standardEditorsRegistry.get('boolean').editor,
override: standardEditorsRegistry.get('boolean').editor,
@@ -29,7 +29,7 @@ export class PanelDataAlertingTab extends SceneObjectBase<PanelDataAlertingTabSt
}
public getTabLabel() {
return 'Alert';
return t('dashboard-scene.panel-data-alerting-tab.tab-label', 'Alert');
}
public getDashboardUID() {
@@ -1,6 +1,6 @@
import { CoreApp, DataSourceApi, DataSourceInstanceSettings, getDataSourceRef } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans } from '@grafana/i18n';
import { t, Trans } from '@grafana/i18n';
import { config, getDataSourceSrv, locationService } from '@grafana/runtime';
import {
SceneObjectBase,
@@ -50,7 +50,7 @@ export class PanelDataQueriesTab extends SceneObjectBase<PanelDataQueriesTabStat
}
public getTabLabel() {
return 'Queries';
return t('dashboard-scene.panel-data-queries-tab.tab-label', 'Queries');
}
public getItemsCount() {
@@ -35,7 +35,7 @@ export class PanelDataTransformationsTab
tabId = TabId.Transformations;
getTabLabel() {
return 'Transformations';
return t('dashboard-scene.panel-data-transformations-tab.tab-label', 'Transformations');
}
public renderTab(props: PanelDataTabHeaderProps) {
@@ -81,7 +81,9 @@ export function getFieldOverrideCategories(
*/
for (let idx = 0; idx < currentFieldConfig.overrides.length; idx++) {
const override = currentFieldConfig.overrides[idx];
const overrideName = `Override ${idx + 1}`;
const overrideName = t('dashboard.get-field-override-categories.override-name', 'Override {{overrideNum}}', {
overrideNum: idx + 1,
});
const matcherUi = fieldMatchersUI.get(override.matcher.id);
const configPropertiesOptions = getOverrideProperties(registry);
const isSystemOverride = isSystemOverrideGuard(override);
@@ -15,15 +15,6 @@ import {
import { Trans, t } from '@grafana/i18n';
import { Button, ColorPicker, colors, IconButton, Input, Label, RadioButtonGroup, stylesFactory } from '@grafana/ui';
const modes: Array<SelectableValue<ThresholdsMode>> = [
{ value: ThresholdsMode.Absolute, label: 'Absolute', description: 'Pick thresholds based on the absolute values' },
{
value: ThresholdsMode.Percentage,
label: 'Percentage',
description: 'Pick threshold based on the percent between min/max',
},
];
export interface Props {
thresholds: ThresholdsConfig;
onChange: (thresholds: ThresholdsConfig) => void;
@@ -155,7 +146,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
return (
<Input
type="text"
value={'Base'}
value={t('dimensions.thresholds-editor.value-base', 'Base')}
aria-label={ariaLabel}
disabled
prefix={
@@ -211,6 +202,25 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
const { thresholds } = this.props;
const { steps } = this.state;
const modes: Array<SelectableValue<ThresholdsMode>> = [
{
value: ThresholdsMode.Absolute,
label: t('dimensions.thresholds-editor.modes.label.absolute', 'Absolute'),
description: t(
'dimensions.thresholds-editor.modes.description.thresholds-based-absolute-values',
'Pick thresholds based on the absolute values'
),
},
{
value: ThresholdsMode.Percentage,
label: t('dimensions.thresholds-editor.modes.label.percentage', 'Percentage'),
description: t(
'dimensions.thresholds-editor.modes.description.threshold-based-percent-between-minmax',
'Pick threshold based on the percent between min/max'
),
},
];
return (
<ThemeContext.Consumer>
{(theme) => {
@@ -10,32 +10,41 @@ import { SuggestionsInput } from '../../suggestionsInput/SuggestionsInput';
import { numberOrVariableValidator } from '../../utils';
import { convertDurationToMilliseconds } from '../utils';
const modeOptions: Array<SelectableValue<HeatmapCalculationMode>> = [
{
label: 'Size',
value: HeatmapCalculationMode.Size,
description: 'Split the buckets based on size',
},
{
label: 'Count',
value: HeatmapCalculationMode.Count,
description: 'Split the buckets based on count',
},
];
const logModeOptions: Array<SelectableValue<HeatmapCalculationMode>> = [
{
label: 'Split',
value: HeatmapCalculationMode.Size,
description: 'Split the buckets based on size',
},
];
export const AxisEditor = ({ value, onChange, item }: StandardEditorProps<HeatmapCalculationBucketConfig>) => {
const [isInvalid, setInvalid] = useState<boolean>(false);
const modeSwitchCounter = useRef(0);
const modeOptions: Array<SelectableValue<HeatmapCalculationMode>> = [
{
label: t('transformers.axis-editor.mode-options.label.size', 'Size'),
value: HeatmapCalculationMode.Size,
description: t(
'transformers.axis-editor.mode-options.description.split-the-buckets-based-on-size',
'Split the buckets based on size'
),
},
{
label: t('transformers.axis-editor.mode-options.label.count', 'Count'),
value: HeatmapCalculationMode.Count,
description: t(
'transformers.axis-editor.mode-options.description.split-the-buckets-based-on-count',
'Split the buckets based on count'
),
},
];
const logModeOptions: Array<SelectableValue<HeatmapCalculationMode>> = [
{
label: t('transformers.axis-editor.log-mode-options.label.split', 'Split'),
value: HeatmapCalculationMode.Size,
description: t(
'transformers.axis-editor.log-mode-options.description.split-the-buckets-based-on-size',
'Split the buckets based on size'
),
},
];
const allowInterval = item.settings?.allowInterval ?? false;
const onValueChange = ({ mode, scale, value = '' }: HeatmapCalculationBucketConfig) => {
@@ -1,4 +1,5 @@
import { PanelOptionsEditorBuilder } from '@grafana/data';
import { t } from '@grafana/i18n';
import { ScaleDistribution, HeatmapCalculationMode, HeatmapCalculationOptions } from '@grafana/schema';
import { ScaleDistributionEditor } from '@grafana/ui/internal';
@@ -13,7 +14,7 @@ export function addHeatmapCalculationOptions(
builder.addCustomEditor({
id: 'xBuckets',
path: `${prefix}xBuckets`,
name: 'X Bucket',
name: t('transformers.calculate-heatmap.add-heatmap-calculation-options.name-x-bucket', 'X Bucket'),
editor: AxisEditor,
category,
defaultValue: {
@@ -27,7 +28,7 @@ export function addHeatmapCalculationOptions(
builder.addCustomEditor({
id: 'yBuckets',
path: `${prefix}yBuckets`,
name: 'Y Bucket',
name: t('transformers.calculate-heatmap.add-heatmap-calculation-options.name-y-bucket', 'Y Bucket'),
editor: AxisEditor,
category,
defaultValue: {
@@ -38,7 +39,7 @@ export function addHeatmapCalculationOptions(
builder.addCustomEditor({
id: 'yBuckets-scale',
path: `${prefix}yBuckets.scale`,
name: 'Y Bucket scale',
name: t('transformers.calculate-heatmap.add-heatmap-calculation-options.name-y-bucket-scale', 'Y Bucket scale'),
category,
editor: ScaleDistributionEditor,
defaultValue: { type: ScaleDistribution.Linear },
+79 -56
View File
@@ -1,5 +1,5 @@
import { DataSourceInstanceSettings, PanelPlugin } from '@grafana/data';
import { Trans } from '@grafana/i18n';
import { t, Trans } from '@grafana/i18n';
import { Button, Stack } from '@grafana/ui';
import { NestedFolderPicker } from 'app/core/components/NestedFolderPicker/NestedFolderPicker';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
@@ -14,41 +14,50 @@ import { UnifiedAlertListPanel } from './UnifiedAlertList';
import { GroupMode, SortOrder, UnifiedAlertListOptions, ViewMode } from './types';
const unifiedAlertList = new PanelPlugin<UnifiedAlertListOptions>(UnifiedAlertListPanel).setPanelOptions((builder) => {
const optionsCategory = [t('alertlist.category-options', 'Options')];
const filterCategory = [t('alertlist.category-filter', 'Filter')];
const alertStateCategory = [t('alertlist.category-alert-state-filter', 'Alert state filter')];
builder
.addRadio({
path: 'viewMode',
name: 'View mode',
description: 'Toggle between list view and stat view',
name: t('alertlist.name-view-mode', 'View mode'),
description: t('alertlist.description-view-mode', 'Toggle between list view and stat view'),
defaultValue: ViewMode.List,
settings: {
options: [
{ label: 'List', value: ViewMode.List },
{ label: 'Stat', value: ViewMode.Stat },
{ label: t('alertlist.view-mode-options.label-list', 'List'), value: ViewMode.List },
{ label: t('alertlist.view-mode-options.label-stat', 'Stat'), value: ViewMode.Stat },
],
},
category: ['Options'],
category: optionsCategory,
})
.addRadio({
path: 'groupMode',
name: 'Group mode',
description: 'How alert instances should be grouped',
name: t('alertlist.name-group-mode', 'Group mode'),
description: t('alertlist.description-group-mode', 'How alert instances should be grouped'),
defaultValue: GroupMode.Default,
settings: {
options: [
{ value: GroupMode.Default, label: 'Default grouping' },
{ value: GroupMode.Custom, label: 'Custom grouping' },
{
value: GroupMode.Default,
label: t('alertlist.group-mode-options.label-default-grouping', 'Default grouping'),
},
{
value: GroupMode.Custom,
label: t('alertlist.group-mode-options.label-custom-grouping', 'Custom grouping'),
},
],
},
category: ['Options'],
category: optionsCategory,
})
.addCustomEditor({
path: 'groupBy',
name: 'Group by',
description: 'Filter alerts using label querying',
name: t('alertlist.name-group-by', 'Group by'),
description: t('alertlist.description-group-by', 'Filter alerts using label querying'),
id: 'groupBy',
defaultValue: [],
showIf: (options) => options.groupMode === GroupMode.Custom,
category: ['Options'],
category: optionsCategory,
editor: (props) => {
return (
<GroupBy
@@ -61,53 +70,62 @@ const unifiedAlertList = new PanelPlugin<UnifiedAlertListOptions>(UnifiedAlertLi
},
})
.addNumberInput({
name: 'Max items',
name: t('alertlist.name-max-items', 'Max items'),
path: 'maxItems',
description: 'Maximum alerts to display',
description: t('alertlist.description-max-items', 'Maximum alerts to display'),
defaultValue: 20,
category: ['Options'],
category: optionsCategory,
})
.addSelect({
name: 'Sort order',
name: t('alertlist.name-sort-order', 'Sort order'),
path: 'sortOrder',
description: 'Sort order of alerts and alert instances',
description: t('alertlist.description-sort-order', 'Sort order of alerts and alert instances'),
settings: {
options: [
{ label: 'Alphabetical (asc)', value: SortOrder.AlphaAsc },
{ label: 'Alphabetical (desc)', value: SortOrder.AlphaDesc },
{ label: 'Importance', value: SortOrder.Importance },
{ label: 'Time (asc)', value: SortOrder.TimeAsc },
{ label: 'Time (desc)', value: SortOrder.TimeDesc },
{
label: t('alertlist.sort-order-options.label-alphabetical-asc', 'Alphabetical (asc)'),
value: SortOrder.AlphaAsc,
},
{
label: t('alertlist.sort-order-options.label-alphabetical-desc', 'Alphabetical (desc)'),
value: SortOrder.AlphaDesc,
},
{ label: t('alertlist.sort-order-options.label-importance', 'Importance'), value: SortOrder.Importance },
{ label: t('alertlist.sort-order-options.label-time-asc', 'Time (asc)'), value: SortOrder.TimeAsc },
{ label: t('alertlist.sort-order-options.label-time-desc', 'Time (desc)'), value: SortOrder.TimeDesc },
],
},
defaultValue: SortOrder.AlphaAsc,
category: ['Options'],
category: optionsCategory,
})
.addBooleanSwitch({
path: 'dashboardAlerts',
name: 'Alerts linked to this dashboard',
description: 'Only show alerts linked to this dashboard',
name: t('alertlist.name-alerts-linked-to-dashboard', 'Alerts linked to this dashboard'),
description: t('alertlist.descriptino-alerts-linked-to-dashboard', 'Only show alerts linked to this dashboard'),
defaultValue: false,
category: ['Options'],
category: optionsCategory,
})
.addTextInput({
path: 'alertName',
name: 'Alert name',
description: 'Filter for alerts containing this text',
name: t('alertlist.name-alert-name', 'Alert name'),
description: t('alertlist.description-alert-name', 'Filter for alerts containing this text'),
defaultValue: '',
category: ['Filter'],
category: filterCategory,
})
.addTextInput({
path: 'alertInstanceLabelFilter',
name: 'Alert instance label',
description: 'Filter alert instances using label querying, ex: {severity="critical", instance=~"cluster-us-.+"}',
name: t('alertlist.name-alert-instance-label', 'Alert instance label'),
description: t(
'alertlist.description-alert-instance-label',
'Filter alert instances using label querying, ex: {severity="critical", instance=~"cluster-us-.+"}'
),
defaultValue: '',
category: ['Filter'],
category: filterCategory,
})
.addCustomEditor({
path: 'datasource',
name: 'Datasource',
description: 'Filter from alert source',
name: t('alertlist.name-datasource', 'Datasource'),
description: t('alertlist.description-datasource', 'Filter from alert source'),
id: 'datasource',
defaultValue: null,
editor: function RenderDatasourcePicker(props) {
@@ -133,13 +151,16 @@ const unifiedAlertList = new PanelPlugin<UnifiedAlertListOptions>(UnifiedAlertLi
</Stack>
);
},
category: ['Filter'],
category: filterCategory,
})
.addCustomEditor({
showIf: (options) => options.datasource === GRAFANA_DATASOURCE_NAME || !Boolean(options.datasource),
path: 'folder',
name: 'Folder',
description: 'Filter for alerts in the selected folder (for Grafana-managed alert rules only)',
name: t('alertlist.name-folder', 'Folder'),
description: t(
'alertlist.description-folder',
'Filter for alerts in the selected folder (for Grafana-managed alert rules only)'
),
id: 'folder',
defaultValue: null,
editor: function RenderFolderPicker(props) {
@@ -154,51 +175,53 @@ const unifiedAlertList = new PanelPlugin<UnifiedAlertListOptions>(UnifiedAlertLi
/>
);
},
category: ['Filter'],
category: filterCategory,
})
.addBooleanSwitch({
path: 'showInactiveAlerts',
name: 'Show alerts with 0 instances',
description:
'Include alert rules which have 0 (zero) instances. Because these rules have no instances, they remain hidden if the Alert instance label filter is configured.',
name: t('alertlist.name-show-inactive-alerts', 'Show alerts with 0 instances'),
description: t(
'alertlist.description-show-inactive-alerts',
'Include alert rules which have 0 (zero) instances. Because these rules have no instances, they remain hidden if the Alert instance label filter is configured.'
),
defaultValue: false,
category: ['Filter'],
category: filterCategory,
})
.addBooleanSwitch({
path: 'stateFilter.firing',
name: 'Alerting / Firing',
name: t('alertlist.name-firing', 'Alerting / Firing'),
defaultValue: true,
category: ['Alert state filter'],
category: alertStateCategory,
})
.addBooleanSwitch({
path: 'stateFilter.pending',
name: 'Pending',
name: t('alertlist.name-pending', 'Pending'),
defaultValue: true,
category: ['Alert state filter'],
category: alertStateCategory,
})
.addBooleanSwitch({
path: 'stateFilter.recovering',
name: 'Recovering',
name: t('alertlist.name-recovering', 'Recovering'),
defaultValue: true,
category: ['Alert state filter'],
category: alertStateCategory,
})
.addBooleanSwitch({
path: 'stateFilter.noData',
name: 'No Data',
name: t('alertlist.name-no-data', 'No Data'),
defaultValue: false,
category: ['Alert state filter'],
category: alertStateCategory,
})
.addBooleanSwitch({
path: 'stateFilter.normal',
name: 'Normal',
name: t('alertlist.name-normal', 'Normal'),
defaultValue: false,
category: ['Alert state filter'],
category: alertStateCategory,
})
.addBooleanSwitch({
path: 'stateFilter.error',
name: 'Error',
name: t('alertlist.name-error', 'Error'),
defaultValue: true,
category: ['Alert state filter'],
category: alertStateCategory,
});
});
+31 -27
View File
@@ -1,4 +1,5 @@
import { PanelModel, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { TagsInput } from '@grafana/ui';
import { AnnoListPanel } from './AnnoListPanel';
@@ -6,88 +7,91 @@ import { defaultOptions, Options } from './panelcfg.gen';
export const plugin = new PanelPlugin<Options>(AnnoListPanel)
.setPanelOptions((builder) => {
const category = [t('annolist.category-annotation-query', 'Annotation query')];
const displayCategory = [t('annolist.category-display', 'Display')];
const linkBehaviourCategory = [t('annolist.category-link-behaviour', 'Link behavior')];
builder
.addRadio({
category: ['Annotation query'],
category,
path: 'onlyFromThisDashboard',
name: 'Query filter',
name: t('annolist.name-query-filter', 'Query filter'),
defaultValue: defaultOptions.onlyFromThisDashboard,
settings: {
options: [
{ value: false, label: 'All dashboards' },
{ value: true, label: 'This dashboard' },
{ value: false, label: t('annolist.query-filter-options.label-all-dashboards', 'All dashboards') },
{ value: true, label: t('annolist.query-filter-options.label-this-dashboard', 'This dashboard') },
],
},
})
.addRadio({
category: ['Annotation query'],
category,
path: 'onlyInTimeRange',
name: 'Time range',
name: t('annolist.name-time-range', 'Time range'),
defaultValue: defaultOptions.onlyInTimeRange,
settings: {
options: [
{ value: false, label: 'None' },
{ value: true, label: 'This dashboard' },
{ value: false, label: t('annolist.time-range-options.label-none', 'None') },
{ value: true, label: t('annolist.time-range-options.label-this-dashboard', 'This dashboard') },
],
},
})
.addCustomEditor({
category: ['Annotation query'],
category,
id: 'tags',
path: 'tags',
name: 'Tags',
description: 'Match annotation tags',
name: t('annolist.name-tags', 'Tags'),
description: t('annolist.description-tags', 'Match annotation tags'),
editor(props) {
return <TagsInput tags={props.value} onChange={props.onChange} />;
},
})
.addNumberInput({
category: ['Annotation query'],
category,
path: 'limit',
name: 'Limit',
name: t('annolist.name-limit', 'Limit'),
defaultValue: defaultOptions.limit,
})
.addBooleanSwitch({
category: ['Display'],
category: displayCategory,
path: 'showUser',
name: 'Show user',
name: t('annolist.name-show-user', 'Show user'),
defaultValue: defaultOptions.showUser,
})
.addBooleanSwitch({
category: ['Display'],
category: displayCategory,
path: 'showTime',
name: 'Show time',
name: t('annolist.name-show-time', 'Show time'),
defaultValue: defaultOptions.showTime,
})
.addBooleanSwitch({
category: ['Display'],
category: displayCategory,
path: 'showTags',
name: 'Show tags',
name: t('annolist.name-show-tags', 'Show tags'),
defaultValue: defaultOptions.showTags,
})
.addRadio({
category: ['Link behavior'],
category: linkBehaviourCategory,
path: 'navigateToPanel',
name: 'Link target',
name: t('annolist.name-link-target', 'Link target'),
defaultValue: defaultOptions.navigateToPanel,
settings: {
options: [
{ value: true, label: 'Panel' },
{ value: false, label: 'Dashboard' },
{ value: true, label: t('annolist.link-target-options.label-panel', 'Panel') },
{ value: false, label: t('annolist.link-target-options.label-dashboard', 'Dashboard') },
],
},
})
.addTextInput({
category: ['Link behavior'],
category: linkBehaviourCategory,
path: 'navigateBefore',
name: 'Time before',
name: t('annolist.name-time-before', 'Time before'),
defaultValue: defaultOptions.navigateBefore,
description: '',
})
.addTextInput({
category: ['Link behavior'],
category: linkBehaviourCategory,
path: 'navigateAfter',
name: 'Time after',
name: t('annolist.name-time-after', 'Time after'),
defaultValue: defaultOptions.navigateAfter,
description: '',
});
@@ -2,30 +2,35 @@ import { SelectableValue, StandardEditorProps } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Checkbox, HorizontalGroup, RadioButtonGroup, Tooltip } from '@grafana/ui';
const GAPS_OPTIONS: Array<SelectableValue<number>> = [
{
label: 'None',
value: 0,
description: 'Show all tick marks',
},
{
label: 'Small',
value: 100,
description: 'Require 100px spacing',
},
{
label: 'Medium',
value: 200,
description: 'Require 200px spacing',
},
{
label: 'Large',
value: 300,
description: 'Require 300px spacing',
},
];
export const TickSpacingEditor = (props: StandardEditorProps<number>) => {
const GAPS_OPTIONS: Array<SelectableValue<number>> = [
{
label: t('barchart.tick-spacing-editor.gaps-options.label-none', 'None'),
value: 0,
description: t('barchart.tick-spacing-editor.gaps-options.description-none', 'Show all tick marks'),
},
{
label: t('barchart.tick-spacing-editor.gaps-options.label-small', 'Small'),
value: 100,
description: t('barchart.tick-spacing-editor.gaps-options.description-small', 'Require {{spacing}} spacing', {
spacing: '100px',
}),
},
{
label: t('barchart.tick-spacing-editor.gaps-options.label-medium', 'Medium'),
value: 200,
description: t('barchart.tick-spacing-editor.gaps-options.description-medium', 'Require {{spacing}} spacing', {
spacing: '200px',
}),
},
{
label: t('barchart.tick-spacing-editor.gaps-options.label-large', 'Large'),
value: 300,
description: t('barchart.tick-spacing-editor.gaps-options.description-large', 'Require {{spacing}} spacing', {
spacing: '300px',
}),
},
];
let value = props.value ?? 0;
const isRTL = value < 0;
if (isRTL) {
+56 -37
View File
@@ -7,8 +7,9 @@ import {
PanelPlugin,
VizOrientation,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { GraphTransform, GraphThresholdsStyleMode, StackingMode, VisibilityMode } from '@grafana/schema';
import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui';
import { getGraphFieldOptions, commonOptionsBuilder } from '@grafana/ui';
import { optsWithHideZeros } from '@grafana/ui/internal';
import { ThresholdsStyleEditor } from '../timeseries/ThresholdsStyleEditor';
@@ -47,7 +48,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
builder
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('barchart.config.name-line-width', 'Line width'),
defaultValue: cfg.lineWidth,
settings: {
min: 0,
@@ -57,7 +58,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('barchart.config.name-fill-opacity', 'Fill opacity'),
defaultValue: cfg.fillOpacity,
settings: {
min: 0,
@@ -67,28 +68,34 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addRadio({
path: 'gradientMode',
name: 'Gradient mode',
defaultValue: graphFieldOptions.fillGradient[0].value,
name: t('barchart.config.name-gradient-mode', 'Gradient mode'),
defaultValue: getGraphFieldOptions().fillGradient[0].value,
settings: {
options: graphFieldOptions.fillGradient,
options: getGraphFieldOptions().fillGradient,
},
});
builder.addSelect({
category: ['Graph styles'],
name: 'Transform',
name: t('barchart.config.name-transform', 'Transform'),
path: 'transform',
settings: {
options: [
{
label: 'Constant',
label: t('barchart.config.transform-options.label-constant', 'Constant'),
value: GraphTransform.Constant,
description: 'The first value will be shown as a constant line',
description: t(
'barchart.config.transform-options.description-constant',
'The first value will be shown as a constant line'
),
},
{
label: 'Negative Y',
label: t('barchart.config.transform-options.label-negative-y', 'Negative Y'),
value: GraphTransform.NegativeY,
description: 'Flip the results to negative values on the y axis',
description: t(
'barchart.config.transform-options.description-negative-y',
'Flip the results to negative values on the y axis'
),
},
],
isClearable: true,
@@ -99,11 +106,11 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
builder.addCustomEditor({
id: 'thresholdsStyle',
path: 'thresholdsStyle',
name: 'Show thresholds',
category: ['Thresholds'],
name: t('barchart.config.name-show-thresholds', 'Show thresholds'),
category: [t('barchart.config.category-thresholds', 'Thresholds')],
defaultValue: { mode: GraphThresholdsStyleMode.Off },
settings: {
options: graphFieldOptions.thresholdsDisplayModes,
options: getGraphFieldOptions().thresholdsDisplayModes,
},
editor: ThresholdsStyleEditor,
override: ThresholdsStyleEditor,
@@ -119,26 +126,32 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
builder
.addFieldNamePicker({
path: 'xField',
name: 'X Axis',
name: t('barchart.config.name-x-axis', 'X Axis'),
settings: {
placeholderText: 'First string or time field',
placeholderText: t('barchart.config.placeholder-x-axis', 'First string or time field'),
},
})
.addRadio({
path: 'orientation',
name: 'Orientation',
name: t('barchart.config.name-orientation', 'Orientation'),
settings: {
options: [
{ value: VizOrientation.Auto, label: 'Auto' },
{ value: VizOrientation.Horizontal, label: 'Horizontal' },
{ value: VizOrientation.Vertical, label: 'Vertical' },
{ value: VizOrientation.Auto, label: t('barchart.config.orientation-options.label-auto', 'Auto') },
{
value: VizOrientation.Horizontal,
label: t('barchart.config.orientation-options.label-horizontal', 'Horizontal'),
},
{
value: VizOrientation.Vertical,
label: t('barchart.config.orientation-options.label-line-vertical', 'Vertical'),
},
],
},
defaultValue: defaultOptions.orientation,
})
.addSliderInput({
path: 'xTickLabelRotation',
name: 'Rotate x-axis tick labels',
name: t('barchart.config.name-rotate-x-labels', 'Rotate x-axis tick labels'),
defaultValue: defaultOptions.xTickLabelRotation,
settings: {
min: -90,
@@ -150,10 +163,13 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addNumberInput({
path: 'xTickLabelMaxLength',
name: 'X-axis tick label max length',
description: 'X-axis labels will be truncated to the length provided',
name: t('barchart.config.name-x-label-max-length', 'X-axis tick label max length'),
description: t(
'barchart.config.description-x-label-max-length',
'X-axis labels will be truncated to the length provided'
),
settings: {
placeholder: 'None',
placeholder: t('barchart.config.placeholder-x-label-max-length', 'None'),
min: 0,
},
showIf: (opts) => opts.xTickLabelRotation !== 0,
@@ -161,33 +177,33 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
.addCustomEditor({
id: 'xTickLabelSpacing',
path: 'xTickLabelSpacing',
name: 'X-axis labels minimum spacing',
name: t('barchart.config.name-x-label-min-spacing', 'X-axis labels minimum spacing'),
defaultValue: defaultOptions.xTickLabelSpacing,
editor: TickSpacingEditor,
})
.addRadio({
path: 'showValue',
name: 'Show values',
name: t('barchart.config.name-show-values', 'Show values'),
settings: {
options: [
{ value: VisibilityMode.Auto, label: 'Auto' },
{ value: VisibilityMode.Always, label: 'Always' },
{ value: VisibilityMode.Never, label: 'Never' },
{ value: VisibilityMode.Auto, label: t('barchart.config.show-values-options.label-auto', 'Auto') },
{ value: VisibilityMode.Always, label: t('barchart.config.show-values-options.label-always', 'Always') },
{ value: VisibilityMode.Never, label: t('barchart.config.show-values-options.label-never', 'Never') },
],
},
defaultValue: defaultOptions.showValue,
})
.addRadio({
path: 'stacking',
name: 'Stacking',
name: t('barchart.config.name-stacking', 'Stacking'),
settings: {
options: graphFieldOptions.stacking,
options: getGraphFieldOptions().stacking,
},
defaultValue: defaultOptions.stacking,
})
.addSliderInput({
path: 'groupWidth',
name: 'Group width',
name: t('barchart.config.name-group-width', 'Group width'),
defaultValue: defaultOptions.groupWidth,
settings: {
min: 0,
@@ -203,7 +219,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addSliderInput({
path: 'barWidth',
name: 'Bar width',
name: t('barchart.config.name-bar-width', 'Bar width'),
defaultValue: defaultOptions.barWidth,
settings: {
min: 0,
@@ -213,7 +229,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addSliderInput({
path: 'barRadius',
name: 'Bar radius',
name: t('barchart.config.name-bar-radius', 'Bar radius'),
defaultValue: defaultOptions.barRadius,
settings: {
min: 0,
@@ -223,15 +239,18 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(BarChartPanel)
})
.addBooleanSwitch({
path: 'fullHighlight',
name: 'Highlight full area on hover',
name: t('barchart.config.name-full-highlight', 'Highlight full area on hover'),
defaultValue: defaultOptions.fullHighlight,
showIf: (c) => c.stacking === StackingMode.None,
});
builder.addFieldNamePicker({
path: 'colorByField',
name: 'Color by field',
description: 'Use the color value for a sibling field to color each bar value.',
name: t('barchart.config.name-color-by-field', 'Color by field'),
description: t(
'barchart.config.description-color-by-field',
'Use the color value for a sibling field to color each bar value.'
),
});
commonOptionsBuilder.addTooltipOptions(builder, false, false, optsWithHideZeros);
+48 -28
View File
@@ -1,4 +1,5 @@
import { PanelPlugin, VizOrientation } from '@grafana/data';
import { t } from '@grafana/i18n';
import { BarGaugeDisplayMode, BarGaugeNamePlacement, BarGaugeSizing, BarGaugeValueMode } from '@grafana/schema';
import { commonOptionsBuilder, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
@@ -12,45 +13,58 @@ import { BarGaugeSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin<Options>(BarGaugePanel)
.useFieldConfig()
.setPanelOptions((builder) => {
const category = [t('bargauge.category-bar-gauge', 'Bar gauge')];
addStandardDataReduceOptions(builder);
addOrientationOption(builder);
addOrientationOption(builder, category);
commonOptionsBuilder.addLegendOptions(builder, true, false);
commonOptionsBuilder.addTextSizeOptions(builder);
builder
.addRadio({
path: 'displayMode',
name: 'Display mode',
name: t('bargauge.name-display-mode', 'Display mode'),
category,
settings: {
options: [
{ value: BarGaugeDisplayMode.Gradient, label: 'Gradient' },
{ value: BarGaugeDisplayMode.Lcd, label: 'Retro LCD' },
{ value: BarGaugeDisplayMode.Basic, label: 'Basic' },
{
value: BarGaugeDisplayMode.Gradient,
label: t('bargauge.display-mode-options.label-gradient', 'Gradient'),
},
{ value: BarGaugeDisplayMode.Lcd, label: t('bargauge.display-mode-options.label-retro', 'Retro LCD') },
{ value: BarGaugeDisplayMode.Basic, label: t('bargauge.display-mode-options.label-basic', 'Basic') },
],
},
defaultValue: defaultOptions.displayMode,
})
.addRadio({
path: 'valueMode',
name: 'Value display',
name: t('bargauge.name-value-display', 'Value display'),
category,
settings: {
options: [
{ value: BarGaugeValueMode.Color, label: 'Value color' },
{ value: BarGaugeValueMode.Text, label: 'Text color' },
{ value: BarGaugeValueMode.Hidden, label: 'Hidden' },
{
value: BarGaugeValueMode.Color,
label: t('bargauge.value-display-options.label-value-color', 'Value color'),
},
{
value: BarGaugeValueMode.Text,
label: t('bargauge.value-display-options.label-text-color', 'Text color'),
},
{ value: BarGaugeValueMode.Hidden, label: t('bargauge.value-display-options.label-hidden', 'Hidden') },
],
},
defaultValue: defaultOptions.valueMode,
})
.addRadio({
path: 'namePlacement',
name: 'Name placement',
name: t('bargauge.name-name-placement', 'Name placement'),
category,
settings: {
options: [
{ value: BarGaugeNamePlacement.Auto, label: 'Auto' },
{ value: BarGaugeNamePlacement.Top, label: 'Top' },
{ value: BarGaugeNamePlacement.Left, label: 'Left' },
{ value: BarGaugeNamePlacement.Hidden, label: 'Hidden' },
{ value: BarGaugeNamePlacement.Auto, label: t('bargauge.name-placement-options.label-auto', 'Auto') },
{ value: BarGaugeNamePlacement.Top, label: t('bargauge.name-placement-options.label-top', 'Top') },
{ value: BarGaugeNamePlacement.Left, label: t('bargauge.name-placement-options.label-left', 'Left') },
{ value: BarGaugeNamePlacement.Hidden, label: t('bargauge.name-placement-options.label-hidden', 'Hidden') },
],
},
defaultValue: defaultOptions.namePlacement,
@@ -58,11 +72,12 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
})
.addRadio({
path: 'namePlacement',
name: 'Name placement',
name: t('bargauge.name-name-placement', 'Name placement'),
category,
settings: {
options: [
{ value: BarGaugeNamePlacement.Auto, label: 'Auto' },
{ value: BarGaugeNamePlacement.Hidden, label: 'Hidden' },
{ value: BarGaugeNamePlacement.Auto, label: t('bargauge.name-placement-options.label-auto', 'Auto') },
{ value: BarGaugeNamePlacement.Hidden, label: t('bargauge.name-placement-options.label-hidden', 'Hidden') },
],
},
defaultValue: defaultOptions.namePlacement,
@@ -70,26 +85,29 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
})
.addBooleanSwitch({
path: 'showUnfilled',
name: 'Show unfilled area',
description: 'When enabled renders the unfilled region as gray',
name: t('bargauge.name-show-unfilled-area', 'Show unfilled area'),
category,
description: t('bargauge.description-show-unfilled-area', 'When enabled renders the unfilled region as gray'),
defaultValue: defaultOptions.showUnfilled,
showIf: (options) => options.displayMode !== 'lcd',
})
.addRadio({
path: 'sizing',
name: 'Bar size',
name: t('bargauge.name-bar-size', 'Bar size'),
category,
settings: {
options: [
{ value: BarGaugeSizing.Auto, label: 'Auto' },
{ value: BarGaugeSizing.Manual, label: 'Manual' },
{ value: BarGaugeSizing.Auto, label: t('bargauge.bar-size-options.label-auto', 'Auto') },
{ value: BarGaugeSizing.Manual, label: t('bargauge.bar-size-options.label-manual', 'Manual') },
],
},
defaultValue: defaultOptions.sizing,
})
.addSliderInput({
path: 'minVizWidth',
name: 'Min width',
description: 'Minimum column width (vertical orientation)',
name: t('bargauge.name-min-width', 'Min width'),
category,
description: t('bargauge.description-min-width', 'Minimum column width (vertical orientation)'),
defaultValue: defaultOptions.minVizWidth,
settings: {
min: 0,
@@ -102,8 +120,9 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
})
.addSliderInput({
path: 'minVizHeight',
name: 'Min height',
description: 'Minimum row height (horizontal orientation)',
name: t('bargauge.name-min-height', 'Min height'),
category,
description: t('bargauge.description-min-height', 'Minimum row height (horizontal orientation)'),
defaultValue: defaultOptions.minVizHeight,
settings: {
min: 0,
@@ -116,8 +135,9 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
})
.addSliderInput({
path: 'maxVizHeight',
name: 'Max height',
description: 'Maximum row height (horizontal orientation)',
name: t('bargauge.name-max-height', 'Max height'),
category,
description: t('bargauge.description-max-height', 'Maximum row height (horizontal orientation)'),
defaultValue: defaultOptions.maxVizHeight,
settings: {
min: 0,
+35 -31
View File
@@ -8,6 +8,7 @@ import {
TimeRange,
} from '@grafana/data';
import { maybeSortFrame } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { findField } from 'app/features/dimensions';
import { prepareGraphableFields } from '../timeseries/utils';
@@ -28,37 +29,39 @@ export interface FieldPickerInfo {
description: string;
}
export const candlestickFieldsInfo: Record<keyof CandlestickFieldMap, FieldPickerInfo> = {
open: {
key: 'open',
name: 'Open',
defaults: ['open', 'o'],
description: 'Value at the start of the period',
},
high: {
key: 'high',
name: 'High',
defaults: ['high', 'h', 'max'],
description: 'Maximum value within the period',
},
low: {
key: 'low',
name: 'Low',
defaults: ['low', 'l', 'min'],
description: 'Minimum value within the period',
},
close: {
key: 'close',
name: 'Close',
defaults: ['close', 'c'],
description: 'Value at the end of the period',
},
volume: {
key: 'volume',
name: 'Volume',
defaults: ['volume', 'v'],
description: 'Sample count within the period',
},
export const getCandlestickFieldsInfo: () => Record<keyof CandlestickFieldMap, FieldPickerInfo> = () => {
return {
open: {
key: 'open',
name: t('candlestick.name-open', 'Open'),
defaults: ['open', 'o'],
description: t('candlestick.description-open', 'Value at the start of the period'),
},
high: {
key: 'high',
name: t('candlestick.name-high', 'High'),
defaults: ['high', 'h', 'max'],
description: t('candlestick.description-high', 'Maximum value within the period'),
},
low: {
key: 'low',
name: t('candlestick.name-low', 'Low'),
defaults: ['low', 'l', 'min'],
description: t('candlestick.description-low', 'Minimum value within the period'),
},
close: {
key: 'close',
name: t('candlestick.name-close', 'Close'),
defaults: ['close', 'c'],
description: t('candlestick.description-close', 'Value at the end of the period'),
},
volume: {
key: 'volume',
name: t('candlestick.name-volume', 'Volume'),
defaults: ['volume', 'v'],
description: t('candlestick.description-volume', 'Sample count within the period'),
},
};
};
export interface CandlestickData {
@@ -103,6 +106,7 @@ export function prepareCandlestickFields(
if (!series?.length) {
return null;
}
const candlestickFieldsInfo = getCandlestickFieldsInfo();
// All fields
const fieldMap = options.fields ?? {};
+50 -43
View File
@@ -1,11 +1,5 @@
import {
Field,
FieldType,
getFieldDisplayName,
PanelOptionsEditorBuilder,
PanelPlugin,
SelectableValue,
} from '@grafana/data';
import { Field, FieldType, getFieldDisplayName, PanelOptionsEditorBuilder, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { GraphFieldConfig } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
@@ -13,32 +7,17 @@ import { commonOptionsBuilder } from '@grafana/ui';
import { defaultGraphConfig, getGraphFieldConfig } from '../timeseries/config';
import { CandlestickPanel } from './CandlestickPanel';
import { CandlestickData, candlestickFieldsInfo, FieldPickerInfo, prepareCandlestickFields } from './fields';
import { CandlestickData, getCandlestickFieldsInfo, FieldPickerInfo, prepareCandlestickFields } from './fields';
import { CandlestickSuggestionsSupplier } from './suggestions';
import { defaultCandlestickColors, defaultOptions, Options, VizDisplayMode, ColorStrategy, CandleStyle } from './types';
const modeOptions: Array<SelectableValue<VizDisplayMode>> = [
{ label: 'Candles', value: VizDisplayMode.Candles },
{ label: 'Volume', value: VizDisplayMode.Volume },
{ label: 'Both', value: VizDisplayMode.CandlesVolume },
];
const candleStyles: Array<SelectableValue<CandleStyle>> = [
{ label: 'Candles', value: CandleStyle.Candles },
{ label: 'OHLC Bars', value: CandleStyle.OHLCBars },
];
const colorStrategies: Array<SelectableValue<ColorStrategy>> = [
{ label: 'Since Open', value: ColorStrategy.OpenClose },
{ label: 'Since Prior Close', value: ColorStrategy.CloseClose },
];
const numericFieldFilter = (f: Field) => f.type === FieldType.number;
function addFieldPicker(
builder: PanelOptionsEditorBuilder<Options>,
info: FieldPickerInfo,
data: CandlestickData | null
data: CandlestickData | null,
category?: string[]
) {
let placeholderText = 'Auto ';
@@ -60,6 +39,7 @@ function addFieldPicker(
path: `fields.${info.key}`,
name: info.name,
description: info.description,
category,
settings: {
filter: numericFieldFilter,
placeholderText,
@@ -70,68 +50,95 @@ function addFieldPicker(
export const plugin = new PanelPlugin<Options, GraphFieldConfig>(CandlestickPanel)
.useFieldConfig(getGraphFieldConfig(defaultGraphConfig))
.setPanelOptions((builder, context) => {
const category = [t('candlestick.category-candlestick', 'Candlestick')];
const opts = context.options ?? defaultOptions;
const info = prepareCandlestickFields(context.data, opts, config.theme2);
builder
.addRadio({
path: 'mode',
name: 'Mode',
name: t('candlestick.name-mode', 'Mode'),
category,
description: '',
defaultValue: defaultOptions.mode,
settings: {
options: modeOptions,
options: [
{ label: t('candlestick.mode-options.label-candles', 'Candles'), value: VizDisplayMode.Candles },
{ label: t('candlestick.mode-options.label-volume', 'Volume'), value: VizDisplayMode.Volume },
{ label: t('candlestick.mode-options.label-both', 'Both'), value: VizDisplayMode.CandlesVolume },
],
},
})
.addRadio({
path: 'candleStyle',
name: 'Candle style',
name: t('candlestick.name-candle-style', 'Candle style'),
category,
description: '',
defaultValue: defaultOptions.candleStyle,
settings: {
options: candleStyles,
options: [
{ label: t('candlestick.candle-style-options.label-candles', 'Candles'), value: CandleStyle.Candles },
{ label: t('candlestick.candle-style-options.label-ohlc-bars', 'OHLC Bars'), value: CandleStyle.OHLCBars },
],
},
showIf: (opts) => opts.mode !== VizDisplayMode.Volume,
})
.addRadio({
path: 'colorStrategy',
name: 'Color strategy',
name: t('candlestick.name-color-strategy', 'Color strategy'),
category,
description: '',
defaultValue: defaultOptions.colorStrategy,
settings: {
options: colorStrategies,
options: [
{
label: t('candlestick.color-strategy-options.label-since-open', 'Since Open'),
value: ColorStrategy.OpenClose,
},
{
label: t('candlestick.color-strategy-options.label-since-prior-close', 'Since Prior Close'),
value: ColorStrategy.CloseClose,
},
],
},
})
.addColorPicker({
path: 'colors.up',
name: 'Up color',
name: t('candlestick.name-up-color', 'Up color'),
category,
defaultValue: defaultCandlestickColors.up,
})
.addColorPicker({
path: 'colors.down',
name: 'Down color',
name: t('candlestick.name-down-color', 'Down color'),
category,
defaultValue: defaultCandlestickColors.down,
});
addFieldPicker(builder, candlestickFieldsInfo.open, info);
const candlestickFieldsInfo = getCandlestickFieldsInfo();
addFieldPicker(builder, candlestickFieldsInfo.open, info, category);
if (opts.mode !== VizDisplayMode.Volume) {
addFieldPicker(builder, candlestickFieldsInfo.high, info);
addFieldPicker(builder, candlestickFieldsInfo.low, info);
addFieldPicker(builder, candlestickFieldsInfo.high, info, category);
addFieldPicker(builder, candlestickFieldsInfo.low, info, category);
}
addFieldPicker(builder, candlestickFieldsInfo.close, info);
addFieldPicker(builder, candlestickFieldsInfo.close, info, category);
if (opts.mode !== VizDisplayMode.Candles) {
addFieldPicker(builder, candlestickFieldsInfo.volume, info);
addFieldPicker(builder, candlestickFieldsInfo.volume, info, category);
}
builder.addRadio({
path: 'includeAllFields',
name: 'Additional fields',
description: 'Use standard timeseries options to configure any fields not mapped above',
name: t('candlestick.name-additional-fields', 'Additional fields'),
category,
description: t(
'candlestick.description-additional-fields',
'Use standard timeseries options to configure any fields not mapped above'
),
defaultValue: defaultOptions.includeAllFields,
settings: {
options: [
{ label: 'Ignore', value: false },
{ label: 'Include', value: true },
{ label: t('candlestick.additional-fields-options.label-ignore', 'Ignore'), value: false },
{ label: t('candlestick.additional-fields-options.label-include', 'Include'), value: true },
],
},
});
+24 -11
View File
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { TagsInput } from '@grafana/ui';
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
@@ -8,55 +9,66 @@ import { defaultOptions, Options } from './panelcfg.gen';
export const plugin = new PanelPlugin<Options>(DashList)
.setPanelOptions((builder) => {
const category = [t('dashlist.category-dashboard-list', 'Dashboard list')];
builder
.addBooleanSwitch({
path: 'keepTime',
name: 'Include current time range',
name: t('dashlist.name-include-current-time-range', 'Include current time range'),
category,
defaultValue: defaultOptions.keepTime,
})
.addBooleanSwitch({
path: 'includeVars',
name: 'Include current template variable values',
name: t('dashlist.name-include-current-template-variables', 'Include current template variable values'),
category,
defaultValue: defaultOptions.includeVars,
})
.addBooleanSwitch({
path: 'showStarred',
name: 'Starred',
name: t('dashlist.name-starred', 'Starred'),
category,
defaultValue: defaultOptions.showStarred,
})
.addBooleanSwitch({
path: 'showRecentlyViewed',
name: 'Recently viewed',
name: t('dashlist.name-recently-viewed', 'Recently viewed'),
category,
defaultValue: defaultOptions.showRecentlyViewed,
})
.addBooleanSwitch({
path: 'showSearch',
name: 'Search',
name: t('dashlist.name-search', 'Search'),
category,
defaultValue: defaultOptions.showSearch,
})
.addBooleanSwitch({
path: 'showHeadings',
name: 'Show headings',
name: t('dashlist.name-show-headings', 'Show headings'),
category,
defaultValue: defaultOptions.showHeadings,
})
.addBooleanSwitch({
path: 'showFolderNames',
name: 'Show folder names',
name: t('dashlist.name-show-folder-names', 'Show folder names'),
category,
defaultValue: defaultOptions.showFolderNames,
})
.addNumberInput({
path: 'maxItems',
name: 'Max items',
name: t('dashlist.name-max-items', 'Max items'),
category,
defaultValue: defaultOptions.maxItems,
})
.addTextInput({
path: 'query',
name: 'Query',
name: t('dashlist.name-query', 'Query'),
category,
defaultValue: defaultOptions.query,
})
.addCustomEditor({
path: 'folderUID',
name: 'Folder',
name: t('dashlist.name-folder', 'Folder'),
category,
id: 'folderUID',
defaultValue: undefined,
editor: function RenderFolderPicker({ value, onChange }) {
@@ -68,7 +80,8 @@ export const plugin = new PanelPlugin<Options>(DashList)
.addCustomEditor({
id: 'tags',
path: 'tags',
name: 'Tags',
name: t('dashlist.name-tags', 'Tags'),
category,
description: '',
defaultValue: defaultOptions.tags,
editor(props) {
+23 -16
View File
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { BarGaugeSizing, VizOrientation } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
@@ -14,61 +15,67 @@ export const plugin = new PanelPlugin<Options>(GaugePanel)
useCustomConfig: (builder) => {
builder.addNumberInput({
path: 'neutral',
name: 'Neutral',
description: 'Leave empty to use Min as neutral point',
category: ['Gauge'],
name: t('gauge.name-neutral', 'Neutral'),
description: t('gauge.description-neutral', 'Leave empty to use Min as neutral point'),
category: [t('gauge.category-gauge', 'Gauge')],
settings: {
placeholder: 'auto',
placeholder: t('gauge.placeholder-neutral', 'auto'),
},
});
},
})
.setPanelOptions((builder) => {
const category = [t('gauge.category-gauge', 'Gauge')];
addStandardDataReduceOptions(builder);
addOrientationOption(builder);
addOrientationOption(builder, category);
builder
.addBooleanSwitch({
path: 'showThresholdLabels',
name: 'Show threshold labels',
description: 'Render the threshold values around the gauge bar',
name: t('gauge.name-show-threshold-labels', 'Show threshold labels'),
description: t('gauge.description-show-threshold-labels', 'Render the threshold values around the gauge bar'),
category,
defaultValue: defaultOptions.showThresholdLabels,
})
.addBooleanSwitch({
path: 'showThresholdMarkers',
name: 'Show threshold markers',
description: 'Renders the thresholds as an outer bar',
name: t('gauge.name-show-threshold-markers', 'Show threshold markers'),
description: t('gauge.description-show-threshold-markers', 'Renders the thresholds as an outer bar'),
category,
defaultValue: defaultOptions.showThresholdMarkers,
})
.addRadio({
path: 'sizing',
name: 'Gauge size',
name: t('gauge.name-gauge-size', 'Gauge size'),
settings: {
options: [
{ value: BarGaugeSizing.Auto, label: 'Auto' },
{ value: BarGaugeSizing.Manual, label: 'Manual' },
{ value: BarGaugeSizing.Auto, label: t('gauge.gauge-size-options.label-auto', 'Auto') },
{ value: BarGaugeSizing.Manual, label: t('gauge.gauge-size-options.label-manual', 'Manual') },
],
},
category,
defaultValue: defaultOptions.sizing,
showIf: (options: Options) => options.orientation !== VizOrientation.Auto,
})
.addSliderInput({
path: 'minVizWidth',
name: 'Min width',
description: 'Minimum column width (vertical orientation)',
name: t('gauge.name-min-width', 'Min width'),
description: t('gauge.description-min-width', 'Minimum column width (vertical orientation)'),
defaultValue: defaultOptions.minVizWidth,
settings: {
min: 0,
max: 600,
step: 1,
},
category,
showIf: (options: Options) =>
options.sizing === BarGaugeSizing.Manual && options.orientation === VizOrientation.Vertical,
})
.addSliderInput({
path: 'minVizHeight',
name: 'Min height',
description: 'Minimum row height (horizontal orientation)',
name: t('gauge.name-min-height', 'Min height'),
description: t('gauge.description-min-height', 'Minimum row height (horizontal orientation)'),
defaultValue: defaultOptions.minVizHeight,
category,
settings: {
min: 0,
max: 600,
+70 -68
View File
@@ -1,4 +1,5 @@
import { DataFrame, FieldConfigProperty, FieldType, identityOverrideProcessor, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import {
AxisPlacement,
@@ -31,11 +32,12 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
},
},
useCustomConfig: (builder) => {
const category = [t('heatmap.category-heatmap', 'Heatmap')];
builder.addCustomEditor<void, ScaleDistributionConfig>({
id: 'scaleDistribution',
path: 'scaleDistribution',
name: 'Y axis scale',
category: ['Heatmap'],
name: t('heatmap.name-y-axis-scale', 'Y axis scale'),
category,
editor: ScaleDistributionEditor,
override: ScaleDistributionEditor,
defaultValue: { type: ScaleDistribution.Linear },
@@ -68,17 +70,17 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
} catch {}
}
let category = ['Heatmap'];
let category = [t('heatmap.category-heatmap', 'Heatmap')];
builder.addRadio({
path: 'calculate',
name: 'Calculate from data',
name: t('heatmap.name-calculate-from-data', 'Calculate from data'),
defaultValue: defaultOptions.calculate,
category,
settings: {
options: [
{ label: 'Yes', value: true },
{ label: 'No', value: false },
{ label: t('heatmap.calculate-from-data-options.label-yes', 'Yes'), value: true },
{ label: t('heatmap.calculate-from-data-options.label-no', 'No'), value: false },
],
},
});
@@ -87,26 +89,26 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
addHeatmapCalculationOptions('calculation.', builder, opts.calculation, category);
}
category = ['Y Axis'];
category = [t('heatmap.category-y-axis', 'Y Axis')];
builder
.addRadio({
path: 'yAxis.axisPlacement',
name: 'Placement',
name: t('heatmap.name-placement', 'Placement'),
defaultValue: defaultOptions.yAxis.axisPlacement ?? AxisPlacement.Left,
category,
settings: {
options: [
{ label: 'Left', value: AxisPlacement.Left },
{ label: 'Right', value: AxisPlacement.Right },
{ label: 'Hidden', value: AxisPlacement.Hidden },
{ label: t('heatmap.placement-options.label-left', 'Left'), value: AxisPlacement.Left },
{ label: t('heatmap.placement-options.label-right', 'Right'), value: AxisPlacement.Right },
{ label: t('heatmap.placement-options.label-hidden', 'Hidden'), value: AxisPlacement.Hidden },
],
},
})
.addUnitPicker({
category,
path: 'yAxis.unit',
name: 'Unit',
name: t('heatmap.name-unit', 'Unit'),
defaultValue: undefined,
settings: {
isClearable: true,
@@ -115,9 +117,9 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
.addNumberInput({
category,
path: 'yAxis.decimals',
name: 'Decimals',
name: t('heatmap.name-decimals', 'Decimals'),
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-decimals', 'Auto'),
},
});
@@ -126,17 +128,17 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder
.addNumberInput({
path: 'yAxis.min',
name: 'Min value',
name: t('heatmap.name-min-value', 'Min value'),
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-min-value', 'Auto'),
},
category,
})
.addTextInput({
path: 'yAxis.max',
name: 'Max value',
name: t('heatmap.name-max-value', 'Max value'),
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-max-value', 'Auto'),
},
category,
});
@@ -145,20 +147,20 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder
.addNumberInput({
path: 'yAxis.axisWidth',
name: 'Axis width',
name: t('heatmap.name-axis-width', 'Axis width'),
defaultValue: defaultOptions.yAxis.axisWidth,
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-axis-width', 'Auto'),
min: 5, // smaller should just be hidden
},
category,
})
.addTextInput({
path: 'yAxis.axisLabel',
name: 'Axis label',
name: t('heatmap.name-axis-label', 'Axis label'),
defaultValue: defaultOptions.yAxis.axisLabel,
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-axis-label', 'Auto'),
},
category,
});
@@ -166,44 +168,44 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
if (!opts.calculate) {
builder.addRadio({
path: 'rowsFrame.layout',
name: 'Tick alignment',
name: t('heatmap.name-tick-alignment', 'Tick alignment'),
defaultValue: defaultOptions.rowsFrame?.layout ?? HeatmapCellLayout.auto,
category,
settings: {
options: [
{ label: 'Auto', value: HeatmapCellLayout.auto },
{ label: 'Top (LE)', value: HeatmapCellLayout.le },
{ label: 'Middle', value: HeatmapCellLayout.unknown },
{ label: 'Bottom (GE)', value: HeatmapCellLayout.ge },
{ label: t('heatmap.tick-alignment-options.label-auto', 'Auto'), value: HeatmapCellLayout.auto },
{ label: t('heatmap.tick-alignment-options.label-top', 'Top (LE)'), value: HeatmapCellLayout.le },
{ label: t('heatmap.tick-alignment-options.label-middle', 'Middle'), value: HeatmapCellLayout.unknown },
{ label: t('heatmap.tick-alignment-options.label-bottom', 'Bottom (GE)'), value: HeatmapCellLayout.ge },
],
},
});
}
builder.addBooleanSwitch({
path: 'yAxis.reverse',
name: 'Reverse',
name: t('heatmap.name-reverse', 'Reverse'),
defaultValue: defaultOptions.yAxis.reverse === true,
category,
});
category = ['Colors'];
category = [t('heatmap.category-colors', 'Colors')];
builder.addRadio({
path: `color.mode`,
name: 'Mode',
name: t('heatmap.name-mode', 'Mode'),
defaultValue: defaultOptions.color.mode,
category,
settings: {
options: [
{ label: 'Scheme', value: HeatmapColorMode.Scheme },
{ label: 'Opacity', value: HeatmapColorMode.Opacity },
{ label: t('heatmap.mode-options.label-scheme', 'Scheme'), value: HeatmapColorMode.Scheme },
{ label: t('heatmap.mode-options.label-opacity', 'Opacity'), value: HeatmapColorMode.Opacity },
],
},
});
builder.addColorPicker({
path: `color.fill`,
name: 'Color',
name: t('heatmap.name-color', 'Color'),
defaultValue: defaultOptions.color.fill,
category,
showIf: (opts) => opts.color.mode === HeatmapColorMode.Opacity,
@@ -211,13 +213,13 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addRadio({
path: `color.scale`,
name: 'Scale',
name: t('heatmap.name-scale', 'Scale'),
defaultValue: defaultOptions.color.scale,
category,
settings: {
options: [
{ label: 'Exponential', value: HeatmapColorScale.Exponential },
{ label: 'Linear', value: HeatmapColorScale.Linear },
{ label: t('heatmap.scale-options.label-exponential', 'Exponential'), value: HeatmapColorScale.Exponential },
{ label: t('heatmap.scale-options.label-linear', 'Linear'), value: HeatmapColorScale.Linear },
],
},
showIf: (opts) => opts.color.mode === HeatmapColorMode.Opacity,
@@ -225,7 +227,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addSliderInput({
path: 'color.exponent',
name: 'Exponent',
name: t('heatmap.name-exponent', 'Exponent'),
defaultValue: defaultOptions.color.exponent,
category,
settings: {
@@ -239,7 +241,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addSelect({
path: `color.scheme`,
name: 'Scheme',
name: t('heatmap.name-scheme', 'Scheme'),
description: '',
defaultValue: defaultOptions.color.scheme,
category,
@@ -256,7 +258,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder
.addSliderInput({
path: 'color.steps',
name: 'Steps',
name: t('heatmap.name-steps', 'Steps'),
defaultValue: defaultOptions.color.steps,
category,
settings: {
@@ -267,7 +269,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
})
.addBooleanSwitch({
path: 'color.reverse',
name: 'Reverse',
name: t('heatmap.name-reverse', 'Reverse'),
defaultValue: defaultOptions.color.reverse,
category,
})
@@ -289,32 +291,32 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder
.addNumberInput({
path: 'color.min',
name: 'Start color scale from value',
name: t('heatmap.name-start-color-from-value', 'Start color scale from value'),
defaultValue: defaultOptions.color.min,
settings: {
placeholder: 'Auto (min)',
placeholder: t('heatmap.placeholder-start-color-from-value', 'Auto (min)'),
},
category,
})
.addNumberInput({
path: 'color.max',
name: 'End color scale at value',
name: t('heatmap.name-end-color-at-value', 'End color scale at value'),
defaultValue: defaultOptions.color.max,
settings: {
placeholder: 'Auto (max)',
placeholder: t('heatmap.placeholder-end-color-at-value', 'Auto (max)'),
},
category,
});
category = ['Cell display'];
category = [t('heatmap.category-cell-display', 'Cell display')];
if (!opts.calculate) {
builder.addTextInput({
path: 'rowsFrame.value',
name: 'Value name',
name: t('heatmap.name-value-name', 'Value name'),
defaultValue: defaultOptions.rowsFrame?.value,
settings: {
placeholder: 'Value',
placeholder: t('heatmap.placeholder-value-name', 'Value'),
},
category,
});
@@ -324,7 +326,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
.addUnitPicker({
category,
path: 'cellValues.unit',
name: 'Unit',
name: t('heatmap.name-unit', 'Unit'),
defaultValue: undefined,
settings: {
isClearable: true,
@@ -333,9 +335,9 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
.addNumberInput({
category,
path: 'cellValues.decimals',
name: 'Decimals',
name: t('heatmap.name-decimals', 'Decimals'),
settings: {
placeholder: 'Auto',
placeholder: t('heatmap.placeholder-decimals', 'Auto'),
},
});
@@ -354,7 +356,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
// },
// })
.addSliderInput({
name: 'Cell gap',
name: t('heatmap.name-cell-gap', 'Cell gap'),
path: 'cellGap',
defaultValue: defaultOptions.cellGap,
category,
@@ -365,19 +367,19 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
})
.addNumberInput({
path: 'filterValues.le',
name: 'Hide cells with values <=',
name: t('heatmap.name-hide-cells-lt', 'Hide cells with values <='),
defaultValue: defaultOptions.filterValues?.le,
settings: {
placeholder: 'None',
placeholder: t('heatmap.placeholder-hide-cells-lt', 'None'),
},
category,
})
.addNumberInput({
path: 'filterValues.ge',
name: 'Hide cells with values >=',
name: t('heatmap.name-hide-cells-gt', 'Hide cells with values >='),
defaultValue: defaultOptions.filterValues?.ge,
settings: {
placeholder: 'None',
placeholder: t('heatmap.placeholder-hide-cells-gt', 'None'),
},
category,
});
@@ -392,25 +394,25 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
// },
// })
category = ['Tooltip'];
category = [t('heatmap.category-tooltip', 'Tooltip')];
builder.addRadio({
path: 'tooltip.mode',
name: 'Tooltip mode',
name: t('heatmap.name-tooltip-mode', 'Tooltip mode'),
category,
defaultValue: TooltipDisplayMode.Single,
settings: {
options: [
{ value: TooltipDisplayMode.Single, label: 'Single' },
{ value: TooltipDisplayMode.Multi, label: 'All' },
{ value: TooltipDisplayMode.None, label: 'Hidden' },
{ value: TooltipDisplayMode.Single, label: t('heatmap.tooltip-mode-options.label-single', 'Single') },
{ value: TooltipDisplayMode.Multi, label: t('heatmap.tooltip-mode-options.label-all', 'All') },
{ value: TooltipDisplayMode.None, label: t('heatmap.tooltip-mode-options.label-hidden', 'Hidden') },
],
},
});
builder.addBooleanSwitch({
path: 'tooltip.yHistogram',
name: 'Show histogram (Y axis)',
name: t('heatmap.name-show-histogram', 'Show histogram (Y axis)'),
defaultValue: defaultOptions.tooltip.yHistogram,
category,
showIf: (opts) => opts.tooltip.mode === TooltipDisplayMode.Single,
@@ -418,7 +420,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addBooleanSwitch({
path: 'tooltip.showColorScale',
name: 'Show color scale',
name: t('heatmap.name-show-color-scale', 'Show color scale'),
defaultValue: defaultOptions.tooltip.showColorScale,
category,
showIf: (opts) => opts.tooltip.mode === TooltipDisplayMode.Single,
@@ -426,7 +428,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addNumberInput({
path: 'tooltip.maxWidth',
name: 'Max width',
name: t('heatmap.name-max-width', 'Max width'),
category,
settings: {
integer: true,
@@ -436,7 +438,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
builder.addNumberInput({
path: 'tooltip.maxHeight',
name: 'Max height',
name: t('heatmap.name-max-height', 'Max height'),
category,
defaultValue: undefined,
settings: {
@@ -447,18 +449,18 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
annotations?.some((df) => df.meta?.custom?.resultType === 'exemplar'),
});
category = ['Legend'];
category = [t('heatmap.category-legend', 'Legend')];
builder.addBooleanSwitch({
path: 'legend.show',
name: 'Show legend',
name: t('heatmap.name-show-legend', 'Show legend'),
defaultValue: defaultOptions.legend.show,
category,
});
category = ['Exemplars'];
category = [t('heatmap.category-exemplars', 'Exemplars')];
builder.addColorPicker({
path: 'exemplars.color',
name: 'Color',
name: t('heatmap.name-color', 'Color'),
defaultValue: defaultOptions.exemplars.color,
category,
showIf: (options: Options, data: DataFrame[] | undefined, annotations: DataFrame[] | undefined) =>
+18 -6
View File
@@ -6,7 +6,8 @@ import {
PanelPlugin,
histogramFieldInfo,
} from '@grafana/data';
import { commonOptionsBuilder, graphFieldOptions } from '@grafana/ui';
import { t } from '@grafana/i18n';
import { commonOptionsBuilder, getGraphFieldOptions } from '@grafana/ui';
import { StackingEditor } from '@grafana/ui/internal';
import { HistogramPanel } from './HistogramPanel';
@@ -18,11 +19,13 @@ import { originalDataHasHistogram } from './utils';
export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
.setPanelChangeHandler(changeToHistogramPanelMigrationHandler)
.setPanelOptions((builder) => {
const category = [t('histogram.category-histogram', 'Histogram')];
builder
.addCustomEditor({
id: '__calc__',
path: '__calc__',
name: 'Values',
category,
description: 'Showing frequencies that are calculated in the query',
editor: () => null, // empty editor
showIf: (opts, data) => originalDataHasHistogram(data),
@@ -30,6 +33,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
.addNumberInput({
path: 'bucketCount',
name: histogramFieldInfo.bucketCount.name,
category,
description: histogramFieldInfo.bucketCount.description,
settings: {
placeholder: `Default: ${defaultOptions.bucketCount}`,
@@ -40,6 +44,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
.addNumberInput({
path: 'bucketSize',
name: histogramFieldInfo.bucketSize.name,
category,
description: histogramFieldInfo.bucketSize.description,
settings: {
placeholder: 'Auto',
@@ -51,6 +56,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
.addNumberInput({
path: 'bucketOffset',
name: histogramFieldInfo.bucketOffset.name,
category,
description: histogramFieldInfo.bucketOffset.description,
settings: {
placeholder: `Default: ${defaultOptions.bucketOffset}`,
@@ -61,6 +67,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
.addBooleanSwitch({
path: 'combine',
name: histogramFieldInfo.combine.name,
category,
description: histogramFieldInfo.combine.description,
defaultValue: defaultOptions.combine,
showIf: (opts, data) => !originalDataHasHistogram(data),
@@ -89,13 +96,15 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
},
useCustomConfig: (builder) => {
const cfg = defaultFieldConfig;
const graphFieldOptions = getGraphFieldOptions();
const category = [t('histogram.category-histogram', 'Histogram')];
builder
.addCustomEditor({
id: 'stacking',
path: 'stacking',
name: 'Stacking',
category: ['Histogram'],
name: t('histogram.name-stacking', 'Stacking'),
category,
defaultValue: defaultHistogramConfig.stacking,
editor: StackingEditor,
override: StackingEditor,
@@ -108,7 +117,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
})
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('histogram.name-line-width', 'Line width'),
category,
defaultValue: cfg.lineWidth,
settings: {
min: 0,
@@ -118,7 +128,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('histogram.name-fill-opacity', 'Fill opacity'),
category,
defaultValue: cfg.fillOpacity,
settings: {
min: 0,
@@ -128,7 +139,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(HistogramPanel)
})
.addRadio({
path: 'gradientMode',
name: 'Gradient mode',
name: t('histogram.name-gradient-mode', 'Gradient mode'),
category,
defaultValue: graphFieldOptions.fillGradient[0].value,
settings: {
options: graphFieldOptions.fillGradient,
+40 -17
View File
@@ -1,4 +1,5 @@
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
import { t } from '@grafana/i18n';
import { LogsPanel } from './LogsPanel';
import { Options } from './panelcfg.gen';
@@ -6,63 +7,84 @@ import { LogsPanelSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin<Options>(LogsPanel)
.setPanelOptions((builder) => {
const category = [t('logs-new.category-logs', 'Logs')];
builder
.addBooleanSwitch({
path: 'showTime',
name: 'Time',
name: t('logs-new.name-time', 'Time'),
category,
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'wrapLogMessage',
name: 'Wrap lines',
name: t('logs-new.name-wrap-lines', 'Wrap lines'),
category,
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'syntaxHighlighting',
name: 'Enable syntax highlighting',
description: 'Use a predefined syntax coloring grammar to highlight relevant parts of the log lines',
name: t('logs-new.name-syntax-highlighting', 'Enable syntax highlighting'),
category,
description: t(
'logs-new.description-syntax-highlighting',
'Use a predefined syntax coloring grammar to highlight relevant parts of the log lines'
),
defaultValue: true,
})
.addBooleanSwitch({
path: 'enableLogDetails',
name: 'Enable log details',
name: t('logs-new.name-enable-log-details', 'Enable log details'),
category,
description: '',
defaultValue: true,
})
.addBooleanSwitch({
path: 'showControls',
name: 'Show controls',
description: 'Display controls to jump to the last or first log line, and filters by log level',
name: t('logs-new.name-show-controls', 'Show controls'),
category,
description: t(
'logs-new.description-show-controls',
'Display controls to jump to the last or first log line, and filters by log level'
),
defaultValue: false,
})
.addBooleanSwitch({
path: 'enableInfiniteScrolling',
name: 'Enable infinite scrolling',
description: 'Experimental. Request more results by scrolling to the bottom of the logs list.',
name: t('logs-new.name-infinite-scrolling', 'Enable infinite scrolling'),
category,
description: t(
'logs-new.description-infinite-scrolling',
'Experimental. Request more results by scrolling to the bottom of the logs list.'
),
defaultValue: false,
})
.addRadio({
path: 'dedupStrategy',
name: 'Deduplication',
name: t('logs-new.name-deduplication', 'Deduplication'),
category,
description: '',
settings: {
options: [
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
{
value: LogsDedupStrategy.none,
label: t('logs-new.deduplication-options.label-none', 'None'),
description: LogsDedupDescription[LogsDedupStrategy.none],
},
{
value: LogsDedupStrategy.exact,
label: 'Exact',
label: t('logs-new.deduplication-options.label-exact', 'Exact'),
description: LogsDedupDescription[LogsDedupStrategy.exact],
},
{
value: LogsDedupStrategy.numbers,
label: 'Numbers',
label: t('logs-new.deduplication-options.label-numbers', 'Numbers'),
description: LogsDedupDescription[LogsDedupStrategy.numbers],
},
{
value: LogsDedupStrategy.signature,
label: 'Signature',
label: t('logs-new.deduplication-options.label-signature', 'Signature'),
description: LogsDedupDescription[LogsDedupStrategy.signature],
},
],
@@ -71,12 +93,13 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
})
.addRadio({
path: 'sortOrder',
name: 'Order',
name: t('logs-new.name-order', 'Order'),
category,
description: '',
settings: {
options: [
{ value: LogsSortOrder.Descending, label: 'Newest first' },
{ value: LogsSortOrder.Ascending, label: 'Oldest first' },
{ value: LogsSortOrder.Descending, label: t('logs-new.order-options.label-newest-first', 'Newest first') },
{ value: LogsSortOrder.Ascending, label: t('logs-new.order-options.label-oldest-first', 'Oldest first') },
],
},
defaultValue: LogsSortOrder.Descending,
+50 -23
View File
@@ -1,4 +1,5 @@
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { LogsPanel } from './LogsPanel';
@@ -7,9 +8,11 @@ import { LogsPanelSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin<Options>(LogsPanel)
.setPanelOptions((builder) => {
const category = [t('logs.category-logs', 'Logs')];
builder.addBooleanSwitch({
path: 'showTime',
name: 'Time',
name: t('logs.name-time', 'Time'),
category,
description: '',
defaultValue: false,
});
@@ -18,13 +21,15 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
builder
.addBooleanSwitch({
path: 'showLabels',
name: 'Unique labels',
name: t('logs.name-unique-labels', 'Unique labels'),
category,
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'showCommonLabels',
name: 'Common labels',
name: t('logs.name-common-labels', 'Common labels'),
category,
description: '',
defaultValue: false,
});
@@ -32,7 +37,8 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
builder.addBooleanSwitch({
path: 'wrapLogMessage',
name: 'Wrap lines',
name: t('logs.name-wrap-lines', 'Wrap lines'),
category,
description: '',
defaultValue: false,
});
@@ -40,13 +46,18 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
if (config.featureToggles.newLogsPanel) {
builder.addBooleanSwitch({
path: 'syntaxHighlighting',
name: 'Enable syntax highlighting',
description: 'Use a predefined syntax coloring grammar to highlight relevant parts of the log lines',
name: t('logs.name-enable-syntax-highlighting', 'Enable syntax highlighting'),
category,
description: t(
'logs.description-enable-syntax-highlighting',
'Use a predefined syntax coloring grammar to highlight relevant parts of the log lines'
),
});
} else {
builder.addBooleanSwitch({
path: 'prettifyLogMessage',
name: 'Prettify JSON',
name: t('logs.name-prettify-json', 'Prettify JSON'),
category,
description: '',
defaultValue: false,
});
@@ -55,14 +66,19 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
builder
.addBooleanSwitch({
path: 'enableLogDetails',
name: 'Enable log details',
name: t('logs.name-enable-log-details', 'Enable log details'),
category,
description: '',
defaultValue: true,
})
.addBooleanSwitch({
path: 'enableInfiniteScrolling',
name: 'Enable infinite scrolling',
description: 'Experimental. Request more results by scrolling to the bottom of the logs list.',
name: t('logs.name-enable-infinite-scrolling', 'Enable infinite scrolling'),
category,
description: t(
'logs.description-enable-infinite-scrolling',
'Experimental. Request more results by scrolling to the bottom of the logs list.'
),
defaultValue: false,
});
@@ -70,20 +86,25 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
builder
.addBooleanSwitch({
path: 'showControls',
name: 'Show controls',
description: 'Display controls to jump to the last or first log line, and filters by log level',
name: t('logs.name-show-controls', 'Show controls'),
category,
description: t(
'logs.description-show-controls',
'Display controls to jump to the last or first log line, and filters by log level'
),
defaultValue: false,
})
.addRadio({
path: 'fontSize',
name: 'Font size',
name: t('logs.name-font-size', 'Font size'),
category,
description: '',
settings: {
options: [
{ value: 'default', label: 'Default' },
{ value: 'default', label: t('logs.font-size-options.label-default', 'Default') },
{
value: 'small',
label: 'Small',
label: t('logs.font-size-options.label-small', 'Small'),
},
],
},
@@ -93,24 +114,29 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
builder
.addRadio({
path: 'dedupStrategy',
name: 'Deduplication',
name: t('logs.name-deduplication', 'Deduplication'),
category,
description: '',
settings: {
options: [
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
{
value: LogsDedupStrategy.none,
label: t('logs.deduplication-options.label-none', 'None'),
description: LogsDedupDescription[LogsDedupStrategy.none],
},
{
value: LogsDedupStrategy.exact,
label: 'Exact',
label: t('logs.deduplication-options.label-exact', 'Exact'),
description: LogsDedupDescription[LogsDedupStrategy.exact],
},
{
value: LogsDedupStrategy.numbers,
label: 'Numbers',
label: t('logs.deduplication-options.label-numbers', 'Numbers'),
description: LogsDedupDescription[LogsDedupStrategy.numbers],
},
{
value: LogsDedupStrategy.signature,
label: 'Signature',
label: t('logs.deduplication-options.label-signature', 'Signature'),
description: LogsDedupDescription[LogsDedupStrategy.signature],
},
],
@@ -119,12 +145,13 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
})
.addRadio({
path: 'sortOrder',
name: 'Order',
name: t('logs.name-order', 'Order'),
category,
description: '',
settings: {
options: [
{ value: LogsSortOrder.Descending, label: 'Newest first' },
{ value: LogsSortOrder.Ascending, label: 'Oldest first' },
{ value: LogsSortOrder.Descending, label: t('logs.order-options.label-newest-first', 'Newest first') },
{ value: LogsSortOrder.Ascending, label: t('logs.order-options.label-oldest-first', 'Oldest first') },
],
},
defaultValue: LogsSortOrder.Descending,
+11 -4
View File
@@ -1,15 +1,18 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { NewsPanel } from './NewsPanel';
import { DEFAULT_FEED_URL } from './constants';
import { Options, defaultOptions } from './panelcfg.gen';
export const plugin = new PanelPlugin<Options>(NewsPanel).setPanelOptions((builder) => {
const category = [t('news.category-news', 'News')];
builder
.addTextInput({
path: 'feedUrl',
name: 'URL',
description: 'Supports RSS and Atom feeds',
name: t('news.name-url', 'URL'),
category,
description: t('news.description-url', 'Supports RSS and Atom feeds'),
settings: {
placeholder: DEFAULT_FEED_URL,
},
@@ -17,8 +20,12 @@ export const plugin = new PanelPlugin<Options>(NewsPanel).setPanelOptions((build
})
.addBooleanSwitch({
path: 'showImage',
name: 'Show image',
description: 'Controls if the news item social (og:image) image is shown above text content',
name: t('news.name-show-image', 'Show image'),
category,
description: t(
'news.description-show-image',
'Controls if the news item social (og:image) image is shown above text content'
),
defaultValue: defaultOptions.showImage,
});
});
+38 -14
View File
@@ -1,4 +1,5 @@
import { FieldConfigProperty, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { NodeGraphPanel } from './NodeGraphPanel';
import { ArcOptionsEditor } from './editor/ArcOptionsEditor';
@@ -10,43 +11,66 @@ export const plugin = new PanelPlugin<NodeGraphOptions>(NodeGraphPanel)
disableStandardOptions: Object.values(FieldConfigProperty).filter((v) => v !== FieldConfigProperty.Links),
})
.setPanelOptions((builder, context) => {
const category = [t('node-graph.category-node-graph', 'Node graph')];
builder.addSelect({
name: 'Zoom mode',
name: t('node-graph.name-zoom-mode', 'Zoom mode'),
category,
path: 'zoomMode',
defaultValue: 'cooperative',
settings: {
options: [
{ value: 'cooperative', label: 'Cooperative', description: 'Lets you scroll the page normally' },
{ value: 'greedy', label: 'Greedy', description: 'Reacts to all zoom gestures' },
{
value: 'cooperative',
label: t('node-graph.zoom-mode-options.label-cooperative', 'Cooperative'),
description: t('node-graph.zoom-mode-options.description-cooperative', 'Lets you scroll the page normally'),
},
{
value: 'greedy',
label: t('node-graph.zoom-mode-options.label-greedy', 'Greedy'),
description: t('node-graph.zoom-mode-options.description-greedy', 'Reacts to all zoom gestures'),
},
],
},
});
builder.addSelect({
name: 'Layout algorithm',
name: t('node-graph.name-layout-algorithm', 'Layout algorithm'),
category,
path: 'layoutAlgorithm',
defaultValue: LayoutAlgorithm.Layered,
settings: {
options: [
{ label: 'Layered', value: LayoutAlgorithm.Layered, description: 'Use a layered layout' },
{ label: 'Force', value: LayoutAlgorithm.Force, description: 'Use a force-directed layout' },
{ label: 'Grid', value: LayoutAlgorithm.Grid, description: 'Use a grid layout' },
{
label: t('node-graph.layout-algorithm-options.label-layered', 'Layered'),
value: LayoutAlgorithm.Layered,
description: t('node-graph.layout-algorithm-options.description-layered', 'Use a layered layout'),
},
{
label: t('node-graph.layout-algorithm-options.label-force', 'Force'),
value: LayoutAlgorithm.Force,
description: t('node-graph.layout-algorithm-options.description-force', 'Use a force-directed layout'),
},
{
label: t('node-graph.layout-algorithm-options.label-grid', 'Grid'),
value: LayoutAlgorithm.Grid,
description: t('node-graph.layout-algorithm-options.description-grid', 'Use a grid layout'),
},
],
},
});
builder.addNestedOptions({
category: ['Nodes'],
category: [t('node-graph.category-nodes', 'Nodes')],
path: 'nodes',
build: (builder) => {
builder.addUnitPicker({
name: 'Main stat unit',
name: t('node-graph.name-main-stat-unit', 'Main stat unit'),
path: 'mainStatUnit',
});
builder.addUnitPicker({
name: 'Secondary stat unit',
name: t('node-graph.name-secondary-stat-unit', 'Secondary stat unit'),
path: 'secondaryStatUnit',
});
builder.addCustomEditor({
name: 'Arc sections',
name: t('node-graph.name-arc-sections', 'Arc sections'),
path: 'arcs',
id: 'arcs',
editor: ArcOptionsEditor,
@@ -54,15 +78,15 @@ export const plugin = new PanelPlugin<NodeGraphOptions>(NodeGraphPanel)
},
});
builder.addNestedOptions({
category: ['Edges'],
category: [t('node-graph.category-edges', 'Edges')],
path: 'edges',
build: (builder) => {
builder.addUnitPicker({
name: 'Main stat unit',
name: t('node-graph.name-main-stat-unit', 'Main stat unit'),
path: 'mainStatUnit',
});
builder.addUnitPicker({
name: 'Secondary stat unit',
name: t('node-graph.name-secondary-stat-unit', 'Secondary stat unit'),
path: 'secondaryStatUnit',
});
},
+18 -13
View File
@@ -1,4 +1,5 @@
import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { commonOptionsBuilder } from '@grafana/ui';
import { optsWithHideZeros } from '@grafana/ui/internal';
@@ -31,28 +32,32 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(PieChartPanel)
})
.setPanelOptions((builder) => {
addStandardDataReduceOptions(builder);
const category = [t('piechart.category-pie-chart', 'Pie chart')];
const legendCategory = [t('piechart.category-legend', 'Legend')];
builder
.addRadio({
name: 'Piechart type',
description: 'How the piechart should be rendered',
name: t('piechart.name-pie-chart-type', 'Pie chart type'),
category,
description: t('piechart.description-pie-chart-type', 'How the pie chart should be rendered'),
path: 'pieType',
settings: {
options: [
{ value: PieChartType.Pie, label: 'Pie' },
{ value: PieChartType.Donut, label: 'Donut' },
{ value: PieChartType.Pie, label: t('piechart.pie-chart-type-options.label-pie', 'Pie') },
{ value: PieChartType.Donut, label: t('piechart.pie-chart-type-options.label-donut', 'Donut') },
],
},
defaultValue: PieChartType.Pie,
})
.addMultiSelect({
name: 'Labels',
name: t('piechart.name-labels', 'Labels'),
category,
path: 'displayLabels',
description: 'Select the labels to be displayed in the pie chart',
description: t('piechart.description-labels', 'Select the labels to be displayed in the pie chart'),
settings: {
options: [
{ value: PieChartLabels.Percent, label: 'Percent' },
{ value: PieChartLabels.Name, label: 'Name' },
{ value: PieChartLabels.Value, label: 'Value' },
{ value: PieChartLabels.Percent, label: t('piechart.labels-options.label-percent', 'Percent') },
{ value: PieChartLabels.Name, label: t('piechart.labels-options.label-name', 'Name') },
{ value: PieChartLabels.Value, label: t('piechart.labels-options.label-value', 'Value') },
],
},
});
@@ -61,13 +66,13 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(PieChartPanel)
commonOptionsBuilder.addLegendOptions(builder, false);
builder.addMultiSelect({
name: 'Legend values',
name: t('piechart.name-legend-values', 'Legend values'),
path: 'legend.values',
category: ['Legend'],
category: legendCategory,
settings: {
options: [
{ value: PieChartLegendValues.Percent, label: 'Percent' },
{ value: PieChartLegendValues.Value, label: 'Value' },
{ value: PieChartLegendValues.Percent, label: t('piechart.legend-values-options.label-percent', 'Percent') },
{ value: PieChartLegendValues.Value, label: t('piechart.legend-values-options.label-value', 'Value') },
],
},
showIf: (c) => c.legend.showLegend !== false,
+40 -18
View File
@@ -8,22 +8,26 @@ import {
ReducerID,
standardEditorsRegistry,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { SingleStatBaseOptions, VizOrientation } from '@grafana/schema';
export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
builder: PanelOptionsEditorBuilder<T>,
includeFieldMatcher = true
) {
const valueOptionsCategory = ['Value options'];
const valueOptionsCategory = [t('stat.add-standard-data-reduce-options.category-value-options', 'Value options')];
builder.addRadio({
path: 'reduceOptions.values',
name: 'Show',
description: 'Calculate a single value per column or series or show each row',
name: t('stat.add-standard-data-reduce-options.name-show', 'Show'),
description: t(
'stat.add-standard-data-reduce-options.description-show',
'Calculate a single value per column or series or show each row'
),
settings: {
options: [
{ value: false, label: 'Calculate' },
{ value: true, label: 'All values' },
{ value: false, label: t('stat.add-standard-data-reduce-options.show-options.label-calculate', 'Calculate') },
{ value: true, label: t('stat.add-standard-data-reduce-options.show-options.label-all-values', 'All values') },
],
},
category: valueOptionsCategory,
@@ -32,8 +36,8 @@ export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
builder.addNumberInput({
path: 'reduceOptions.limit',
name: 'Limit',
description: 'Max number of rows to display',
name: t('stat.add-standard-data-reduce-options.name-limit', 'Limit'),
description: t('stat.add-standard-data-reduce-options.description-limit', 'Max number of rows to display'),
category: valueOptionsCategory,
settings: {
placeholder: '25',
@@ -47,8 +51,11 @@ export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
builder.addCustomEditor({
id: 'reduceOptions.calcs',
path: 'reduceOptions.calcs',
name: 'Calculation',
description: 'Choose a reducer function / calculation',
name: t('stat.add-standard-data-reduce-options.name-calculation', 'Calculation'),
description: t(
'stat.add-standard-data-reduce-options.description-calculation',
'Choose a reducer function / calculation'
),
category: valueOptionsCategory,
editor: standardEditorsRegistry.get('stats-picker').editor,
// TODO: Get ReducerID from generated schema one day?
@@ -60,16 +67,25 @@ export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
if (includeFieldMatcher) {
builder.addSelect({
path: 'reduceOptions.fields',
name: 'Fields',
description: 'Select the fields that should be included in the panel',
name: t('stat.add-standard-data-reduce-options.name-fields', 'Fields'),
description: t(
'stat.add-standard-data-reduce-options.description-fields',
'Select the fields that should be included in the panel'
),
category: valueOptionsCategory,
settings: {
allowCustomValue: true,
options: [],
getOptions: async (context: FieldOverrideContext) => {
const options = [
{ value: '', label: 'Numeric Fields' },
{ value: '/.*/', label: 'All Fields' },
{
value: '',
label: t('stat.add-standard-data-reduce-options.fields-options.label-numeric-fields', 'Numeric Fields'),
},
{
value: '/.*/',
label: t('stat.add-standard-data-reduce-options.fields-options.label-all-fields', 'All Fields'),
},
];
if (context && context.data) {
for (const frame of context.data) {
@@ -94,14 +110,20 @@ export function addOrientationOption<T extends SingleStatBaseOptions>(
) {
builder.addRadio({
path: 'orientation',
name: 'Orientation',
description: 'Layout orientation',
name: t('stat.add-orientation-option.name-orientation', 'Orientation'),
description: t('stat.add-orientation-option.description-orientation', 'Layout orientation'),
category,
settings: {
options: [
{ value: VizOrientation.Auto, label: 'Auto' },
{ value: VizOrientation.Horizontal, label: 'Horizontal' },
{ value: VizOrientation.Vertical, label: 'Vertical' },
{ value: VizOrientation.Auto, label: t('stat.add-orientation-option.orientation-options.label-auto', 'Auto') },
{
value: VizOrientation.Horizontal,
label: t('stat.add-orientation-option.orientation-options.label-horizontal', 'Horizontal'),
},
{
value: VizOrientation.Vertical,
label: t('stat.add-orientation-option.orientation-options.label-vertical', 'Vertical'),
},
],
},
defaultValue: VizOrientation.Auto,
+47 -28
View File
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import {
BigValueColorMode,
BigValueGraphMode,
@@ -17,7 +18,7 @@ import { StatSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin<Options>(StatPanel)
.useFieldConfig()
.setPanelOptions((builder) => {
const mainCategory = ['Stat styles'];
const mainCategory = [t('stat.category-stat-styles', 'Stat styles')];
addStandardDataReduceOptions(builder);
addOrientationOption(builder, mainCategory);
@@ -26,28 +27,31 @@ export const plugin = new PanelPlugin<Options>(StatPanel)
builder
.addSelect({
path: 'textMode',
name: 'Text mode',
description: 'Control if name and value is displayed or just name',
name: t('stat.name-text-mode', 'Text mode'),
description: t('stat.description-text-mode', 'Control if name and value is displayed or just name'),
category: mainCategory,
settings: {
options: [
{ value: BigValueTextMode.Auto, label: 'Auto' },
{ value: BigValueTextMode.Value, label: 'Value' },
{ value: BigValueTextMode.ValueAndName, label: 'Value and name' },
{ value: BigValueTextMode.Name, label: 'Name' },
{ value: BigValueTextMode.None, label: 'None' },
{ value: BigValueTextMode.Auto, label: t('stat.text-mode-options.label-auto', 'Auto') },
{ value: BigValueTextMode.Value, label: t('stat.text-mode-options.label-value', 'Value') },
{
value: BigValueTextMode.ValueAndName,
label: t('stat.text-mode-options.label-value-and-name', 'Value and name'),
},
{ value: BigValueTextMode.Name, label: t('stat.text-mode-options.label-name', 'Name') },
{ value: BigValueTextMode.None, label: t('stat.text-mode-options.label-none', 'None') },
],
},
defaultValue: defaultOptions.textMode,
})
.addRadio({
path: 'wideLayout',
name: 'Wide layout',
name: t('stat.name-wide-layout', 'Wide layout'),
category: mainCategory,
settings: {
options: [
{ value: true, label: 'On' },
{ value: false, label: 'Off' },
{ value: true, label: t('stat.wide-layout-options.label-on', 'On') },
{ value: false, label: t('stat.wide-layout-options.label-off', 'Off') },
],
},
defaultValue: defaultOptions.wideLayout,
@@ -57,60 +61,75 @@ export const plugin = new PanelPlugin<Options>(StatPanel)
builder
.addSelect({
path: 'colorMode',
name: 'Color mode',
name: t('stat.name-color-modcolor-mode-options.label', 'Color mode'),
defaultValue: BigValueColorMode.Value,
category: mainCategory,
settings: {
options: [
{ value: BigValueColorMode.None, label: 'None' },
{ value: BigValueColorMode.Value, label: 'Value' },
{ value: BigValueColorMode.Background, label: 'Background Gradient' },
{ value: BigValueColorMode.BackgroundSolid, label: 'Background Solid' },
{ value: BigValueColorMode.None, label: t('stat.color-mode-options.label-none', 'None') },
{ value: BigValueColorMode.Value, label: t('stat.color-mode-options.label-value', 'Value') },
{
value: BigValueColorMode.Background,
label: t('stat.color-mode-options.label-background-gradient', 'Background Gradient'),
},
{
value: BigValueColorMode.BackgroundSolid,
label: t('stat.color-mode-options.label-background-solid', 'Background Solid'),
},
],
},
})
.addRadio({
path: 'graphMode',
name: 'Graph mode',
description: 'Stat panel graph / sparkline mode',
name: t('stat.name-graph-mode', 'Graph mode'),
description: t('stat.description-graph-mode', 'Stat panel graph / sparkline mode'),
category: mainCategory,
defaultValue: defaultOptions.graphMode,
settings: {
options: [
{ value: BigValueGraphMode.None, label: 'None' },
{ value: BigValueGraphMode.Area, label: 'Area' },
{ value: BigValueGraphMode.None, label: t('stat.graph-mode.options.label-none', 'None') },
{ value: BigValueGraphMode.Area, label: t('stat.graph-mode.options.label-area', 'Area') },
],
},
})
.addRadio({
path: 'justifyMode',
name: 'Text alignment',
name: t('stat.name-text-alignment', 'Text alignment'),
defaultValue: defaultOptions.justifyMode,
category: mainCategory,
settings: {
options: [
{ value: BigValueJustifyMode.Auto, label: 'Auto' },
{ value: BigValueJustifyMode.Center, label: 'Center' },
{ value: BigValueJustifyMode.Auto, label: t('stat.text-alignment-options.label-auto', 'Auto') },
{ value: BigValueJustifyMode.Center, label: t('stat.text-alignment-options.label-center', 'Center') },
],
},
})
.addBooleanSwitch({
path: 'showPercentChange',
name: 'Show percent change',
name: t('stat.name-show-percent-change', 'Show percent change'),
defaultValue: defaultOptions.showPercentChange,
category: mainCategory,
showIf: (config) => !config.reduceOptions.values,
})
.addSelect({
path: 'percentChangeColorMode',
name: 'Percent change color mode',
name: t('stat.percent-change-color-mode', 'Percent change color mode'),
defaultValue: defaultOptions.percentChangeColorMode,
category: mainCategory,
settings: {
options: [
{ value: PercentChangeColorMode.Standard, label: 'Standard' },
{ value: PercentChangeColorMode.Inverted, label: 'Inverted' },
{ value: PercentChangeColorMode.SameAsValue, label: 'Same as Value' },
{
value: PercentChangeColorMode.Standard,
label: t('stat.percent-change-color-mode-options.label-standard', 'Standard'),
},
{
value: PercentChangeColorMode.Inverted,
label: t('stat.percent-change-color-mode-options.label-inverted', 'Inverted'),
},
{
value: PercentChangeColorMode.SameAsValue,
label: t('stat.percent-change-color-mode-options.label-same-as-value', 'Same as Value'),
},
],
},
showIf: (config) => config.showPercentChange,
@@ -5,6 +5,7 @@ import {
identityOverrideProcessor,
PanelPlugin,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { AxisPlacement, VisibilityMode } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
@@ -39,10 +40,12 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
},
},
useCustomConfig: (builder) => {
const category = [t('state-timeline.category-state-timeline', 'State timeline')];
builder
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('state-timeline.name-line-width', 'Line width'),
category,
defaultValue: defaultFieldConfig.lineWidth,
settings: {
min: 0,
@@ -52,7 +55,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('state-timeline.name-fill-opacity', 'Fill opacity'),
category,
defaultValue: defaultFieldConfig.fillOpacity,
settings: {
min: 0,
@@ -63,7 +67,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
.addCustomEditor<NullEditorSettings, boolean>({
id: 'spanNulls',
path: 'spanNulls',
name: 'Connect null values',
name: t('state-timeline.name-connect-null-values', 'Connect null values'),
category,
defaultValue: false,
editor: SpanNullsEditor,
override: SpanNullsEditor,
@@ -74,7 +79,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
.addCustomEditor<NullEditorSettings, boolean>({
id: 'insertNulls',
path: 'insertNulls',
name: 'Disconnect values',
name: t('state-timeline.name-disconnect-values', 'Disconnect values'),
category,
defaultValue: false,
editor: InsertNullsEditor,
override: InsertNullsEditor,
@@ -92,39 +98,44 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
},
})
.setPanelOptions((builder) => {
const category = [t('state-timeline.category-state-timeline', 'State timeline')];
builder
.addBooleanSwitch({
path: 'mergeValues',
name: 'Merge equal consecutive values',
name: t('state-timeline.name-merge-equal-consecutive-values', 'Merge equal consecutive values'),
category,
defaultValue: defaultOptions.mergeValues,
})
.addRadio({
path: 'showValue',
name: 'Show values',
name: t('state-timeline.name-show-values', 'Show values'),
category,
settings: {
options: [
{ value: VisibilityMode.Auto, label: 'Auto' },
{ value: VisibilityMode.Always, label: 'Always' },
{ value: VisibilityMode.Never, label: 'Never' },
{ value: VisibilityMode.Auto, label: t('state-timeline.show-values-options.label-auto', 'Auto') },
{ value: VisibilityMode.Always, label: t('state-timeline.show-values-options.label-always', 'Always') },
{ value: VisibilityMode.Never, label: t('state-timeline.show-values-options.label-never', 'Never') },
],
},
defaultValue: defaultOptions.showValue,
})
.addRadio({
path: 'alignValue',
name: 'Align values',
name: t('state-timeline.name-align-values', 'Align values'),
category,
settings: {
options: [
{ value: 'left', label: 'Left' },
{ value: 'center', label: 'Center' },
{ value: 'right', label: 'Right' },
{ value: 'left', label: t('state-timeline.align-values-options.label-left', 'Left') },
{ value: 'center', label: t('state-timeline.align-values-options.label-center', 'Center') },
{ value: 'right', label: t('state-timeline.align-values-options.label-right', 'Right') },
],
},
defaultValue: defaultOptions.alignValue,
})
.addSliderInput({
path: 'rowHeight',
name: 'Row height',
name: t('state-timeline.name-row-height', 'Row height'),
category,
settings: {
min: 0,
max: 1,
@@ -134,7 +145,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StateTimelinePanel)
})
.addNumberInput({
path: 'perPage',
name: 'Page size (enable pagination)',
name: t('state-timeline.name-page-size', 'Page size (enable pagination)'),
category,
settings: {
min: 1,
step: 1,
@@ -1,4 +1,5 @@
import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { AxisPlacement, VisibilityMode } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
@@ -27,10 +28,12 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StatusHistoryPanel)
},
},
useCustomConfig: (builder) => {
const category = [t('status-history.category-status-history', 'Status history')];
builder
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('status-history.name-line-width', 'Line width'),
category,
defaultValue: defaultFieldConfig.lineWidth,
settings: {
min: 0,
@@ -40,7 +43,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StatusHistoryPanel)
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('status-history.name-fill-opacity', 'Fill opacity'),
category,
defaultValue: defaultFieldConfig.fillOpacity,
settings: {
min: 0,
@@ -58,22 +62,25 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StatusHistoryPanel)
},
})
.setPanelOptions((builder) => {
const category = [t('status-history.category-status-history', 'Status history')];
builder
.addRadio({
path: 'showValue',
name: 'Show values',
name: t('status-history.name-show-values', 'Show values'),
category,
settings: {
options: [
{ value: VisibilityMode.Auto, label: 'Auto' },
{ value: VisibilityMode.Always, label: 'Always' },
{ value: VisibilityMode.Never, label: 'Never' },
{ value: VisibilityMode.Auto, label: t('status-history.show-values-options.label-auto', 'Auto') },
{ value: VisibilityMode.Always, label: t('status-history.show-values-options.label-always', 'Always') },
{ value: VisibilityMode.Never, label: t('status-history.show-values-options.label-never', 'Never') },
],
},
defaultValue: VisibilityMode.Auto,
})
.addSliderInput({
path: 'rowHeight',
name: 'Row height',
name: t('status-history.name-row-height', 'Row height'),
category,
defaultValue: 0.9,
settings: {
min: 0,
@@ -83,7 +90,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StatusHistoryPanel)
})
.addSliderInput({
path: 'colWidth',
name: 'Column width',
name: t('status-history.name-column-width', 'Column width'),
category,
defaultValue: 0.9,
settings: {
min: 0,
@@ -93,7 +101,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(StatusHistoryPanel)
})
.addNumberInput({
path: 'perPage',
name: 'Page size (enable pagination)',
name: t('status-history.name-page-size', 'Page size (enable pagination)'),
category,
settings: {
min: 1,
step: 1,
+46 -36
View File
@@ -8,6 +8,7 @@ import {
identityOverrideProcessor,
FieldConfigProperty,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { TableCellOptions, TableCellDisplayMode, defaultTableFieldOptions, TableCellHeight } from '@grafana/schema';
import { PaginationEditor } from './PaginationEditor';
@@ -17,9 +18,6 @@ import { tableMigrationHandler, tablePanelChangedHandler } from './migrations';
import { Options, defaultOptions, FieldConfig } from './panelcfg.gen';
import { TableSuggestionsSupplier } from './suggestions';
const footerCategory = 'Table footer';
const cellCategory = ['Cell options'];
export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.setPanelChangeHandler(tablePanelChangedHandler)
.setMigrationHandler(tableMigrationHandler)
@@ -30,11 +28,14 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
},
},
useCustomConfig: (builder) => {
const category = [t('table.category-table', 'Table')];
const cellCategory = [t('table.category-cell-options', 'Cell options')];
builder
.addNumberInput({
path: 'minWidth',
name: 'Minimum column width',
description: 'The minimum width for column auto resizing',
name: t('table.name-min-column-width', 'Minimum column width'),
category,
description: t('table.description-min-column-width', 'The minimum width for column auto resizing'),
settings: {
placeholder: '150',
min: 50,
@@ -45,9 +46,10 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addNumberInput({
path: 'width',
name: 'Column width',
name: t('table.name-column-width', 'Column width'),
category,
settings: {
placeholder: 'auto',
placeholder: t('table.placeholder-column-width', 'auto'),
min: 20,
max: 300,
},
@@ -56,13 +58,14 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addRadio({
path: 'align',
name: 'Column alignment',
name: t('table.name-column-alignment', 'Column alignment'),
category,
settings: {
options: [
{ label: 'Auto', value: 'auto' },
{ label: 'Left', value: 'left' },
{ label: 'Center', value: 'center' },
{ label: 'Right', value: 'right' },
{ label: t('table.column-alignment-options.label-auto', 'Auto'), value: 'auto' },
{ label: t('table.column-alignment-options.label-left', 'Left'), value: 'left' },
{ label: t('table.column-alignment-options.label-center', 'Center'), value: 'center' },
{ label: t('table.column-alignment-options.label-right', 'Right'), value: 'right' },
],
},
defaultValue: defaultTableFieldOptions.align,
@@ -70,7 +73,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.addCustomEditor<void, TableCellOptions>({
id: 'cellOptions',
path: 'cellOptions',
name: 'Cell type',
name: t('table.name-cell-type', 'Cell type'),
editor: TableCellOptionEditor,
override: TableCellOptionEditor,
defaultValue: defaultTableFieldOptions.cellOptions,
@@ -80,8 +83,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addBooleanSwitch({
path: 'inspect',
name: 'Cell value inspect',
description: 'Enable cell value inspection in a modal window',
name: t('table.name-cell-value-inspect', 'Cell value inspect'),
description: t('table.description-cell-value-inspect', 'Enable cell value inspection in a modal window'),
defaultValue: false,
category: cellCategory,
showIf: (cfg) => {
@@ -95,70 +98,76 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addBooleanSwitch({
path: 'filterable',
name: 'Column filter',
description: 'Enables/disables field filters in table',
name: t('table.name-column-filter', 'Column filter'),
category,
description: t('table.description-column-filter', 'Enables/disables field filters in table'),
defaultValue: defaultTableFieldOptions.filterable,
})
.addBooleanSwitch({
path: 'hidden',
name: 'Hide in table',
name: t('table.name-hide-in-table', 'Hide in table'),
category,
defaultValue: undefined,
hideFromDefaults: true,
});
},
})
.setPanelOptions((builder) => {
const category = [t('table.category-table', 'Table')];
const footerCategory = [t('table.category-table-footer', 'Table footer')];
builder
.addBooleanSwitch({
path: 'showHeader',
name: 'Show table header',
name: t('table.name-show-table-header', 'Show table header'),
category,
defaultValue: defaultOptions.showHeader,
})
.addRadio({
path: 'cellHeight',
name: 'Cell height',
name: t('table.name-cell-height', 'Cell height'),
category,
defaultValue: defaultOptions.cellHeight,
settings: {
options: [
{ value: TableCellHeight.Sm, label: 'Small' },
{ value: TableCellHeight.Md, label: 'Medium' },
{ value: TableCellHeight.Lg, label: 'Large' },
{ value: TableCellHeight.Sm, label: t('table.cell-height-options.label-small', 'Small') },
{ value: TableCellHeight.Md, label: t('table.cell-height-options.label-medium', 'Medium') },
{ value: TableCellHeight.Lg, label: t('table.cell-height-options.label-large', 'Large') },
],
},
})
.addBooleanSwitch({
path: 'footer.show',
category: [footerCategory],
name: 'Show table footer',
category: footerCategory,
name: t('table.name-show-table-footer', 'Show table footer'),
defaultValue: defaultOptions.footer?.show,
})
.addCustomEditor({
id: 'footer.reducer',
category: [footerCategory],
category: footerCategory,
path: 'footer.reducer',
name: 'Calculation',
description: 'Choose a reducer function / calculation',
name: t('table.name-calculation', 'Calculation'),
description: t('table.description-calculation', 'Choose a reducer function / calculation'),
editor: standardEditorsRegistry.get('stats-picker').editor,
defaultValue: [ReducerID.sum],
showIf: (cfg) => cfg.footer?.show,
})
.addBooleanSwitch({
path: 'footer.countRows',
category: [footerCategory],
name: 'Count rows',
description: 'Display a single count for all data rows',
category: footerCategory,
name: t('table.name-count-rows', 'Count rows'),
description: t('table.description-count-rows', 'Display a single count for all data rows'),
defaultValue: defaultOptions.footer?.countRows,
showIf: (cfg) => cfg.footer?.reducer?.length === 1 && cfg.footer?.reducer[0] === ReducerID.count,
})
.addMultiSelect({
path: 'footer.fields',
category: [footerCategory],
name: 'Fields',
description: 'Select the fields that should be calculated',
category: footerCategory,
name: t('table.name-fields', 'Fields'),
description: t('table.description-fields', 'Select the fields that should be calculated'),
settings: {
allowCustomValue: false,
options: [],
placeholder: 'All Numeric Fields',
placeholder: t('table.placeholder-fields', 'All Numeric Fields'),
getOptions: async (context: FieldOverrideContext) => {
const options = [];
if (context && context.data && context.data.length > 0) {
@@ -180,7 +189,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.addCustomEditor({
id: 'footer.enablePagination',
path: 'footer.enablePagination',
name: 'Enable pagination',
name: t('table.name-enable-paginations', 'Enable pagination'),
category,
editor: PaginationEditor,
});
})
@@ -8,6 +8,7 @@ import {
identityOverrideProcessor,
FieldConfigProperty,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { TableCellOptions, TableCellDisplayMode, defaultTableFieldOptions, TableCellHeight } from '@grafana/schema';
import { PaginationEditor } from './PaginationEditor';
@@ -17,9 +18,6 @@ import { tableMigrationHandler, tablePanelChangedHandler } from './migrations';
import { Options, defaultOptions, FieldConfig } from './panelcfg.gen';
import { TableSuggestionsSupplier } from './suggestions';
const footerCategory = 'Table footer';
const cellCategory = ['Cell options'];
export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.setPanelChangeHandler(tablePanelChangedHandler)
.setMigrationHandler(tableMigrationHandler)
@@ -30,11 +28,14 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
},
},
useCustomConfig: (builder) => {
const category = [t('table-new.category-table', 'Table')];
const cellCategory = [t('table-new.category-cell-options', 'Cell options')];
builder
.addNumberInput({
path: 'minWidth',
name: 'Minimum column width',
description: 'The minimum width for column auto resizing',
name: t('table-new.name-min-column-width', 'Minimum column width'),
category,
description: t('table-new.description-min-column-width', 'The minimum width for column auto resizing'),
settings: {
placeholder: '150',
min: 50,
@@ -45,9 +46,10 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addNumberInput({
path: 'width',
name: 'Column width',
name: t('table-new.name-column-width', 'Column width'),
category,
settings: {
placeholder: 'auto',
placeholder: t('table-new.placeholder-column-width', 'auto'),
min: 20,
max: 300,
},
@@ -56,13 +58,14 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addRadio({
path: 'align',
name: 'Column alignment',
name: t('table-new.name-column-alignment', 'Column alignment'),
category,
settings: {
options: [
{ label: 'Auto', value: 'auto' },
{ label: 'Left', value: 'left' },
{ label: 'Center', value: 'center' },
{ label: 'Right', value: 'right' },
{ label: t('table-new.column-alignment-options.label-auto', 'Auto'), value: 'auto' },
{ label: t('table-new.column-alignment-options.label-left', 'Left'), value: 'left' },
{ label: t('table-new.column-alignment-options.label-center', 'Center'), value: 'center' },
{ label: t('table-new.column-alignment-options.label-right', 'Right'), value: 'right' },
],
},
defaultValue: defaultTableFieldOptions.align,
@@ -70,7 +73,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.addCustomEditor<void, TableCellOptions>({
id: 'cellOptions',
path: 'cellOptions',
name: 'Cell type',
name: t('table-new.name-cell-type', 'Cell type'),
editor: TableCellOptionEditor,
override: TableCellOptionEditor,
defaultValue: defaultTableFieldOptions.cellOptions,
@@ -80,8 +83,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addBooleanSwitch({
path: 'inspect',
name: 'Cell value inspect',
description: 'Enable cell value inspection in a modal window',
name: t('table-new.name-cell-value-inspect', 'Cell value inspect'),
description: t('table-new.description-cell-value-inspect', 'Enable cell value inspection in a modal window'),
defaultValue: false,
category: cellCategory,
showIf: (cfg) => {
@@ -95,70 +98,76 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
})
.addBooleanSwitch({
path: 'filterable',
name: 'Column filter',
description: 'Enables/disables field filters in table',
name: t('table-new.name-column-filter', 'Column filter'),
category,
description: t('table-new.description-column-filter', 'Enables/disables field filters in table'),
defaultValue: defaultTableFieldOptions.filterable,
})
.addBooleanSwitch({
path: 'hidden',
name: 'Hide in table',
name: t('table-new.name-hide-in-table', 'Hide in table'),
category,
defaultValue: undefined,
hideFromDefaults: true,
});
},
})
.setPanelOptions((builder) => {
const footerCategory = [t('table-new.category-table-footer', 'Table footer')];
const category = [t('table-new.category-table', 'Table')];
builder
.addBooleanSwitch({
path: 'showHeader',
name: 'Show table header',
name: t('table-new.name-show-table-header', 'Show table header'),
category,
defaultValue: defaultOptions.showHeader,
})
.addRadio({
path: 'cellHeight',
name: 'Cell height',
name: t('table-new.name-cell-height', 'Cell height'),
category,
defaultValue: defaultOptions.cellHeight,
settings: {
options: [
{ value: TableCellHeight.Sm, label: 'Small' },
{ value: TableCellHeight.Md, label: 'Medium' },
{ value: TableCellHeight.Lg, label: 'Large' },
{ value: TableCellHeight.Sm, label: t('table-new.cell-height-options.label-small', 'Small') },
{ value: TableCellHeight.Md, label: t('table-new.cell-height-options.label-medium', 'Medium') },
{ value: TableCellHeight.Lg, label: t('table-new.cell-height-options.label-large', 'Large') },
],
},
})
.addBooleanSwitch({
path: 'footer.show',
category: [footerCategory],
name: 'Show table footer',
category: footerCategory,
name: t('table-new.name-show-table-footer', 'Show table footer'),
defaultValue: defaultOptions.footer?.show,
})
.addCustomEditor({
id: 'footer.reducer',
category: [footerCategory],
category: footerCategory,
path: 'footer.reducer',
name: 'Calculation',
description: 'Choose a reducer function / calculation',
name: t('table-new.name-calculation', 'Calculation'),
description: t('table-new.description-calculation', 'Choose a reducer function / calculation'),
editor: standardEditorsRegistry.get('stats-picker').editor,
defaultValue: [ReducerID.sum],
showIf: (cfg) => cfg.footer?.show,
})
.addBooleanSwitch({
path: 'footer.countRows',
category: [footerCategory],
name: 'Count rows',
description: 'Display a single count for all data rows',
category: footerCategory,
name: t('table-new.name-count-rows', 'Count rows'),
description: t('table-new.description-count-rows', 'Display a single count for all data rows'),
defaultValue: defaultOptions.footer?.countRows,
showIf: (cfg) => cfg.footer?.reducer?.length === 1 && cfg.footer?.reducer[0] === ReducerID.count,
})
.addMultiSelect({
path: 'footer.fields',
category: [footerCategory],
name: 'Fields',
description: 'Select the fields that should be calculated',
category: footerCategory,
name: t('table-new.name-fields', 'Fields'),
description: t('table-new.description-fields', 'Select the fields that should be calculated'),
settings: {
allowCustomValue: false,
options: [],
placeholder: 'All Numeric Fields',
placeholder: t('table-new.placeholder-fields', 'All Numeric Fields'),
getOptions: async (context: FieldOverrideContext) => {
const options = [];
if (context && context.data && context.data.length > 0) {
@@ -180,7 +189,8 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TablePanel)
.addCustomEditor({
id: 'footer.enablePagination',
path: 'footer.enablePagination',
name: 'Enable pagination',
name: t('table-new.name-enable-pagination', 'Enable pagination'),
category,
editor: PaginationEditor,
});
})
+15 -8
View File
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { TextPanel } from './TextPanel';
import { TextPanelEditor } from './TextPanelEditor';
@@ -7,22 +8,25 @@ import { textPanelMigrationHandler } from './textPanelMigrationHandler';
export const plugin = new PanelPlugin<Options>(TextPanel)
.setPanelOptions((builder) => {
const category = [t('text.category-text', 'Text')];
builder
.addRadio({
path: 'mode',
name: 'Mode',
name: t('text.name-mode', 'Mode'),
category,
settings: {
options: [
{ value: TextMode.Markdown, label: 'Markdown' },
{ value: TextMode.HTML, label: 'HTML' },
{ value: TextMode.Code, label: 'Code' },
{ value: TextMode.Markdown, label: t('text.mode-options.label-markdown', 'Markdown') },
{ value: TextMode.HTML, label: t('text.mode-options.label-html', 'HTML') },
{ value: TextMode.Code, label: t('text.mode-options.label-code', 'Code') },
],
},
defaultValue: defaultOptions.mode,
})
.addSelect({
path: 'code.language',
name: 'Language',
name: t('text.name-language', 'Language'),
category,
settings: {
options: Object.values(CodeLanguage).map((v) => ({
value: v,
@@ -34,20 +38,23 @@ export const plugin = new PanelPlugin<Options>(TextPanel)
})
.addBooleanSwitch({
path: 'code.showLineNumbers',
name: 'Show line numbers',
name: t('text.name-show-line-numbers', 'Show line numbers'),
category,
defaultValue: defaultCodeOptions.showLineNumbers,
showIf: (v) => v.mode === TextMode.Code,
})
.addBooleanSwitch({
path: 'code.showMiniMap',
name: 'Show mini map',
name: t('text.name-show-mini-map', 'Show mini map'),
category,
defaultValue: defaultCodeOptions.showMiniMap,
showIf: (v) => v.mode === TextMode.Code,
})
.addCustomEditor({
id: 'content',
path: 'content',
name: 'Content',
name: t('text.name-content', 'Content'),
category,
editor: TextPanelEditor,
defaultValue: defaultOptions.content,
});
@@ -1,22 +1,22 @@
import { StandardEditorProps, SelectableValue } from '@grafana/data';
import { t } from '@grafana/i18n';
import { HorizontalGroup, RadioButtonGroup } from '@grafana/ui';
import { InputPrefix, NullsThresholdInput } from './NullsThresholdInput';
const DISCONNECT_OPTIONS: Array<SelectableValue<boolean | number>> = [
{
label: 'Never',
value: false,
},
{
label: 'Threshold',
value: 3600000, // 1h
},
];
type Props = StandardEditorProps<boolean | number, { isTime: boolean }>;
export const InsertNullsEditor = ({ value, onChange, item }: Props) => {
const DISCONNECT_OPTIONS: Array<SelectableValue<boolean | number>> = [
{
label: t('timeseries.insert-nulls-editor.disconnect-options.label-never', 'Never'),
value: false,
},
{
label: t('timeseries.insert-nulls-editor.disconnect-options.label-threshold', 'Threshold'),
value: 3600000, // 1h
},
];
const isThreshold = typeof value === 'number';
DISCONNECT_OPTIONS[1].value = isThreshold ? value : 3600000; // 1h
@@ -7,21 +7,6 @@ import { HorizontalGroup, IconButton, RadioButtonGroup, Select } from '@grafana/
type LineFill = 'solid' | 'dash' | 'dot';
const lineFillOptions: Array<SelectableValue<LineFill>> = [
{
label: 'Solid',
value: 'solid',
},
{
label: 'Dash',
value: 'dash',
},
{
label: 'Dots',
value: 'dot',
},
];
const dashOptions: Array<SelectableValue<string>> = [
'10, 10', // default
'10, 15',
@@ -56,6 +41,20 @@ const dotOptions: Array<SelectableValue<string>> = [
type Props = StandardEditorProps<LineStyle, unknown>;
export const LineStyleEditor = ({ value, onChange }: Props) => {
const lineFillOptions: Array<SelectableValue<LineFill>> = [
{
label: t('timeseries.line-style-editor.line-fill-options.label-solid', 'Solid'),
value: 'solid',
},
{
label: t('timeseries.line-style-editor.line-fill-options.label-dash', 'Dash'),
value: 'dash',
},
{
label: t('timeseries.line-style-editor.line-fill-options.label-dots', 'Dots'),
value: 'dot',
},
];
const options = useMemo(() => (value?.fill === 'dash' ? dashOptions : dotOptions), [value]);
const current = useMemo(() => {
if (!value?.dash?.length) {
@@ -1,26 +1,26 @@
import { StandardEditorProps, SelectableValue } from '@grafana/data';
import { t } from '@grafana/i18n';
import { HorizontalGroup, RadioButtonGroup } from '@grafana/ui';
import { InputPrefix, NullsThresholdInput } from './NullsThresholdInput';
const GAPS_OPTIONS: Array<SelectableValue<boolean | number>> = [
{
label: 'Never',
value: false,
},
{
label: 'Always',
value: true,
},
{
label: 'Threshold',
value: 3600000, // 1h
},
];
type Props = StandardEditorProps<boolean | number, { isTime: boolean }>;
export const SpanNullsEditor = ({ value, onChange, item }: Props) => {
const GAPS_OPTIONS: Array<SelectableValue<boolean | number>> = [
{
label: t('timeseries.span-nulls-editor.gaps-options.label-never', 'Never'),
value: false,
},
{
label: t('timeseries.span-nulls-editor.gaps-options.label-always', 'Always'),
value: true,
},
{
label: t('timeseries.span-nulls-editor.gaps-options.label-threshold', 'Threshold'),
value: 3600000, // 1h
},
];
const isThreshold = typeof value === 'number';
GAPS_OPTIONS[2].value = isThreshold ? value : 3600000; // 1h
+37 -27
View File
@@ -6,6 +6,7 @@ import {
SetFieldConfigOptionsArgs,
Field,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import {
BarAlignment,
GraphDrawStyle,
@@ -18,7 +19,7 @@ import {
GraphThresholdsStyleMode,
GraphTransform,
} from '@grafana/schema';
import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui';
import { getGraphFieldOptions, commonOptionsBuilder } from '@grafana/ui';
import { InsertNullsEditor } from './InsertNullsEditor';
import { LineStyleEditor } from './LineStyleEditor';
@@ -42,11 +43,11 @@ export const defaultGraphConfig: GraphFieldConfig = {
axisBorderShow: false,
};
const categoryStyles = ['Graph styles'];
export type NullEditorSettings = { isTime: boolean };
export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFieldConfigOptionsArgs<GraphFieldConfig> {
const graphFieldOptions = getGraphFieldOptions();
const categoryStyles = [t('timeseries.config.get-graph-field-config.category-graph-styles', 'Graph styles')];
return {
standardOptions: {
[FieldConfigProperty.Color]: {
@@ -72,7 +73,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
builder
.addRadio({
path: 'drawStyle',
name: 'Style',
name: t('timeseries.config.get-graph-field-config.name-style', 'Style'),
category: categoryStyles,
defaultValue: cfg.drawStyle,
settings: {
@@ -81,7 +82,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addRadio({
path: 'lineInterpolation',
name: 'Line interpolation',
name: t('timeseries.config.get-graph-field-config.name-line-interpolation', 'Line interpolation'),
category: categoryStyles,
defaultValue: cfg.lineInterpolation,
settings: {
@@ -91,7 +92,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addRadio({
path: 'barAlignment',
name: 'Bar alignment',
name: t('timeseries.config.get-graph-field-config.name-bar-alignment', 'Bar alignment'),
category: categoryStyles,
defaultValue: cfg.barAlignment,
settings: {
@@ -101,46 +102,49 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addSliderInput({
path: 'barWidthFactor',
name: 'Bar width factor',
name: t('timeseries.config.get-graph-field-config.name-bar-width-factor', 'Bar width factor'),
category: categoryStyles,
defaultValue: cfg.barWidthFactor,
settings: {
min: 0.1,
max: 1.0,
step: 0.1,
ariaLabelForHandle: 'Bar width factor',
ariaLabelForHandle: t(
'timeseries.config.get-graph-field-config.aria-label-bar-width-factor',
'Bar width factor'
),
},
showIf: (config) => config.drawStyle === GraphDrawStyle.Bars,
})
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('timeseries.config.get-graph-field-config.name-line-width', 'Line width'),
category: categoryStyles,
defaultValue: cfg.lineWidth,
settings: {
min: 0,
max: 10,
step: 1,
ariaLabelForHandle: 'Line width',
ariaLabelForHandle: t('timeseries.config.get-graph-field-config.aria-label-line-width', 'Line width'),
},
showIf: (config) => config.drawStyle !== GraphDrawStyle.Points,
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('timeseries.config.get-graph-field-config.name-fill-opacity', 'Fill opacity'),
category: categoryStyles,
defaultValue: cfg.fillOpacity,
settings: {
min: 0,
max: 100,
step: 1,
ariaLabelForHandle: 'Fill opacity',
ariaLabelForHandle: t('timeseries.config.get-graph-field-config.aria-label-fill-opacity', 'Fill opacity'),
},
showIf: (config) => config.drawStyle !== GraphDrawStyle.Points,
})
.addRadio({
path: 'gradientMode',
name: 'Gradient mode',
name: t('timeseries.config.get-graph-field-config.name-gradient-mode', 'Gradient mode'),
category: categoryStyles,
defaultValue: graphFieldOptions.fillGradient[0].value,
settings: {
@@ -150,7 +154,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addFieldNamePicker({
path: 'fillBelowTo',
name: 'Fill below to',
name: t('timeseries.config.get-graph-field-config.name-fill-below-to', 'Fill below to'),
category: categoryStyles,
hideFromDefaults: true,
settings: {
@@ -160,7 +164,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
.addCustomEditor<void, LineStyle>({
id: 'lineStyle',
path: 'lineStyle',
name: 'Line style',
name: t('timeseries.config.get-graph-field-config.name-line-style', 'Line style'),
category: categoryStyles,
showIf: (config) => config.drawStyle === GraphDrawStyle.Line,
editor: LineStyleEditor,
@@ -171,7 +175,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
.addCustomEditor<NullEditorSettings, boolean>({
id: 'spanNulls',
path: 'spanNulls',
name: 'Connect null values',
name: t('timeseries.config.get-graph-field-config.name-connect-nulls', 'Connect null values'),
category: categoryStyles,
defaultValue: false,
editor: SpanNullsEditor,
@@ -184,7 +188,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
.addCustomEditor<NullEditorSettings, boolean>({
id: 'insertNulls',
path: 'insertNulls',
name: 'Disconnect values',
name: t('timeseries.config.get-graph-field-config.name-disconnect-values', 'Disconnect values'),
category: categoryStyles,
defaultValue: false,
editor: InsertNullsEditor,
@@ -196,7 +200,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addRadio({
path: 'showPoints',
name: 'Show points',
name: t('timeseries.config.get-graph-field-config.name-show-points', 'Show points'),
category: categoryStyles,
defaultValue: graphFieldOptions.showPoints[0].value,
settings: {
@@ -206,14 +210,14 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
})
.addSliderInput({
path: 'pointSize',
name: 'Point size',
name: t('timeseries.config.get-graph-field-config.name-point-size', 'Point size'),
category: categoryStyles,
defaultValue: 5,
settings: {
min: 1,
max: 40,
step: 1,
ariaLabelForHandle: 'Point size',
ariaLabelForHandle: t('timeseries.config.get-graph-field-config.aria-label-point-size', 'Point size'),
},
showIf: (config) => config.showPoints !== VisibilityMode.Never || config.drawStyle === GraphDrawStyle.Points,
});
@@ -222,19 +226,25 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
builder.addSelect({
category: categoryStyles,
name: 'Transform',
name: t('timeseries.config.get-graph-field-config.name-transform', 'Transform'),
path: 'transform',
settings: {
options: [
{
label: 'Constant',
label: t('timeseries.config.get-graph-field-config.transform-options.label-constant', 'Constant'),
value: GraphTransform.Constant,
description: 'The first value will be shown as a constant line',
description: t(
'timeseries.config.get-graph-field-config.transform-options.description-constant',
'The first value will be shown as a constant line'
),
},
{
label: 'Negative Y',
label: t('timeseries.config.get-graph-field-config.transform-options.label-style', 'Negative Y'),
value: GraphTransform.NegativeY,
description: 'Flip the results to negative values on the y axis',
description: t(
'timeseries.config.get-graph-field-config.transform-options.description-style',
'Flip the results to negative values on the y axis'
),
},
],
isClearable: true,
@@ -248,8 +258,8 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig, isTime = true): SetFi
builder.addCustomEditor({
id: 'thresholdsStyle',
path: 'thresholdsStyle',
name: 'Show thresholds',
category: ['Thresholds'],
name: t('timeseries.config.get-graph-field-config.name-show-thresholds', 'Show thresholds'),
category: [t('timeseries.config.get-graph-field-config.category-thresholds', 'Thresholds')],
defaultValue: { mode: GraphThresholdsStyleMode.Off },
settings: {
options: graphFieldOptions.thresholdsDisplayModes,
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { commonOptionsBuilder } from '@grafana/ui';
import { optsWithHideZeros } from '@grafana/ui/internal';
@@ -18,9 +19,9 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(TimeSeriesPanel)
builder.addCustomEditor({
id: 'timezone',
name: 'Time zone',
name: t('timeseries.name-time-zone', 'Time zone'),
path: 'timezone',
category: ['Axis'],
category: [t('timeseries.category-axis', 'Axis')],
editor: TimezonesEditor,
defaultValue: undefined,
});
+12 -11
View File
@@ -1,4 +1,5 @@
import { PanelPlugin, toOption } from '@grafana/data';
import { t } from '@grafana/i18n';
import { getTraceServiceNames, getTraceSpanNames } from '../../../features/explore/TraceView/utils/tags';
import { transformDataFrames } from '../../../features/explore/TraceView/utils/transform';
@@ -9,25 +10,25 @@ import { TracesSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin(TracesPanel)
.setPanelOptions((builder, context) => {
const category = ['Span filters'];
const category = [t('traces.category-span-filters', 'Span filters')];
const trace = transformDataFrames(context?.data?.[0]);
// Find
builder
.addTextInput({
path: 'spanFilters.query',
name: 'Find in trace',
name: t('traces.name-find-in-trace', 'Find in trace'),
category,
})
.addBooleanSwitch({
path: 'spanFilters.matchesOnly',
name: 'Show matches only',
name: t('traces.name-show-matches-only', 'Show matches only'),
defaultValue: false,
category,
})
.addBooleanSwitch({
path: 'spanFilters.criticalPathOnly',
name: 'Show critical path only',
name: t('traces.name-critical-path-only', 'Show critical path only'),
defaultValue: false,
category,
});
@@ -36,7 +37,7 @@ export const plugin = new PanelPlugin(TracesPanel)
builder
.addSelect({
path: 'spanFilters.serviceName',
name: 'Service name',
name: t('traces.name-service-name', 'Service name'),
category,
settings: {
options: trace ? getTraceServiceNames(trace).map(toOption) : [],
@@ -46,7 +47,7 @@ export const plugin = new PanelPlugin(TracesPanel)
})
.addRadio({
path: 'spanFilters.serviceNameOperator',
name: 'Service name operator',
name: t('traces.name-service-name-operator', 'Service name operator'),
defaultValue: '=',
settings: {
options: [
@@ -61,7 +62,7 @@ export const plugin = new PanelPlugin(TracesPanel)
builder
.addSelect({
path: 'spanFilters.spanName',
name: 'Span name',
name: t('traces.name-span-name', 'Span name'),
category,
settings: {
options: trace ? getTraceSpanNames(trace).map(toOption) : [],
@@ -71,7 +72,7 @@ export const plugin = new PanelPlugin(TracesPanel)
})
.addRadio({
path: 'spanFilters.spanNameOperator',
name: 'Span name operator',
name: t('traces.name-span-name-operator', 'Span name operator'),
defaultValue: '=',
settings: {
options: [
@@ -86,18 +87,18 @@ export const plugin = new PanelPlugin(TracesPanel)
builder
.addTextInput({
path: 'spanFilters.from',
name: 'Min duration',
name: t('traces.name-min-duration', 'Min duration'),
category,
})
.addTextInput({
path: 'spanFilters.to',
name: 'Max duration',
name: t('traces.name-max-duration', 'Max duration'),
category,
});
builder.addCustomEditor({
id: 'tags',
name: 'Tags',
name: t('traces.name-tags', 'Tags'),
path: 'spanFilters',
category,
editor: TagsEditor,
+5 -4
View File
@@ -1,4 +1,5 @@
import { Field, FieldType, PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { commonOptionsBuilder } from '@grafana/ui';
import { optsWithHideZeros } from '@grafana/ui/internal';
@@ -11,16 +12,16 @@ import { TrendSuggestionsSupplier } from './suggestions';
export const plugin = new PanelPlugin<Options, FieldConfig>(TrendPanel)
.useFieldConfig(getGraphFieldConfig(defaultGraphConfig, false))
.setPanelOptions((builder) => {
const category = ['X axis'];
const category = [t('trend.category-x-axis', 'X axis')];
builder.addFieldNamePicker({
path: 'xField',
name: 'X field',
description: 'An increasing numeric value',
name: t('trend.name-x-field', 'X field'),
description: t('trend.description-x-field', 'An increasing numeric value'),
category,
defaultValue: undefined,
settings: {
isClearable: true,
placeholderText: 'First numeric value',
placeholderText: t('trend.placeholder-x-field', 'First numeric value'),
filter: (field: Field) => field.type === FieldType.number,
},
});
@@ -186,7 +186,9 @@ export const SeriesEditor = ({
!field.config.custom?.hideFrom?.viz,
baseNameMode,
placeholderText:
mapping === SeriesMapping.Auto ? 'First number or time field in each frame' : undefined,
mapping === SeriesMapping.Auto
? t('xychart.series-editor.placeholder-x-field', 'First number or time field in each frame')
: undefined,
},
}}
/>
@@ -221,7 +223,10 @@ export const SeriesEditor = ({
field.type === FieldType.number &&
!field.config.custom?.hideFrom?.viz,
baseNameMode,
placeholderText: mapping === SeriesMapping.Auto ? 'Remaining number fields in each frame' : undefined,
placeholderText:
mapping === SeriesMapping.Auto
? t('xychart.series-editor.placeholder-y-field', 'Remaining number fields in each frame')
: undefined,
},
}}
/>
+25 -14
View File
@@ -5,6 +5,7 @@ import {
identityOverrideProcessor,
SetFieldConfigOptionsArgs,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { LineStyle } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
@@ -58,16 +59,18 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
},
useCustomConfig: (builder) => {
const category = [t('xychart.category-xychart', 'XY Chart')];
builder
.addRadio({
path: 'show',
name: 'Show',
name: t('xychart.name-show', 'Show'),
category,
defaultValue: cfg.show,
settings: {
options: [
{ label: 'Points', value: XYShowMode.Points },
{ label: 'Lines', value: XYShowMode.Lines },
{ label: 'Both', value: XYShowMode.PointsAndLines },
{ label: t('xychart.show-options.label-points', 'Points'), value: XYShowMode.Points },
{ label: t('xychart.show-options.label-lines', 'Lines'), value: XYShowMode.Lines },
{ label: t('xychart.show-options.label-both', 'Both'), value: XYShowMode.PointsAndLines },
],
},
})
@@ -92,7 +95,8 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
// )
.addSliderInput({
path: 'pointSize.fixed',
name: 'Point size',
name: t('xychart.name-point-size', 'Point size'),
category,
defaultValue: cfg.pointSize?.fixed ?? DEFAULT_POINT_SIZE,
settings: {
min: 1,
@@ -103,29 +107,33 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
})
.addNumberInput({
path: 'pointSize.min',
name: 'Min point size',
name: t('xychart.name-min-point-size', 'Min point size'),
category,
showIf: (c) => c.show !== XYShowMode.Lines,
})
.addNumberInput({
path: 'pointSize.max',
name: 'Max point size',
name: t('xychart.name-max-point-size', 'Max point size'),
category,
showIf: (c) => c.show !== XYShowMode.Lines,
})
.addRadio({
path: 'pointShape',
name: 'Point shape',
name: t('xychart.name-point-shape', 'Point shape'),
category,
defaultValue: PointShape.Circle,
settings: {
options: [
{ value: PointShape.Circle, label: 'Circle' },
{ value: PointShape.Square, label: 'Square' },
{ value: PointShape.Circle, label: t('xychart.point-shape-options.label-circle', 'Circle') },
{ value: PointShape.Square, label: t('xychart.point-shape-options.label-square', 'Square') },
],
},
showIf: (c) => c.show !== XYShowMode.Lines,
})
.addSliderInput({
path: 'pointStrokeWidth',
name: 'Point stroke width',
name: t('xychart.name-point-stroke-width', 'Point stroke width'),
category,
defaultValue: 1,
settings: {
min: 0,
@@ -135,7 +143,8 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
})
.addSliderInput({
path: 'fillOpacity',
name: 'Fill opacity',
name: t('xychart.name-fill-opacity', 'Fill opacity'),
category,
defaultValue: 50,
settings: {
min: 0,
@@ -147,7 +156,8 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
.addCustomEditor<void, LineStyle>({
id: 'lineStyle',
path: 'lineStyle',
name: 'Line style',
name: t('xychart.name-line-style', 'Line style'),
category,
showIf: (c) => c.show !== XYShowMode.Points,
editor: LineStyleEditor,
override: LineStyleEditor,
@@ -156,7 +166,8 @@ export function getScatterFieldConfig(cfg: FieldConfig): SetFieldConfigOptionsAr
})
.addSliderInput({
path: 'lineWidth',
name: 'Line width',
name: t('xychart.name-line-width', 'Line width'),
category,
defaultValue: cfg.lineWidth,
settings: {
min: 0,
+7 -3
View File
@@ -1,4 +1,5 @@
import { PanelPlugin } from '@grafana/data';
import { t } from '@grafana/i18n';
import { commonOptionsBuilder } from '@grafana/ui';
import { SeriesEditor } from './SeriesEditor';
@@ -12,15 +13,17 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(XYChartPanel2)
.setMigrationHandler(xyChartMigrationHandler)
.useFieldConfig(getScatterFieldConfig(defaultFieldConfig))
.setPanelOptions((builder) => {
const category = [t('xychart.category-xychart', 'XY Chart')];
builder
.addRadio({
path: 'mapping',
name: 'Series mapping',
name: t('xychart.name-series-mapping', 'Series mapping'),
category,
defaultValue: 'auto',
settings: {
options: [
{ value: 'auto', label: 'Auto' },
{ value: 'manual', label: 'Manual' },
{ value: 'auto', label: t('xychart.series-mapping-options.label-auto', 'Auto') },
{ value: 'manual', label: t('xychart.series-mapping-options.label-manual', 'Manual') },
],
},
})
@@ -28,6 +31,7 @@ export const plugin = new PanelPlugin<Options, FieldConfig>(XYChartPanel2)
id: 'series',
path: 'series',
name: '',
category,
editor: SeriesEditor,
defaultValue: [{}],
});
File diff suppressed because it is too large Load Diff