feat: pass orgrole when adding rs event (#94890)

* chore: pass orgRole, orgId for RS event report

* chore: track panel plugin search

* ref: extract interaction const to separate file
This commit is contained in:
Syerikjan Kh 2024-10-21 12:22:51 -04:00 committed by GitHub
parent 8abfcdbb78
commit 20a33632bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 49 additions and 5 deletions

View File

@ -24,17 +24,25 @@ export interface EchoMeta {
*/ */
sessionId: string; sessionId: string;
/** /**
* The current users username used to login into Grafana e.g. email. * The current user's username used to login into Grafana e.g. email.
*/ */
userLogin: string; userLogin: string;
/** /**
* The current users unique identifier. * The current user's unique identifier.
*/ */
userId: number; userId: number;
/** /**
* True when user is logged in into Grafana. * True when user is logged in into Grafana.
*/ */
userSignedIn: boolean; userSignedIn: boolean;
/**
* Current user's role
*/
orgRole: string | '';
/**
* Current user's org
*/
orgId: number;
/** /**
* A millisecond epoch * A millisecond epoch
*/ */

View File

@ -72,6 +72,8 @@ export class Echo implements EchoSrv {
userId: contextSrv.user.id, userId: contextSrv.user.id,
userLogin: contextSrv.user.login, userLogin: contextSrv.user.login,
userSignedIn: contextSrv.user.isSignedIn, userSignedIn: contextSrv.user.isSignedIn,
orgRole: contextSrv.user.orgRole,
orgId: contextSrv.user.orgId,
screenSize: { screenSize: {
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight, height: window.innerHeight,

View File

@ -11,7 +11,7 @@ import {
PluginType, PluginType,
} from '@grafana/data'; } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime'; import { config, locationService, reportInteraction } from '@grafana/runtime';
import { import {
DeepPartial, DeepPartial,
SceneComponentProps, SceneComponentProps,
@ -33,6 +33,7 @@ import { isUsingAngularPanelPlugin } from '../scene/angular/AngularDeprecation';
import { PanelOptions } from './PanelOptions'; import { PanelOptions } from './PanelOptions';
import { PanelVizTypePicker } from './PanelVizTypePicker'; import { PanelVizTypePicker } from './PanelVizTypePicker';
import { INTERACTION_EVENT_NAME, INTERACTION_ITEM } from './interaction';
export interface PanelOptionsPaneState extends SceneObjectState { export interface PanelOptionsPaneState extends SceneObjectState {
isVizPickerOpen?: boolean; isVizPickerOpen?: boolean;
@ -50,6 +51,10 @@ export class PanelOptionsPane extends SceneObjectBase<PanelOptionsPaneState> {
private _cachedPluginOptions: Record<string, PluginOptionsCache | undefined> = {}; private _cachedPluginOptions: Record<string, PluginOptionsCache | undefined> = {};
onToggleVizPicker = () => { onToggleVizPicker = () => {
reportInteraction(INTERACTION_EVENT_NAME, {
item: INTERACTION_ITEM.TOGGLE_DROPDOWN,
open: !this.state.isVizPickerOpen,
});
this.setState({ isVizPickerOpen: !this.state.isVizPickerOpen }); this.setState({ isVizPickerOpen: !this.state.isVizPickerOpen });
}; };
@ -57,6 +62,10 @@ export class PanelOptionsPane extends SceneObjectBase<PanelOptionsPaneState> {
const panel = this.state.panelRef.resolve(); const panel = this.state.panelRef.resolve();
const { options: prevOptions, fieldConfig: prevFieldConfig, pluginId: prevPluginId } = panel.state; const { options: prevOptions, fieldConfig: prevFieldConfig, pluginId: prevPluginId } = panel.state;
const pluginId = options.pluginId; const pluginId = options.pluginId;
reportInteraction(INTERACTION_EVENT_NAME, {
item: INTERACTION_ITEM.SELECT_PANEL_PLUGIN,
plugin_id: pluginId,
});
// clear custom options // clear custom options
let newFieldConfig: FieldConfigSource = { let newFieldConfig: FieldConfigSource = {

View File

@ -4,6 +4,7 @@ import { useLocalStorage } from 'react-use';
import { GrafanaTheme2, PanelData, SelectableValue } from '@grafana/data'; import { GrafanaTheme2, PanelData, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { reportInteraction } from '@grafana/runtime';
import { VizPanel } from '@grafana/scenes'; import { VizPanel } from '@grafana/scenes';
import { Button, CustomScrollbar, Field, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui'; import { Button, CustomScrollbar, Field, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui';
import { LS_VISUALIZATION_SELECT_TAB_KEY, LS_WIDGET_SELECT_TAB_KEY } from 'app/core/constants'; import { LS_VISUALIZATION_SELECT_TAB_KEY, LS_WIDGET_SELECT_TAB_KEY } from 'app/core/constants';
@ -14,6 +15,8 @@ import { VizTypeChangeDetails } from 'app/features/panel/components/VizTypePicke
import { PanelModelCompatibilityWrapper } from '../utils/PanelModelCompatibilityWrapper'; import { PanelModelCompatibilityWrapper } from '../utils/PanelModelCompatibilityWrapper';
import { INTERACTION_EVENT_NAME, INTERACTION_ITEM } from './interaction';
export interface Props { export interface Props {
data?: PanelData; data?: PanelData;
panel: VizPanel; panel: VizPanel;
@ -25,6 +28,13 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const handleSearchChange = (value: string) => {
if (value) {
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.SEARCH, query: value });
}
setSearchQuery(value);
};
const isWidgetEnabled = false; const isWidgetEnabled = false;
const tabKey = isWidgetEnabled ? LS_WIDGET_SELECT_TAB_KEY : LS_VISUALIZATION_SELECT_TAB_KEY; const tabKey = isWidgetEnabled ? LS_WIDGET_SELECT_TAB_KEY : LS_VISUALIZATION_SELECT_TAB_KEY;
const defaultTab = isWidgetEnabled ? VisualizationSelectPaneTab.Widgets : VisualizationSelectPaneTab.Visualizations; const defaultTab = isWidgetEnabled ? VisualizationSelectPaneTab.Widgets : VisualizationSelectPaneTab.Visualizations;
@ -40,6 +50,14 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
[] []
); );
const [listMode, setListMode] = useLocalStorage(tabKey, defaultTab); const [listMode, setListMode] = useLocalStorage(tabKey, defaultTab);
const handleListModeChange = (value: VisualizationSelectPaneTab) => {
reportInteraction(INTERACTION_EVENT_NAME, {
item: INTERACTION_ITEM.CHANGE_TAB,
tab: VisualizationSelectPaneTab[value],
});
setListMode(value);
};
useEffect(() => { useEffect(() => {
if (listMode && !supportedListModes.has(listMode)) { if (listMode && !supportedListModes.has(listMode)) {
setListMode(defaultTab); setListMode(defaultTab);
@ -57,7 +75,7 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
<FilterInput <FilterInput
className={styles.filter} className={styles.filter}
value={searchQuery} value={searchQuery}
onChange={setSearchQuery} onChange={handleSearchChange}
autoFocus={true} autoFocus={true}
placeholder="Search for..." placeholder="Search for..."
/> />
@ -71,7 +89,7 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
/> />
</div> </div>
<Field className={styles.customFieldMargin}> <Field className={styles.customFieldMargin}>
<RadioButtonGroup options={radioOptions} value={listMode} onChange={setListMode} fullWidth /> <RadioButtonGroup options={radioOptions} value={listMode} onChange={handleListModeChange} fullWidth />
</Field> </Field>
<CustomScrollbar> <CustomScrollbar>
{listMode === VisualizationSelectPaneTab.Visualizations && ( {listMode === VisualizationSelectPaneTab.Visualizations && (

View File

@ -0,0 +1,7 @@
export const INTERACTION_EVENT_NAME = 'dashboards_panel_plugin_picker_clicked';
export const INTERACTION_ITEM = {
TOGGLE_DROPDOWN: 'toggle_panel_plugin_picker',
SELECT_PANEL_PLUGIN: 'select_panel_plugin',
CHANGE_TAB: 'change_tab', // for ref - PanelVizTypePicker
SEARCH: 'search', // for ref - PanelVizTypePicker
};