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:
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ?? {};
|
||||
|
||||
@@ -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 },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user