Cue: Update Text, Stat, and Annolist panel cue schemas (#49479)

* user essentials mob! 🔱

* user essentials mob! 🔱

* user essentials mob! 🔱

lastFile:public/app/plugins/panel/stat/types.ts

* user essentials mob! 🔱

* user essentials mob! 🔱

* Use generate defaults, and fix a few remaining issues

* Add annolist to dashboard dist plugins

* minor fixes

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
Co-authored-by: Joao Silva <joao.silva@grafana.com>
Co-authored-by: Alexandra Vargas <alexa1866@gmail.com>
Co-authored-by: sam boyer <sdboyer@grafana.com>
This commit is contained in:
Josh Hunt 2022-05-25 12:07:32 +01:00 committed by GitHub
parent 5455174de5
commit 9092150143
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 151 additions and 108 deletions

View File

@ -216,7 +216,7 @@ export enum BigValueTextMode {
Name = 'name',
None = 'none',
Value = 'value',
Value_and_name = 'value_and_name',
ValueAndName = 'value_and_name',
}
export type FieldTextAlignment = 'auto' | 'left' | 'right' | 'center';

View File

@ -48,6 +48,6 @@ BigValueGraphMode: "none" | "line" | "area" @cuetsy(kind="enum")
BigValueJustifyMode: "auto" | "center" @cuetsy(kind="enum")
// TODO copy back to appropriate place
// TODO does cuetsy handle underscores the expected way?
BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(kind="enum")
BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(kind="enum",memberNames="Auto|Value|ValueAndName|Name|None")
// TODO copy back to appropriate place
BarGaugeDisplayMode: "basic" | "lcd" | "gradient" @cuetsy(kind="enum")

View File

@ -2,6 +2,7 @@ package dist
import (
"github.com/grafana/grafana/packages/grafana-schema/src/scuemata/dashboard"
pannolist "github.com/grafana/grafana/public/app/plugins/panel/annolist:grafanaschema"
pbarchart "github.com/grafana/grafana/public/app/plugins/panel/barchart:grafanaschema"
pbargauge "github.com/grafana/grafana/public/app/plugins/panel/bargauge:grafanaschema"
pcanvas "github.com/grafana/grafana/public/app/plugins/panel/canvas:grafanaschema"
@ -27,6 +28,7 @@ import (
Family: dashboard.Family & {
compose: Panel: {
// TODO do this with a loop once we include the panel type/plugin id in the model
annolist: pannolist.Panel
barchart: pbarchart.Panel
bargauge: pbargauge.Panel
canvas: pcanvas.Panel
@ -43,4 +45,4 @@ Family: dashboard.Family & {
timeseries: ptimeseries.Panel
"heatmap-new": pheatmap_new.Panel
}
}
}

View File

@ -45,12 +45,10 @@ var skipPaths = []string{
"public/app/plugins/panel/gauge/models.cue",
"public/app/plugins/panel/histogram/models.cue",
"public/app/plugins/panel/heatmap-new/models.cue",
"public/app/plugins/panel/stat/models.cue",
"public/app/plugins/panel/candlestick/models.cue",
"public/app/plugins/panel/state-timeline/models.cue",
"public/app/plugins/panel/status-history/models.cue",
"public/app/plugins/panel/table/models.cue",
"public/app/plugins/panel/text/models.cue",
"public/app/plugins/panel/timeseries/models.cue",
// All the cue files in this dir have to be individually excluded, even
// though the generator currently smooshes them all together

View File

@ -10,14 +10,14 @@ import { backendSrv } from '../../../core/services/backend_srv';
import { setDashboardSrv } from '../../../features/dashboard/services/DashboardSrv';
import { AnnoListPanel, Props } from './AnnoListPanel';
import { AnnoOptions } from './types';
import { PanelOptions } from './models.gen';
jest.mock('@grafana/runtime', () => ({
...(jest.requireActual('@grafana/runtime') as unknown as object),
getBackendSrv: () => backendSrv,
}));
const defaultOptions: AnnoOptions = {
const defaultOptions: PanelOptions = {
limit: 10,
navigateAfter: '10m',
navigateBefore: '10m',
@ -47,7 +47,7 @@ const defaultResult: any = {
async function setupTestContext({
options = defaultOptions,
results = [defaultResult],
}: { options?: AnnoOptions; results?: AnnotationEvent[] } = {}) {
}: { options?: PanelOptions; results?: AnnotationEvent[] } = {}) {
jest.clearAllMocks();
const getMock = jest.spyOn(backendSrv, 'get');

View File

@ -20,7 +20,7 @@ import appEvents from 'app/core/app_events';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { AnnotationListItem } from './AnnotationListItem';
import { AnnoOptions } from './types';
import { PanelOptions } from './models.gen';
interface UserInfo {
id?: number;
@ -28,7 +28,7 @@ interface UserInfo {
email?: string;
}
export interface Props extends PanelProps<AnnoOptions> {}
export interface Props extends PanelProps<PanelOptions> {}
interface State {
annotations: AnnotationEvent[];
timeInfo: string;

View File

@ -4,9 +4,9 @@ import React, { FC, MouseEvent } from 'react';
import { AnnotationEvent, DateTimeInput, GrafanaTheme2, PanelProps } from '@grafana/data';
import { Card, TagList, Tooltip, useStyles2 } from '@grafana/ui';
import { AnnoOptions } from './types';
import { PanelOptions } from './models.gen';
interface Props extends Pick<PanelProps<AnnoOptions>, 'options'> {
interface Props extends Pick<PanelProps<PanelOptions>, 'options'> {
annotation: AnnotationEvent;
formatDate: (date: DateTimeInput, format?: string) => string;
onClick: (annotation: AnnotationEvent) => void;

View File

@ -0,0 +1,37 @@
// Copyright 2022 Grafana Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package grafanaschema
Panel: {
lineages: [
[
{
PanelOptions: {
onlyFromThisDashboard: bool | *false
onlyInTimeRange: bool | *false
tags: [...string]
limit: uint32 | *10
showUser: bool | *true
showTime: bool | *true
showTags: bool | *true
navigateToPanel: bool | *true
navigateBefore: string | *"10m"
navigateAfter: string | *"10m"
} @cuetsy(kind="interface")
}
]
]
migrations: []
}

View File

@ -1,29 +1,33 @@
export interface AnnoOptions {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file was autogenerated by cuetsy. DO NOT EDIT!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export const modelVersion = Object.freeze([0, 0]);
export interface PanelOptions {
limit: number;
tags: string[];
navigateAfter: string;
navigateBefore: string;
navigateToPanel: boolean;
onlyFromThisDashboard: boolean;
onlyInTimeRange: boolean;
showTags: boolean;
showUser: boolean;
showTime: boolean;
navigateBefore: string;
navigateAfter: string;
navigateToPanel: boolean;
showUser: boolean;
tags: string[];
}
export const defaults: AnnoOptions = {
export const defaultPanelOptions: Partial<PanelOptions> = {
limit: 10,
tags: [],
navigateAfter: '10m',
navigateBefore: '10m',
navigateToPanel: true,
onlyFromThisDashboard: false,
onlyInTimeRange: false,
showTags: true,
showUser: true,
showTime: true,
navigateBefore: '10m',
navigateAfter: '10m',
navigateToPanel: true,
showUser: true,
tags: [],
};

View File

@ -1,37 +1,36 @@
import { truncate } from '@sentry/utils';
import React from 'react';
import { PanelModel, PanelPlugin } from '@grafana/data';
import { TagsInput } from '@grafana/ui';
import { AnnoListPanel } from './AnnoListPanel';
import { AnnoOptions } from './types';
import { defaultPanelOptions, PanelOptions } from './models.gen';
export const plugin = new PanelPlugin<AnnoOptions>(AnnoListPanel)
export const plugin = new PanelPlugin<PanelOptions>(AnnoListPanel)
.setPanelOptions((builder) => {
builder
.addRadio({
category: ['Annotation query'],
path: 'onlyFromThisDashboard',
name: 'Query filter',
defaultValue: false,
defaultValue: defaultPanelOptions.onlyFromThisDashboard,
settings: {
options: [
{ value: false, label: 'All dashboards' },
{ value: true, label: 'This dashboard' },
] as any, // does not like boolean, but works fine!
],
},
})
.addRadio({
category: ['Annotation query'],
path: 'onlyInTimeRange',
name: 'Time range',
defaultValue: false,
defaultValue: defaultPanelOptions.onlyInTimeRange,
settings: {
options: [
{ value: false, label: 'None' },
{ value: true, label: 'This dashboard' },
] as any, // does not like boolean, but works fine!
],
},
})
.addCustomEditor({
@ -48,57 +47,58 @@ export const plugin = new PanelPlugin<AnnoOptions>(AnnoListPanel)
category: ['Annotation query'],
path: 'limit',
name: 'Limit',
defaultValue: 10,
defaultValue: defaultPanelOptions.limit,
})
.addBooleanSwitch({
category: ['Display'],
path: 'showUser',
name: 'Show user',
defaultValue: true,
defaultValue: defaultPanelOptions.showUser,
})
.addBooleanSwitch({
category: ['Display'],
path: 'showTime',
name: 'Show time',
defaultValue: true,
defaultValue: defaultPanelOptions.showTime,
})
.addBooleanSwitch({
category: ['Display'],
path: 'showTags',
name: 'Show tags',
defaultValue: true,
defaultValue: defaultPanelOptions.showTags,
})
.addRadio({
category: ['Link behavior'],
path: 'navigateToPanel',
name: 'Link target',
defaultValue: truncate,
defaultValue: defaultPanelOptions.navigateToPanel,
settings: {
options: [
{ value: true, label: 'Panel' },
{ value: false, label: 'Dashboard' },
] as any, // does not like boolean, but works fine!
],
},
})
.addTextInput({
category: ['Link behavior'],
path: 'navigateBefore',
name: 'Time before',
defaultValue: '10m',
defaultValue: defaultPanelOptions.navigateBefore,
description: '',
})
.addTextInput({
category: ['Link behavior'],
path: 'navigateAfter',
name: 'Time after',
defaultValue: '10m',
defaultValue: defaultPanelOptions.navigateAfter,
description: '',
});
})
// TODO, we should support this directly in the plugin infrastructure
.setPanelChangeHandler((panel: PanelModel<AnnoOptions>, prevPluginId: string, prevOptions: any) => {
.setPanelChangeHandler((panel: PanelModel<PanelOptions>, prevPluginId: string, prevOptions: unknown) => {
if (prevPluginId === 'ryantxu-annolist-panel') {
return prevOptions as AnnoOptions;
return prevOptions as PanelOptions;
}
return panel.options;
});

View File

@ -1,7 +1,7 @@
import { PanelPlugin, VizOrientation } from '@grafana/data';
import { commonOptionsBuilder, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
import { addOrientationOption, addStandardDataReduceOptions } from '../stat/types';
import { addOrientationOption, addStandardDataReduceOptions } from '../stat/common';
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
import { BarGaugePanel } from './BarGaugePanel';

View File

@ -1,7 +1,7 @@
import { PanelPlugin } from '@grafana/data';
import { commonOptionsBuilder } from '@grafana/ui';
import { addOrientationOption, addStandardDataReduceOptions } from '../stat/types';
import { addOrientationOption, addStandardDataReduceOptions } from '../stat/common';
import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations';
import { GaugePanel } from './GaugePanel';

View File

@ -2,7 +2,7 @@ import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/dat
import { LegendDisplayMode } from '@grafana/schema';
import { commonOptionsBuilder } from '@grafana/ui';
import { addStandardDataReduceOptions } from '../stat/types';
import { addStandardDataReduceOptions } from '../stat/common';
import { PieChartPanel } from './PieChartPanel';
import { PieChartPanelChangedHandler } from './migrations';

View File

@ -1,6 +1,5 @@
import { PanelModel } from '@grafana/data';
import { BigValueGraphMode, BigValueColorMode } from '@grafana/ui';
import { BigValueTextMode } from '@grafana/ui/src/components/BigValue/BigValue';
import { BigValueGraphMode, BigValueColorMode, BigValueTextMode } from '@grafana/schema';
import { statPanelChangedHandler } from './StatMigrations';

View File

@ -1,17 +1,17 @@
import { FieldColorModeId, FieldConfigSource, PanelModel } from '@grafana/data';
import { sharedSingleStatPanelChangedHandler, BigValueGraphMode, BigValueColorMode } from '@grafana/ui';
import { BigValueTextMode } from '@grafana/ui/src/components/BigValue/BigValue';
import { BigValueTextMode, BigValueGraphMode, BigValueColorMode } from '@grafana/schema';
import { sharedSingleStatPanelChangedHandler } from '@grafana/ui';
import { StatPanelOptions } from './types';
import { PanelOptions } from './models.gen';
// This is called when the panel changes from another panel
export const statPanelChangedHandler = (
panel: PanelModel<Partial<StatPanelOptions>> | any,
panel: PanelModel<Partial<PanelOptions>> | any,
prevPluginId: string,
prevOptions: any
) => {
// This handles most config changes
const options = sharedSingleStatPanelChangedHandler(panel, prevPluginId, prevOptions) as StatPanelOptions;
const options = sharedSingleStatPanelChangedHandler(panel, prevPluginId, prevOptions) as PanelOptions;
// Changing from angular singlestat
if (prevOptions.angular && (prevPluginId === 'singlestat' || prevPluginId === 'grafana-singlestat-panel')) {

View File

@ -11,20 +11,14 @@ import {
PanelProps,
} from '@grafana/data';
import { findNumericFieldMinMax } from '@grafana/data/src/field/fieldOverrides';
import {
BigValue,
BigValueGraphMode,
DataLinksContextMenu,
VizRepeater,
VizRepeaterRenderValueProps,
BigValueTextMode,
} from '@grafana/ui';
import { BigValueTextMode, BigValueGraphMode } from '@grafana/schema';
import { BigValue, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui';
import { DataLinksContextMenuApi } from '@grafana/ui/src/components/DataLinks/DataLinksContextMenu';
import { config } from 'app/core/config';
import { StatPanelOptions } from './types';
import { PanelOptions } from './models.gen';
export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
export class StatPanel extends PureComponent<PanelProps<PanelOptions>> {
renderComponent = (
valueProps: VizRepeaterRenderValueProps<FieldDisplay, DisplayValueAlignmentFactors>,
menuProps: DataLinksContextMenuApi

View File

@ -1,27 +1,14 @@
// These are used in some other plugins for some reason
import {
ReducerID,
standardEditorsRegistry,
escapeStringForRegex,
FieldOverrideContext,
getFieldDisplayName,
escapeStringForRegex,
VizOrientation,
PanelOptionsEditorBuilder,
ReducerID,
standardEditorsRegistry,
} from '@grafana/data';
import {
SingleStatBaseOptions,
BigValueColorMode,
BigValueGraphMode,
BigValueJustifyMode,
BigValueTextMode,
} from '@grafana/ui';
// Structure copied from angular
export interface StatPanelOptions extends SingleStatBaseOptions {
graphMode: BigValueGraphMode;
colorMode: BigValueColorMode;
justifyMode: BigValueJustifyMode;
textMode: BigValueTextMode;
}
import { SingleStatBaseOptions, VizOrientation } from '@grafana/schema';
export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
builder: PanelOptionsEditorBuilder<T>,
@ -64,6 +51,7 @@ export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>(
description: 'Choose a reducer function / calculation',
category: valueOptionsCategory,
editor: standardEditorsRegistry.get('stats-picker').editor as any,
// TODO: Get ReducerID from generated schema one day?
defaultValue: [ReducerID.lastNotNull],
// Hides it when all values mode is on
showIf: (currentConfig) => currentConfig.reduceOptions.values === false,

View File

@ -22,10 +22,10 @@ Panel: {
{
PanelOptions: {
ui.SingleStatBaseOptions
graphMode: ui.BigValueGraphMode
colorMode: ui.BigValueColorMode
justifyMode: ui.BigValueJustifyMode
textMode: ui.BigValueTextMode
graphMode: ui.BigValueGraphMode | *"area"
colorMode: ui.BigValueColorMode | *"value"
justifyMode: ui.BigValueJustifyMode | *"auto"
textMode: ui.BigValueTextMode | *"auto"
} @cuetsy(kind="interface")
}
]

View File

@ -0,0 +1,22 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file was autogenerated by cuetsy. DO NOT EDIT!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import * as ui from '@grafana/schema';
export const modelVersion = Object.freeze([0, 0]);
export interface PanelOptions extends ui.SingleStatBaseOptions {
colorMode: ui.BigValueColorMode;
graphMode: ui.BigValueGraphMode;
justifyMode: ui.BigValueJustifyMode;
textMode: ui.BigValueTextMode;
}
export const defaultPanelOptions: Partial<PanelOptions> = {
colorMode: ui.BigValueColorMode.Value,
graphMode: ui.BigValueGraphMode.Area,
justifyMode: ui.BigValueJustifyMode.Auto,
textMode: ui.BigValueTextMode.Auto,
};

View File

@ -1,17 +1,14 @@
import { PanelPlugin } from '@grafana/data';
import {
BigValueColorMode,
BigValueTextMode,
commonOptionsBuilder,
sharedSingleStatMigrationHandler,
} from '@grafana/ui';
import { BigValueColorMode, BigValueGraphMode, BigValueJustifyMode, BigValueTextMode } from '@grafana/schema';
import { commonOptionsBuilder, sharedSingleStatMigrationHandler } from '@grafana/ui';
import { statPanelChangedHandler } from './StatMigrations';
import { StatPanel } from './StatPanel';
import { addStandardDataReduceOptions, addOrientationOption } from './common';
import { defaultPanelOptions, PanelOptions } from './models.gen';
import { StatSuggestionsSupplier } from './suggestions';
import { addOrientationOption, addStandardDataReduceOptions, StatPanelOptions } from './types';
export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
export const plugin = new PanelPlugin<PanelOptions>(StatPanel)
.useFieldConfig()
.setPanelOptions((builder) => {
const mainCategory = ['Stat styles'];
@ -34,7 +31,7 @@ export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
{ value: BigValueTextMode.None, label: 'None' },
],
},
defaultValue: 'auto',
defaultValue: defaultPanelOptions.textMode,
});
builder
@ -56,23 +53,23 @@ export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
name: 'Graph mode',
description: 'Stat panel graph / sparkline mode',
category: mainCategory,
defaultValue: 'area',
defaultValue: defaultPanelOptions.graphMode,
settings: {
options: [
{ value: 'none', label: 'None' },
{ value: 'area', label: 'Area' },
{ value: BigValueGraphMode.None, label: 'None' },
{ value: BigValueGraphMode.Area, label: 'Area' },
],
},
})
.addRadio({
path: 'justifyMode',
name: 'Text alignment',
defaultValue: 'auto',
defaultValue: defaultPanelOptions.justifyMode,
category: mainCategory,
settings: {
options: [
{ value: 'auto', label: 'Auto' },
{ value: 'center', label: 'Center' },
{ value: BigValueJustifyMode.Auto, label: 'Auto' },
{ value: BigValueJustifyMode.Center, label: 'Center' },
],
},
});

View File

@ -1,8 +1,8 @@
import { VisualizationSuggestionsBuilder } from '@grafana/data';
import { BigValueColorMode, BigValueGraphMode } from '@grafana/ui';
import { BigValueColorMode, BigValueGraphMode } from '@grafana/schema';
import { SuggestionName } from 'app/types/suggestions';
import { StatPanelOptions } from './types';
import { PanelOptions } from './models.gen';
export class StatSuggestionsSupplier {
getSuggestionsForData(builder: VisualizationSuggestionsBuilder) {
@ -12,7 +12,7 @@ export class StatSuggestionsSupplier {
return;
}
const list = builder.getListAppender<StatPanelOptions, {}>({
const list = builder.getListAppender<PanelOptions, {}>({
name: SuggestionName.Stat,
pluginId: 'stat',
options: {},

View File

@ -1,9 +1,11 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file was almost autogenerated by cuetsy.
// This file was autogenerated by cuetsy. DO NOT EDIT!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export const modelVersion = Object.freeze([0, 0]);
export enum TextMode {
HTML = 'html',
Markdown = 'markdown',
@ -14,7 +16,7 @@ export interface PanelOptions {
mode: TextMode;
}
export const defaultPanelOptions: PanelOptions = {
export const defaultPanelOptions: Partial<PanelOptions> = {
content: `# Title
For markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)`,