<commit_before>'use strict';
/*global ace*/

import DataSelector from './data_selector.react';
import Icon from './icon.react';

export default React.createClass({
    displayName: 'NativeQueryEditor',
    propTypes: {
        databases: React.PropTypes.array.isRequired,
        query: React.PropTypes.object.isRequired,
        setQueryFn: React.PropTypes.func.isRequired,
        setDatabaseFn: React.PropTypes.func.isRequired,
        autocompleteResultsFn: React.PropTypes.func.isRequired
    },

    getInitialState: function() {
        return {
            showEditor: false
        };
    },

    componentDidMount: function() {
        this.loadAceEditor();
    },

    loadAceEditor: function() {
        var editor = ace.edit("id_sql");

        // TODO: theme?

        // set editor mode appropriately
        // TODO: at some point we could make this dynamic based on database type
        editor.getSession().setMode("ace/mode/sql");

        // listen to onChange events
        editor.getSession().on('change', this.onChange);

        // initialize the content
        editor.setValue(this.props.query.native.query);

        // clear the editor selection, otherwise we start with the whole editor selected
        editor.clearSelection();

        // hmmm, this could be dangerous
        editor.focus();

        this.setState({
            editor: editor
        });

        var aceLanguageTools = ace.require('ace/ext/language_tools');
        editor.setOptions({
            enableBasicAutocompletion: true,
            enableSnippets: true,
            enableLiveAutocompletion: true,
            showPrintMargin: false,
            highlightActiveLine: false,
            highlightGutterLine: false,
            showLineNumbers: true
        });

        var autocompleteFn = this.props.autocompleteResultsFn;
        aceLanguageTools.addCompleter({
            getCompletions: function(editor, session, pos, prefix, callback) {
                if (prefix.length < 2) {
                    callback(null, []);
                    return;
                }

                autocompleteFn(prefix).then(function (results) {
                    // transform results of the API call into what ACE expects
                    var js_results = results.map(function(result) {
                        return {
                            name: result[0],
                            value: result[0],
                            meta: result[1]
                        };
                    });
                    callback(null, js_results);

                }, function (error) {
                    console.log('error getting autocompletion data', error);
                    callback(null, []);
                });
            }
        });
    },

    setQuery: function(dataset_query) {
        this.props.setQueryFn(dataset_query);
    },

    onChange: function(event) {
        if (this.state.editor) {
            var query = this.props.query;
            query.native.query = this.state.editor.getValue();
            this.setQuery(query);
        }
    },

    toggleEditor: function() {
        this.setState({ showEditor: !this.state.showEditor })
    },

    render: function() {
        // we only render a db selector if there are actually multiple to choose from
        var dbSelector;
        if(this.state.showEditor && this.props.databases && this.props.databases.length > 1) {
            dbSelector = (
                <DataSelector
                    name="Database"
                    databases={this.props.databases}
                    query={this.props.query}
                    setDatabaseFn={this.props.setDatabaseFn}
                />
            );
        } else {
            dbSelector = <span className="p2 text-grey-4">This question is written in SQL.</span>;
        }

        var editorClasses, toggleEditorText, toggleEditorIcon;
        if (this.state.showEditor) {
            editorClasses = "";
            toggleEditorText = "Hide Editor";
            toggleEditorIcon = "contract";
        } else {
            editorClasses = "hide";
            toggleEditorText = "Open Editor";
            toggleEditorIcon = "expand";
        }

        return (
            <div className="wrapper">
                <div className="NativeQueryEditor bordered rounded shadowed">
                    <div className="flex">
                        {dbSelector}
                        <a href="#" className="Query-label no-decoration flex-align-right flex align-center px2" onClick={this.toggleEditor}>
                            <span className="mx2">{toggleEditorText}</span>
                            <Icon name={toggleEditorIcon} width="20" height="20"/>
                        </a>
                    </div>
                    <div className={"border-top " + editorClasses}>
                        <div id="id_sql"></div>
                    </div>
                </div>
            </div>
        );
    }
});
<commit_msg>allow the SQL editor to start in an expanded state when the query is empty.  (fixes #915)<commit_after>'use strict';
/*global ace*/

import DataSelector from './data_selector.react';
import Icon from './icon.react';

export default React.createClass({
    displayName: 'NativeQueryEditor',
    propTypes: {
        databases: React.PropTypes.array.isRequired,
        query: React.PropTypes.object.isRequired,
        setQueryFn: React.PropTypes.func.isRequired,
        setDatabaseFn: React.PropTypes.func.isRequired,
        autocompleteResultsFn: React.PropTypes.func.isRequired
    },

    getInitialState: function() {
        return {
            showEditor: false
        };
    },

    componentWillMount: function() {
        // if the sql is empty then start with the editor showing, otherwise our default is to start out collapsed
        if (!this.props.query.native.query) {
            this.setState({
                showEditor: true
            });
        }
    },

    componentDidMount: function() {
        this.loadAceEditor();
    },

    loadAceEditor: function() {
        var editor = ace.edit("id_sql");

        // TODO: theme?

        // set editor mode appropriately
        // TODO: at some point we could make this dynamic based on database type
        editor.getSession().setMode("ace/mode/sql");

        // listen to onChange events
        editor.getSession().on('change', this.onChange);

        // initialize the content
        editor.setValue(this.props.query.native.query);

        // clear the editor selection, otherwise we start with the whole editor selected
        editor.clearSelection();

        // hmmm, this could be dangerous
        editor.focus();

        this.setState({
            editor: editor
        });

        var aceLanguageTools = ace.require('ace/ext/language_tools');
        editor.setOptions({
            enableBasicAutocompletion: true,
            enableSnippets: true,
            enableLiveAutocompletion: true,
            showPrintMargin: false,
            highlightActiveLine: false,
            highlightGutterLine: false,
            showLineNumbers: true
        });

        var autocompleteFn = this.props.autocompleteResultsFn;
        aceLanguageTools.addCompleter({
            getCompletions: function(editor, session, pos, prefix, callback) {
                if (prefix.length < 2) {
                    callback(null, []);
                    return;
                }

                autocompleteFn(prefix).then(function (results) {
                    // transform results of the API call into what ACE expects
                    var js_results = results.map(function(result) {
                        return {
                            name: result[0],
                            value: result[0],
                            meta: result[1]
                        };
                    });
                    callback(null, js_results);

                }, function (error) {
                    console.log('error getting autocompletion data', error);
                    callback(null, []);
                });
            }
        });
    },

    setQuery: function(dataset_query) {
        this.props.setQueryFn(dataset_query);
    },

    onChange: function(event) {
        if (this.state.editor) {
            var query = this.props.query;
            query.native.query = this.state.editor.getValue();
            this.setQuery(query);
        }
    },

    toggleEditor: function() {
        this.setState({ showEditor: !this.state.showEditor })
    },

    render: function() {
        // we only render a db selector if there are actually multiple to choose from
        var dbSelector;
        if(this.state.showEditor && this.props.databases && this.props.databases.length > 1) {
            dbSelector = (
                <DataSelector
                    name="Database"
                    databases={this.props.databases}
                    query={this.props.query}
                    setDatabaseFn={this.props.setDatabaseFn}
                />
            );
        } else {
            dbSelector = <span className="p2 text-grey-4">This question is written in SQL.</span>;
        }

        var editorClasses, toggleEditorText, toggleEditorIcon;
        if (this.state.showEditor) {
            editorClasses = "";
            toggleEditorText = "Hide Editor";
            toggleEditorIcon = "contract";
        } else {
            editorClasses = "hide";
            toggleEditorText = "Open Editor";
            toggleEditorIcon = "expand";
        }

        return (
            <div className="wrapper">
                <div className="NativeQueryEditor bordered rounded shadowed">
                    <div className="flex">
                        {dbSelector}
                        <a href="#" className="Query-label no-decoration flex-align-right flex align-center px2" onClick={this.toggleEditor}>
                            <span className="mx2">{toggleEditorText}</span>
                            <Icon name={toggleEditorIcon} width="20" height="20"/>
                        </a>
                    </div>
                    <div className={"border-top " + editorClasses}>
                        <div id="id_sql"></div>
                    </div>
                </div>
            </div>
        );
    }
});

{'fraction_non_alphanumeric': 0.10323515210043457, 'fraction_numerical': 0.0028005794302269436, 'mean_word_length': 1.5538840937114673, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5937859', 'n_tokens_mistral': 2593, 'n_tokens_neox': 2470, 'n_words': 582}