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:
102
caravel/assets/javascripts/components/CopyToClipboard.jsx
Normal file
102
caravel/assets/javascripts/components/CopyToClipboard.jsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Button, Tooltip, OverlayTrigger } from 'react-bootstrap';
|
||||
|
||||
const propTypes = {
|
||||
copyNode: PropTypes.node,
|
||||
onCopyEnd: PropTypes.func,
|
||||
shouldShowText: PropTypes.bool,
|
||||
text: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
copyNode: <span>Copy</span>,
|
||||
onCopyEnd: () => {},
|
||||
shouldShowText: true,
|
||||
};
|
||||
|
||||
export default class CopyToClipboard extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hasCopied: false,
|
||||
};
|
||||
|
||||
// bindings
|
||||
this.copyToClipboard = this.copyToClipboard.bind(this);
|
||||
this.resetTooltipText = this.resetTooltipText.bind(this);
|
||||
this.onMouseOut = this.onMouseOut.bind(this);
|
||||
}
|
||||
|
||||
onMouseOut() {
|
||||
// delay to avoid flash of text change on tooltip
|
||||
setTimeout(this.resetTooltipText, 200);
|
||||
}
|
||||
|
||||
resetTooltipText() {
|
||||
this.setState({ hasCopied: false });
|
||||
}
|
||||
|
||||
copyToClipboard() {
|
||||
const textToCopy = this.props.text;
|
||||
const textArea = document.createElement('textarea');
|
||||
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-1000px';
|
||||
textArea.value = textToCopy;
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
if (!document.execCommand('copy')) {
|
||||
throw new Error('Not successful');
|
||||
}
|
||||
} catch (err) {
|
||||
window.alert('Sorry, your browser does not support copying. Use Ctrl / Cmd + C!'); // eslint-disable-line
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
this.setState({ hasCopied: true });
|
||||
this.props.onCopyEnd();
|
||||
}
|
||||
|
||||
tooltipText() {
|
||||
let tooltipText;
|
||||
if (this.state.hasCopied) {
|
||||
tooltipText = 'Copied!';
|
||||
} else {
|
||||
tooltipText = 'Copy text';
|
||||
}
|
||||
return tooltipText;
|
||||
}
|
||||
|
||||
render() {
|
||||
const tooltip = (
|
||||
<Tooltip id="copy-to-clipboard-tooltip">
|
||||
{this.tooltipText()}
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{this.props.shouldShowText &&
|
||||
<span>{this.props.text}</span>
|
||||
}
|
||||
|
||||
<OverlayTrigger placement="top" overlay={tooltip} trigger={['hover']}>
|
||||
<Button
|
||||
bsStyle="link"
|
||||
onClick={this.copyToClipboard}
|
||||
onMouseOut={this.onMouseOut}
|
||||
>
|
||||
{this.props.copyNode}
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CopyToClipboard.propTypes = propTypes;
|
||||
CopyToClipboard.defaultProps = defaultProps;
|
||||
59
caravel/assets/javascripts/components/ModalTrigger.jsx
Normal file
59
caravel/assets/javascripts/components/ModalTrigger.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
import cx from 'classnames';
|
||||
|
||||
const propTypes = {
|
||||
triggerNode: PropTypes.node.isRequired,
|
||||
modalTitle: PropTypes.string.isRequired,
|
||||
modalBody: PropTypes.node.isRequired,
|
||||
beforeOpen: PropTypes.func,
|
||||
isButton: PropTypes.bool,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
beforeOpen: () => {},
|
||||
isButton: false,
|
||||
};
|
||||
|
||||
export default class ModalTrigger extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showModal: false,
|
||||
};
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({ showModal: false });
|
||||
}
|
||||
|
||||
open(e) {
|
||||
e.preventDefault();
|
||||
this.props.beforeOpen();
|
||||
this.setState({ showModal: true });
|
||||
}
|
||||
|
||||
render() {
|
||||
const classNames = cx({
|
||||
'btn btn-default btn-sm': this.props.isButton,
|
||||
});
|
||||
return (
|
||||
<a href="#" className={classNames} onClick={this.open}>
|
||||
{this.props.triggerNode}
|
||||
<Modal show={this.state.showModal} onHide={this.close}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>{this.props.modalTitle}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{this.props.modalBody}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ModalTrigger.propTypes = propTypes;
|
||||
ModalTrigger.defaultProps = defaultProps;
|
||||
Reference in New Issue
Block a user