Share Button: Added ClipboardItem route after Safari issues (#107925)

* Share Button: Added ClipboardItem route after Safari issues

* Removed console log

* Feedback fixes

* Test feedback fix

* Removed export
pull/107984/head
Collin Fingar 1 week ago committed by GitHub
parent 7e0848294e
commit 0c76b52e8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 36
      public/app/core/utils/shortLinks.test.ts
  2. 25
      public/app/core/utils/shortLinks.ts
  3. 2
      public/app/features/dashboard-scene/scene/new-toolbar/actions/ShareDashboardButton.tsx
  4. 4
      public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx

@ -15,6 +15,17 @@ jest.mock('@grafana/runtime', () => ({
},
}));
beforeEach(() => {
Object.assign(navigator, {
clipboard: {
write: jest.fn().mockResolvedValue(undefined),
writeText: jest.fn().mockResolvedValue(undefined),
},
});
document.execCommand = jest.fn();
});
describe('createShortLink', () => {
it('creates short link', async () => {
const shortUrl = await createShortLink('www.verylonglinkwehavehere.com');
@ -23,11 +34,34 @@ describe('createShortLink', () => {
});
describe('createAndCopyShortLink', () => {
it('copies short link to clipboard', async () => {
it('copies short link to clipboard via document.execCommand when navigator.clipboard is undefined', async () => {
Object.assign(navigator, {
clipboard: {
write: undefined,
},
});
document.execCommand = jest.fn();
await createAndCopyShortLink('www.verylonglinkwehavehere.com');
expect(document.execCommand).toHaveBeenCalledWith('copy');
});
it('copies short link to clipboard via navigator.clipboard.writeText when ClipboardItem is undefined', async () => {
window.isSecureContext = true;
await createAndCopyShortLink('www.verylonglinkwehavehere.com');
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('www.short.com');
});
it('copies short link to clipboard via navigator.clipboard.write and ClipboardItem when it is defined', async () => {
global.ClipboardItem = jest.fn().mockImplementation(() => ({
type: 'text/plain',
size: 0,
slice: jest.fn(),
supports: jest.fn().mockReturnValue(true),
// eslint-disable-next-line
})) as any;
await createAndCopyShortLink('www.verylonglinkwehavehere.com');
expect(navigator.clipboard.write).toHaveBeenCalled();
});
});
describe('getLogsPermalinkRange', () => {

@ -35,13 +35,30 @@ export const createShortLink = memoizeOne(async function (path: string) {
}
});
/**
* Creates a ClipboardItem for the shortened link. This is used due to clipboard issues in Safari after making async calls.
* See https://github.com/grafana/grafana/issues/106889
* @param path - The long path to share.
* @returns A ClipboardItem for the shortened link.
*/
const createShortLinkClipboardItem = (path: string) => {
return new ClipboardItem({
'text/plain': createShortLink(path),
});
};
export const createAndCopyShortLink = async (path: string) => {
const shortLink = await createShortLink(path);
if (shortLink) {
copyStringToClipboard(shortLink);
if (typeof ClipboardItem !== 'undefined' && navigator.clipboard.write) {
navigator.clipboard.write([createShortLinkClipboardItem(path)]);
dispatch(notifyApp(createSuccessNotification('Shortened link copied to clipboard')));
} else {
dispatch(notifyApp(createErrorNotification('Error generating shortened link')));
const shortLink = await createShortLink(path);
if (shortLink) {
copyStringToClipboard(shortLink);
dispatch(notifyApp(createSuccessNotification('Shortened link copied to clipboard')));
} else {
dispatch(notifyApp(createErrorNotification('Error generating shortened link')));
}
}
};

@ -15,7 +15,7 @@ const newShareButtonSelector = e2eSelectors.pages.Dashboard.DashNav.newShareButt
export const ShareDashboardButton = ({ dashboard }: ToolbarActionProps) => {
const [_, buildUrl] = useAsyncFn(async () => {
DashboardInteractions.toolbarShareClick();
return await buildShareUrl(dashboard);
await buildShareUrl(dashboard);
}, [dashboard]);
return (

@ -22,8 +22,8 @@ export default function ShareButton({ dashboard, panel }: { dashboard: Dashboard
const [_, buildUrl] = useAsyncFn(async () => {
DashboardInteractions.toolbarShareClick();
return await buildShareUrl(dashboard, panel);
}, [dashboard]);
await buildShareUrl(dashboard, panel);
}, [dashboard, panel]);
const onMenuClick = useCallback((isOpen: boolean) => {
if (isOpen) {

Loading…
Cancel
Save