diff --git a/docs/sources/enterprise/access-control/usage-scenarios.md b/docs/sources/enterprise/access-control/usage-scenarios.md index 0aa8e69868e..7f8f9703e65 100644 --- a/docs/sources/enterprise/access-control/usage-scenarios.md +++ b/docs/sources/enterprise/access-control/usage-scenarios.md @@ -228,5 +228,4 @@ By default, the Grafana Server Admin is the only user who can create and manage 1. Create a built-in role assignment and map `fixed:permissions:admin:edit` and `fixed:permissions:admin:read` fixed roles to the `Editor` built-in role. 1. [Create a custom role]({{< ref "#create-your-custom-role" >}}) with `roles.builtin:add` and `roles:write` permissions, then create a built-in role assignment for `Editor` organization role. - Note that any user with the ability to modify roles can only create, update or delete roles with permissions they themselves have been granted. For example, a user with the `Editor` role would be able to create and manage roles only with the permissions they have, or with a subset of them. diff --git a/packages/grafana-schema/src/index.ts b/packages/grafana-schema/src/index.ts index 1a5564433cc..bbd351c0757 100644 --- a/packages/grafana-schema/src/index.ts +++ b/packages/grafana-schema/src/index.ts @@ -6,3 +6,5 @@ export * from './schema/legend.gen'; export * from './schema/tooltip.gen'; export * from './schema/text.gen'; +export * from './schema/table.gen'; +export * from './schema/graph.gen'; diff --git a/packages/grafana-ui/src/components/uPlot/models.cue b/packages/grafana-schema/src/schema/graph.cue similarity index 52% rename from packages/grafana-ui/src/components/uPlot/models.cue rename to packages/grafana-schema/src/schema/graph.cue index 5839ea927a0..32068654b77 100644 --- a/packages/grafana-ui/src/components/uPlot/models.cue +++ b/packages/grafana-schema/src/schema/graph.cue @@ -1,88 +1,72 @@ -package grafanaschema - -AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(targetType="enum") -PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum") -DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum") -LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum") -ScaleDistribution: "linear" | "log" | "ordinal" @cuetsy(targetType="enum") -GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum") +AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(targetType="enum") +PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum") +DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum") +LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum") +ScaleDistribution: "linear" | "log" @cuetsy(targetType="enum") +GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum") StackingMode: "none" | "normal" | "percent" @cuetsy(targetType="enum") BarValueVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum") BarAlignment: -1 | 0 | 1 @cuetsy(targetType="enum",memberNames="Before|Center|After") ScaleOrientation: 0 | 1 @cuetsy(targetType="enum",memberNames="Horizontal|Vertical") ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(targetType="enum",memberNames="Up|Right|Down|Left") - LineStyle: { - fill?: "solid" | "dash" | "dot" | "square" - dash?: [...number] + fill?: "solid" | "dash" | "dot" | "square" + dash?: [...number] } @cuetsy(targetType="interface") - LineConfig: { - lineColor?: string - lineWidth?: number - lineInterpolation?: LineInterpolation - lineStyle?: LineStyle - spanNulls?: bool | number + lineColor?: string + lineWidth?: number + lineInterpolation?: LineInterpolation + lineStyle?: LineStyle + spanNulls?: bool | number } @cuetsy(targetType="interface") - BarConfig: { - barAlignment?: BarAlignment - barWidthFactor?: number - barMaxWidth?: number + barAlignment?: BarAlignment + barWidthFactor?: number + barMaxWidth?: number } @cuetsy(targetType="interface") - FillConfig: { - fillColor?: string - fillOpacity?: number - fillBelowTo?: string + fillColor?: string + fillOpacity?: number + fillBelowTo?: string } @cuetsy(targetType="interface") - PointsConfig: { - showPoints?: PointVisibility - pointSize?: number - pointColor?: string - pointSymbol?: string + showPoints?: PointVisibility + pointSize?: number + pointColor?: string + pointSymbol?: string } @cuetsy(targetType="interface") - ScaleDistributionConfig: { - type: ScaleDistribution - log?: number + type: ScaleDistribution + log?: number } @cuetsy(targetType="interface") - AxisConfig: { - axisPlacement?: AxisPlacement - axisLabel?: string - axisWidth?: number - axisSoftMin?: number - axisSoftMax?: number - scaleDistribution?: ScaleDistributionConfig + axisPlacement?: AxisPlacement + axisLabel?: string + axisWidth?: number + axisSoftMin?: number + axisSoftMax?: number + scaleDistribution?: ScaleDistributionConfig } @cuetsy(targetType="interface") - HideSeriesConfig: { - tooltip: bool - legend: bool - viz: bool + tooltip: bool + legend: bool + viz: bool } @cuetsy(targetType="interface") - StackingConfig: { mode?: StackingMode group?: string } @cuetsy(targetType="interface") - StackableFieldConfig: { stacking?: StackingConfig } @cuetsy(targetType="interface") - HideableFieldConfig: { hideFrom?: HideSeriesConfig } @cuetsy(targetType="interface") - GraphTresholdsStyleMode: "off" | "line" | "area" | "line+area" | "series" @cuetsy(targetType="enum",memberNames="Off|Line|Area|LineAndArea|Series") - GraphThresholdsStyleConfig: { mode: GraphTresholdsStyleMode } @cuetsy(targetType="interface") - GraphFieldConfig: { LineConfig FillConfig @@ -94,4 +78,4 @@ GraphFieldConfig: { drawStyle?: DrawStyle gradientMode?: GraphGradientMode thresholdsStyle?: GraphThresholdsStyleConfig -} @cuetsy(targetType="interface") +} @cuetsy(targetType="interface") \ No newline at end of file diff --git a/packages/grafana-schema/src/schema/graph.gen.ts b/packages/grafana-schema/src/schema/graph.gen.ts new file mode 100644 index 00000000000..051fb8da81a --- /dev/null +++ b/packages/grafana-schema/src/schema/graph.gen.ts @@ -0,0 +1,213 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NOTE: This file will be auto generated from models.cue +// It is currenty hand written but will serve as the target for cuetsy +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +export enum AxisPlacement { + Auto = 'auto', + Bottom = 'bottom', + Hidden = 'hidden', + Left = 'left', + Right = 'right', + Top = 'top', +} +export enum PointVisibility { + Always = 'always', + Auto = 'auto', + Never = 'never', +} +export enum DrawStyle { + Bars = 'bars', + Line = 'line', + Points = 'points', +} +export enum LineInterpolation { + Linear = 'linear', + Smooth = 'smooth', + StepAfter = 'stepAfter', + StepBefore = 'stepBefore', +} +/** + * @alpha + */ +export enum ScaleDistribution { + Linear = 'linear', + Log = 'log', + Ordinal = 'ordinal', +} +export enum GraphGradientMode { + Hue = 'hue', + None = 'none', + Opacity = 'opacity', + Scheme = 'scheme', +} +export interface LineStyle { + dash?: number[]; + fill?: 'solid' | 'dash' | 'dot' | 'square'; +} + +export interface PointsConfig { + pointColor?: string; + pointSize?: number; + pointSymbol?: string; + showPoints?: PointVisibility; +} +export interface ScaleDistributionConfig { + log?: number; + type: ScaleDistribution; +} +export interface HideSeriesConfig { + viz: boolean; + legend: boolean; + tooltip: boolean; +} + +/** + * @alpha + */ +export enum BarAlignment { + Before = -1, + Center = 0, + After = 1, +} + +/** + * @alpha + */ +export enum BarValueVisibility { + Auto = 'auto', + Never = 'never', + Always = 'always', +} + +/** + * @alpha + */ +export enum ScaleOrientation { + Horizontal = 0, + Vertical = 1, +} + +/** + * @alpha + */ + +export enum ScaleDirection { + Up = 1, + Right = 1, + Down = -1, + Left = -1, +} + +/** + * @alpha + */ +export interface LineConfig { + lineColor?: string; + lineWidth?: number; + lineInterpolation?: LineInterpolation; + lineStyle?: LineStyle; + + /** + * Indicate if null values should be treated as gaps or connected. + * When the value is a number, it represents the maximum delta in the + * X axis that should be considered connected. For timeseries, this is milliseconds + */ + spanNulls?: boolean | number; +} + +/** + * @alpha + */ +export interface BarConfig { + barAlignment?: BarAlignment; + barWidthFactor?: number; + barMaxWidth?: number; +} + +/** + * @alpha + */ +export interface FillConfig { + fillColor?: string; + fillOpacity?: number; + fillBelowTo?: string; // name of the field +} + +/** + * @alpha + * Axis is actually unique based on the unit... not each field! + */ +export interface AxisConfig { + axisPlacement?: AxisPlacement; + axisLabel?: string; + axisWidth?: number; // pixels ideally auto? + axisSoftMin?: number; + axisSoftMax?: number; + scaleDistribution?: ScaleDistributionConfig; +} + +/** + * @alpha + */ +export interface HideableFieldConfig { + hideFrom?: HideSeriesConfig; +} + +/** + * @alpha + */ +export enum StackingMode { + None = 'none', + Normal = 'normal', + Percent = 'percent', +} + +/** + * @alpha + */ +export interface StackingConfig { + mode?: StackingMode; + group?: string; +} + +/** + * @alpha + */ +export interface StackableFieldConfig { + stacking?: StackingConfig; +} + +/** + * @alpha + */ +export enum GraphTresholdsStyleMode { + Off = 'off', + Line = 'line', + Area = 'area', + LineAndArea = 'line+area', + Series = 'series', +} + +/** + * @alpha + */ +export interface GraphThresholdsStyleConfig { + mode: GraphTresholdsStyleMode; +} + +/** + * @alpha + */ +export interface GraphFieldConfig + extends LineConfig, + FillConfig, + PointsConfig, + AxisConfig, + BarConfig, + StackableFieldConfig, + HideableFieldConfig { + drawStyle?: DrawStyle; + gradientMode?: GraphGradientMode; + thresholdsStyle?: GraphThresholdsStyleConfig; +} diff --git a/packages/grafana-ui/src/components/Table/models.cue b/packages/grafana-schema/src/schema/table.cue similarity index 82% rename from packages/grafana-ui/src/components/Table/models.cue rename to packages/grafana-schema/src/schema/table.cue index 096c2873bf3..c5f37cfd38d 100644 --- a/packages/grafana-ui/src/components/Table/models.cue +++ b/packages/grafana-schema/src/schema/table.cue @@ -1,5 +1,4 @@ -package grafanaschema - +// TODO -- should not be table specific! FieldTextAlignment: "auto" | "left" | "right" | "center" @cuetsy(targetType="type") TableCellDisplayMode: { @@ -20,9 +19,3 @@ TableFieldOptions: { displayMode: TableCellDisplayMode | *"auto" hidden?: bool // ?? default is missing or false ?? } @cuetsy(targetType="interface") - - -TableSortByFieldState: { - displayName: string - desc?: bool -} @cuetsy(targetType="interface") \ No newline at end of file diff --git a/packages/grafana-schema/src/schema/table.gen.ts b/packages/grafana-schema/src/schema/table.gen.ts new file mode 100644 index 00000000000..3807e27d154 --- /dev/null +++ b/packages/grafana-schema/src/schema/table.gen.ts @@ -0,0 +1,21 @@ +export interface TableFieldOptions { + width: number; + minWidth: number; + align: FieldTextAlignment; + displayMode: TableCellDisplayMode; + hidden?: boolean; +} + +export enum TableCellDisplayMode { + Auto = 'auto', + ColorText = 'color-text', + ColorBackground = 'color-background', + ColorBackgroundSolid = 'color-background-solid', + GradientGauge = 'gradient-gauge', + LcdGauge = 'lcd-gauge', + JSONView = 'json-view', + BasicGauge = 'basic', + Image = 'image', +} + +export type FieldTextAlignment = 'auto' | 'left' | 'right' | 'center'; diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx index b1963dcdfff..e9cd3c8b620 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx @@ -9,7 +9,7 @@ import { calculateFontSize } from '../../utils/measureText'; // Types import { BigValueColorMode, Props, BigValueJustifyMode, BigValueTextMode } from './BigValue'; import { getTextColorForBackground } from '../../utils'; -import { DrawStyle, GraphFieldConfig } from '../uPlot/config'; +import { DrawStyle, GraphFieldConfig } from '@grafana/schema'; import { Sparkline } from '../Sparkline/Sparkline'; const LINE_HEIGHT = 1.2; diff --git a/packages/grafana-ui/src/components/Forms/Form.mdx b/packages/grafana-ui/src/components/Forms/Form.mdx index cff858a9d4f..3cfc01aaf10 100644 --- a/packages/grafana-ui/src/components/Forms/Form.mdx +++ b/packages/grafana-ui/src/components/Forms/Form.mdx @@ -276,7 +276,7 @@ In a nutshell, the two most important changes are: ```jsx - -+ ++ ; ``` - `InputControl`'s `as` prop has been replaced with `render`, which has `field` and `fieldState` objects as arguments. `onChange`, `onBlur`, `value`, `name`, and `ref` are parts of `field`. diff --git a/packages/grafana-ui/src/components/GraphNG/utils.test.ts b/packages/grafana-ui/src/components/GraphNG/utils.test.ts index 1529dc05c29..990c66df6dc 100644 --- a/packages/grafana-ui/src/components/GraphNG/utils.test.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.test.ts @@ -20,7 +20,7 @@ import { LineInterpolation, PointVisibility, StackingMode, -} from '..'; +} from '@grafana/schema'; function mockDataFrame() { const df1 = new MutableDataFrame({ diff --git a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx index 3354e1eca3c..80e59498ba3 100755 --- a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx +++ b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx @@ -16,7 +16,7 @@ import { PointVisibility, ScaleDirection, ScaleOrientation, -} from '../uPlot/config'; +} from '@grafana/schema'; import { UPlotConfigBuilder } from '../uPlot/config/UPlotConfigBuilder'; import { UPlotChart } from '../uPlot/Plot'; import { Themeable2 } from '../../types'; diff --git a/packages/grafana-ui/src/components/Sparkline/utils.ts b/packages/grafana-ui/src/components/Sparkline/utils.ts index eed7dd1da9f..d9ec460f3b3 100644 --- a/packages/grafana-ui/src/components/Sparkline/utils.ts +++ b/packages/grafana-ui/src/components/Sparkline/utils.ts @@ -1,5 +1,5 @@ import { DataFrame, FieldConfig, FieldSparkline, IndexVector } from '@grafana/data'; -import { GraphFieldConfig } from '../uPlot/config'; +import { GraphFieldConfig } from '@grafana/schema'; /** @internal * Given a sparkline config returns a DataFrame ready to be turned into Plot data set diff --git a/packages/grafana-ui/src/components/Table/types.ts b/packages/grafana-ui/src/components/Table/types.ts index 4472e72fc6c..f8481c5666f 100644 --- a/packages/grafana-ui/src/components/Table/types.ts +++ b/packages/grafana-ui/src/components/Table/types.ts @@ -3,27 +3,7 @@ import { Field } from '@grafana/data'; import { TableStyles } from './styles'; import { CSSProperties, FC } from 'react'; -export interface TableFieldOptions { - width: number; - minWidth: number; - align: FieldTextAlignment; - displayMode: TableCellDisplayMode; - hidden?: boolean; -} - -export enum TableCellDisplayMode { - Auto = 'auto', - ColorText = 'color-text', - ColorBackground = 'color-background', - ColorBackgroundSolid = 'color-background-solid', - GradientGauge = 'gradient-gauge', - LcdGauge = 'lcd-gauge', - JSONView = 'json-view', - BasicGauge = 'basic', - Image = 'image', -} - -export type FieldTextAlignment = 'auto' | 'left' | 'right' | 'center'; +export { TableFieldOptions, TableCellDisplayMode, FieldTextAlignment } from '@grafana/schema'; export interface TableRow { [x: string]: any; diff --git a/packages/grafana-ui/src/components/TimeSeries/utils.ts b/packages/grafana-ui/src/components/TimeSeries/utils.ts index 6db692ab3fb..dd0e12d623e 100644 --- a/packages/grafana-ui/src/components/TimeSeries/utils.ts +++ b/packages/grafana-ui/src/components/TimeSeries/utils.ts @@ -23,7 +23,7 @@ import { PointVisibility, ScaleDirection, ScaleOrientation, -} from '../uPlot/config'; +} from '@grafana/schema'; import { collectStackingGroups, preparePlotData } from '../uPlot/utils'; import uPlot from 'uplot'; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 67c9dfe4937..ae4cc1e5cbd 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -237,7 +237,6 @@ export { LegacyForms, LegacyInputStatus }; // WIP, need renames and exports cleanup export * from './uPlot/config'; -export { ScaleDistribution } from './uPlot/models.gen'; export { UPlotConfigBuilder, UPlotConfigPrepFn } from './uPlot/config/UPlotConfigBuilder'; export { UPlotChart } from './uPlot/Plot'; export { PlotLegend } from './uPlot/PlotLegend'; diff --git a/packages/grafana-ui/src/components/uPlot/Plot.test.tsx b/packages/grafana-ui/src/components/uPlot/Plot.test.tsx index 67a698f2a8b..936f7619282 100644 --- a/packages/grafana-ui/src/components/uPlot/Plot.test.tsx +++ b/packages/grafana-ui/src/components/uPlot/Plot.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { UPlotChart } from './Plot'; import { render } from '@testing-library/react'; import { ArrayVector, dateTime, FieldConfig, FieldType, MutableDataFrame } from '@grafana/data'; -import { GraphFieldConfig, DrawStyle } from '../uPlot/config'; +import { GraphFieldConfig, DrawStyle } from '@grafana/schema'; import uPlot from 'uplot'; import createMockRaf from 'mock-raf'; import { UPlotConfigBuilder } from './config/UPlotConfigBuilder'; diff --git a/packages/grafana-ui/src/components/uPlot/PlotLegend.tsx b/packages/grafana-ui/src/components/uPlot/PlotLegend.tsx index ab77a7010f0..e0a6fe1ff7f 100644 --- a/packages/grafana-ui/src/components/uPlot/PlotLegend.tsx +++ b/packages/grafana-ui/src/components/uPlot/PlotLegend.tsx @@ -9,8 +9,7 @@ import { } from '@grafana/data'; import { UPlotConfigBuilder } from './config/UPlotConfigBuilder'; import { VizLegendItem } from '../VizLegend/types'; -import { VizLegendOptions } from '@grafana/schema'; -import { AxisPlacement } from './config'; +import { VizLegendOptions, AxisPlacement } from '@grafana/schema'; import { VizLayout, VizLayoutLegendProps } from '../VizLayout/VizLayout'; import { VizLegend } from '../VizLegend/VizLegend'; import { useTheme2 } from '../../themes'; diff --git a/packages/grafana-ui/src/components/uPlot/config.ts b/packages/grafana-ui/src/components/uPlot/config.ts index bbf685c6d1c..744daf43098 100644 --- a/packages/grafana-ui/src/components/uPlot/config.ts +++ b/packages/grafana-ui/src/components/uPlot/config.ts @@ -1,239 +1,14 @@ import { SelectableValue } from '@grafana/data'; -import { ScaleDistribution } from './models.gen'; - -/** - * @alpha - */ -export enum AxisPlacement { - Auto = 'auto', // First axis on the left, the rest on the right - Top = 'top', - Right = 'right', - Bottom = 'bottom', - Left = 'left', - Hidden = 'hidden', -} - -/** - * @alpha - */ -export enum PointVisibility { - Auto = 'auto', // will show points when the density is low or line is hidden - Never = 'never', - Always = 'always', -} - -/** - * @alpha - */ -export enum DrawStyle { - Line = 'line', // default - Bars = 'bars', // will also have a gap percent - Points = 'points', // Only show points -} - -/** - * @alpha - */ -export enum LineInterpolation { - Linear = 'linear', - Smooth = 'smooth', - StepBefore = 'stepBefore', - StepAfter = 'stepAfter', -} - -/** - * @alpha - */ -export enum BarAlignment { - Before = -1, - Center = 0, - After = 1, -} - -/** - * @alpha - */ -export enum BarValueVisibility { - Auto = 'auto', - Never = 'never', - Always = 'always', -} - -/** - * @alpha - */ -export enum ScaleOrientation { - Horizontal = 0, - Vertical = 1, -} - -/** - * @alpha - */ - -export enum ScaleDirection { - Up = 1, - Right = 1, - Down = -1, - Left = -1, -} - -/** - * @alpha - */ -export interface LineStyle { - fill?: 'solid' | 'dash' | 'dot' | 'square'; - dash?: number[]; -} - -/** - * @alpha - */ -export interface LineConfig { - lineColor?: string; - lineWidth?: number; - lineInterpolation?: LineInterpolation; - lineStyle?: LineStyle; - - /** - * Indicate if null values should be treated as gaps or connected. - * When the value is a number, it represents the maximum delta in the - * X axis that should be considered connected. For timeseries, this is milliseconds - */ - spanNulls?: boolean | number; -} - -/** - * @alpha - */ -export interface BarConfig { - barAlignment?: BarAlignment; - barWidthFactor?: number; - barMaxWidth?: number; -} - -/** - * @alpha - */ -export interface FillConfig { - fillColor?: string; - fillOpacity?: number; - fillBelowTo?: string; // name of the field -} - -/** - * @alpha - */ -export enum GraphGradientMode { - None = 'none', - Opacity = 'opacity', - Hue = 'hue', - Scheme = 'scheme', -} - -/** - * @alpha - */ -export interface PointsConfig { - showPoints?: PointVisibility; - pointSize?: number; - pointSymbol?: string; // eventually dot,star, etc -} - -/** - * @alpha - */ -export interface ScaleDistributionConfig { - type: ScaleDistribution; - log?: number; -} - -/** - * @alpha - * Axis is actually unique based on the unit... not each field! - */ -export interface AxisConfig { - axisPlacement?: AxisPlacement; - axisLabel?: string; - axisWidth?: number; // pixels ideally auto? - axisSoftMin?: number; - axisSoftMax?: number; - scaleDistribution?: ScaleDistributionConfig; -} - -/** - * @alpha - */ -export interface HideSeriesConfig { - tooltip: boolean; - legend: boolean; - viz: boolean; -} - -/** - * @alpha - */ -export interface HideableFieldConfig { - hideFrom?: HideSeriesConfig; -} - -/** - * @alpha - */ -export enum StackingMode { - None = 'none', - Normal = 'normal', - Percent = 'percent', -} - -/** - * @alpha - */ -export interface StackingConfig { - mode?: StackingMode; - group?: string; -} - -/** - * @alpha - */ -export interface StackableFieldConfig { - stacking?: StackingConfig; -} - -/** - * @alpha - */ -export enum GraphTresholdsStyleMode { - Off = 'off', - Line = 'line', - Area = 'area', - LineAndArea = 'line+area', - Series = 'series', -} - -/** - * @alpha - */ -export interface GraphThresholdsStyleConfig { - mode: GraphTresholdsStyleMode; -} - -/** - * @alpha - */ -export interface GraphFieldConfig - extends LineConfig, - FillConfig, - PointsConfig, - AxisConfig, - BarConfig, - StackableFieldConfig, - HideableFieldConfig { - drawStyle?: DrawStyle; - gradientMode?: GraphGradientMode; - thresholdsStyle?: GraphThresholdsStyleConfig; -} +import { + AxisPlacement, + BarAlignment, + DrawStyle, + GraphGradientMode, + GraphTresholdsStyleMode, + LineInterpolation, + PointVisibility, + StackingMode, +} from '@grafana/schema'; /** * @alpha diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts index d12ff095b6a..f807324bf77 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts @@ -2,7 +2,7 @@ import { dateTimeFormat, GrafanaTheme2, isBooleanUnit, systemDateFormats, TimeZo import uPlot, { Axis } from 'uplot'; import { PlotConfigBuilder } from '../types'; import { measureText } from '../../../utils/measureText'; -import { AxisPlacement } from '../config'; +import { AxisPlacement } from '@grafana/schema'; import { optMinMax } from './UPlotScaleBuilder'; export interface AxisProps { diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts index 91a61158b07..1b3ceb7a32f 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts @@ -9,9 +9,9 @@ import { ScaleOrientation, ScaleDirection, GraphTresholdsStyleMode, -} from '../config'; + ScaleDistribution, +} from '@grafana/schema'; import { createTheme, ThresholdsMode } from '@grafana/data'; -import { ScaleDistribution } from '../models.gen'; describe('UPlotConfigBuilder', () => { const darkTheme = createTheme(); diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.ts index 16cedfa9d2d..d475c8ef05e 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.ts @@ -13,7 +13,7 @@ import { PlotConfig, PlotTooltipInterpolator } from '../types'; import { ScaleProps, UPlotScaleBuilder } from './UPlotScaleBuilder'; import { SeriesProps, UPlotSeriesBuilder } from './UPlotSeriesBuilder'; import { AxisProps, UPlotAxisBuilder } from './UPlotAxisBuilder'; -import { AxisPlacement } from '../config'; +import { AxisPlacement } from '@grafana/schema'; import { pluginLog } from '../utils'; import { getThresholdsDrawHook, UPlotThresholdOptions } from './UPlotThresholds'; diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts index 1f7e5aee56b..4491ebc4e5a 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts @@ -1,7 +1,6 @@ import uPlot, { Scale, Range } from 'uplot'; import { PlotConfigBuilder } from '../types'; -import { ScaleOrientation, ScaleDirection } from '../config'; -import { ScaleDistribution } from '../models.gen'; +import { ScaleOrientation, ScaleDirection, ScaleDistribution } from '@grafana/schema'; import { isBooleanUnit } from '@grafana/data'; export interface ScaleProps { diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts index 81e9bd74338..633f1f0f2e6 100755 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts @@ -17,7 +17,7 @@ import { LineInterpolation, PointsConfig, PointVisibility, -} from '../config'; +} from '@grafana/schema'; import { PlotConfigBuilder } from '../types'; import { getHueGradientFn, getOpacityGradientFn, getScaleGradientFn } from './gradientFills'; diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts index be4a2609b54..d3921790555 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts @@ -1,7 +1,7 @@ import { GrafanaTheme2, ThresholdsConfig, ThresholdsMode } from '@grafana/data'; -import tinycolor from 'tinycolor2'; -import { GraphThresholdsStyleConfig, GraphTresholdsStyleMode } from '../config'; +import { GraphThresholdsStyleConfig, GraphTresholdsStyleMode } from '@grafana/schema'; import { getDataRange, GradientDirection, scaleGradient } from './gradientFills'; +import tinycolor from 'tinycolor2'; export interface UPlotThresholdOptions { scaleKey: string; diff --git a/packages/grafana-ui/src/components/uPlot/models.gen.ts b/packages/grafana-ui/src/components/uPlot/models.gen.ts deleted file mode 100644 index b4b39742159..00000000000 --- a/packages/grafana-ui/src/components/uPlot/models.gen.ts +++ /dev/null @@ -1,87 +0,0 @@ -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// NOTE: This file will be auto generated from models.cue -// It is currenty hand written but will serve as the target for cuetsy -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -export enum AxisPlacement { - Auto = 'auto', - Bottom = 'bottom', - Hidden = 'hidden', - Left = 'left', - Right = 'right', - Top = 'top', -} -export enum PointVisibility { - Always = 'always', - Auto = 'auto', - Never = 'never', -} -export enum DrawStyle { - Bars = 'bars', - Line = 'line', - Points = 'points', -} -export enum LineInterpolation { - Linear = 'linear', - Smooth = 'smooth', - StepAfter = 'stepAfter', - StepBefore = 'stepBefore', -} -/** - * @alpha - */ -export enum ScaleDistribution { - Linear = 'linear', - Log = 'log', - Ordinal = 'ordinal', -} -export enum GraphGradientMode { - Hue = 'hue', - None = 'none', - Opacity = 'opacity', - Scheme = 'scheme', -} -export interface LineStyle { - dash?: number[]; - fill?: 'solid' | 'dash' | 'dot' | 'square'; -} -export interface LineConfig { - lineColor?: string; - lineInterpolation?: LineInterpolation; - lineStyle?: LineStyle; - lineWidth?: number; - spanNulls?: boolean; -} -export interface FillConfig { - fillBelowTo?: string; - fillColor?: string; - fillOpacity?: number; -} -export interface PointsConfig { - pointColor?: string; - pointSize?: number; - pointSymbol?: string; - showPoints?: PointVisibility; -} -export interface ScaleDistributionConfig { - log?: number; - type: ScaleDistribution; -} -export interface AxisConfig { - axisLabel?: string; - axisPlacement?: AxisPlacement; - axisSoftMax?: number; - axisSoftMin?: number; - axisWidth?: number; - scaleDistribution?: ScaleDistributionConfig; -} -export interface HideSeriesConfig { - graph: boolean; - legend: boolean; - tooltip: boolean; -} -export interface GraphFieldConfig extends LineConfig, FillConfig, PointsConfig, AxisConfig { - drawStyle?: DrawStyle; - gradientMode?: GraphGradientMode; - hideFrom?: HideSeriesConfig; -} diff --git a/packages/grafana-ui/src/components/uPlot/utils.test.ts b/packages/grafana-ui/src/components/uPlot/utils.test.ts index 109fc28d176..c3523457613 100644 --- a/packages/grafana-ui/src/components/uPlot/utils.test.ts +++ b/packages/grafana-ui/src/components/uPlot/utils.test.ts @@ -1,6 +1,6 @@ import { preparePlotData, timeFormatToTemplate } from './utils'; import { FieldType, MutableDataFrame } from '@grafana/data'; -import { StackingMode } from './config'; +import { StackingMode } from '@grafana/schema'; describe('timeFormatToTemplate', () => { it.each` diff --git a/packages/grafana-ui/src/components/uPlot/utils.ts b/packages/grafana-ui/src/components/uPlot/utils.ts index 1be74629d3b..8ffb02866e0 100755 --- a/packages/grafana-ui/src/components/uPlot/utils.ts +++ b/packages/grafana-ui/src/components/uPlot/utils.ts @@ -1,5 +1,5 @@ import { DataFrame, dateTime, Field, FieldType } from '@grafana/data'; -import { StackingMode } from './config'; +import { StackingMode } from '@grafana/schema'; import { createLogger } from '../../utils/logger'; import { attachDebugger } from '../../utils'; import { AlignedData, Options, PaddingSide } from 'uplot'; diff --git a/packages/grafana-ui/src/options/builder/axis.tsx b/packages/grafana-ui/src/options/builder/axis.tsx index 18e89251d6f..ec5d31aa550 100644 --- a/packages/grafana-ui/src/options/builder/axis.tsx +++ b/packages/grafana-ui/src/options/builder/axis.tsx @@ -6,16 +6,8 @@ import { identityOverrideProcessor, SelectableValue, } from '@grafana/data'; -import { - AxisConfig, - AxisPlacement, - graphFieldOptions, - ScaleDistributionConfig, - Select, - HorizontalGroup, - RadioButtonGroup, -} from '../../index'; -import { ScaleDistribution } from '../../components/uPlot/models.gen'; +import { graphFieldOptions, Select, HorizontalGroup, RadioButtonGroup } from '../../index'; +import { AxisConfig, AxisPlacement, ScaleDistribution, ScaleDistributionConfig } from '@grafana/schema'; /** * @alpha diff --git a/packages/grafana-ui/src/options/builder/hideSeries.tsx b/packages/grafana-ui/src/options/builder/hideSeries.tsx index 1a6dd4b2500..efc1dd96851 100644 --- a/packages/grafana-ui/src/options/builder/hideSeries.tsx +++ b/packages/grafana-ui/src/options/builder/hideSeries.tsx @@ -2,7 +2,7 @@ import React, { useCallback } from 'react'; import { startCase } from 'lodash'; import { FilterPill, HorizontalGroup } from '../../index'; import { FieldConfigEditorBuilder, FieldConfigEditorProps } from '@grafana/data'; -import { HideableFieldConfig, HideSeriesConfig } from '../../components/uPlot/config'; +import { HideableFieldConfig, HideSeriesConfig } from '@grafana/schema'; const SeriesConfigEditor: React.FC> = (props) => { const { value, onChange } = props; diff --git a/packages/grafana-ui/src/options/builder/stacking.tsx b/packages/grafana-ui/src/options/builder/stacking.tsx index f69db522c4b..38667addb19 100644 --- a/packages/grafana-ui/src/options/builder/stacking.tsx +++ b/packages/grafana-ui/src/options/builder/stacking.tsx @@ -5,16 +5,8 @@ import { identityOverrideProcessor, } from '@grafana/data'; import React from 'react'; -import { - graphFieldOptions, - HorizontalGroup, - IconButton, - Input, - RadioButtonGroup, - StackingConfig, - StackingMode, - Tooltip, -} from '../..'; +import { graphFieldOptions, HorizontalGroup, IconButton, Input, RadioButtonGroup, Tooltip } from '../..'; +import { StackingConfig, StackingMode } from '@grafana/schema'; export const StackingEditor: React.FC> = ({ value, diff --git a/pkg/api/api.go b/pkg/api/api.go index ce453d0e646..d5b4da005f0 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -385,7 +385,7 @@ func (hs *HTTPServer) registerRoutes() { }) apiRoute.Get("/alert-notifiers", reqEditorRole, routing.Wrap( - GetAlertNotifiers(hs.MultiOrgAlertmanager != nil && hs.Cfg.IsNgAlertEnabled())), + GetAlertNotifiers(hs.Cfg.IsNgAlertEnabled())), ) apiRoute.Group("/alert-notifications", func(alertNotifications routing.RouteRegister) { diff --git a/pkg/api/common_test.go b/pkg/api/common_test.go index d836cdfa1c8..5145c2965c0 100644 --- a/pkg/api/common_test.go +++ b/pkg/api/common_test.go @@ -1,7 +1,6 @@ package api import ( - "context" "fmt" "net/http" "net/http/httptest" @@ -16,6 +15,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/services/accesscontrol" + accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/contexthandler" @@ -229,33 +229,6 @@ func (s *fakeRenderService) Init() error { return nil } -var _ accesscontrol.AccessControl = new(fakeAccessControl) - -type fakeAccessControl struct { - isDisabled bool - permissions []*accesscontrol.Permission -} - -func (f *fakeAccessControl) Evaluate(ctx context.Context, user *models.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { - permissions, err := f.GetUserPermissions(ctx, user) - if err != nil { - return false, err - } - return evaluator.Evaluate(accesscontrol.GroupScopesByAction(permissions)) -} - -func (f *fakeAccessControl) GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*accesscontrol.Permission, error) { - return f.permissions, nil -} - -func (f *fakeAccessControl) IsDisabled() bool { - return f.isDisabled -} - -func (f *fakeAccessControl) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistration) error { - return nil -} - func setupAccessControlScenarioContext(t *testing.T, cfg *setting.Cfg, url string, permissions []*accesscontrol.Permission) (*scenarioContext, *HTTPServer) { cfg.FeatureToggles = make(map[string]bool) cfg.FeatureToggles["accesscontrol"] = true @@ -263,7 +236,7 @@ func setupAccessControlScenarioContext(t *testing.T, cfg *setting.Cfg, url strin hs := &HTTPServer{ Cfg: cfg, RouteRegister: routing.NewRouteRegister(), - AccessControl: &fakeAccessControl{permissions: permissions}, + AccessControl: accesscontrolmock.New().WithPermissions(permissions), } sc := setupScenarioContext(t, url) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 75a576bdfab..58862e989cd 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -42,7 +42,6 @@ import ( "github.com/grafana/grafana/pkg/services/live" "github.com/grafana/grafana/pkg/services/live/pushhttp" "github.com/grafana/grafana/pkg/services/login" - "github.com/grafana/grafana/pkg/services/ngalert/notifier" "github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/rendering" @@ -104,7 +103,6 @@ type HTTPServer struct { PluginDashboardService *plugindashboards.Service `inject:""` AlertEngine *alerting.AlertEngine `inject:""` LoadSchemaService *schemaloader.SchemaLoaderService `inject:""` - MultiOrgAlertmanager *notifier.MultiOrgAlertmanager `inject:""` LibraryPanelService librarypanels.Service `inject:""` LibraryElementService libraryelements.Service `inject:""` SocialService social.Service `inject:""` diff --git a/pkg/api/index.go b/pkg/api/index.go index 86b4185655d..859efa7cb0e 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -376,12 +376,6 @@ func (hs *HTTPServer) buildAdminNavLinks(c *models.ReqContext) []*dtos.NavLink { }) } - if hasAccess(ac.ReqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)) { - adminNavLinks = append(adminNavLinks, &dtos.NavLink{ - Text: "Stats", Id: "server-stats", Url: hs.Cfg.AppSubURL + "/admin/stats", Icon: "graph-bar", - }) - } - if hs.Cfg.LDAPEnabled && hasAccess(ac.ReqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPStatusRead)) { adminNavLinks = append(adminNavLinks, &dtos.NavLink{ Text: "LDAP", Id: "ldap", Url: hs.Cfg.AppSubURL + "/admin/ldap", Icon: "book", diff --git a/pkg/services/accesscontrol/middleware/middleware_test.go b/pkg/services/accesscontrol/middleware/middleware_test.go index ad38dc2e574..6c52365b9ae 100644 --- a/pkg/services/accesscontrol/middleware/middleware_test.go +++ b/pkg/services/accesscontrol/middleware/middleware_test.go @@ -1,7 +1,6 @@ package middleware import ( - "context" "net/http" "net/http/httptest" "testing" @@ -13,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/accesscontrol/mock" ) type middlewareTestCase struct { @@ -27,26 +27,24 @@ func TestMiddleware(t *testing.T) { tests := []middlewareTestCase{ { desc: "should use fallback if access control is disabled", - ac: fakeAccessControl{isDisabled: true}, + ac: mock.New().WithDisabled(), expectFallback: true, expectEndpoint: true, }, { desc: "should pass middleware for correct permissions", - ac: fakeAccessControl{ - isDisabled: false, - permissions: []*accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, - }, + ac: mock.New().WithPermissions( + []*accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, + ), evaluator: accesscontrol.EvalPermission("users:read", "users:*"), expectFallback: false, expectEndpoint: true, }, { desc: "should not reach endpoint when missing permissions", - ac: fakeAccessControl{ - isDisabled: false, - permissions: []*accesscontrol.Permission{{Action: "users:read", Scope: "users:1"}}, - }, + ac: mock.New().WithPermissions( + []*accesscontrol.Permission{{Action: "users:read", Scope: "users:1"}}, + ), evaluator: accesscontrol.EvalPermission("users:read", "users:*"), expectFallback: false, expectEndpoint: false, @@ -95,27 +93,3 @@ func contextProvider() macaron.Handler { c.Map(reqCtx) } } - -var _ accesscontrol.AccessControl = new(fakeAccessControl) - -type fakeAccessControl struct { - isDisabled bool - permissions []*accesscontrol.Permission -} - -func (f fakeAccessControl) Evaluate(ctx context.Context, user *models.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { - permissions, _ := f.GetUserPermissions(ctx, user) - return evaluator.Evaluate(accesscontrol.GroupScopesByAction(permissions)) -} - -func (f fakeAccessControl) GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*accesscontrol.Permission, error) { - return f.permissions, nil -} - -func (f fakeAccessControl) IsDisabled() bool { - return f.isDisabled -} - -func (f fakeAccessControl) DeclareFixedRoles(registration ...accesscontrol.RoleRegistration) error { - return nil -} diff --git a/pkg/services/accesscontrol/mock/mock.go b/pkg/services/accesscontrol/mock/mock.go new file mode 100644 index 00000000000..e2f6d91c0e8 --- /dev/null +++ b/pkg/services/accesscontrol/mock/mock.go @@ -0,0 +1,152 @@ +package mock + +import ( + "context" + + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/accesscontrol" +) + +type fullAccessControl interface { + accesscontrol.AccessControl + GetUserBuiltInRoles(user *models.SignedInUser) []string + RegisterFixedRoles() error +} + +type Calls struct { + Evaluate []interface{} + GetUserPermissions []interface{} + IsDisabled []interface{} + DeclareFixedRoles []interface{} + GetUserBuiltInRoles []interface{} + RegisterFixedRoles []interface{} +} + +type Mock struct { + // Unless an override is provided, permissions will be returned by GetUserPermissions + permissions []*accesscontrol.Permission + // Unless an override is provided, disabled will be returned by IsDisabled + disabled bool + // Unless an override is provided, builtInRoles will be returned by GetUserBuiltInRoles + builtInRoles []string + + // Track the list of calls + Calls Calls + + // Override functions + EvaluateFunc func(context.Context, *models.SignedInUser, accesscontrol.Evaluator) (bool, error) + GetUserPermissionsFunc func(context.Context, *models.SignedInUser) ([]*accesscontrol.Permission, error) + IsDisabledFunc func() bool + DeclareFixedRolesFunc func(...accesscontrol.RoleRegistration) error + GetUserBuiltInRolesFunc func(user *models.SignedInUser) []string + RegisterFixedRolesFunc func() error +} + +type MockOptions func(*Mock) + +// Ensure the mock stays in line with the interface +var _ fullAccessControl = New() + +func New() *Mock { + mock := &Mock{ + Calls: Calls{}, + disabled: false, + permissions: []*accesscontrol.Permission{}, + builtInRoles: []string{}, + } + + return mock +} + +func (m Mock) WithPermissions(permissions []*accesscontrol.Permission) *Mock { + m.permissions = permissions + return &m +} + +func (m Mock) WithDisabled() *Mock { + m.disabled = true + return &m +} + +func (m Mock) WithBuiltInRoles(builtInRoles []string) *Mock { + m.builtInRoles = builtInRoles + return &m +} + +// Evaluate evaluates access to the given resource. +// This mock uses GetUserPermissions to then call the evaluator Evaluate function. +func (m *Mock) Evaluate(ctx context.Context, user *models.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { + m.Calls.Evaluate = append(m.Calls.Evaluate, []interface{}{ctx, user, evaluator}) + // Use override if provided + if m.EvaluateFunc != nil { + return m.EvaluateFunc(ctx, user, evaluator) + } + // Otherwise perform an actual evaluation of the permissions + permissions, err := m.GetUserPermissions(ctx, user) + if err != nil { + return false, err + } + return evaluator.Evaluate(accesscontrol.GroupScopesByAction(permissions)) +} + +// GetUserPermissions returns user permissions. +// This mock return m.permissions unless an override is provided. +func (m *Mock) GetUserPermissions(ctx context.Context, user *models.SignedInUser) ([]*accesscontrol.Permission, error) { + m.Calls.GetUserPermissions = append(m.Calls.GetUserPermissions, []interface{}{ctx, user}) + // Use override if provided + if m.GetUserPermissionsFunc != nil { + return m.GetUserPermissionsFunc(ctx, user) + } + // Otherwise return the Permissions list + return m.permissions, nil +} + +// Middleware checks if service disabled or not to switch to fallback authorization. +// This mock return m.disabled unless an override is provided. +func (m *Mock) IsDisabled() bool { + m.Calls.IsDisabled = append(m.Calls.IsDisabled, struct{}{}) + // Use override if provided + if m.IsDisabledFunc != nil { + return m.IsDisabledFunc() + } + // Otherwise return the Disabled bool + return m.disabled +} + +// DeclareFixedRoles allow the caller to declare, to the service, fixed roles and their +// assignments to organization roles ("Viewer", "Editor", "Admin") or "Grafana Admin" +// This mock returns no error unless an override is provided. +func (m *Mock) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistration) error { + m.Calls.DeclareFixedRoles = append(m.Calls.DeclareFixedRoles, []interface{}{registrations}) + // Use override if provided + if m.DeclareFixedRolesFunc != nil { + return m.DeclareFixedRolesFunc(registrations...) + } + return nil +} + +// GetUserBuiltInRoles returns the list of organizational roles ("Viewer", "Editor", "Admin") +// or "Grafana Admin" associated to a user +// This mock returns m.builtInRoles unless an override is provided. +func (m *Mock) GetUserBuiltInRoles(user *models.SignedInUser) []string { + m.Calls.GetUserBuiltInRoles = append(m.Calls.GetUserBuiltInRoles, []interface{}{user}) + + // Use override if provided + if m.GetUserBuiltInRolesFunc != nil { + return m.GetUserBuiltInRolesFunc(user) + } + + // Otherwise return the BuiltInRoles list + return m.builtInRoles +} + +// RegisterFixedRoles registers all roles declared to AccessControl +// This mock returns no error unless an override is provided. +func (m *Mock) RegisterFixedRoles() error { + m.Calls.RegisterFixedRoles = append(m.Calls.RegisterFixedRoles, []struct{}{}) + // Use override if provided + if m.RegisterFixedRolesFunc != nil { + return m.RegisterFixedRolesFunc() + } + return nil +} diff --git a/pkg/services/licensing/oss.go b/pkg/services/licensing/oss.go index 174ddf56c96..1113ea933f0 100644 --- a/pkg/services/licensing/oss.go +++ b/pkg/services/licensing/oss.go @@ -49,7 +49,7 @@ func (l *OSSLicensingService) Init() error { for _, node := range indexData.NavTree { if node.Id == "admin" { node.Children = append(node.Children, &dtos.NavLink{ - Text: "Upgrade", + Text: "Stats and license", Id: "upgrading", Url: l.LicenseURL(req.SignedInUser), Icon: "unlock", diff --git a/pkg/services/ngalert/notifier/receivers.go b/pkg/services/ngalert/notifier/receivers.go index 202c4954dbb..4985183d102 100644 --- a/pkg/services/ngalert/notifier/receivers.go +++ b/pkg/services/ngalert/notifier/receivers.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/url" + "sort" "time" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" @@ -126,6 +127,12 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei for _, next := range m { v.Receivers = append(v.Receivers, next) } + + // Make sure the return order is deterministic. + sort.Slice(v.Receivers, func(i, j int) bool { + return v.Receivers[i].Name < v.Receivers[j].Name + }) + return v } diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index 6c70b26e278..5ca3b45df74 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -1,5 +1,6 @@ import { size } from 'lodash'; -import { ansicolor, BarAlignment, colors, DrawStyle, StackingMode } from '@grafana/ui'; +import { BarAlignment, DrawStyle, StackingMode } from '@grafana/schema'; +import { ansicolor, colors } from '@grafana/ui'; import { AbsoluteTimeRange, diff --git a/public/app/features/admin/ServerStats.test.tsx b/public/app/features/admin/ServerStats.test.tsx index 575fe89826d..7ddcde97f99 100644 --- a/public/app/features/admin/ServerStats.test.tsx +++ b/public/app/features/admin/ServerStats.test.tsx @@ -1,27 +1,48 @@ import React from 'react'; -// @ts-ignore -import renderer from 'react-test-renderer'; -import { ServerStats } from './ServerStats'; -import { createNavModel } from 'test/mocks/common'; +import { render, screen } from '@testing-library/react'; +import { ServerStats, Props } from './ServerStats'; import { ServerStat } from './state/apis'; +const stats: ServerStat = { + activeAdmins: 1, + activeEditors: 0, + activeSessions: 1, + activeUsers: 1, + activeViewers: 0, + admins: 1, + alerts: 5, + dashboards: 1599, + datasources: 54, + editors: 2, + orgs: 1, + playlists: 1, + snapshots: 1, + stars: 3, + tags: 42, + users: 5, + viewers: 2, +}; + +const getServerStats = () => { + return Promise.resolve(stats); +}; + +const setup = (propOverrides?: Partial) => { + const props: Props = { + getServerStats, + }; + Object.assign(props, propOverrides); + + render(); +}; describe('ServerStats', () => { - it('Should render table with stats', (done) => { - const navModel = createNavModel('Admin', 'stats'); - const stats: ServerStat[] = [ - { name: 'Total dashboards', value: 10 }, - { name: 'Total Users', value: 1 }, - ]; - - const getServerStats = () => { - return Promise.resolve(stats); - }; - - const page = renderer.create(); - - setTimeout(() => { - expect(page.toJSON()).toBeDefined(); - done(); - }); + it('Should render page with stats', async () => { + setup(); + expect(await screen.findByRole('heading', { name: /instance statistics/i })).toBeInTheDocument(); + expect(screen.getByText('Dashboards (starred)')).toBeInTheDocument(); + expect(screen.getByText('Tags')).toBeInTheDocument(); + expect(screen.getByText('Playlists')).toBeInTheDocument(); + expect(screen.getByText('Snapshots')).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Manage dashboards' })).toBeInTheDocument(); }); }); diff --git a/public/app/features/admin/ServerStats.tsx b/public/app/features/admin/ServerStats.tsx index 95f45025dfe..81204802a2c 100644 --- a/public/app/features/admin/ServerStats.tsx +++ b/public/app/features/admin/ServerStats.tsx @@ -1,79 +1,187 @@ -import React, { PureComponent } from 'react'; +import React, { useEffect, useState } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import { Icon, Tooltip } from '@grafana/ui'; -import { NavModel } from '@grafana/data'; -import { StoreState } from 'app/types'; +import { css } from '@emotion/css'; +import { CardContainer, LinkButton, useStyles2 } from '@grafana/ui'; +import { GrafanaTheme2 } from '@grafana/data'; +import { AccessControlAction, StoreState } from 'app/types'; import { getNavModel } from 'app/core/selectors/navModel'; -import Page from 'app/core/components/Page/Page'; import { getServerStats, ServerStat } from './state/apis'; +import { contextSrv } from '../../core/services/context_srv'; +import { Loader } from '../plugins/admin/components/Loader'; -interface Props { - navModel: NavModel; - getServerStats: () => Promise; +export interface Props { + getServerStats: () => Promise; } -interface State { - stats: ServerStat[]; - isLoading: boolean; -} +export const ServerStats = ({ getServerStats }: Props) => { + const [stats, setStats] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const styles = useStyles2(getStyles); -export class ServerStats extends PureComponent { - state: State = { - stats: [], - isLoading: true, - }; + useEffect(() => { + getServerStats().then((stats) => { + setStats(stats); + setIsLoading(false); + }); + }, [getServerStats]); - async componentDidMount() { - try { - const stats = await this.props.getServerStats(); - this.setState({ stats, isLoading: false }); - } catch (error) { - console.error(error); - } + if (!contextSrv.hasPermission(AccessControlAction.ActionServerStatsRead)) { + return null; } - render() { - const { navModel } = this.props; - const { stats, isLoading } = this.state; - - return ( - - - - - - - - - - {stats.map(StatItem)} -
NameValue
-
-
- ); - } -} - -function StatItem(stat: ServerStat) { return ( - - - {stat.name}{' '} - {stat.tooltip && ( - - - - )} - - {stat.value} - + <> +

Instance statistics

+ {isLoading ? ( +
+ +
+ ) : stats ? ( +
+ + Manage dashboards + + } + /> + +
+ + Manage data sources + + } + /> + + Alerts + + } + /> +
+ + Manage users + + } + /> +
+ ) : ( +

No stats found.

+ )} + ); -} +}; + +const getStyles = (theme: GrafanaTheme2) => { + return { + title: css` + margin-bottom: ${theme.spacing(4)}; + `, + row: css` + display: flex; + justify-content: space-between; + width: 100%; + + & > div:not(:last-of-type) { + margin-right: ${theme.spacing(2)}; + } + + & > div { + width: 33.3%; + } + `, + doubleRow: css` + display: flex; + flex-direction: column; + + & > div:first-of-type { + margin-bottom: ${theme.spacing(2)}; + } + `, + + loader: css` + height: 290px; + `, + + notFound: css` + font-size: ${theme.typography.h6.fontSize}; + text-align: center; + height: 290px; + `, + }; +}; const mapStateToProps = (state: StoreState) => ({ navModel: getNavModel(state.navIndex, 'server-stats'), - getServerStats: getServerStats, + getServerStats, }); +type StatCardProps = { + content: Array>; + footer?: JSX.Element; +}; + +const StatCard = ({ content, footer }: StatCardProps) => { + const styles = useStyles2(getCardStyles); + return ( + +
+
+ {content.map((item) => { + return ( +
+ {item.name} + {item.value} +
+ ); + })} +
+ {footer &&
{footer}
} +
+
+ ); +}; + +const getCardStyles = (theme: GrafanaTheme2) => { + return { + container: css` + padding: ${theme.spacing(2)}; + `, + inner: css` + display: flex; + flex-direction: column; + width: 100%; + `, + content: css` + flex: 1 0 auto; + `, + row: css` + display: flex; + justify-content: space-between; + width: 100%; + margin-bottom: ${theme.spacing(2)}; + align-items: center; + `, + }; +}; export default hot(module)(connect(mapStateToProps)(ServerStats)); diff --git a/public/app/features/admin/UpgradePage.tsx b/public/app/features/admin/UpgradePage.tsx index f597052c7ee..b963cb0664e 100644 --- a/public/app/features/admin/UpgradePage.tsx +++ b/public/app/features/admin/UpgradePage.tsx @@ -1,13 +1,14 @@ import React from 'react'; -import { css } from '@emotion/css'; -import { NavModel } from '@grafana/data'; -import Page from '../../core/components/Page/Page'; -import { LicenseChrome } from './LicenseChrome'; -import { LinkButton } from '@grafana/ui'; -import { hot } from 'react-hot-loader'; -import { StoreState } from '../../types'; -import { getNavModel } from '../../core/selectors/navModel'; import { connect } from 'react-redux'; +import { hot } from 'react-hot-loader'; +import { css } from '@emotion/css'; +import { LinkButton, useStyles2 } from '@grafana/ui'; +import { GrafanaTheme2, NavModel } from '@grafana/data'; +import Page from '../../core/components/Page/Page'; +import { getNavModel } from '../../core/selectors/navModel'; +import { LicenseChrome } from './LicenseChrome'; +import { StoreState } from '../../types'; +import ServerStats from './ServerStats'; interface Props { navModel: NavModel; @@ -17,6 +18,7 @@ export const UpgradePage: React.FC = ({ navModel }) => { return ( + = ({ editionNotice }) => { - const columnStyles = css` - display: grid; - grid-template-columns: 100%; - column-gap: 20px; - row-gap: 40px; - - @media (min-width: 1050px) { - grid-template-columns: 50% 50%; - } - `; + const styles = useStyles2(getStyles); return ( - -
- - -
-
+ <> +

Enterprise license

+ +
+ + +
+
+ ); }; +const getStyles = (theme: GrafanaTheme2) => { + return { + column: css` + display: grid; + grid-template-columns: 100%; + column-gap: 20px; + row-gap: 40px; + + @media (min-width: 1050px) { + grid-template-columns: 50% 50%; + } + `, + title: css` + margin: ${theme.spacing(4)} 0; + `, + }; +}; + const GetEnterprise: React.FC = () => { return (
diff --git a/public/app/features/admin/state/apis.tsx b/public/app/features/admin/state/apis.tsx index ae3a5731212..79c2061e4f5 100644 --- a/public/app/features/admin/state/apis.tsx +++ b/public/app/features/admin/state/apis.tsx @@ -1,58 +1,30 @@ -import React from 'react'; import { getBackendSrv } from '@grafana/runtime'; -import { PopoverContent } from '@grafana/ui'; -import { config } from 'app/core/config'; export interface ServerStat { - name: string; - value: number; - tooltip?: PopoverContent; + activeAdmins: number; + activeEditors: number; + activeSessions: number; + activeUsers: number; + activeViewers: number; + admins: number; + alerts: number; + dashboards: number; + datasources: number; + editors: number; + orgs: number; + playlists: number; + snapshots: number; + stars: number; + tags: number; + users: number; + viewers: number; } -const { hasLicense } = config.licenseInfo; - -export const getServerStats = async (): Promise => { - try { - const res = await getBackendSrv().get('api/admin/stats'); - return [ - { name: 'Total users', value: res.users }, - ...(!hasLicense - ? [ - { name: 'Total admins', value: res.admins }, - { name: 'Total editors', value: res.editors }, - { name: 'Total viewers', value: res.viewers }, - ] - : []), - { - name: 'Active users (seen last 30 days)', - value: res.activeUsers, - tooltip: hasLicense - ? () => ( - <> - For active user count by role, see the Licensing page. - - ) - : '', - }, - ...(!hasLicense - ? [ - { name: 'Active admins (seen last 30 days)', value: res.activeAdmins }, - { name: 'Active editors (seen last 30 days)', value: res.activeEditors }, - { name: 'Active viewers (seen last 30 days)', value: res.activeViewers }, - ] - : []), - { name: 'Active sessions', value: res.activeSessions }, - { name: 'Total dashboards', value: res.dashboards }, - { name: 'Total orgs', value: res.orgs }, - { name: 'Total playlists', value: res.playlists }, - { name: 'Total snapshots', value: res.snapshots }, - { name: 'Total dashboard tags', value: res.tags }, - { name: 'Total starred dashboards', value: res.stars }, - { name: 'Total alerts', value: res.alerts }, - { name: 'Total data sources', value: res.datasources }, - ]; - } catch (error) { - console.error(error); - throw error; - } +export const getServerStats = async (): Promise => { + return getBackendSrv() + .get('api/admin/stats') + .catch((err) => { + console.error(err); + return null; + }); }; diff --git a/public/app/features/explore/ExploreGraphNGPanel.tsx b/public/app/features/explore/ExploreGraphNGPanel.tsx index 412f29d8e2c..b5117c9e357 100644 --- a/public/app/features/explore/ExploreGraphNGPanel.tsx +++ b/public/app/features/explore/ExploreGraphNGPanel.tsx @@ -14,7 +14,6 @@ import { TimeZone, } from '@grafana/data'; import { - DrawStyle, Icon, PanelContext, PanelContextProvider, @@ -25,7 +24,7 @@ import { useTheme2, ZoomPlugin, } from '@grafana/ui'; -import { LegendDisplayMode, TooltipDisplayMode } from '@grafana/schema'; +import { LegendDisplayMode, TooltipDisplayMode, DrawStyle } from '@grafana/schema'; import { defaultGraphConfig, getGraphFieldConfig } from 'app/plugins/panel/timeseries/config'; import { ContextMenuPlugin } from 'app/plugins/panel/timeseries/plugins/ContextMenuPlugin'; import { ExemplarsPlugin } from 'app/plugins/panel/timeseries/plugins/ExemplarsPlugin'; diff --git a/public/app/features/explore/utils/decorators.test.ts b/public/app/features/explore/utils/decorators.test.ts index 550431de25b..21a2c1926f1 100644 --- a/public/app/features/explore/utils/decorators.test.ts +++ b/public/app/features/explore/utils/decorators.test.ts @@ -1,4 +1,4 @@ -import { DrawStyle, StackingMode } from '@grafana/ui'; +import { DrawStyle, StackingMode } from '@grafana/schema'; import { lastValueFrom } from 'rxjs'; import { ArrayVector, diff --git a/public/app/features/plugins/admin/components/Loader.tsx b/public/app/features/plugins/admin/components/Loader.tsx index 8cfa0d05dff..1113f8e7215 100644 --- a/public/app/features/plugins/admin/components/Loader.tsx +++ b/public/app/features/plugins/admin/components/Loader.tsx @@ -2,11 +2,15 @@ import React from 'react'; import { LoadingPlaceholder } from '@grafana/ui'; import { Page } from './Page'; -export const Loader = () => { +export interface Props { + text?: string; +} + +export const Loader = ({ text = 'Loading...' }: Props) => { return (
- +
); diff --git a/public/app/plugins/panel/barchart/BarChartPanel.tsx b/public/app/plugins/panel/barchart/BarChartPanel.tsx index 41541603810..f766626c92d 100755 --- a/public/app/plugins/panel/barchart/BarChartPanel.tsx +++ b/public/app/plugins/panel/barchart/BarChartPanel.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; -import { TooltipDisplayMode } from '@grafana/schema'; +import { TooltipDisplayMode, StackingMode } from '@grafana/schema'; import { PanelProps, TimeRange, VizOrientation } from '@grafana/data'; -import { StackingMode, TooltipPlugin, useTheme2 } from '@grafana/ui'; +import { TooltipPlugin, useTheme2 } from '@grafana/ui'; import { BarChartOptions } from './types'; import { BarChart } from './BarChart'; import { prepareGraphableFrames } from './utils'; diff --git a/public/app/plugins/panel/barchart/bars.ts b/public/app/plugins/panel/barchart/bars.ts index 11e0732ea42..509e455db0d 100644 --- a/public/app/plugins/panel/barchart/bars.ts +++ b/public/app/plugins/panel/barchart/bars.ts @@ -2,15 +2,14 @@ import uPlot, { Axis, AlignedData } from 'uplot'; import { pointWithin, Quadtree, Rect } from './quadtree'; import { distribute, SPACE_BETWEEN } from './distribute'; import { DataFrame, GrafanaTheme2 } from '@grafana/data'; -import { VizTextDisplayOptions } from '@grafana/schema'; +import { calculateFontSize, PlotTooltipInterpolator } from '@grafana/ui'; import { - calculateFontSize, - PlotTooltipInterpolator, StackingMode, BarValueVisibility, ScaleDirection, ScaleOrientation, -} from '@grafana/ui'; + VizTextDisplayOptions, +} from '@grafana/schema'; import { preparePlotData } from '../../../../../packages/grafana-ui/src/components/uPlot/utils'; const groupDistr = SPACE_BETWEEN; diff --git a/public/app/plugins/panel/barchart/module.tsx b/public/app/plugins/panel/barchart/module.tsx index 69e876842ff..583878c5dbf 100755 --- a/public/app/plugins/panel/barchart/module.tsx +++ b/public/app/plugins/panel/barchart/module.tsx @@ -7,7 +7,8 @@ import { VizOrientation, } from '@grafana/data'; import { BarChartPanel } from './BarChartPanel'; -import { StackingMode, BarValueVisibility, graphFieldOptions, commonOptionsBuilder } from '@grafana/ui'; +import { StackingMode, BarValueVisibility } from '@grafana/schema'; +import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui'; import { BarChartFieldConfig, BarChartOptions, defaultBarChartFieldConfig } from 'app/plugins/panel/barchart/types'; diff --git a/public/app/plugins/panel/barchart/types.ts b/public/app/plugins/panel/barchart/types.ts index 66aa1b26c54..b80cab51265 100644 --- a/public/app/plugins/panel/barchart/types.ts +++ b/public/app/plugins/panel/barchart/types.ts @@ -1,6 +1,14 @@ -import { OptionsWithLegend, OptionsWithTextFormatting, OptionsWithTooltip } from '@grafana/schema'; +import { + OptionsWithLegend, + OptionsWithTextFormatting, + OptionsWithTooltip, + AxisConfig, + BarValueVisibility, + GraphGradientMode, + HideableFieldConfig, + StackingMode, +} from '@grafana/schema'; import { VizOrientation } from '@grafana/data'; -import { AxisConfig, BarValueVisibility, GraphGradientMode, HideableFieldConfig, StackingMode } from '@grafana/ui'; /** * @alpha diff --git a/public/app/plugins/panel/barchart/utils.test.ts b/public/app/plugins/panel/barchart/utils.test.ts index 6c3330dee45..7d233d8cd64 100644 --- a/public/app/plugins/panel/barchart/utils.test.ts +++ b/public/app/plugins/panel/barchart/utils.test.ts @@ -1,5 +1,11 @@ import { prepareGraphableFrames, preparePlotConfigBuilder, preparePlotFrame } from './utils'; -import { LegendDisplayMode, TooltipDisplayMode } from '@grafana/schema'; +import { + LegendDisplayMode, + TooltipDisplayMode, + BarValueVisibility, + GraphGradientMode, + StackingMode, +} from '@grafana/schema'; import { createTheme, DefaultTimeZone, @@ -11,7 +17,6 @@ import { VizOrientation, } from '@grafana/data'; import { BarChartFieldConfig, BarChartOptions } from './types'; -import { BarValueVisibility, GraphGradientMode, StackingMode } from '@grafana/ui'; function mockDataFrame() { const df1 = new MutableDataFrame({ diff --git a/public/app/plugins/panel/barchart/utils.ts b/public/app/plugins/panel/barchart/utils.ts index b35c3b2b5d0..261ef27ecf9 100644 --- a/public/app/plugins/panel/barchart/utils.ts +++ b/public/app/plugins/panel/barchart/utils.ts @@ -13,16 +13,8 @@ import { } from '@grafana/data'; import { BarChartFieldConfig, BarChartOptions, defaultBarChartFieldConfig } from './types'; import { BarsOptions, getConfig } from './bars'; -import { - AxisPlacement, - FIXED_UNIT, - ScaleDirection, - ScaleDistribution, - ScaleOrientation, - StackingMode, - UPlotConfigBuilder, - UPlotConfigPrepFn, -} from '@grafana/ui'; +import { AxisPlacement, ScaleDirection, ScaleDistribution, ScaleOrientation, StackingMode } from '@grafana/schema'; +import { FIXED_UNIT, UPlotConfigBuilder, UPlotConfigPrepFn } from '@grafana/ui'; import { collectStackingGroups } from '../../../../../packages/grafana-ui/src/components/uPlot/utils'; /** @alpha */ diff --git a/public/app/plugins/panel/histogram/Histogram.tsx b/public/app/plugins/panel/histogram/Histogram.tsx index dbe08ac5216..d74ce4d7878 100644 --- a/public/app/plugins/panel/histogram/Histogram.tsx +++ b/public/app/plugins/panel/histogram/Histogram.tsx @@ -1,6 +1,13 @@ import React from 'react'; import uPlot, { AlignedData } from 'uplot'; -import { VizLegendOptions, LegendDisplayMode } from '@grafana/schema'; +import { + VizLegendOptions, + LegendDisplayMode, + ScaleDistribution, + AxisPlacement, + ScaleDirection, + ScaleOrientation, +} from '@grafana/schema'; import { DataFrame, formattedValueToString, @@ -8,23 +15,13 @@ import { getFieldSeriesColor, GrafanaTheme2, } from '@grafana/data'; -import { - Themeable2, - UPlotConfigBuilder, - UPlotChart, - VizLayout, - AxisPlacement, - ScaleDirection, - ScaleOrientation, - PlotLegend, -} from '@grafana/ui'; +import { Themeable2, UPlotConfigBuilder, UPlotChart, VizLayout, PlotLegend } from '@grafana/ui'; import { histogramBucketSizes, histogramFrameBucketMaxFieldName, } from '@grafana/data/src/transformations/transformers/histogram'; import { PanelOptions } from './models.gen'; -import { ScaleDistribution } from '@grafana/ui/src/components/uPlot/models.gen'; function incrRoundDn(num: number, incr: number) { return Math.floor(num / incr) * incr; diff --git a/public/app/plugins/panel/histogram/models.gen.ts b/public/app/plugins/panel/histogram/models.gen.ts index 4cc57e51978..8b1c0cfb095 100644 --- a/public/app/plugins/panel/histogram/models.gen.ts +++ b/public/app/plugins/panel/histogram/models.gen.ts @@ -3,8 +3,14 @@ // It is currenty hand written but will serve as the target for cuetsy //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -import { LegendDisplayMode, OptionsWithLegend, OptionsWithTooltip, TooltipDisplayMode } from '@grafana/schema'; -import { GraphGradientMode, HideableFieldConfig } from '@grafana/ui'; +import { + LegendDisplayMode, + OptionsWithLegend, + OptionsWithTooltip, + TooltipDisplayMode, + GraphGradientMode, + HideableFieldConfig, +} from '@grafana/schema'; export const modelVersion = Object.freeze([1, 0]); diff --git a/public/app/plugins/panel/state-timeline/TimelineChart.tsx b/public/app/plugins/panel/state-timeline/TimelineChart.tsx index 4d2ccfbba06..22444eb9d73 100755 --- a/public/app/plugins/panel/state-timeline/TimelineChart.tsx +++ b/public/app/plugins/panel/state-timeline/TimelineChart.tsx @@ -1,11 +1,10 @@ import React from 'react'; -import { LegendDisplayMode } from '@grafana/schema'; +import { LegendDisplayMode, BarValueVisibility } from '@grafana/schema'; import { PanelContext, PanelContextRoot, GraphNG, GraphNGProps, - BarValueVisibility, UPlotConfigBuilder, VizLayout, VizLegend, diff --git a/public/app/plugins/panel/state-timeline/module.tsx b/public/app/plugins/panel/state-timeline/module.tsx index 18ea3c45b6b..793d0c2f9e9 100755 --- a/public/app/plugins/panel/state-timeline/module.tsx +++ b/public/app/plugins/panel/state-timeline/module.tsx @@ -1,7 +1,8 @@ import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data'; import { StateTimelinePanel } from './StateTimelinePanel'; import { TimelineOptions, TimelineFieldConfig, defaultPanelOptions, defaultTimelineFieldConfig } from './types'; -import { BarValueVisibility, commonOptionsBuilder } from '@grafana/ui'; +import { BarValueVisibility } from '@grafana/schema'; +import { commonOptionsBuilder } from '@grafana/ui'; import { timelinePanelChangedHandler } from './migrations'; export const plugin = new PanelPlugin(StateTimelinePanel) diff --git a/public/app/plugins/panel/state-timeline/timeline.ts b/public/app/plugins/panel/state-timeline/timeline.ts index 975d485f084..a9d3f525bd4 100644 --- a/public/app/plugins/panel/state-timeline/timeline.ts +++ b/public/app/plugins/panel/state-timeline/timeline.ts @@ -4,7 +4,7 @@ import { pointWithin, Quadtree, Rect } from 'app/plugins/panel/barchart/quadtree import { distribute, SPACE_BETWEEN } from 'app/plugins/panel/barchart/distribute'; import { TimelineFieldConfig, TimelineMode, TimelineValueAlignment } from './types'; import { GrafanaTheme2, TimeRange } from '@grafana/data'; -import { BarValueVisibility } from '@grafana/ui'; +import { BarValueVisibility } from '@grafana/schema'; import { alpha } from '@grafana/data/src/themes/colorManipulator'; const { round, min, ceil } = Math; diff --git a/public/app/plugins/panel/state-timeline/types.ts b/public/app/plugins/panel/state-timeline/types.ts index 9cda1c5d30a..909cb58a55a 100644 --- a/public/app/plugins/panel/state-timeline/types.ts +++ b/public/app/plugins/panel/state-timeline/types.ts @@ -1,5 +1,4 @@ -import { OptionsWithTooltip, OptionsWithLegend } from '@grafana/schema'; -import { HideableFieldConfig, BarValueVisibility } from '@grafana/ui'; +import { OptionsWithTooltip, OptionsWithLegend, HideableFieldConfig, BarValueVisibility } from '@grafana/schema'; /** * @alpha diff --git a/public/app/plugins/panel/state-timeline/utils.ts b/public/app/plugins/panel/state-timeline/utils.ts index 0ab875dcc5e..fd1d9d77e03 100644 --- a/public/app/plugins/panel/state-timeline/utils.ts +++ b/public/app/plugins/panel/state-timeline/utils.ts @@ -1,5 +1,4 @@ import React from 'react'; -import { VizLegendOptions } from '@grafana/schema'; import { XYFieldMatchers } from '@grafana/ui/src/components/GraphNG/types'; import { ArrayVector, @@ -24,7 +23,7 @@ import { VizLegendItem, } from '@grafana/ui'; import { getConfig, TimelineCoreOptions } from './timeline'; -import { AxisPlacement, ScaleDirection, ScaleOrientation } from '@grafana/ui/src/components/uPlot/config'; +import { VizLegendOptions, AxisPlacement, ScaleDirection, ScaleOrientation } from '@grafana/schema'; import { TimelineFieldConfig, TimelineOptions } from './types'; import { PlotTooltipInterpolator } from '@grafana/ui/src/components/uPlot/types'; import { preparePlotData } from '../../../../../packages/grafana-ui/src/components/uPlot/utils'; diff --git a/public/app/plugins/panel/status-history/module.tsx b/public/app/plugins/panel/status-history/module.tsx index e83d1239372..505a241e846 100755 --- a/public/app/plugins/panel/status-history/module.tsx +++ b/public/app/plugins/panel/status-history/module.tsx @@ -1,7 +1,8 @@ import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data'; import { StatusHistoryPanel } from './StatusHistoryPanel'; import { StatusPanelOptions, StatusFieldConfig, defaultStatusFieldConfig } from './types'; -import { BarValueVisibility, commonOptionsBuilder } from '@grafana/ui'; +import { BarValueVisibility } from '@grafana/schema'; +import { commonOptionsBuilder } from '@grafana/ui'; export const plugin = new PanelPlugin(StatusHistoryPanel) .useFieldConfig({ diff --git a/public/app/plugins/panel/status-history/types.ts b/public/app/plugins/panel/status-history/types.ts index bab48dc0a39..ed96f94e634 100644 --- a/public/app/plugins/panel/status-history/types.ts +++ b/public/app/plugins/panel/status-history/types.ts @@ -1,5 +1,4 @@ -import { HideableFieldConfig, BarValueVisibility } from '@grafana/ui'; -import { OptionsWithTooltip, OptionsWithLegend } from '@grafana/schema'; +import { HideableFieldConfig, BarValueVisibility, OptionsWithTooltip, OptionsWithLegend } from '@grafana/schema'; /** * @alpha diff --git a/public/app/plugins/panel/timeseries/LineStyleEditor.tsx b/public/app/plugins/panel/timeseries/LineStyleEditor.tsx index bc5448fef07..75a089ce70e 100644 --- a/public/app/plugins/panel/timeseries/LineStyleEditor.tsx +++ b/public/app/plugins/panel/timeseries/LineStyleEditor.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from 'react'; +import { LineStyle } from '@grafana/schema'; import { FieldOverrideEditorProps, SelectableValue } from '@grafana/data'; -import { HorizontalGroup, IconButton, LineStyle, RadioButtonGroup, Select } from '@grafana/ui'; +import { HorizontalGroup, IconButton, RadioButtonGroup, Select } from '@grafana/ui'; type LineFill = 'solid' | 'dash' | 'dot'; diff --git a/public/app/plugins/panel/timeseries/ThresholdsStyleEditor.tsx b/public/app/plugins/panel/timeseries/ThresholdsStyleEditor.tsx index 560b053268f..03669ad9187 100644 --- a/public/app/plugins/panel/timeseries/ThresholdsStyleEditor.tsx +++ b/public/app/plugins/panel/timeseries/ThresholdsStyleEditor.tsx @@ -1,6 +1,7 @@ import React, { useCallback } from 'react'; +import { GraphTresholdsStyleMode } from '@grafana/schema'; import { FieldOverrideEditorProps, SelectableValue } from '@grafana/data'; -import { GraphTresholdsStyleMode, Select } from '@grafana/ui'; +import { Select } from '@grafana/ui'; export const ThresholdsStyleEditor: React.FC< FieldOverrideEditorProps, any> diff --git a/public/app/plugins/panel/timeseries/config.ts b/public/app/plugins/panel/timeseries/config.ts index be629fa2e06..576b65b87ae 100644 --- a/public/app/plugins/panel/timeseries/config.ts +++ b/public/app/plugins/panel/timeseries/config.ts @@ -10,15 +10,16 @@ import { BarAlignment, DrawStyle, GraphFieldConfig, - graphFieldOptions, GraphGradientMode, LineInterpolation, LineStyle, PointVisibility, StackingMode, - commonOptionsBuilder, GraphTresholdsStyleMode, -} from '@grafana/ui'; +} from '@grafana/schema'; + +import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui'; + import { LineStyleEditor } from './LineStyleEditor'; import { FillBellowToEditor } from './FillBelowToEditor'; import { SpanNullsEditor } from './SpanNullsEditor'; diff --git a/public/app/plugins/panel/timeseries/migrations.ts b/public/app/plugins/panel/timeseries/migrations.ts index badcdee201a..46cbb9e0b78 100644 --- a/public/app/plugins/panel/timeseries/migrations.ts +++ b/public/app/plugins/panel/timeseries/migrations.ts @@ -13,6 +13,8 @@ import { ThresholdsMode, } from '@grafana/data'; import { + LegendDisplayMode, + TooltipDisplayMode, AxisPlacement, DrawStyle, GraphFieldConfig, @@ -23,8 +25,7 @@ import { PointVisibility, ScaleDistribution, StackingMode, -} from '@grafana/ui'; -import { LegendDisplayMode, TooltipDisplayMode } from '@grafana/schema'; +} from '@grafana/schema'; import { TimeSeriesOptions } from './types'; import { omitBy, pickBy, isNil, isNumber, isString } from 'lodash'; import { defaultGraphConfig } from './config'; diff --git a/public/app/plugins/panel/timeseries/module.tsx b/public/app/plugins/panel/timeseries/module.tsx index fa08e647799..a6dc76b8940 100644 --- a/public/app/plugins/panel/timeseries/module.tsx +++ b/public/app/plugins/panel/timeseries/module.tsx @@ -1,5 +1,6 @@ +import { GraphFieldConfig } from '@grafana/schema'; import { PanelPlugin } from '@grafana/data'; -import { GraphFieldConfig, commonOptionsBuilder } from '@grafana/ui'; +import { commonOptionsBuilder } from '@grafana/ui'; import { TimeSeriesPanel } from './TimeSeriesPanel'; import { graphPanelChangedHandler } from './migrations'; import { TimeSeriesOptions } from './types'; diff --git a/public/app/plugins/panel/timeseries/utils.ts b/public/app/plugins/panel/timeseries/utils.ts index 6bcc2db2dec..da4cdee11a1 100644 --- a/public/app/plugins/panel/timeseries/utils.ts +++ b/public/app/plugins/panel/timeseries/utils.ts @@ -7,7 +7,7 @@ import { GrafanaTheme2, isBooleanUnit, } from '@grafana/data'; -import { GraphFieldConfig, LineInterpolation, StackingMode } from '@grafana/ui'; +import { GraphFieldConfig, LineInterpolation, StackingMode } from '@grafana/schema'; // This will return a set of frames with only graphable values included export function prepareGraphableFields( diff --git a/public/app/plugins/panel/xychart/module.tsx b/public/app/plugins/panel/xychart/module.tsx index 9003dde7d92..6c8ebf9c4d0 100644 --- a/public/app/plugins/panel/xychart/module.tsx +++ b/public/app/plugins/panel/xychart/module.tsx @@ -1,5 +1,6 @@ +import { GraphFieldConfig, DrawStyle } from '@grafana/schema'; import { PanelPlugin } from '@grafana/data'; -import { DrawStyle, GraphFieldConfig, commonOptionsBuilder } from '@grafana/ui'; +import { commonOptionsBuilder } from '@grafana/ui'; import { XYChartPanel } from './XYChartPanel'; import { Options } from './types'; import { XYDimsEditor } from './XYDimsEditor'; diff --git a/public/app/types/accessControl.ts b/public/app/types/accessControl.ts index d5e795ed969..445ec2f34e8 100644 --- a/public/app/types/accessControl.ts +++ b/public/app/types/accessControl.ts @@ -34,4 +34,6 @@ export enum AccessControlAction { LDAPUsersSync = 'ldap.user:sync', LDAPStatusRead = 'ldap.status:read', DataSourcesExplore = 'datasources:explore', + + ActionServerStatsRead = 'server.stats:read', }