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.", "1"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
[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": [
|
"public/app/core/components/connectWithCleanUp.tsx:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
[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, "Unexpected any. Specify a different type.", "1"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "2"]
|
[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": [
|
"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.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[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.", "6"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "7"]
|
[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": [
|
"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.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[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');
|
export type FieldTextAlignment = ('auto' | 'left' | 'right' | 'center');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the value alignment in the TimelineChart component
|
||||||
|
*/
|
||||||
|
export type TimelineValueAlignment = ('center' | 'left' | 'right');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO docs
|
* TODO docs
|
||||||
*/
|
*/
|
||||||
|
@ -193,6 +193,9 @@ BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(
|
|||||||
// TODO docs
|
// TODO docs
|
||||||
FieldTextAlignment: "auto" | "left" | "right" | "center" @cuetsy(kind="type")
|
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
|
// TODO docs
|
||||||
VizTextDisplayOptions: {
|
VizTextDisplayOptions: {
|
||||||
// Explicit title text size
|
// Explicit title text size
|
||||||
|
@ -1349,6 +1349,30 @@
|
|||||||
"pluralMachineName": "serviceaccounts",
|
"pluralMachineName": "serviceaccounts",
|
||||||
"pluralName": "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": {
|
"statpanelcfg": {
|
||||||
"category": "composable",
|
"category": "composable",
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
@ -1373,6 +1397,30 @@
|
|||||||
"pluralName": "StatPanelCfgs",
|
"pluralName": "StatPanelCfgs",
|
||||||
"schemaInterface": "PanelCfg"
|
"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": {
|
"tableoldpanelcfg": {
|
||||||
"category": "composable",
|
"category": "composable",
|
||||||
"codeowners": [],
|
"codeowners": [],
|
||||||
@ -1744,7 +1792,9 @@
|
|||||||
"postgresqldatasourcecfg",
|
"postgresqldatasourcecfg",
|
||||||
"prometheusdataquery",
|
"prometheusdataquery",
|
||||||
"prometheusdatasourcecfg",
|
"prometheusdatasourcecfg",
|
||||||
|
"statetimelinepanelcfg",
|
||||||
"statpanelcfg",
|
"statpanelcfg",
|
||||||
|
"statushistorypanelcfg",
|
||||||
"tableoldpanelcfg",
|
"tableoldpanelcfg",
|
||||||
"tempodataquery",
|
"tempodataquery",
|
||||||
"tempodatasourcecfg",
|
"tempodatasourcecfg",
|
||||||
@ -1757,7 +1807,7 @@
|
|||||||
"zipkindataquery",
|
"zipkindataquery",
|
||||||
"zipkindatasourcecfg"
|
"zipkindatasourcecfg"
|
||||||
],
|
],
|
||||||
"count": 63
|
"count": 65
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"name": "core",
|
"name": "core",
|
||||||
@ -1791,11 +1841,13 @@
|
|||||||
"histogrampanelcfg",
|
"histogrampanelcfg",
|
||||||
"newspanelcfg",
|
"newspanelcfg",
|
||||||
"piechartpanelcfg",
|
"piechartpanelcfg",
|
||||||
|
"statetimelinepanelcfg",
|
||||||
"statpanelcfg",
|
"statpanelcfg",
|
||||||
|
"statushistorypanelcfg",
|
||||||
"textpanelcfg",
|
"textpanelcfg",
|
||||||
"xychartpanelcfg"
|
"xychartpanelcfg"
|
||||||
],
|
],
|
||||||
"count": 12
|
"count": 14
|
||||||
},
|
},
|
||||||
"mature": {
|
"mature": {
|
||||||
"name": "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/nodeGraph", "nodeGraph", rt),
|
||||||
parsePluginOrPanic("public/app/plugins/panel/piechart", "piechart", rt),
|
parsePluginOrPanic("public/app/plugins/panel/piechart", "piechart", rt),
|
||||||
parsePluginOrPanic("public/app/plugins/panel/stat", "stat", 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/table-old", "table_old", rt),
|
||||||
parsePluginOrPanic("public/app/plugins/panel/text", "text", rt),
|
parsePluginOrPanic("public/app/plugins/panel/text", "text", rt),
|
||||||
parsePluginOrPanic("public/app/plugins/panel/traces", "traces", rt),
|
parsePluginOrPanic("public/app/plugins/panel/traces", "traces", rt),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DataFrame, FALLBACK_COLOR, FieldType, TimeRange } from '@grafana/data';
|
import { DataFrame, FALLBACK_COLOR, FieldType, TimeRange } from '@grafana/data';
|
||||||
import { VisibilityMode } from '@grafana/schema';
|
import { VisibilityMode, TimelineValueAlignment } from '@grafana/schema';
|
||||||
import {
|
import {
|
||||||
PanelContext,
|
PanelContext,
|
||||||
PanelContextRoot,
|
PanelContextRoot,
|
||||||
@ -13,17 +13,14 @@ import {
|
|||||||
VizLegendItem,
|
VizLegendItem,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
|
|
||||||
import { TimelineMode, TimelineOptions, TimelineValueAlignment } from './types';
|
import { preparePlotConfigBuilder, TimelineMode } from './utils';
|
||||||
import { preparePlotConfigBuilder } from './utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
export interface TimelineProps
|
export interface TimelineProps extends Omit<GraphNGProps, 'prepConfig' | 'propsToDiff' | 'renderLegend'> {
|
||||||
extends TimelineOptions,
|
|
||||||
Omit<GraphNGProps, 'prepConfig' | 'propsToDiff' | 'renderLegend'> {
|
|
||||||
mode: TimelineMode;
|
mode: TimelineMode;
|
||||||
rowHeight: number;
|
rowHeight?: number;
|
||||||
showValue: VisibilityMode;
|
showValue: VisibilityMode;
|
||||||
alignValue?: TimelineValueAlignment;
|
alignValue?: TimelineValueAlignment;
|
||||||
colWidth?: number;
|
colWidth?: number;
|
@ -2,12 +2,14 @@ import uPlot, { Cursor, Series } from 'uplot';
|
|||||||
|
|
||||||
import { GrafanaTheme2, TimeRange } from '@grafana/data';
|
import { GrafanaTheme2, TimeRange } from '@grafana/data';
|
||||||
import { alpha } from '@grafana/data/src/themes/colorManipulator';
|
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 { FIXED_UNIT } from '@grafana/ui/src/components/GraphNG/GraphNG';
|
||||||
import { distribute, SPACE_BETWEEN } from 'app/plugins/panel/barchart/distribute';
|
import { distribute, SPACE_BETWEEN } from 'app/plugins/panel/barchart/distribute';
|
||||||
import { pointWithin, Quadtree, Rect } from 'app/plugins/panel/barchart/quadtree';
|
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;
|
const { round, min, ceil } = Math;
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ export interface TimelineCoreOptions {
|
|||||||
mode: TimelineMode;
|
mode: TimelineMode;
|
||||||
alignValue?: TimelineValueAlignment;
|
alignValue?: TimelineValueAlignment;
|
||||||
numSeries: number;
|
numSeries: number;
|
||||||
rowHeight: number;
|
rowHeight?: number;
|
||||||
colWidth?: number;
|
colWidth?: number;
|
||||||
theme: GrafanaTheme2;
|
theme: GrafanaTheme2;
|
||||||
showValue: VisibilityMode;
|
showValue: VisibilityMode;
|
||||||
@ -49,7 +51,7 @@ export interface TimelineCoreOptions {
|
|||||||
label: (seriesIdx: number) => string;
|
label: (seriesIdx: number) => string;
|
||||||
getTimeRange: () => TimeRange;
|
getTimeRange: () => TimeRange;
|
||||||
formatValue?: (seriesIdx: number, value: any) => string;
|
formatValue?: (seriesIdx: number, value: any) => string;
|
||||||
getFieldConfig: (seriesIdx: number) => TimelineFieldConfig;
|
getFieldConfig: (seriesIdx: number) => StateTimeLineFieldConfig | StatusHistoryFieldConfig;
|
||||||
onHover: (seriesIdx: number, valueIdx: number, rect: Rect) => void;
|
onHover: (seriesIdx: number, valueIdx: number, rect: Rect) => void;
|
||||||
onLeave: () => 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
|
// if #rgba with pre-existing alpha. ignore fieldConfig.fillOpacity
|
||||||
// e.g. thresholds with opacity
|
// e.g. thresholds with opacity
|
||||||
if (color[0] === '#' && color.length === 9) {
|
if (color[0] === '#' && color.length === 9) {
|
@ -24,7 +24,15 @@ import {
|
|||||||
TimeRange,
|
TimeRange,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { maybeSortFrame } from '@grafana/data/src/transformations/transformers/joinDataFrames';
|
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 {
|
import {
|
||||||
FIXED_UNIT,
|
FIXED_UNIT,
|
||||||
SeriesVisibilityChangeMode,
|
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 { preparePlotData2, getStackingGroups } from '@grafana/ui/src/components/uPlot/utils';
|
||||||
|
|
||||||
import { getConfig, TimelineCoreOptions } from './timeline';
|
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,
|
lineWidth: 0,
|
||||||
fillOpacity: 80,
|
fillOpacity: 80,
|
||||||
};
|
};
|
||||||
@ -52,7 +88,7 @@ export function mapMouseEventToMode(event: React.MouseEvent): SeriesVisibilityCh
|
|||||||
return SeriesVisibilityChangeMode.ToggleSelection;
|
return SeriesVisibilityChangeMode.ToggleSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
export const preparePlotConfigBuilder: UPlotConfigPrepFn<UPlotConfigOptions> = ({
|
||||||
frame,
|
frame,
|
||||||
theme,
|
theme,
|
||||||
timeZones,
|
timeZones,
|
||||||
@ -92,12 +128,11 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const opts: TimelineCoreOptions = {
|
const opts: TimelineCoreOptions = {
|
||||||
// should expose in panel config
|
|
||||||
mode: mode!,
|
mode: mode!,
|
||||||
numSeries: frame.fields.length - 1,
|
numSeries: frame.fields.length - 1,
|
||||||
isDiscrete: (seriesIdx) => isDiscrete(frame.fields[seriesIdx]),
|
isDiscrete: (seriesIdx) => isDiscrete(frame.fields[seriesIdx]),
|
||||||
mergeValues,
|
mergeValues,
|
||||||
rowHeight: rowHeight!,
|
rowHeight: rowHeight,
|
||||||
colWidth: colWidth,
|
colWidth: colWidth,
|
||||||
showValue: showValue!,
|
showValue: showValue!,
|
||||||
alignValue,
|
alignValue,
|
||||||
@ -209,8 +244,8 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<TimelineOptions> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const field = frame.fields[i];
|
const field = frame.fields[i];
|
||||||
const config: FieldConfig<TimelineFieldConfig> = field.config;
|
const config: FieldConfig<PanelFieldConfig> = field.config;
|
||||||
const customConfig: TimelineFieldConfig = {
|
const customConfig: PanelFieldConfig = {
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
...config.custom,
|
...config.custom,
|
||||||
};
|
};
|
@ -21,16 +21,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var skipPlugins = map[string]bool{
|
var skipPlugins = map[string]bool{
|
||||||
"canvas": true,
|
"canvas": true,
|
||||||
"heatmap": true,
|
"heatmap": true,
|
||||||
"candlestick": true,
|
"candlestick": true,
|
||||||
"state-timeline": true,
|
"table": true,
|
||||||
"status-history": true,
|
"timeseries": true,
|
||||||
"table": true,
|
"influxdb": true, // plugin.json fails validation (defaultMatchFormat)
|
||||||
"timeseries": true,
|
"mixed": true, // plugin.json fails validation (mixed)
|
||||||
"influxdb": true, // plugin.json fails validation (defaultMatchFormat)
|
"opentsdb": 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)
|
const sep = string(filepath.Separator)
|
||||||
|
@ -33,9 +33,9 @@ import {
|
|||||||
import { PropDiffFn } from '@grafana/ui/src/components/GraphNG/GraphNG';
|
import { PropDiffFn } from '@grafana/ui/src/components/GraphNG/GraphNG';
|
||||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
||||||
|
import { getFieldLegendItem } from 'app/core/components/TimelineChart/utils';
|
||||||
|
|
||||||
import { DataHoverView } from '../geomap/components/DataHoverView';
|
import { DataHoverView } from '../geomap/components/DataHoverView';
|
||||||
import { getFieldLegendItem } from '../state-timeline/utils';
|
|
||||||
|
|
||||||
import { PanelOptions } from './panelcfg.gen';
|
import { PanelOptions } from './panelcfg.gen';
|
||||||
import { prepareBarChartDisplayValues, preparePlotConfigBuilder } from './utils';
|
import { prepareBarChartDisplayValues, preparePlotConfigBuilder } from './utils';
|
||||||
|
@ -9,9 +9,9 @@ import { getMinMaxAndDelta } from '@grafana/data/src/field/scale';
|
|||||||
import { useStyles2, VizLegendItem } from '@grafana/ui';
|
import { useStyles2, VizLegendItem } from '@grafana/ui';
|
||||||
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
||||||
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
|
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
|
||||||
|
import { getThresholdItems } from 'app/core/components/TimelineChart/utils';
|
||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
import { DimensionSupplier } from 'app/features/dimensions';
|
import { DimensionSupplier } from 'app/features/dimensions';
|
||||||
import { getThresholdItems } from 'app/plugins/panel/state-timeline/utils';
|
|
||||||
|
|
||||||
import { StyleConfigState } from '../style/types';
|
import { StyleConfigState } from '../style/types';
|
||||||
import { MapLayerState } from '../types';
|
import { MapLayerState } from '../types';
|
||||||
|
@ -12,6 +12,12 @@ import {
|
|||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
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 { getLastStreamingDataFramePacket } from 'app/features/live/data/StreamingDataFrame';
|
||||||
|
|
||||||
import { AnnotationEditorPlugin } from '../timeseries/plugins/AnnotationEditorPlugin';
|
import { AnnotationEditorPlugin } from '../timeseries/plugins/AnnotationEditorPlugin';
|
||||||
@ -20,13 +26,11 @@ import { OutsideRangePlugin } from '../timeseries/plugins/OutsideRangePlugin';
|
|||||||
import { getTimezones } from '../timeseries/utils';
|
import { getTimezones } from '../timeseries/utils';
|
||||||
|
|
||||||
import { StateTimelineTooltip } from './StateTimelineTooltip';
|
import { StateTimelineTooltip } from './StateTimelineTooltip';
|
||||||
import { TimelineChart } from './TimelineChart';
|
import { PanelOptions } from './panelcfg.gen';
|
||||||
import { TimelineMode, TimelineOptions } from './types';
|
|
||||||
import { prepareTimelineFields, prepareTimelineLegendItems } from './utils';
|
|
||||||
|
|
||||||
const TOOLTIP_OFFSET = 10;
|
const TOOLTIP_OFFSET = 10;
|
||||||
|
|
||||||
interface TimelinePanelProps extends PanelProps<TimelineOptions> {}
|
interface TimelinePanelProps extends PanelProps<PanelOptions> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
|
@ -10,8 +10,7 @@ import {
|
|||||||
LinkModel,
|
LinkModel,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { MenuItem, SeriesTableRow, useTheme2 } from '@grafana/ui';
|
import { MenuItem, SeriesTableRow, useTheme2 } from '@grafana/ui';
|
||||||
|
import { findNextStateIndex, fmtDuration } from 'app/core/components/TimelineChart/utils';
|
||||||
import { findNextStateIndex, fmtDuration } from './utils';
|
|
||||||
|
|
||||||
interface StateTimelineTooltipProps {
|
interface StateTimelineTooltipProps {
|
||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
|
@ -2,15 +2,15 @@ import { isArray } from 'lodash';
|
|||||||
|
|
||||||
import { FieldConfigSource, MappingType, PanelModel, ValueMap } from '@grafana/data';
|
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
|
// This is called when the panel changes from another panel
|
||||||
export const timelinePanelChangedHandler = (
|
export const timelinePanelChangedHandler = (
|
||||||
panel: PanelModel<Partial<TimelineOptions>> | any,
|
panel: PanelModel<Partial<PanelOptions>> | any,
|
||||||
prevPluginId: string,
|
prevPluginId: string,
|
||||||
prevOptions: any
|
prevOptions: any
|
||||||
) => {
|
) => {
|
||||||
let options = (panel.options ?? {}) as TimelineOptions;
|
let options = (panel.options ?? {}) as PanelOptions;
|
||||||
|
|
||||||
// Changing from angular singlestat
|
// Changing from angular singlestat
|
||||||
if (prevPluginId === 'natel-discrete-panel' && prevOptions.angular) {
|
if (prevPluginId === 'natel-discrete-panel' && prevOptions.angular) {
|
||||||
@ -21,7 +21,7 @@ export const timelinePanelChangedHandler = (
|
|||||||
fieldConfig.defaults.unit = oldOptions.units;
|
fieldConfig.defaults.unit = oldOptions.units;
|
||||||
}
|
}
|
||||||
|
|
||||||
const custom: TimelineFieldConfig = {
|
const custom: PanelFieldConfig = {
|
||||||
fillOpacity: 100,
|
fillOpacity: 100,
|
||||||
lineWidth: 0,
|
lineWidth: 0,
|
||||||
};
|
};
|
||||||
|
@ -12,10 +12,10 @@ import { SpanNullsEditor } from '../timeseries/SpanNullsEditor';
|
|||||||
|
|
||||||
import { StateTimelinePanel } from './StateTimelinePanel';
|
import { StateTimelinePanel } from './StateTimelinePanel';
|
||||||
import { timelinePanelChangedHandler } from './migrations';
|
import { timelinePanelChangedHandler } from './migrations';
|
||||||
|
import { PanelOptions, PanelFieldConfig, defaultPanelOptions, defaultPanelFieldConfig } from './panelcfg.gen';
|
||||||
import { StatTimelineSuggestionsSupplier } from './suggestions';
|
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)
|
.setPanelChangeHandler(timelinePanelChangedHandler)
|
||||||
.useFieldConfig({
|
.useFieldConfig({
|
||||||
standardOptions: {
|
standardOptions: {
|
||||||
@ -33,7 +33,7 @@ export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(Stat
|
|||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'lineWidth',
|
path: 'lineWidth',
|
||||||
name: 'Line width',
|
name: 'Line width',
|
||||||
defaultValue: defaultTimelineFieldConfig.lineWidth,
|
defaultValue: defaultPanelFieldConfig.lineWidth,
|
||||||
settings: {
|
settings: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 10,
|
max: 10,
|
||||||
@ -43,7 +43,7 @@ export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(Stat
|
|||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'fillOpacity',
|
path: 'fillOpacity',
|
||||||
name: 'Fill opacity',
|
name: 'Fill opacity',
|
||||||
defaultValue: defaultTimelineFieldConfig.fillOpacity,
|
defaultValue: defaultPanelFieldConfig.fillOpacity,
|
||||||
settings: {
|
settings: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100,
|
max: 100,
|
||||||
|
@ -15,33 +15,34 @@
|
|||||||
package grafanaplugin
|
package grafanaplugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/grafana/grafana/packages/grafana-schema/src/common"
|
ui "github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
composableKinds: PanelCfg: {
|
composableKinds: PanelCfg: {
|
||||||
|
maturity: "experimental"
|
||||||
lineage: {
|
lineage: {
|
||||||
seqs: [
|
seqs: [
|
||||||
{
|
{
|
||||||
schemas: [
|
schemas: [
|
||||||
{
|
{
|
||||||
TimelineMode: "changes" | "samples" @cuetsy(kind="enum")
|
|
||||||
TimelineValueAlignment: "center" | "left" | "right" @cuetsy(kind="type")
|
|
||||||
PanelOptions: {
|
PanelOptions: {
|
||||||
// FIXME ts comments indicate this shouldn't be in the saved model, but currently is emitted
|
ui.OptionsWithLegend
|
||||||
mode?: TimelineMode
|
ui.OptionsWithTooltip
|
||||||
common.OptionsWithLegend
|
ui.OptionsWithTimezones
|
||||||
common.OptionsWithTooltip
|
|
||||||
common.OptionsWithTimezones
|
//Show timeline values on chart
|
||||||
showValue: common.VisibilityMode | *"auto"
|
showValue: ui.VisibilityMode | *"auto"
|
||||||
rowHeight: number | *0.9
|
//Controls the row height
|
||||||
colWidth?: number
|
rowHeight: float & <=1 | *0.9
|
||||||
|
//Merge equal consecutive values
|
||||||
mergeValues?: bool | *true
|
mergeValues?: bool | *true
|
||||||
alignValue?: TimelineValueAlignment | *"left"
|
//Controls value alignment on the timelines
|
||||||
|
alignValue?: ui.TimelineValueAlignment | *"left"
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
PanelFieldConfig: {
|
PanelFieldConfig: {
|
||||||
common.HideableFieldConfig
|
ui.HideableFieldConfig
|
||||||
lineWidth?: number | *0
|
lineWidth?: uint32 & <=10 | *0
|
||||||
fillOpacity?: number | *70
|
fillOpacity?: uint32 & <=100 | *70
|
||||||
} @cuetsy(kind="interface")
|
} @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 { VisualizationSuggestionsBuilder } from '@grafana/data';
|
||||||
import { SuggestionName } from 'app/types/suggestions';
|
import { SuggestionName } from 'app/types/suggestions';
|
||||||
|
|
||||||
import { TimelineFieldConfig, TimelineOptions } from './types';
|
import { PanelFieldConfig, PanelOptions } from './panelcfg.gen';
|
||||||
|
|
||||||
export class StatTimelineSuggestionsSupplier {
|
export class StatTimelineSuggestionsSupplier {
|
||||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
@ -26,7 +26,7 @@ export class StatTimelineSuggestionsSupplier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const list = builder.getListAppender<TimelineOptions, TimelineFieldConfig>({
|
const list = builder.getListAppender<PanelOptions, PanelFieldConfig>({
|
||||||
name: '',
|
name: '',
|
||||||
pluginId: 'state-timeline',
|
pluginId: 'state-timeline',
|
||||||
options: {},
|
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';
|
} from '@grafana/ui';
|
||||||
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
import { HoverEvent, addTooltipSupport } from '@grafana/ui/src/components/uPlot/config/addTooltipSupport';
|
||||||
import { CloseButton } from 'app/core/components/CloseButton/CloseButton';
|
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 { OutsideRangePlugin } from '../timeseries/plugins/OutsideRangePlugin';
|
||||||
import { getTimezones } from '../timeseries/utils';
|
import { getTimezones } from '../timeseries/utils';
|
||||||
|
|
||||||
import { StatusHistoryTooltip } from './StatusHistoryTooltip';
|
import { StatusHistoryTooltip } from './StatusHistoryTooltip';
|
||||||
import { StatusPanelOptions } from './types';
|
import { PanelOptions } from './panelcfg.gen';
|
||||||
|
|
||||||
const TOOLTIP_OFFSET = 10;
|
const TOOLTIP_OFFSET = 10;
|
||||||
|
|
||||||
interface TimelinePanelProps extends PanelProps<StatusPanelOptions> {}
|
interface TimelinePanelProps extends PanelProps<PanelOptions> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @alpha
|
||||||
@ -193,7 +196,6 @@ export const StatusHistoryPanel: React.FC<TimelinePanelProps> = ({
|
|||||||
height={height}
|
height={height}
|
||||||
legendItems={legendItems}
|
legendItems={legendItems}
|
||||||
{...options}
|
{...options}
|
||||||
// hardcoded
|
|
||||||
mode={TimelineMode.Samples}
|
mode={TimelineMode.Samples}
|
||||||
>
|
>
|
||||||
{(config, alignedFrame) => {
|
{(config, alignedFrame) => {
|
||||||
|
@ -3,10 +3,10 @@ import { VisibilityMode } from '@grafana/schema';
|
|||||||
import { commonOptionsBuilder } from '@grafana/ui';
|
import { commonOptionsBuilder } from '@grafana/ui';
|
||||||
|
|
||||||
import { StatusHistoryPanel } from './StatusHistoryPanel';
|
import { StatusHistoryPanel } from './StatusHistoryPanel';
|
||||||
|
import { PanelOptions, PanelFieldConfig, defaultPanelFieldConfig } from './panelcfg.gen';
|
||||||
import { StatusHistorySuggestionsSupplier } from './suggestions';
|
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({
|
.useFieldConfig({
|
||||||
standardOptions: {
|
standardOptions: {
|
||||||
[FieldConfigProperty.Color]: {
|
[FieldConfigProperty.Color]: {
|
||||||
@ -23,7 +23,7 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
|||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'lineWidth',
|
path: 'lineWidth',
|
||||||
name: 'Line width',
|
name: 'Line width',
|
||||||
defaultValue: defaultStatusFieldConfig.lineWidth,
|
defaultValue: defaultPanelFieldConfig.lineWidth,
|
||||||
settings: {
|
settings: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 10,
|
max: 10,
|
||||||
@ -33,7 +33,7 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
|||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'fillOpacity',
|
path: 'fillOpacity',
|
||||||
name: 'Fill opacity',
|
name: 'Fill opacity',
|
||||||
defaultValue: defaultStatusFieldConfig.fillOpacity,
|
defaultValue: defaultPanelFieldConfig.fillOpacity,
|
||||||
settings: {
|
settings: {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100,
|
max: 100,
|
||||||
@ -56,16 +56,6 @@ export const plugin = new PanelPlugin<StatusPanelOptions, StatusFieldConfig>(Sta
|
|||||||
},
|
},
|
||||||
defaultValue: VisibilityMode.Auto,
|
defaultValue: VisibilityMode.Auto,
|
||||||
})
|
})
|
||||||
.addSliderInput({
|
|
||||||
path: 'rowHeight',
|
|
||||||
name: 'Row height',
|
|
||||||
defaultValue: 0.9,
|
|
||||||
settings: {
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
step: 0.01,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.addSliderInput({
|
.addSliderInput({
|
||||||
path: 'colWidth',
|
path: 'colWidth',
|
||||||
name: 'Column width',
|
name: 'Column width',
|
||||||
|
@ -15,28 +15,30 @@
|
|||||||
package grafanaplugin
|
package grafanaplugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/grafana/grafana/packages/grafana-schema/src/common"
|
ui "github.com/grafana/grafana/packages/grafana-schema/src/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
composableKinds: PanelCfg: {
|
composableKinds: PanelCfg: {
|
||||||
|
maturity: "experimental"
|
||||||
lineage: {
|
lineage: {
|
||||||
seqs: [
|
seqs: [
|
||||||
{
|
{
|
||||||
schemas: [
|
schemas: [
|
||||||
{
|
{
|
||||||
PanelOptions: {
|
PanelOptions: {
|
||||||
common.OptionsWithLegend
|
ui.OptionsWithLegend
|
||||||
common.OptionsWithTooltip
|
ui.OptionsWithTooltip
|
||||||
common.OptionsWithTimezones
|
ui.OptionsWithTimezones
|
||||||
showValue: common.VisibilityMode
|
|
||||||
rowHeight: number
|
//Show values on the columns
|
||||||
colWidth?: number
|
showValue: ui.VisibilityMode | *"auto"
|
||||||
alignValue: "center" | *"left" | "right"
|
//Controls the column width
|
||||||
|
colWidth?: float & <=1 | *0.9
|
||||||
} @cuetsy(kind="interface")
|
} @cuetsy(kind="interface")
|
||||||
PanelFieldConfig: {
|
PanelFieldConfig: {
|
||||||
common.HideableFieldConfig
|
ui.HideableFieldConfig
|
||||||
lineWidth?: number | *1
|
lineWidth?: uint32 & <=10 | *1
|
||||||
fillOpacity?: number | *70
|
fillOpacity?: uint32 & <=100 | *70
|
||||||
} @cuetsy(kind="interface")
|
} @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 { FieldColorModeId, VisualizationSuggestionsBuilder } from '@grafana/data';
|
||||||
import { SuggestionName } from 'app/types/suggestions';
|
import { SuggestionName } from 'app/types/suggestions';
|
||||||
|
|
||||||
import { StatusPanelOptions, StatusFieldConfig } from './types';
|
import { PanelOptions, PanelFieldConfig } from './panelcfg.gen';
|
||||||
|
|
||||||
export class StatusHistorySuggestionsSupplier {
|
export class StatusHistorySuggestionsSupplier {
|
||||||
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
|
||||||
@ -31,7 +31,7 @@ export class StatusHistorySuggestionsSupplier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const list = builder.getListAppender<StatusPanelOptions, StatusFieldConfig>({
|
const list = builder.getListAppender<PanelOptions, PanelFieldConfig>({
|
||||||
name: '',
|
name: '',
|
||||||
pluginId: 'status-history',
|
pluginId: 'status-history',
|
||||||
options: {},
|
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