mirror of
https://github.com/grafana/grafana.git
synced 2024-12-30 10:47:30 -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
@ -33,7 +33,7 @@ export interface DataLink<T extends DataQuery = any> {
|
||||
onClick?: (event: DataLinkClickEvent) => void;
|
||||
|
||||
// If dataLink represents internal link this has to be filled. Internal link is defined as a query in a particular
|
||||
// datas ource that we want to show to the user. Usually this results in a link to explore but can also lead to
|
||||
// data source that we want to show to the user. Usually this results in a link to explore but can also lead to
|
||||
// more custom onClick behaviour if needed.
|
||||
// @internal and subject to change in future releases
|
||||
internal?: InternalDataLink<T>;
|
||||
|
@ -2,16 +2,19 @@ import { Field, LinkModel } from '@grafana/data';
|
||||
import React from 'react';
|
||||
import { ButtonProps, Button } from '../Button';
|
||||
|
||||
type FieldLinkProps = {
|
||||
type DataLinkButtonProps = {
|
||||
link: LinkModel<Field>;
|
||||
buttonProps?: ButtonProps;
|
||||
};
|
||||
|
||||
export function FieldLink({ link, buttonProps }: FieldLinkProps) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function DataLinkButton({ link, buttonProps }: DataLinkButtonProps) {
|
||||
return (
|
||||
<a
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
target={link.target}
|
||||
rel="noreferrer"
|
||||
onClick={
|
||||
link.onClick
|
||||
@ -24,7 +27,7 @@ export function FieldLink({ link, buttonProps }: FieldLinkProps) {
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Button icon="external-link-alt" {...buttonProps}>
|
||||
<Button icon="external-link-alt" variant="primary" size="sm" {...buttonProps}>
|
||||
{link.title}
|
||||
</Button>
|
||||
</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
|
||||
import { LogLabelStats } from './LogLabelStats';
|
||||
import { IconButton } from '../IconButton/IconButton';
|
||||
import { FieldLink } from './FieldLink';
|
||||
import { DataLinkButton } from '../DataLinks/DataLinkButton';
|
||||
|
||||
export interface Props extends Themeable {
|
||||
parsedValue: string;
|
||||
@ -158,7 +158,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
|
||||
return (
|
||||
<>
|
||||
|
||||
<FieldLink link={link} />
|
||||
<DataLinkButton link={link} />
|
||||
</>
|
||||
);
|
||||
})}
|
||||
|
@ -87,7 +87,8 @@ export { LogLabels } from './Logs/LogLabels';
|
||||
export { LogMessageAnsi } from './Logs/LogMessageAnsi';
|
||||
export { LogRows } from './Logs/LogRows';
|
||||
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';
|
||||
// Panel editors
|
||||
export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer';
|
||||
|
@ -30,7 +30,7 @@ import AccordianReferences from './AccordianReferences';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { UIDivider } from '../../uiElementsContext';
|
||||
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';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
@ -183,7 +183,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
<LabeledList className={ubTxRightAlign} dividerClassName={styles.divider} items={overviewItems} />
|
||||
</div>
|
||||
{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}
|
||||
<UIDivider className={cx(styles.divider, styles.dividerVertical, ubMy1)} />
|
||||
<div>
|
||||
|
@ -15,7 +15,7 @@ const onExemplarsChange = ({ query, onChange }: Props) => (e: React.ChangeEvent<
|
||||
export function PromExemplarField(props: Props) {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
@ -165,8 +165,9 @@ function getDataLinks(options: ExemplarTraceIdDestination): DataLink[] {
|
||||
|
||||
if (options.url) {
|
||||
dataLinks.push({
|
||||
title: 'Open link',
|
||||
title: `Go to ${options.url}`,
|
||||
url: options.url,
|
||||
targetBlank: true,
|
||||
});
|
||||
}
|
||||
return dataLinks;
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
systemDateFormats,
|
||||
TimeZone,
|
||||
} 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 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;
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td>{field.name}</td>
|
||||
<td className={styles.valueWrapper}>
|
||||
{field.type === FieldType.time ? timeFormatter(value) : value}{' '}
|
||||
{links &&
|
||||
links.map((link, i) => {
|
||||
return (
|
||||
<div key={i} className={styles.link}>
|
||||
<FieldLink link={link} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<td valign="top">{field.name}</td>
|
||||
<td>
|
||||
<div className={styles.valueWrapper}>
|
||||
<span>{field.type === FieldType.time ? timeFormatter(value) : value}</span>
|
||||
{links && <FieldLinkList links={links} />}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
@ -179,7 +174,17 @@ const getExemplarMarkerStyles = (theme: GrafanaTheme) => {
|
||||
valueWrapper: css`
|
||||
display: flex;
|
||||
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`
|
||||
background: none;
|
||||
@ -203,9 +208,6 @@ const getExemplarMarkerStyles = (theme: GrafanaTheme) => {
|
||||
padding: ${theme.spacing.sm};
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
`,
|
||||
link: css`
|
||||
margin: 0 ${theme.spacing.sm};
|
||||
`,
|
||||
marble,
|
||||
activeMarble,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user