mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* Change download icon from sortDown to exportAction in workpad loader * Added context menu and download menu item to workpad export popover * Updated icon on download button in workpad loader * Added TODO in workpad export * Added copy to clipboard on click to disabled reporting panel view
This commit is contained in:
parent
bea81ad0c6
commit
1ba322c4a8
9 changed files with 190 additions and 85 deletions
|
@ -28,7 +28,7 @@ export class Clipboard extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div className="canvas_clipboard" onClick={this.onClick}>
|
||||
<div className="canvasClipboard" onClick={this.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.canvasClipboard {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -13,6 +13,7 @@ import { getWorkpad, getPages } from '../../state/selectors/workpad';
|
|||
import { getReportingBrowserType } from '../../state/selectors/app';
|
||||
import { notify } from '../../lib/notify';
|
||||
import { getWindow } from '../../lib/get_window';
|
||||
import { downloadWorkpad } from '../../lib/download_workpad';
|
||||
import { WorkpadExport as Component } from './workpad_export';
|
||||
import { getPdfUrl, createPdf } from './utils';
|
||||
|
||||
|
@ -43,29 +44,34 @@ export const WorkpadExport = compose(
|
|||
throw new Error(`Unknown export type: ${type}`);
|
||||
},
|
||||
onCopy: type => {
|
||||
if (type === 'pdf') {
|
||||
return notify.info('The PDF generation URL was copied to your clipboard.');
|
||||
switch (type) {
|
||||
case 'pdf':
|
||||
return notify.info('The PDF generation URL was copied to your clipboard.');
|
||||
case 'reportingConfig':
|
||||
return notify.info(`Copied reporting configuration to clipboard`);
|
||||
}
|
||||
|
||||
throw new Error(`Unknown export type: ${type}`);
|
||||
},
|
||||
onExport: type => {
|
||||
if (type === 'pdf') {
|
||||
return createPdf(workpad, { pageCount })
|
||||
.then(({ data }) => {
|
||||
notify.info('Exporting PDF. You can track the progress in Management.', {
|
||||
title: `PDF export of workpad '${workpad.name}'`,
|
||||
switch (type) {
|
||||
case 'pdf':
|
||||
return createPdf(workpad, { pageCount })
|
||||
.then(({ data }) => {
|
||||
notify.info('Exporting PDF. You can track the progress in Management.', {
|
||||
title: `PDF export of workpad '${workpad.name}'`,
|
||||
});
|
||||
|
||||
// register the job so a completion notification shows up when it's ready
|
||||
jobCompletionNotifications.add(data.job.id);
|
||||
})
|
||||
.catch(err => {
|
||||
notify.error(err, { title: `Failed to create PDF for '${workpad.name}'` });
|
||||
});
|
||||
|
||||
// register the job so a completion notification shows up when it's ready
|
||||
jobCompletionNotifications.add(data.job.id);
|
||||
})
|
||||
.catch(err => {
|
||||
notify.error(err, { title: `Failed to create PDF for '${workpad.name}'` });
|
||||
});
|
||||
case 'json':
|
||||
return downloadWorkpad(workpad.id);
|
||||
default:
|
||||
throw new Error(`Unknown export type: ${type}`);
|
||||
}
|
||||
|
||||
throw new Error(`Unknown export type: ${type}`);
|
||||
},
|
||||
}))
|
||||
)(Component);
|
||||
|
|
|
@ -9,12 +9,12 @@ import PropTypes from 'prop-types';
|
|||
import {
|
||||
EuiButton,
|
||||
EuiButtonIcon,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiSpacer,
|
||||
EuiCodeBlock,
|
||||
EuiHorizontalRule,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiContextMenu,
|
||||
EuiIcon,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { Popover } from '../popover';
|
||||
import { Clipboard } from '../clipboard';
|
||||
|
@ -27,81 +27,155 @@ export class WorkpadExport extends React.PureComponent {
|
|||
getExportUrl: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
anchorElement = React.createRef();
|
||||
|
||||
flattenPanelTree(tree, array = []) {
|
||||
array.push(tree);
|
||||
|
||||
if (tree.items) {
|
||||
tree.items.forEach(item => {
|
||||
if (item.panel) {
|
||||
this.flattenPanelTree(item.panel, array);
|
||||
item.panel = item.panel.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
exportPdf = () => {
|
||||
this.props.onExport('pdf');
|
||||
};
|
||||
|
||||
renderControls = closePopover => {
|
||||
downloadWorkpad = () => {
|
||||
this.props.onExport('json');
|
||||
};
|
||||
|
||||
renderPDFControls = closePopover => {
|
||||
const pdfUrl = this.props.getExportUrl('pdf');
|
||||
return (
|
||||
<div>
|
||||
<EuiFlexGroup justifyContent="spaceAround">
|
||||
<EuiFlexItem grow>
|
||||
<EuiFormRow label="Click below to create a PDF. You'll be notified when the export is complete">
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
this.exportPdf();
|
||||
closePopover();
|
||||
}}
|
||||
>
|
||||
Export as PDF
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiHorizontalRule size="half" />
|
||||
<EuiFormRow label="To generate a PDF from a script or with Watcher, use this URL.">
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem style={{ overflow: 'auto' }}>
|
||||
<EuiCodeBlock style={{ whiteSpace: 'nowrap' }} paddingSize="s">
|
||||
{pdfUrl}
|
||||
</EuiCodeBlock>
|
||||
</EuiFlexItem>
|
||||
<div className="canvasWorkpadExport__panelContent">
|
||||
<EuiText size="s">
|
||||
<p>PDFs can take a minute or two to generate based upon the size of your workpad</p>
|
||||
</EuiText>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<Clipboard
|
||||
content={pdfUrl}
|
||||
onCopy={() => {
|
||||
this.props.onCopy('pdf');
|
||||
closePopover();
|
||||
}}
|
||||
>
|
||||
<EuiButtonIcon aria-label="Copy to clipboard" iconType="copy" />
|
||||
</Clipboard>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFormRow>
|
||||
{this.props.options}
|
||||
|
||||
<EuiButton
|
||||
fill
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
this.exportPdf();
|
||||
}}
|
||||
size="s"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
Generate PDF
|
||||
</EuiButton>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<EuiText size="s">
|
||||
<p>
|
||||
Alternatively, copy this POST URL to call generation from outside Kibana or from
|
||||
Watcher.
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<Clipboard
|
||||
content={pdfUrl}
|
||||
onCopy={() => {
|
||||
this.props.onCopy('pdf');
|
||||
closePopover();
|
||||
}}
|
||||
>
|
||||
<EuiButton
|
||||
aria-label="Copy to clipboard"
|
||||
iconType="copy"
|
||||
size="s"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
Copy POST URL
|
||||
</EuiButton>
|
||||
</Clipboard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderPanelTree = closePopover => ({
|
||||
id: 0,
|
||||
title: 'Share this workpad',
|
||||
items: [
|
||||
{
|
||||
name: 'Download as JSON',
|
||||
icon: <EuiIcon type="exportAction" size="m" />,
|
||||
onClick: () => {
|
||||
closePopover();
|
||||
this.downloadWorkpad();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'PDF Reports',
|
||||
icon: 'document',
|
||||
panel: {
|
||||
id: 1,
|
||||
title: 'PDF Reports',
|
||||
content: this.props.enabled
|
||||
? this.renderPDFControls(closePopover)
|
||||
: this.renderDisabled(),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
renderDisabled = () => {
|
||||
const reportingConfig = `xpack.reporting:
|
||||
enabled: true
|
||||
capture.browser.type: chromium`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
Export to PDF is disabled. You must configure reporting to use the Chromium browser. Add
|
||||
this to your kibana.yml file.
|
||||
<div className="canvasWorkpadExport__panelContent">
|
||||
<EuiText size="s">
|
||||
<p>
|
||||
Export to PDF is disabled. You must configure reporting to use the Chromium browser. Add
|
||||
this to your <EuiCode>kibana.yml</EuiCode> file.
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiCodeBlock paddingSize="s" language="yml">
|
||||
xpack.reporting.capture.browser.type: chromium
|
||||
</EuiCodeBlock>
|
||||
<Clipboard content={reportingConfig} onCopy={() => this.props.onCopy('reportingConfig')}>
|
||||
<EuiCodeBlock
|
||||
className="canvasWorkpadExport__reportingConfig"
|
||||
paddingSize="s"
|
||||
fontSize="s"
|
||||
language="yml"
|
||||
>
|
||||
{reportingConfig}
|
||||
</EuiCodeBlock>
|
||||
</Clipboard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const exportControl = togglePopover => (
|
||||
<EuiButtonIcon iconType="exportAction" aria-label="Create PDF" onClick={togglePopover} />
|
||||
<EuiButtonIcon iconType="share" aria-label="Share this workpad" onClick={togglePopover} />
|
||||
);
|
||||
|
||||
// TODO: replace this with `showShareContextMenu` in `ui/share` once it's been converted to React
|
||||
return (
|
||||
<Popover button={exportControl} tooltip="Export workpad" tooltipPosition="bottom">
|
||||
<Popover
|
||||
button={exportControl}
|
||||
panelPaddingSize="none"
|
||||
tooltip="Share workpad"
|
||||
tooltipPosition="bottom"
|
||||
>
|
||||
{({ closePopover }) => (
|
||||
<EuiFlexGroup justifyContent="flexEnd">
|
||||
<EuiFlexItem grow={false} style={{ maxWidth: '300px' }}>
|
||||
{this.props.enabled && this.renderControls(closePopover)}
|
||||
{!this.props.enabled && this.renderDisabled()}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiContextMenu
|
||||
initialPanelId={0}
|
||||
panels={this.flattenPanelTree(this.renderPanelTree(closePopover))}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.canvasWorkpadExport__panelContent {
|
||||
padding: $euiSize;
|
||||
}
|
||||
.canvasWorkpadExport__reportingConfig {
|
||||
.euiCodeBlock__pre {
|
||||
@include euiScrollBar;
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
|
@ -7,13 +7,13 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose, withState, getContext, withHandlers } from 'recompose';
|
||||
import fileSaver from 'file-saver';
|
||||
import * as workpadService from '../../lib/workpad_service';
|
||||
import { notify } from '../../lib/notify';
|
||||
import { canUserWrite } from '../../state/selectors/app';
|
||||
import { getWorkpad } from '../../state/selectors/workpad';
|
||||
import { getId } from '../../lib/get_id';
|
||||
import { setCanUserWrite } from '../../state/actions/transient';
|
||||
import { downloadWorkpad } from '../../lib/download_workpad';
|
||||
import { WorkpadLoader as Component } from './workpad_loader';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
@ -67,15 +67,7 @@ export const WorkpadLoader = compose(
|
|||
},
|
||||
|
||||
// Workpad import/export methods
|
||||
downloadWorkpad: () => async workpadId => {
|
||||
try {
|
||||
const workpad = await workpadService.get(workpadId);
|
||||
const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' });
|
||||
fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`);
|
||||
} catch (err) {
|
||||
notify.error(err, { title: `Couldn't download workpad` });
|
||||
}
|
||||
},
|
||||
downloadWorkpad: () => workpadId => downloadWorkpad(workpadId),
|
||||
|
||||
// Clone workpad given an id
|
||||
cloneWorkpad: props => async workpadId => {
|
||||
|
|
|
@ -142,7 +142,7 @@ export class WorkpadLoader extends React.PureComponent {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Download">
|
||||
<EuiButtonIcon
|
||||
iconType="sortDown"
|
||||
iconType="exportAction"
|
||||
onClick={() => this.props.downloadWorkpad(workpad.id)}
|
||||
aria-label="Download Workpad"
|
||||
/>
|
||||
|
@ -288,7 +288,7 @@ export class WorkpadLoader extends React.PureComponent {
|
|||
);
|
||||
|
||||
const downloadButton = (
|
||||
<EuiButton color="secondary" onClick={this.downloadWorkpads} iconType="sortDown">
|
||||
<EuiButton color="secondary" onClick={this.downloadWorkpads} iconType="exportAction">
|
||||
{`Download (${selectedWorkpads.length})`}
|
||||
</EuiButton>
|
||||
);
|
||||
|
|
18
x-pack/plugins/canvas/public/lib/download_workpad.js
Normal file
18
x-pack/plugins/canvas/public/lib/download_workpad.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import fileSaver from 'file-saver';
|
||||
import { notify } from './notify';
|
||||
import * as workpadService from './workpad_service';
|
||||
|
||||
export const downloadWorkpad = async workpadId => {
|
||||
try {
|
||||
const workpad = await workpadService.get(workpadId);
|
||||
const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' });
|
||||
fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`);
|
||||
} catch (err) {
|
||||
notify.error(err, { title: `Couldn't download workpad` });
|
||||
}
|
||||
};
|
|
@ -24,6 +24,7 @@
|
|||
@import '../components/autocomplete/autocomplete';
|
||||
@import '../components/border_connection/border_connection';
|
||||
@import '../components/border_resize_handle/border_resize_handle';
|
||||
@import '../components/clipboard/clipboard';
|
||||
@import '../components/color_dot/color_dot';
|
||||
@import '../components/color_palette/color_palette';
|
||||
@import '../components/color_picker_mini/color_picker_mini';
|
||||
|
@ -52,6 +53,7 @@
|
|||
@import '../components/toolbar/toolbar';
|
||||
@import '../components/toolbar/tray/tray';
|
||||
@import '../components/workpad/workpad';
|
||||
@import '../components/workpad_export/workpad_export';
|
||||
@import '../components/workpad_loader/workpad_loader';
|
||||
@import '../components/workpad_loader/workpad_dropzone/workpad_dropzone';
|
||||
@import '../components/workpad_page/workpad_page';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue