mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Refactor dashboard interactions tracking * Local scenes tmp * Use latest scenes * Review refactor * Fix enterprise tests * Reporting parity for panel description
187 lines
6.0 KiB
TypeScript
187 lines
6.0 KiB
TypeScript
import saveAs from 'file-saver';
|
|
import React from 'react';
|
|
import { useAsync } from 'react-use';
|
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
|
|
|
import { SceneComponentProps, SceneObjectBase, SceneObjectRef } from '@grafana/scenes';
|
|
import { Button, ClipboardButton, CodeEditor, Field, Modal, Switch, VerticalGroup } from '@grafana/ui';
|
|
import { t, Trans } from 'app/core/internationalization';
|
|
import { DashboardExporter } from 'app/features/dashboard/components/DashExportModal';
|
|
import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
|
|
import { DashboardModel } from 'app/features/dashboard/state';
|
|
|
|
import { DashboardScene } from '../scene/DashboardScene';
|
|
import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
|
import { DashboardInteractions } from '../utils/interactions';
|
|
|
|
import { SceneShareTabState } from './types';
|
|
|
|
const exportExternallyTranslation = t('share-modal.export.share-externally-label', `Export for sharing externally`);
|
|
|
|
interface ShareExportTabState extends SceneShareTabState {
|
|
dashboardRef: SceneObjectRef<DashboardScene>;
|
|
isSharingExternally?: boolean;
|
|
isViewingJSON?: boolean;
|
|
}
|
|
|
|
export class ShareExportTab extends SceneObjectBase<ShareExportTabState> {
|
|
public tabId = shareDashboardType.export;
|
|
static Component = ShareExportTabRenderer;
|
|
|
|
private _exporter = new DashboardExporter();
|
|
|
|
constructor(state: Omit<ShareExportTabState, 'panelRef'>) {
|
|
super({
|
|
isSharingExternally: false,
|
|
isViewingJSON: false,
|
|
...state,
|
|
});
|
|
}
|
|
|
|
public getTabLabel() {
|
|
return t('share-modal.tab-title.export', 'Export');
|
|
}
|
|
|
|
public onShareExternallyChange = () => {
|
|
this.setState({
|
|
isSharingExternally: !this.state.isSharingExternally,
|
|
});
|
|
};
|
|
|
|
public onViewJSON = () => {
|
|
this.setState({
|
|
isViewingJSON: !this.state.isViewingJSON,
|
|
});
|
|
};
|
|
|
|
public getClipboardText() {
|
|
return;
|
|
}
|
|
|
|
public async getExportableDashboardJson() {
|
|
const { dashboardRef, isSharingExternally } = this.state;
|
|
const saveModel = transformSceneToSaveModel(dashboardRef.resolve());
|
|
|
|
const exportable = isSharingExternally
|
|
? await this._exporter.makeExportable(new DashboardModel(saveModel))
|
|
: saveModel;
|
|
|
|
return exportable;
|
|
}
|
|
|
|
public async onSaveAsFile() {
|
|
const dashboardJson = await this.getExportableDashboardJson();
|
|
const dashboardJsonPretty = JSON.stringify(dashboardJson, null, 2);
|
|
const { isSharingExternally } = this.state;
|
|
|
|
const blob = new Blob([dashboardJsonPretty], {
|
|
type: 'application/json;charset=utf-8',
|
|
});
|
|
|
|
const time = new Date().getTime();
|
|
let title = 'dashboard';
|
|
if ('title' in dashboardJson && dashboardJson.title) {
|
|
title = dashboardJson.title;
|
|
}
|
|
saveAs(blob, `${title}-${time}.json`);
|
|
DashboardInteractions.exportDownloadJsonClicked({
|
|
externally: isSharingExternally,
|
|
});
|
|
}
|
|
}
|
|
|
|
function ShareExportTabRenderer({ model }: SceneComponentProps<ShareExportTab>) {
|
|
const { isSharingExternally, isViewingJSON, modalRef } = model.useState();
|
|
|
|
const dashboardJson = useAsync(async () => {
|
|
if (isViewingJSON) {
|
|
const json = await model.getExportableDashboardJson();
|
|
return JSON.stringify(json, null, 2);
|
|
}
|
|
|
|
return '';
|
|
}, [isViewingJSON]);
|
|
|
|
return (
|
|
<>
|
|
{!isViewingJSON && (
|
|
<>
|
|
<p className="share-modal-info-text">
|
|
<Trans i18nKey="share-modal.export.info-text">Export this dashboard.</Trans>
|
|
</p>
|
|
<VerticalGroup spacing="md">
|
|
<Field label={exportExternallyTranslation}>
|
|
<Switch
|
|
id="share-externally-toggle"
|
|
value={isSharingExternally}
|
|
onChange={model.onShareExternallyChange}
|
|
/>
|
|
</Field>
|
|
</VerticalGroup>
|
|
|
|
<Modal.ButtonRow>
|
|
<Button
|
|
variant="secondary"
|
|
onClick={() => {
|
|
modalRef?.resolve().onDismiss();
|
|
}}
|
|
fill="outline"
|
|
>
|
|
<Trans i18nKey="share-modal.export.cancel-button">Cancel</Trans>
|
|
</Button>
|
|
<Button variant="secondary" icon="brackets-curly" onClick={model.onViewJSON}>
|
|
<Trans i18nKey="share-modal.export.view-button">View JSON</Trans>
|
|
</Button>
|
|
<Button variant="primary" icon="save" onClick={() => model.onSaveAsFile()}>
|
|
<Trans i18nKey="share-modal.export.save-button">Save to file</Trans>
|
|
</Button>
|
|
</Modal.ButtonRow>
|
|
</>
|
|
)}
|
|
|
|
{isViewingJSON && (
|
|
<>
|
|
<AutoSizer disableHeight>
|
|
{({ width }) => {
|
|
if (dashboardJson.value) {
|
|
return (
|
|
<CodeEditor
|
|
value={dashboardJson.value ?? ''}
|
|
language="json"
|
|
showMiniMap={false}
|
|
height="500px"
|
|
width={width}
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (dashboardJson.loading) {
|
|
return <div>Loading...</div>;
|
|
}
|
|
|
|
return null;
|
|
}}
|
|
</AutoSizer>
|
|
|
|
<Modal.ButtonRow>
|
|
<Button variant="secondary" fill="outline" onClick={model.onViewJSON} icon="arrow-left">
|
|
<Trans i18nKey="share-modal.export.back-button">Back to export config</Trans>
|
|
</Button>
|
|
<ClipboardButton
|
|
variant="secondary"
|
|
icon="copy"
|
|
disabled={dashboardJson.loading}
|
|
getText={() => dashboardJson.value ?? ''}
|
|
>
|
|
<Trans i18nKey="share-modal.view-json.copy-button">Copy to Clipboard</Trans>
|
|
</ClipboardButton>
|
|
<Button variant="primary" icon="save" disabled={dashboardJson.loading} onClick={() => model.onSaveAsFile()}>
|
|
<Trans i18nKey="share-modal.export.save-button">Save to file</Trans>
|
|
</Button>
|
|
</Modal.ButtonRow>
|
|
</>
|
|
)}
|
|
</>
|
|
);
|
|
}
|