mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 03:12:13 +08:00
GLDS: Text component (#71439)
This commit is contained in:
@ -125,7 +125,7 @@ export function Drawer({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.titleWrapper}>
|
<div className={styles.titleWrapper}>
|
||||||
<Text as="h3" {...titleProps}>
|
<Text element="h3" {...titleProps}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
{subtitle && <div className={styles.subtitle}>{subtitle}</div>}
|
{subtitle && <div className={styles.subtitle}>{subtitle}</div>}
|
||||||
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { StoryExample } from '../../utils/storybook/StoryExample';
|
import { StoryExample } from '../../utils/storybook/StoryExample';
|
||||||
import { VerticalGroup } from '../Layout/Layout';
|
import { VerticalGroup } from '../Layout/Layout';
|
||||||
import { P } from '../Text/TextElements';
|
import { Text } from '../Text/Text';
|
||||||
|
|
||||||
import { TextLink } from './TextLink';
|
import { TextLink } from './TextLink';
|
||||||
import mdx from './TextLink.mdx';
|
import mdx from './TextLink.mdx';
|
||||||
@ -44,13 +44,13 @@ export const Example: StoryFn = (args) => {
|
|||||||
return (
|
return (
|
||||||
<VerticalGroup>
|
<VerticalGroup>
|
||||||
<StoryExample name="This is a 'inline + external' link with the default behaviour">
|
<StoryExample name="This is a 'inline + external' link with the default behaviour">
|
||||||
<P>
|
<Text element="p">
|
||||||
To get started with a forever free Grafana Cloud account, sign up at  
|
To get started with a forever free Grafana Cloud account, sign up at  
|
||||||
<TextLink href="https://grafana.com/" {...args} inline>
|
<TextLink href="https://grafana.com/" {...args} inline>
|
||||||
grafana.com
|
grafana.com
|
||||||
</TextLink>
|
</TextLink>
|
||||||
.
|
.
|
||||||
</P>
|
</Text>
|
||||||
</StoryExample>
|
</StoryExample>
|
||||||
<StoryExample name="This is a 'standalone + external' link with the default behaviour">
|
<StoryExample name="This is a 'standalone + external' link with the default behaviour">
|
||||||
<TextLink href="https://grafana.com/docs/grafana/latest/" {...args}>
|
<TextLink href="https://grafana.com/docs/grafana/latest/" {...args}>
|
||||||
@ -58,7 +58,9 @@ export const Example: StoryFn = (args) => {
|
|||||||
</TextLink>
|
</TextLink>
|
||||||
</StoryExample>
|
</StoryExample>
|
||||||
<hr />
|
<hr />
|
||||||
<P>*The examples cannot contemplate an internal link due to conflicts between Storybook and React Router</P>
|
<Text element="p">
|
||||||
|
*The examples cannot contemplate an internal link due to conflicts between Storybook and React Router
|
||||||
|
</Text>
|
||||||
</VerticalGroup>
|
</VerticalGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@ import { VerticalGroup } from '../Layout/Layout';
|
|||||||
|
|
||||||
import { Text } from './Text';
|
import { Text } from './Text';
|
||||||
import mdx from './Text.mdx';
|
import mdx from './Text.mdx';
|
||||||
import { H1, H2, H3, H4, H5, H6, Span, P, Legend, TextModifier } from './TextElements';
|
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta = {
|
||||||
title: 'General/Text',
|
title: 'General/Text',
|
||||||
@ -15,7 +14,6 @@ const meta: Meta = {
|
|||||||
docs: {
|
docs: {
|
||||||
page: mdx,
|
page: mdx,
|
||||||
},
|
},
|
||||||
controls: { exclude: ['as'] },
|
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
variant: { control: 'select', options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'body', 'bodySmall', undefined] },
|
variant: { control: 'select', options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'body', 'bodySmall', undefined] },
|
||||||
@ -39,93 +37,73 @@ const meta: Meta = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
truncate: { control: 'boolean' },
|
truncate: { control: 'boolean' },
|
||||||
|
italic: { control: 'boolean' },
|
||||||
textAlignment: {
|
textAlignment: {
|
||||||
control: 'select',
|
control: 'select',
|
||||||
options: ['inherit', 'initial', 'left', 'right', 'center', 'justify', undefined],
|
options: ['inherit', 'initial', 'left', 'right', 'center', 'justify', undefined],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
args: {
|
||||||
|
element: 'h1',
|
||||||
|
variant: undefined,
|
||||||
|
weight: 'light',
|
||||||
|
textAlignment: 'left',
|
||||||
|
truncate: false,
|
||||||
|
italic: false,
|
||||||
|
color: 'primary',
|
||||||
|
children: `This is an example of a Text component`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Example: StoryFn = () => {
|
export const Example: StoryFn = (args) => {
|
||||||
return (
|
return (
|
||||||
<VerticalGroup>
|
<VerticalGroup>
|
||||||
<StoryExample name="Header, paragraph, span and legend elements">
|
<StoryExample name="Header, paragraph and span">
|
||||||
<H1>h1. Heading</H1>
|
<Text {...args} element="h1">
|
||||||
<H2>h2. Heading</H2>
|
This is a header
|
||||||
<H3>h3. Heading</H3>
|
</Text>
|
||||||
<H4>h4. Heading</H4>
|
<Text {...args} element="p">
|
||||||
<H5>h5. Heading</H5>
|
This is a paragraph that contains
|
||||||
<H6>h6. Heading</H6>
|
<Text color="success" italic>
|
||||||
<P>This is a paragraph</P>
|
{' '}
|
||||||
<Legend>This is a legend</Legend>
|
a span element with different color and style{' '}
|
||||||
<Span>This is a span</Span>
|
</Text>
|
||||||
|
but is comprised within the same block text
|
||||||
|
</Text>
|
||||||
|
</StoryExample>
|
||||||
|
<StoryExample name="Paragraph with truncate set to true and wrapping up a span element">
|
||||||
|
<Text {...args} element="p" truncate>
|
||||||
|
This is a paragraph that contains
|
||||||
|
<Text color="warning" italic>
|
||||||
|
{' '}
|
||||||
|
a span element{' '}
|
||||||
|
</Text>
|
||||||
|
but has truncate set to true
|
||||||
|
</Text>
|
||||||
</StoryExample>
|
</StoryExample>
|
||||||
</VerticalGroup>
|
</VerticalGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Example.parameters = {
|
Example.parameters = {
|
||||||
controls: {
|
controls: {
|
||||||
exclude: ['variant', 'weight', 'textAlignment', 'truncate', 'color', 'children'],
|
exclude: ['element', 'variant', 'weight', 'textAlignment', 'truncate', 'italic', 'color', 'children'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HeadingComponent: StoryFn = (args) => {
|
export const Basic: StoryFn = (args) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ width: '300px' }}>
|
<div style={{ width: '300px' }}>
|
||||||
<H1 variant={args.variant} weight={args.weight} textAlignment={args.textAlignment} {...args}>
|
<Text
|
||||||
|
element={args.element}
|
||||||
|
variant={args.variant}
|
||||||
|
weight={args.weight}
|
||||||
|
textAlignment={args.textAlignment}
|
||||||
|
{...args}
|
||||||
|
>
|
||||||
{args.children}
|
{args.children}
|
||||||
</H1>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
HeadingComponent.args = {
|
|
||||||
variant: undefined,
|
|
||||||
weight: 'light',
|
|
||||||
textAlignment: 'center',
|
|
||||||
truncate: false,
|
|
||||||
color: 'primary',
|
|
||||||
children: 'This is a H1 component',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LegendComponent: StoryFn = (args) => {
|
|
||||||
return (
|
|
||||||
<div style={{ width: '300px' }}>
|
|
||||||
<Legend variant={args.variant} weight={args.weight} textAlignment={args.textAlignment} {...args}>
|
|
||||||
{args.children}
|
|
||||||
</Legend>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
LegendComponent.args = {
|
|
||||||
variant: undefined,
|
|
||||||
weight: 'bold',
|
|
||||||
textAlignment: 'center',
|
|
||||||
truncate: false,
|
|
||||||
color: 'error',
|
|
||||||
children: 'This is a lengend component',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TextModifierComponent: StoryFn = (args) => {
|
|
||||||
return (
|
|
||||||
<div style={{ width: '300px' }}>
|
|
||||||
<H6 variant={args.variant} weight={args.weight} textAlignment={args.textAlignment} {...args}>
|
|
||||||
{args.children}{' '}
|
|
||||||
<TextModifier weight="bold" color="error">
|
|
||||||
{' '}
|
|
||||||
with a part of its text modified{' '}
|
|
||||||
</TextModifier>
|
|
||||||
</H6>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
TextModifierComponent.args = {
|
|
||||||
variant: undefined,
|
|
||||||
weight: 'light',
|
|
||||||
textAlignment: 'center',
|
|
||||||
truncate: false,
|
|
||||||
color: 'maxContrast',
|
|
||||||
children: 'This is a H6 component',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
@ -7,13 +7,13 @@ import { Text } from './Text';
|
|||||||
|
|
||||||
describe('Text', () => {
|
describe('Text', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
render(<Text as={'h1'}>This is a text component</Text>);
|
render(<Text element={'h1'}>This is a text component</Text>);
|
||||||
expect(screen.getByText('This is a text component')).toBeInTheDocument();
|
expect(screen.getByText('This is a text component')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
it('keeps the element type but changes its styles', () => {
|
it('keeps the element type but changes its styles', () => {
|
||||||
const customVariant: keyof ThemeTypographyVariantTypes = 'body';
|
const customVariant: keyof ThemeTypographyVariantTypes = 'body';
|
||||||
render(
|
render(
|
||||||
<Text as={'h1'} variant={customVariant}>
|
<Text element={'h1'} variant={customVariant}>
|
||||||
This is a text component
|
This is a text component
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
@ -26,7 +26,7 @@ describe('Text', () => {
|
|||||||
const customColor = 'info';
|
const customColor = 'info';
|
||||||
const theme = createTheme();
|
const theme = createTheme();
|
||||||
render(
|
render(
|
||||||
<Text as={'h1'} color={customColor}>
|
<Text element={'h1'} color={customColor}>
|
||||||
This is a text component
|
This is a text component
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
@ -5,11 +5,11 @@ import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
|
|||||||
|
|
||||||
import { useStyles2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
import { customWeight, customColor } from './utils';
|
import { customWeight, customColor, customVariant } from './utils';
|
||||||
|
|
||||||
export interface TextProps {
|
export interface TextProps {
|
||||||
/** Defines what HTML element is defined underneath */
|
/** Defines what HTML element is defined underneath. "span" by default */
|
||||||
as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p' | 'legend';
|
element?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p';
|
||||||
/** What typograpy variant should be used for the component. Only use if default variant for the defined element is not what is needed */
|
/** What typograpy variant should be used for the component. Only use if default variant for the defined element is not what is needed */
|
||||||
variant?: keyof ThemeTypographyVariantTypes;
|
variant?: keyof ThemeTypographyVariantTypes;
|
||||||
/** Override the default weight for the used variant */
|
/** Override the default weight for the used variant */
|
||||||
@ -18,22 +18,24 @@ export interface TextProps {
|
|||||||
color?: keyof GrafanaTheme2['colors']['text'] | 'error' | 'success' | 'warning' | 'info';
|
color?: keyof GrafanaTheme2['colors']['text'] | 'error' | 'success' | 'warning' | 'info';
|
||||||
/** Use to cut the text off with ellipsis if there isn't space to show all of it. On hover shows the rest of the text */
|
/** Use to cut the text off with ellipsis if there isn't space to show all of it. On hover shows the rest of the text */
|
||||||
truncate?: boolean;
|
truncate?: boolean;
|
||||||
|
/** If true, show the text as italic. False by default */
|
||||||
|
italic?: boolean;
|
||||||
/** Whether to align the text to left, center or right */
|
/** Whether to align the text to left, center or right */
|
||||||
textAlignment?: CSSProperties['textAlign'];
|
textAlignment?: CSSProperties['textAlign'];
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Text = React.forwardRef<HTMLElement, TextProps>(
|
export const Text = React.forwardRef<HTMLElement, TextProps>(
|
||||||
({ as, variant, weight, color, truncate, textAlignment, children }, ref) => {
|
({ element = 'span', variant, weight, color, truncate, italic, textAlignment, children }, ref) => {
|
||||||
const styles = useStyles2(
|
const styles = useStyles2(
|
||||||
useCallback(
|
useCallback(
|
||||||
(theme) => getTextStyles(theme, variant, color, weight, truncate, textAlignment),
|
(theme) => getTextStyles(theme, element, variant, color, weight, truncate, italic, textAlignment),
|
||||||
[color, textAlignment, truncate, weight, variant]
|
[color, textAlignment, truncate, italic, weight, variant, element]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return createElement(
|
return createElement(
|
||||||
as,
|
element,
|
||||||
{
|
{
|
||||||
className: styles,
|
className: styles,
|
||||||
ref,
|
ref,
|
||||||
@ -47,19 +49,22 @@ Text.displayName = 'Text';
|
|||||||
|
|
||||||
const getTextStyles = (
|
const getTextStyles = (
|
||||||
theme: GrafanaTheme2,
|
theme: GrafanaTheme2,
|
||||||
|
element?: TextProps['element'],
|
||||||
variant?: keyof ThemeTypographyVariantTypes,
|
variant?: keyof ThemeTypographyVariantTypes,
|
||||||
color?: TextProps['color'],
|
color?: TextProps['color'],
|
||||||
weight?: TextProps['weight'],
|
weight?: TextProps['weight'],
|
||||||
truncate?: TextProps['truncate'],
|
truncate?: TextProps['truncate'],
|
||||||
|
italic?: TextProps['italic'],
|
||||||
textAlignment?: TextProps['textAlignment']
|
textAlignment?: TextProps['textAlignment']
|
||||||
) => {
|
) => {
|
||||||
return css([
|
return css([
|
||||||
variant && {
|
|
||||||
...theme.typography[variant],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
|
...customVariant(theme, element, variant),
|
||||||
|
},
|
||||||
|
variant && {
|
||||||
|
...theme.typography[variant],
|
||||||
},
|
},
|
||||||
color && {
|
color && {
|
||||||
color: customColor(color, theme),
|
color: customColor(color, theme),
|
||||||
@ -72,6 +77,9 @@ const getTextStyles = (
|
|||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
},
|
},
|
||||||
|
italic && {
|
||||||
|
fontStyle: 'italic',
|
||||||
|
},
|
||||||
textAlignment && {
|
textAlignment && {
|
||||||
textAlign: textAlignment,
|
textAlign: textAlignment,
|
||||||
},
|
},
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
|
||||||
|
|
||||||
import { Text, TextProps } from './Text';
|
|
||||||
|
|
||||||
interface TextElementsProps extends Omit<TextProps, 'as'> {}
|
|
||||||
|
|
||||||
interface TextModifierProps {
|
|
||||||
/** Override the default weight for the used variant */
|
|
||||||
weight?: 'light' | 'regular' | 'medium' | 'bold';
|
|
||||||
/** Color to use for text */
|
|
||||||
color?: keyof GrafanaTheme2['colors']['text'] | 'error' | 'success' | 'warning' | 'info';
|
|
||||||
children: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const H1 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h1" {...props} variant={props.variant || 'h1'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H1.displayName = 'H1';
|
|
||||||
|
|
||||||
export const H2 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h2" {...props} variant={props.variant || 'h2'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H2.displayName = 'H2';
|
|
||||||
|
|
||||||
export const H3 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h3" {...props} variant={props.variant || 'h3'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H3.displayName = 'H3';
|
|
||||||
|
|
||||||
export const H4 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h4" {...props} variant={props.variant || 'h4'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H4.displayName = 'H4';
|
|
||||||
|
|
||||||
export const H5 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h5" {...props} variant={props.variant || 'h5'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H5.displayName = 'H5';
|
|
||||||
|
|
||||||
export const H6 = React.forwardRef<HTMLHeadingElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="h6" {...props} variant={props.variant || 'h6'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
H6.displayName = 'H6';
|
|
||||||
|
|
||||||
export const P = React.forwardRef<HTMLParagraphElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="p" {...props} variant={props.variant || 'body'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
P.displayName = 'P';
|
|
||||||
|
|
||||||
export const Span = React.forwardRef<HTMLSpanElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="span" {...props} variant={props.variant || 'bodySmall'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
Span.displayName = 'Span';
|
|
||||||
|
|
||||||
export const Legend = React.forwardRef<HTMLLegendElement, TextElementsProps>((props, ref) => {
|
|
||||||
return <Text as="legend" {...props} variant={props.variant || 'bodySmall'} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
Legend.displayName = 'Legend';
|
|
||||||
|
|
||||||
export const TextModifier = React.forwardRef<HTMLSpanElement, TextModifierProps>((props, ref) => {
|
|
||||||
return <Text as="span" {...props} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
TextModifier.displayName = 'TextModifier';
|
|
@ -1,4 +1,4 @@
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
|
||||||
|
|
||||||
import { TextProps } from './Text';
|
import { TextProps } from './Text';
|
||||||
|
|
||||||
@ -30,3 +30,32 @@ export const customColor = (color: TextProps['color'], theme: GrafanaTheme2): st
|
|||||||
return color ? theme.colors.text[color] : undefined;
|
return color ? theme.colors.text[color] : undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const customVariant = (
|
||||||
|
theme: GrafanaTheme2,
|
||||||
|
element: TextProps['element'],
|
||||||
|
variant?: keyof ThemeTypographyVariantTypes
|
||||||
|
) => {
|
||||||
|
if (variant) {
|
||||||
|
return theme.typography[variant];
|
||||||
|
}
|
||||||
|
switch (element) {
|
||||||
|
//Span elements does not have a default variant to be able to take the parents style
|
||||||
|
case 'span':
|
||||||
|
return;
|
||||||
|
case 'h1':
|
||||||
|
return theme.typography.h1;
|
||||||
|
case 'h2':
|
||||||
|
return theme.typography.h2;
|
||||||
|
case 'h3':
|
||||||
|
return theme.typography.h3;
|
||||||
|
case 'h4':
|
||||||
|
return theme.typography.h4;
|
||||||
|
case 'h5':
|
||||||
|
return theme.typography.h5;
|
||||||
|
case 'h6':
|
||||||
|
return theme.typography.h6;
|
||||||
|
default:
|
||||||
|
return theme.typography.body;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -9,4 +9,4 @@
|
|||||||
* be subject to the standard policies
|
* be subject to the standard policies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './components/Text/TextElements';
|
export * from './components/Text/Text';
|
||||||
|
@ -5,7 +5,7 @@ import { useToggle } from 'react-use';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { Button, Drawer, ToolbarButton, useStyles2 } from '@grafana/ui';
|
import { Button, Drawer, ToolbarButton, useStyles2 } from '@grafana/ui';
|
||||||
import { H3 } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants';
|
import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants';
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export function NewsContainer({ className }: NewsContainerProps) {
|
|||||||
<Drawer
|
<Drawer
|
||||||
title={
|
title={
|
||||||
<div className={styles.title}>
|
<div className={styles.title}>
|
||||||
<H3>{t('news.title', 'Latest from the blog')}</H3>
|
<Text element="h3">{t('news.title', 'Latest from the blog')}</Text>
|
||||||
<a
|
<a
|
||||||
href="https://grafana.com/blog/"
|
href="https://grafana.com/blog/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -209,9 +209,8 @@ function Row({ index, style: virtualStyles, data }: RowProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<label className={styles.label} id={labelId}>
|
<label className={styles.label} id={labelId}>
|
||||||
<Text as="span" truncate>
|
{/* TODO: text is not truncated properly, it still overflows the container */}
|
||||||
{item.title}
|
<Text truncate>{item.title}</Text>
|
||||||
</Text>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@ import { useAsync } from 'react-use';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Alert, Button, Icon, Input, LoadingBar, useStyles2 } from '@grafana/ui';
|
import { Alert, Button, Icon, Input, LoadingBar, useStyles2 } from '@grafana/ui';
|
||||||
import { Text } from '@grafana/ui/src/components/Text/Text';
|
import { Text } from '@grafana/ui/src/components/Text/Text';
|
||||||
import { Trans, t } from 'app/core/internationalization';
|
import { t, Trans } from 'app/core/internationalization';
|
||||||
import { skipToken, useGetFolderQuery } from 'app/features/browse-dashboards/api/browseDashboardsAPI';
|
import { skipToken, useGetFolderQuery } from 'app/features/browse-dashboards/api/browseDashboardsAPI';
|
||||||
import { PAGE_SIZE } from 'app/features/browse-dashboards/api/services';
|
import { PAGE_SIZE } from 'app/features/browse-dashboards/api/services';
|
||||||
import {
|
import {
|
||||||
@ -209,7 +209,7 @@ export function NestedFolderPicker({ value, onChange }: NestedFolderPickerProps)
|
|||||||
{selectedFolder.isLoading ? (
|
{selectedFolder.isLoading ? (
|
||||||
<Skeleton width={100} />
|
<Skeleton width={100} />
|
||||||
) : (
|
) : (
|
||||||
<Text as="span" truncate>
|
<Text truncate>
|
||||||
{label ?? <Trans i18nKey="browse-dashboards.folder-picker.button-label">Select folder</Trans>}
|
{label ?? <Trans i18nKey="browse-dashboards.folder-picker.button-label">Select folder</Trans>}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { isFetchError } from '@grafana/runtime';
|
import { isFetchError } from '@grafana/runtime';
|
||||||
import { Field, IconButton, Input, useStyles2 } from '@grafana/ui';
|
import { Field, IconButton, Input, useStyles2 } from '@grafana/ui';
|
||||||
import { H1 } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
value: string;
|
value: string;
|
||||||
@ -61,7 +61,9 @@ export const EditableTitle = ({ value, onEdit }: Props) => {
|
|||||||
this is to prevent the title from flickering back to the old value after the user has edited
|
this is to prevent the title from flickering back to the old value after the user has edited
|
||||||
caused by the delay between the save completing and the new value being refetched
|
caused by the delay between the save completing and the new value being refetched
|
||||||
*/}
|
*/}
|
||||||
<H1 truncate>{localValue}</H1>
|
<Text element="h1" truncate>
|
||||||
|
{localValue}
|
||||||
|
</Text>
|
||||||
<IconButton name="pen" size="lg" tooltip="Edit title" onClick={() => setIsEditing(true)} />
|
<IconButton name="pen" size="lg" tooltip="Edit title" onClick={() => setIsEditing(true)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,11 +3,11 @@ import React, { ComponentProps, HTMLAttributes } from 'react';
|
|||||||
|
|
||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { Icon, IconName, useStyles2 } from '@grafana/ui';
|
import { Icon, IconName, useStyles2 } from '@grafana/ui';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
|
|
||||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||||
icon?: IconName;
|
icon?: IconName;
|
||||||
color?: ComponentProps<typeof Span>['color'];
|
color?: ComponentProps<typeof Text>['color'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MetaText = ({ children, icon, color = 'secondary', ...rest }: Props) => {
|
const MetaText = ({ children, icon, color = 'secondary', ...rest }: Props) => {
|
||||||
@ -22,12 +22,12 @@ const MetaText = ({ children, icon, color = 'secondary', ...rest }: Props) => {
|
|||||||
// allow passing ARIA and data- attributes
|
// allow passing ARIA and data- attributes
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Span variant="bodySmall" color={color}>
|
<Text color={color}>
|
||||||
<Stack direction="row" alignItems="center" gap={0.5}>
|
<Stack direction="row" alignItems="center" gap={0.5}>
|
||||||
{icon && <Icon name={icon} />}
|
{icon && <Icon name={icon} />}
|
||||||
{children}
|
{children}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Span>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import React from 'react';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { Button, Dropdown, Icon, Menu, Tooltip, useStyles2 } from '@grafana/ui';
|
import { Button, Dropdown, Icon, Menu, Tooltip, useStyles2 } from '@grafana/ui';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
|
import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
|
||||||
import { GrafanaNotifierType } from 'app/types/alerting';
|
import { GrafanaNotifierType } from 'app/types/alerting';
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ const ContactPointHeader = (props: ContactPointHeaderProps) => {
|
|||||||
<div className={styles.headerWrapper}>
|
<div className={styles.headerWrapper}>
|
||||||
<Stack direction="row" alignItems="center" gap={1}>
|
<Stack direction="row" alignItems="center" gap={1}>
|
||||||
<Stack alignItems="center" gap={1}>
|
<Stack alignItems="center" gap={1}>
|
||||||
<Span variant="body">{name}</Span>
|
<Text variant="body">{name}</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
{policies.length > 0 ? (
|
{policies.length > 0 ? (
|
||||||
<MetaText>
|
<MetaText>
|
||||||
@ -179,14 +179,14 @@ const ContactPointReceiver = (props: ContactPointReceiverProps) => {
|
|||||||
<Stack direction="row" alignItems="center" gap={1}>
|
<Stack direction="row" alignItems="center" gap={1}>
|
||||||
<Stack direction="row" alignItems="center" gap={0.5}>
|
<Stack direction="row" alignItems="center" gap={0.5}>
|
||||||
{iconName && <Icon name={iconName} />}
|
{iconName && <Icon name={iconName} />}
|
||||||
<Span variant="body" color="primary">
|
<Text variant="body" color="primary">
|
||||||
{type}
|
{type}
|
||||||
</Span>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
{description && (
|
{description && (
|
||||||
<Span variant="bodySmall" color="secondary">
|
<Text variant="bodySmall" color="secondary">
|
||||||
{description}
|
{description}
|
||||||
</Span>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
@ -196,7 +196,7 @@ const ContactPointReceiver = (props: ContactPointReceiverProps) => {
|
|||||||
<>
|
<>
|
||||||
{/* TODO we might need an error variant for MetaText, dito for success */}
|
{/* TODO we might need an error variant for MetaText, dito for success */}
|
||||||
{/* TODO show error details on hover or elsewhere */}
|
{/* TODO show error details on hover or elsewhere */}
|
||||||
<Span color="error" variant="bodySmall" weight="bold">
|
<Text color="error" variant="bodySmall" weight="bold">
|
||||||
<Stack direction="row" alignItems={'center'} gap={0.5}>
|
<Stack direction="row" alignItems={'center'} gap={0.5}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
@ -208,7 +208,7 @@ const ContactPointReceiver = (props: ContactPointReceiverProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Span>
|
</Text>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -7,7 +7,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { Badge, Button, Dropdown, getTagColorsFromName, Icon, Menu, Tooltip, useStyles2 } from '@grafana/ui';
|
import { Badge, Button, Dropdown, getTagColorsFromName, Icon, Menu, Tooltip, useStyles2 } from '@grafana/ui';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
|
import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
|
||||||
import { RouteWithID, Receiver, ObjectMatcher, AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
|
import { RouteWithID, Receiver, ObjectMatcher, AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
|
||||||
@ -554,17 +554,17 @@ const routePropertyToValue = (
|
|||||||
|
|
||||||
if (isNotGrouping) {
|
if (isNotGrouping) {
|
||||||
return (
|
return (
|
||||||
<Span variant="bodySmall" color="secondary">
|
<Text variant="bodySmall" color="secondary">
|
||||||
Not grouping
|
Not grouping
|
||||||
</Span>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSingleGroup) {
|
if (isSingleGroup) {
|
||||||
return (
|
return (
|
||||||
<Span variant="bodySmall" color="secondary">
|
<Text variant="bodySmall" color="secondary">
|
||||||
Single group
|
Single group
|
||||||
</Span>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import React, { lazy, Suspense } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Button, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
import { Button, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||||
import { H4 } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { alertRuleApi } from 'app/features/alerting/unified/api/alertRuleApi';
|
import { alertRuleApi } from 'app/features/alerting/unified/api/alertRuleApi';
|
||||||
import { Stack } from 'app/plugins/datasource/parca/QueryEditor/Stack';
|
import { Stack } from 'app/plugins/datasource/parca/QueryEditor/Stack';
|
||||||
import { AlertQuery } from 'app/types/unified-alerting-dto';
|
import { AlertQuery } from 'app/types/unified-alerting-dto';
|
||||||
@ -67,7 +67,7 @@ export const NotificationPreview = ({
|
|||||||
<Stack direction="column" gap={2}>
|
<Stack direction="column" gap={2}>
|
||||||
<div className={styles.routePreviewHeaderRow}>
|
<div className={styles.routePreviewHeaderRow}>
|
||||||
<div className={styles.previewHeader}>
|
<div className={styles.previewHeader}>
|
||||||
<H4>Alert instance routing preview</H4>
|
<Text element="h4">Alert instance routing preview</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.button}>
|
<div className={styles.button}>
|
||||||
<Button icon="sync" variant="secondary" type="button" onClick={onPreview}>
|
<Button icon="sync" variant="secondary" type="button" onClick={onPreview}>
|
||||||
|
@ -8,7 +8,7 @@ import { selectors } from '@grafana/e2e-selectors';
|
|||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { config, getDataSourceSrv } from '@grafana/runtime';
|
import { config, getDataSourceSrv } from '@grafana/runtime';
|
||||||
import { Alert, Button, Dropdown, Field, Icon, InputControl, Menu, MenuItem, Tooltip, useStyles2 } from '@grafana/ui';
|
import { Alert, Button, Dropdown, Field, Icon, InputControl, Menu, MenuItem, Tooltip, useStyles2 } from '@grafana/ui';
|
||||||
import { H5 } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/components/Text/Text';
|
||||||
import { isExpressionQuery } from 'app/features/expressions/guards';
|
import { isExpressionQuery } from 'app/features/expressions/guards';
|
||||||
import { ExpressionDatasourceUID, ExpressionQueryType, expressionTypes } from 'app/features/expressions/types';
|
import { ExpressionDatasourceUID, ExpressionQueryType, expressionTypes } from 'app/features/expressions/types';
|
||||||
import { useDispatch } from 'app/types';
|
import { useDispatch } from 'app/types';
|
||||||
@ -435,8 +435,8 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange }: P
|
|||||||
onClickSwitch={onClickSwitch}
|
onClickSwitch={onClickSwitch}
|
||||||
/>
|
/>
|
||||||
{/* Expression Queries */}
|
{/* Expression Queries */}
|
||||||
<H5>Expressions</H5>
|
<Text element="h5">Expressions</Text>
|
||||||
<div className={styles.mutedText}>Manipulate data returned from queries with math and other operations.</div>
|
<div className={styles.mutedText}>Manipulate data returned from queries with math and other operations</div>
|
||||||
<ExpressionsEditor
|
<ExpressionsEditor
|
||||||
queries={queries}
|
queries={queries}
|
||||||
panelData={queryPreviewData}
|
panelData={queryPreviewData}
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||||||
|
|
||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { Alert, Button, Icon, LoadingPlaceholder, Tab, TabContent, TabsBar } from '@grafana/ui';
|
import { Alert, Button, Icon, LoadingPlaceholder, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||||
import { H1, Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||||
import { GrafanaAlertState } from 'app/types/unified-alerting-dto';
|
import { GrafanaAlertState } from 'app/types/unified-alerting-dto';
|
||||||
|
|
||||||
@ -129,18 +129,18 @@ interface BreadcrumbProps {
|
|||||||
|
|
||||||
const BreadCrumb = ({ folder, evaluationGroup }: BreadcrumbProps) => (
|
const BreadCrumb = ({ folder, evaluationGroup }: BreadcrumbProps) => (
|
||||||
<Stack alignItems="center" gap={0.5}>
|
<Stack alignItems="center" gap={0.5}>
|
||||||
<Span color="secondary">
|
<Text color="secondary">
|
||||||
<Icon name="folder" />
|
<Icon name="folder" />
|
||||||
</Span>
|
</Text>
|
||||||
<Span variant="body" color="primary">
|
<Text variant="body" color="primary">
|
||||||
{folder}
|
{folder}
|
||||||
</Span>
|
</Text>
|
||||||
<Span variant="body" color="secondary">
|
<Text variant="body" color="secondary">
|
||||||
<Icon name="angle-right" />
|
<Icon name="angle-right" />
|
||||||
</Span>
|
</Text>
|
||||||
<Span variant="body" color="primary">
|
<Text variant="body" color="primary">
|
||||||
{evaluationGroup}
|
{evaluationGroup}
|
||||||
</Span>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -154,9 +154,9 @@ const Title = ({ name, state }: TitleProps) => (
|
|||||||
<Stack alignItems={'center'} gap={1}>
|
<Stack alignItems={'center'} gap={1}>
|
||||||
<AlertStateDot size="md" state={state} />
|
<AlertStateDot size="md" state={state} />
|
||||||
{/* <Button variant="secondary" fill="outline" icon="angle-left" /> */}
|
{/* <Button variant="secondary" fill="outline" icon="angle-left" /> */}
|
||||||
<H1 variant="h2" weight="bold">
|
<Text element="h1" variant="h2" weight="bold">
|
||||||
{name}
|
{name}
|
||||||
</H1>
|
</Text>
|
||||||
{/* <Badge color="red" text={state} icon="exclamation-circle" /> */}
|
{/* <Badge color="red" text={state} icon="exclamation-circle" /> */}
|
||||||
</Stack>
|
</Stack>
|
||||||
</header>
|
</header>
|
||||||
@ -167,9 +167,9 @@ interface SummaryProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Summary = ({ text }: SummaryProps) => (
|
const Summary = ({ text }: SummaryProps) => (
|
||||||
<Span variant="body" color="secondary">
|
<Text variant="body" color="secondary">
|
||||||
{text}
|
{text}
|
||||||
</Span>
|
</Text>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default RuleViewer;
|
export default RuleViewer;
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||||||
|
|
||||||
import { Space } from '@grafana/experimental';
|
import { Space } from '@grafana/experimental';
|
||||||
import { ConfirmModal } from '@grafana/ui';
|
import { ConfirmModal } from '@grafana/ui';
|
||||||
import { P } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { Trans, t } from 'app/core/internationalization';
|
import { Trans, t } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { DashboardTreeSelection } from '../../types';
|
import { DashboardTreeSelection } from '../../types';
|
||||||
@ -33,11 +33,11 @@ export const DeleteModal = ({ onConfirm, onDismiss, selectedItems, ...props }: P
|
|||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
body={
|
body={
|
||||||
<>
|
<>
|
||||||
<P>
|
<Text element="p">
|
||||||
<Trans i18nKey="browse-dashboards.action.delete-modal-text">
|
<Trans i18nKey="browse-dashboards.action.delete-modal-text">
|
||||||
This action will delete the following content:
|
This action will delete the following content:
|
||||||
</Trans>
|
</Trans>
|
||||||
</P>
|
</Text>
|
||||||
<DescendantCount selectedItems={selectedItems} />
|
<DescendantCount selectedItems={selectedItems} />
|
||||||
<Space v={2} />
|
<Space v={2} />
|
||||||
</>
|
</>
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import Skeleton from 'react-loading-skeleton';
|
import Skeleton from 'react-loading-skeleton';
|
||||||
|
|
||||||
import { Alert } from '@grafana/ui';
|
import { Alert } from '@grafana/ui';
|
||||||
import { P } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
|
|
||||||
import { useGetAffectedItemsQuery } from '../../api/browseDashboardsAPI';
|
import { useGetAffectedItemsQuery } from '../../api/browseDashboardsAPI';
|
||||||
import { DashboardTreeSelection } from '../../types';
|
import { DashboardTreeSelection } from '../../types';
|
||||||
@ -18,10 +18,10 @@ export const DescendantCount = ({ selectedItems }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<P color="secondary">
|
<Text element="p" color="secondary">
|
||||||
{data && buildBreakdownString(data.folder, data.dashboard, data.libraryPanel, data.alertRule)}
|
{data && buildBreakdownString(data.folder, data.dashboard, data.libraryPanel, data.alertRule)}
|
||||||
{(isFetching || isLoading) && <Skeleton width={200} />}
|
{(isFetching || isLoading) && <Skeleton width={200} />}
|
||||||
</P>
|
</Text>
|
||||||
{error && <Alert severity="error" title="Unable to retrieve descendant information" />}
|
{error && <Alert severity="error" title="Unable to retrieve descendant information" />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
|||||||
import { Space } from '@grafana/experimental';
|
import { Space } from '@grafana/experimental';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { Alert, Button, Field, Modal } from '@grafana/ui';
|
import { Alert, Button, Field, Modal } from '@grafana/ui';
|
||||||
import { P } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { NestedFolderPicker } from 'app/core/components/NestedFolderPicker/NestedFolderPicker';
|
import { NestedFolderPicker } from 'app/core/components/NestedFolderPicker/NestedFolderPicker';
|
||||||
import { FolderChange } from 'app/core/components/NestedFolderPicker/types';
|
import { FolderChange } from 'app/core/components/NestedFolderPicker/types';
|
||||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||||
@ -51,9 +51,9 @@ export const MoveModal = ({ onConfirm, onDismiss, selectedItems, ...props }: Pro
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<P>
|
<Text element="p">
|
||||||
<Trans i18nKey="browse-dashboards.action.move-modal-text">This action will move the following content:</Trans>
|
<Trans i18nKey="browse-dashboards.action.move-modal-text">This action will move the following content:</Trans>
|
||||||
</P>
|
</Text>
|
||||||
|
|
||||||
<DescendantCount selectedItems={selectedItems} />
|
<DescendantCount selectedItems={selectedItems} />
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
|||||||
import { reportInteraction } from '@grafana/runtime';
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { Icon, IconButton, Link, Spinner, useStyles2 } from '@grafana/ui';
|
import { Icon, IconButton, Link, Spinner, useStyles2 } from '@grafana/ui';
|
||||||
import { getSvgSize } from '@grafana/ui/src/components/Icon/utils';
|
import { getSvgSize } from '@grafana/ui/src/components/Icon/utils';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { getIconForKind } from 'app/features/search/service/utils';
|
import { getIconForKind } from 'app/features/search/service/utils';
|
||||||
|
|
||||||
import { useChildrenByParentUIDState } from '../state';
|
import { useChildrenByParentUIDState } from '../state';
|
||||||
@ -36,9 +36,9 @@ export function NameCell({ row: { original: data }, onFolderClick }: NameCellPro
|
|||||||
<span className={styles.folderButtonSpacer} />
|
<span className={styles.folderButtonSpacer} />
|
||||||
{item.uiKind === 'empty-folder' ? (
|
{item.uiKind === 'empty-folder' ? (
|
||||||
<em className={styles.emptyText}>
|
<em className={styles.emptyText}>
|
||||||
<Span variant="body" color="secondary" truncate>
|
<Text variant="body" color="secondary" truncate>
|
||||||
No items
|
No items
|
||||||
</Span>
|
</Text>
|
||||||
</em>
|
</em>
|
||||||
) : (
|
) : (
|
||||||
<Skeleton width={200} />
|
<Skeleton width={200} />
|
||||||
@ -66,7 +66,7 @@ export function NameCell({ row: { original: data }, onFolderClick }: NameCellPro
|
|||||||
)}
|
)}
|
||||||
<div className={styles.iconNameContainer}>
|
<div className={styles.iconNameContainer}>
|
||||||
{isLoading ? <Spinner size={ICON_SIZE} /> : <Icon size={ICON_SIZE} name={iconName} />}
|
{isLoading ? <Spinner size={ICON_SIZE} /> : <Icon size={ICON_SIZE} name={iconName} />}
|
||||||
<Span variant="body" truncate>
|
<Text variant="body" truncate>
|
||||||
{item.url ? (
|
{item.url ? (
|
||||||
<Link
|
<Link
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -80,7 +80,7 @@ export function NameCell({ row: { original: data }, onFolderClick }: NameCellPro
|
|||||||
) : (
|
) : (
|
||||||
item.title
|
item.title
|
||||||
)}
|
)}
|
||||||
</Span>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
|||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { config, locationService, reportInteraction } from '@grafana/runtime';
|
import { config, locationService, reportInteraction } from '@grafana/runtime';
|
||||||
import { Button, useStyles2 } from '@grafana/ui';
|
import { Button, useStyles2 } from '@grafana/ui';
|
||||||
import { H1, H3, P } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { Trans } from 'app/core/internationalization';
|
import { Trans } from 'app/core/internationalization';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state';
|
import { DashboardModel } from 'app/features/dashboard/state';
|
||||||
import { onAddLibraryPanel, onCreateNewPanel, onCreateNewRow } from 'app/features/dashboard/utils/dashboard';
|
import { onAddLibraryPanel, onCreateNewPanel, onCreateNewRow } from 'app/features/dashboard/utils/dashboard';
|
||||||
@ -28,19 +28,19 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
<div className={cx(styles.centeredContent, styles.wrapper)}>
|
<div className={cx(styles.centeredContent, styles.wrapper)}>
|
||||||
<div className={cx(styles.containerBox, styles.centeredContent, styles.visualizationContainer)}>
|
<div className={cx(styles.containerBox, styles.centeredContent, styles.visualizationContainer)}>
|
||||||
<div className={styles.headerBig}>
|
<div className={styles.headerBig}>
|
||||||
<H1 textAlignment="center" weight="medium">
|
<Text element="h1" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-visualization-header">
|
<Trans i18nKey="dashboard.empty.add-visualization-header">
|
||||||
Start your new dashboard by adding a visualization
|
Start your new dashboard by adding a visualization
|
||||||
</Trans>
|
</Trans>
|
||||||
</H1>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.bodyBig}>
|
<div className={styles.bodyBig}>
|
||||||
<P textAlignment="center" color="secondary">
|
<Text element="p" textAlignment="center" color="secondary">
|
||||||
<Trans i18nKey="dashboard.empty.add-visualization-body">
|
<Trans i18nKey="dashboard.empty.add-visualization-body">
|
||||||
Select a data source and then query and visualize your data with charts, stats and tables or create
|
Select a data source and then query and visualize your data with charts, stats and tables or create
|
||||||
lists, markdowns and other widgets.
|
lists, markdowns and other widgets.
|
||||||
</Trans>
|
</Trans>
|
||||||
</P>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="lg"
|
||||||
@ -61,14 +61,14 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
{config.featureToggles.vizAndWidgetSplit && (
|
{config.featureToggles.vizAndWidgetSplit && (
|
||||||
<div className={cx(styles.containerBox, styles.centeredContent, styles.widgetContainer)}>
|
<div className={cx(styles.containerBox, styles.centeredContent, styles.widgetContainer)}>
|
||||||
<div className={styles.headerSmall}>
|
<div className={styles.headerSmall}>
|
||||||
<H3 textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
|
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
|
||||||
</H3>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.bodySmall}>
|
<div className={styles.bodySmall}>
|
||||||
<P textAlignment="center" color="secondary">
|
<Text element="p" textAlignment="center" color="secondary">
|
||||||
<Trans i18nKey="dashboard.empty.add-widget-body">Create lists, markdowns and other widgets</Trans>
|
<Trans i18nKey="dashboard.empty.add-widget-body">Create lists, markdowns and other widgets</Trans>
|
||||||
</P>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
icon="plus"
|
icon="plus"
|
||||||
@ -86,16 +86,16 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
)}
|
)}
|
||||||
<div className={cx(styles.containerBox, styles.centeredContent, styles.rowContainer)}>
|
<div className={cx(styles.containerBox, styles.centeredContent, styles.rowContainer)}>
|
||||||
<div className={styles.headerSmall}>
|
<div className={styles.headerSmall}>
|
||||||
<H3 textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-row-header">Add a row</Trans>
|
<Trans i18nKey="dashboard.empty.add-row-header">Add a row</Trans>
|
||||||
</H3>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.bodySmall}>
|
<div className={styles.bodySmall}>
|
||||||
<P textAlignment="center" color="secondary">
|
<Text element="p" textAlignment="center" color="secondary">
|
||||||
<Trans i18nKey="dashboard.empty.add-row-body">
|
<Trans i18nKey="dashboard.empty.add-row-body">
|
||||||
Group your visualizations into expandable sections.
|
Group your visualizations into expandable sections.
|
||||||
</Trans>
|
</Trans>
|
||||||
</P>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
icon="plus"
|
icon="plus"
|
||||||
@ -112,16 +112,16 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className={cx(styles.containerBox, styles.centeredContent, styles.libraryContainer)}>
|
<div className={cx(styles.containerBox, styles.centeredContent, styles.libraryContainer)}>
|
||||||
<div className={styles.headerSmall}>
|
<div className={styles.headerSmall}>
|
||||||
<H3 textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-import-header">Import panel</Trans>
|
<Trans i18nKey="dashboard.empty.add-import-header">Import panel</Trans>
|
||||||
</H3>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.bodySmall}>
|
<div className={styles.bodySmall}>
|
||||||
<P textAlignment="center" color="secondary">
|
<Text element="p" textAlignment="center" color="secondary">
|
||||||
<Trans i18nKey="dashboard.empty.add-import-body">
|
<Trans i18nKey="dashboard.empty.add-import-body">
|
||||||
Import visualizations that are shared with other dashboards.
|
Import visualizations that are shared with other dashboards.
|
||||||
</Trans>
|
</Trans>
|
||||||
</P>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
icon="plus"
|
icon="plus"
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { config, getDataSourceSrv } from '@grafana/runtime';
|
import { config, getDataSourceSrv } from '@grafana/runtime';
|
||||||
import { Checkbox, Icon, IconName, TagList } from '@grafana/ui';
|
import { Checkbox, Icon, IconName, TagList } from '@grafana/ui';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
import { PluginIconName } from 'app/features/plugins/admin/types';
|
import { PluginIconName } from 'app/features/plugins/admin/types';
|
||||||
@ -179,9 +179,9 @@ export const generateColumns = (
|
|||||||
return info ? (
|
return info ? (
|
||||||
<a key={p} href={info.url} className={styles.locationItem}>
|
<a key={p} href={info.url} className={styles.locationItem}>
|
||||||
<Icon name={getIconForKind(info.kind)} />
|
<Icon name={getIconForKind(info.kind)} />
|
||||||
<Span variant="body" truncate>
|
<Text variant="body" truncate>
|
||||||
{info.name}
|
{info.name}
|
||||||
</Span>
|
</Text>
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<span key={p}>{p}</span>
|
<span key={p}>{p}</span>
|
||||||
|
@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
|
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
|
||||||
import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data';
|
import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data';
|
||||||
import { DataSourceHttpSettings, InlineField, InlineFormLabel, InlineSwitch, Select } from '@grafana/ui';
|
import { DataSourceHttpSettings, InlineField, InlineFormLabel, InlineSwitch, Select } from '@grafana/ui';
|
||||||
import { Span } from '@grafana/ui/src/unstable';
|
import { Text } from '@grafana/ui/src/unstable';
|
||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
|
|
||||||
import { AlertManagerDataSourceJsonData, AlertManagerImplementation } from './types';
|
import { AlertManagerDataSourceJsonData, AlertManagerImplementation } from './types';
|
||||||
@ -76,9 +76,9 @@ export const ConfigEditor = (props: Props) => {
|
|||||||
</InlineField>
|
</InlineField>
|
||||||
</div>
|
</div>
|
||||||
{options.jsonData.handleGrafanaManagedAlerts && (
|
{options.jsonData.handleGrafanaManagedAlerts && (
|
||||||
<Span variant="bodySmall" color="secondary">
|
<Text variant="bodySmall" color="secondary">
|
||||||
Make sure to enable the alert forwarding on the <Link to="/alerting/admin">admin page</Link>.
|
Make sure to enable the alert forwarding on the <Link to="/alerting/admin">admin page</Link>.
|
||||||
</Span>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<DataSourceHttpSettings
|
<DataSourceHttpSettings
|
||||||
|
Reference in New Issue
Block a user