[Chore] Refactor Panel Menu Rudderstack events and add missing instrumentation (#66850)

pull/67487/head
Alexa V 2 years ago committed by GitHub
parent 236862a07c
commit b4a7427f31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      packages/grafana-ui/src/components/PanelChrome/HoverWidget.tsx
  2. 14
      packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx
  3. 17
      packages/grafana-ui/src/components/PanelChrome/PanelMenu.tsx
  4. 1
      public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx
  5. 7
      public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx
  6. 8
      public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuTrigger.tsx
  7. 1
      public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx
  8. 5
      public/app/features/dashboard/utils/getPanelChromeProps.tsx
  9. 23
      public/app/features/dashboard/utils/getPanelMenu.ts

@ -15,14 +15,13 @@ interface Props {
title?: string;
offset?: number;
dragClass?: string;
onOpenMenu?: () => void;
}
const selectors = e2eSelectors.components.Panels.Panel.HoverWidget;
export function HoverWidget({ menu, title, dragClass, children, offset = -32 }: Props) {
export function HoverWidget({ menu, title, dragClass, children, offset = -32, onOpenMenu }: Props) {
const styles = useStyles2(getStyles);
const draggableRef = useRef<HTMLDivElement>(null);
const selectors = e2eSelectors.components.Panels.Panel.HoverWidget;
// Capture the pointer to keep the widget visible while dragging
const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {
draggableRef.current?.setPointerCapture(e.pointerId);
@ -64,6 +63,7 @@ export function HoverWidget({ menu, title, dragClass, children, offset = -32 }:
placement="bottom"
menuButtonClass={styles.menuButton}
onVisibleChange={setMenuOpen}
onOpenMenu={onOpenMenu}
/>
)}
</div>

@ -53,6 +53,10 @@ export interface PanelChromeProps {
actions?: ReactNode;
displayMode?: 'default' | 'transparent';
onCancelQuery?: () => void;
/**
* callback when opening the panel menu
*/
onOpenMenu?: () => void;
}
/**
@ -83,6 +87,7 @@ export function PanelChrome({
leftItems,
actions,
onCancelQuery,
onOpenMenu,
}: PanelChromeProps) {
const theme = useTheme2();
const styles = useStyles2(getStyles);
@ -159,7 +164,13 @@ export function PanelChrome({
{hoverHeader && !isTouchDevice && (
<>
<HoverWidget menu={menu} title={title} offset={hoverHeaderOffset} dragClass={dragClass}>
<HoverWidget
menu={menu}
title={title}
offset={hoverHeaderOffset}
dragClass={dragClass}
onOpenMenu={onOpenMenu}
>
{headerContent}
</HoverWidget>
@ -192,6 +203,7 @@ export function PanelChrome({
dragClassCancel,
showOnHoverClass
)}
onOpenMenu={onOpenMenu}
/>
)}
</div>

@ -1,5 +1,5 @@
import { cx } from '@emotion/css';
import React, { ReactElement } from 'react';
import React, { ReactElement, useCallback } from 'react';
import { selectors } from '@grafana/e2e-selectors';
@ -15,6 +15,7 @@ interface PanelMenuProps {
placement?: TooltipPlacement;
offset?: [number, number];
onVisibleChange?: (state: boolean) => void;
onOpenMenu?: () => void;
}
export function PanelMenu({
@ -25,10 +26,22 @@ export function PanelMenu({
dragClassCancel,
menuButtonClass,
onVisibleChange,
onOpenMenu,
}: PanelMenuProps) {
const testId = title ? selectors.components.Panels.Panel.menu(title) : `panel-menu-button`;
const handleVisibility = useCallback(
(show: boolean) => {
if (show && onOpenMenu) {
onOpenMenu();
}
return onVisibleChange;
},
[onOpenMenu, onVisibleChange]
);
return (
<Dropdown overlay={menu} placement={placement} offset={offset} onVisibleChange={onVisibleChange}>
<Dropdown overlay={menu} placement={placement} offset={offset} onVisibleChange={handleVisibility}>
<ToolbarButton
aria-label={`Menu for panel with ${title ? `title ${title}` : 'no title'}`}
title="Menu"

@ -229,6 +229,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
hoverHeader={panelChromeProps.hasOverlayHeader()}
displayMode={transparent ? 'transparent' : 'default'}
onCancelQuery={panelChromeProps.onCancelQuery}
onOpenMenu={panelChromeProps.onOpenMenu}
>
{() => <div ref={(element) => (this.element = element)} className="panel-height-helper" />}
</PanelChrome>

@ -3,6 +3,7 @@ import React from 'react';
import { DataLink, GrafanaTheme2, PanelData } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { reportInteraction } from '@grafana/runtime';
import { Icon, useStyles2, ClickOutsideWrapper } from '@grafana/ui';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
@ -33,6 +34,10 @@ export function PanelHeader({ panel, error, isViewing, isEditing, data, alertSta
const className = cx('panel-header', !(isViewing || isEditing) ? 'grid-drag-handle' : '');
const styles = useStyles2(panelStyles);
const onOpenMenu = () => {
reportInteraction('dashboards_panelheader_menu', { item: 'menu' });
};
return (
<>
<PanelHeaderLoadingIndicator state={data.state} onClick={onCancelQuery} />
@ -45,7 +50,7 @@ export function PanelHeader({ panel, error, isViewing, isEditing, data, alertSta
error={error}
/>
<div className={className}>
<PanelHeaderMenuTrigger data-testid={selectors.components.Panels.Panel.title(title)}>
<PanelHeaderMenuTrigger data-testid={selectors.components.Panels.Panel.title(title)} onOpenMenu={onOpenMenu}>
{({ closeMenu, panelMenuOpen }) => {
return (
<ClickOutsideWrapper onClick={closeMenu} parent={document}>

@ -9,9 +9,10 @@ interface PanelHeaderMenuTriggerApi {
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
children: (props: PanelHeaderMenuTriggerApi) => ReactElement;
onOpenMenu?: () => void;
}
export function PanelHeaderMenuTrigger({ children, ...divProps }: Props) {
export function PanelHeaderMenuTrigger({ children, onOpenMenu, ...divProps }: Props) {
const clickCoordinates = useRef<CartesianCoords2D>({ x: 0, y: 0 });
const [panelMenuOpen, setPanelMenuOpen] = useState<boolean>(false);
@ -22,8 +23,11 @@ export function PanelHeaderMenuTrigger({ children, ...divProps }: Props) {
}
setPanelMenuOpen(!panelMenuOpen);
if (panelMenuOpen) {
onOpenMenu?.();
}
},
[panelMenuOpen, setPanelMenuOpen]
[panelMenuOpen, setPanelMenuOpen, onOpenMenu]
);
const onMouseDown = useCallback((event: MouseEvent<HTMLDivElement>) => {

@ -646,6 +646,7 @@ export class PanelStateWrapper extends PureComponent<Props, State> {
hoverHeader={panelChromeProps.hasOverlayHeader()}
displayMode={transparent ? 'transparent' : 'default'}
onCancelQuery={panelChromeProps.onCancelQuery}
onOpenMenu={panelChromeProps.onOpenMenu}
>
{(innerWidth, innerHeight) => (
<>

@ -106,6 +106,10 @@ export function getPanelChromeProps(props: CommonProps) {
const title = props.panel.getDisplayTitle();
const onOpenMenu = () => {
reportInteraction('dashboards_panelheader_menu', { item: 'menu' });
};
return {
hasOverlayHeader,
onShowPanelDescription,
@ -118,5 +122,6 @@ export function getPanelChromeProps(props: CommonProps) {
dragClass,
title,
titleItems,
onOpenMenu,
};
}

@ -40,7 +40,7 @@ export function getPanelMenu(
locationService.partial({
viewPanel: panel.id,
});
reportInteraction('dashboards_panelheader_view_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'view' });
};
const onEditPanel = (event: React.MouseEvent<any>) => {
@ -48,25 +48,26 @@ export function getPanelMenu(
locationService.partial({
editPanel: panel.id,
});
reportInteraction('dashboards_panelheader_edit_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'edit' });
};
const onSharePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
sharePanel(dashboard, panel);
reportInteraction('dashboards_panelheader_share_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'share' });
};
const onAddLibraryPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
addLibraryPanel(dashboard, panel);
reportInteraction('dashboards_panelheader_createlibrarypanel_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'createLibraryPanel' });
};
const onUnlinkLibraryPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
unlinkLibraryPanel(panel);
reportInteraction('dashboards_panelheader_unlinklibrarypanel_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'unlinkLibraryPanel' });
};
const onInspectPanel = (tab?: InspectTab) => {
@ -74,7 +75,7 @@ export function getPanelMenu(
inspect: panel.id,
inspectTab: tab,
});
reportInteraction('dashboards_panelheader_inspect_clicked', { tab: tab ?? InspectTab.Data });
reportInteraction('dashboards_panelheader_menu', { item: 'inspect', tab: tab ?? InspectTab.Data });
};
const onMore = (event: React.MouseEvent<any>) => {
@ -84,19 +85,19 @@ export function getPanelMenu(
const onDuplicatePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
duplicatePanel(dashboard, panel);
reportInteraction('dashboards_panelheader_duplicate_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'duplicate' });
};
const onCopyPanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
copyPanel(panel);
reportInteraction('dashboards_panelheader_copy_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'copy' });
};
const onRemovePanel = (event: React.MouseEvent<any>) => {
event.preventDefault();
removePanel(dashboard, panel, true);
reportInteraction('dashboards_panelheader_remove_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'remove' });
};
const onNavigateToExplore = (event: React.MouseEvent<any>) => {
@ -104,13 +105,13 @@ export function getPanelMenu(
const openInNewWindow =
event.ctrlKey || event.metaKey ? (url: string) => window.open(`${config.appSubUrl}${url}`) : undefined;
store.dispatch(navigateToExplore(panel, { getDataSourceSrv, getTimeSrv, getExploreUrl, openInNewWindow }) as any);
reportInteraction('dashboards_panelheader_explore_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'explore' });
};
const onToggleLegend = (event: React.MouseEvent) => {
event.preventDefault();
toggleLegend(panel);
reportInteraction('dashboards_panelheader_togglelegend_clicked');
reportInteraction('dashboards_panelheader_menu', { item: 'toggleLegend' });
};
const menu: PanelMenuItem[] = [];

Loading…
Cancel
Save