Files
grafana/public/app/features/dashboard/components/ShareModal/ShareModal.tsx
Polina Boneva c5b399dc99 Dashboard: Add analytics events for sharing a dashboard (#72613)
* activeTab for public dashboard matches others

* add analytics action for going through categories of sharing modal

* add analytics for going through actions of any cateogry in sharing modal

* change 'tab' to 'category'; add key 'sharing_category' to actions for easier distinction

* sharedCategory sounds like a category is shared; changed naming to shareDashboardType

* remove hard-coded analytic event name

* wrap the reportInteraction call for all actions when sharing dashboard

---------

Co-authored-by: Alexandra Vargas <alexa1866@gmail.com>
2023-08-03 16:41:26 +03:00

168 lines
4.9 KiB
TypeScript

import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Modal, ModalTabsHeader, TabContent, Themeable2, withTheme2 } from '@grafana/ui';
import { config } from 'app/core/config';
import { contextSrv } from 'app/core/core';
import { t } from 'app/core/internationalization';
import { SharePublicDashboard } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard';
import { ShareEmbed } from './ShareEmbed';
import { ShareExport } from './ShareExport';
import { ShareLibraryPanel } from './ShareLibraryPanel';
import { ShareLink } from './ShareLink';
import { ShareSnapshot } from './ShareSnapshot';
import { trackDashboardSharingTypeOpen } from './analytics';
import { ShareModalTabModel } from './types';
import { shareDashboardType } from './utils';
const customDashboardTabs: ShareModalTabModel[] = [];
const customPanelTabs: ShareModalTabModel[] = [];
export function addDashboardShareTab(tab: ShareModalTabModel) {
customDashboardTabs.push(tab);
}
export function addPanelShareTab(tab: ShareModalTabModel) {
customPanelTabs.push(tab);
}
function getTabs(panel?: PanelModel, activeTab?: string) {
const linkLabel = t('share-modal.tab-title.link', 'Link');
const tabs: ShareModalTabModel[] = [{ label: linkLabel, value: shareDashboardType.link, component: ShareLink }];
if (contextSrv.isSignedIn && config.snapshotEnabled) {
const snapshotLabel = t('share-modal.tab-title.snapshot', 'Snapshot');
tabs.push({ label: snapshotLabel, value: shareDashboardType.snapshot, component: ShareSnapshot });
}
if (panel) {
const embedLabel = t('share-modal.tab-title.embed', 'Embed');
tabs.push({ label: embedLabel, value: shareDashboardType.embed, component: ShareEmbed });
if (!isPanelModelLibraryPanel(panel)) {
const libraryPanelLabel = t('share-modal.tab-title.library-panel', 'Library panel');
tabs.push({ label: libraryPanelLabel, value: shareDashboardType.libraryPanel, component: ShareLibraryPanel });
}
tabs.push(...customPanelTabs);
} else {
const exportLabel = t('share-modal.tab-title.export', 'Export');
tabs.push({
label: exportLabel,
value: shareDashboardType.export,
component: ShareExport,
});
tabs.push(...customDashboardTabs);
}
if (Boolean(config.featureToggles['publicDashboards'])) {
tabs.push({
label: 'Public dashboard',
value: shareDashboardType.publicDashboard,
component: SharePublicDashboard,
});
}
const at = tabs.find((t) => t.value === activeTab);
return {
tabs,
activeTab: at?.value ?? tabs[0].value,
};
}
interface Props extends Themeable2 {
dashboard: DashboardModel;
panel?: PanelModel;
activeTab?: string;
onDismiss(): void;
}
interface State {
tabs: ShareModalTabModel[];
activeTab: string;
}
function getInitialState(props: Props): State {
const { tabs, activeTab } = getTabs(props.panel, props.activeTab);
return {
tabs,
activeTab,
};
}
class UnthemedShareModal extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = getInitialState(props);
}
onSelectTab: React.ComponentProps<typeof ModalTabsHeader>['onChangeTab'] = (t) => {
this.setState((prevState) => ({ ...prevState, activeTab: t.value }));
trackDashboardSharingTypeOpen(t.value);
};
getActiveTab() {
const { tabs, activeTab } = this.state;
return tabs.find((t) => t.value === activeTab)!;
}
renderTitle() {
const { panel } = this.props;
const { activeTab } = this.state;
const title = panel ? t('share-modal.panel.title', 'Share Panel') : t('share-modal.dashboard.title', 'Share');
const tabs = getTabs(this.props.panel, this.state.activeTab).tabs;
return (
<ModalTabsHeader
title={title}
icon="share-alt"
tabs={tabs}
activeTab={activeTab}
onChangeTab={this.onSelectTab}
/>
);
}
render() {
const { dashboard, panel, theme } = this.props;
const styles = getStyles(theme);
const activeTabModel = this.getActiveTab();
const ActiveTab = activeTabModel.component;
return (
<Modal
isOpen={true}
title={this.renderTitle()}
onDismiss={this.props.onDismiss}
className={styles.container}
contentClassName={styles.content}
>
<TabContent>
<ActiveTab dashboard={dashboard} panel={panel} onDismiss={this.props.onDismiss} />
</TabContent>
</Modal>
);
}
}
export const ShareModal = withTheme2(UnthemedShareModal);
const getStyles = (theme: GrafanaTheme2) => {
return {
container: css({
label: 'shareModalContainer',
paddingTop: theme.spacing(1),
}),
content: css({
label: 'shareModalContent',
padding: theme.spacing(3, 2, 2, 2),
}),
};
};