From 516bdddcb5c2464934576e984e239b18bf0ce8bc Mon Sep 17 00:00:00 2001 From: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> Date: Thu, 19 Jan 2023 12:03:17 -0800 Subject: [PATCH] Canvas: Add server element (#61104) Co-authored-by: nmarrs --- .../canvas/elements/server/server.tsx | 211 ++++++++++++++++++ .../canvas/elements/server/types/database.tsx | 42 ++++ .../canvas/elements/server/types/single.tsx | 32 +++ .../canvas/elements/server/types/stack.tsx | 52 +++++ .../canvas/elements/server/types/terminal.tsx | 41 ++++ public/app/features/canvas/registry.ts | 2 + 6 files changed, 380 insertions(+) create mode 100644 public/app/features/canvas/elements/server/server.tsx create mode 100644 public/app/features/canvas/elements/server/types/database.tsx create mode 100644 public/app/features/canvas/elements/server/types/single.tsx create mode 100644 public/app/features/canvas/elements/server/types/stack.tsx create mode 100644 public/app/features/canvas/elements/server/types/terminal.tsx diff --git a/public/app/features/canvas/elements/server/server.tsx b/public/app/features/canvas/elements/server/server.tsx new file mode 100644 index 00000000000..3bb6c648450 --- /dev/null +++ b/public/app/features/canvas/elements/server/server.tsx @@ -0,0 +1,211 @@ +import { css } from '@emotion/css'; +import React from 'react'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { ColorDimensionConfig, DimensionContext, ScalarDimensionConfig } from 'app/features/dimensions'; +import { ColorDimensionEditor, ScalarDimensionEditor } from 'app/features/dimensions/editors'; + +import { CanvasElementItem, CanvasElementProps } from '../../element'; + +import { ServerDatabase } from './types/database'; +import { ServerSingle } from './types/single'; +import { ServerStack } from './types/stack'; +import { ServerTerminal } from './types/terminal'; + +interface ServerConfig { + blinkRate?: ScalarDimensionConfig; + statusColor?: ColorDimensionConfig; + bulbColor?: ColorDimensionConfig; + type: ServerType; +} + +export interface ServerData { + blinkRate?: number; + statusColor?: string; + bulbColor?: string; + type: ServerType; +} + +enum ServerType { + Single = 'Single', + Stack = 'Stack', + Database = 'Database', + Terminal = 'Terminal', +} + +type Props = CanvasElementProps; + +const ServerDisplay = ({ data }: Props) => { + return data ? ( + + {data.type === ServerType.Single ? ( + + ) : data.type === ServerType.Stack ? ( + + ) : data.type === ServerType.Database ? ( + + ) : data.type === ServerType.Terminal ? ( + + ) : null} + + ) : null; +}; + +export const serverItem: CanvasElementItem = { + id: 'server', + name: 'Server', + description: 'Basic server with status', + + display: ServerDisplay, + + defaultSize: { + width: 100, + height: 100, + }, + + getNewOptions: (options) => ({ + ...options, + background: { + color: { + fixed: 'transparent', + }, + }, + placement: { + width: options?.placement?.width ?? 100, + height: options?.placement?.height ?? 100, + top: options?.placement?.top, + left: options?.placement?.left, + }, + config: { + type: ServerType.Single, + }, + }), + + // Called when data changes + prepareData: (ctx: DimensionContext, cfg: ServerConfig) => { + const data: ServerData = { + blinkRate: cfg?.blinkRate ? ctx.getScalar(cfg.blinkRate).value() : 0, + statusColor: cfg?.statusColor ? ctx.getColor(cfg.statusColor).value() : '#8a8a8a', + bulbColor: cfg?.bulbColor ? ctx.getColor(cfg.bulbColor).value() : 'green', + type: cfg.type, + }; + + return data; + }, + + registerOptionsUI: (builder) => { + const category = ['Server']; + builder + .addSelect({ + category, + path: 'config.type', + name: 'Type', + settings: { + options: [ + { value: ServerType.Single, label: ServerType.Single }, + { value: ServerType.Stack, label: ServerType.Stack }, + { value: ServerType.Database, label: ServerType.Database }, + { value: ServerType.Terminal, label: ServerType.Terminal }, + ], + }, + defaultValue: ServerType.Single, + }) + .addCustomEditor({ + category, + id: 'statusColor', + path: 'config.statusColor', + name: 'Status color', + editor: ColorDimensionEditor, + settings: {}, + defaultValue: { + fixed: '#8a8a8a', + }, + }) + .addCustomEditor({ + category, + id: 'bulbColor', + path: 'config.bulbColor', + name: 'Bulb color', + editor: ColorDimensionEditor, + settings: {}, + defaultValue: { + fixed: 'green', + }, + }) + .addCustomEditor({ + category, + id: 'blinkRate', + path: 'config.blinkRate', + name: 'Blink rate [hz] (0 = off)', + editor: ScalarDimensionEditor, + settings: { min: 0, max: 100 }, + }); + }, +}; + +export const getServerStyles = (data: ServerData | undefined) => (theme: GrafanaTheme2) => ({ + bulb: css` + @keyframes blink { + 0% { + fill-opacity: 0; + } + 50% { + fill-opacity: 1; + } + 100% { + fill-opacity: 0; + } + } + `, + server: css` + fill: #dadada; + stroke-linecap: round; + stroke-miterlimit: 10; + stroke-width: 10; + stroke: ${data?.statusColor ?? '#8a8a8a'}; + `, + circle: css` + animation: blink ${data?.blinkRate ? 1 / data.blinkRate : 0}s infinite step-end; + fill: ${data?.bulbColor}; + stroke-linecap: round; + stroke-miterlimit: 10; + stroke-width: 3; + stroke: #000; + `, + outline: css` + fill: none; + stroke-linecap: round; + stroke-miterlimit: 10; + stroke-width: 10; + stroke: #303030; + `, + pathA: css` + display: none; + fill: #fff; + `, + pathB: css` + fill: #fff; + `, + thinLine: css` + stroke-width: 0.7; + `, + monitor: css` + stroke: ${data?.statusColor ?? '#8a8a8a'}; + fill: #fff; + stroke-linecap: square; + stroke-miterlimit: 0; + stroke-width: 14; + `, + monitorOutline: css` + stroke: #8a8a8a; + stroke-linecap: square; + stroke-miterlimit: 0; + `, + keyboard: css` + fill: #dadada; + stroke-linecap: round; + stroke-miterlimit: 10; + stroke-width: 10; + stroke: ${data?.statusColor ?? '#8a8a8a'}; + `, +}); diff --git a/public/app/features/canvas/elements/server/types/database.tsx b/public/app/features/canvas/elements/server/types/database.tsx new file mode 100644 index 00000000000..b4fb6afe0ba --- /dev/null +++ b/public/app/features/canvas/elements/server/types/database.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +import { useStyles2 } from '@grafana/ui'; + +import { getServerStyles, ServerData } from '../server'; + +export const ServerDatabase = (data: ServerData) => { + const styles = useStyles2(getServerStyles(data)); + return ( + + + + + + + + + + + + + + ); +}; diff --git a/public/app/features/canvas/elements/server/types/single.tsx b/public/app/features/canvas/elements/server/types/single.tsx new file mode 100644 index 00000000000..57e7c53b28b --- /dev/null +++ b/public/app/features/canvas/elements/server/types/single.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +import { useStyles2 } from '@grafana/ui'; + +import { getServerStyles, ServerData } from '../server'; + +export const ServerSingle = (data: ServerData) => { + const styles = useStyles2(getServerStyles(data)); + return ( + + + + + + + + + + + + + + + ); +}; diff --git a/public/app/features/canvas/elements/server/types/stack.tsx b/public/app/features/canvas/elements/server/types/stack.tsx new file mode 100644 index 00000000000..01e8c35e569 --- /dev/null +++ b/public/app/features/canvas/elements/server/types/stack.tsx @@ -0,0 +1,52 @@ +import React from 'react'; + +import { useStyles2 } from '@grafana/ui'; + +import { getServerStyles, ServerData } from '../server'; + +export const ServerStack = (data: ServerData) => { + const styles = useStyles2(getServerStyles(data)); + return ( + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/public/app/features/canvas/elements/server/types/terminal.tsx b/public/app/features/canvas/elements/server/types/terminal.tsx new file mode 100644 index 00000000000..b29af7baf99 --- /dev/null +++ b/public/app/features/canvas/elements/server/types/terminal.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +import { useStyles2 } from '@grafana/ui'; + +import { getServerStyles, ServerData } from '../server'; + +export const ServerTerminal = (data: ServerData) => { + const styles = useStyles2(getServerStyles(data)); + return ( + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/public/app/features/canvas/registry.ts b/public/app/features/canvas/registry.ts index e6abfd9ba74..fad1ebaa292 100644 --- a/public/app/features/canvas/registry.ts +++ b/public/app/features/canvas/registry.ts @@ -8,6 +8,7 @@ import { droneTopItem } from './elements/droneTop'; import { iconItem } from './elements/icon'; import { metricValueItem } from './elements/metricValue'; import { rectangleItem } from './elements/rectangle'; +import { serverItem } from './elements/server/server'; import { textItem } from './elements/text'; import { windTurbineItem } from './elements/windTurbine'; @@ -23,6 +24,7 @@ export const defaultElementItems = [ textItem, rectangleItem, iconItem, + serverItem, ]; export const advancedElementItems = [buttonItem, windTurbineItem, droneTopItem, droneFrontItem, droneSideItem];