151 lines
4.9 KiB
TypeScript
151 lines
4.9 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { useCallback } from 'react';
|
|
import * as React from 'react';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
|
import { config, locationService } from '@grafana/runtime';
|
|
import { VizPanel } from '@grafana/scenes';
|
|
import { Icon, IconName, Menu, useStyles2 } from '@grafana/ui';
|
|
import { contextSrv } from 'app/core/core';
|
|
import { t } from 'app/core/internationalization';
|
|
import { AccessControlAction } from 'app/types';
|
|
|
|
import { isPublicDashboardsEnabled } from '../../../dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
|
import { getTrackingSource, shareDashboardType } from '../../../dashboard/components/ShareModal/utils';
|
|
import { getExternalUserMngLinkUrl } from '../../../users/utils';
|
|
import { DashboardScene } from '../../scene/DashboardScene';
|
|
import { DashboardInteractions } from '../../utils/interactions';
|
|
|
|
const newShareButtonSelector = e2eSelectors.pages.Dashboard.DashNav.newShareButton.menu;
|
|
|
|
export interface ShareDrawerMenuItem {
|
|
shareId: string;
|
|
testId: string;
|
|
label: string;
|
|
description?: string;
|
|
icon: IconName;
|
|
renderCondition: boolean;
|
|
onClick: (d: DashboardScene) => void;
|
|
renderDividerAbove?: boolean;
|
|
component?: React.ComponentType;
|
|
className?: string;
|
|
}
|
|
|
|
let customShareDrawerItems: ShareDrawerMenuItem[] = [];
|
|
|
|
export function addDashboardShareDrawerItem(item: ShareDrawerMenuItem) {
|
|
customShareDrawerItems.push(item);
|
|
}
|
|
|
|
export function resetDashboardShareDrawerItems() {
|
|
customShareDrawerItems = [];
|
|
}
|
|
|
|
export default function ShareMenu({ dashboard, panel }: { dashboard: DashboardScene; panel?: VizPanel }) {
|
|
const styles = useStyles2(getStyles);
|
|
const onMenuItemClick = (shareView: string) => {
|
|
locationService.partial({ shareView });
|
|
};
|
|
|
|
const buildMenuItems = useCallback(() => {
|
|
const menuItems: ShareDrawerMenuItem[] = [];
|
|
|
|
menuItems.push({
|
|
shareId: shareDashboardType.link,
|
|
testId: newShareButtonSelector.shareInternally,
|
|
icon: 'building',
|
|
label: t('share-dashboard.menu.share-internally-title', 'Share internally'),
|
|
renderCondition: true,
|
|
onClick: () => onMenuItemClick(shareDashboardType.link),
|
|
});
|
|
|
|
menuItems.push({
|
|
shareId: shareDashboardType.publicDashboard,
|
|
testId: newShareButtonSelector.shareExternally,
|
|
icon: 'share-alt',
|
|
label: t('share-dashboard.menu.share-externally-title', 'Share externally'),
|
|
renderCondition: !panel && isPublicDashboardsEnabled(),
|
|
onClick: () => {
|
|
onMenuItemClick(shareDashboardType.publicDashboard);
|
|
},
|
|
});
|
|
|
|
menuItems.push({
|
|
shareId: shareDashboardType.snapshot,
|
|
testId: newShareButtonSelector.shareSnapshot,
|
|
icon: 'camera',
|
|
label: t('share-dashboard.menu.share-snapshot-title', 'Share snapshot'),
|
|
renderCondition:
|
|
contextSrv.isSignedIn &&
|
|
config.snapshotEnabled &&
|
|
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate),
|
|
onClick: () => {
|
|
onMenuItemClick(shareDashboardType.snapshot);
|
|
},
|
|
});
|
|
|
|
customShareDrawerItems.forEach((d) => menuItems.push(d));
|
|
|
|
menuItems.push({
|
|
shareId: shareDashboardType.inviteUser,
|
|
testId: newShareButtonSelector.inviteUser,
|
|
icon: 'add-user',
|
|
label: t('share-dashboard.menu.invite-user-title', 'Invite new member'),
|
|
renderCondition: !!config.externalUserMngLinkUrl && contextSrv.hasPermission(AccessControlAction.OrgUsersAdd),
|
|
onClick: () => {
|
|
const url = getExternalUserMngLinkUrl('share-invite');
|
|
|
|
window.open(url.toString(), '_blank');
|
|
},
|
|
renderDividerAbove: true,
|
|
component: () => <Icon name="external-link-alt" className={styles.inviteUserItemIcon} />,
|
|
className: styles.inviteUserItem,
|
|
});
|
|
|
|
return menuItems.filter((item) => item.renderCondition);
|
|
}, [panel, styles]);
|
|
|
|
const onClick = (item: ShareDrawerMenuItem) => {
|
|
DashboardInteractions.sharingCategoryClicked({
|
|
item: item.shareId,
|
|
shareResource: getTrackingSource(panel?.getRef()),
|
|
});
|
|
|
|
item.onClick(dashboard);
|
|
};
|
|
|
|
return (
|
|
<Menu data-testid={newShareButtonSelector.container}>
|
|
{buildMenuItems().map((item) => (
|
|
<React.Fragment key={item.shareId}>
|
|
{item.renderDividerAbove && <Menu.Divider />}
|
|
<Menu.Item
|
|
testId={item.testId}
|
|
label={item.label}
|
|
icon={item.icon}
|
|
description={item.description}
|
|
component={item.component}
|
|
className={item.className}
|
|
onClick={() => onClick(item)}
|
|
/>
|
|
</React.Fragment>
|
|
))}
|
|
</Menu>
|
|
);
|
|
}
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
inviteUserItem: css({
|
|
display: 'flex',
|
|
justifyContent: 'start',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
}),
|
|
inviteUserItemIcon: css({
|
|
color: theme.colors.text.link,
|
|
}),
|
|
};
|
|
};
|