mirror of https://github.com/grafana/grafana.git
Accessibility: Make either `tooltip` or `aria-label` required when no button children present (#109131)
* ensure button must have tooltip/aria-label when no children * fix violations * restore some unnecessarily removed labels * use types instead of interfaces as before * further fixes * fix unit test * commit translations and fix unit test * upgrade plugin-ui to 0.10.8 * set aria-label + unit tests
This commit is contained in:
parent
c7f3c92b21
commit
1021f05e32
|
|
@ -41,7 +41,7 @@ module.exports = {
|
|||
verbose: false,
|
||||
testEnvironment: 'jsdom',
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx|js|jsx)$': [require.resolve('ts-jest'), { isolatedModules: true }],
|
||||
'^.+\\.(ts|tsx|js|jsx)$': [require.resolve('ts-jest')],
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})`, // exclude es modules to prevent TS complaining
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@
|
|||
"@grafana/llm": "0.22.1",
|
||||
"@grafana/monaco-logql": "^0.0.8",
|
||||
"@grafana/o11y-ds-frontend": "workspace:*",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/prometheus": "workspace:*",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/scenes": "6.29.1",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/e2e-selectors": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/schema": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ export function TraceToMetricsSettings({ options, onOptionsChange }: Props) {
|
|||
|
||||
<Button
|
||||
variant="destructive"
|
||||
title="Remove query"
|
||||
aria-label="Remove query"
|
||||
icon="times"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/e2e-selectors": "12.2.0-pre",
|
||||
"@grafana/i18n": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/schema": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ export function ExemplarSetting({ value, onChange, onDelete, disabled }: Props)
|
|||
>
|
||||
<Button
|
||||
variant="destructive"
|
||||
title={t(
|
||||
aria-label={t(
|
||||
'grafana-prometheus.configuration.exemplar-setting.title-remove-exemplar-link',
|
||||
'Remove exemplar link'
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ export function OperationEditor({
|
|||
fill="text"
|
||||
icon="times"
|
||||
variant="secondary"
|
||||
title={t('grafana-prometheus.querybuilder.operation-editor.title-remove', 'Remove {{name}}', {
|
||||
aria-label={t('grafana-prometheus.querybuilder.operation-editor.title-remove', 'Remove {{name}}', {
|
||||
name: paramDef.name,
|
||||
})}
|
||||
onClick={() => onRemoveRestParam(paramIndex)}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export const OperationHeader = memo<Props>(
|
|||
onClick={onToggleSwitcher}
|
||||
fill="text"
|
||||
variant="secondary"
|
||||
title={t(
|
||||
aria-label={t(
|
||||
'grafana-prometheus.querybuilder.operation-header.title-click-to-view-alternative-operations',
|
||||
'Click to view alternative operations'
|
||||
)}
|
||||
|
|
@ -67,7 +67,10 @@ export const OperationHeader = memo<Props>(
|
|||
onClick={() => onRemove(index)}
|
||||
fill="text"
|
||||
variant="secondary"
|
||||
title={t('grafana-prometheus.querybuilder.operation-header.title-remove-operation', 'Remove operation')}
|
||||
aria-label={t(
|
||||
'grafana-prometheus.querybuilder.operation-header.title-remove-operation',
|
||||
'Remove operation'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export const OperationInfoButton = memo<Props>(({ def, operation }) => {
|
|||
return (
|
||||
<>
|
||||
<Button
|
||||
title={t(
|
||||
tooltip={t(
|
||||
'grafana-prometheus.querybuilder.operation-info-button.title-click-to-show-description',
|
||||
'Click to show description'
|
||||
)}
|
||||
|
|
@ -78,7 +78,7 @@ export const OperationInfoButton = memo<Props>(({ def, operation }) => {
|
|||
onClick={() => setShow(false)}
|
||||
fill="text"
|
||||
variant="secondary"
|
||||
title={t(
|
||||
aria-label={t(
|
||||
'grafana-prometheus.querybuilder.operation-info-button.title-remove-operation',
|
||||
'Remove operation'
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ describe('OperationList', () => {
|
|||
|
||||
it('removes an operation', async () => {
|
||||
const { onChange } = setup();
|
||||
const removeOperationButtons = screen.getAllByTitle('Remove operation');
|
||||
const removeOperationButtons = screen.getAllByLabelText('Remove operation');
|
||||
expect(removeOperationButtons).toHaveLength(2);
|
||||
await userEvent.click(removeOperationButtons[1]);
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ function SelectInputParamEditor({
|
|||
fill="text"
|
||||
icon="times"
|
||||
variant="secondary"
|
||||
title={t('grafana-prometheus.querybuilder.operation-param-editor.title-remove', 'Remove {{name}}', {
|
||||
aria-label={t('grafana-prometheus.querybuilder.operation-param-editor.title-remove', 'Remove {{name}}', {
|
||||
name: paramDef.name,
|
||||
})}
|
||||
onClick={() => onChange(index, '')}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/e2e-selectors": "12.2.0-pre",
|
||||
"@grafana/i18n": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
"@react-awesome-query-builder/ui": "6.6.15",
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export const settings: Settings = {
|
|||
return (
|
||||
<Button
|
||||
type="button"
|
||||
title={t('grafana-sql.components.settings.title-button-filter', '{{ buttonLabel }} filter', {
|
||||
aria-label={t('grafana-sql.components.settings.title-button-filter', '{{ buttonLabel }} filter', {
|
||||
buttonLabel: buttonProps?.label,
|
||||
})}
|
||||
onClick={buttonProps?.onClick}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ function makeRenderColumn({ options }: { options?: Array<SelectableValue<string>
|
|||
onChange={({ value }) => value && onChangeItem(setGroupByField(value))}
|
||||
/>
|
||||
<AccessoryButton
|
||||
title={t(
|
||||
aria-label={t(
|
||||
'grafana-sql.components.make-render-column.render-column.title-remove-group-by-column',
|
||||
'Remove group by column'
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export function SelectCustomFunctionParameters({
|
|||
data-testid={selectors.components.SQLQueryEditor.selectInputParameter}
|
||||
addonAfter={
|
||||
<Button
|
||||
title={t(
|
||||
aria-label={t(
|
||||
'grafana-sql.components.select-custom-function-parameters.render-parameters.params.title-remove-parameter',
|
||||
'Remove parameter'
|
||||
)}
|
||||
|
|
@ -127,7 +127,7 @@ export function SelectCustomFunctionParameters({
|
|||
variant="secondary"
|
||||
size="md"
|
||||
icon="plus"
|
||||
title={t('grafana-sql.components.select-custom-function-parameters.title-add-parameter', 'Add parameter')}
|
||||
aria-label={t('grafana-sql.components.select-custom-function-parameters.title-add-parameter', 'Add parameter')}
|
||||
/>
|
||||
<InlineLabel className={styles.label}>)</InlineLabel>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
|
|||
/>
|
||||
</EditorField>
|
||||
<Button
|
||||
title={t('grafana-sql.components.select-row.title-remove-column', 'Remove column')}
|
||||
aria-label={t('grafana-sql.components.select-row.title-remove-column', 'Remove column')}
|
||||
type="button"
|
||||
icon="trash-alt"
|
||||
variant="secondary"
|
||||
|
|
@ -167,7 +167,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
|
|||
type="button"
|
||||
onClick={addColumn}
|
||||
variant="secondary"
|
||||
title={t('grafana-sql.components.select-row.title-add-column', 'Add column')}
|
||||
aria-label={t('grafana-sql.components.select-row.title-add-column', 'Add column')}
|
||||
size="md"
|
||||
icon="plus"
|
||||
className={styles.addButton}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { ConfirmModal } from '../ConfirmModal/ConfirmModal';
|
|||
|
||||
import { VariablesInputModal } from './VariablesInputModal';
|
||||
|
||||
type ActionButtonProps = ButtonProps & {
|
||||
type ActionButtonProps = Omit<ButtonProps, 'children'> & {
|
||||
action: ActionModel<Field>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,4 +41,26 @@ describe('Button', () => {
|
|||
const svgElement = document.querySelector('svg');
|
||||
expect(svgElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should set an aria-label if there is a tooltip string but no children', () => {
|
||||
setup(<Button tooltip="Tooltip text" />);
|
||||
expect(screen.getByRole('button', { name: 'Tooltip text' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not set an aria-label if there is a tooltip string but child text', () => {
|
||||
setup(<Button tooltip="Tooltip text">Child text</Button>);
|
||||
expect(screen.queryByRole('button', { name: 'Tooltip text' })).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Child text' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should prioritise the aria-label if it is present', () => {
|
||||
setup(
|
||||
<Button aria-label="Aria label" tooltip="Tooltip text">
|
||||
Child text
|
||||
</Button>
|
||||
);
|
||||
expect(screen.queryByRole('button', { name: 'Child text' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Tooltip text' })).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Aria label' })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,28 +18,43 @@ export const allButtonVariants: ButtonVariant[] = ['primary', 'secondary', 'dest
|
|||
export type ButtonFill = 'solid' | 'outline' | 'text';
|
||||
export const allButtonFills: ButtonFill[] = ['solid', 'outline', 'text'];
|
||||
|
||||
type CommonProps = {
|
||||
type BaseProps = {
|
||||
size?: ComponentSize;
|
||||
variant?: ButtonVariant;
|
||||
fill?: ButtonFill;
|
||||
icon?: IconName | React.ReactElement;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
fullWidth?: boolean;
|
||||
type?: string;
|
||||
/** Tooltip content to display on hover */
|
||||
tooltip?: PopoverContent;
|
||||
/** Position of the tooltip */
|
||||
tooltipPlacement?: TooltipPlacement;
|
||||
/** Position of the icon */
|
||||
iconPlacement?: 'left' | 'right';
|
||||
};
|
||||
|
||||
// either aria-label or tooltip is required for buttons without children
|
||||
type NoChildrenAriaLabel = BaseProps & {
|
||||
children?: never;
|
||||
'aria-label': string;
|
||||
};
|
||||
type NoChildrenTooltip = BaseProps & {
|
||||
children?: never;
|
||||
tooltip: PopoverContent;
|
||||
tooltipPlacement?: TooltipPlacement;
|
||||
};
|
||||
|
||||
type BasePropsWithChildren = BaseProps & {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
type CommonProps = BasePropsWithChildren | NoChildrenTooltip | NoChildrenAriaLabel;
|
||||
|
||||
export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
(
|
||||
{
|
||||
'aria-label': ariaLabel,
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
fill = 'solid',
|
||||
|
|
@ -92,6 +107,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
aria-disabled={hasTooltip && disabled}
|
||||
disabled={!hasTooltip && disabled}
|
||||
ref={tooltip ? undefined : ref}
|
||||
aria-label={ariaLabel ?? (!children && typeof tooltip === 'string' ? tooltip : undefined)}
|
||||
>
|
||||
{iconPlacement === 'left' && iconComponent}
|
||||
{children && <span className={styles.content}>{children}</span>}
|
||||
|
|
@ -113,13 +129,12 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
|
||||
Button.displayName = 'Button';
|
||||
|
||||
export type ButtonLinkProps = CommonProps &
|
||||
ButtonHTMLAttributes<HTMLButtonElement> &
|
||||
AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
export type ButtonLinkProps = ButtonProps & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'aria-label'>;
|
||||
|
||||
export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
(
|
||||
{
|
||||
'aria-label': ariaLabel,
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
fill = 'solid',
|
||||
|
|
@ -164,6 +179,7 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
|||
tabIndex={disabled ? -1 : 0}
|
||||
aria-disabled={disabled}
|
||||
ref={tooltip ? undefined : ref}
|
||||
aria-label={ariaLabel ?? (!children && typeof tooltip === 'string' ? tooltip : undefined)}
|
||||
>
|
||||
<IconRenderer icon={icon} size={size} className={styles.icon} />
|
||||
{children && <span className={styles.content}>{children}</span>}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { Icon } from '../Icon/Icon';
|
|||
|
||||
export interface ButtonCascaderProps {
|
||||
options: CascaderOption[];
|
||||
children?: string;
|
||||
children: string;
|
||||
icon?: IconName;
|
||||
disabled?: boolean;
|
||||
value?: string[];
|
||||
|
|
@ -24,7 +24,7 @@ export interface ButtonCascaderProps {
|
|||
onPopupVisibleChange?: (visible: boolean) => void;
|
||||
className?: string;
|
||||
variant?: ButtonProps['variant'];
|
||||
buttonProps?: ButtonProps;
|
||||
buttonProps?: Omit<ButtonProps, 'children'>;
|
||||
hideDownIcon?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ const meta: Meta = {
|
|||
},
|
||||
};
|
||||
|
||||
interface StoryProps extends Partial<Props> {
|
||||
type StoryProps = Partial<Props> & {
|
||||
inputText: string;
|
||||
buttonText: string;
|
||||
}
|
||||
};
|
||||
|
||||
export const ClipboardButton: StoryFn<StoryProps> = (args) => {
|
||||
const shareUrl = 'https://grafana.com/d/abcDEF-34t';
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ import { Button, ButtonProps } from '../Button/Button';
|
|||
import { Icon } from '../Icon/Icon';
|
||||
import { InlineToast } from '../InlineToast/InlineToast';
|
||||
|
||||
export interface Props extends ButtonProps {
|
||||
export type Props = ButtonProps & {
|
||||
/** A function that returns text to be copied */
|
||||
getText(): string;
|
||||
/** Callback when the text has been successfully copied */
|
||||
onClipboardCopy?(copiedText: string): void;
|
||||
/** Callback when there was an error copying the text */
|
||||
onClipboardError?(copiedText: string, error: unknown): void;
|
||||
}
|
||||
};
|
||||
|
||||
const SHOW_SUCCESS_DURATION = 2 * 1000;
|
||||
|
||||
|
|
@ -73,7 +73,6 @@ export function ClipboardButton({
|
|||
onClick={copyTextCallback}
|
||||
icon={icon}
|
||||
variant={showCopySuccess ? 'success' : variant}
|
||||
aria-label={showCopySuccess ? copiedText : undefined}
|
||||
{...buttonProps}
|
||||
className={cx(styles.button, showCopySuccess && styles.successButton, buttonProps.className)}
|
||||
ref={buttonRef}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ButtonProps, Button } from '../Button/Button';
|
|||
|
||||
type DataLinkButtonProps = {
|
||||
link: LinkModel<Field>;
|
||||
buttonProps?: ButtonProps;
|
||||
buttonProps?: Omit<ButtonProps, 'children'>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ export const FilterPopup = ({
|
|||
value={searchFilter}
|
||||
/>
|
||||
<Button
|
||||
tooltip={t('grafana-ui.table.filter-popup-aria-label-match-case', 'Match case')}
|
||||
variant="secondary"
|
||||
style={{ color: matchCase ? theme.colors.text.link : theme.colors.text.disabled }}
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ export default class PageActionBar extends PureComponent<Props> {
|
|||
placeholder = 'Search by name or type',
|
||||
sortPicker,
|
||||
} = this.props;
|
||||
const linkProps: Parameters<typeof LinkButton>[0] = { href: linkButton?.href, disabled: linkButton?.disabled };
|
||||
const linkProps: Omit<Parameters<typeof LinkButton>[0], 'children'> = {
|
||||
href: linkButton?.href,
|
||||
disabled: linkButton?.disabled,
|
||||
};
|
||||
|
||||
if (target) {
|
||||
linkProps.target = target;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Trans, t } from '@grafana/i18n';
|
|||
import { Button, ButtonProps, Icon, Stack } from '@grafana/ui';
|
||||
|
||||
const MoreButton = forwardRef(function MoreButton(
|
||||
props: ButtonProps & { title?: string },
|
||||
props: Omit<ButtonProps, 'children'> & { title?: string },
|
||||
ref: Ref<HTMLButtonElement>
|
||||
) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { Icon, LinkButton, Stack, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { ReceiverPluginMetadata } from './useReceiversMetadata';
|
||||
|
|
@ -25,7 +26,14 @@ export const ReceiverMetadataBadge = ({ metadata: { icon, title, externalUrl, wa
|
|||
<span>{title}</span>
|
||||
</Stack>
|
||||
{externalUrl && (
|
||||
<LinkButton icon="external-link-alt" href={externalUrl} target="_blank" variant="secondary" size="sm" />
|
||||
<LinkButton
|
||||
aria-label={t('alerting.receiver-metadata-badge.aria-label-open-external-link', 'Open external link')}
|
||||
icon="external-link-alt"
|
||||
href={externalUrl}
|
||||
target="_blank"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -301,7 +301,14 @@ export const Title = ({ name, paused = false, state, health, ruleType, ruleOrigi
|
|||
|
||||
return (
|
||||
<Stack direction="row" gap={1} minWidth={0} alignItems="center">
|
||||
{returnToHref && <LinkButton variant="secondary" icon="angle-left" href={returnTo} />}
|
||||
{returnToHref && (
|
||||
<LinkButton
|
||||
aria-label={t('alerting.rule-viewer.aria-label-return-to', 'Return to previous view')}
|
||||
variant="secondary"
|
||||
icon="angle-left"
|
||||
href={returnTo}
|
||||
/>
|
||||
)}
|
||||
{ruleOrigin && <PluginOriginBadge pluginId={ruleOrigin.pluginId} size="lg" />}
|
||||
<Text variant="h1" truncate>
|
||||
{name}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@ import { Button, ButtonProps, useStyles2 } from '@grafana/ui';
|
|||
|
||||
type Props = Omit<ButtonProps, 'variant' | 'size'>;
|
||||
|
||||
export const ActionButton = ({ className, ...restProps }: Props) => {
|
||||
export const ActionButton = ({ children, className, ...restProps }: Props) => {
|
||||
const styles = useStyles2(getStyle);
|
||||
return <Button variant="secondary" size="xs" className={cx(styles.wrapper, className)} {...restProps} />;
|
||||
return (
|
||||
<Button variant="secondary" size="xs" className={cx(styles.wrapper, className)} {...restProps}>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStyle = (theme: GrafanaTheme2) => ({
|
||||
|
|
|
|||
|
|
@ -27,32 +27,32 @@ export const ActionIcon = ({
|
|||
}: Props) => {
|
||||
const ariaLabel = typeof tooltip === 'string' ? tooltip : undefined;
|
||||
|
||||
return (
|
||||
<Tooltip content={tooltip} placement={tooltipPlacement}>
|
||||
{to ? (
|
||||
<LinkButton
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
icon={icon}
|
||||
href={to}
|
||||
size="sm"
|
||||
target={target}
|
||||
{...rest}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
className={className}
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
size="sm"
|
||||
icon={icon}
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
{...rest}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
)}
|
||||
</Tooltip>
|
||||
return to ? (
|
||||
<LinkButton
|
||||
tooltip={tooltip}
|
||||
tooltipPlacement={tooltipPlacement}
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
icon={icon}
|
||||
href={to}
|
||||
size="sm"
|
||||
target={target}
|
||||
{...rest}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
tooltip={tooltip}
|
||||
tooltipPlacement={tooltipPlacement}
|
||||
className={className}
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
size="sm"
|
||||
icon={icon}
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
{...rest}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { t } from '@grafana/i18n';
|
||||
import { LinkButton, Stack, Text } from '@grafana/ui';
|
||||
|
||||
import { useReturnTo } from '../hooks/useReturnTo';
|
||||
|
|
@ -7,7 +8,12 @@ export const Title = ({ name }: { name: string }) => {
|
|||
|
||||
return (
|
||||
<Stack direction="row" gap={1} minWidth={0} alignItems="center">
|
||||
<LinkButton variant="secondary" icon="angle-left" href={returnTo} />
|
||||
<LinkButton
|
||||
aria-label={t('alerting.group-details.title.back', 'Back to alerting')}
|
||||
variant="secondary"
|
||||
icon="angle-left"
|
||||
href={returnTo}
|
||||
/>
|
||||
<Text element="h1" truncate>
|
||||
{name}
|
||||
</Text>
|
||||
|
|
|
|||
|
|
@ -21,17 +21,17 @@ export function RuleListPageTitle({ title }: { title: string }) {
|
|||
window.location.reload();
|
||||
};
|
||||
|
||||
const { text, ...configToUse }: ButtonProps & { text: string; 'data-testid': string } = listViewV2Enabled
|
||||
const configToUse: ButtonProps & { 'data-testid': string } = listViewV2Enabled
|
||||
? {
|
||||
variant: 'secondary',
|
||||
icon: undefined,
|
||||
text: t('alerting.rule-list.toggle.go-back-to-old-look', 'Go back to the old look'),
|
||||
children: t('alerting.rule-list.toggle.go-back-to-old-look', 'Go back to the old look'),
|
||||
'data-testid': 'alerting-list-view-toggle-v1',
|
||||
}
|
||||
: {
|
||||
variant: 'primary',
|
||||
icon: 'rocket',
|
||||
text: t('alerting.rule-list.toggle.try-out-the-new-look', 'Try out the new look!'),
|
||||
children: t('alerting.rule-list.toggle.try-out-the-new-look', 'Try out the new look!'),
|
||||
'data-testid': 'alerting-list-view-toggle-v2',
|
||||
};
|
||||
|
||||
|
|
@ -40,9 +40,7 @@ export function RuleListPageTitle({ title }: { title: string }) {
|
|||
<h1>{title}</h1>
|
||||
{shouldShowV2Toggle && (
|
||||
<div>
|
||||
<Button size="sm" fill="outline" {...configToUse} onClick={toggleListView} className="fs-unmask">
|
||||
{text}
|
||||
</Button>
|
||||
<Button size="sm" fill="outline" {...configToUse} onClick={toggleListView} className="fs-unmask" />
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
|
|||
placeholder={t('dashboard-scene.panel-viz-type-picker.placeholder-search-for', 'Search for...')}
|
||||
/>
|
||||
<Button
|
||||
title={t('dashboard-scene.panel-viz-type-picker.title-close', 'Close')}
|
||||
aria-label={t('dashboard-scene.panel-viz-type-picker.title-close', 'Close')}
|
||||
variant="secondary"
|
||||
icon="angle-up"
|
||||
className={styles.closeButton}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useLocalStorage } from 'react-use';
|
|||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { Button, Counter, Icon, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
|
||||
|
|
@ -139,6 +140,11 @@ export const OptionsPaneCategory = React.memo(
|
|||
{renderTitle(isExpanded)}
|
||||
</h6>
|
||||
<Button
|
||||
aria-label={
|
||||
isExpanded
|
||||
? t('dashboard.options-pane-category.aria-label-collapse', 'Collapse {{title}} category', { title })
|
||||
: t('dashboard.options-pane-category.aria-label-expand', 'Expand {{title}} category', { title })
|
||||
}
|
||||
data-testid={selectors.components.OptionsGroup.toggle(id)}
|
||||
type="button"
|
||||
fill="text"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useRef } from 'react';
|
|||
import * as React from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Trans } from '@grafana/i18n';
|
||||
import { t, Trans } from '@grafana/i18n';
|
||||
import {
|
||||
Button,
|
||||
InlineField,
|
||||
|
|
@ -86,7 +86,16 @@ export const ResourcePicker = (props: Props) => {
|
|||
placeholder={placeholder}
|
||||
readOnly={true}
|
||||
prefix={sanitizedSrc && <SanitizedSVG src={sanitizedSrc} className={styles.icon} style={{ ...colorStyle }} />}
|
||||
suffix={<Button icon="times" variant="secondary" fill="text" size="sm" onClick={onClear} />}
|
||||
suffix={
|
||||
<Button
|
||||
aria-label={t('dimensions.resource-picker.aria-label-clear-value', 'Clear value')}
|
||||
icon="times"
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
size="sm"
|
||||
onClick={onClear}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
|
|
|
|||
|
|
@ -115,7 +115,16 @@ export const TextDimensionEditor = ({ value, context, onChange }: Props) => {
|
|||
onChange={onFixedChange}
|
||||
item={dummyStringSettings}
|
||||
suffix={
|
||||
value?.fixed && <Button icon="times" variant="secondary" fill="text" size="sm" onClick={onClearFixed} />
|
||||
value?.fixed && (
|
||||
<Button
|
||||
aria-label={t('dimensions.text-dimension-editor.aria-label-clear-value', 'Clear value')}
|
||||
icon="times"
|
||||
variant="secondary"
|
||||
fill="text"
|
||||
size="sm"
|
||||
onClick={onClearFixed}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ export function ContentOutlineItemButton({
|
|||
</button>
|
||||
{onRemove && (
|
||||
<Button
|
||||
aria-label={t(
|
||||
'explore.content-outline-item-button.body.aria-label-content-outline-item-delete-button',
|
||||
'Delete item'
|
||||
)}
|
||||
variant="destructive"
|
||||
className={styles.deleteButton}
|
||||
icon="times"
|
||||
|
|
|
|||
|
|
@ -218,7 +218,14 @@ export const LogsVolumePanelList = ({
|
|||
label={t('explore.logs-volume-panel-list.label-reload-log-volume', 'Reload log volume')}
|
||||
transparent
|
||||
>
|
||||
<Button size="xs" icon="sync" variant="secondary" onClick={onLoadLogsVolume} id="reload-volume" />
|
||||
<Button
|
||||
aria-label={t('explore.logs-volume-panel-list.aria-label-reload-log-volume', 'Reload log volume')}
|
||||
size="xs"
|
||||
icon="sync"
|
||||
variant="secondary"
|
||||
onClick={onLoadLogsVolume}
|
||||
id="reload-volume"
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -249,7 +249,13 @@ export const TracePageHeader = memo((props: TracePageHeaderProps) => {
|
|||
</Tooltip>
|
||||
|
||||
<Dropdown overlay={shareDropdownMenu} placement="bottom-end">
|
||||
<Button size="sm" variant="secondary" fill="outline" icon="angle-down" />
|
||||
<Button
|
||||
aria-label={t('explore.trace-page-header.aria-label-share-dropdown', 'Open share trace options menu')}
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
fill="outline"
|
||||
icon="angle-down"
|
||||
/>
|
||||
</Dropdown>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,13 @@ export default function CopyIcon({ copyText, icon = 'copy', tooltipTitle }: Prop
|
|||
|
||||
return (
|
||||
<Tooltip content={hasCopied ? t('explore.trace-view.tooltip-copy-icon', 'Copied') : tooltipTitle}>
|
||||
<Button className={cx(styles.CopyIcon)} type="button" icon={icon} onClick={handleClick} />
|
||||
<Button
|
||||
aria-label={t('explore.trace-view.aria-label-copy', 'Copy to clipboard')}
|
||||
className={cx(styles.CopyIcon)}
|
||||
type="button"
|
||||
icon={icon}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ describe('LogDetailsRow', () => {
|
|||
it('should be invisible unless mouse is over', () => {
|
||||
setup({ parsedValues: ['test value'] });
|
||||
// This tests a regression where the button was always visible.
|
||||
expect(screen.getByTitle('Copy value to clipboard')).not.toBeVisible();
|
||||
expect(screen.getByLabelText('Copy value to clipboard')).not.toBeVisible();
|
||||
// Asserting visibility on mouse-over is currently not possible.
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
|
|||
<div className={`log-details-value-copy ${styles.copyButton}`}>
|
||||
<ClipboardButton
|
||||
getText={() => val}
|
||||
title={t('logs.un-themed-log-details-row.title-copy-value-to-clipboard', 'Copy value to clipboard')}
|
||||
aria-label={t('logs.un-themed-log-details-row.title-copy-value-to-clipboard', 'Copy value to clipboard')}
|
||||
fill="text"
|
||||
variant="secondary"
|
||||
icon="copy"
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ const ClipboardButtonWrapper = ({ value }: { value: string }) => {
|
|||
<div className={styles.button}>
|
||||
<ClipboardButton
|
||||
getText={() => value}
|
||||
title={t('logs.log-line-details.fields.copy-value-to-clipboard', 'Copy value to clipboard')}
|
||||
aria-label={t('logs.log-line-details.fields.copy-value-to-clipboard', 'Copy value to clipboard')}
|
||||
fill="text"
|
||||
variant="secondary"
|
||||
icon="copy"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { ClipboardButton, useStyles2, CodeEditor } from '@grafana/ui';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -16,7 +17,14 @@ export const CodeBlock = ({ code, copyCode = true }: Props) => {
|
|||
return (
|
||||
<div className={styles.container}>
|
||||
{copyCode && (
|
||||
<ClipboardButton className={styles.copyButton} variant="secondary" size="sm" icon="copy" getText={() => code} />
|
||||
<ClipboardButton
|
||||
aria-label={t('provisioning.code-block.aria-label-copy', 'Copy code to clipboard')}
|
||||
className={styles.copyButton}
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
icon="copy"
|
||||
getText={() => code}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
value={code}
|
||||
|
|
|
|||
|
|
@ -431,7 +431,7 @@ export function QueryGroupTopSection({
|
|||
<Button
|
||||
variant="secondary"
|
||||
icon="question-circle"
|
||||
title={t(
|
||||
tooltip={t(
|
||||
'query.query-group-top-section.query-tab-help-button-title-open-data-source-help',
|
||||
'Open data source help'
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,12 @@ export const FilterByValueFilterEditor = (props: Props) => {
|
|||
<editor.component field={field} options={filter.config.options ?? {}} onChange={onChangeMatcherOptions} />
|
||||
</InlineField>
|
||||
<Box marginBottom={0.5}>
|
||||
<Button icon="times" onClick={onDelete} variant="secondary" />
|
||||
<Button
|
||||
aria-label={t('transformers.filter-by-value-filter-editor.aria-label-remove-filter', 'Remove filter')}
|
||||
icon="times"
|
||||
onClick={onDelete}
|
||||
variant="secondary"
|
||||
/>
|
||||
</Box>
|
||||
</InlineFieldRow>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,12 @@ export const FilterItem: React.FC<FilterItemProps> = ({
|
|||
width={inputFieldSize}
|
||||
disabled={!filter.property?.name}
|
||||
/>
|
||||
<Button variant="secondary" icon="times" onClick={() => onDelete(groupIndex, filterIndex)} />
|
||||
<Button
|
||||
aria-label={t('components.filter-item.aria-label-remove-filter', 'Remove filter')}
|
||||
variant="secondary"
|
||||
icon="times"
|
||||
onClick={() => onDelete(groupIndex, filterIndex)}
|
||||
/>
|
||||
{showOr && (
|
||||
<Label style={{ padding: '9px 14px' }}>
|
||||
<Trans i18nKey="components.filter-item.label-or">OR</Trans>
|
||||
|
|
|
|||
|
|
@ -219,7 +219,12 @@ export const FilterSection: React.FC<FilterSectionProps> = ({
|
|||
<div className={styles.filters}>
|
||||
{filters.length === 0 || filters.every((g) => g.expressions.length === 0) ? (
|
||||
<InputGroup>
|
||||
<Button variant="secondary" onClick={onAddAndFilters} icon="plus" />
|
||||
<Button
|
||||
aria-label={t('components.filter-section.aria-label-add-filter', 'Add filter')}
|
||||
variant="secondary"
|
||||
onClick={onAddAndFilters}
|
||||
icon="plus"
|
||||
/>
|
||||
</InputGroup>
|
||||
) : (
|
||||
<>
|
||||
|
|
@ -248,6 +253,7 @@ export const FilterSection: React.FC<FilterSectionProps> = ({
|
|||
))}
|
||||
</>
|
||||
<Button
|
||||
tooltip={t('components.filter-section.aria-label-add-or-filter', 'Add OR filter')}
|
||||
variant="secondary"
|
||||
style={{ marginLeft: '15px' }}
|
||||
onClick={() => onAddOrFilters(groupIndex, 'property', '')}
|
||||
|
|
|
|||
|
|
@ -126,10 +126,20 @@ export const FuzzySearch: React.FC<FuzzySearchProps> = ({
|
|||
onChange={(e: SelectableValue<string>) => updateFuzzySearch(e.value ?? '*', searchTerm)}
|
||||
width="auto"
|
||||
/>
|
||||
<Button variant="secondary" icon="times" onClick={onDeleteFuzzySearch} />
|
||||
<Button
|
||||
aria-label={t('components.fuzzy-search.aria-label-remove-fuzzy-search', 'Remove fuzzy search')}
|
||||
variant="secondary"
|
||||
icon="times"
|
||||
onClick={onDeleteFuzzySearch}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Button variant="secondary" onClick={() => setIsOpen(true)} icon="plus" />
|
||||
<Button
|
||||
aria-label={t('components.fuzzy-search.aria-label-add-fuzzy-search', 'Add fuzzy search')}
|
||||
variant="secondary"
|
||||
onClick={() => setIsOpen(true)}
|
||||
icon="plus"
|
||||
/>
|
||||
)}
|
||||
</InputGroup>
|
||||
</EditorField>
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ export const GroupBySection: React.FC<GroupBySectionProps> = ({
|
|||
/>
|
||||
) : (
|
||||
<Button
|
||||
aria-label={t('components.group-by-section.aria-label-add-group-by', 'Add group by')}
|
||||
variant="secondary"
|
||||
icon="plus"
|
||||
onClick={() =>
|
||||
|
|
|
|||
|
|
@ -139,9 +139,15 @@ export const OrderBySection: React.FC<OrderBySectionProps> = ({ query, allColumn
|
|||
options={orderOptions}
|
||||
onChange={(e) => e.value && handleOrderByChange(index, 'order', e.value)}
|
||||
/>
|
||||
<Button variant="secondary" icon="times" onClick={() => onDeleteOrderBy(index)} />
|
||||
<Button
|
||||
aria-label={t('components.order-by-section.aria-label-remove-order-by', 'Remove order by')}
|
||||
variant="secondary"
|
||||
icon="times"
|
||||
onClick={() => onDeleteOrderBy(index)}
|
||||
/>
|
||||
{index === orderBy.length - 1 ? (
|
||||
<Button
|
||||
aria-label={t('components.order-by-section.aria-label-add-order-by', 'Add order by')}
|
||||
variant="secondary"
|
||||
onClick={() => handleOrderByChange(-1, 'column', '')}
|
||||
icon="plus"
|
||||
|
|
@ -154,7 +160,12 @@ export const OrderBySection: React.FC<OrderBySectionProps> = ({ query, allColumn
|
|||
))
|
||||
) : (
|
||||
<InputGroup>
|
||||
<Button variant="secondary" onClick={() => handleOrderByChange(-1, 'column', '')} icon="plus" />
|
||||
<Button
|
||||
aria-label={t('components.order-by-section.aria-label-add-order-by', 'Add order by')}
|
||||
variant="secondary"
|
||||
onClick={() => handleOrderByChange(-1, 'column', '')}
|
||||
icon="plus"
|
||||
/>
|
||||
</InputGroup>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -163,7 +163,12 @@ export const TableSection: React.FC<TableSectionProps> = (props) => {
|
|||
isDisabled={!builderQuery?.from?.property.name}
|
||||
width={30}
|
||||
/>
|
||||
<Button variant="secondary" icon="times" onClick={onDeleteAllColumns} />
|
||||
<Button
|
||||
tooltip={t('components.table-section.tooltip-remove-all-columns', 'Remove all columns')}
|
||||
variant="secondary"
|
||||
icon="times"
|
||||
onClick={onDeleteAllColumns}
|
||||
/>
|
||||
</InputGroup>
|
||||
</EditorField>
|
||||
</EditorFieldGroup>
|
||||
|
|
|
|||
|
|
@ -115,9 +115,12 @@
|
|||
"aria-label-column": "Column",
|
||||
"aria-label-column-value": "Column value",
|
||||
"aria-label-operator": "Operator",
|
||||
"aria-label-remove-filter": "Remove filter",
|
||||
"label-or": "OR"
|
||||
},
|
||||
"filter-section": {
|
||||
"aria-label-add-filter": "Add filter",
|
||||
"aria-label-add-or-filter": "Add OR filter",
|
||||
"label-add-group": "Add group",
|
||||
"label-and": "AND",
|
||||
"label-filters": "Filters",
|
||||
|
|
@ -130,6 +133,8 @@
|
|||
"label-format-as": "Format as"
|
||||
},
|
||||
"fuzzy-search": {
|
||||
"aria-label-add-fuzzy-search": "Add fuzzy search",
|
||||
"aria-label-remove-fuzzy-search": "Remove fuzzy search",
|
||||
"aria-label-select-column": "Select Column",
|
||||
"label-fuzzy-search": "Fuzzy Search",
|
||||
"placeholder-search-team": "Enter search term",
|
||||
|
|
@ -144,6 +149,7 @@
|
|||
"aria-label-remove": "Remove"
|
||||
},
|
||||
"group-by-section": {
|
||||
"aria-label-add-group-by": "Add group by",
|
||||
"label-group-by": "Group by",
|
||||
"tooltip-group-by": "Organize results into categories based on specified columns. Group by can be used independently to list unique values in selected columns, or combined with aggregate functions to produce summary statistics for each group. When used alone, it returns distinct combinations of the specified columns."
|
||||
},
|
||||
|
|
@ -186,8 +192,10 @@
|
|||
"text-loading": "Loading..."
|
||||
},
|
||||
"order-by-section": {
|
||||
"aria-label-add-order-by": "Add order by",
|
||||
"aria-label-order-by-column": "Order by column",
|
||||
"aria-label-order-direction": "Order Direction",
|
||||
"aria-label-remove-order-by": "Remove order by",
|
||||
"label-by": "BY",
|
||||
"label-order-by": "Order By",
|
||||
"tooltip-order-by": "Sort results based on one or more columns in ascending or descending order."
|
||||
|
|
@ -249,7 +257,8 @@
|
|||
"label-columns": "Columns",
|
||||
"label-table": "Table",
|
||||
"placeholder-select-columns": "Select columns",
|
||||
"placeholder-select-table": "Select a table"
|
||||
"placeholder-select-table": "Select a table",
|
||||
"tooltip-remove-all-columns": "Remove all columns"
|
||||
},
|
||||
"time-grain-field": {
|
||||
"label-time-grain": "Time grain"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/i18n": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/schema": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/google-sdk": "0.3.4",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/schema": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export const DataLink = (props: Props) => {
|
|||
</InlineField>
|
||||
<Button
|
||||
variant={'destructive'}
|
||||
title="Remove field"
|
||||
aria-label="Remove field"
|
||||
icon="times"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"dependencies": {
|
||||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/sql": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -83,7 +83,12 @@ const CSVWaveEditor = (props: WaveProps) => {
|
|||
onBlur={() => onValueChange('labels', labels)}
|
||||
/>
|
||||
</InlineField>
|
||||
<Button icon={last ? 'plus' : 'minus'} variant="secondary" onClick={onAction} />
|
||||
<Button
|
||||
aria-label={last ? 'Add wave' : 'Remove wave'}
|
||||
icon={last ? 'plus' : 'minus'}
|
||||
variant="secondary"
|
||||
onClick={onAction}
|
||||
/>
|
||||
</InlineFieldRow>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"@grafana/data": "workspace:*",
|
||||
"@grafana/e2e-selectors": "workspace:*",
|
||||
"@grafana/o11y-ds-frontend": "workspace:*",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/ui": "workspace:*",
|
||||
"lodash": "4.17.21",
|
||||
|
|
|
|||
|
|
@ -269,32 +269,31 @@ export function LokiContextUi(props: LokiContextUiProps) {
|
|||
elevated={true}
|
||||
></Alert>
|
||||
)}
|
||||
<Tooltip content={'Revert to initial log context query.'}>
|
||||
<div className={styles.iconButton}>
|
||||
<Button
|
||||
data-testid="revert-button"
|
||||
icon="history-alt"
|
||||
variant="secondary"
|
||||
disabled={isInitialState}
|
||||
onClick={(e) => {
|
||||
reportInteraction('grafana_explore_logs_loki_log_context_reverted', {
|
||||
logRowUid: row.uid,
|
||||
});
|
||||
setContextFilters((contextFilters) => {
|
||||
return contextFilters.map((contextFilter) => ({
|
||||
...contextFilter,
|
||||
// For revert to initial query we need to enable all labels and disable all parsed labels
|
||||
enabled: !contextFilter.nonIndexed,
|
||||
}));
|
||||
});
|
||||
// We are removing the preserved labels from local storage so we can preselect the labels in the UI
|
||||
window.localStorage.removeItem(LOKI_LOG_CONTEXT_PRESERVED_LABELS);
|
||||
window.localStorage.removeItem(SHOULD_INCLUDE_PIPELINE_OPERATIONS);
|
||||
setIncludePipelineOperations(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={styles.iconButton}>
|
||||
<Button
|
||||
tooltip="Revert to initial log context query"
|
||||
data-testid="revert-button"
|
||||
icon="history-alt"
|
||||
variant="secondary"
|
||||
disabled={isInitialState}
|
||||
onClick={(e) => {
|
||||
reportInteraction('grafana_explore_logs_loki_log_context_reverted', {
|
||||
logRowUid: row.uid,
|
||||
});
|
||||
setContextFilters((contextFilters) => {
|
||||
return contextFilters.map((contextFilter) => ({
|
||||
...contextFilter,
|
||||
// For revert to initial query we need to enable all labels and disable all parsed labels
|
||||
enabled: !contextFilter.nonIndexed,
|
||||
}));
|
||||
});
|
||||
// We are removing the preserved labels from local storage so we can preselect the labels in the UI
|
||||
window.localStorage.removeItem(LOKI_LOG_CONTEXT_PRESERVED_LABELS);
|
||||
window.localStorage.removeItem(SHOULD_INCLUDE_PIPELINE_OPERATIONS);
|
||||
setIncludePipelineOperations(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Collapse
|
||||
collapsible={true}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ export const DerivedField = (props: Props) => {
|
|||
<Field label="">
|
||||
<Button
|
||||
variant="destructive"
|
||||
title="Remove field"
|
||||
aria-label="Remove field"
|
||||
icon="times"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ describe('DerivedFields', () => {
|
|||
const onChange = jest.fn();
|
||||
render(<DerivedFields fields={testFields} onChange={onChange} />);
|
||||
|
||||
await userEvent.click((await screen.findAllByTitle('Remove field'))[0]);
|
||||
await userEvent.click((await screen.findAllByLabelText('Remove field'))[0]);
|
||||
|
||||
await waitFor(() => expect(onChange).toHaveBeenCalledWith([testFields[1]]));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/i18n": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/sql": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"dependencies": {
|
||||
"@emotion/css": "11.13.5",
|
||||
"@grafana/data": "12.2.0-pre",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "12.2.0-pre",
|
||||
"@grafana/sql": "12.2.0-pre",
|
||||
"@grafana/ui": "12.2.0-pre",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"@grafana/lezer-traceql": "0.0.23",
|
||||
"@grafana/monaco-logql": "^0.0.8",
|
||||
"@grafana/o11y-ds-frontend": "workspace:*",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/schema": "workspace:*",
|
||||
"@grafana/ui": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"@grafana/data": "workspace:*",
|
||||
"@grafana/e2e-selectors": "workspace:*",
|
||||
"@grafana/o11y-ds-frontend": "workspace:*",
|
||||
"@grafana/plugin-ui": "0.10.7",
|
||||
"@grafana/plugin-ui": "0.10.8",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/ui": "workspace:*",
|
||||
"lodash": "4.17.21",
|
||||
|
|
|
|||
|
|
@ -84,7 +84,14 @@ export const MeasureOverlay = ({ map, menuActiveState }: Props) => {
|
|||
vector.current.addInteraction(map, m.geometry, showSegments, clearPrevious);
|
||||
}}
|
||||
/>
|
||||
<Button className={measureStyle.button} icon="times" variant="secondary" size="sm" onClick={toggleMenu} />
|
||||
<Button
|
||||
aria-label={t('geomap.measure-overlay.aria-label-close', 'Close measure tools')}
|
||||
className={measureStyle.button}
|
||||
icon="times"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={toggleMenu}
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
className={measureStyle.unitSelect}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ describe('NodeGraph', () => {
|
|||
layoutAlgorithm={LayoutAlgorithm.Force}
|
||||
/>
|
||||
);
|
||||
const zoomIn = await screen.findByTitle(/Zoom in/);
|
||||
const zoomOut = await screen.findByTitle(/Zoom out/);
|
||||
const zoomIn = await screen.findByLabelText(/Zoom in/);
|
||||
const zoomOut = await screen.findByLabelText(/Zoom out/);
|
||||
|
||||
expect(getScale()).toBe(1);
|
||||
await userEvent.click(zoomIn);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export function ViewControls<Config extends Record<string, any>>(props: Props<Co
|
|||
icon={'plus-circle'}
|
||||
onClick={onPlus}
|
||||
size={'md'}
|
||||
title={t('nodeGraph.view-controls.title-zoom-in', 'Zoom in')}
|
||||
aria-label={t('nodeGraph.view-controls.title-zoom-in', 'Zoom in')}
|
||||
variant="secondary"
|
||||
disabled={disableZoomIn}
|
||||
/>
|
||||
|
|
@ -50,7 +50,7 @@ export function ViewControls<Config extends Record<string, any>>(props: Props<Co
|
|||
icon={'minus-circle'}
|
||||
onClick={onMinus}
|
||||
size={'md'}
|
||||
title={t('nodeGraph.view-controls.title-zoom-out', 'Zoom out')}
|
||||
aria-label={t('nodeGraph.view-controls.title-zoom-out', 'Zoom out')}
|
||||
variant="secondary"
|
||||
disabled={disableZoomOut}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export const ArcOptionsEditor = ({ value, onChange, context }: ArcOptionsEditorP
|
|||
icon="minus"
|
||||
variant="secondary"
|
||||
onClick={() => removeArc(i)}
|
||||
title={t('nodeGraph.arc-options-editor.title-remove-arc', 'Remove arc')}
|
||||
aria-label={t('nodeGraph.arc-options-editor.title-remove-arc', 'Remove arc')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1523,7 +1523,10 @@
|
|||
"group-loading-error": "Error loading the group",
|
||||
"interval": "Interval",
|
||||
"namespace": "Namespace",
|
||||
"new": "New"
|
||||
"new": "New",
|
||||
"title": {
|
||||
"back": "Back to alerting"
|
||||
}
|
||||
},
|
||||
"group-edit": {
|
||||
"ds-error": "Error loading data source details",
|
||||
|
|
@ -2240,6 +2243,9 @@
|
|||
"title-attention": "Attention",
|
||||
"title-manage-contact-point-permissions": "Manage contact point permissions"
|
||||
},
|
||||
"receiver-metadata-badge": {
|
||||
"aria-label-open-external-link": "Open external link"
|
||||
},
|
||||
"receivers-section": {
|
||||
"button-more": "More",
|
||||
"new-menu": {
|
||||
|
|
@ -2566,6 +2572,7 @@
|
|||
}
|
||||
},
|
||||
"rule-viewer": {
|
||||
"aria-label-return-to": "Return to previous view",
|
||||
"error-loading": "Something went wrong loading the rule",
|
||||
"evaluation-interval": "Every {{interval}}",
|
||||
"prometheus-consistency-check": {
|
||||
|
|
@ -4944,6 +4951,10 @@
|
|||
"description": "Description",
|
||||
"title-option": "Title"
|
||||
},
|
||||
"options-pane-category": {
|
||||
"aria-label-collapse": "Collapse {{title}} category",
|
||||
"aria-label-expand": "Expand {{title}} category"
|
||||
},
|
||||
"options-pane-options": {
|
||||
"placeholder-search-options": "Search options",
|
||||
"Recent options-title-recent-options": "Recent options",
|
||||
|
|
@ -6598,6 +6609,7 @@
|
|||
"label-source": "Source"
|
||||
},
|
||||
"resource-picker": {
|
||||
"aria-label-clear-value": "Clear value",
|
||||
"render-small-resource-picker": {
|
||||
"set-icon": "Set icon"
|
||||
}
|
||||
|
|
@ -6634,6 +6646,7 @@
|
|||
"noOptionsMessage-no-fields-found": "No fields found"
|
||||
},
|
||||
"text-dimension-editor": {
|
||||
"aria-label-clear-value": "Clear value",
|
||||
"description-field": "Display field value",
|
||||
"description-fixed": "Fixed value",
|
||||
"label-field": "Field",
|
||||
|
|
@ -6771,7 +6784,8 @@
|
|||
},
|
||||
"content-outline-item-button": {
|
||||
"body": {
|
||||
"aria-label-content-outline-item-collapse-button": "Content outline item collapse button"
|
||||
"aria-label-content-outline-item-collapse-button": "Content outline item collapse button",
|
||||
"aria-label-content-outline-item-delete-button": "Delete item"
|
||||
}
|
||||
},
|
||||
"correlation-editor-mode-bar": {
|
||||
|
|
@ -6981,6 +6995,7 @@
|
|||
"content-streaming": "Streaming"
|
||||
},
|
||||
"logs-volume-panel-list": {
|
||||
"aria-label-reload-log-volume": "Reload log volume",
|
||||
"label-reload-log-volume": "Reload log volume",
|
||||
"loading": "Loading...",
|
||||
"title-failed-volume-query": "Failed to load log volume for this query",
|
||||
|
|
@ -7279,6 +7294,7 @@
|
|||
"split-widen": "Widen pane"
|
||||
},
|
||||
"trace-page-header": {
|
||||
"aria-label-share-dropdown": "Open share trace options menu",
|
||||
"duration": "Duration",
|
||||
"export-started": "Export started",
|
||||
"give-feedback": "Feedback",
|
||||
|
|
@ -7303,6 +7319,7 @@
|
|||
"label-show-paths": "Show critical path only switch"
|
||||
},
|
||||
"trace-view": {
|
||||
"aria-label-copy": "Copy to clipboard",
|
||||
"no-data": "No data",
|
||||
"tooltip-copy-icon": "Copied"
|
||||
},
|
||||
|
|
@ -7607,6 +7624,7 @@
|
|||
"title-symbol": "Symbol"
|
||||
},
|
||||
"measure-overlay": {
|
||||
"aria-label-close": "Close measure tools",
|
||||
"tooltip-show-measure-tools": "Show measure tools"
|
||||
},
|
||||
"name-initial-view": "Initial view",
|
||||
|
|
@ -8639,6 +8657,7 @@
|
|||
"csv-placeholder": "Enter CSV here...",
|
||||
"filter-placeholder": "Filter values",
|
||||
"filter-popup-apply": "Ok",
|
||||
"filter-popup-aria-label-match-case": "Match case",
|
||||
"filter-popup-cancel": "Cancel",
|
||||
"filter-popup-clear": "Clear filter",
|
||||
"filter-popup-heading": "Filter by values:",
|
||||
|
|
@ -11066,6 +11085,9 @@
|
|||
"check-repository": {
|
||||
"check": "Check"
|
||||
},
|
||||
"code-block": {
|
||||
"aria-label-copy": "Copy code to clipboard"
|
||||
},
|
||||
"config-form": {
|
||||
"alert-repository-settings-saved": "Repository settings saved",
|
||||
"alert-repository-settings-updated": "Repository settings updated",
|
||||
|
|
@ -13121,6 +13143,7 @@
|
|||
}
|
||||
},
|
||||
"filter-by-value-filter-editor": {
|
||||
"aria-label-remove-filter": "Remove filter",
|
||||
"label-field": "Field",
|
||||
"label-match": "Match",
|
||||
"label-value": "Value",
|
||||
|
|
|
|||
32
yarn.lock
32
yarn.lock
|
|
@ -2542,7 +2542,7 @@ __metadata:
|
|||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/i18n": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/schema": "npm:12.2.0-pre"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -2588,7 +2588,7 @@ __metadata:
|
|||
"@grafana/data": "npm:12.2.0-pre"
|
||||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/sql": "npm:12.2.0-pre"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -2702,7 +2702,7 @@ __metadata:
|
|||
"@grafana/e2e-selectors": "workspace:*"
|
||||
"@grafana/o11y-ds-frontend": "workspace:*"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/ui": "workspace:*"
|
||||
"@testing-library/dom": "npm:10.4.1"
|
||||
|
|
@ -2789,7 +2789,7 @@ __metadata:
|
|||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/i18n": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/sql": "npm:12.2.0-pre"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -2821,7 +2821,7 @@ __metadata:
|
|||
"@grafana/data": "npm:12.2.0-pre"
|
||||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/sql": "npm:12.2.0-pre"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -2887,7 +2887,7 @@ __metadata:
|
|||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/google-sdk": "npm:0.3.4"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/schema": "npm:12.2.0-pre"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -2936,7 +2936,7 @@ __metadata:
|
|||
"@grafana/monaco-logql": "npm:^0.0.8"
|
||||
"@grafana/o11y-ds-frontend": "workspace:*"
|
||||
"@grafana/plugin-configs": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/schema": "workspace:*"
|
||||
"@grafana/ui": "workspace:*"
|
||||
|
|
@ -2994,7 +2994,7 @@ __metadata:
|
|||
"@grafana/e2e-selectors": "workspace:*"
|
||||
"@grafana/o11y-ds-frontend": "workspace:*"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/ui": "workspace:*"
|
||||
"@testing-library/dom": "npm:10.4.1"
|
||||
|
|
@ -3379,7 +3379,7 @@ __metadata:
|
|||
"@emotion/css": "npm:11.13.5"
|
||||
"@grafana/data": "npm:12.2.0-pre"
|
||||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/schema": "npm:12.2.0-pre"
|
||||
"@grafana/tsconfig": "npm:^2.0.0"
|
||||
|
|
@ -3450,9 +3450,9 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/plugin-ui@npm:0.10.7, @grafana/plugin-ui@npm:^0.10.1":
|
||||
version: 0.10.7
|
||||
resolution: "@grafana/plugin-ui@npm:0.10.7"
|
||||
"@grafana/plugin-ui@npm:0.10.8, @grafana/plugin-ui@npm:^0.10.1":
|
||||
version: 0.10.8
|
||||
resolution: "@grafana/plugin-ui@npm:0.10.8"
|
||||
dependencies:
|
||||
"@emotion/css": "npm:^11.11.2"
|
||||
"@hello-pangea/dnd": "npm:^17.0.0"
|
||||
|
|
@ -3474,7 +3474,7 @@ __metadata:
|
|||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
rxjs: ^7.8.1
|
||||
checksum: 10/4fa878d042ef138cfb9fdcee7de883dca8e1e222f23f2ae852e98b18e0b095f8e741547d1c89c38c48f3274149a4d61515b4fc9ccfcaa77fa62221cb5b6ee0cf
|
||||
checksum: 10/3ef5eddd9a517fe2c7a0796f3d96dcd802153b625c46d7b2733f91f0378c6a8423022cae238b3bb6f554845f7e1bf63447ed8f9d3a6a5ada7d3df1e53c9cbf09
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -3487,7 +3487,7 @@ __metadata:
|
|||
"@grafana/data": "npm:12.2.0-pre"
|
||||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/i18n": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/schema": "npm:12.2.0-pre"
|
||||
"@grafana/tsconfig": "npm:^2.0.0"
|
||||
|
|
@ -3663,7 +3663,7 @@ __metadata:
|
|||
"@grafana/data": "npm:12.2.0-pre"
|
||||
"@grafana/e2e-selectors": "npm:12.2.0-pre"
|
||||
"@grafana/i18n": "npm:12.2.0-pre"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/runtime": "npm:12.2.0-pre"
|
||||
"@grafana/tsconfig": "npm:^2.0.0"
|
||||
"@grafana/ui": "npm:12.2.0-pre"
|
||||
|
|
@ -18219,7 +18219,7 @@ __metadata:
|
|||
"@grafana/monaco-logql": "npm:^0.0.8"
|
||||
"@grafana/o11y-ds-frontend": "workspace:*"
|
||||
"@grafana/plugin-e2e": "npm:2.1.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.7"
|
||||
"@grafana/plugin-ui": "npm:0.10.8"
|
||||
"@grafana/prometheus": "workspace:*"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/scenes": "npm:6.29.1"
|
||||
|
|
|
|||
Loading…
Reference in New Issue