Explore: Interaction tracking for logs pinning and filtering in content outline (#90213)

* Add interaction tracking

* Move reportInteraction out of scrollIntoView to improve readability

* move activateFilter logic inside handleItemClicked
This commit is contained in:
Haris Rozajac 2024-07-09 08:17:50 -07:00 committed by GitHub
parent 434f386982
commit 8a6e92c0c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 20 deletions

View File

@ -7,6 +7,7 @@ import { reportInteraction } from '@grafana/runtime';
import { useStyles2, PanelContainer, CustomScrollbar } from '@grafana/ui';
import { ContentOutlineItemContextProps, useContentOutlineContext } from './ContentOutlineContext';
import { ITEM_TYPES } from './ContentOutlineItem';
import { ContentOutlineItemButton } from './ContentOutlineItemButton';
function scrollableChildren(item: ContentOutlineItemContextProps) {
@ -56,7 +57,12 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
}, {});
});
const scrollIntoView = (ref: HTMLElement | null, itemPanelId: string, customOffsetTop = 0) => {
const scrollIntoView = (
ref: HTMLElement | null,
itemPanelId: string,
itemType: ITEM_TYPES | undefined,
customOffsetTop = 0
) => {
let scrollValue = 0;
let el: HTMLElement | null | undefined = ref;
@ -73,11 +79,24 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
top: scrollValue + customOffsetTop,
behavior: 'smooth',
});
};
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'select_section',
type: itemPanelId,
});
const handleItemClicked = (item: ContentOutlineItemContextProps) => {
if (item.level === 'child' && item.type === 'filter') {
const activeParent = outlineItems.find((parent) => {
return parent.children?.find((child) => child.id === item.id);
});
if (activeParent) {
scrollIntoView(activeParent.ref, activeParent.panelId, activeParent.type, activeParent.customTopOffset);
}
} else {
scrollIntoView(item.ref, item.panelId, item.type, item.customTopOffset);
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'select_section',
type: item.panelId,
});
}
};
const toggle = () => {
@ -131,16 +150,6 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
}
}, [outlineItems, verticalScroll]);
const activateFilter = (filterId: string) => {
const activeParent = outlineItems.find((item) => {
return item.children?.find((child) => child.id === filterId);
});
if (activeParent) {
scrollIntoView(activeParent.ref, activeParent.panelId, activeParent.customTopOffset);
}
};
return (
<PanelContainer className={styles.wrapper} id={panelId}>
<CustomScrollbar>
@ -173,7 +182,7 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
isChildActive(item, activeSectionChildId) && !contentOutlineExpanded && sectionsExpanded[item.id],
})}
icon={item.icon}
onClick={() => scrollIntoView(item.ref, item.panelId)}
onClick={() => handleItemClicked(item)}
tooltip={item.title}
collapsible={isCollapsible(item)}
collapsed={!sectionsExpanded[item.id]}
@ -208,9 +217,7 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
})}
indentStyle={styles.indentChild}
onClick={(e) => {
child.type === 'filter'
? activateFilter(child.id)
: scrollIntoView(child.ref, child.panelId, child.customTopOffset);
handleItemClicked(child);
child.onClick?.(e);
}}
tooltip={child.title}

View File

@ -262,6 +262,10 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
highlight: currentLevelSelected && !allLevelsSelected,
onClick: (e: React.MouseEvent) => {
toggleLegendRef.current?.(level.levelStr, mapMouseEventToMode(e));
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'section',
type: `Logs:filter:${level.levelStr}`,
});
},
ref: null,
color: LogLevelColor[level.logLevel],
@ -658,6 +662,11 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
</Trans>
</span>
);
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'section',
type: 'Logs:pinned:pinned-log-limit-reached',
});
return;
}
@ -677,16 +686,31 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
ref: null,
color: LogLevelColor[row.logLevel],
childOnTop: true,
onClick: () => onOpenContext(row, () => {}),
onClick: () => {
onOpenContext(row, () => {});
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'section',
type: 'Logs:pinned:pinned-log-clicked',
});
},
onRemove: (id: string) => {
unregister?.(id);
if (getPinnedLogsCount() < PINNED_LOGS_LIMIT) {
setPinLineButtonTooltipTitle('Pin to content outline');
}
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'section',
type: 'Logs:pinned:pinned-log-deleted',
});
},
});
props.onPinLineCallback?.();
reportInteraction('explore_toolbar_contentoutline_clicked', {
item: 'section',
type: 'Logs:pinned:pinned-log-added',
});
};
const getPinnedLogsCount = () => {