mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Exemplars: Change CTA style (#30880)
* Exemplars: Change CTA style * Address review feedbacks * Fix table column aligning * Minor alignments + uncontrolled component warning fix
This commit is contained in:
parent
e0448513eb
commit
cc463f30a4
@ -2,16 +2,19 @@ import { Field, LinkModel } from '@grafana/data';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ButtonProps, Button } from '../Button';
|
import { ButtonProps, Button } from '../Button';
|
||||||
|
|
||||||
type FieldLinkProps = {
|
type DataLinkButtonProps = {
|
||||||
link: LinkModel<Field>;
|
link: LinkModel<Field>;
|
||||||
buttonProps?: ButtonProps;
|
buttonProps?: ButtonProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FieldLink({ link, buttonProps }: FieldLinkProps) {
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export function DataLinkButton({ link, buttonProps }: DataLinkButtonProps) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
target="_blank"
|
target={link.target}
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
onClick={
|
onClick={
|
||||||
link.onClick
|
link.onClick
|
||||||
@ -24,7 +27,7 @@ export function FieldLink({ link, buttonProps }: FieldLinkProps) {
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Button icon="external-link-alt" {...buttonProps}>
|
<Button icon="external-link-alt" variant="primary" size="sm" {...buttonProps}>
|
||||||
{link.title}
|
{link.title}
|
||||||
</Button>
|
</Button>
|
||||||
</a>
|
</a>
|
@ -0,0 +1,71 @@
|
|||||||
|
import { Field, GrafanaTheme, LinkModel } from '@grafana/data';
|
||||||
|
import { css } from 'emotion';
|
||||||
|
import React from 'react';
|
||||||
|
import { useStyles } from '../../themes';
|
||||||
|
import { Icon } from '../Icon/Icon';
|
||||||
|
import { DataLinkButton } from './DataLinkButton';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
links: Array<LinkModel<Field>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export function FieldLinkList({ links }: Props) {
|
||||||
|
const styles = useStyles(getStyles);
|
||||||
|
|
||||||
|
if (links.length === 1) {
|
||||||
|
return <DataLinkButton link={links[0]} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const externalLinks = links.filter((link) => link.target === '_blank');
|
||||||
|
const internalLinks = links.filter((link) => link.target === '_self');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{internalLinks.map((link, i) => {
|
||||||
|
return <DataLinkButton key={i} link={link} />;
|
||||||
|
})}
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<p className={styles.externalLinksHeading}>External links</p>
|
||||||
|
{externalLinks.map((link, i) => (
|
||||||
|
<a key={i} href={link.href} target={link.target} className={styles.externalLink}>
|
||||||
|
<Icon name="external-link-alt" />
|
||||||
|
{link.title}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme) => ({
|
||||||
|
wrapper: css`
|
||||||
|
flex-basis: 150px;
|
||||||
|
width: 100px;
|
||||||
|
margin-top: ${theme.spacing.sm};
|
||||||
|
`,
|
||||||
|
externalLinksHeading: css`
|
||||||
|
color: ${theme.colors.textWeak};
|
||||||
|
font-weight: ${theme.typography.weight.regular};
|
||||||
|
font-size: ${theme.typography.size.sm};
|
||||||
|
margin: 0;
|
||||||
|
`,
|
||||||
|
externalLink: css`
|
||||||
|
color: ${theme.colors.linkExternal};
|
||||||
|
font-weight: ${theme.typography.weight.regular};
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin-right: ${theme.spacing.sm};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
@ -10,7 +10,7 @@ import { stylesFactory } from '../../themes/stylesFactory';
|
|||||||
//Components
|
//Components
|
||||||
import { LogLabelStats } from './LogLabelStats';
|
import { LogLabelStats } from './LogLabelStats';
|
||||||
import { IconButton } from '../IconButton/IconButton';
|
import { IconButton } from '../IconButton/IconButton';
|
||||||
import { FieldLink } from './FieldLink';
|
import { DataLinkButton } from '../DataLinks/DataLinkButton';
|
||||||
|
|
||||||
export interface Props extends Themeable {
|
export interface Props extends Themeable {
|
||||||
parsedValue: string;
|
parsedValue: string;
|
||||||
@ -158,7 +158,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<FieldLink link={link} />
|
<DataLinkButton link={link} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -87,7 +87,8 @@ export { LogLabels } from './Logs/LogLabels';
|
|||||||
export { LogMessageAnsi } from './Logs/LogMessageAnsi';
|
export { LogMessageAnsi } from './Logs/LogMessageAnsi';
|
||||||
export { LogRows } from './Logs/LogRows';
|
export { LogRows } from './Logs/LogRows';
|
||||||
export { getLogRowStyles } from './Logs/getLogRowStyles';
|
export { getLogRowStyles } from './Logs/getLogRowStyles';
|
||||||
export { FieldLink } from './Logs/FieldLink';
|
export { DataLinkButton } from './DataLinks/DataLinkButton';
|
||||||
|
export { FieldLinkList } from './DataLinks/FieldLinkList';
|
||||||
export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup';
|
export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup';
|
||||||
// Panel editors
|
// Panel editors
|
||||||
export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer';
|
export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer';
|
||||||
|
@ -30,7 +30,7 @@ import AccordianReferences from './AccordianReferences';
|
|||||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||||
import { UIDivider } from '../../uiElementsContext';
|
import { UIDivider } from '../../uiElementsContext';
|
||||||
import { ubFlex, ubFlexAuto, ubItemsCenter, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles';
|
import { ubFlex, ubFlexAuto, ubItemsCenter, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles';
|
||||||
import { FieldLink, TextArea } from '@grafana/ui';
|
import { DataLinkButton, TextArea } from '@grafana/ui';
|
||||||
import { CreateSpanLink } from '../types';
|
import { CreateSpanLink } from '../types';
|
||||||
|
|
||||||
const getStyles = createStyle((theme: Theme) => {
|
const getStyles = createStyle((theme: Theme) => {
|
||||||
@ -183,7 +183,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
|||||||
<LabeledList className={ubTxRightAlign} dividerClassName={styles.divider} items={overviewItems} />
|
<LabeledList className={ubTxRightAlign} dividerClassName={styles.divider} items={overviewItems} />
|
||||||
</div>
|
</div>
|
||||||
{link ? (
|
{link ? (
|
||||||
<FieldLink link={{ ...link, title: 'Logs for this span' } as any} buttonProps={{ icon: 'gf-logs' }} />
|
<DataLinkButton link={{ ...link, title: 'Logs for this span' } as any} buttonProps={{ icon: 'gf-logs' }} />
|
||||||
) : null}
|
) : null}
|
||||||
<UIDivider className={cx(styles.divider, styles.dividerVertical, ubMy1)} />
|
<UIDivider className={cx(styles.divider, styles.dividerVertical, ubMy1)} />
|
||||||
<div>
|
<div>
|
||||||
|
@ -15,7 +15,7 @@ const onExemplarsChange = ({ query, onChange }: Props) => (e: React.ChangeEvent<
|
|||||||
export function PromExemplarField(props: Props) {
|
export function PromExemplarField(props: Props) {
|
||||||
return (
|
return (
|
||||||
<InlineField label="Exemplars" labelWidth="auto">
|
<InlineField label="Exemplars" labelWidth="auto">
|
||||||
<InlineSwitch label="Exemplars" value={props.query.exemplar} onChange={onExemplarsChange(props)} />
|
<InlineSwitch label="Exemplars" value={!!props.query.exemplar} onChange={onExemplarsChange(props)} />
|
||||||
</InlineField>
|
</InlineField>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -165,8 +165,9 @@ function getDataLinks(options: ExemplarTraceIdDestination): DataLink[] {
|
|||||||
|
|
||||||
if (options.url) {
|
if (options.url) {
|
||||||
dataLinks.push({
|
dataLinks.push({
|
||||||
title: 'Open link',
|
title: `Go to ${options.url}`,
|
||||||
url: options.url,
|
url: options.url,
|
||||||
|
targetBlank: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return dataLinks;
|
return dataLinks;
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
systemDateFormats,
|
systemDateFormats,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { FieldLink, Portal, TooltipContainer, useStyles } from '@grafana/ui';
|
import { FieldLinkList, Portal, TooltipContainer, useStyles } from '@grafana/ui';
|
||||||
import { css, cx } from 'emotion';
|
import { css, cx } from 'emotion';
|
||||||
import React, { useCallback, useRef, useState } from 'react';
|
import React, { useCallback, useRef, useState } from 'react';
|
||||||
|
|
||||||
@ -78,17 +78,12 @@ export const ExemplarMarker: React.FC<ExemplarMarkerProps> = ({ timeZone, dataFr
|
|||||||
const links = field.config.links?.length ? getFieldLinks(field, index) : undefined;
|
const links = field.config.links?.length ? getFieldLinks(field, index) : undefined;
|
||||||
return (
|
return (
|
||||||
<tr key={i}>
|
<tr key={i}>
|
||||||
<td>{field.name}</td>
|
<td valign="top">{field.name}</td>
|
||||||
<td className={styles.valueWrapper}>
|
<td>
|
||||||
{field.type === FieldType.time ? timeFormatter(value) : value}{' '}
|
<div className={styles.valueWrapper}>
|
||||||
{links &&
|
<span>{field.type === FieldType.time ? timeFormatter(value) : value}</span>
|
||||||
links.map((link, i) => {
|
{links && <FieldLinkList links={links} />}
|
||||||
return (
|
|
||||||
<div key={i} className={styles.link}>
|
|
||||||
<FieldLink link={link} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
})}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
@ -179,7 +174,17 @@ const getExemplarMarkerStyles = (theme: GrafanaTheme) => {
|
|||||||
valueWrapper: css`
|
valueWrapper: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
flex-wrap: wrap;
|
||||||
|
column-gap: ${theme.spacing.sm};
|
||||||
|
|
||||||
|
> span {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
flex: 1 1;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
tooltip: css`
|
tooltip: css`
|
||||||
background: none;
|
background: none;
|
||||||
@ -203,9 +208,6 @@ const getExemplarMarkerStyles = (theme: GrafanaTheme) => {
|
|||||||
padding: ${theme.spacing.sm};
|
padding: ${theme.spacing.sm};
|
||||||
font-weight: ${theme.typography.weight.semibold};
|
font-weight: ${theme.typography.weight.semibold};
|
||||||
`,
|
`,
|
||||||
link: css`
|
|
||||||
margin: 0 ${theme.spacing.sm};
|
|
||||||
`,
|
|
||||||
marble,
|
marble,
|
||||||
activeMarble,
|
activeMarble,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user