ShareDrawer: Share snapshot panel (#90678)
This commit is contained in:
@@ -13,6 +13,7 @@ import { LocalValueVariable, sceneGraph, SceneGridRow, VizPanel, VizPanelMenu }
|
||||
import { DataQuery, OptionsWithLegend } from '@grafana/schema';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { t } from 'app/core/internationalization';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
|
||||
import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
|
||||
import { InspectTab } from 'app/features/inspector/types';
|
||||
@@ -21,6 +22,7 @@ import { createExtensionSubMenu } from 'app/features/plugins/extensions/utils';
|
||||
import { addDataTrailPanelAction } from 'app/features/trails/Integrations/dashboardIntegration';
|
||||
import { ShowConfirmModalEvent } from 'app/types/events';
|
||||
|
||||
import { ShareSnapshot } from '../sharing/ShareButton/share-snapshot/ShareSnapshot';
|
||||
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
|
||||
import { ShareModal } from '../sharing/ShareModal';
|
||||
import { SharePanelEmbedTab } from '../sharing/SharePanelEmbedTab';
|
||||
@@ -109,6 +111,22 @@ export function panelMenuBehavior(menu: VizPanelMenu, isRepeat = false) {
|
||||
},
|
||||
});
|
||||
|
||||
if (contextSrv.isSignedIn && config.snapshotEnabled && dashboard.canEditDashboard()) {
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-snapshot-title', 'Share snapshot'),
|
||||
iconClassName: 'camera',
|
||||
shortcut: 'p s',
|
||||
onClick: () => {
|
||||
const drawer = new ShareDrawer({
|
||||
title: t('share-panel.drawer.share-snapshot-title', 'Share snapshot'),
|
||||
body: new ShareSnapshot({ dashboardRef: dashboard.getRef(), panelRef: panel.getRef() }),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
type: 'submenu',
|
||||
text: t('panel.header-menu.share', 'Share'),
|
||||
|
||||
@@ -4,7 +4,9 @@ import { sceneGraph, VizPanel } from '@grafana/scenes';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { t } from 'app/core/internationalization';
|
||||
import { KeybindingSet } from 'app/core/services/KeybindingSet';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
|
||||
import { ShareSnapshot } from '../sharing/ShareButton/share-snapshot/ShareSnapshot';
|
||||
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
|
||||
import { ShareModal } from '../sharing/ShareModal';
|
||||
import { SharePanelEmbedTab } from '../sharing/SharePanelEmbedTab';
|
||||
@@ -72,6 +74,20 @@ export function setupKeyboardShortcuts(scene: DashboardScene) {
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
|
||||
if (contextSrv.isSignedIn && config.snapshotEnabled && scene.canEditDashboard()) {
|
||||
keybindings.addBinding({
|
||||
key: 'p s',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
title: t('share-panel.drawer.share-snapshot-title', 'Share snapshot'),
|
||||
body: new ShareSnapshot({ dashboardRef: scene.getRef(), panelRef: vizPanel.getRef() }),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
keybindings.addBinding({
|
||||
key: 'p s',
|
||||
|
||||
+26
-8
@@ -1,6 +1,7 @@
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import { SceneObjectRef, VizPanel } from '@grafana/scenes';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
@@ -20,7 +21,10 @@ import { Trans } from 'app/core/internationalization';
|
||||
import { SnapshotSharingOptions } from '../../../../dashboard/services/SnapshotSrv';
|
||||
import { getExpireOptions } from '../../ShareSnapshotTab';
|
||||
|
||||
const SNAPSHOT_URL = 'https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/#publish-a-snapshot';
|
||||
const DASHBOARD_SNAPSHOT_URL =
|
||||
'https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/#publish-a-snapshot';
|
||||
const PANEL_SNAPSHOT_URL =
|
||||
'https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/#publish-a-snapshot-1';
|
||||
|
||||
interface Props {
|
||||
isLoading: boolean;
|
||||
@@ -31,6 +35,7 @@ interface Props {
|
||||
onCreateClick: (isExternal?: boolean) => void;
|
||||
onNameChange: (v: string) => void;
|
||||
onExpireChange: (v: number) => void;
|
||||
panelRef?: SceneObjectRef<VizPanel>;
|
||||
}
|
||||
export function CreateSnapshot({
|
||||
name,
|
||||
@@ -41,6 +46,7 @@ export function CreateSnapshot({
|
||||
onCancelClick,
|
||||
onCreateClick,
|
||||
isLoading,
|
||||
panelRef,
|
||||
}: Props) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
@@ -49,18 +55,30 @@ export function CreateSnapshot({
|
||||
<Alert severity="info" title={''}>
|
||||
<Stack justifyContent="space-between" gap={2} alignItems="center">
|
||||
<Text>
|
||||
<Trans i18nKey="snapshot.share.info-alert">
|
||||
A Grafana dashboard snapshot publicly shares a dashboard while removing sensitive data such as queries and
|
||||
panel links, leaving only visible metrics and series names. Anyone with the link can access the snapshot.
|
||||
</Trans>
|
||||
{panelRef ? (
|
||||
<Trans i18nKey="snapshot.share-panel.info-alert">
|
||||
A Grafana panel snapshot publicly shares a panel while removing sensitive data such as queries and panel
|
||||
links, leaving only visible metrics and series names. Anyone with the link can access the snapshot.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="snapshot.share.info-alert">
|
||||
A Grafana dashboard snapshot publicly shares a dashboard while removing sensitive data such as queries
|
||||
and panel links, leaving only visible metrics and series names. Anyone with the link can access the
|
||||
snapshot.
|
||||
</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Button variant="secondary" onClick={() => window.open(SNAPSHOT_URL, '_blank')} type="button">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => window.open(panelRef ? PANEL_SNAPSHOT_URL : DASHBOARD_SNAPSHOT_URL, '_blank')}
|
||||
type="button"
|
||||
>
|
||||
<Trans i18nKey="snapshot.share.learn-more-button">Learn more</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
</Alert>
|
||||
<Field label={t('snapshot.share.name-label', 'Snapshot name*')}>
|
||||
<Input id="snapshot-name-input" defaultValue={name} onBlur={(e) => onNameChange(e.target.value)} />
|
||||
<Field label={t('snapshot.share.name-label', 'Snapshot name')}>
|
||||
<Input id="snapshot-name-input" defaultValue={name} onChange={(e) => onNameChange(e.currentTarget.value)} />
|
||||
</Field>
|
||||
<Field label={t('snapshot.share.expiration-label', 'Expires in')}>
|
||||
<RadioButtonGroup<number>
|
||||
|
||||
+2
-1
@@ -23,7 +23,7 @@ function ShareSnapshotRenderer({ model }: SceneComponentProps<ShareSnapshot>) {
|
||||
const [showDeletedAlert, setShowDeletedAlert] = useState(false);
|
||||
const [step, setStep] = useState(1);
|
||||
|
||||
const { snapshotName, snapshotSharingOptions, selectedExpireOption, dashboardRef } = model.useState();
|
||||
const { snapshotName, snapshotSharingOptions, selectedExpireOption, dashboardRef, panelRef } = model.useState();
|
||||
|
||||
const [snapshotResult, createSnapshot] = useAsyncFn(async (external = false) => {
|
||||
const response = await model.onSnapshotCreate(external);
|
||||
@@ -76,6 +76,7 @@ function ShareSnapshotRenderer({ model }: SceneComponentProps<ShareSnapshot>) {
|
||||
onExpireChange={model.onExpireChange}
|
||||
onCreateClick={createSnapshot}
|
||||
isLoading={snapshotResult.loading}
|
||||
panelRef={panelRef}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -2130,11 +2130,13 @@
|
||||
"share-panel": {
|
||||
"drawer": {
|
||||
"share-embed-title": "Share embed",
|
||||
"share-link-title": "Link settings"
|
||||
"share-link-title": "Link settings",
|
||||
"share-snapshot-title": "Share snapshot"
|
||||
},
|
||||
"menu": {
|
||||
"share-embed-title": "Share embed",
|
||||
"share-link-title": "Share link"
|
||||
"share-link-title": "Share link",
|
||||
"share-snapshot-title": "Share snapshot"
|
||||
}
|
||||
},
|
||||
"share-playlist": {
|
||||
@@ -2215,12 +2217,15 @@
|
||||
"info-alert": "A Grafana dashboard snapshot publicly shares a dashboard while removing sensitive data such as queries and panel links, leaving only visible metrics and series names. Anyone with the link can access the snapshot.",
|
||||
"learn-more-button": "Learn more",
|
||||
"local-button": "Publish snapshot",
|
||||
"name-label": "Snapshot name*",
|
||||
"name-label": "Snapshot name",
|
||||
"new-snapshot-button": "New snapshot",
|
||||
"success-creation": "Your snapshot has been created",
|
||||
"success-delete": "Your snapshot has been deleted",
|
||||
"view-all-button": "View all snapshots"
|
||||
},
|
||||
"share-panel": {
|
||||
"info-alert": "A Grafana panel snapshot publicly shares a panel while removing sensitive data such as queries and panel links, leaving only visible metrics and series names. Anyone with the link can access the snapshot."
|
||||
},
|
||||
"url-column-header": "Snapshot url",
|
||||
"view-button": "View"
|
||||
},
|
||||
|
||||
@@ -2130,11 +2130,13 @@
|
||||
"share-panel": {
|
||||
"drawer": {
|
||||
"share-embed-title": "Ŝĥäřę ęmþęđ",
|
||||
"share-link-title": "Ŀįʼnĸ şęŧŧįʼnģş"
|
||||
"share-link-title": "Ŀįʼnĸ şęŧŧįʼnģş",
|
||||
"share-snapshot-title": "Ŝĥäřę şʼnäpşĥőŧ"
|
||||
},
|
||||
"menu": {
|
||||
"share-embed-title": "Ŝĥäřę ęmþęđ",
|
||||
"share-link-title": "Ŝĥäřę ľįʼnĸ"
|
||||
"share-link-title": "Ŝĥäřę ľįʼnĸ",
|
||||
"share-snapshot-title": "Ŝĥäřę şʼnäpşĥőŧ"
|
||||
}
|
||||
},
|
||||
"share-playlist": {
|
||||
@@ -2215,12 +2217,15 @@
|
||||
"info-alert": "Å Ğřäƒäʼnä đäşĥþőäřđ şʼnäpşĥőŧ pūþľįčľy şĥäřęş ä đäşĥþőäřđ ŵĥįľę řęmővįʼnģ şęʼnşįŧįvę đäŧä şūčĥ äş qūęřįęş äʼnđ päʼnęľ ľįʼnĸş, ľęävįʼnģ őʼnľy vįşįþľę męŧřįčş äʼnđ şęřįęş ʼnämęş. Åʼnyőʼnę ŵįŧĥ ŧĥę ľįʼnĸ čäʼn äččęşş ŧĥę şʼnäpşĥőŧ.",
|
||||
"learn-more-button": "Ŀęäřʼn mőřę",
|
||||
"local-button": "Pūþľįşĥ şʼnäpşĥőŧ",
|
||||
"name-label": "Ŝʼnäpşĥőŧ ʼnämę*",
|
||||
"name-label": "Ŝʼnäpşĥőŧ ʼnämę",
|
||||
"new-snapshot-button": "Ńęŵ şʼnäpşĥőŧ",
|
||||
"success-creation": "Ÿőūř şʼnäpşĥőŧ ĥäş þęęʼn čřęäŧęđ",
|
||||
"success-delete": "Ÿőūř şʼnäpşĥőŧ ĥäş þęęʼn đęľęŧęđ",
|
||||
"view-all-button": "Vįęŵ äľľ şʼnäpşĥőŧş"
|
||||
},
|
||||
"share-panel": {
|
||||
"info-alert": "Å Ğřäƒäʼnä päʼnęľ şʼnäpşĥőŧ pūþľįčľy şĥäřęş ä päʼnęľ ŵĥįľę řęmővįʼnģ şęʼnşįŧįvę đäŧä şūčĥ äş qūęřįęş äʼnđ päʼnęľ ľįʼnĸş, ľęävįʼnģ őʼnľy vįşįþľę męŧřįčş äʼnđ şęřįęş ʼnämęş. Åʼnyőʼnę ŵįŧĥ ŧĥę ľįʼnĸ čäʼn äččęşş ŧĥę şʼnäpşĥőŧ."
|
||||
},
|
||||
"url-column-header": "Ŝʼnäpşĥőŧ ūřľ",
|
||||
"view-button": "Vįęŵ"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user