Logs: Derived fields link design update (#23695)

This commit is contained in:
Andrej Ocenas
2020-04-23 20:47:54 +02:00
committed by GitHub
parent 376765b3d7
commit 170a0df194
8 changed files with 159 additions and 67 deletions

View File

@@ -121,7 +121,19 @@ class UnThemedLogDetails extends PureComponent<Props> {
}
return acc;
}, {} as { [key: string]: FieldDef });
return Object.values(fieldsMap);
const allFields = Object.values(fieldsMap);
allFields.sort((fieldA, fieldB) => {
if (fieldA.links?.length && !fieldB.links?.length) {
return -1;
}
if (!fieldA.links?.length && fieldB.links?.length) {
return 1;
}
return fieldA.key > fieldB.key ? 1 : fieldA.key < fieldB.key ? -1 : 0;
});
return allFields;
});
getStatsForParsedField = (key: string) => {

View File

@@ -9,8 +9,8 @@ import { stylesFactory } from '../../themes/stylesFactory';
//Components
import { LogLabelStats } from './LogLabelStats';
import { LinkButton } from '../Button/Button';
import { IconButton } from '../IconButton/IconButton';
import { Tag } from '..';
export interface Props extends Themeable {
parsedValue: string;
@@ -116,27 +116,10 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
{links &&
links.map(link => {
return (
<span key={link.href}>
<>
&nbsp;
<LinkButton
variant="link"
size={'sm'}
icon={link.onClick ? 'list-ul' : 'external-link-alt'}
href={link.href}
target={'_blank'}
onClick={
link.onClick &&
((event: any) => {
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
event.preventDefault();
link.onClick(event);
}
})
}
/>
</>
</span>
<>
&nbsp;
<FieldLink link={link} />
</>
);
})}
{showFieldsStats && (
@@ -154,5 +137,40 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
}
}
const getLinkStyles = stylesFactory(() => {
return {
tag: css`
margin-left: 6px;
font-size: 11px;
padding: 2px 6px;
`,
};
});
type FieldLinkProps = {
link: LinkModel<Field>;
};
function FieldLink({ link }: FieldLinkProps) {
const styles = getLinkStyles();
return (
<a
href={link.href}
target={'_blank'}
onClick={
link.onClick
? event => {
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
event.preventDefault();
link.onClick(event);
}
}
: undefined
}
>
<Tag name={link.title} className={styles.tag} colorIndex={6} />
</a>
);
}
export const LogDetailsRow = withTheme(UnThemedLogDetailsRow);
LogDetailsRow.displayName = 'LogDetailsRow';

View File

@@ -2,19 +2,21 @@ import React, { forwardRef, HTMLAttributes } from 'react';
import { cx, css } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { useTheme } from '../../themes';
import { getTagColorsFromName } from '../../utils';
import { getTagColor, getTagColorsFromName } from '../../utils';
export type OnTagClick = (name: string, event: React.MouseEvent<HTMLElement>) => any;
export interface Props extends Omit<HTMLAttributes<HTMLElement>, 'onClick'> {
/** Name of the tag to display */
name: string;
/** Use constant color from TAG_COLORS. Using index instead of color directly so we can match other styling. */
colorIndex?: number;
onClick?: OnTagClick;
}
export const Tag = forwardRef<HTMLElement, Props>(({ name, onClick, className, ...rest }, ref) => {
export const Tag = forwardRef<HTMLElement, Props>(({ name, onClick, className, colorIndex, ...rest }, ref) => {
const theme = useTheme();
const styles = getTagStyles(theme, name);
const styles = getTagStyles(theme, name, colorIndex);
const onTagClick = (event: React.MouseEvent<HTMLElement>) => {
if (onClick) {
@@ -29,20 +31,25 @@ export const Tag = forwardRef<HTMLElement, Props>(({ name, onClick, className, .
);
});
const getTagStyles = (theme: GrafanaTheme, name: string) => {
const { borderColor, color } = getTagColorsFromName(name);
const getTagStyles = (theme: GrafanaTheme, name: string, colorIndex?: number) => {
let colors;
if (colorIndex === undefined) {
colors = getTagColorsFromName(name);
} else {
colors = getTagColor(colorIndex);
}
return {
wrapper: css`
font-weight: ${theme.typography.weight.semibold};
font-size: ${theme.typography.size.sm};
line-height: ${theme.typography.lineHeight.xs};
vertical-align: baseline;
background-color: ${color};
background-color: ${colors.color};
color: ${theme.palette.white};
white-space: nowrap;
text-shadow: none;
padding: 3px 6px;
border: 1px solid ${borderColor};
border: 1px solid ${colors.borderColor};
border-radius: ${theme.border.radius.md};
:hover {

View File

@@ -68,9 +68,12 @@ const TAG_BORDER_COLORS = [
*/
export function getTagColorsFromName(name = ''): { color: string; borderColor: string } {
const hash = djb2(name.toLowerCase());
const color = TAG_COLORS[Math.abs(hash % TAG_COLORS.length)];
const borderColor = TAG_BORDER_COLORS[Math.abs(hash % TAG_BORDER_COLORS.length)];
return { color, borderColor };
const index = Math.abs(hash % TAG_COLORS.length);
return getTagColor(index);
}
export function getTagColor(index: number): { color: string; borderColor: string } {
return { color: TAG_COLORS[index], borderColor: TAG_BORDER_COLORS[index] };
}
function djb2(str: string) {