mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Refactor state timeline/status history to cue model and refactor TimelineChart
component (#61631)
* Adapt state timeline to scuemata * Refactor status history to cue model * Refactor * Refactor TimelineChart as a core component * wip * Change as per CR Co-authored-by: sam boyer <sdboyer@grafana.com>
This commit is contained in:
parent
6c9174a766
commit
6a93c77082
@ -2476,6 +2476,24 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
],
|
||||
"public/app/core/components/TimelineChart/TimelineChart.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/core/components/TimelineChart/timeline.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"]
|
||||
],
|
||||
"public/app/core/components/TimelineChart/utils.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/core/components/TimelineChart/utils.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/core/components/connectWithCleanUp.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
@ -7510,10 +7528,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/TimelineChart.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/migrations.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
@ -7524,22 +7538,6 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "6"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "7"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/timeline.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/types.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/utils.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/state-timeline/utils.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/table-old/column_options.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
|
@ -0,0 +1,41 @@
|
||||
---
|
||||
keywords:
|
||||
- grafana
|
||||
- schema
|
||||
title: StateTimelinePanelCfg kind
|
||||
---
|
||||
> Both documentation generation and kinds schemas are in active development and subject to change without prior notice.
|
||||
|
||||
# StateTimelinePanelCfg kind
|
||||
|
||||
## Maturity: experimental
|
||||
## Version: 0.0
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|--------------------|-----------------------------|----------|-------------|
|
||||
| `PanelFieldConfig` | [object](#panelfieldconfig) | **Yes** | |
|
||||
| `PanelOptions` | [object](#paneloptions) | **Yes** | |
|
||||
|
||||
## PanelFieldConfig
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|---------------|---------|----------|----------------|
|
||||
| `fillOpacity` | integer | No | Default: `70`. |
|
||||
| `lineWidth` | integer | No | Default: `0`. |
|
||||
|
||||
## PanelOptions
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|---------------|---------|----------|-------------------------------------------------------------------------------------------------------------|
|
||||
| `alignValue` | string | No | Controls the value alignment in the TimelineChart component Possible values are: `center`, `left`, `right`. |
|
||||
| `mergeValues` | boolean | No | Merge equal consecutive values Default: `true`. |
|
||||
| `rowHeight` | number | No | Controls the row height Default: `0.9`. |
|
||||
| `showValue` | string | No | TODO docs Possible values are: `auto`, `never`, `always`. |
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
---
|
||||
keywords:
|
||||
- grafana
|
||||
- schema
|
||||
title: StatusHistoryPanelCfg kind
|
||||
---
|
||||
> Both documentation generation and kinds schemas are in active development and subject to change without prior notice.
|
||||
|
||||
# StatusHistoryPanelCfg kind
|
||||
|
||||
## Maturity: experimental
|
||||
## Version: 0.0
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|--------------------|-----------------------------|----------|-------------|
|
||||
| `PanelFieldConfig` | [object](#panelfieldconfig) | **Yes** | |
|
||||
| `PanelOptions` | [object](#paneloptions) | **Yes** | |
|
||||
|
||||
## PanelFieldConfig
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|---------------|---------|----------|----------------|
|
||||
| `fillOpacity` | integer | No | Default: `70`. |
|
||||
| `lineWidth` | integer | No | Default: `1`. |
|
||||
|
||||
## PanelOptions
|
||||
|
||||
### Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|-------------|--------|----------|-----------------------------------------------------------|
|
||||
| `colWidth` | number | No | Controls the column width Default: `0.9`. |
|
||||
| `showValue` | string | No | TODO docs Possible values are: `auto`, `never`, `always`. |
|
||||
|
||||
|
@ -485,6 +485,11 @@ export enum BigValueTextMode {
|
||||
*/
|
||||
export type FieldTextAlignment = ('auto' | 'left' | 'right' | 'center');
|
||||
|
||||
/**
|
||||
* Controls the value alignment in the TimelineChart component
|
||||
*/
|
||||
export type TimelineValueAlignment = ('center' | 'left' | 'right');
|
||||
|
||||
/**
|
||||
* TODO docs
|
||||
*/
|
||||
|
@ -193,6 +193,9 @@ BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(
|
||||
// TODO docs
|
||||
FieldTextAlignment: "auto" | "left" | "right" | "center" @cuetsy(kind="type")
|
||||
|
||||
// Controls the value alignment in the TimelineChart component
|
||||
TimelineValueAlignment: "center" | "left" | "right" @cuetsy(kind="type")
|
||||
|
||||
// TODO docs
|
||||
VizTextDisplayOptions: {
|
||||
// Explicit title text size
|
||||
|
@ -1349,6 +1349,30 @@
|
||||
"pluralMachineName": "serviceaccounts",
|
||||
"pluralName": "ServiceAccounts"
|
||||
},
|
||||
"statetimelinepanelcfg": {
|
||||
"category": "composable",
|
||||
"codeowners": [
|
||||
"grafana/grafana-bi-squad"
|
||||
],
|
||||
"currentVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"grafanaMaturityCount": 0,
|
||||
"lineageIsGroup": true,
|
||||
"links": {
|
||||
"docs": "https://grafana.com/docs/grafana/next/developers/kinds/composable/statetimelinepanelcfg/schema-reference",
|
||||
"go": "n/a",
|
||||
"schema": "https://github.com/grafana/grafana/tree/main/public/app/plugins/panel/state-timeline/panelcfg.cue",
|
||||
"ts": "https://github.com/grafana/grafana/tree/main/public/app/plugins/panel/state-timeline/panelcfg.gen.ts"
|
||||
},
|
||||
"machineName": "statetimelinepanelcfg",
|
||||
"maturity": "experimental",
|
||||
"name": "StateTimelinePanelCfg",
|
||||
"pluralMachineName": "statetimelinepanelcfgs",
|
||||
"pluralName": "StateTimelinePanelCfgs",
|
||||
"schemaInterface": "PanelCfg"
|
||||
},
|
||||
"statpanelcfg": {
|
||||
"category": "composable",
|
||||
"codeowners": [
|
||||
@ -1373,6 +1397,30 @@
|
||||
"pluralName": "StatPanelCfgs",
|
||||
"schemaInterface": "PanelCfg"
|
||||
},
|
||||
"statushistorypanelcfg": {
|
||||
"category": "composable",
|
||||
"codeowners": [
|
||||
"grafana/grafana-bi-squad"
|
||||
],
|
||||
"currentVersion": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"grafanaMaturityCount": 0,
|
||||
"lineageIsGroup": true,
|
||||
"links": {
|
||||
"docs": "https://grafana.com/docs/grafana/next/developers/kinds/composable/statushistorypanelcfg/schema-reference",
|
||||
"go": "n/a",
|
||||
"schema": "https://github.com/grafana/grafana/tree/main/public/app/plugins/panel/status-history/panelcfg.cue",
|
||||
"ts": "https://github.com/grafana/grafana/tree/main/public/app/plugins/panel/status-history/panelcfg.gen.ts"
|
||||
},
|
||||
"machineName": "statushistorypanelcfg",
|
||||
"maturity": "experimental",
|
||||
"name": "StatusHistoryPanelCfg",
|
||||
"pluralMachineName": "statushistorypanelcfgs",
|
||||
"pluralName": "StatusHistoryPanelCfgs",
|
||||
"schemaInterface": "PanelCfg"
|
||||
},
|
||||
"tableoldpanelcfg": {
|
||||
"category": "composable",
|
||||
"codeowners": [],
|
||||
@ -1744,7 +1792,9 @@
|
||||
"postgresqldatasourcecfg",
|
||||
"prometheusdataquery",
|
||||
"prometheusdatasourcecfg",
|
||||
"statetimelinepanelcfg",
|
||||
"statpanelcfg",
|
||||
"statushistorypanelcfg",
|
||||
"tableoldpanelcfg",
|
||||
"tempodataquery",
|
||||
"tempodatasourcecfg",
|
||||
@ -1757,7 +1807,7 @@
|
||||
"zipkindataquery",
|
||||
"zipkindatasourcecfg"
|
||||
],
|
||||
"count": 63
|
||||
"count": 65
|
||||
},
|
||||
"core": {
|
||||
"name": "core",
|
||||
@ -1791,11 +1841,13 @@
|
||||
"histogrampanelcfg",
|
||||
"newspanelcfg",
|
||||
"piechartpanelcfg",
|
||||
"statetimelinepanelcfg",
|
||||
"statpanelcfg",
|
||||
"statushistorypanelcfg",
|
||||
"textpanelcfg",
|
||||
"xychartpanelcfg"
|
||||
],
|
||||
"count": 12
|
||||
"count": 14
|
||||
},
|
||||
"mature": {
|
||||
"name": "mature",
|
||||
|
@ -71,6 +71,8 @@ func corePlugins(rt *thema.Runtime) []pfs.ParsedPlugin {
|
||||
parsePluginOrPanic("public/app/plugins/panel/nodeGraph", "nodeGraph", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/piechart", "piechart", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/stat", "stat", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/state-timeline", "state_timeline", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/status-history", "status_history", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/table-old", "table_old", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/text", "text", rt),
|
||||
parsePluginOrPanic("public/app/plugins/panel/traces", "traces", rt),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DataFrame, FALLBACK_COLOR, FieldType, TimeRange } from '@grafana/data';
|
||||
import { VisibilityMode } from '@grafana/schema';
|
||||
import { VisibilityMode, TimelineValueAlignment } from '@grafana/schema';
|
||||
import {
|
||||
PanelContext,
|
||||
PanelContextRoot,
|
||||
@ -13,17 +13,14 @@ import {
|
||||
VizLegendItem,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { TimelineMode, TimelineOptions, TimelineValueAlignment } from './types';
|
||||
import { preparePlotConfigBuilder } from './utils';
|
||||
import { preparePlotConfigBuilder, TimelineMode } from './utils';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface TimelineProps
|
||||
extends TimelineOptions,
|
||||
Omit<GraphNGProps, 'prepConfig' | 'propsToDiff' | 'renderLegend'> {
|
||||
export interface TimelineProps extends Omit<GraphNGProps, 'prepConfig' | 'propsToDiff' | 'renderLegend'> {
|
||||
mode: TimelineMode;
|
||||
rowHeight: number;
|
||||
rowHeight?: number;
|
||||
showValue: VisibilityMode;
|
||||
alignValue?: TimelineValueAlignment;
|
||||
colWidth?: number;
|
@ -2,12 +2,14 @@ import uPlot, { Cursor, Series } from 'uplot';
|
||||
|
||||
import { GrafanaTheme2, TimeRange } from '@grafana/data';
|
||||
import { alpha } from '@grafana/data/src/themes/colorManipulator';
|
||||
import { VisibilityMode } from '@grafana/schema';
|
||||
import { VisibilityMode, TimelineValueAlignment } from '@grafana/schema';
|
||||
import { FIXED_UNIT } from '@grafana/ui/src/components/GraphNG/GraphNG';
|
||||
import { distribute, SPACE_BETWEEN } from 'app/plugins/panel/barchart/distribute';
|
||||
import { pointWithin, Quadtree, Rect } from 'app/plugins/panel/barchart/quadtree';
|
||||
import { PanelFieldConfig as StateTimeLineFieldConfig } from 'app/plugins/panel/state-timeline/panelcfg.gen';
|
||||
import { PanelFieldConfig as StatusHistoryFieldConfig } from 'app/plugins/panel/status-history/panelcfg.gen';
|
||||
|
||||
import { TimelineFieldConfig, TimelineMode, TimelineValueAlignment } from './types';
|
||||
import { TimelineMode } from './utils';
|
||||
|
||||
const { round, min, ceil } = Math;
|
||||
|
||||
@ -39,7 +41,7 @@ export interface TimelineCoreOptions {
|
||||
mode: TimelineMode;
|
||||
alignValue?: TimelineValueAlignment;
|
||||
numSeries: number;
|
||||
rowHeight: number;
|
||||
rowHeight?: number;
|
||||
colWidth?: number;
|
||||
theme: GrafanaTheme2;
|
||||
showValue: VisibilityMode;
|
||||
@ -49,7 +51,7 @@ export interface TimelineCoreOptions {
|
||||
label: (seriesIdx: number) => string;
|
||||
getTimeRange: () => TimeRange;
|
||||
formatValue?: (seriesIdx: number, value: any) => string;
|
||||
getFieldConfig: (seriesIdx: number) => TimelineFieldConfig;
|
||||
getFieldConfig: (seriesIdx: number) => StateTimeLineFieldConfig | StatusHistoryFieldConfig;
|
||||
onHover: (seriesIdx: number, valueIdx: number, rect: Rect) => void;
|
||||
onLeave: () => void;
|
||||
}
|
||||
@ -567,7 +569,7 @@ export function getConfig(opts: TimelineCoreOptions) {
|
||||
};
|
||||
}
|
||||
|
||||
function getFillColor(fieldConfig: TimelineFieldConfig, color: string) {
|
||||
function getFillColor(fieldConfig: { fillOpacity?: number; lineWidth?: number }, color: string) {
|
||||
// if #rgba with pre-existing alpha. ignore fieldConfig.fillOpacity
|
||||
// e.g. thresholds with opacity
|
||||
if (color[0] === '#' && color.length === 9) {
|
@ -24,7 +24,15 @@ import {
|
||||
TimeRange,
|
||||
} from '@grafana/data';
|
||||
import { maybeSortFrame } from '@grafana/data/src/transformations/transformers/joinDataFrames';
|
||||
import { VizLegendOptions, AxisPlacement, ScaleDirection, ScaleOrientation } from '@grafana/schema';
|
||||
import {
|
||||
VizLegendOptions,
|
||||
AxisPlacement,
|
||||
ScaleDirection,
|
||||
ScaleOrientation,
|
||||
VisibilityMode,
|
||||
TimelineValueAlignment,
|
||||
HideableFieldConfig,
|
||||
} from '@grafana/schema';
|
||||
import {
|
||||
FIXED_UNIT,
|
||||
SeriesVisibilityChangeMode,
|
||||
@ -38,9 +46,37 @@ import { PlotTooltipInterpolator } from '@grafana/ui/src/components/uPlot/types'
|
||||
import { preparePlotData2, getStackingGroups } from '@grafana/ui/src/components/uPlot/utils';
|
||||
|
||||
import { getConfig, TimelineCoreOptions } from './timeline';
|
||||
import { TimelineFieldConfig, TimelineOptions } from './types';
|
||||
|
||||
const defaultConfig: TimelineFieldConfig = {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface UPlotConfigOptions {
|
||||
frame: DataFrame;
|
||||
theme: GrafanaTheme2;
|
||||
mode: TimelineMode;
|
||||
sync?: () => DashboardCursorSync;
|
||||
rowHeight?: number;
|
||||
colWidth?: number;
|
||||
showValue: VisibilityMode;
|
||||
alignValue?: TimelineValueAlignment;
|
||||
mergeValues?: boolean;
|
||||
getValueColor: (frameIdx: number, fieldIdx: number, value: any) => string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface PanelFieldConfig extends HideableFieldConfig {
|
||||
fillOpacity?: number;
|
||||
lineWidth?: number;
|
||||
}
|
||||
|
||||
export enum TimelineMode {
|
||||
Changes = 'changes',
|
||||
Samples = 'samples',
|
||||
}
|
||||
|
||||
const defaultConfig: PanelFieldConfig = {
|
||||
lineWidth: 0,
|
||||
fillOpacity: 80,
|
||||
};
|
||||
@ -52,7 +88,7 @@ export function mapMouseEventToMode(event: React.MouseEvent): SeriesVisibilityCh
|
||||
return SeriesVisibilityChangeMode.ToggleSelection;
|
||||
}
|
||||
|
||||
export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
||||
export const preparePlotConfigBuilder: UPlotConfigPrepFn<UPlotConfigOptions> = ({
|
||||
frame,
|
||||
theme,
|
||||
timeZones,
|
||||
@ -92,12 +128,11 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
||||
};
|
||||
|
||||
const opts: TimelineCoreOptions = {
|
||||
// should expose in panel config
|
||||
mode: mode!,
|
||||
numSeries: frame.fields.length - 1,
|
||||
isDiscrete: (seriesIdx) => isDiscrete(frame.fields[seriesIdx]),
|
||||
mergeValues,
|
||||
rowHeight: rowHeight!,
|
||||
rowHeight: rowHeight,
|
||||
colWidth: colWidth,
|
||||
showValue: showValue!,
|
||||
alignValue,
|
||||
@ -209,8 +244,8 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
||||
}
|
||||
|
||||
const field = frame.fields[i];
|
||||
const config: FieldConfig<TimelineFieldConfig> = field.config;
|
||||
const customConfig: TimelineFieldConfig = {
|
||||
const config: FieldConfig<PanelFieldConfig> = field.config;
|
||||
const customConfig: PanelFieldConfig = {
|
||||
...defaultConfig,
|
||||
...config.custom,
|
||||
};
|
@ -21,16 +21,14 @@ import (
|
||||
)
|
||||
|
||||
var skipPlugins = map[string]bool{
|
||||
"canvas": true,
|
||||
"heatmap": true,
|
||||
"candlestick": true,
|
||||
"state-timeline": true,
|
||||
"status-history": true,
|
||||
"table": true,
|
||||
"timeseries": true,
|
||||
"influxdb": true, // plugin.json fails validation (defaultMatchFormat)
|
||||
"mixed": true, // plugin.json fails validation (mixed)
|
||||
"opentsdb": true, // plugin.json fails validation (defaultMatchFormat)
|
||||
"canvas": true,
|
||||
"heatmap": true,
|
||||
"candlestick": true,
|
||||
"table": true,
|
||||
"timeseries": true,
|
||||
"influxdb": true, // plugin.json fails validation (defaultMatchFormat)
|
||||
"mixed": true, // plugin.json fails validation (mixed)
|
||||
"opentsdb": true, // plugin.json fails validation (defaultMatchFormat)
|
||||
}
|
||||
|
||||
const sep = string(filepath.Separator)
|
||||
|
@ -33,9 +33,9 @@ import {
|
||||
import { PropDiffFn } from '@grafana/ui/src/components/GraphNG/GraphNG';
|
||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||
import { getFieldLegendItem } from 'app/core/components/TimelineChart/utils';
|
||||
|
||||
import { DataHoverView } from '../geomap/components/DataHoverView';
|
||||
import { getFieldLegendItem } from '../state-timeline/utils';
|
||||
|
||||
import { PanelOptions } from './panelcfg.gen';
|
||||
import { prepareBarChartDisplayValues, preparePlotConfigBuilder } from './utils';
|
||||
|
@ -9,9 +9,9 @@ import { getMinMaxAndDelta } from '@grafana/data/src/field/scale';
|
||||
import { useStyles2, VizLegendItem } from '@grafana/ui';
|
||||
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
||||
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
|
||||
import { getThresholdItems } from 'app/core/components/TimelineChart/utils';
|
||||
import { config } from 'app/core/config';
|
||||
import { DimensionSupplier } from 'app/features/dimensions';
|
||||
import { getThresholdItems } from 'app/plugins/panel/state-timeline/utils';
|
||||
|
||||
import { StyleConfigState } from '../style/types';
|
||||
import { MapLayerState } from '../types';
|
||||
|
@ -12,6 +12,12 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||
import { TimelineChart } from 'app/core/components/TimelineChart/TimelineChart';
|
||||
import {
|
||||
prepareTimelineFields,
|
||||
prepareTimelineLegendItems,
|
||||
TimelineMode,
|
||||
} from 'app/core/components/TimelineChart/utils';
|
||||
import { getLastStreamingDataFramePacket } from 'app/features/live/data/StreamingDataFrame';
|
||||
|
||||
import { AnnotationEditorPlugin } from '../timeseries/plugins/AnnotationEditorPlugin';
|
||||
@ -20,13 +26,11 @@ import { OutsideRangePlugin } from '../timeseries/plugins/OutsideRangePlugin';
|
||||
import { getTimezones } from '../timeseries/utils';
|
||||
|
||||
import { StateTimelineTooltip } from './StateTimelineTooltip';
|
||||
import { TimelineChart } from './TimelineChart';
|
||||
import { TimelineMode, TimelineOptions } from './types';
|
||||
import { prepareTimelineFields, prepareTimelineLegendItems } from './utils';
|
||||
import { PanelOptions } from './panelcfg.gen';
|
||||
|
||||
const TOOLTIP_OFFSET = 10;
|
||||
|
||||
interface TimelinePanelProps extends PanelProps<TimelineOptions> {}
|
||||
interface TimelinePanelProps extends PanelProps<PanelOptions> {}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
|
@ -10,8 +10,7 @@ import {
|
||||
LinkModel,
|
||||
} from '@grafana/data';
|
||||
import { MenuItem, SeriesTableRow, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { findNextStateIndex, fmtDuration } from './utils';
|
||||
import { findNextStateIndex, fmtDuration } from 'app/core/components/TimelineChart/utils';
|
||||
|
||||
interface StateTimelineTooltipProps {
|
||||
data: DataFrame[];
|
||||
|
@ -2,15 +2,15 @@ import { isArray } from 'lodash';
|
||||
|
||||
import { FieldConfigSource, MappingType, PanelModel, ValueMap } from '@grafana/data';
|
||||
|
||||
import { TimelineFieldConfig, TimelineOptions } from './types';
|
||||
import { PanelFieldConfig, PanelOptions } from './panelcfg.gen';
|
||||
|
||||
// This is called when the panel changes from another panel
|
||||
export const timelinePanelChangedHandler = (
|
||||
panel: PanelModel<Partial<TimelineOptions>> | any,
|
||||
panel: PanelModel<Partial<PanelOptions>> | any,
|
||||
prevPluginId: string,
|
||||
prevOptions: any
|
||||
) => {
|
||||
let options = (panel.options ?? {}) as TimelineOptions;
|
||||
let options = (panel.options ?? {}) as PanelOptions;
|
||||
|
||||
// Changing from angular singlestat
|
||||
if (prevPluginId === 'natel-discrete-panel' && prevOptions.angular) {
|
||||
@ -21,7 +21,7 @@ export const timelinePanelChangedHandler = (
|
||||
fieldConfig.defaults.unit = oldOptions.units;
|
||||
}
|
||||
|
||||
const custom: TimelineFieldConfig = {
|
||||
const custom: PanelFieldConfig = {
|
||||
fillOpacity: 100,
|
||||
lineWidth: 0,
|
||||
};
|
||||
|
@ -12,10 +12,10 @@ import { SpanNullsEditor } from '../timeseries/SpanNullsEditor';
|
||||
|
||||
import { StateTimelinePanel } from './StateTimelinePanel';
|
||||
import { timelinePanelChangedHandler } from './migrations';
|
||||
import { PanelOptions, PanelFieldConfig, defaultPanelOptions, defaultPanelFieldConfig } from './panelcfg.gen';
|
||||
import { StatTimelineSuggestionsSupplier } from './suggestions';
|
||||
import { TimelineOptions, TimelineFieldConfig, defaultPanelOptions, defaultTimelineFieldConfig } from './types';
|
||||
|
||||
export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(StateTimelinePanel)
|
||||
export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(StateTimelinePanel)
|
||||
.setPanelChangeHandler(timelinePanelChangedHandler)
|
||||
.useFieldConfig({
|
||||
standardOptions: {
|
||||
@ -33,7 +33,7 @@ export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(Stat
|
||||
.addSliderInput({
|
||||
path: 'lineWidth',
|
||||
name: 'Line width',
|
||||
defaultValue: defaultTimelineFieldConfig.lineWidth,
|
||||
defaultValue: defaultPanelFieldConfig.lineWidth,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 10,
|
||||
@ -43,7 +43,7 @@ export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(Stat
|
||||
.addSliderInput({
|
||||
path: 'fillOpacity',
|
||||
name: 'Fill opacity',
|
||||
defaultValue: defaultTimelineFieldConfig.fillOpacity,
|
||||
defaultValue: defaultPanelFieldConfig.fillOpacity,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
|
@ -15,33 +15,34 @@
|
||||
package grafanaplugin
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||
ui "github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||
)
|
||||
|
||||
composableKinds: PanelCfg: {
|
||||
maturity: "experimental"
|
||||
lineage: {
|
||||
seqs: [
|
||||
{
|
||||
schemas: [
|
||||
{
|
||||
TimelineMode: "changes" | "samples" @cuetsy(kind="enum")
|
||||
TimelineValueAlignment: "center" | "left" | "right" @cuetsy(kind="type")
|
||||
PanelOptions: {
|
||||
// FIXME ts comments indicate this shouldn't be in the saved model, but currently is emitted
|
||||
mode?: TimelineMode
|
||||
common.OptionsWithLegend
|
||||
common.OptionsWithTooltip
|
||||
common.OptionsWithTimezones
|
||||
showValue: common.VisibilityMode | *"auto"
|
||||
rowHeight: number | *0.9
|
||||
colWidth?: number
|
||||
ui.OptionsWithLegend
|
||||
ui.OptionsWithTooltip
|
||||
ui.OptionsWithTimezones
|
||||
|
||||
//Show timeline values on chart
|
||||
showValue: ui.VisibilityMode | *"auto"
|
||||
//Controls the row height
|
||||
rowHeight: float & <=1 | *0.9
|
||||
//Merge equal consecutive values
|
||||
mergeValues?: bool | *true
|
||||
alignValue?: TimelineValueAlignment | *"left"
|
||||
//Controls value alignment on the timelines
|
||||
alignValue?: ui.TimelineValueAlignment | *"left"
|
||||
} @cuetsy(kind="interface")
|
||||
PanelFieldConfig: {
|
||||
common.HideableFieldConfig
|
||||
lineWidth?: number | *0
|
||||
fillOpacity?: number | *70
|
||||
ui.HideableFieldConfig
|
||||
lineWidth?: uint32 & <=10 | *0
|
||||
fillOpacity?: uint32 & <=100 | *70
|
||||
} @cuetsy(kind="interface")
|
||||
},
|
||||
]
|
||||
|
49
public/app/plugins/panel/state-timeline/panelcfg.gen.ts
Normal file
49
public/app/plugins/panel/state-timeline/panelcfg.gen.ts
Normal file
@ -0,0 +1,49 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
//
|
||||
// Generated by:
|
||||
// public/app/plugins/gen.go
|
||||
// Using jennies:
|
||||
// TSTypesJenny
|
||||
// PluginTSTypesJenny
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const PanelCfgModelVersion = Object.freeze([0, 0]);
|
||||
|
||||
export interface PanelOptions extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones {
|
||||
/**
|
||||
* Controls value alignment on the timelines
|
||||
*/
|
||||
alignValue?: ui.TimelineValueAlignment;
|
||||
/**
|
||||
* Merge equal consecutive values
|
||||
*/
|
||||
mergeValues?: boolean;
|
||||
/**
|
||||
* Controls the row height
|
||||
*/
|
||||
rowHeight: number;
|
||||
/**
|
||||
* Show timeline values on chart
|
||||
*/
|
||||
showValue: ui.VisibilityMode;
|
||||
}
|
||||
|
||||
export const defaultPanelOptions: Partial<PanelOptions> = {
|
||||
alignValue: 'left',
|
||||
mergeValues: true,
|
||||
rowHeight: 0.9,
|
||||
showValue: ui.VisibilityMode.Auto,
|
||||
};
|
||||
|
||||
export interface PanelFieldConfig extends ui.HideableFieldConfig {
|
||||
fillOpacity?: number;
|
||||
lineWidth?: number;
|
||||
}
|
||||
|
||||
export const defaultPanelFieldConfig: Partial<PanelFieldConfig> = {
|
||||
fillOpacity: 70,
|
||||
lineWidth: 0,
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { VisualizationSuggestionsBuilder } from '@grafana/data';
|
||||
import { SuggestionName } from 'app/types/suggestions';
|
||||
|
||||
import { TimelineFieldConfig, TimelineOptions } from './types';
|
||||
import { PanelFieldConfig, PanelOptions } from './panelcfg.gen';
|
||||
|
||||
export class StatTimelineSuggestionsSupplier {
|
||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||
@ -26,7 +26,7 @@ export class StatTimelineSuggestionsSupplier {
|
||||
return;
|
||||
}
|
||||
|
||||
const list = builder.getListAppender<TimelineOptions, TimelineFieldConfig>({
|
||||
const list = builder.getListAppender<PanelOptions, PanelFieldConfig>({
|
||||
name: '',
|
||||
pluginId: 'state-timeline',
|
||||
options: {},
|
||||
|
@ -1,66 +0,0 @@
|
||||
import { DashboardCursorSync } from '@grafana/data';
|
||||
import {
|
||||
HideableFieldConfig,
|
||||
OptionsWithLegend,
|
||||
OptionsWithTimezones,
|
||||
OptionsWithTooltip,
|
||||
VisibilityMode,
|
||||
} from '@grafana/schema';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface TimelineOptions extends OptionsWithLegend, OptionsWithTooltip, OptionsWithTimezones {
|
||||
mode: TimelineMode; // not in the saved model!
|
||||
|
||||
showValue: VisibilityMode;
|
||||
rowHeight: number;
|
||||
|
||||
// only used for "samples" mode (status-history)
|
||||
colWidth?: number;
|
||||
// only used in "changes" mode (state-timeline)
|
||||
mergeValues?: boolean;
|
||||
// only used in "changes" mode (state-timeline)
|
||||
alignValue?: TimelineValueAlignment;
|
||||
|
||||
sync?: () => DashboardCursorSync;
|
||||
getValueColor?: (frameIdx: number, fieldIdx: number, value: any) => string;
|
||||
}
|
||||
|
||||
export type TimelineValueAlignment = 'center' | 'left' | 'right';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface TimelineFieldConfig extends HideableFieldConfig {
|
||||
lineWidth?: number; // 0
|
||||
fillOpacity?: number; // 100
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export const defaultPanelOptions: Partial<TimelineOptions> = {
|
||||
showValue: VisibilityMode.Auto,
|
||||
alignValue: 'left',
|
||||
mergeValues: true,
|
||||
rowHeight: 0.9,
|
||||
};
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export const defaultTimelineFieldConfig: TimelineFieldConfig = {
|
||||
lineWidth: 0,
|
||||
fillOpacity: 70,
|
||||
};
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export enum TimelineMode {
|
||||
// state-timeline
|
||||
Changes = 'changes',
|
||||
// status-history
|
||||
Samples = 'samples',
|
||||
}
|
@ -12,19 +12,22 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||
import { TimelineChart } from 'app/core/components/TimelineChart/TimelineChart';
|
||||
import {
|
||||
prepareTimelineFields,
|
||||
prepareTimelineLegendItems,
|
||||
TimelineMode,
|
||||
} from 'app/core/components/TimelineChart/utils';
|
||||
|
||||
import { TimelineChart } from '../state-timeline/TimelineChart';
|
||||
import { TimelineMode } from '../state-timeline/types';
|
||||
import { prepareTimelineFields, prepareTimelineLegendItems } from '../state-timeline/utils';
|
||||
import { OutsideRangePlugin } from '../timeseries/plugins/OutsideRangePlugin';
|
||||
import { getTimezones } from '../timeseries/utils';
|
||||
|
||||
import { StatusHistoryTooltip } from './StatusHistoryTooltip';
|
||||
import { StatusPanelOptions } from './types';
|
||||
import { PanelOptions } from './panelcfg.gen';
|
||||
|
||||
const TOOLTIP_OFFSET = 10;
|
||||
|
||||
interface TimelinePanelProps extends PanelProps<StatusPanelOptions> {}
|
||||
interface TimelinePanelProps extends PanelProps<PanelOptions> {}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
@ -193,7 +196,6 @@ export const StatusHistoryPanel: React.FC<TimelinePanelProps> = ({
|
||||
height={height}
|
||||
legendItems={legendItems}
|
||||
{...options}
|
||||
// hardcoded
|
||||
mode={TimelineMode.Samples}
|
||||
>
|
||||
{(config, alignedFrame) => {
|
||||
|
@ -3,10 +3,10 @@ import { VisibilityMode } from '@grafana/schema';
|
||||
import { commonOptionsBuilder } from '@grafana/ui';
|
||||
|
||||
import { StatusHistoryPanel } from './StatusHistoryPanel';
|
||||
import { PanelOptions, PanelFieldConfig, defaultPanelFieldConfig } from './panelcfg.gen';
|
||||
import { StatusHistorySuggestionsSupplier } from './suggestions';
|
||||
import { StatusPanelOptions, StatusFieldConfig, defaultStatusFieldConfig } from './types';
|
||||
|
||||
export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(StatusHistoryPanel)
|
||||
export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(StatusHistoryPanel)
|
||||
.useFieldConfig({
|
||||
standardOptions: {
|
||||
[FieldConfigProperty.Color]: {
|
||||
@ -23,7 +23,7 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
||||
.addSliderInput({
|
||||
path: 'lineWidth',
|
||||
name: 'Line width',
|
||||
defaultValue: defaultStatusFieldConfig.lineWidth,
|
||||
defaultValue: defaultPanelFieldConfig.lineWidth,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 10,
|
||||
@ -33,7 +33,7 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
||||
.addSliderInput({
|
||||
path: 'fillOpacity',
|
||||
name: 'Fill opacity',
|
||||
defaultValue: defaultStatusFieldConfig.fillOpacity,
|
||||
defaultValue: defaultPanelFieldConfig.fillOpacity,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
@ -56,16 +56,6 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
||||
},
|
||||
defaultValue: VisibilityMode.Auto,
|
||||
})
|
||||
.addSliderInput({
|
||||
path: 'rowHeight',
|
||||
name: 'Row height',
|
||||
defaultValue: 0.9,
|
||||
settings: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
},
|
||||
})
|
||||
.addSliderInput({
|
||||
path: 'colWidth',
|
||||
name: 'Column width',
|
||||
|
@ -15,28 +15,30 @@
|
||||
package grafanaplugin
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||
ui "github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||
)
|
||||
|
||||
composableKinds: PanelCfg: {
|
||||
maturity: "experimental"
|
||||
lineage: {
|
||||
seqs: [
|
||||
{
|
||||
schemas: [
|
||||
{
|
||||
PanelOptions: {
|
||||
common.OptionsWithLegend
|
||||
common.OptionsWithTooltip
|
||||
common.OptionsWithTimezones
|
||||
showValue: common.VisibilityMode
|
||||
rowHeight: number
|
||||
colWidth?: number
|
||||
alignValue: "center" | *"left" | "right"
|
||||
ui.OptionsWithLegend
|
||||
ui.OptionsWithTooltip
|
||||
ui.OptionsWithTimezones
|
||||
|
||||
//Show values on the columns
|
||||
showValue: ui.VisibilityMode | *"auto"
|
||||
//Controls the column width
|
||||
colWidth?: float & <=1 | *0.9
|
||||
} @cuetsy(kind="interface")
|
||||
PanelFieldConfig: {
|
||||
common.HideableFieldConfig
|
||||
lineWidth?: number | *1
|
||||
fillOpacity?: number | *70
|
||||
ui.HideableFieldConfig
|
||||
lineWidth?: uint32 & <=10 | *1
|
||||
fillOpacity?: uint32 & <=100 | *70
|
||||
} @cuetsy(kind="interface")
|
||||
},
|
||||
]
|
||||
|
39
public/app/plugins/panel/status-history/panelcfg.gen.ts
Normal file
39
public/app/plugins/panel/status-history/panelcfg.gen.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
//
|
||||
// Generated by:
|
||||
// public/app/plugins/gen.go
|
||||
// Using jennies:
|
||||
// TSTypesJenny
|
||||
// PluginTSTypesJenny
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const PanelCfgModelVersion = Object.freeze([0, 0]);
|
||||
|
||||
export interface PanelOptions extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones {
|
||||
/**
|
||||
* Controls the column width
|
||||
*/
|
||||
colWidth?: number;
|
||||
/**
|
||||
* Show values on the columns
|
||||
*/
|
||||
showValue: ui.VisibilityMode;
|
||||
}
|
||||
|
||||
export const defaultPanelOptions: Partial<PanelOptions> = {
|
||||
colWidth: 0.9,
|
||||
showValue: ui.VisibilityMode.Auto,
|
||||
};
|
||||
|
||||
export interface PanelFieldConfig extends ui.HideableFieldConfig {
|
||||
fillOpacity?: number;
|
||||
lineWidth?: number;
|
||||
}
|
||||
|
||||
export const defaultPanelFieldConfig: Partial<PanelFieldConfig> = {
|
||||
fillOpacity: 70,
|
||||
lineWidth: 1,
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { FieldColorModeId, VisualizationSuggestionsBuilder } from '@grafana/data';
|
||||
import { SuggestionName } from 'app/types/suggestions';
|
||||
|
||||
import { StatusPanelOptions, StatusFieldConfig } from './types';
|
||||
import { PanelOptions, PanelFieldConfig } from './panelcfg.gen';
|
||||
|
||||
export class StatusHistorySuggestionsSupplier {
|
||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||
@ -31,7 +31,7 @@ export class StatusHistorySuggestionsSupplier {
|
||||
return;
|
||||
}
|
||||
|
||||
const list = builder.getListAppender<StatusPanelOptions, StatusFieldConfig>({
|
||||
const list = builder.getListAppender<PanelOptions, PanelFieldConfig>({
|
||||
name: '',
|
||||
pluginId: 'status-history',
|
||||
options: {},
|
||||
|
@ -1,32 +0,0 @@
|
||||
import {
|
||||
HideableFieldConfig,
|
||||
VisibilityMode,
|
||||
OptionsWithTooltip,
|
||||
OptionsWithLegend,
|
||||
OptionsWithTimezones,
|
||||
} from '@grafana/schema';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface StatusPanelOptions extends OptionsWithTooltip, OptionsWithLegend, OptionsWithTimezones {
|
||||
showValue: VisibilityMode;
|
||||
rowHeight: number;
|
||||
colWidth?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface StatusFieldConfig extends HideableFieldConfig {
|
||||
lineWidth?: number; // 0
|
||||
fillOpacity?: number; // 100
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export const defaultStatusFieldConfig: StatusFieldConfig = {
|
||||
lineWidth: 1,
|
||||
fillOpacity: 70,
|
||||
};
|
Loading…
Reference in New Issue
Block a user