From d5945bc26ebbeea07772b69742eda0e5697fda54 Mon Sep 17 00:00:00 2001 From: Adela Almasan <88068998+adela-almasan@users.noreply.github.com> Date: Fri, 13 Oct 2023 00:11:08 -0500 Subject: [PATCH] Canvas: Button API Editor visual feedback on response (#76499) --- public/app/features/canvas/element.ts | 2 +- .../app/features/canvas/elements/button.tsx | 58 ++++++++++++------- .../panel/canvas/editor/element/APIEditor.tsx | 50 ++++++++-------- .../panel/canvas/editor/element/utils.ts | 16 ++--- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/public/app/features/canvas/element.ts b/public/app/features/canvas/element.ts index b7b0bf069dd..0e51e4a8815 100644 --- a/public/app/features/canvas/element.ts +++ b/public/app/features/canvas/element.ts @@ -92,4 +92,4 @@ export interface CanvasElementItem extends RegistryI export const defaultBgColor = '#D9D9D9'; export const defaultTextColor = '#000000'; export const defaultLightTextColor = '#F0F4FD'; -export const defaultThemeTextColor = config.theme2.colors.background.primary; +export const defaultThemeTextColor = config.theme2.colors.text.primary; diff --git a/public/app/features/canvas/elements/button.tsx b/public/app/features/canvas/elements/button.tsx index e0f3f46f3bf..15224bda7b7 100644 --- a/public/app/features/canvas/elements/button.tsx +++ b/public/app/features/canvas/elements/button.tsx @@ -1,11 +1,10 @@ import { css } from '@emotion/css'; -import React, { PureComponent } from 'react'; +import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { PluginState } from '@grafana/data/src'; import { TextDimensionMode } from '@grafana/schema'; -import { Button, stylesFactory } from '@grafana/ui'; -import { config } from 'app/core/config'; +import { Button, Spinner, useStyles2 } from '@grafana/ui'; import { DimensionContext } from 'app/features/dimensions/context'; import { ColorDimensionEditor } from 'app/features/dimensions/editors'; import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensionEditor'; @@ -40,26 +39,39 @@ export const defaultStyleConfig: ButtonStyleConfig = { variant: 'primary', }; -class ButtonDisplay extends PureComponent> { - render() { - const { data } = this.props; - const styles = getStyles(config.theme2, data); +const ButtonDisplay = ({ data }: CanvasElementProps) => { + const styles = useStyles2(getStyles, data); - const onClick = () => { - if (data?.api && data?.api?.endpoint) { - callApi(data.api); - } - }; + const [isLoading, setIsLoading] = React.useState(false); - return ( - - ); - } -} + + + ); +}; -const getStyles = stylesFactory((theme: GrafanaTheme2, data: ButtonData | undefined) => ({ +const getStyles = (theme: GrafanaTheme2, data: ButtonData | undefined) => ({ button: css({ height: '100%', width: '100%', @@ -67,12 +79,16 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, data: ButtonData | undefi '> span': { display: 'inline-grid', + gridAutoFlow: 'column', textAlign: data?.align, fontSize: `${data?.size}px`, color: data?.color, }, }), -})); + buttonSpinner: css({ + marginRight: theme.spacing(0.5), + }), +}); export const buttonItem: CanvasElementItem = { id: 'button', @@ -137,7 +153,7 @@ export const buttonItem: CanvasElementItem = { const data: ButtonData = { text: cfg?.text ? ctx.getText(cfg.text).value() : '', align: cfg.align ?? Align.Center, - size: cfg.size, + size: cfg.size ?? 14, api: getCfgApi(), style: cfg?.style ?? defaultStyleConfig, }; diff --git a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx index 9a4e9445a2e..711caffd200 100644 --- a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx +++ b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx @@ -132,7 +132,7 @@ export function APIEditor({ value, context, onChange }: Props) { const renderTestAPIButton = (api: APIEditorConfig) => { if (api && api.endpoint) { return ( - ); @@ -158,36 +158,36 @@ export function APIEditor({ value, context, onChange }: Props) { + {value?.method === HttpRequestMethod.POST && ( + + + - - - {value?.contentType && ( - - - - )} - + {value?.method === HttpRequestMethod.POST && value?.contentType && ( + + + )} {renderTestAPIButton(value)}
diff --git a/public/app/plugins/panel/canvas/editor/element/utils.ts b/public/app/plugins/panel/canvas/editor/element/utils.ts index 46201539f15..8b34aee5836 100644 --- a/public/app/plugins/panel/canvas/editor/element/utils.ts +++ b/public/app/plugins/panel/canvas/editor/element/utils.ts @@ -7,11 +7,14 @@ import { HttpRequestMethod } from '../../panelcfg.gen'; import { APIEditorConfig } from './APIEditor'; -export const callApi = (api: APIEditorConfig, isTest = false) => { +type IsLoadingCallback = (loading: boolean) => void; + +export const callApi = (api: APIEditorConfig, updateLoadingStateCallback?: IsLoadingCallback) => { if (api && api.endpoint) { // If API endpoint origin matches Grafana origin, don't call it. if (requestMatchesGrafanaOrigin(api.endpoint)) { appEvents.emit(AppEvents.alertError, ['Cannot call API at Grafana origin.']); + updateLoadingStateCallback && updateLoadingStateCallback(false); return; } const request = getRequest(api); @@ -20,15 +23,12 @@ export const callApi = (api: APIEditorConfig, isTest = false) => { .fetch(request) .subscribe({ error: (error) => { - if (isTest) { - appEvents.emit(AppEvents.alertError, ['Error has occurred: ', JSON.stringify(error)]); - console.error(error); - } + appEvents.emit(AppEvents.alertError, ['An error has occurred: ', JSON.stringify(error)]); + updateLoadingStateCallback && updateLoadingStateCallback(false); }, complete: () => { - if (isTest) { - appEvents.emit(AppEvents.alertSuccess, ['Test successful']); - } + appEvents.emit(AppEvents.alertSuccess, ['API call was successful']); + updateLoadingStateCallback && updateLoadingStateCallback(false); }, }); }