Files
superset2/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
Maxime Beauchemin 69195f8d2d Introduce Javascript controls (#4076)
* Introduce Javascript controls

This allows power-users to perform intricate transformations on data and
objects using javascript code.

The operations allowed are "sanboxed" or limited using node's vm
`runInNewContext`
https://nodejs.org/api/vm.html#vm_vm_runinnewcontext_code_sandbox_options

For now I'm only enabling in the line chart visualization, but the plan
would be to go towards offering more power to people who can write some
JS moving forward.

* Not applied
2017-12-20 21:24:35 -08:00

106 lines
2.8 KiB
JavaScript

import React from 'react';
import PropTypes from 'prop-types';
import { Button, FormGroup, FormControl } from 'react-bootstrap';
import AceEditor from 'react-ace';
import 'brace/mode/sql';
import 'brace/mode/json';
import 'brace/mode/html';
import 'brace/mode/markdown';
import 'brace/mode/javascript';
import 'brace/theme/textmate';
import ControlHeader from '../ControlHeader';
import ModalTrigger from '../../../components/ModalTrigger';
import { t } from '../../../locales';
const propTypes = {
name: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string,
height: PropTypes.number,
minLines: PropTypes.number,
maxLines: PropTypes.number,
offerEditInModal: PropTypes.bool,
language: PropTypes.oneOf([null, 'json', 'html', 'sql', 'markdown', 'javascript']),
aboveEditorSection: PropTypes.node,
};
const defaultProps = {
onChange: () => {},
value: '',
height: 250,
minLines: 3,
maxLines: 10,
offerEditInModal: true,
};
export default class TextAreaControl extends React.Component {
onControlChange(event) {
this.props.onChange(event.target.value);
}
onAceChange(value) {
this.props.onChange(value);
}
renderEditor(inModal = false) {
if (this.props.language) {
return (
<AceEditor
mode={this.props.language}
theme="textmate"
style={{ border: '1px solid #CCC' }}
minLines={inModal ? 40 : this.props.minLines}
maxLines={inModal ? 1000 : this.props.maxLines}
onChange={this.onAceChange.bind(this)}
width="100%"
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion
value={this.props.value}
/>
);
}
return (
<FormGroup controlId="formControlsTextarea">
<FormControl
componentClass="textarea"
placeholder={t('textarea')}
onChange={this.onControlChange.bind(this)}
value={this.props.value}
style={{ height: this.props.height }}
/>
</FormGroup>);
}
renderModalBody() {
return (
<div>
<div>{this.props.aboveEditorSection}</div>
{this.renderEditor(true)}
</div>
);
}
render() {
const controlHeader = <ControlHeader {...this.props} />;
return (
<div>
{controlHeader}
{this.renderEditor()}
{this.props.offerEditInModal &&
<ModalTrigger
bsSize="large"
modalTitle={controlHeader}
triggerNode={
<Button bsSize="small" className="m-t-5">
{t('Edit')} <strong>{this.props.language}</strong> {t('in modal')}
</Button>
}
modalBody={this.renderModalBody(true)}
/>}
</div>
);
}
}
TextAreaControl.propTypes = propTypes;
TextAreaControl.defaultProps = defaultProps;