DatasourcePicker: Add favorite info in reported events (#109866)

This commit is contained in:
Andres Martinez Gotor
2025-08-21 11:27:05 +02:00
committed by GitHub
parent 29aff8c387
commit 7f044a1e3c
4 changed files with 28 additions and 18 deletions
@@ -11,8 +11,8 @@ const mockSetItem = jest.fn();
jest.mock('./userStorage', () => {
return {
UserStorage: jest.fn().mockImplementation(() => ({
getItem: mockGetItem,
setItem: mockSetItem,
getItem: (key: string) => mockGetItem(key),
setItem: (key: string, value: string) => mockSetItem(key, value),
})),
};
});
@@ -18,6 +18,9 @@ export type FavoriteDatasources = {
isFavoriteDatasource: (dsUid: string) => boolean;
};
// Initialize user storage as a singleton
const userStorage = new UserStorage('grafana-runtime');
/**
* A hook for managing favorite data sources using user storage.
* This hook provides functionality to store and retrieve a list of favorite data source UIDs
@@ -45,7 +48,6 @@ export function useFavoriteDatasources(): FavoriteDatasources {
};
}
const [userStorage] = useState(() => new UserStorage('grafana-runtime'));
const [favoriteDatasources, setFavoriteDatasources] = useState<string[]>([]);
const [initialFavoriteDataSources, setInitialFavoriteDataSources] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState(false);
@@ -64,18 +66,15 @@ export function useFavoriteDatasources(): FavoriteDatasources {
};
loadFavorites();
}, [userStorage]);
}, []);
// Helper function to save favorites to storage
const saveFavorites = useCallback(
async (newFavorites: string[]) => {
setIsLoading(true);
await userStorage.setItem(FAVORITE_DATASOURCES_KEY, JSON.stringify(newFavorites));
setFavoriteDatasources(newFavorites);
setIsLoading(false);
},
[userStorage]
);
const saveFavorites = useCallback(async (newFavorites: string[]) => {
setIsLoading(true);
await userStorage.setItem(FAVORITE_DATASOURCES_KEY, JSON.stringify(newFavorites));
setFavoriteDatasources(newFavorites);
setIsLoading(false);
}, []);
const addFavoriteDatasource = useCallback(
(ds: DataSourceInstanceSettings) => {
@@ -6,13 +6,14 @@ import { Observable } from 'rxjs';
import { DataSourceInstanceSettings, DataSourceJsonData, DataSourceRef, GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans } from '@grafana/i18n';
import { getTemplateSrv, useFavoriteDatasources } from '@grafana/runtime';
import { getTemplateSrv, reportInteraction, useFavoriteDatasources } from '@grafana/runtime';
import { useStyles2, useTheme2 } from '@grafana/ui';
import { useDatasources, useKeyboardNavigatableList, useRecentlyUsedDataSources } from '../../hooks';
import { AddNewDataSourceButton } from './AddNewDataSourceButton';
import { DataSourceCard } from './DataSourceCard';
import { INTERACTION_EVENT_NAME, INTERACTION_ITEM } from './DataSourcePicker';
import { getDataSourceCompareFn, isDataSourceMatch } from './utils';
/**
@@ -107,10 +108,15 @@ export function DataSourceList(props: DataSourceListProps) {
onChange(ds);
}}
selected={isDataSourceMatch(ds, current)}
isFavorite={favoriteDataSources.isFavoriteDatasource(ds.uid)}
isFavorite={favoriteDataSources.enabled ? favoriteDataSources.isFavoriteDatasource(ds.uid) : undefined}
onToggleFavorite={
favoriteDataSources.enabled
? () => {
reportInteraction(INTERACTION_EVENT_NAME, {
item: INTERACTION_ITEM.TOGGLE_FAVORITE,
ds_type: ds.type,
is_favorite: !favoriteDataSources.isFavoriteDatasource(ds.uid),
});
favoriteDataSources.isFavoriteDatasource(ds.uid)
? favoriteDataSources.removeFavoriteDatasource(ds)
: favoriteDataSources.addFavoriteDatasource(ds);
@@ -11,7 +11,7 @@ import { Observable } from 'rxjs';
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { reportInteraction } from '@grafana/runtime';
import { reportInteraction, useFavoriteDatasources } from '@grafana/runtime';
import { DataQuery, DataSourceJsonData, DataSourceRef } from '@grafana/schema';
import { Button, Icon, Input, ModalsController, Portal, ScrollContainer, useStyles2 } from '@grafana/ui';
import config from 'app/core/config';
@@ -25,14 +25,15 @@ import { DataSourceLogo, DataSourceLogoPlaceHolder } from './DataSourceLogo';
import { DataSourceModal } from './DataSourceModal';
import { dataSourceLabel, matchDataSourceWithSearch } from './utils';
const INTERACTION_EVENT_NAME = 'dashboards_dspicker_clicked';
const INTERACTION_ITEM = {
export const INTERACTION_EVENT_NAME = 'dashboards_dspicker_clicked';
export const INTERACTION_ITEM = {
SEARCH: 'search',
OPEN_DROPDOWN: 'open_dspicker',
SELECT_DS: 'select_ds',
ADD_FILE: 'add_file',
OPEN_ADVANCED_DS_PICKER: 'open_advanced_ds_picker',
CONFIG_NEW_DS_EMPTY_STATE: 'config_new_ds_empty_state',
TOGGLE_FAVORITE: 'toggle_favorite',
};
export interface DataSourcePickerProps {
@@ -114,6 +115,7 @@ export function DataSourcePicker(props: DataSourcePickerProps) {
type: props.type,
variables: props.variables,
});
const favoriteDataSources = useFavoriteDatasources();
// the order of middleware is important!
const middleware = [
@@ -298,6 +300,9 @@ export function DataSourcePicker(props: DataSourcePickerProps) {
reportInteraction(INTERACTION_EVENT_NAME, {
item: INTERACTION_ITEM.SELECT_DS,
ds_type: ds.type,
is_favorite: favoriteDataSources.enabled
? favoriteDataSources.isFavoriteDatasource(ds.uid)
: undefined,
});
}
}}