mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Analytics: send dashboard_list_viewed events to rudderstack (#44589)
* #44449: report interactions with showPreviews toggle * #44449: hookify showPreviews * #44449: report dashboard_list_viewed event rather than enabled/disabled_dashboard_previews
This commit is contained in:
parent
e39d43db0a
commit
6e1615b42a
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { locationService, setEchoSrv } from '@grafana/runtime';
|
||||
import { selectOptionInTest } from '@grafana/ui';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
@ -9,6 +9,7 @@ import * as MockSearchSrv from 'app/core/services/__mocks__/search_srv';
|
||||
import { DashboardSearch, Props } from './DashboardSearch';
|
||||
import { searchResults } from '../testData';
|
||||
import { SearchLayout } from '../types';
|
||||
import { Echo } from 'app/core/services/echo/Echo';
|
||||
|
||||
jest.mock('app/core/services/search_srv');
|
||||
// Typecast the mock search so the mock import is correctly recognised by TS
|
||||
@ -38,6 +39,10 @@ const setup = (testProps?: Partial<Props>) => {
|
||||
* calls inside useDebounce hook
|
||||
*/
|
||||
describe('DashboardSearch', () => {
|
||||
beforeAll(() => {
|
||||
setEchoSrv(new Echo());
|
||||
});
|
||||
|
||||
it('should call search api with default query when initialised', async () => {
|
||||
locationService.push('/');
|
||||
setup();
|
||||
|
@ -1,15 +1,12 @@
|
||||
import React, { FC, memo } from 'react';
|
||||
import { useLocalStorage } from 'react-use';
|
||||
import { css } from '@emotion/css';
|
||||
import { useTheme2, CustomScrollbar, stylesFactory, IconButton } from '@grafana/ui';
|
||||
import { CustomScrollbar, IconButton, stylesFactory, useTheme2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { useSearchQuery } from '../hooks/useSearchQuery';
|
||||
import { useDashboardSearch } from '../hooks/useDashboardSearch';
|
||||
import { SearchField } from './SearchField';
|
||||
import { SearchResults } from './SearchResults';
|
||||
import { ActionRow } from './ActionRow';
|
||||
import { PREVIEWS_LOCAL_STORAGE_KEY } from '../constants';
|
||||
|
||||
export interface Props {
|
||||
onCloseSearch: () => void;
|
||||
@ -17,14 +14,12 @@ export interface Props {
|
||||
|
||||
export const DashboardSearch: FC<Props> = memo(({ onCloseSearch }) => {
|
||||
const { query, onQueryChange, onTagFilterChange, onTagAdd, onSortChange, onLayoutChange } = useSearchQuery({});
|
||||
const { results, loading, onToggleSection, onKeyDown } = useDashboardSearch(query, onCloseSearch);
|
||||
const { results, loading, onToggleSection, onKeyDown, showPreviews, onShowPreviewsChange } = useDashboardSearch(
|
||||
query,
|
||||
onCloseSearch
|
||||
);
|
||||
const theme = useTheme2();
|
||||
const styles = getStyles(theme);
|
||||
const previewsEnabled = config.featureToggles.dashboardPreviews;
|
||||
const [showPreviews, setShowPreviews] = useLocalStorage<boolean>(PREVIEWS_LOCAL_STORAGE_KEY, previewsEnabled);
|
||||
const onShowPreviewsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setShowPreviews(event.target.checked);
|
||||
};
|
||||
|
||||
return (
|
||||
<div tabIndex={0} className={styles.overlay}>
|
||||
@ -39,7 +34,7 @@ export const DashboardSearch: FC<Props> = memo(({ onCloseSearch }) => {
|
||||
<ActionRow
|
||||
{...{
|
||||
onLayoutChange,
|
||||
onShowPreviewsChange,
|
||||
onShowPreviewsChange: (ev) => onShowPreviewsChange(ev.target.checked),
|
||||
onSortChange,
|
||||
onTagFilterChange,
|
||||
query,
|
||||
@ -54,7 +49,7 @@ export const DashboardSearch: FC<Props> = memo(({ onCloseSearch }) => {
|
||||
editable={false}
|
||||
onToggleSection={onToggleSection}
|
||||
layout={query.layout}
|
||||
showPreviews={previewsEnabled && showPreviews}
|
||||
showPreviews={showPreviews}
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React, { FC, memo, useState } from 'react';
|
||||
import { useLocalStorage } from 'react-use';
|
||||
import { css } from '@emotion/css';
|
||||
import { stylesFactory, useTheme, Spinner, FilterInput } from '@grafana/ui';
|
||||
import { FilterInput, Spinner, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import { FolderDTO } from 'app/types';
|
||||
@ -15,7 +13,6 @@ import { useSearchQuery } from '../hooks/useSearchQuery';
|
||||
import { SearchResultsFilter } from './SearchResultsFilter';
|
||||
import { SearchResults } from './SearchResults';
|
||||
import { DashboardActions } from './DashboardActions';
|
||||
import { PREVIEWS_LOCAL_STORAGE_KEY } from '../constants';
|
||||
|
||||
export interface Props {
|
||||
folder?: FolderDTO;
|
||||
@ -24,11 +21,6 @@ export interface Props {
|
||||
const { isEditor } = contextSrv;
|
||||
|
||||
export const ManageDashboards: FC<Props> = memo(({ folder }) => {
|
||||
const previewsEnabled = Boolean(config.featureToggles.dashboardPreviews);
|
||||
const [showPreviews, setShowPreviews] = useLocalStorage<boolean>(PREVIEWS_LOCAL_STORAGE_KEY, true);
|
||||
const onShowPreviewsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setShowPreviews(event.target.checked);
|
||||
};
|
||||
const folderId = folder?.id;
|
||||
const folderUid = folder?.uid;
|
||||
const theme = useTheme();
|
||||
@ -69,6 +61,8 @@ export const ManageDashboards: FC<Props> = memo(({ folder }) => {
|
||||
onDeleteItems,
|
||||
onMoveItems,
|
||||
noFolders,
|
||||
showPreviews,
|
||||
onShowPreviewsChange,
|
||||
} = useManageDashboards(query, {}, folder);
|
||||
|
||||
const onMoveTo = () => {
|
||||
@ -114,13 +108,13 @@ export const ManageDashboards: FC<Props> = memo(({ folder }) => {
|
||||
canMove={hasEditPermissionInFolders && canMove}
|
||||
deleteItem={onItemDelete}
|
||||
moveTo={onMoveTo}
|
||||
onShowPreviewsChange={onShowPreviewsChange}
|
||||
onShowPreviewsChange={(ev) => onShowPreviewsChange(ev.target.checked)}
|
||||
onToggleAllChecked={onToggleAllChecked}
|
||||
onStarredFilterChange={onStarredFilterChange}
|
||||
onSortChange={onSortChange}
|
||||
onTagFilterChange={onTagFilterChange}
|
||||
query={query}
|
||||
showPreviews={previewsEnabled && showPreviews}
|
||||
showPreviews={showPreviews}
|
||||
hideLayout={!!folderUid}
|
||||
onLayoutChange={onLayoutChange}
|
||||
editable={hasEditPermissionInFolders}
|
||||
@ -133,7 +127,7 @@ export const ManageDashboards: FC<Props> = memo(({ folder }) => {
|
||||
onToggleSection={onToggleSection}
|
||||
onToggleChecked={onToggleChecked}
|
||||
layout={query.layout}
|
||||
showPreviews={previewsEnabled && showPreviews}
|
||||
showPreviews={showPreviews}
|
||||
/>
|
||||
</div>
|
||||
<ConfirmDeleteModal
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { KeyboardEvent, useReducer } from 'react';
|
||||
import { KeyboardEvent, useEffect, useReducer } from 'react';
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
import { DashboardQuery, DashboardSearchItemType, DashboardSection } from '../types';
|
||||
import { MOVE_SELECTION_DOWN, MOVE_SELECTION_UP } from '../reducers/actionTypes';
|
||||
@ -6,15 +6,22 @@ import { dashboardsSearchState, DashboardsSearchState, searchReducer } from '../
|
||||
import { findSelected } from '../utils';
|
||||
import { useSearch } from './useSearch';
|
||||
import { locationUtil } from '@grafana/data';
|
||||
import { useShowDashboardPreviews } from './useShowDashboardPreviews';
|
||||
import { reportDashboardListViewed } from './useManageDashboards';
|
||||
|
||||
export const useDashboardSearch = (query: DashboardQuery, onCloseSearch: () => void) => {
|
||||
const reducer = useReducer(searchReducer, dashboardsSearchState);
|
||||
const { showPreviews, onShowPreviewsChange, previewFeatureEnabled } = useShowDashboardPreviews();
|
||||
const {
|
||||
state: { results, loading },
|
||||
onToggleSection,
|
||||
dispatch,
|
||||
} = useSearch<DashboardsSearchState>(query, reducer, { queryParsing: true });
|
||||
|
||||
useEffect(() => {
|
||||
reportDashboardListViewed('dashboard_search', showPreviews, previewFeatureEnabled, query.layout);
|
||||
}, [showPreviews, previewFeatureEnabled, query.layout]);
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
@ -47,5 +54,7 @@ export const useDashboardSearch = (query: DashboardQuery, onCloseSearch: () => v
|
||||
loading,
|
||||
onToggleSection,
|
||||
onKeyDown,
|
||||
showPreviews,
|
||||
onShowPreviewsChange,
|
||||
};
|
||||
};
|
||||
|
@ -6,11 +6,17 @@ import { DashboardQuery, DashboardSearchItemType, DashboardSection, SearchAction
|
||||
import { ManageDashboardsState } from '../reducers/manageDashboards';
|
||||
import { useManageDashboards } from './useManageDashboards';
|
||||
import { GENERAL_FOLDER_ID } from '../constants';
|
||||
import { setEchoSrv } from '@grafana/runtime/src';
|
||||
import { Echo } from 'app/core/services/echo/Echo';
|
||||
|
||||
describe('useManageDashboards', () => {
|
||||
const useSearchMock = jest.spyOn(useSearch, 'useSearch');
|
||||
const toggle = async (section: DashboardSection) => section;
|
||||
|
||||
beforeAll(() => {
|
||||
setEchoSrv(new Echo());
|
||||
});
|
||||
|
||||
function setupTestContext({ results = [] }: { results?: DashboardSection[] } = {}) {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
@ -1,16 +1,31 @@
|
||||
import { useCallback, useMemo, useReducer } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useReducer } from 'react';
|
||||
import { FolderDTO } from 'app/types';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import { DashboardQuery, DashboardSection, OnDeleteItems, OnMoveItems, OnToggleChecked } from '../types';
|
||||
import { DashboardQuery, DashboardSection, OnDeleteItems, OnMoveItems, OnToggleChecked, SearchLayout } from '../types';
|
||||
import { DELETE_ITEMS, MOVE_ITEMS, TOGGLE_ALL_CHECKED, TOGGLE_CHECKED } from '../reducers/actionTypes';
|
||||
import { manageDashboardsReducer, manageDashboardsState, ManageDashboardsState } from '../reducers/manageDashboards';
|
||||
import { useSearch } from './useSearch';
|
||||
import { GENERAL_FOLDER_ID } from '../constants';
|
||||
import { useShowDashboardPreviews } from './useShowDashboardPreviews';
|
||||
import { reportInteraction } from '@grafana/runtime/src';
|
||||
|
||||
const hasChecked = (section: DashboardSection) => {
|
||||
return section.checked || section.items.some((item) => item.checked);
|
||||
};
|
||||
|
||||
export const reportDashboardListViewed = (
|
||||
dashboardListType: 'manage_dashboards' | 'dashboard_search',
|
||||
showPreviews: boolean,
|
||||
previewsEnabled: boolean,
|
||||
searchLayout: SearchLayout
|
||||
) => {
|
||||
const previews = previewsEnabled ? (showPreviews ? 'on' : 'off') : 'feature_disabled';
|
||||
reportInteraction(`${dashboardListType}_viewed`, {
|
||||
previews,
|
||||
layout: searchLayout,
|
||||
});
|
||||
};
|
||||
|
||||
export const useManageDashboards = (
|
||||
query: DashboardQuery,
|
||||
state: Partial<ManageDashboardsState> = {},
|
||||
@ -21,6 +36,11 @@ export const useManageDashboards = (
|
||||
...state,
|
||||
});
|
||||
|
||||
const { showPreviews, onShowPreviewsChange, previewFeatureEnabled } = useShowDashboardPreviews();
|
||||
useEffect(() => {
|
||||
reportDashboardListViewed('manage_dashboards', showPreviews, previewFeatureEnabled, query.layout);
|
||||
}, [showPreviews, previewFeatureEnabled, query.layout]);
|
||||
|
||||
const {
|
||||
state: { results, loading, initialLoading, allChecked },
|
||||
onToggleSection,
|
||||
@ -73,5 +93,7 @@ export const useManageDashboards = (
|
||||
onDeleteItems,
|
||||
onMoveItems,
|
||||
noFolders,
|
||||
showPreviews,
|
||||
onShowPreviewsChange,
|
||||
};
|
||||
};
|
||||
|
13
public/app/features/search/hooks/useShowDashboardPreviews.ts
Normal file
13
public/app/features/search/hooks/useShowDashboardPreviews.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { PREVIEWS_LOCAL_STORAGE_KEY } from '../constants';
|
||||
import { config } from '@grafana/runtime/src';
|
||||
import { useLocalStorage } from 'react-use';
|
||||
|
||||
export const useShowDashboardPreviews = () => {
|
||||
const previewFeatureEnabled = Boolean(config.featureToggles.dashboardPreviews);
|
||||
const [showPreviews, setShowPreviews] = useLocalStorage<boolean>(PREVIEWS_LOCAL_STORAGE_KEY, previewFeatureEnabled);
|
||||
const onShowPreviewsChange = (showPreviews: boolean) => {
|
||||
setShowPreviews(showPreviews);
|
||||
};
|
||||
|
||||
return { showPreviews: Boolean(showPreviews && previewFeatureEnabled), previewFeatureEnabled, onShowPreviewsChange };
|
||||
};
|
Loading…
Reference in New Issue
Block a user