From d07dc3bf406d0303dff245cacca825821ae4c337 Mon Sep 17 00:00:00 2001
From: Juan Cabanas
Date: Mon, 24 Jun 2024 16:31:42 -0300
Subject: [PATCH] ShareDrawer: Share Internally (#89315)
---
.betterer.results | 3 -
public/app/core/utils/shortLinks.ts | 22 ++--
.../scene/NavToolbarActions.tsx | 2 +-
.../scene/PanelMenuBehavior.tsx | 3 +-
.../scene/keyboardShortcuts.ts | 2 +-
.../sharing/ShareButton/ShareButton.test.tsx | 10 --
.../sharing/ShareButton/ShareButton.tsx | 10 +-
.../sharing/ShareButton/ShareMenu.test.tsx | 9 --
.../sharing/ShareButton/ShareMenu.tsx | 16 ++-
.../share-internally/ShareInternally.tsx | 104 ++++++++++++++++++
.../sharing/ShareButton/utils.ts | 42 ++++++-
.../sharing/ShareExportTab.tsx | 5 +-
.../sharing/ShareLibraryPanelTab.tsx | 5 +-
.../sharing/ShareLinkTab.test.tsx | 20 +++-
.../dashboard-scene/sharing/ShareLinkTab.tsx | 65 +++++++----
.../dashboard-scene/sharing/ShareModal.tsx | 18 ++-
.../sharing/SharePanelEmbedTab.tsx | 6 +-
.../sharing/ShareSnapshotTab.tsx | 3 +-
.../ConfigPublicDashboard.tsx | 8 +-
.../CreatePublicDashboard.tsx | 5 +-
.../SharePublicDashboardTab.tsx | 3 +-
.../features/dashboard-scene/sharing/types.ts | 3 -
public/locales/en-US/grafana.json | 16 ++-
public/locales/pseudo-LOCALE/grafana.json | 16 ++-
24 files changed, 293 insertions(+), 103 deletions(-)
create mode 100644 public/app/features/dashboard-scene/sharing/ShareButton/share-internally/ShareInternally.tsx
diff --git a/.betterer.results b/.betterer.results
index 796548a475e..842d1803312 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -3082,9 +3082,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryButtons\`)", "3"],
[0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryComparison\`)", "4"]
],
- "public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx:5381": [
- [0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
- ],
"public/app/features/dashboard-scene/sharing/ShareExportTab.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
diff --git a/public/app/core/utils/shortLinks.ts b/public/app/core/utils/shortLinks.ts
index 74ebbfbeb44..13d162967a2 100644
--- a/public/app/core/utils/shortLinks.ts
+++ b/public/app/core/utils/shortLinks.ts
@@ -9,6 +9,9 @@ import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScen
import { getDashboardUrl } from 'app/features/dashboard-scene/utils/urlBuilders';
import { dispatch } from 'app/store/store';
+import { ShareLinkConfiguration } from '../../features/dashboard-scene/sharing/ShareButton/utils';
+import { t } from '../internationalization';
+
import { copyStringToClipboard } from './explore';
function buildHostUrl() {
@@ -42,20 +45,21 @@ export const createAndCopyShortLink = async (path: string) => {
}
};
-export const createAndCopyDashboardShortLink = async (
+export const createAndCopyShareDashboardLink = async (
dashboard: DashboardScene,
- opts: { useAbsoluteTimeRange: boolean; theme: string },
+ opts: ShareLinkConfiguration,
panel?: VizPanel
) => {
- const shareUrl = await createDashboardShareUrl(dashboard, opts, panel);
- await createAndCopyShortLink(shareUrl);
+ const shareUrl = createDashboardShareUrl(dashboard, opts, panel);
+ if (opts.useShortUrl) {
+ return await createAndCopyShortLink(shareUrl);
+ } else {
+ copyStringToClipboard(shareUrl);
+ dispatch(notifyApp(createSuccessNotification(t('link.share.copy-to-clipboard', 'Link copied to clipboard'))));
+ }
};
-export const createDashboardShareUrl = async (
- dashboard: DashboardScene,
- opts: { useAbsoluteTimeRange: boolean; theme: string },
- panel?: VizPanel
-) => {
+export const createDashboardShareUrl = (dashboard: DashboardScene, opts: ShareLinkConfiguration, panel?: VizPanel) => {
const location = locationService.getLocation();
const timeRange = sceneGraph.getTimeRange(panel ?? dashboard);
diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
index 28e2902509d..051c473f411 100644
--- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
+++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx
@@ -321,7 +321,7 @@ export function ToolbarActions({ dashboard }: Props) {
fill="outline"
onClick={() => {
DashboardInteractions.toolbarShareClick();
- dashboard.showModal(new ShareModal({ dashboardRef: dashboard.getRef() }));
+ dashboard.showModal(new ShareModal({}));
}}
data-testid={selectors.components.NavToolbar.shareDashboard}
>
diff --git a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx
index d33ed831670..24a0314c676 100644
--- a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx
+++ b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx
@@ -84,7 +84,7 @@ export function panelMenuBehavior(menu: VizPanelMenu, isRepeat = false) {
iconClassName: 'share-alt',
onClick: () => {
DashboardInteractions.panelMenuItemClicked('share');
- dashboard.showModal(new ShareModal({ panelRef: panel.getRef(), dashboardRef: dashboard.getRef() }));
+ dashboard.showModal(new ShareModal({ panelRef: panel.getRef() }));
},
shortcut: 'p s',
});
@@ -139,7 +139,6 @@ export function panelMenuBehavior(menu: VizPanelMenu, isRepeat = false) {
dashboard.showModal(
new ShareModal({
panelRef: panel.getRef(),
- dashboardRef: dashboard.getRef(),
activeTab: shareDashboardType.libraryPanel,
})
);
diff --git a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts
index dfa49e6625a..f0edd586360 100644
--- a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts
+++ b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts
@@ -60,7 +60,7 @@ export function setupKeyboardShortcuts(scene: DashboardScene) {
keybindings.addBinding({
key: 'p s',
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
- scene.showModal(new ShareModal({ panelRef: vizPanel.getRef(), dashboardRef: scene.getRef() }));
+ scene.showModal(new ShareModal({ panelRef: vizPanel.getRef() }));
}),
});
diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.test.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.test.tsx
index 3fec88b051c..ac1b76fb655 100644
--- a/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.test.tsx
+++ b/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.test.tsx
@@ -24,16 +24,6 @@ describe('ShareButton', () => {
expect(await screen.findByTestId(selector.shareLink)).toBeInTheDocument();
expect(await screen.findByTestId(selector.arrowMenu)).toBeInTheDocument();
});
-
- it('should call createAndCopyDashboardShortLink when share link clicked', async () => {
- setup();
-
- const shareLink = await screen.findByTestId(selector.shareLink);
-
- await userEvent.click(shareLink);
- expect(createAndCopyDashboardShortLinkMock).toHaveBeenCalled();
- });
-
it('should render menu when arrow button clicked', async () => {
setup();
diff --git a/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx b/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx
index 01fcf60706b..6a79cbdb0da 100644
--- a/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx
+++ b/public/app/features/dashboard-scene/sharing/ShareButton/ShareButton.tsx
@@ -4,6 +4,7 @@ import { useAsyncFn } from 'react-use';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { VizPanel } from '@grafana/scenes';
import { Button, ButtonGroup, Dropdown } from '@grafana/ui';
+import { t, Trans } from 'app/core/internationalization';
import { DashboardScene } from '../../scene/DashboardScene';
import { DashboardInteractions } from '../../utils/interactions';
@@ -32,8 +33,13 @@ export default function ShareButton({ dashboard, panel }: { dashboard: Dashboard
return (
-
),
onDismiss: () => {
- dashboard.showModal(new ShareModal({ dashboardRef, activeTab: 'Public Dashboard' }));
+ dashboard.showModal(new ShareModal({ activeTab: shareDashboardType.publicDashboard }));
},
onConfirm: () => {
deletePublicDashboard({ dashboard, dashboardUid: dashboard.state.uid!, uid: publicDashboard!.uid });
diff --git a/public/app/features/dashboard-scene/sharing/public-dashboards/CreatePublicDashboard.tsx b/public/app/features/dashboard-scene/sharing/public-dashboards/CreatePublicDashboard.tsx
index 5b01c56aa72..1e22bea501c 100644
--- a/public/app/features/dashboard-scene/sharing/public-dashboards/CreatePublicDashboard.tsx
+++ b/public/app/features/dashboard-scene/sharing/public-dashboards/CreatePublicDashboard.tsx
@@ -3,12 +3,13 @@ import React from 'react';
import { SceneComponentProps } from '@grafana/scenes';
import { CreatePublicDashboardBase } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard';
+import { getDashboardSceneFor } from '../../utils/utils';
+
import { SharePublicDashboardTab } from './SharePublicDashboardTab';
import { useUnsupportedDatasources } from './hooks';
export function CreatePublicDashboard({ model }: SceneComponentProps) {
- const { dashboardRef } = model.useState();
- const dashboard = dashboardRef.resolve();
+ const dashboard = getDashboardSceneFor(model);
const unsupportedDataSources = useUnsupportedDatasources(dashboard);
const hasTemplateVariables = (dashboard.state.$variables?.state.variables.length ?? 0) > 0;
diff --git a/public/app/features/dashboard-scene/sharing/public-dashboards/SharePublicDashboardTab.tsx b/public/app/features/dashboard-scene/sharing/public-dashboards/SharePublicDashboardTab.tsx
index 311652d5fb8..e172883a8ab 100644
--- a/public/app/features/dashboard-scene/sharing/public-dashboards/SharePublicDashboardTab.tsx
+++ b/public/app/features/dashboard-scene/sharing/public-dashboards/SharePublicDashboardTab.tsx
@@ -7,6 +7,7 @@ import { Loader } from 'app/features/dashboard/components/ShareModal/SharePublic
import { publicDashboardPersisted } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
+import { getDashboardSceneFor } from '../../utils/utils';
import { SceneShareTabState } from '../types';
import { ConfigPublicDashboard } from './ConfigPublicDashboard';
@@ -23,7 +24,7 @@ export class SharePublicDashboardTab extends SceneObjectBase
function SharePublicDashboardTabRenderer({ model }: SceneComponentProps) {
const { data: publicDashboard, isLoading: isGetLoading } = useGetPublicDashboardQuery(
- model.state.dashboardRef.resolve().state.uid!
+ getDashboardSceneFor(model).state.uid!
);
return (
diff --git a/public/app/features/dashboard-scene/sharing/types.ts b/public/app/features/dashboard-scene/sharing/types.ts
index 1d4aadf0907..dc4ddb676e6 100644
--- a/public/app/features/dashboard-scene/sharing/types.ts
+++ b/public/app/features/dashboard-scene/sharing/types.ts
@@ -1,13 +1,10 @@
import { SceneObject, SceneObjectRef, SceneObjectState } from '@grafana/scenes';
-import { DashboardScene } from '../scene/DashboardScene';
-
export interface ModalSceneObjectLike {
onDismiss: () => void;
}
export interface SceneShareTabState extends SceneObjectState {
- dashboardRef: SceneObjectRef;
modalRef?: SceneObjectRef;
}
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 00a8a74492a..db4af3a4bba 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -797,6 +797,18 @@
"success": "Library panel saved"
}
},
+ "link": {
+ "share": {
+ "config-alert-description": "Updating your settings will modify the default copy link to include these changes.",
+ "config-alert-title": "Link configuration",
+ "config-description": "Create a personalized, direct link to share your dashboard within your organization, with the following customization settings:",
+ "copy-link-button": "Copy link",
+ "copy-to-clipboard": "Link copied to clipboard",
+ "short-url-label": "Shorten link",
+ "time-range-description": "Change the current relative time range to an absolute time range",
+ "time-range-label": "Lock time range"
+ }
+ },
"login": {
"error": {
"blocked": "You have exceeded the number of login attempts for this user. Please try again later.",
@@ -1701,7 +1713,9 @@
"share-internally-description": "Advanced settings",
"share-internally-title": "Share internally",
"share-snapshot-title": "Share snapshot"
- }
+ },
+ "share-button": "Share",
+ "share-button-tooltip": "Copy shortened link"
},
"share-drawer": {
"confirm-action": {
diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json
index 4c3eecbe49f..b97f6522f70 100644
--- a/public/locales/pseudo-LOCALE/grafana.json
+++ b/public/locales/pseudo-LOCALE/grafana.json
@@ -797,6 +797,18 @@
"success": "Ŀįþřäřy päʼnęľ şävęđ"
}
},
+ "link": {
+ "share": {
+ "config-alert-description": "Ůpđäŧįʼnģ yőūř şęŧŧįʼnģş ŵįľľ mőđįƒy ŧĥę đęƒäūľŧ čőpy ľįʼnĸ ŧő įʼnčľūđę ŧĥęşę čĥäʼnģęş.",
+ "config-alert-title": "Ŀįʼnĸ čőʼnƒįģūřäŧįőʼn",
+ "config-description": "Cřęäŧę ä pęřşőʼnäľįžęđ, đįřęčŧ ľįʼnĸ ŧő şĥäřę yőūř đäşĥþőäřđ ŵįŧĥįʼn yőūř őřģäʼnįžäŧįőʼn, ŵįŧĥ ŧĥę ƒőľľőŵįʼnģ čūşŧőmįžäŧįőʼn şęŧŧįʼnģş:",
+ "copy-link-button": "Cőpy ľįʼnĸ",
+ "copy-to-clipboard": "Ŀįʼnĸ čőpįęđ ŧő čľįpþőäřđ",
+ "short-url-label": "Ŝĥőřŧęʼn ľįʼnĸ",
+ "time-range-description": "Cĥäʼnģę ŧĥę čūřřęʼnŧ řęľäŧįvę ŧįmę řäʼnģę ŧő äʼn äþşőľūŧę ŧįmę řäʼnģę",
+ "time-range-label": "Ŀőčĸ ŧįmę řäʼnģę"
+ }
+ },
"login": {
"error": {
"blocked": "Ÿőū ĥävę ęχčęęđęđ ŧĥę ʼnūmþęř őƒ ľőģįʼn äŧŧęmpŧş ƒőř ŧĥįş ūşęř. Pľęäşę ŧřy äģäįʼn ľäŧęř.",
@@ -1701,7 +1713,9 @@
"share-internally-description": "Åđväʼnčęđ şęŧŧįʼnģş",
"share-internally-title": "Ŝĥäřę įʼnŧęřʼnäľľy",
"share-snapshot-title": "Ŝĥäřę şʼnäpşĥőŧ"
- }
+ },
+ "share-button": "Ŝĥäřę",
+ "share-button-tooltip": "Cőpy şĥőřŧęʼnęđ ľįʼnĸ"
},
"share-drawer": {
"confirm-action": {