Просмотр исходного кода

HUE-9066 [frontend] Create a separate component for the gist modal

Johan Ahlen 6 лет назад
Родитель
Сommit
0189da2079

+ 4 - 3
desktop/core/src/desktop/js/apps/notebook/snippet.js

@@ -28,6 +28,7 @@ import hueUtils from 'utils/hueUtils';
 import Result from 'apps/notebook/result';
 import Session from 'apps/notebook/session';
 import sqlStatementsParser from 'parse/sqlStatementsParser';
+import { SHOW_EVENT as SHOW_GIST_MODAL_EVENT } from 'ko/components/ko.shareGistModal';
 
 const NOTEBOOK_MAPPING = {
   ignore: [
@@ -1916,7 +1917,7 @@ class Snippet {
         apiHelper
           .createGist({
             statement:
-              self.ace().getSelectedText() != ''
+              self.ace().getSelectedText() !== ''
                 ? self.ace().getSelectedText()
                 : self.statement_raw(),
             doc_type: self.type(),
@@ -1924,8 +1925,8 @@ class Snippet {
             description: ''
           })
           .done(data => {
-            if (data.status == 0) {
-              $(document).trigger('showGistModal', {
+            if (data.status === 0) {
+              huePubSub.publish(SHOW_GIST_MODAL_EVENT, {
                 link: data.link
               });
             } else {

+ 3 - 6
desktop/core/src/desktop/js/apps/notebook2/components/ko.snippetEditorActions.js

@@ -14,7 +14,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import $ from 'jquery';
 import * as ko from 'knockout';
 
 import 'ko/bindings/ko.publish';
@@ -22,7 +21,9 @@ import 'ko/bindings/ko.publish';
 import apiHelper from 'api/apiHelper';
 import componentUtils from 'ko/components/componentUtils';
 import hueAnalytics from 'utils/hueAnalytics';
+import huePubSub from 'utils/huePubSub';
 import I18n from 'utils/i18n';
+import { SHOW_EVENT as SHOW_GIST_MODAL_EVENT } from 'ko/components/ko.shareGistModal';
 import { STATUS } from 'apps/notebook2/snippet';
 
 const TEMPLATE = `
@@ -173,11 +174,7 @@ class SnippetEditorActions {
       description: ''
     });
 
-    new window.Clipboard('.gist-link-btn');
-
-    $(document).trigger('showGistModal', {
-      link: gistLink
-    });
+    huePubSub.publish(SHOW_GIST_MODAL_EVENT, { link: gistLink });
   }
 
   format() {

+ 1 - 1
desktop/core/src/desktop/js/ko/bindings/ko.clipboard.js

@@ -22,7 +22,7 @@ ko.bindingHandlers.clipboard = {
       console.warn('ko.clipboard.js depends on window.Clipboard');
       return;
     }
-    const options = valueAccessor();
+    const options = valueAccessor() || {};
 
     const clipboard = new window.Clipboard(element, {
       target: options.target,

+ 29 - 0
desktop/core/src/desktop/js/ko/components/__snapshots__/ko.shareGistModal.test.js.snap

@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ko.shareGistModal.js should render component 1`] = `
+"<html><head></head><body class=\\"modal-open\\"><div id=\\"shareGistModal\\" data-bind=\\"descendantsComplete: descendantsComplete, component: { name: 'share-gist-modal', params: params }\\" data-keyboard=\\"true\\" class=\\"modal hide fade in\\" tabindex=\\"-1\\" aria-hidden=\\"false\\">
+  <div class=\\"modal-header\\">
+    <button type=\\"button\\" class=\\"close\\" data-dismiss=\\"modal\\" aria-label=\\"Close\\"><span aria-hidden=\\"true\\">×</span></button>
+    <h2 class=\\"modal-title\\">Shareable link</h2>
+  </div>
+  <div class=\\"modal-body\\">
+    <div class=\\"row-fluid\\">
+      <div class=\\"span12\\">
+        <div class=\\"input-group\\">
+          <input id=\\"gistLink\\" class=\\"input-xxlarge\\" onfocus=\\"this.select()\\" data-bind=\\"value: link\\" type=\\"text\\" placeholder=\\"Link\\">
+        </div>
+        <div class=\\"input-prepend\\">
+          <a class=\\"btn gist-link-btn\\" data-clipboard-target=\\"#gistLink\\" data-bind=\\"clipboard\\" data-dismiss=\\"modal\\">Copy</a>
+          <button class=\\"add-on muted gist-link-btn\\" data-clipboard-target=\\"#gistLink\\" data-bind=\\"clipboard\\">
+            <i class=\\"fa fa-clipboard\\"></i>
+          </button>
+        </div>
+      </div>
+    </div>
+
+  </div>
+  <div class=\\"modal-footer\\">
+    <a class=\\"btn\\" data-dismiss=\\"modal\\">Close</a>
+  </div>
+</div><div class=\\"modal-backdrop fade in\\"></div></body></html>"
+`;

+ 77 - 0
desktop/core/src/desktop/js/ko/components/ko.shareGistModal.js

@@ -0,0 +1,77 @@
+// 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 $ from 'jquery';
+import * as ko from 'knockout';
+
+import componentUtils from './componentUtils';
+import huePubSub from 'utils/huePubSub';
+import I18n from 'utils/i18n';
+
+export const SHOW_EVENT = 'show.share.gist.modal';
+export const SHOWN_EVENT = 'share.gist.modal.shown';
+
+// prettier-ignore
+const TEMPLATE = `
+  <div class="modal-header">
+    <button type="button" class="close" data-dismiss="modal" aria-label="${ I18n('Close') }"><span aria-hidden="true">&times;</span></button>
+    <h2 class="modal-title">${ I18n('Shareable link') }</h2>
+  </div>
+  <div class="modal-body">
+    <div class="row-fluid">
+      <div class="span12">
+        <div class="input-group">
+          <input id="gistLink" class="input-xxlarge" onfocus="this.select()" data-bind="value: link" type="text" placeholder="${ I18n('Link') }"/>
+        </div>
+        <div class="input-prepend">
+          <a class="btn gist-link-btn" data-clipboard-target="#gistLink" data-bind="clipboard" data-dismiss="modal">${ I18n('Copy') }</a>
+          <button class="add-on muted gist-link-btn" data-clipboard-target="#gistLink" data-bind="clipboard" >
+            <i class="fa fa-clipboard"></i>
+          </button>
+        </div>
+      </div>
+    </div>
+
+  </div>
+  <div class="modal-footer">
+    <a class="btn" data-dismiss="modal">${ I18n('Close') }</a>
+  </div>
+`;
+
+componentUtils.registerComponent('share-gist-modal', undefined, TEMPLATE).then(() => {
+  huePubSub.subscribe(SHOW_EVENT, async params => {
+    let $shareGistModal = $('#shareGistModal');
+    if ($shareGistModal.length) {
+      ko.cleanNode($shareGistModal[0]);
+      $shareGistModal.remove();
+    }
+
+    $shareGistModal = $(
+      '<div id="shareGistModal" data-bind="descendantsComplete: descendantsComplete, component: { name: \'share-gist-modal\', params: params }" data-keyboard="true" class="modal hide fade" tabindex="-1"/>'
+    );
+    $('body').append($shareGistModal);
+
+    const data = {
+      params: params,
+      descendantsComplete: () => {
+        huePubSub.publish(SHOWN_EVENT);
+      }
+    };
+
+    ko.applyBindings(data, $shareGistModal[0]);
+    $shareGistModal.modal('show');
+  });
+});

+ 46 - 0
desktop/core/src/desktop/js/ko/components/ko.shareGistModal.test.js

@@ -0,0 +1,46 @@
+// 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 { SHOWN_EVENT, SHOW_EVENT } from './ko.shareGistModal';
+import huePubSub from 'utils/huePubSub';
+
+import 'ext/bootstrap.2.3.2.min';
+
+describe('ko.shareGistModal.js', () => {
+  it('should render component', async () => {
+    huePubSub.publish(SHOW_EVENT, {
+      link: 'http://some.url'
+    });
+
+    await new Promise(resolve => {
+      huePubSub.subscribeOnce(SHOWN_EVENT, resolve);
+    });
+
+    expect(document.documentElement.outerHTML).toMatchSnapshot();
+  });
+
+  it('should set the link as the input value', async () => {
+    huePubSub.publish(SHOW_EVENT, {
+      link: 'http://some.url'
+    });
+
+    await new Promise(resolve => {
+      huePubSub.subscribeOnce(SHOWN_EVENT, resolve);
+    });
+
+    expect(document.querySelector('#gistLink').value).toEqual('http://some.url');
+  });
+});

+ 1 - 1
desktop/core/src/desktop/js/ko/ko.all.js

@@ -24,7 +24,6 @@ import 'knockout.validation';
 import 'ext/ko.editable.custom';
 import 'ext/ko.selectize.custom';
 
-// import 'ko/bindings/charts/plotly/ko.plotly'; // The Plotly chart replacement
 import 'ko/bindings/charts/mapchart/ko.mapChart';
 import 'ko/bindings/charts/ko.barChart';
 import 'ko/bindings/charts/ko.leafletMapChart';
@@ -165,6 +164,7 @@ import 'ko/components/ko.sentryPrivileges';
 import 'ko/components/ko.sessionAuthModal';
 import 'ko/components/ko.sessionPanel';
 import 'ko/components/ko.shareDocModal';
+import 'ko/components/ko.shareGistModal';
 import 'ko/components/ko.sidebar';
 import 'ko/components/ko.sqlColumnsTable';
 

+ 0 - 30
desktop/core/src/desktop/templates/common_header_footer_components.mako

@@ -286,31 +286,6 @@ from metadata.conf import has_optimizer, OPTIMIZER
   </div>
 </div>
 
-<div id="gistModal" class="modal hide fade">
-  <div class="modal-header">
-    <button type="button" class="close" data-dismiss="modal" aria-label="${ _('Close') }"><span aria-hidden="true">&times;</span></button>
-    <h2 class="modal-title">${ _('Shareable link') }</h2>
-  </div>
-  <div class="modal-body">
-    <div class="row-fluid">
-      <div class="span12">
-        <div class="input-group">
-          <input class="input-xxlarge" onfocus="this.select()" name="gist-link" id="gist-link" type="text" placeholder="${ _('Link') }"/>
-        </div>
-        <div class="input-prepend">
-          <a class="btn gist-link-btn" data-clipboard-target="#gist-link" data-dismiss="modal">${_('Copy')}</a>
-          <button class="add-on muted gist-link-btn" data-clipboard-target="#gist-link">
-            <i class="fa fa-clipboard"></i>
-          </button>
-        </div>
-      </div>
-    </div>
-  </div>
-  <div class="modal-footer">
-    <a class="btn" data-dismiss="modal">${_('Close')}</a>
-  </div>
-</div>
-
 <div class="clipboard-content"></div>
 
 <script type="text/javascript">
@@ -591,11 +566,6 @@ from metadata.conf import has_optimizer, OPTIMIZER
     };
   }
 
-  $(document).on('showGistModal', (e, data) => {
-    $('#gistModal input[name="gist-link"]').val(data['link']);
-    $('#gistModal').modal('show');
-  });
-
   % if collect_usage:
     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
     (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),