mirror of
https://github.com/apache/superset.git
synced 2026-04-21 09:04:38 +00:00
[explore] refactor slice action button group (#1074)
* pull explore actions button group into component * use button component * make sure we render all action buttons * test that embed code is correct * don't need before each * generalize modal trigger for use with plain links or icons
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import ModalTrigger from './../../components/ModalTrigger';
|
||||
|
||||
const propTypes = {
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default class DisplayQueryButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
viewSqlQuery: '',
|
||||
};
|
||||
this.beforeOpen = this.beforeOpen.bind(this);
|
||||
}
|
||||
|
||||
beforeOpen() {
|
||||
this.setState({
|
||||
viewSqlQuery: this.props.slice.viewSqlQuery,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const modalBody = (<pre>{this.state.viewSqlQuery}</pre>);
|
||||
return (
|
||||
<ModalTrigger
|
||||
isButton
|
||||
triggerNode={<span>Query</span>}
|
||||
modalTitle="Query"
|
||||
modalBody={modalBody}
|
||||
beforeOpen={this.beforeOpen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayQueryButton.propTypes = propTypes;
|
||||
@@ -0,0 +1,105 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import CopyToClipboard from './../../components/CopyToClipboard';
|
||||
import { Popover, OverlayTrigger } from 'react-bootstrap';
|
||||
|
||||
const propTypes = {
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default class EmbedCodeButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
height: '400',
|
||||
width: '600',
|
||||
srcLink: window.location.origin + props.slice.data.standalone_endpoint,
|
||||
};
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
}
|
||||
|
||||
handleInputChange(e) {
|
||||
const value = e.currentTarget.value;
|
||||
const name = e.currentTarget.name;
|
||||
const data = {};
|
||||
data[name] = value;
|
||||
this.setState(data);
|
||||
}
|
||||
|
||||
generateEmbedHTML() {
|
||||
const { width, height, srcLink } = this.state;
|
||||
/* eslint max-len: 0 */
|
||||
const embedHTML =
|
||||
`<iframe src="${srcLink}" width="${width}" height="${height}" seamless frameBorder="0" scrolling="no"></iframe>`;
|
||||
return embedHTML;
|
||||
}
|
||||
|
||||
renderPopover() {
|
||||
const html = this.generateEmbedHTML();
|
||||
return (
|
||||
<Popover id="embed-code-popover">
|
||||
<div>
|
||||
<div className="row">
|
||||
<div className="col-sm-10">
|
||||
<textarea name="embedCode" value={html} rows="4" readOnly className="form-control input-sm"></textarea>
|
||||
</div>
|
||||
<div className="col-sm-2">
|
||||
<CopyToClipboard
|
||||
shouldShowText={false}
|
||||
text={html}
|
||||
copyNode={<i className="fa fa-clipboard" title="Copy to clipboard"></i>}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div className="row">
|
||||
<div className="col-md-6 col-sm-12">
|
||||
<div className="form-group">
|
||||
<small>
|
||||
<label className="control-label" htmlFor="embed-height">Height</label>
|
||||
</small>
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
type="text"
|
||||
defaultValue={this.state.height}
|
||||
name="height"
|
||||
onChange={this.handleInputChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-6 col-sm-12">
|
||||
<div className="form-group">
|
||||
<small>
|
||||
<label className="control-label" htmlFor="embed-width">Width</label>
|
||||
</small>
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
type="text"
|
||||
defaultValue={this.state.width}
|
||||
name="width"
|
||||
onChange={this.handleInputChange}
|
||||
id="embed-width"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger
|
||||
trigger="click"
|
||||
rootClose
|
||||
placement="left"
|
||||
overlay={this.renderPopover()}
|
||||
>
|
||||
<span className="btn btn-default btn-sm">
|
||||
<i className="fa fa-code"></i>
|
||||
</span>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EmbedCodeButton.propTypes = propTypes;
|
||||
@@ -0,0 +1,46 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import cx from 'classnames';
|
||||
import URLShortLinkButton from './URLShortLinkButton';
|
||||
import EmbedCodeButton from './EmbedCodeButton';
|
||||
import DisplayQueryButton from './DisplayQueryButton';
|
||||
|
||||
const propTypes = {
|
||||
canDownload: PropTypes.string.isRequired,
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default function ExploreActionButtons({ canDownload, slice }) {
|
||||
const exportToCSVClasses = cx('btn btn-default btn-sm', {
|
||||
'disabled disabledButton': !canDownload,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="btn-group results" role="group">
|
||||
<URLShortLinkButton slice={slice} />
|
||||
|
||||
<EmbedCodeButton slice={slice} />
|
||||
|
||||
<a
|
||||
href={slice.data.json_endpoint}
|
||||
className="btn btn-default btn-sm"
|
||||
title="Export to .json"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa fa-file-code-o"></i> .json
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={slice.data.csv_endpoint}
|
||||
className={exportToCSVClasses}
|
||||
title="Export to .csv format"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa fa-file-text-o"></i> .csv
|
||||
</a>
|
||||
|
||||
<DisplayQueryButton slice={slice} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ExploreActionButtons.propTypes = propTypes;
|
||||
@@ -0,0 +1,71 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Popover, OverlayTrigger } from 'react-bootstrap';
|
||||
import CopyToClipboard from './../../components/CopyToClipboard';
|
||||
import $ from 'jquery';
|
||||
|
||||
const propTypes = {
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default class URLShortLinkButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shortUrl: '',
|
||||
};
|
||||
|
||||
this.getShortUrl();
|
||||
}
|
||||
|
||||
getShortUrl() {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/r/shortner/',
|
||||
data: {
|
||||
data: '/' + window.location.pathname + this.props.slice.querystring(),
|
||||
},
|
||||
success: (data) => {
|
||||
this.setState({
|
||||
shortUrl: data,
|
||||
});
|
||||
},
|
||||
error: (error) => {
|
||||
/* eslint no-console: 0 */
|
||||
if (console && console.warn) {
|
||||
console.warn('Something went wrong...');
|
||||
console.warn(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderPopover() {
|
||||
return (
|
||||
<Popover id="shorturl-popover">
|
||||
<CopyToClipboard
|
||||
text={this.state.shortUrl}
|
||||
copyNode={<i className="fa fa-clipboard" title="Copy to clipboard"></i>}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const shortUrl = this.state.shortUrl;
|
||||
const isDisabled = shortUrl === '';
|
||||
return (
|
||||
<OverlayTrigger
|
||||
trigger="click"
|
||||
rootClose
|
||||
placement="left"
|
||||
overlay={this.renderPopover()}
|
||||
>
|
||||
<span className="btn btn-default btn-sm" disabled={isDisabled}>
|
||||
<i className="fa fa-link"></i>
|
||||
</span>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
URLShortLinkButton.propTypes = propTypes;
|
||||
Reference in New Issue
Block a user