mirror of
https://github.com/grafana/grafana.git
synced 2025-09-22 14:33:50 +08:00
Chore: Update Action interface (#93248)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
@ -3,10 +3,18 @@ import { DataFrame, Field, ValueLinkConfig } from './dataFrame';
|
|||||||
import { InterpolateFunction } from './panel';
|
import { InterpolateFunction } from './panel';
|
||||||
import { SelectableValue } from './select';
|
import { SelectableValue } from './select';
|
||||||
|
|
||||||
export interface Action<T = ActionType.Fetch, TOptions = FetchOptions> {
|
export enum ActionType {
|
||||||
type: T;
|
Fetch = 'fetch',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Action {
|
||||||
|
type: ActionType;
|
||||||
title: string;
|
title: string;
|
||||||
options: TOptions;
|
|
||||||
|
// Options for the selected type
|
||||||
|
// Currently this is required because there is only one valid type (fetch)
|
||||||
|
// once multiple types are valid, usage of this will need to be optional
|
||||||
|
[ActionType.Fetch]: FetchOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,10 +33,6 @@ interface FetchOptions {
|
|||||||
headers?: Array<[string, string]>;
|
headers?: Array<[string, string]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ActionType {
|
|
||||||
Fetch = 'fetch',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum HttpRequestMethod {
|
export enum HttpRequestMethod {
|
||||||
POST = 'POST',
|
POST = 'POST',
|
||||||
PUT = 'PUT',
|
PUT = 'PUT',
|
||||||
@ -51,7 +55,7 @@ export const contentTypeOptions: SelectableValue[] = [
|
|||||||
export const defaultActionConfig: Action = {
|
export const defaultActionConfig: Action = {
|
||||||
type: ActionType.Fetch,
|
type: ActionType.Fetch,
|
||||||
title: '',
|
title: '',
|
||||||
options: {
|
fetch: {
|
||||||
url: '',
|
url: '',
|
||||||
method: HttpRequestMethod.POST,
|
method: HttpRequestMethod.POST,
|
||||||
body: '{}',
|
body: '{}',
|
||||||
|
@ -32,8 +32,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
const onUrlChange = (url: string) => {
|
const onUrlChange = (url: string) => {
|
||||||
onChange(index, {
|
onChange(index, {
|
||||||
...value,
|
...value,
|
||||||
options: {
|
fetch: {
|
||||||
...value.options,
|
...value.fetch,
|
||||||
url,
|
url,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -42,8 +42,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
const onBodyChange = (body: string) => {
|
const onBodyChange = (body: string) => {
|
||||||
onChange(index, {
|
onChange(index, {
|
||||||
...value,
|
...value,
|
||||||
options: {
|
fetch: {
|
||||||
...value.options,
|
...value.fetch,
|
||||||
body,
|
body,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -52,8 +52,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
const onMethodChange = (method: HttpRequestMethod) => {
|
const onMethodChange = (method: HttpRequestMethod) => {
|
||||||
onChange(index, {
|
onChange(index, {
|
||||||
...value,
|
...value,
|
||||||
options: {
|
fetch: {
|
||||||
...value.options,
|
...value.fetch,
|
||||||
method,
|
method,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -62,8 +62,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
const onQueryParamsChange = (queryParams: Array<[string, string]>) => {
|
const onQueryParamsChange = (queryParams: Array<[string, string]>) => {
|
||||||
onChange(index, {
|
onChange(index, {
|
||||||
...value,
|
...value,
|
||||||
options: {
|
fetch: {
|
||||||
...value.options,
|
...value.fetch,
|
||||||
queryParams,
|
queryParams,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -72,8 +72,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
const onHeadersChange = (headers: Array<[string, string]>) => {
|
const onHeadersChange = (headers: Array<[string, string]>) => {
|
||||||
onChange(index, {
|
onChange(index, {
|
||||||
...value,
|
...value,
|
||||||
options: {
|
fetch: {
|
||||||
...value.options,
|
...value.fetch,
|
||||||
headers,
|
headers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -93,8 +93,8 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
};
|
};
|
||||||
|
|
||||||
const shouldRenderJSON =
|
const shouldRenderJSON =
|
||||||
value.options.method !== HttpRequestMethod.GET &&
|
value.fetch.method !== HttpRequestMethod.GET &&
|
||||||
value.options.headers?.some(([name, value]) => name === 'Content-Type' && value === 'application/json');
|
value.fetch.headers?.some(([name, value]) => name === 'Content-Type' && value === 'application/json');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.listItem}>
|
<div className={styles.listItem}>
|
||||||
@ -111,7 +111,7 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
<InlineFieldRow>
|
<InlineFieldRow>
|
||||||
<InlineField label="Method" labelWidth={LABEL_WIDTH} grow={true}>
|
<InlineField label="Method" labelWidth={LABEL_WIDTH} grow={true}>
|
||||||
<RadioButtonGroup<HttpRequestMethod>
|
<RadioButtonGroup<HttpRequestMethod>
|
||||||
value={value?.options.method}
|
value={value?.fetch.method}
|
||||||
options={httpMethodOptions}
|
options={httpMethodOptions}
|
||||||
onChange={onMethodChange}
|
onChange={onMethodChange}
|
||||||
fullWidth
|
fullWidth
|
||||||
@ -122,7 +122,7 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
<InlineFieldRow>
|
<InlineFieldRow>
|
||||||
<InlineField label="URL" labelWidth={LABEL_WIDTH} grow={true}>
|
<InlineField label="URL" labelWidth={LABEL_WIDTH} grow={true}>
|
||||||
<SuggestionsInput
|
<SuggestionsInput
|
||||||
value={value.options.url}
|
value={value.fetch.url}
|
||||||
onChange={onUrlChange}
|
onChange={onUrlChange}
|
||||||
suggestions={suggestions}
|
suggestions={suggestions}
|
||||||
placeholder="URL"
|
placeholder="URL"
|
||||||
@ -131,26 +131,22 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
</InlineFieldRow>
|
</InlineFieldRow>
|
||||||
|
|
||||||
<Field label="Query parameters" className={styles.fieldGap}>
|
<Field label="Query parameters" className={styles.fieldGap}>
|
||||||
<ParamsEditor
|
<ParamsEditor value={value?.fetch.queryParams ?? []} onChange={onQueryParamsChange} suggestions={suggestions} />
|
||||||
value={value?.options.queryParams ?? []}
|
|
||||||
onChange={onQueryParamsChange}
|
|
||||||
suggestions={suggestions}
|
|
||||||
/>
|
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field label="Headers">
|
<Field label="Headers">
|
||||||
<ParamsEditor
|
<ParamsEditor
|
||||||
value={value?.options.headers ?? []}
|
value={value?.fetch.headers ?? []}
|
||||||
onChange={onHeadersChange}
|
onChange={onHeadersChange}
|
||||||
suggestions={suggestions}
|
suggestions={suggestions}
|
||||||
contentTypeHeader={true}
|
contentTypeHeader={true}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
{value?.options.method !== HttpRequestMethod.GET && (
|
{value?.fetch.method !== HttpRequestMethod.GET && (
|
||||||
<Field label="Body">
|
<Field label="Body">
|
||||||
<SuggestionsInput
|
<SuggestionsInput
|
||||||
value={value.options.body}
|
value={value.fetch.body}
|
||||||
onChange={onBodyChange}
|
onChange={onBodyChange}
|
||||||
suggestions={suggestions}
|
suggestions={suggestions}
|
||||||
type={HTMLElementType.TextAreaElement}
|
type={HTMLElementType.TextAreaElement}
|
||||||
@ -161,7 +157,7 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions }: Actio
|
|||||||
{shouldRenderJSON && (
|
{shouldRenderJSON && (
|
||||||
<>
|
<>
|
||||||
<br />
|
<br />
|
||||||
{renderJSON(value?.options.body)}
|
{renderJSON(value?.fetch.body)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,7 +42,7 @@ export const ActionEditorModalContent = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onSave(index, dirtyAction);
|
onSave(index, dirtyAction);
|
||||||
}}
|
}}
|
||||||
disabled={dirtyAction.title.trim() === '' || dirtyAction.options.url.trim() === ''}
|
disabled={dirtyAction.title.trim() === '' || dirtyAction.fetch.url.trim() === ''}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -68,25 +68,25 @@ export const getActions = (
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
const buildActionOnClick = (action: Action, replaceVariables: InterpolateFunction) => {
|
const buildActionOnClick = (action: Action, replaceVariables: InterpolateFunction) => {
|
||||||
try {
|
try {
|
||||||
const url = new URL(getUrl(replaceVariables(action.options.url)));
|
const url = new URL(getUrl(replaceVariables(action.fetch.url)));
|
||||||
|
|
||||||
const requestHeaders: Record<string, string> = {};
|
const requestHeaders: Record<string, string> = {};
|
||||||
|
|
||||||
let request: BackendSrvRequest = {
|
let request: BackendSrvRequest = {
|
||||||
url: url.toString(),
|
url: url.toString(),
|
||||||
method: action.options.method,
|
method: action.fetch.method,
|
||||||
data: getData(action, replaceVariables),
|
data: getData(action, replaceVariables),
|
||||||
headers: requestHeaders,
|
headers: requestHeaders,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (action.options.headers) {
|
if (action.fetch.headers) {
|
||||||
action.options.headers.forEach(([name, value]) => {
|
action.fetch.headers.forEach(([name, value]) => {
|
||||||
requestHeaders[replaceVariables(name)] = replaceVariables(value);
|
requestHeaders[replaceVariables(name)] = replaceVariables(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.options.queryParams) {
|
if (action.fetch.queryParams) {
|
||||||
action.options.queryParams?.forEach(([name, value]) => {
|
action.fetch.queryParams?.forEach(([name, value]) => {
|
||||||
url.searchParams.append(replaceVariables(name), replaceVariables(value));
|
url.searchParams.append(replaceVariables(name), replaceVariables(value));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ const getUrl = (endpoint: string) => {
|
|||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
const getData = (action: Action, replaceVariables: InterpolateFunction) => {
|
const getData = (action: Action, replaceVariables: InterpolateFunction) => {
|
||||||
let data: string | undefined = action.options.body ? replaceVariables(action.options.body) : '{}';
|
let data: string | undefined = action.fetch.body ? replaceVariables(action.fetch.body) : '{}';
|
||||||
if (action.options.method === HttpRequestMethod.GET) {
|
if (action.fetch.method === HttpRequestMethod.GET) {
|
||||||
data = undefined;
|
data = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,14 +68,24 @@ export const canvasMigrationHandler = (panel: PanelModel): Partial<Options> => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrate oneClickLinks to oneClickMode
|
|
||||||
const root = panel.options?.root;
|
const root = panel.options?.root;
|
||||||
if (root?.elements) {
|
if (root?.elements) {
|
||||||
for (const element of root.elements) {
|
for (const element of root.elements) {
|
||||||
|
// migrate oneClickLinks to oneClickMode
|
||||||
if (element.oneClickLinks) {
|
if (element.oneClickLinks) {
|
||||||
element.oneClickMode = OneClickMode.Link;
|
element.oneClickMode = OneClickMode.Link;
|
||||||
delete element.oneClickLinks;
|
delete element.oneClickLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// migrate action options to new format (fetch)
|
||||||
|
if (element.actions) {
|
||||||
|
for (const action of element.actions) {
|
||||||
|
if (action.options) {
|
||||||
|
action.fetch = { ...action.options };
|
||||||
|
delete action.options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user