From d7abefe0cb8157bef5067af9e18ad9ceaba094fb Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 16 Jan 2019 00:54:26 -0800 Subject: [PATCH 1/6] allow execution of selected subquery --- client/app/components/QueryEditor.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx index 9c4d78f305c..2468861c1fc 100644 --- a/client/app/components/QueryEditor.jsx +++ b/client/app/components/QueryEditor.jsx @@ -129,6 +129,7 @@ class QueryEditor extends React.Component { onLoad = (editor) => { // Release Cmd/Ctrl+L to the browser + this.editor = editor; editor.commands.bindKey('Cmd+L', null); editor.commands.bindKey('Ctrl+P', null); editor.commands.bindKey('Ctrl+L', null); @@ -181,6 +182,17 @@ class QueryEditor extends React.Component { }); }; + updateQueryWithSelection = (selection) => { + const doc = this.editor.getSession().doc; + const queryText = doc.getTextRange(selection.getRange()); + const hasSelectedQuery = queryText.length > 1; + if (hasSelectedQuery) { + this.props.updateQuery(queryText); + } else { + this.props.updateQuery(this.state.queryText); + } + } + updateQuery = (queryText) => { this.props.updateQuery(queryText); this.setState({ queryText }); @@ -229,6 +241,7 @@ class QueryEditor extends React.Component { onLoad={this.onLoad} onPaste={this.onPaste} onChange={this.updateQuery} + onSelectionChange={this.updateQueryWithSelection} /> From 130652126d3bb3a3abcb7bf6f8eacc6cf9a1e92a Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 16 Jan 2019 01:41:35 -0800 Subject: [PATCH 2/6] fix query save while highlighted --- client/app/components/QueryEditor.jsx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx index 2468861c1fc..60ef9cd5dec 100644 --- a/client/app/components/QueryEditor.jsx +++ b/client/app/components/QueryEditor.jsx @@ -182,17 +182,25 @@ class QueryEditor extends React.Component { }); }; + setFullUnhighlightedQuery = () => { + this.props.updateQuery(this.state.queryText); + } + updateQueryWithSelection = (selection) => { const doc = this.editor.getSession().doc; - const queryText = doc.getTextRange(selection.getRange()); - const hasSelectedQuery = queryText.length > 1; - if (hasSelectedQuery) { - this.props.updateQuery(queryText); + const highlightedQueryText = doc.getTextRange(selection.getRange()); + if (highlightedQueryText.length > 1) { + this.props.updateQuery(highlightedQueryText); } else { - this.props.updateQuery(this.state.queryText); + this.setFullUnhighlightedQuery(); } } + saveQuery = (customOptions, data) => { + this.setFullUnhighlightedQuery(); + this.props.saveQuery(customOptions, data); + } + updateQuery = (queryText) => { this.props.updateQuery(queryText); this.setState({ queryText }); @@ -282,7 +290,7 @@ class QueryEditor extends React.Component { {this.props.canEdit ? ( - diff --git a/client/app/pages/queries/query.html b/client/app/pages/queries/query.html index 91197ec2af0..ba8dea95398 100644 --- a/client/app/pages/queries/query.html +++ b/client/app/pages/queries/query.html @@ -164,6 +164,7 @@

listen-for-editor-command="listenForEditorCommand" save-query="saveQuery" update-query="updateQuery" + update-highlighted-query="updateHighlightedQuery" add-new-parameter="addNewParameter" data-data-source="dataSource" data-data-sources="dataSources"> diff --git a/client/app/pages/queries/view.js b/client/app/pages/queries/view.js index 6b4b08438a5..fc2567daf92 100644 --- a/client/app/pages/queries/view.js +++ b/client/app/pages/queries/view.js @@ -26,7 +26,7 @@ function QueryViewCtrl( DataSource, Visualization, ) { - function getQueryResult(maxAge) { + function getQueryResult(maxAge, highlightedQueryText) { if (maxAge === undefined) { maxAge = $location.search().maxAge; } @@ -36,7 +36,7 @@ function QueryViewCtrl( } $scope.showLog = false; - $scope.queryResult = $scope.query.getQueryResult(maxAge); + $scope.queryResult = $scope.query.getQueryResult(maxAge, highlightedQueryText); } function getDataSourceId() { @@ -105,6 +105,10 @@ function QueryViewCtrl( getSchema(); } + $scope.updateHighlightedQuery = (highlightedQueryText) => { + $scope.highlightedQueryText = highlightedQueryText; + }; + $scope.executeQuery = () => { if (!$scope.canExecuteQuery()) { return; @@ -114,7 +118,7 @@ function QueryViewCtrl( return; } - getQueryResult(0); + getQueryResult(0, $scope.highlightedQueryText); $scope.lockButton(true); $scope.cancelling = false; Events.record('execute', 'query', $scope.query.id); @@ -372,8 +376,11 @@ function QueryViewCtrl( } if (status === 'done') { - $scope.query.latest_query_data_id = $scope.queryResult.getId(); - $scope.query.queryResult = $scope.queryResult; + const ranSelectedQuery = $scope.query.query !== $scope.queryResult.query; + if (!ranSelectedQuery) { + $scope.query.latest_query_data_id = $scope.queryResult.getId(); + $scope.query.queryResult = $scope.queryResult; + } Notifications.showNotification('Redash', `${$scope.query.name} updated.`); } else if (status === 'failed') { diff --git a/client/app/services/query.js b/client/app/services/query.js index 1999787cd91..33e635e9cce 100644 --- a/client/app/services/query.js +++ b/client/app/services/query.js @@ -431,12 +431,12 @@ function QueryResource( return this.getParameters().isRequired(); }; - Query.prototype.getQueryResult = function getQueryResult(maxAge) { + Query.prototype.getQueryResult = function getQueryResult(maxAge, highlightedQueryText) { if (!this.query) { return new QueryResultError("Can't execute empty query."); } - const queryText = this.query; + const queryText = (highlightedQueryText == null) ? this.query : highlightedQueryText; const parameters = this.getParameters(); const missingParams = parameters.getMissing(); From 516e8126b0d4253116ebfd80f49f3fae2015dc30 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 18 Jan 2019 02:19:06 -0800 Subject: [PATCH 4/6] code style and transition --- client/app/components/QueryEditor.css | 8 ++++++++ client/app/components/QueryEditor.jsx | 9 +++++++-- client/app/services/query.js | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 client/app/components/QueryEditor.css diff --git a/client/app/components/QueryEditor.css b/client/app/components/QueryEditor.css new file mode 100644 index 00000000000..24caf893827 --- /dev/null +++ b/client/app/components/QueryEditor.css @@ -0,0 +1,8 @@ +@keyframes fadeIt { + 0% { background-color: rgba(255, 121, 100, 0.557); } + 100% { background-color: transparent; } +} + +.ace_editor.highlightedText .ace_marker-layer .ace_selection { + animation: fadeIt 0.5s ease-out; +} diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx index 92098e3cecd..71eb5c924eb 100644 --- a/client/app/components/QueryEditor.jsx +++ b/client/app/components/QueryEditor.jsx @@ -19,6 +19,8 @@ import AutocompleteToggle from '@/components/AutocompleteToggle'; import keywordBuilder from './keywordBuilder'; import { DataSource, Schema } from './proptypes'; +import './QueryEditor.css'; + const langTools = ace.acequire('ace/ext/language_tools'); const snippetsModule = ace.acequire('ace/snippets'); @@ -65,6 +67,8 @@ class QueryEditor extends React.Component { constructor(props) { super(props); + this.refEditor = React.createRef(); + this.state = { schema: null, // eslint-disable-line react/no-unused-state keywords: { @@ -131,7 +135,6 @@ class QueryEditor extends React.Component { onLoad = (editor) => { // Release Cmd/Ctrl+L to the browser - this.editor = editor; editor.commands.bindKey('Cmd+L', null); editor.commands.bindKey('Ctrl+P', null); editor.commands.bindKey('Ctrl+L', null); @@ -185,7 +188,8 @@ class QueryEditor extends React.Component { }; updateSelectedQuery = (selection) => { - const doc = this.editor.getSession().doc; + const { editor } = this.refEditor.current; + const doc = editor.getSession().doc; const rawHighlightedQueryText = doc.getTextRange(selection.getRange()); const highlightedQueryText = (rawHighlightedQueryText.length > 1) ? rawHighlightedQueryText : null; this.setState({ highlightedQueryText }); @@ -221,6 +225,7 @@ class QueryEditor extends React.Component {
Date: Fri, 18 Jan 2019 14:51:32 +0200 Subject: [PATCH 5/6] Fix query selection execution background color --- client/app/components/QueryEditor.css | 9 ++------- client/app/components/QueryEditor.jsx | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/client/app/components/QueryEditor.css b/client/app/components/QueryEditor.css index 24caf893827..ca718e1fd32 100644 --- a/client/app/components/QueryEditor.css +++ b/client/app/components/QueryEditor.css @@ -1,8 +1,3 @@ -@keyframes fadeIt { - 0% { background-color: rgba(255, 121, 100, 0.557); } - 100% { background-color: transparent; } -} - -.ace_editor.highlightedText .ace_marker-layer .ace_selection { - animation: fadeIt 0.5s ease-out; +.editor__container[data-executing="true"] .ace_marker-layer .ace_selection { + background-color: rgb(255, 210, 181); } diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx index 71eb5c924eb..e4903e74198 100644 --- a/client/app/components/QueryEditor.jsx +++ b/client/app/components/QueryEditor.jsx @@ -223,9 +223,8 @@ class QueryEditor extends React.Component { return (
-
+
Date: Fri, 18 Jan 2019 12:27:34 -0800 Subject: [PATCH 6/6] make naming consistent --- client/app/components/QueryEditor.jsx | 14 +++++++------- client/app/pages/queries/query.html | 2 +- client/app/pages/queries/view.js | 10 +++++----- client/app/services/query.js | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx index e4903e74198..f9e2499f8f8 100644 --- a/client/app/components/QueryEditor.jsx +++ b/client/app/components/QueryEditor.jsx @@ -53,7 +53,7 @@ class QueryEditor extends React.Component { queryExecuting: PropTypes.bool.isRequired, saveQuery: PropTypes.func.isRequired, updateQuery: PropTypes.func.isRequired, - updateHighlightedQuery: PropTypes.func.isRequired, + updateSelectedQuery: PropTypes.func.isRequired, listenForResize: PropTypes.func.isRequired, listenForEditorCommand: PropTypes.func.isRequired, }; @@ -80,7 +80,7 @@ class QueryEditor extends React.Component { liveAutocompleteDisabled: false, // XXX temporary while interfacing with angular queryText: props.queryText, - highlightedQueryText: null, + selectedQueryText: null, }; const schemaCompleter = { @@ -190,10 +190,10 @@ class QueryEditor extends React.Component { updateSelectedQuery = (selection) => { const { editor } = this.refEditor.current; const doc = editor.getSession().doc; - const rawHighlightedQueryText = doc.getTextRange(selection.getRange()); - const highlightedQueryText = (rawHighlightedQueryText.length > 1) ? rawHighlightedQueryText : null; - this.setState({ highlightedQueryText }); - this.props.updateHighlightedQuery(highlightedQueryText); + const rawSelectedQueryText = doc.getTextRange(selection.getRange()); + const selectedQueryText = (rawSelectedQueryText.length > 1) ? rawSelectedQueryText : null; + this.setState({ selectedQueryText }); + this.props.updateSelectedQuery(selectedQueryText); } updateQuery = (queryText) => { @@ -308,7 +308,7 @@ class QueryEditor extends React.Component { data-test="ExecuteButton" > - { (this.state.highlightedQueryText == null) ? 'Execute' : 'Execute Selected' } + { (this.state.selectedQueryText == null) ? 'Execute' : 'Execute Selected' }
diff --git a/client/app/pages/queries/query.html b/client/app/pages/queries/query.html index b8bdf0310f6..d302beb0311 100644 --- a/client/app/pages/queries/query.html +++ b/client/app/pages/queries/query.html @@ -164,7 +164,7 @@

listen-for-editor-command="listenForEditorCommand" save-query="saveQuery" update-query="updateQuery" - update-highlighted-query="updateHighlightedQuery" + update-selected-query="updateSelectedQuery" add-new-parameter="addNewParameter" data-data-source="dataSource" data-data-sources="dataSources"> diff --git a/client/app/pages/queries/view.js b/client/app/pages/queries/view.js index fc2567daf92..76fc36b9914 100644 --- a/client/app/pages/queries/view.js +++ b/client/app/pages/queries/view.js @@ -26,7 +26,7 @@ function QueryViewCtrl( DataSource, Visualization, ) { - function getQueryResult(maxAge, highlightedQueryText) { + function getQueryResult(maxAge, selectedQueryText) { if (maxAge === undefined) { maxAge = $location.search().maxAge; } @@ -36,7 +36,7 @@ function QueryViewCtrl( } $scope.showLog = false; - $scope.queryResult = $scope.query.getQueryResult(maxAge, highlightedQueryText); + $scope.queryResult = $scope.query.getQueryResult(maxAge, selectedQueryText); } function getDataSourceId() { @@ -105,8 +105,8 @@ function QueryViewCtrl( getSchema(); } - $scope.updateHighlightedQuery = (highlightedQueryText) => { - $scope.highlightedQueryText = highlightedQueryText; + $scope.updateSelectedQuery = (selectedQueryText) => { + $scope.selectedQueryText = selectedQueryText; }; $scope.executeQuery = () => { @@ -118,7 +118,7 @@ function QueryViewCtrl( return; } - getQueryResult(0, $scope.highlightedQueryText); + getQueryResult(0, $scope.selectedQueryText); $scope.lockButton(true); $scope.cancelling = false; Events.record('execute', 'query', $scope.query.id); diff --git a/client/app/services/query.js b/client/app/services/query.js index 545f8410927..23151cc9107 100644 --- a/client/app/services/query.js +++ b/client/app/services/query.js @@ -426,12 +426,12 @@ function QueryResource( return this.getParameters().isRequired(); }; - Query.prototype.getQueryResult = function getQueryResult(maxAge, highlightedQueryText) { + Query.prototype.getQueryResult = function getQueryResult(maxAge, selectedQueryText) { if (!this.query) { return new QueryResultError("Can't execute empty query."); } - const queryText = highlightedQueryText || this.query; + const queryText = selectedQueryText || this.query; const parameters = this.getParameters(); const missingParams = parameters.getMissing();