Actions: Add button style customization (#104126)

pull/104789/head
Adela Almasan 3 weeks ago committed by GitHub
parent 53321b56d8
commit d7463556c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 18
      packages/grafana-data/src/types/action.ts
  2. 7
      packages/grafana-ui/src/components/Actions/ActionButton.tsx
  3. 2
      packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx
  4. 40
      public/app/features/actions/ActionEditor.tsx
  5. 5
      public/app/features/actions/utils.ts
  6. 8
      public/locales/en-US/grafana.json

@ -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",

Loading…
Cancel
Save