mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add analytics to new DS picker and onboarding experience (#67060)
* Add analytics to ds picker advanced mode * Add analytics to ds picker dropdown
This commit is contained in:
parent
ad964a0e1d
commit
581cc85ba5
@ -6,6 +6,7 @@ import React, { useCallback, useRef, useState } from 'react';
|
||||
import { usePopper } from 'react-popper';
|
||||
|
||||
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { DataSourceJsonData } from '@grafana/schema';
|
||||
import { Button, CustomScrollbar, Icon, Input, ModalsController, Portal, useStyles2 } from '@grafana/ui';
|
||||
import config from 'app/core/config';
|
||||
@ -18,6 +19,14 @@ import { DataSourceModal } from './DataSourceModal';
|
||||
import { PickerContentProps, DataSourceDropdownProps } from './types';
|
||||
import { dataSourceLabel } from './utils';
|
||||
|
||||
const INTERACTION_EVENT_NAME = 'dashboards_dspicker_clicked';
|
||||
const INTERACTION_ITEM = {
|
||||
OPEN_DROPDOWN: 'open_dspicker',
|
||||
SELECT_DS: 'select_ds',
|
||||
ADD_FILE: 'add_file',
|
||||
OPEN_ADVANCED_DS_PICKER: 'open_advanced_ds_picker',
|
||||
};
|
||||
|
||||
export function DataSourceDropdown(props: DataSourceDropdownProps) {
|
||||
const { current, onChange, ...restProps } = props;
|
||||
|
||||
@ -25,6 +34,10 @@ export function DataSourceDropdown(props: DataSourceDropdownProps) {
|
||||
const [markerElement, setMarkerElement] = useState<HTMLInputElement | null>();
|
||||
const [selectorElement, setSelectorElement] = useState<HTMLDivElement | null>();
|
||||
const [filterTerm, setFilterTerm] = useState<string>();
|
||||
const openDropdown = () => {
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.OPEN_DROPDOWN });
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const currentDataSourceInstanceSettings = useDatasource(current);
|
||||
|
||||
@ -93,20 +106,13 @@ export function DataSourceDropdown(props: DataSourceDropdownProps) {
|
||||
</Portal>
|
||||
</FocusScope>
|
||||
) : (
|
||||
<div
|
||||
className={styles.trigger}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
<div className={styles.trigger} onClick={openDropdown}>
|
||||
<Input
|
||||
className={styles.input}
|
||||
prefix={<DataSourceLogo dataSource={currentDataSourceInstanceSettings} />}
|
||||
suffix={<Icon name="angle-down" />}
|
||||
value={dataSourceLabel(currentDataSourceInstanceSettings)}
|
||||
onFocus={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
onFocus={openDropdown}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -135,6 +141,7 @@ const PickerContent = React.forwardRef<HTMLDivElement, PickerContentProps>((prop
|
||||
const changeCallback = useCallback(
|
||||
(ds: DataSourceInstanceSettings<DataSourceJsonData>) => {
|
||||
onChange(ds);
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.SELECT_DS, ds_type: ds.type });
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
@ -142,6 +149,7 @@ const PickerContent = React.forwardRef<HTMLDivElement, PickerContentProps>((prop
|
||||
const clickAddCSVCallback = useCallback(() => {
|
||||
onClickAddCSV?.();
|
||||
onClose();
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.ADD_FILE });
|
||||
}, [onClickAddCSV, onClose]);
|
||||
|
||||
const styles = useStyles2(getStylesPickerContent);
|
||||
@ -176,6 +184,7 @@ const PickerContent = React.forwardRef<HTMLDivElement, PickerContentProps>((prop
|
||||
showModal(DataSourceModal, {
|
||||
enableFileUpload: props.enableFileUpload,
|
||||
fileUploadOptions: props.fileUploadOptions,
|
||||
reportedInteractionFrom: 'ds_picker',
|
||||
current,
|
||||
onDismiss: hideModal,
|
||||
onChange: (ds) => {
|
||||
@ -183,6 +192,7 @@ const PickerContent = React.forwardRef<HTMLDivElement, PickerContentProps>((prop
|
||||
hideModal();
|
||||
},
|
||||
});
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.OPEN_ADVANCED_DS_PICKER });
|
||||
}}
|
||||
>
|
||||
Open advanced data source picker
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { once } from 'lodash';
|
||||
import React, { useState } from 'react';
|
||||
import { DropzoneOptions } from 'react-dropzone';
|
||||
|
||||
import { DataSourceInstanceSettings, DataSourceRef, GrafanaTheme2 } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import {
|
||||
Modal,
|
||||
FileDropzone,
|
||||
@ -20,6 +22,15 @@ import { DATASOURCES_ROUTES } from 'app/features/datasources/constants';
|
||||
|
||||
import { DataSourceList } from './DataSourceList';
|
||||
|
||||
const INTERACTION_EVENT_NAME = 'dashboards_dspickermodal_clicked';
|
||||
const INTERACTION_ITEM = {
|
||||
SELECT_DS: 'select_ds',
|
||||
UPLOAD_FILE: 'upload_file',
|
||||
CONFIG_NEW_DS: 'config_new_ds',
|
||||
SEARCH: 'search',
|
||||
DISMISS: 'dismiss',
|
||||
};
|
||||
|
||||
interface DataSourceModalProps {
|
||||
onChange: (ds: DataSourceInstanceSettings) => void;
|
||||
current: DataSourceRef | string | null | undefined;
|
||||
@ -27,6 +38,7 @@ interface DataSourceModalProps {
|
||||
recentlyUsed?: string[];
|
||||
enableFileUpload?: boolean;
|
||||
fileUploadOptions?: DropzoneOptions;
|
||||
reportedInteractionFrom?: string;
|
||||
}
|
||||
|
||||
export function DataSourceModal({
|
||||
@ -35,13 +47,36 @@ export function DataSourceModal({
|
||||
onChange,
|
||||
current,
|
||||
onDismiss,
|
||||
reportedInteractionFrom,
|
||||
}: DataSourceModalProps) {
|
||||
const styles = useStyles2(getDataSourceModalStyles);
|
||||
const [search, setSearch] = useState('');
|
||||
const analyticsInteractionSrc = reportedInteractionFrom || 'modal';
|
||||
const newDataSourceURL = config.featureToggles.dataConnectionsConsole
|
||||
? CONNECTIONS_ROUTES.DataSourcesNew
|
||||
: DATASOURCES_ROUTES.New;
|
||||
|
||||
const onDismissModal = () => {
|
||||
onDismiss();
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: INTERACTION_ITEM.DISMISS, src: analyticsInteractionSrc });
|
||||
};
|
||||
const onChangeDataSource = (ds: DataSourceInstanceSettings) => {
|
||||
onChange(ds);
|
||||
reportInteraction(INTERACTION_EVENT_NAME, {
|
||||
item: INTERACTION_ITEM.SELECT_DS,
|
||||
ds_type: ds.type,
|
||||
src: analyticsInteractionSrc,
|
||||
});
|
||||
};
|
||||
// Memoizing to keep once() cached so it avoids reporting multiple times
|
||||
const reportSearchUsageOnce = React.useMemo(
|
||||
() =>
|
||||
once(() => {
|
||||
reportInteraction(INTERACTION_EVENT_NAME, { item: 'search', src: analyticsInteractionSrc });
|
||||
}),
|
||||
[analyticsInteractionSrc]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Select data source"
|
||||
@ -50,8 +85,8 @@ export function DataSourceModal({
|
||||
isOpen={true}
|
||||
className={styles.modal}
|
||||
contentClassName={styles.modalContent}
|
||||
onClickBackdrop={onDismiss}
|
||||
onDismiss={onDismiss}
|
||||
onClickBackdrop={onDismissModal}
|
||||
onDismiss={onDismissModal}
|
||||
>
|
||||
<div className={styles.leftColumn}>
|
||||
<Input
|
||||
@ -59,7 +94,10 @@ export function DataSourceModal({
|
||||
value={search}
|
||||
prefix={<Icon name="search" />}
|
||||
placeholder="Search data source"
|
||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
onChange={(e) => {
|
||||
setSearch(e.currentTarget.value);
|
||||
reportSearchUsageOnce();
|
||||
}}
|
||||
/>
|
||||
<CustomScrollbar>
|
||||
<DataSourceList
|
||||
@ -67,7 +105,7 @@ export function DataSourceModal({
|
||||
mixed={false}
|
||||
variables
|
||||
filter={(ds) => ds.name.includes(search) && !ds.meta.builtIn}
|
||||
onChange={onChange}
|
||||
onChange={onChangeDataSource}
|
||||
current={current}
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
@ -79,7 +117,7 @@ export function DataSourceModal({
|
||||
filter={(ds) => !!ds.meta.builtIn}
|
||||
dashboard
|
||||
mixed
|
||||
onChange={onChange}
|
||||
onChange={onChangeDataSource}
|
||||
current={current}
|
||||
/>
|
||||
{enableFileUpload && (
|
||||
@ -94,6 +132,10 @@ export function DataSourceModal({
|
||||
onDrop: (...args) => {
|
||||
fileUploadOptions?.onDrop?.(...args);
|
||||
onDismiss();
|
||||
reportInteraction(INTERACTION_EVENT_NAME, {
|
||||
item: INTERACTION_ITEM.UPLOAD_FILE,
|
||||
src: analyticsInteractionSrc,
|
||||
});
|
||||
},
|
||||
}}
|
||||
>
|
||||
@ -102,7 +144,16 @@ export function DataSourceModal({
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.dsCTAs}>
|
||||
<LinkButton variant="secondary" href={newDataSourceURL}>
|
||||
<LinkButton
|
||||
variant="secondary"
|
||||
href={newDataSourceURL}
|
||||
onClick={() => {
|
||||
reportInteraction(INTERACTION_EVENT_NAME, {
|
||||
item: INTERACTION_ITEM.CONFIG_NEW_DS,
|
||||
src: analyticsInteractionSrc,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Configure a new data source
|
||||
</LinkButton>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user