Actions: Add button style customization (#104126)
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import { ScopedVars } from './ScopedVars';
|
||||
import { DataFrame, Field, ValueLinkConfig } from './dataFrame';
|
||||
import { InterpolateFunction } from './panel';
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
import { SelectableValue } from './select';
|
||||
|
||||
export enum ActionType {
|
||||
Fetch = 'fetch',
|
||||
}
|
||||
|
||||
type ActionButtonCssProperties = Pick<CSSProperties, 'backgroundColor'>;
|
||||
|
||||
export interface Action {
|
||||
type: ActionType;
|
||||
title: string;
|
||||
@@ -17,6 +18,7 @@ export interface Action {
|
||||
[ActionType.Fetch]: FetchOptions;
|
||||
confirmation?: string;
|
||||
oneClick?: boolean;
|
||||
style?: ActionButtonCssProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,6 +29,7 @@ export interface ActionModel<T = any> {
|
||||
onClick: (event: any, origin?: any) => void;
|
||||
confirmation?: string;
|
||||
oneClick?: boolean;
|
||||
style: ActionButtonCssProperties;
|
||||
}
|
||||
|
||||
interface FetchOptions {
|
||||
@@ -67,12 +70,3 @@ export const defaultActionConfig: Action = {
|
||||
headers: [['Content-Type', 'application/json']],
|
||||
},
|
||||
};
|
||||
|
||||
export type ActionsArgs = {
|
||||
frame: DataFrame;
|
||||
field: Field;
|
||||
fieldScopedVars: ScopedVars;
|
||||
replaceVariables: InterpolateFunction;
|
||||
actions: Action[];
|
||||
config: ValueLinkConfig;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState } from 'react';
|
||||
|
||||
import { ActionModel, Field } from '@grafana/data';
|
||||
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { t } from '../../utils/i18n';
|
||||
import { Button, ButtonProps } from '../Button';
|
||||
import { ConfirmModal } from '../ConfirmModal/ConfirmModal';
|
||||
@@ -14,6 +15,10 @@ type ActionButtonProps = ButtonProps & {
|
||||
* @internal
|
||||
*/
|
||||
export function ActionButton({ action, ...buttonProps }: ActionButtonProps) {
|
||||
const theme = useTheme2();
|
||||
const backgroundColor = action.style.backgroundColor || theme.colors.secondary.main;
|
||||
const textColor = theme.colors.getContrastText(backgroundColor);
|
||||
|
||||
const [showConfirm, setShowConfirm] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -23,7 +28,7 @@ export function ActionButton({ action, ...buttonProps }: ActionButtonProps) {
|
||||
size="sm"
|
||||
onClick={() => setShowConfirm(true)}
|
||||
{...buttonProps}
|
||||
style={{ width: 'fit-content' }}
|
||||
style={{ width: 'fit-content', backgroundColor, color: textColor }}
|
||||
>
|
||||
{action.title}
|
||||
</Button>
|
||||
|
||||
@@ -73,7 +73,7 @@ const renderDataLinks = makeRenderLinksOrActions<LinkModel>(
|
||||
|
||||
const renderActions = makeRenderLinksOrActions<ActionModel>(
|
||||
(title) => <Trans i18nKey="grafana-ui.viz-tooltip.footer-click-to-action">Click to {{ actionTitle: title }}</Trans>,
|
||||
(item, i, styles) => <ActionButton key={i} action={item} variant="secondary" />
|
||||
(item, i) => <ActionButton key={i} action={item} variant="secondary" />
|
||||
);
|
||||
|
||||
export const VizTooltipFooter = ({ dataLinks, actions = [], annotate }: VizTooltipFooterProps) => {
|
||||
|
||||
@@ -2,7 +2,17 @@ import { css } from '@emotion/css';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { Action, GrafanaTheme2, httpMethodOptions, HttpRequestMethod, VariableSuggestion } from '@grafana/data';
|
||||
import { Switch, Field, InlineField, InlineFieldRow, RadioButtonGroup, JSONFormatter, useStyles2 } from '@grafana/ui';
|
||||
import {
|
||||
Switch,
|
||||
Field,
|
||||
InlineField,
|
||||
InlineFieldRow,
|
||||
RadioButtonGroup,
|
||||
JSONFormatter,
|
||||
useStyles2,
|
||||
ColorPicker,
|
||||
useTheme2,
|
||||
} from '@grafana/ui';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
import { HTMLElementType, SuggestionsInput } from '../transformers/suggestionsInput/SuggestionsInput';
|
||||
@@ -21,6 +31,7 @@ const LABEL_WIDTH = 13;
|
||||
|
||||
export const ActionEditor = memo(({ index, value, onChange, suggestions, showOneClick }: ActionEditorProps) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const theme = useTheme2();
|
||||
|
||||
const onTitleChange = (title: string) => {
|
||||
onChange(index, { ...value, title });
|
||||
@@ -84,6 +95,16 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions, showOne
|
||||
});
|
||||
};
|
||||
|
||||
const onBackgroundColorChange = (backgroundColor: string) => {
|
||||
onChange(index, {
|
||||
...value,
|
||||
style: {
|
||||
...value.style,
|
||||
backgroundColor,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const renderJSON = (data = '{}') => {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
@@ -133,6 +154,19 @@ export const ActionEditor = memo(({ index, value, onChange, suggestions, showOne
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field label={t('grafana-ui.action-editor.button.style', 'Button style')}>
|
||||
<InlineField
|
||||
label={t('actions.action-editor.button.style.background-color', 'Color')}
|
||||
labelWidth={LABEL_WIDTH}
|
||||
className={styles.colorPicker}
|
||||
>
|
||||
<ColorPicker
|
||||
color={value?.style?.backgroundColor || theme.colors.secondary.main}
|
||||
onChange={onBackgroundColorChange}
|
||||
/>
|
||||
</InlineField>
|
||||
</Field>
|
||||
|
||||
{showOneClick && (
|
||||
<Field
|
||||
label={t('grafana-ui.data-link-inline-editor.one-click', 'One click')}
|
||||
@@ -223,6 +257,10 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
inputField: css({
|
||||
marginRight: 4,
|
||||
}),
|
||||
colorPicker: css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}),
|
||||
});
|
||||
|
||||
ActionEditor.displayName = 'ActionEditor';
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
textUtil,
|
||||
ValueLinkConfig,
|
||||
} from '@grafana/data';
|
||||
import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime';
|
||||
import { BackendSrvRequest, getBackendSrv, config as grafanaConfig } from '@grafana/runtime';
|
||||
import { appEvents } from 'app/core/core';
|
||||
|
||||
import { HttpRequestMethod } from '../../plugins/panel/canvas/panelcfg.gen';
|
||||
@@ -63,6 +63,9 @@ export const getActions = (
|
||||
buildActionOnClick(action, boundReplaceVariables);
|
||||
},
|
||||
oneClick: action.oneClick ?? false,
|
||||
style: {
|
||||
backgroundColor: action.style?.backgroundColor ?? grafanaConfig.theme2.colors.secondary.main,
|
||||
},
|
||||
};
|
||||
|
||||
return actionModel;
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
},
|
||||
"actions": {
|
||||
"action-editor": {
|
||||
"button": {
|
||||
"style": {
|
||||
"background-color": "Color"
|
||||
}
|
||||
},
|
||||
"label-headers": "Headers",
|
||||
"label-url": "URL",
|
||||
"placeholder-url": "URL"
|
||||
@@ -5242,7 +5247,8 @@
|
||||
"action-editor": {
|
||||
"button": {
|
||||
"confirm": "Confirm",
|
||||
"confirm-action": "Confirm action"
|
||||
"confirm-action": "Confirm action",
|
||||
"style": "Button style"
|
||||
},
|
||||
"inline": {
|
||||
"add-action": "Add action",
|
||||
|
||||
Reference in New Issue
Block a user