You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2022/04/15 18:28:51 UTC

[superset] branch master updated: fix: sql lab ctrl t behaved differently from clicking (#19420)

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 56381f4ee8 fix: sql lab ctrl t behaved differently from clicking (#19420)
56381f4ee8 is described below

commit 56381f4ee8a7a1e36fcb33b2b3a5e16793ab0b8b
Author: Luis Casillas <ca...@gmail.com>
AuthorDate: Fri Apr 15 13:28:40 2022 -0500

    fix: sql lab ctrl t behaved differently from clicking (#19420)
    
    * initial approach
    
    To have consistent behaviour when creating a new tab with ctrl+t
    
    * consistent behaviour when creating tabs
    
    * fixed bug and added tests
    
    * updates to pass checks
---
 .../src/SqlLab/components/SqlEditor/index.jsx      | 10 ++---
 .../SqlLab/components/TabbedSqlEditors/index.jsx   | 15 +------
 .../src/SqlLab/utils/newQueryTabName.test.ts       | 46 ++++++++++++++++++++
 .../src/SqlLab/utils/newQueryTabName.ts            | 49 ++++++++++++++++++++++
 4 files changed, 102 insertions(+), 18 deletions(-)

diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
index 7899cbf719..14e8caa011 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
@@ -75,6 +75,7 @@ import ShareSqlLabQuery from '../ShareSqlLabQuery';
 import SqlEditorLeftBar from '../SqlEditorLeftBar';
 import AceEditorWrapper from '../AceEditorWrapper';
 import RunQueryActionButton from '../RunQueryActionButton';
+import { newQueryTabName } from '../../utils/newQueryTabName';
 
 const LIMIT_DROPDOWN = [10, 100, 1000, 10000, 100000];
 const SQL_EDITOR_PADDING = 10;
@@ -333,10 +334,10 @@ class SqlEditor extends React.PureComponent {
         key: userOS === 'Windows' ? 'ctrl+q' : 'ctrl+t',
         descr: t('New tab'),
         func: () => {
+          const title = newQueryTabName(this.props.queryEditors || []);
           this.props.addQueryEditor({
             ...this.props.queryEditor,
-            title: t('Untitled query'),
-            sql: '',
+            title,
           });
         },
       },
@@ -804,13 +805,12 @@ class SqlEditor extends React.PureComponent {
 SqlEditor.defaultProps = defaultProps;
 SqlEditor.propTypes = propTypes;
 
-function mapStateToProps(state, props) {
-  const { sqlLab } = state;
+function mapStateToProps({ sqlLab }, props) {
   const queryEditor = sqlLab.queryEditors.find(
     editor => editor.id === props.queryEditorId,
   );
 
-  return { sqlLab, ...props, queryEditor };
+  return { sqlLab, ...props, queryEditor, queryEditors: sqlLab.queryEditors };
 }
 
 function mapDispatchToProps(dispatch) {
diff --git a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx
index 8c20a493b0..494ef9cba0 100644
--- a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx
+++ b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx
@@ -31,6 +31,7 @@ import { Tooltip } from 'src/components/Tooltip';
 import { detectOS } from 'src/utils/common';
 import * as Actions from 'src/SqlLab/actions/sqlLab';
 import { EmptyStateBig } from 'src/components/EmptyState';
+import { newQueryTabName } from '../../utils/newQueryTabName';
 import SqlEditor from '../SqlEditor';
 import TabStatusIcon from '../TabStatusIcon';
 
@@ -262,19 +263,7 @@ class TabbedSqlEditors extends React.PureComponent {
           '-- Note: Unless you save your query, these tabs will NOT persist if you clear your cookies or change browsers.\n\n',
         );
 
-    let newTitle = 'Untitled Query 1';
-
-    if (this.props.queryEditors.length > 0) {
-      const untitledQueryNumbers = this.props.queryEditors
-        .filter(x => x.title.match(/^Untitled Query (\d+)$/))
-        .map(x => x.title.replace('Untitled Query ', ''));
-      if (untitledQueryNumbers.length > 0) {
-        // When there are query tabs open, and at least one is called "Untitled Query #"
-        // Where # is a valid number
-        const largestNumber = Math.max.apply(null, untitledQueryNumbers);
-        newTitle = t('Untitled Query %s', largestNumber + 1);
-      }
-    }
+    const newTitle = newQueryTabName(this.props.queryEditors || []);
 
     const qe = {
       title: newTitle,
diff --git a/superset-frontend/src/SqlLab/utils/newQueryTabName.test.ts b/superset-frontend/src/SqlLab/utils/newQueryTabName.test.ts
new file mode 100644
index 0000000000..d0d98c3cd5
--- /dev/null
+++ b/superset-frontend/src/SqlLab/utils/newQueryTabName.test.ts
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { newQueryTabName } from './newQueryTabName';
+
+const emptyEditor = {
+  title: '',
+  schema: '',
+  autorun: false,
+  sql: '',
+  remoteId: null,
+};
+
+describe('newQueryTabName', () => {
+  it("should return default title if queryEditor's length is 0", () => {
+    const defaultTitle = 'default title';
+    const title = newQueryTabName([], defaultTitle);
+    expect(title).toEqual(defaultTitle);
+  });
+  it('should return next available number if there are unsaved editors', () => {
+    const untitledQueryText = 'Untitled Query';
+    const unsavedEditors = [
+      { ...emptyEditor, title: `${untitledQueryText} 1` },
+      { ...emptyEditor, title: `${untitledQueryText} 2` },
+    ];
+
+    const nextTitle = newQueryTabName(unsavedEditors);
+    expect(nextTitle).toEqual(`${untitledQueryText} 3`);
+  });
+});
diff --git a/superset-frontend/src/SqlLab/utils/newQueryTabName.ts b/superset-frontend/src/SqlLab/utils/newQueryTabName.ts
new file mode 100644
index 0000000000..a719a74af5
--- /dev/null
+++ b/superset-frontend/src/SqlLab/utils/newQueryTabName.ts
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { t } from '@superset-ui/core';
+import { QueryEditor } from '../types';
+
+const untitledQueryRegex = /^Untitled Query (\d+)$/; // Literal notation isn't recompiled
+const untitledQuery = 'Untitled Query ';
+
+export const newQueryTabName = (
+  queryEditors: QueryEditor[],
+  initialTitle = `${untitledQuery}1`,
+): string => {
+  const resultTitle = t(initialTitle);
+
+  if (queryEditors.length > 0) {
+    const mappedUntitled = queryEditors.filter(qe =>
+      qe.title.match(untitledQueryRegex),
+    );
+    const untitledQueryNumbers = mappedUntitled.map(
+      qe => +qe.title.replace(untitledQuery, ''),
+    );
+    if (untitledQueryNumbers.length > 0) {
+      // When there are query tabs open, and at least one is called "Untitled Query #"
+      // Where # is a valid number
+      const largestNumber: number = Math.max(...untitledQueryNumbers);
+      return t(`${untitledQuery}%s`, largestNumber + 1);
+    }
+    return resultTitle;
+  }
+
+  return resultTitle;
+};