diff --git a/public/app/features/canvas/elements/button.tsx b/public/app/features/canvas/elements/button.tsx index 3dc035658f5..ac17cef926c 100644 --- a/public/app/features/canvas/elements/button.tsx +++ b/public/app/features/canvas/elements/button.tsx @@ -24,6 +24,7 @@ export const defaultApiConfig: APIEditorConfig = { endpoint: '', method: HttpRequestMethod.POST, data: '{}', + contentType: 'application/json', }; class ButtonDisplay extends PureComponent> { @@ -80,7 +81,11 @@ export const buttonItem: CanvasElementItem = { prepareData: (ctx: DimensionContext, cfg: ButtonConfig) => { const getCfgApi = () => { if (cfg?.api) { - cfg.api = { ...cfg.api, method: cfg.api.method ?? HttpRequestMethod.POST }; + cfg.api = { + ...cfg.api, + method: cfg.api.method ?? defaultApiConfig.method, + contentType: cfg.api.contentType ?? defaultApiConfig.contentType, + }; return cfg.api; } diff --git a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx index 1c5ba0475ca..299b6a5ce05 100644 --- a/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx +++ b/public/app/plugins/panel/canvas/editor/element/APIEditor.tsx @@ -1,8 +1,14 @@ import React, { useCallback } from 'react'; -import { AppEvents, StandardEditorProps, StandardEditorsRegistryItem, StringFieldConfigSettings } from '@grafana/data'; -import { config, getBackendSrv } from '@grafana/runtime'; -import { Button, InlineField, InlineFieldRow, JSONFormatter, RadioButtonGroup } from '@grafana/ui'; +import { + AppEvents, + SelectableValue, + StandardEditorProps, + StandardEditorsRegistryItem, + StringFieldConfigSettings, +} from '@grafana/data'; +import { BackendSrvRequest, config, getBackendSrv } from '@grafana/runtime'; +import { Button, Field, InlineField, InlineFieldRow, JSONFormatter, RadioButtonGroup, Select } 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'; @@ -13,20 +19,36 @@ export interface APIEditorConfig { method: string; endpoint: string; data?: string; + contentType?: string; } const dummyStringSettings = { settings: {}, } as StandardEditorsRegistryItem; +const getRequest = (api: APIEditorConfig) => { + const requestHeaders: HeadersInit = []; + + let request: BackendSrvRequest = { + url: api.endpoint, + method: api.method, + data: getData(api), + headers: requestHeaders, + }; + + if (api.method === HttpRequestMethod.POST) { + requestHeaders.push(['Content-Type', api.contentType!]); + } + + request.headers = requestHeaders; + + return request; +}; + export const callApi = (api: APIEditorConfig, isTest = false) => { if (api && api.endpoint) { getBackendSrv() - .fetch({ - url: api.endpoint, - method: api.method, - data: getData(api), - }) + .fetch(getRequest(api)) .subscribe({ error: (error) => { if (isTest) { @@ -59,6 +81,15 @@ const httpMethodOptions = [ { label: HttpRequestMethod.POST, value: HttpRequestMethod.POST }, ]; +const contentTypeOptions: SelectableValue[] = [ + { label: 'JSON', value: 'application/json' }, + { label: 'Text', value: 'text/plain' }, + { label: 'JavaScript', value: 'application/javascript' }, + { label: 'HTML', value: 'text/html' }, + { label: 'XML', value: 'application/XML' }, + { label: 'x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }, +]; + export function APIEditor({ value, context, onChange }: Props) { const LABEL_WIDTH = 9; @@ -96,6 +127,20 @@ export function APIEditor({ value, context, onChange }: Props) { [onChange, value] ); + const onContentTypeChange = useCallback( + (contentType: SelectableValue) => { + onChange({ + ...value, + contentType: contentType?.value, + }); + }, + [onChange, value] + ); + + const formatCreateLabel = (input: string) => { + return input; + }; + const renderJSON = (data: string) => { try { const json = JSON.parse(data); @@ -124,12 +169,7 @@ export function APIEditor({ value, context, onChange }: Props) { return config.disableSanitizeHtml ? ( <> - - - - - - + + + + + + {value?.method === HttpRequestMethod.POST && ( - - - + +