Files
grafana/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanLinks.tsx
Andre Pereira 607a664ef4 Trace View: Span list visual update (#75238)
* Show color of row as a border under the row. Hide service name for sequential spans

* Increase default span name column width. Smaller font for service and span names in span list

* New background color on spans. Fixed hover of indent markers

* Service name and span name style tweaks

* Collapse hidden levels

* Fixed test

* Small tweak to Buffer size to make sure tests pass

* Trigger runs

* Update betterer results

* Address comment

* Style tweaks

* Remove duplicated code

* Rollback change to join <span> since they are needed for the tests
2023-10-04 14:00:40 +01:00

109 lines
2.7 KiB
TypeScript

import { css } from '@emotion/css';
import React, { useState } from 'react';
import { config, reportInteraction } from '@grafana/runtime';
import { useStyles2, MenuItem, Icon, ContextMenu } from '@grafana/ui';
import { SpanLinkDef } from '../types/links';
interface SpanLinksProps {
links: SpanLinkDef[];
datasourceType: string;
color: string;
}
const renderMenuItems = (
links: SpanLinkDef[],
styles: ReturnType<typeof getStyles>,
closeMenu: () => void,
datasourceType: string
) => {
links.sort(function (linkA, linkB) {
return (linkA.title || 'link').toLowerCase().localeCompare((linkB.title || 'link').toLowerCase());
});
return links.map((link, i) => (
<MenuItem
key={i}
label={link.title || 'Link'}
onClick={
link.onClick
? (event) => {
reportInteraction(`grafana_traces_trace_view_span_link_clicked`, {
datasourceType: datasourceType,
grafana_version: config.buildInfo.version,
type: link.type,
location: 'menu',
});
event?.preventDefault();
link.onClick!(event);
closeMenu();
}
: undefined
}
url={link.href}
className={styles.menuItem}
/>
));
};
export const SpanLinksMenu = ({ links, datasourceType, color }: SpanLinksProps) => {
const styles = useStyles2(() => getStyles(color));
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
const closeMenu = () => setIsMenuOpen(false);
return (
<div data-testid="SpanLinksMenu" className={styles.wrapper}>
<button
onClick={(e) => {
setIsMenuOpen(true);
setMenuPosition({
x: e.pageX,
y: e.pageY,
});
}}
className={styles.button}
>
<Icon name="link" className={styles.icon} />
</button>
{isMenuOpen ? (
<ContextMenu
onClose={() => setIsMenuOpen(false)}
renderMenuItems={() => renderMenuItems(links, styles, closeMenu, datasourceType)}
focusOnOpen={false}
x={menuPosition.x}
y={menuPosition.y}
/>
) : null}
</div>
);
};
const getStyles = (color: string) => {
return {
wrapper: css`
border: none;
background: ${color}10;
border-bottom: 1px solid ${color}CF;
padding-right: 4px;
`,
button: css`
background: transparent;
border: none;
padding: 0;
`,
icon: css`
background: transparent;
border: none;
padding: 0;
`,
menuItem: css`
max-width: 60ch;
overflow: hidden;
`,
};
};