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>
pull/62102/head
Victor Marin 2 years ago committed by GitHub
parent 6c9174a766
commit 6a93c77082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      .betterer.results
  2. 41
      docs/sources/developers/kinds/composable/statetimelinepanelcfg/schema-reference.md
  3. 39
      docs/sources/developers/kinds/composable/statushistorypanelcfg/schema-reference.md
  4. 5
      packages/grafana-schema/src/common/common.gen.ts
  5. 3
      packages/grafana-schema/src/common/mudball.cue
  6. 56
      pkg/kindsys/report.json
  7. 2
      pkg/plugins/pfs/corelist/corelist_load_gen.go
  8. 11
      public/app/core/components/TimelineChart/TimelineChart.tsx
  9. 12
      public/app/core/components/TimelineChart/timeline.ts
  10. 0
      public/app/core/components/TimelineChart/utils.test.ts
  11. 51
      public/app/core/components/TimelineChart/utils.ts
  12. 18
      public/app/plugins/gen.go
  13. 2
      public/app/plugins/panel/barchart/BarChartPanel.tsx
  14. 2
      public/app/plugins/panel/geomap/components/MarkersLegend.tsx
  15. 12
      public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx
  16. 3
      public/app/plugins/panel/state-timeline/StateTimelineTooltip.tsx
  17. 8
      public/app/plugins/panel/state-timeline/migrations.ts
  18. 8
      public/app/plugins/panel/state-timeline/module.tsx
  19. 31
      public/app/plugins/panel/state-timeline/panelcfg.cue
  20. 49
      public/app/plugins/panel/state-timeline/panelcfg.gen.ts
  21. 4
      public/app/plugins/panel/state-timeline/suggestions.ts
  22. 66
      public/app/plugins/panel/state-timeline/types.ts
  23. 14
      public/app/plugins/panel/status-history/StatusHistoryPanel.tsx
  24. 18
      public/app/plugins/panel/status-history/module.tsx
  25. 24
      public/app/plugins/panel/status-history/panelcfg.cue
  26. 39
      public/app/plugins/panel/status-history/panelcfg.gen.ts
  27. 4
      public/app/plugins/panel/status-history/suggestions.ts
  28. 32
      public/app/plugins/panel/status-history/types.ts

@ -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")
},
]

@ -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")
},
]

@ -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…
Cancel
Save