From 89127d5ec973904498c8c7a580f2072ddfc69828 Mon Sep 17 00:00:00 2001 From: Adela Almasan <88068998+adela-almasan@users.noreply.github.com> Date: Mon, 11 Sep 2023 08:03:52 -0500 Subject: [PATCH] Canvas: Button API - Add support for GET requests (#74566) --- .../canvas/panelcfg/schema-reference.md | 1 + .../panelcfg/x/CanvasPanelCfg_types.gen.ts | 5 ++ .../app/features/canvas/elements/button.tsx | 35 +++++++-- .../panel/canvas/editor/element/APIEditor.tsx | 75 ++++++++++++++----- public/app/plugins/panel/canvas/panelcfg.cue | 2 + .../app/plugins/panel/canvas/panelcfg.gen.ts | 5 ++ 6 files changed, 98 insertions(+), 25 deletions(-) diff --git a/docs/sources/developers/kinds/composable/canvas/panelcfg/schema-reference.md b/docs/sources/developers/kinds/composable/canvas/panelcfg/schema-reference.md index 2d43f330135..7b97a1ab5fc 100644 --- a/docs/sources/developers/kinds/composable/canvas/panelcfg/schema-reference.md +++ b/docs/sources/developers/kinds/composable/canvas/panelcfg/schema-reference.md @@ -28,6 +28,7 @@ title: CanvasPanelCfg kind | `ConnectionPath` | string | **Yes** | | Possible values are: `straight`. | | `Constraint` | [object](#constraint) | **Yes** | | | | `HorizontalConstraint` | string | **Yes** | | Possible values are: `left`, `right`, `leftright`, `center`, `scale`. | +| `HttpRequestMethod` | string | **Yes** | | Possible values are: `GET`, `POST`. | | `LineConfig` | [object](#lineconfig) | **Yes** | | | | `Options` | [object](#options) | **Yes** | | | | `Placement` | [object](#placement) | **Yes** | | | diff --git a/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts index 1305709fbae..2f69328fb08 100644 --- a/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts @@ -62,6 +62,11 @@ export interface LineConfig { width?: number; } +export enum HttpRequestMethod { + GET = 'GET', + POST = 'POST', +} + export interface ConnectionCoordinates { x: number; y: number; diff --git a/public/app/features/canvas/elements/button.tsx b/public/app/features/canvas/elements/button.tsx index a4d054b6f16..3dc035658f5 100644 --- a/public/app/features/canvas/elements/button.tsx +++ b/public/app/features/canvas/elements/button.tsx @@ -1,11 +1,12 @@ import React, { PureComponent } from 'react'; import { PluginState } from '@grafana/data/src'; -import { TextDimensionConfig } from '@grafana/schema'; +import { TextDimensionConfig, TextDimensionMode } from '@grafana/schema'; import { Button } from '@grafana/ui'; import { DimensionContext } from 'app/features/dimensions/context'; import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensionEditor'; import { APIEditor, APIEditorConfig, callApi } from 'app/plugins/panel/canvas/editor/element/APIEditor'; +import { HttpRequestMethod } from 'app/plugins/panel/canvas/panelcfg.gen'; import { CanvasElementItem, CanvasElementProps, defaultBgColor } from '../element'; @@ -19,6 +20,12 @@ interface ButtonConfig { api?: APIEditorConfig; } +export const defaultApiConfig: APIEditorConfig = { + endpoint: '', + method: HttpRequestMethod.POST, + data: '{}', +}; + class ButtonDisplay extends PureComponent> { render() { const { data } = this.props; @@ -45,30 +52,44 @@ export const buttonItem: CanvasElementItem = { display: ButtonDisplay, defaultSize: { - width: 32, + width: 78, height: 32, }, getNewOptions: (options) => ({ ...options, + config: { + text: { + mode: TextDimensionMode.Fixed, + fixed: 'Button', + }, + api: defaultApiConfig, + }, background: { color: { fixed: 'transparent', }, }, placement: { - width: 32, - height: 32, - top: 0, - left: 0, + top: 100, + left: 100, }, }), // Called when data changes prepareData: (ctx: DimensionContext, cfg: ButtonConfig) => { + const getCfgApi = () => { + if (cfg?.api) { + cfg.api = { ...cfg.api, method: cfg.api.method ?? HttpRequestMethod.POST }; + return cfg.api; + } + + return undefined; + }; + const data: ButtonData = { text: cfg?.text ? ctx.getText(cfg.text).value() : '', - api: cfg?.api ?? undefined, + api: getCfgApi(), }; return data; diff --git a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx index 2118657ff04..1c5ba0475ca 100644 --- a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx +++ b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx @@ -2,11 +2,15 @@ import React, { useCallback } from 'react'; import { AppEvents, StandardEditorProps, StandardEditorsRegistryItem, StringFieldConfigSettings } from '@grafana/data'; import { config, getBackendSrv } from '@grafana/runtime'; -import { Button, InlineField, InlineFieldRow, JSONFormatter } from '@grafana/ui'; +import { Button, InlineField, InlineFieldRow, JSONFormatter, RadioButtonGroup } from '@grafana/ui'; import { StringValueEditor } from 'app/core/components/OptionsUI/string'; import { appEvents } from 'app/core/core'; +import { defaultApiConfig } from 'app/features/canvas/elements/button'; + +import { HttpRequestMethod } from '../../panelcfg.gen'; export interface APIEditorConfig { + method: string; endpoint: string; data?: string; } @@ -16,12 +20,12 @@ const dummyStringSettings = { } as StandardEditorsRegistryItem; export const callApi = (api: APIEditorConfig, isTest = false) => { - if (api) { + if (api && api.endpoint) { getBackendSrv() .fetch({ - url: api.endpoint!, - method: 'POST', - data: api.data ?? {}, + url: api.endpoint, + method: api.method, + data: getData(api), }) .subscribe({ error: (error) => { @@ -39,10 +43,28 @@ export const callApi = (api: APIEditorConfig, isTest = false) => { } }; +const getData = (api: APIEditorConfig) => { + let data: string | undefined = api.data ?? '{}'; + if (api.method === HttpRequestMethod.GET) { + data = undefined; + } + + return data; +}; + type Props = StandardEditorProps; +const httpMethodOptions = [ + { label: HttpRequestMethod.GET, value: HttpRequestMethod.GET }, + { label: HttpRequestMethod.POST, value: HttpRequestMethod.POST }, +]; + export function APIEditor({ value, context, onChange }: Props) { - const labelWidth = 9; + const LABEL_WIDTH = 9; + + if (!value) { + value = defaultApiConfig; + } const onEndpointChange = useCallback( (endpoint = '') => { @@ -64,6 +86,16 @@ export function APIEditor({ value, context, onChange }: Props) { [onChange, value] ); + const onMethodChange = useCallback( + (method: string) => { + onChange({ + ...value, + method, + }); + }, + [onChange, value] + ); + const renderJSON = (data: string) => { try { const json = JSON.parse(data); @@ -92,7 +124,12 @@ export function APIEditor({ value, context, onChange }: Props) { return config.disableSanitizeHtml ? ( <> - + + + + + + - - - - - + {value?.method === HttpRequestMethod.POST && ( + + + + + + )} {renderTestAPIButton(value)}
- {renderJSON(value?.data ?? '{}')} + {value?.method === HttpRequestMethod.POST && renderJSON(value?.data ?? '{}')} ) : ( <>Must enable disableSanitizeHtml feature flag to access diff --git a/public/app/plugins/panel/canvas/panelcfg.cue b/public/app/plugins/panel/canvas/panelcfg.cue index e3ac65f3ac5..ed72529378b 100644 --- a/public/app/plugins/panel/canvas/panelcfg.cue +++ b/public/app/plugins/panel/canvas/panelcfg.cue @@ -56,6 +56,8 @@ composableKinds: PanelCfg: { width?: float64 } @cuetsy(kind="interface") + HttpRequestMethod: "GET" | "POST" @cuetsy(kind="enum", memberNames="GET|POST") + ConnectionCoordinates: { x: float64 y: float64 diff --git a/public/app/plugins/panel/canvas/panelcfg.gen.ts b/public/app/plugins/panel/canvas/panelcfg.gen.ts index 69ba86ea266..b1412db2e58 100644 --- a/public/app/plugins/panel/canvas/panelcfg.gen.ts +++ b/public/app/plugins/panel/canvas/panelcfg.gen.ts @@ -59,6 +59,11 @@ export interface LineConfig { width?: number; } +export enum HttpRequestMethod { + GET = 'GET', + POST = 'POST', +} + export interface ConnectionCoordinates { x: number; y: number;