ShareDrawer: Share embed panel (#90994)

pull/90009/head
Juan Cabanas 11 months ago committed by GitHub
parent 55381a3e77
commit b569c1610f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 14
      public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx
  2. 12
      public/app/features/dashboard-scene/scene/keyboardShortcuts.ts
  3. 1
      public/app/features/dashboard-scene/sharing/SharePanelEmbedTab.tsx
  4. 75
      public/app/features/dashboard/components/ShareModal/ShareEmbed.tsx
  5. 11
      public/locales/en-US/grafana.json
  6. 11
      public/locales/pseudo-LOCALE/grafana.json

@ -23,6 +23,7 @@ import { ShowConfirmModalEvent } from 'app/types/events';
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
import { ShareModal } from '../sharing/ShareModal';
import { SharePanelEmbedTab } from '../sharing/SharePanelEmbedTab';
import { SharePanelInternally } from '../sharing/panel-share/SharePanelInternally';
import { DashboardInteractions } from '../utils/interactions';
import { getEditPanelUrl, getInspectUrl, getViewPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders';
@ -94,6 +95,19 @@ export function panelMenuBehavior(menu: VizPanelMenu, isRepeat = false) {
dashboard.showModal(drawer);
},
});
subMenu.push({
text: t('share-panel.menu.share-embed-title', 'Share embed'),
iconClassName: 'arrow',
shortcut: 'p e',
onClick: () => {
const drawer = new ShareDrawer({
title: t('share-panel.drawer.share-embed-title', 'Share embed'),
body: new SharePanelEmbedTab({ panelRef: panel.getRef() }),
});
dashboard.showModal(drawer);
},
});
items.push({
type: 'submenu',

@ -7,6 +7,7 @@ import { KeybindingSet } from 'app/core/services/KeybindingSet';
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
import { ShareModal } from '../sharing/ShareModal';
import { SharePanelEmbedTab } from '../sharing/SharePanelEmbedTab';
import { SharePanelInternally } from '../sharing/panel-share/SharePanelInternally';
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
import { getEditPanelUrl, getInspectUrl, getViewPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders';
@ -57,6 +58,17 @@ export function setupKeyboardShortcuts(scene: DashboardScene) {
body: new SharePanelInternally({ panelRef: vizPanel.getRef() }),
});
scene.showModal(drawer);
}),
});
keybindings.addBinding({
key: 'p e',
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
const drawer = new ShareDrawer({
title: t('share-panel.drawer.share-embed-title', 'Share embed'),
body: new SharePanelEmbedTab({ panelRef: vizPanel.getRef() }),
});
scene.showModal(drawer);
}),
});

@ -48,6 +48,7 @@ function SharePanelEmbedTabRenderer({ model }: SceneComponentProps<SharePanelEmb
range={timeRangeState.state.value}
dashboard={{ uid: dashUid ?? '', time: timeRangeState.state.value }}
buildIframe={getIframeBuilder(dash)}
onCancelClick={() => dash.closeModal()}
/>
);
}

@ -2,8 +2,8 @@ import { FormEvent, useEffect, useState } from 'react';
import { useEffectOnce } from 'react-use';
import { RawTimeRange, TimeRange } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { ClipboardButton, Field, Modal, Switch, TextArea } from '@grafana/ui';
import { config, reportInteraction } from '@grafana/runtime';
import { Button, ClipboardButton, Field, Label, Modal, Stack, Switch, TextArea } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
@ -16,9 +16,10 @@ interface Props extends Omit<ShareModalTabProps, 'panel' | 'dashboard'> {
dashboard: { uid: string; time: RawTimeRange };
range?: TimeRange;
buildIframe?: typeof buildIframeHtml;
onCancelClick?: () => void;
}
export function ShareEmbed({ panel, dashboard, range, buildIframe = buildIframeHtml }: Props) {
export function ShareEmbed({ panel, dashboard, range, onCancelClick, buildIframe = buildIframeHtml }: Props) {
const [useCurrentTimeRange, setUseCurrentTimeRange] = useState(true);
const [selectedTheme, setSelectedTheme] = useState('current');
const [iframeHtml, setIframeHtml] = useState('');
@ -44,21 +45,45 @@ export function ShareEmbed({ panel, dashboard, range, buildIframe = buildIframeH
setSelectedTheme(value);
};
const isRelativeTime = dashboard.time.to === 'now';
const timeRangeDescription = isRelativeTime
? t(
'share-modal.embed.time-range-description',
'Transforms the current relative time range to an absolute time range'
)
: '';
const clipboardButton = (
<ClipboardButton
icon="copy"
variant="primary"
getText={() => iframeHtml}
onClipboardCopy={() => {
DashboardInteractions.embedSnippetCopy({
currentTimeRange: useCurrentTimeRange,
theme: selectedTheme,
shareResource: getTrackingSource(panel),
});
}}
>
<Trans i18nKey="share-modal.embed.copy">Copy to clipboard</Trans>
</ClipboardButton>
);
return (
<>
<p>
<Trans i18nKey="share-modal.embed.info">Generate HTML for embedding an iframe with this panel.</Trans>
</p>
<Field label={t('share-modal.embed.time-range', 'Current time range')} description={timeRangeDescription}>
<Switch id="share-current-time-range" value={useCurrentTimeRange} onChange={onUseCurrentTimeRangeChange} />
<Field>
<Stack gap={1} alignItems="start">
<Switch
label={t('share-modal.embed.time-range', 'Time range')}
id="share-current-time-range"
value={useCurrentTimeRange}
onChange={onUseCurrentTimeRangeChange}
/>
<Label
description={t(
'embed.share.time-range-description',
'Change the current relative time range to an absolute time range'
)}
>
<Trans i18nKey="embed.share.time-range-label">Time range</Trans>
</Label>
</Stack>
</Field>
<ThemePicker selectedTheme={selectedTheme} onChange={onThemeChange} />
<Field
@ -76,22 +101,16 @@ export function ShareEmbed({ panel, dashboard, range, buildIframe = buildIframeH
onChange={onIframeHtmlChange}
/>
</Field>
<Modal.ButtonRow>
<ClipboardButton
icon="copy"
variant="primary"
getText={() => iframeHtml}
onClipboardCopy={() => {
DashboardInteractions.embedSnippetCopy({
currentTimeRange: useCurrentTimeRange,
theme: selectedTheme,
shareResource: getTrackingSource(panel),
});
}}
>
<Trans i18nKey="share-modal.embed.copy">Copy to clipboard</Trans>
</ClipboardButton>
</Modal.ButtonRow>
{config.featureToggles.newDashboardSharingComponent ? (
<Stack gap={1} justifyContent={'start'}>
{clipboardButton}
<Button variant="secondary" fill="outline" onClick={onCancelClick}>
<Trans i18nKey="snapshot.share.cancel-button">Cancel</Trans>
</Button>
</Stack>
) : (
<Modal.ButtonRow>{clipboardButton}</Modal.ButtonRow>
)}
</>
);
}

@ -694,6 +694,12 @@
"message": "No data sources found"
}
},
"embed": {
"share": {
"time-range-description": "Change the current relative time range to an absolute time range",
"time-range-label": "Time range"
}
},
"explore": {
"add-to-dashboard": "Add to dashboard",
"add-to-library-modal": {
@ -2046,8 +2052,7 @@
"html": "Embed HTML",
"html-description": "The HTML code below can be pasted and included in another web page. Unless anonymous access is enabled, the user viewing that page need to be signed into Grafana for the graph to load.",
"info": "Generate HTML for embedding an iframe with this panel.",
"time-range": "Current time range",
"time-range-description": "Transforms the current relative time range to an absolute time range"
"time-range": "Time range"
},
"export": {
"back-button": "Back to export config",
@ -2117,9 +2122,11 @@
},
"share-panel": {
"drawer": {
"share-embed-title": "Share embed",
"share-link-title": "Link settings"
},
"menu": {
"share-embed-title": "Share embed",
"share-link-title": "Share link"
}
},

@ -694,6 +694,12 @@
"message": "Ńő đäŧä şőūřčęş ƒőūʼnđ"
}
},
"embed": {
"share": {
"time-range-description": "Cĥäʼnģę ŧĥę čūřřęʼnŧ řęľäŧįvę ŧįmę řäʼnģę ŧő äʼn äþşőľūŧę ŧįmę řäʼnģę",
"time-range-label": "Ŧįmę řäʼnģę"
}
},
"explore": {
"add-to-dashboard": "Åđđ ŧő đäşĥþőäřđ",
"add-to-library-modal": {
@ -2046,8 +2052,7 @@
"html": "Ēmþęđ ĦŦMĿ",
"html-description": "Ŧĥę ĦŦMĿ čőđę þęľőŵ čäʼn þę päşŧęđ äʼnđ įʼnčľūđęđ įʼn äʼnőŧĥęř ŵęþ päģę. Ůʼnľęşş äʼnőʼnymőūş äččęşş įş ęʼnäþľęđ, ŧĥę ūşęř vįęŵįʼnģ ŧĥäŧ päģę ʼnęęđ ŧő þę şįģʼnęđ įʼnŧő Ğřäƒäʼnä ƒőř ŧĥę ģřäpĥ ŧő ľőäđ.",
"info": "Ğęʼnęřäŧę ĦŦMĿ ƒőř ęmþęđđįʼnģ äʼn įƒřämę ŵįŧĥ ŧĥįş päʼnęľ.",
"time-range": "Cūřřęʼnŧ ŧįmę řäʼnģę",
"time-range-description": "Ŧřäʼnşƒőřmş ŧĥę čūřřęʼnŧ řęľäŧįvę ŧįmę řäʼnģę ŧő äʼn äþşőľūŧę ŧįmę řäʼnģę"
"time-range": "Ŧįmę řäʼnģę"
},
"export": {
"back-button": "ßäčĸ ŧő ęχpőřŧ čőʼnƒįģ",
@ -2117,9 +2122,11 @@
},
"share-panel": {
"drawer": {
"share-embed-title": "Ŝĥäřę ęmþęđ",
"share-link-title": "Ŀįʼnĸ şęŧŧįʼnģş"
},
"menu": {
"share-embed-title": "Ŝĥäřę ęmþęđ",
"share-link-title": "Ŝĥäřę ľįʼnĸ"
}
},

Loading…
Cancel
Save