Browse Source

[frontend] Add shortcut key for toggling side panels (#2827)

* [frontend] Add shortcut key for toggling side panels

* [frontend] Update import path in unit test

* [frontend] refactor variable name in test

Co-authored-by: Björn Alm <balm@cloudera.com>
Bjorn Alm 3 years ago
parent
commit
4c9ff15758

+ 8 - 0
desktop/core/src/desktop/js/hue.js

@@ -61,6 +61,7 @@ import 'components/sidebar/HueSidebarWebComponent';
 import 'components/assist/AssistPanelWebComponent';
 
 import 'ko/components/assist/assistViewModel';
+import { BOTH_ASSIST_TOGGLE_EVENT } from 'ko/components/assist/events';
 import OnePageViewModel from 'onePageViewModel';
 import SidePanelViewModel from 'sidePanelViewModel';
 import TopNavViewModel from 'topNavViewModel';
@@ -175,3 +176,10 @@ $(document).ready(async () => {
 
   $('.page-content').jHueScrollUp();
 });
+
+// Framework independent global keyboard shortcuts
+document.addEventListener('keydown', e => {
+  if (e.key === '.' && (e.metaKey || e.ctrlKey)) {
+    huePubSub.publish(BOTH_ASSIST_TOGGLE_EVENT);
+  }
+});

+ 1 - 0
desktop/core/src/desktop/js/ko/components/assist/events.js

@@ -16,6 +16,7 @@
 
 export const SHOW_LEFT_ASSIST_EVENT = 'left.assist.show';
 export const SHOW_RIGHT_ASSIST_EVENT = 'right.assist.show';
+export const BOTH_ASSIST_TOGGLE_EVENT = 'both.assists.toggle';
 
 export const ASSIST_IS_DB_PANEL_READY_EVENT = 'assist.is.db.panel.ready';
 export const ASSIST_DB_PANEL_IS_READY_EVENT = 'assist.db.panel.is.ready';

+ 15 - 1
desktop/core/src/desktop/js/sidePanelViewModel.js

@@ -20,7 +20,11 @@ import * as ko from 'knockout';
 import hueAnalytics from 'utils/hueAnalytics';
 import huePubSub from 'utils/huePubSub';
 import { ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT } from 'apps/editor/events';
-import { SHOW_LEFT_ASSIST_EVENT, SHOW_RIGHT_ASSIST_EVENT } from 'ko/components/assist/events';
+import {
+  SHOW_LEFT_ASSIST_EVENT,
+  SHOW_RIGHT_ASSIST_EVENT,
+  BOTH_ASSIST_TOGGLE_EVENT
+} from 'ko/components/assist/events';
 import { getFromLocalStorage, setInLocalStorage } from 'utils/storageUtils';
 import defer from 'utils/timing/defer';
 
@@ -133,6 +137,16 @@ class SidePanelViewModel {
       });
     };
 
+    huePubSub.subscribe(BOTH_ASSIST_TOGGLE_EVENT, () => {
+      const hideBoth = self.rightAssistVisible() || self.leftAssistVisible();
+      if (hideBoth) {
+        hideAssists(true, true);
+      } else {
+        self.leftAssistVisible(true);
+        self.rightAssistVisible(true);
+      }
+    });
+
     huePubSub.subscribe('both.assists.hide', preventStorage => {
       hideAssists(true, true, preventStorage);
     });

+ 88 - 0
desktop/core/src/desktop/js/sidePanelViewModel.test.js

@@ -0,0 +1,88 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. 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 SidePanelViewModel from './sidePanelViewModel';
+import huePubSub from 'utils/huePubSub';
+import { BOTH_ASSIST_TOGGLE_EVENT } from 'ko/components/assist/events';
+import hueAnalytics from 'utils/hueAnalytics';
+import * as storageUtils from 'utils/storageUtils';
+
+describe('SidePanelViewModel', () => {
+  beforeAll(() => {
+    jest.spyOn(hueAnalytics, 'convert').mockImplementation();
+  });
+
+  afterEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('Should hide the assistspanels on BOTH_ASSIST_TOGGLE_EVENT when visible', () => {
+    jest.spyOn(storageUtils, 'getFromLocalStorage').mockImplementation(() => true);
+    jest.spyOn(storageUtils, 'setInLocalStorage').mockImplementation(() => {});
+    const sidePanelViewModel = new SidePanelViewModel();
+    expect(sidePanelViewModel.rightAssistVisible()).toBeTruthy();
+    expect(sidePanelViewModel.leftAssistVisible()).toBeTruthy();
+    expect(storageUtils.setInLocalStorage).not.toHaveBeenCalledWith(
+      'assist.left_assist_panel_visible',
+      false
+    );
+    expect(storageUtils.setInLocalStorage).not.toHaveBeenCalledWith(
+      'assist.right_assist_panel_visible',
+      false
+    );
+
+    huePubSub.publish(BOTH_ASSIST_TOGGLE_EVENT);
+    expect(sidePanelViewModel.rightAssistVisible()).toBeFalsy();
+    expect(sidePanelViewModel.leftAssistVisible()).toBeFalsy();
+    expect(storageUtils.setInLocalStorage).toHaveBeenCalledWith(
+      'assist.left_assist_panel_visible',
+      false
+    );
+    expect(storageUtils.setInLocalStorage).toHaveBeenCalledWith(
+      'assist.right_assist_panel_visible',
+      false
+    );
+  });
+
+  it('Should show the assistspanels on BOTH_ASSIST_TOGGLE_EVENT when hidden', () => {
+    jest.spyOn(storageUtils, 'getFromLocalStorage').mockImplementation(() => false);
+    jest.spyOn(storageUtils, 'setInLocalStorage').mockImplementation(() => {});
+    const sidePanelViewModel = new SidePanelViewModel();
+
+    expect(sidePanelViewModel.rightAssistVisible()).toBeFalsy();
+    expect(sidePanelViewModel.leftAssistVisible()).toBeFalsy();
+    expect(storageUtils.setInLocalStorage).not.toHaveBeenCalledWith(
+      'assist.left_assist_panel_visible',
+      true
+    );
+    expect(storageUtils.setInLocalStorage).not.toHaveBeenCalledWith(
+      'assist.right_assist_panel_visible',
+      true
+    );
+
+    huePubSub.publish(BOTH_ASSIST_TOGGLE_EVENT);
+    expect(sidePanelViewModel.rightAssistVisible()).toBeTruthy();
+    expect(sidePanelViewModel.leftAssistVisible()).toBeTruthy();
+    expect(storageUtils.setInLocalStorage).toHaveBeenCalledWith(
+      'assist.left_assist_panel_visible',
+      true
+    );
+    expect(storageUtils.setInLocalStorage).toHaveBeenCalledWith(
+      'assist.right_assist_panel_visible',
+      true
+    );
+  });
+});

+ 4 - 1
desktop/core/src/desktop/templates/common_notebook_ko_components.mako

@@ -882,7 +882,10 @@ else:
         },{
           id: 'settings',
           label: '${ _('Settings')}',
-          shortcuts: [{ shortcut: 'Ctrl - ,', macShortcut: 'Command - ,', description: '${ _('Show the settings menu where you can control autocomplete behaviour, syntax checker, dark theme and various editor settings.')}' }]
+          shortcuts: [
+            { shortcut: 'Ctrl-,', macShortcut: 'Command-,', description: '${ _('Show the settings menu where you can control autocomplete behaviour, syntax checker, dark theme and various editor settings.')}'},
+            { shortcut: 'Ctrl-.', macShortcut: 'Command-.', description: '${ _('Show or hide the assist panels.')}' }
+            ]
         }];
 
         self.query = ko.observable('');