Icon Panel: add new alpha panel to show an icon (#40355)

This commit is contained in:
Ryan McKinley
2021-10-14 09:30:21 -07:00
committed by GitHub
parent d8c71370ef
commit 7a35a31929
10 changed files with 147 additions and 6 deletions

1
.github/CODEOWNERS vendored
View File

@@ -92,6 +92,7 @@ go.sum @grafana/backend-platform
/public/app/plugins/panel/timeseries @grafana/grafana-bi-squad
/public/app/plugins/panel/geomap @grafana/grafana-edge-squad
/public/app/plugins/panel/canvas @grafana/grafana-edge-squad
/public/app/plugins/panel/icon @grafana/grafana-edge-squad
/scripts/build/release-packages.sh @grafana/plugins-platform
/scripts/circle-release-next-packages.sh @grafana/plugins-platform
/scripts/ci-frontend-metrics.sh @grafana/user-essentials @grafana/plugins-platform @grafana/grafana-bi-squad

View File

@@ -14,7 +14,7 @@ import { isString } from 'lodash';
import { LineConfig } from '../types';
import { DimensionContext } from 'app/features/dimensions/context';
interface IconConfig {
export interface IconConfig {
path?: ResourceDimensionConfig;
fill?: ColorDimensionConfig;
stroke?: LineConfig;

View File

@@ -71,6 +71,7 @@ import * as alertGroupsPanel from 'app/plugins/panel/alertGroups/module';
// Async loaded panels
const geomapPanel = async () => await import(/* webpackChunkName: "geomapPanel" */ 'app/plugins/panel/geomap/module');
const canvasPanel = async () => await import(/* webpackChunkName: "canvasPanel" */ 'app/plugins/panel/canvas/module');
const iconPanel = async () => await import(/* webpackChunkName: "iconPanel" */ 'app/plugins/panel/icon/module');
const builtInPlugins: any = {
'app/plugins/datasource/graphite/module': graphitePlugin,
@@ -102,6 +103,7 @@ const builtInPlugins: any = {
'app/plugins/panel/xychart/module': xyChartPanel,
'app/plugins/panel/geomap/module': geomapPanel,
'app/plugins/panel/canvas/module': canvasPanel,
'app/plugins/panel/icon/module': iconPanel,
'app/plugins/panel/dashlist/module': dashListPanel,
'app/plugins/panel/pluginlist/module': pluginsListPanel,
'app/plugins/panel/alertlist/module': alertListPanel,

View File

@@ -89,7 +89,7 @@ export class CanvasPanel extends Component<Props, State> {
};
shouldComponentUpdate(nextProps: Props) {
const { width, height, data, renderCounter } = this.props;
const { width, height, data } = this.props;
let changed = false;
if (width !== nextProps.width || height !== nextProps.height) {
@@ -110,10 +110,6 @@ export class CanvasPanel extends Component<Props, State> {
changed = true;
}
if (renderCounter !== nextProps.renderCounter) {
changed = true;
}
return changed;
}

View File

@@ -0,0 +1,67 @@
import React, { Component } from 'react';
import { PanelProps } from '@grafana/data';
import { PanelOptions } from './models.gen';
import { ElementState } from 'app/features/canvas/runtime/element';
import { iconItem } from 'app/features/canvas/elements/icon';
import {
ColorDimensionConfig,
DimensionContext,
getColorDimensionFromData,
getResourceDimensionFromData,
getScaleDimensionFromData,
getTextDimensionFromData,
ResourceDimensionConfig,
ScaleDimensionConfig,
TextDimensionConfig,
} from 'app/features/dimensions';
interface Props extends PanelProps<PanelOptions> {}
export class IconPanel extends Component<Props> {
private element: ElementState;
constructor(props: Props) {
super(props);
this.element = this.initElement(props);
}
initElement = (props: Props) => {
this.element = new ElementState(iconItem, props.options.root as any);
this.element.updateSize(props.width, props.height);
this.element.updateData(this.dims);
return this.element;
};
dims: DimensionContext = {
getColor: (color: ColorDimensionConfig) => getColorDimensionFromData(this.props.data, color),
getScale: (scale: ScaleDimensionConfig) => getScaleDimensionFromData(this.props.data, scale),
getText: (text: TextDimensionConfig) => getTextDimensionFromData(this.props.data, text),
getResource: (res: ResourceDimensionConfig) => getResourceDimensionFromData(this.props.data, res),
};
shouldComponentUpdate(nextProps: Props) {
const { width, height, data } = this.props;
let changed = false;
if (width !== nextProps.width || height !== nextProps.height) {
this.element.updateSize(nextProps.width, nextProps.height);
changed = true;
}
if (data !== nextProps.data) {
this.element.updateData(this.dims);
changed = true;
}
// Reload the element when options change
if (this.props.options?.root !== nextProps.options?.root) {
this.initElement(nextProps);
changed = true;
}
return changed;
}
render() {
const { width, height } = this.props;
return <div style={{ width, height, overflow: 'hidden', position: 'relative' }}>{this.element.render()}</div>;
}
}

View File

@@ -0,0 +1,3 @@
# Icon panel - Native Plugin
The icon panel is **included** with Grafana.

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<defs><style>.cls-1{fill:#84aff1;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:#3865ab;}</style><linearGradient id="linear-gradient" y1="40.18" x2="82.99" y2="40.18" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2cc0c"/><stop offset="1" stop-color="#ff9830"/></linearGradient></defs>
<path class="cls-3" d="M21.92,6.62a1,1,0,0,0-.54-.54A1,1,0,0,0,21,6H16a1,1,0,0,0,0,2h2.59L13,13.59l-3.29-3.3a1,1,0,0,0-1.42,0l-6,6a1,1,0,0,0,0,1.42,1,1,0,0,0,1.42,0L9,12.41l3.29,3.3a1,1,0,0,0,1.42,0L20,9.41V12a1,1,0,0,0,2,0V7A1,1,0,0,0,21.92,6.62Z" />
</svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@@ -0,0 +1,23 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NOTE: This file will be auto generated from models.cue
// It is currenty hand written but will serve as the target for cuetsy
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import { CanvasElementOptions } from 'app/features/canvas';
import { IconConfig } from 'app/features/canvas/elements/icon';
import { ResourceDimensionMode } from 'app/features/dimensions';
export interface PanelOptions {
root: Omit<CanvasElementOptions<IconConfig>, 'type'>; // type is forced
}
export const defaultPanelOptions: PanelOptions = {
root: {
config: {
path: {
mode: ResourceDimensionMode.Fixed,
fixed: 'img/icons/unicons/analysis.svg',
},
},
},
};

View File

@@ -0,0 +1,27 @@
import { PanelPlugin } from '@grafana/data';
import { IconPanel } from './IconPanel';
import { defaultPanelOptions, PanelOptions } from './models.gen';
import { IconConfig, iconItem } from 'app/features/canvas/elements/icon';
import { optionBuilder } from '../canvas/editor/options';
import { CanvasElementOptions } from 'app/features/canvas';
export const plugin = new PanelPlugin<PanelOptions>(IconPanel)
.setNoPadding() // extend to panel edges
.useFieldConfig()
.setPanelOptions((builder) => {
builder.addNestedOptions<CanvasElementOptions<IconConfig>>({
category: ['Icon'],
path: 'root',
// Dynamically fill the selected element
build: (builder, ctx) => {
iconItem.registerOptionsUI!(builder, ctx);
optionBuilder.addBackground(builder, ctx);
optionBuilder.addBorder(builder, ctx);
},
defaultValue: defaultPanelOptions.root as any,
});
});

View File

@@ -0,0 +1,18 @@
{
"type": "panel",
"name": "Icon",
"id": "icon",
"state": "alpha",
"info": {
"description": "Show icon based on data",
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"logos": {
"small": "img/icn-icon.svg",
"large": "img/icn-icon.svg"
}
}
}