mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
434f386982
commit
8a6e92c0c9
@ -7,6 +7,7 @@ import { reportInteraction } from '@grafana/runtime';
|
|||||||
import { useStyles2, PanelContainer, CustomScrollbar } from '@grafana/ui';
|
import { useStyles2, PanelContainer, CustomScrollbar } from '@grafana/ui';
|
||||||
|
|
||||||
import { ContentOutlineItemContextProps, useContentOutlineContext } from './ContentOutlineContext';
|
import { ContentOutlineItemContextProps, useContentOutlineContext } from './ContentOutlineContext';
|
||||||
|
import { ITEM_TYPES } from './ContentOutlineItem';
|
||||||
import { ContentOutlineItemButton } from './ContentOutlineItemButton';
|
import { ContentOutlineItemButton } from './ContentOutlineItemButton';
|
||||||
|
|
||||||
function scrollableChildren(item: ContentOutlineItemContextProps) {
|
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 scrollValue = 0;
|
||||||
let el: HTMLElement | null | undefined = ref;
|
let el: HTMLElement | null | undefined = ref;
|
||||||
|
|
||||||
@ -73,11 +79,24 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
|
|||||||
top: scrollValue + customOffsetTop,
|
top: scrollValue + customOffsetTop,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
const handleItemClicked = (item: ContentOutlineItemContextProps) => {
|
||||||
item: 'select_section',
|
if (item.level === 'child' && item.type === 'filter') {
|
||||||
type: itemPanelId,
|
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 = () => {
|
const toggle = () => {
|
||||||
@ -131,16 +150,6 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
|
|||||||
}
|
}
|
||||||
}, [outlineItems, verticalScroll]);
|
}, [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 (
|
return (
|
||||||
<PanelContainer className={styles.wrapper} id={panelId}>
|
<PanelContainer className={styles.wrapper} id={panelId}>
|
||||||
<CustomScrollbar>
|
<CustomScrollbar>
|
||||||
@ -173,7 +182,7 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
|
|||||||
isChildActive(item, activeSectionChildId) && !contentOutlineExpanded && sectionsExpanded[item.id],
|
isChildActive(item, activeSectionChildId) && !contentOutlineExpanded && sectionsExpanded[item.id],
|
||||||
})}
|
})}
|
||||||
icon={item.icon}
|
icon={item.icon}
|
||||||
onClick={() => scrollIntoView(item.ref, item.panelId)}
|
onClick={() => handleItemClicked(item)}
|
||||||
tooltip={item.title}
|
tooltip={item.title}
|
||||||
collapsible={isCollapsible(item)}
|
collapsible={isCollapsible(item)}
|
||||||
collapsed={!sectionsExpanded[item.id]}
|
collapsed={!sectionsExpanded[item.id]}
|
||||||
@ -208,9 +217,7 @@ export function ContentOutline({ scroller, panelId }: { scroller: HTMLElement |
|
|||||||
})}
|
})}
|
||||||
indentStyle={styles.indentChild}
|
indentStyle={styles.indentChild}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
child.type === 'filter'
|
handleItemClicked(child);
|
||||||
? activateFilter(child.id)
|
|
||||||
: scrollIntoView(child.ref, child.panelId, child.customTopOffset);
|
|
||||||
child.onClick?.(e);
|
child.onClick?.(e);
|
||||||
}}
|
}}
|
||||||
tooltip={child.title}
|
tooltip={child.title}
|
||||||
|
@ -262,6 +262,10 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
|
|||||||
highlight: currentLevelSelected && !allLevelsSelected,
|
highlight: currentLevelSelected && !allLevelsSelected,
|
||||||
onClick: (e: React.MouseEvent) => {
|
onClick: (e: React.MouseEvent) => {
|
||||||
toggleLegendRef.current?.(level.levelStr, mapMouseEventToMode(e));
|
toggleLegendRef.current?.(level.levelStr, mapMouseEventToMode(e));
|
||||||
|
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
||||||
|
item: 'section',
|
||||||
|
type: `Logs:filter:${level.levelStr}`,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
ref: null,
|
ref: null,
|
||||||
color: LogLevelColor[level.logLevel],
|
color: LogLevelColor[level.logLevel],
|
||||||
@ -658,6 +662,11 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
|
|||||||
</Trans>
|
</Trans>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
||||||
|
item: 'section',
|
||||||
|
type: 'Logs:pinned:pinned-log-limit-reached',
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,16 +686,31 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
|
|||||||
ref: null,
|
ref: null,
|
||||||
color: LogLevelColor[row.logLevel],
|
color: LogLevelColor[row.logLevel],
|
||||||
childOnTop: true,
|
childOnTop: true,
|
||||||
onClick: () => onOpenContext(row, () => {}),
|
onClick: () => {
|
||||||
|
onOpenContext(row, () => {});
|
||||||
|
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
||||||
|
item: 'section',
|
||||||
|
type: 'Logs:pinned:pinned-log-clicked',
|
||||||
|
});
|
||||||
|
},
|
||||||
onRemove: (id: string) => {
|
onRemove: (id: string) => {
|
||||||
unregister?.(id);
|
unregister?.(id);
|
||||||
if (getPinnedLogsCount() < PINNED_LOGS_LIMIT) {
|
if (getPinnedLogsCount() < PINNED_LOGS_LIMIT) {
|
||||||
setPinLineButtonTooltipTitle('Pin to content outline');
|
setPinLineButtonTooltipTitle('Pin to content outline');
|
||||||
}
|
}
|
||||||
|
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
||||||
|
item: 'section',
|
||||||
|
type: 'Logs:pinned:pinned-log-deleted',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
props.onPinLineCallback?.();
|
props.onPinLineCallback?.();
|
||||||
|
|
||||||
|
reportInteraction('explore_toolbar_contentoutline_clicked', {
|
||||||
|
item: 'section',
|
||||||
|
type: 'Logs:pinned:pinned-log-added',
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPinnedLogsCount = () => {
|
const getPinnedLogsCount = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user