mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* WIP first pass * Change to toolbarbutton/buttonselect pattern * Move to two toolbarbuttons with dropdown * Justify text to the right of icons * Fix betterer * Fix styling and tests * Add to docs * Perist last clicked, add translations * move styling to core component * use label for tooltip, let parser combine panes in multiple params * Explore: Panes encoding suggestions (#78210) panes encoding suggestions * WIP-add menu groups * Get group actions working * add icons and non-local last selected state * Fix translations after merge * Add categories to translation, tweak the verbiage * Fix translation extraction * Fix tests * fix translation conflict * Log if time is absolute --------- Co-authored-by: Giordano Ricci <me@giordanoricci.com>
158 lines
4.8 KiB
TypeScript
158 lines
4.8 KiB
TypeScript
import React, { useState } from 'react';
|
|
|
|
import { IconName } from '@grafana/data';
|
|
import { reportInteraction, config } from '@grafana/runtime';
|
|
import { ToolbarButton, Dropdown, Menu, Stack, ToolbarButtonRow, MenuGroup } from '@grafana/ui';
|
|
import { t } from 'app/core/internationalization';
|
|
import { copyStringToClipboard } from 'app/core/utils/explore';
|
|
import { createAndCopyShortLink } from 'app/core/utils/shortLinks';
|
|
import { useSelector } from 'app/types';
|
|
|
|
import { selectPanes } from './state/selectors';
|
|
import { constructAbsoluteUrl } from './utils/links';
|
|
|
|
interface ShortLinkGroupData {
|
|
key: string;
|
|
label: string;
|
|
items: ShortLinkMenuItemData[];
|
|
}
|
|
|
|
interface ShortLinkMenuItemData {
|
|
key: string;
|
|
label: string;
|
|
icon: IconName;
|
|
getUrl: Function;
|
|
shorten: boolean;
|
|
absTime: boolean;
|
|
}
|
|
|
|
const defaultMode: ShortLinkMenuItemData = {
|
|
key: 'copy-link',
|
|
label: t('explore.toolbar.copy-shortened-link', 'Copy shortened URL'),
|
|
icon: 'share-alt',
|
|
getUrl: () => undefined,
|
|
shorten: true,
|
|
absTime: false,
|
|
};
|
|
|
|
export function ShortLinkButtonMenu() {
|
|
const panes = useSelector(selectPanes);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [lastSelected, setLastSelected] = useState(defaultMode);
|
|
const onCopyLink = (shorten: boolean, absTime: boolean, url?: string) => {
|
|
if (shorten) {
|
|
createAndCopyShortLink(url || global.location.href);
|
|
reportInteraction('grafana_explore_shortened_link_clicked', { isAbsoluteTime: absTime });
|
|
} else {
|
|
copyStringToClipboard(
|
|
url !== undefined
|
|
? `${window.location.protocol}//${window.location.host}${config.appSubUrl}${url}`
|
|
: global.location.href
|
|
);
|
|
reportInteraction('grafana_explore_copy_link_clicked', { isAbsoluteTime: absTime });
|
|
}
|
|
};
|
|
|
|
const menuOptions: ShortLinkGroupData[] = [
|
|
{
|
|
key: 'normal',
|
|
label: t('explore.toolbar.copy-links-normal-category', 'Normal URL links'),
|
|
items: [
|
|
{
|
|
key: 'copy-shortened-link',
|
|
icon: 'link',
|
|
label: t('explore.toolbar.copy-shortened-link', 'Copy shortened URL'),
|
|
getUrl: () => undefined,
|
|
shorten: true,
|
|
absTime: false,
|
|
},
|
|
{
|
|
key: 'copy-link',
|
|
icon: 'link',
|
|
label: t('explore.toolbar.copy-link', 'Copy URL'),
|
|
getUrl: () => undefined,
|
|
shorten: false,
|
|
absTime: false,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'timesync',
|
|
label: t('explore.toolbar.copy-links-absolute-category', 'Time-sync URL links (share with time range intact)'),
|
|
items: [
|
|
{
|
|
key: 'copy-short-link-abs-time',
|
|
icon: 'clock-nine',
|
|
label: t('explore.toolbar.copy-shortened-link-abs-time', 'Copy Absolute Shortened URL'),
|
|
shorten: true,
|
|
getUrl: () => {
|
|
return constructAbsoluteUrl(panes);
|
|
},
|
|
absTime: true,
|
|
},
|
|
{
|
|
key: 'copy-link-abs-time',
|
|
icon: 'clock-nine',
|
|
label: t('explore.toolbar.copy-link-abs-time', 'Copy Absolute Shortened URL'),
|
|
shorten: false,
|
|
getUrl: () => {
|
|
return constructAbsoluteUrl(panes);
|
|
},
|
|
absTime: true,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const MenuActions = (
|
|
<Menu>
|
|
{menuOptions.map((groupOption) => {
|
|
return (
|
|
<MenuGroup key={groupOption.key} label={groupOption.label}>
|
|
{groupOption.items.map((option) => {
|
|
return (
|
|
<Menu.Item
|
|
key={option.key}
|
|
label={option.label}
|
|
icon={option.icon}
|
|
onClick={() => {
|
|
const url = option.getUrl();
|
|
onCopyLink(option.shorten, option.absTime, url);
|
|
setLastSelected(option);
|
|
}}
|
|
/>
|
|
);
|
|
})}
|
|
</MenuGroup>
|
|
);
|
|
})}
|
|
</Menu>
|
|
);
|
|
|
|
// we need the Toolbar button click to be an action separate from opening/closing the menu
|
|
return (
|
|
<ToolbarButtonRow>
|
|
<Stack gap={0} direction="row" alignItems="center" wrap="nowrap">
|
|
<ToolbarButton
|
|
tooltip={lastSelected.label}
|
|
icon={lastSelected.icon}
|
|
iconOnly={true}
|
|
narrow={true}
|
|
onClick={() => {
|
|
const url = lastSelected.getUrl();
|
|
onCopyLink(lastSelected.shorten, lastSelected.absTime, url);
|
|
}}
|
|
aria-label={t('explore.toolbar.copy-shortened-link', 'Copy shortened URL')}
|
|
/>
|
|
<Dropdown overlay={MenuActions} placement="bottom-end" onVisibleChange={setIsOpen}>
|
|
<ToolbarButton
|
|
narrow={true}
|
|
isOpen={isOpen}
|
|
aria-label={t('explore.toolbar.copy-shortened-link-menu', 'Open copy link options')}
|
|
/>
|
|
</Dropdown>
|
|
</Stack>
|
|
</ToolbarButtonRow>
|
|
);
|
|
}
|