Эх сурвалжийг харах

HUE-2962 [editor] Extract ko templates and components for configuration into separate mako

Johan Ahlen 9 жил өмнө
parent
commit
395c7898a0

+ 438 - 0
desktop/core/src/desktop/templates/config_ko_components.mako

@@ -0,0 +1,438 @@
+## 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.
+
+<%!
+from desktop import conf
+from desktop.lib.i18n import smart_unicode
+from django.utils.translation import ugettext as _
+from desktop.views import _ko
+%>
+
+<%def name="config()">
+
+  <style>
+    .config-property {
+      display: inline-block;
+      vertical-align: top;
+      padding-top:10px;
+      margin-bottom: 20px;
+      position: relative;
+    }
+
+    .config-property-remove {
+      position: absolute;
+      top: -8px;
+      z-index: 1000;
+      right: 0;
+    }
+
+    .property-help {
+      display: inline-block;
+      width: 10px;
+      height: 14px;
+      margin-left: 7px;
+      font-size: 14px;
+      color: #888;
+    }
+  </style>
+
+  <script type="text/html" id="property">
+    <div data-bind="visibleOnHover: { selector: '.hover-actions' }, css: { 'config-property' : typeof inline === 'undefined' || inline, 'control-group' : typeof inline !== 'undefined' && ! inline }">
+      <label class="control-label" data-bind="style: { 'width' : typeof inline === 'undefined' || inline ? '120px' : '' }">
+        <!-- ko text: label --><!-- /ko --><!-- ko if: typeof helpText !== 'undefined' --><div class="property-help" data-bind="tooltip: { title: helpText(), placement: 'bottom' }"><i class="fa fa-question-circle-o"></i></div><!-- /ko -->
+      </label>
+      <div class="controls" style="margin-right:10px;" data-bind="style: { 'margin-left' : typeof inline === 'undefined' || inline ? '140px' : '' }">
+        <!-- ko template: { name: 'property-' + type } --><!-- /ko -->
+      </div>
+      <!-- ko if: typeof remove !== "undefined" -->
+      <div class="hover-actions config-property-remove">
+        <a class="inactive-action" href="javascript:void(0)" data-bind="click: remove" title="${ _('Remove') }">
+          <i class="fa fa-times"></i>
+        </a>
+      </div>
+      <!-- /ko -->
+    </div>
+  </script>
+
+  <script type="text/html" id="property-jvm">
+    <div data-bind="component: { name: 'jvm-memory-input', params: { value: value } }"></div>
+  </script>
+
+  <script type="text/html" id="property-number">
+    <input type="text" class="input-small" data-bind="numericTextInput: { value: value, precision: 1, allowEmpty: true }, valueUpdate:'afterkeydown', attr: { 'title': typeof title === 'undefined' ? '' : title }"/>
+  </script>
+
+  <script type="text/html" id="property-string">
+    <input class="input-small" type="text" data-bind="textInput: value, valueUpdate:'afterkeydown'" />
+  </script>
+
+  <script type="text/html" id="property-csv">
+    <div data-bind="component: { name: 'csv-list-input', params: { value: value, placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
+  </script>
+
+  <script type="text/html" id="property-settings">
+    <div data-bind="component: { name: 'key-value-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
+  </script>
+
+  <script type="text/html" id="property-hdfs-files">
+    <div data-bind="component: { name: 'hdfs-file-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
+  </script>
+
+  <script type="text/html" id="property-csv-hdfs-files">
+    <div data-bind="component: { name: 'csv-list-input', params: { value: value, inputTemplate: 'property-csv-hdfs-file-input', placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
+  </script>
+
+  <script type="text/html" id="property-csv-hdfs-file-input">
+    <input type="text" class="filechooser-input" data-bind="value: value, valueUpdate:'afterkeydown', filechooser: { value: value, isAddon: true }" placeholder="${ _('Path to the file, e.g. hdfs://localhost:8020/user/hue/file.hue') }"/>
+  </script>
+
+  <script type="text/html" id="property-functions">
+    <div data-bind="component: { name: 'function-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
+  </script>
+
+  <script type="text/html" id="jvm-memory-input-template">
+    <input type="text" class="input-small" data-bind="numericTextInput: { value: value, precision: 0, allowEmpty: true }" /> <select class="input-mini" data-bind="options: units, value: selectedUnit" />
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function (factory) {
+      if(typeof require === "function") {
+        require(['knockout'], factory);
+      } else {
+        factory(ko);
+      }
+    }(function (ko) {
+      (function () {
+        var JVM_MEM_PATTERN = /([0-9]+)([MG])$/;
+        var UNITS = {'MB': 'M', 'GB': 'G'};
+
+        function JvmMemoryInputViewModel(params) {
+          this.valueObservable = params.value;
+          this.units = Object.keys(UNITS);
+          this.selectedUnit = ko.observable();
+          this.value = ko.observable('');
+
+          var match = JVM_MEM_PATTERN.exec(this.valueObservable());
+          if (match && match.length === 3) {
+            this.value(match[1]);
+            this.selectedUnit(match[2] === 'M' ? 'MB' : 'GB');
+          }
+
+          this.value.subscribe(this.updateValueObservable, this);
+          this.selectedUnit.subscribe(this.updateValueObservable, this);
+        }
+
+        JvmMemoryInputViewModel.prototype.updateValueObservable = function () {
+          if (isNaN(this.value()) || this.value() === '') {
+            this.valueObservable(undefined);
+          } else {
+            this.valueObservable(this.value() + UNITS[this.selectedUnit()]);
+          }
+        };
+
+        ko.components.register('jvm-memory-input', {
+          viewModel: JvmMemoryInputViewModel,
+          template: { element: 'jvm-memory-input-template' }
+        });
+      }());
+    }));
+  </script>
+
+  <script type="text/html" id="key-value-list-input-template">
+    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
+      <li>
+        <div class="input-append" style="margin-bottom: 4px">
+          <input type="text" style="width: 130px" placeholder="${ _('Key') }" data-bind="textInput: key, valueUpdate: 'afterkeydown'"/>
+          <input type="text" style="width: 130px" placeholder="${ _('Value') }" data-bind="textInput: value, valueUpdate: 'afterkeydown'"/>
+          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
+          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
+        </div>
+      </li>
+    </ul>
+    <div style="min-width: 280px; margin-top: 5px;">
+      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
+        <i class="fa fa-plus"></i>
+      </a>
+    </div>
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function (factory) {
+      if(typeof require === "function") {
+        require(['knockout'], factory);
+      } else {
+        factory(ko);
+      }
+    }(function (ko) {
+      (function () {
+
+        function KeyValueListInputViewModel(params) {
+          var self = this;
+          self.values = params.values;
+          params.visibleObservable.subscribe(function (newValue) {
+            if (!newValue) {
+              self.values($.grep(self.values(), function (value) {
+                return value.key() && value.value();
+              }))
+            }
+          });
+        }
+
+        KeyValueListInputViewModel.prototype.addValue = function () {
+          var self = this;
+          var newValue = {
+            key: ko.observable(''),
+            value: ko.observable('')
+          };
+          self.values.push(newValue);
+        };
+
+        KeyValueListInputViewModel.prototype.removeValue = function (valueToRemove) {
+          var self = this;
+          self.values.remove(valueToRemove);
+        };
+
+        ko.components.register('key-value-list-input', {
+          viewModel: KeyValueListInputViewModel,
+          template: { element: 'key-value-list-input-template' }
+        });
+      }());
+    }));
+  </script>
+
+  <script type="text/html" id="function-list-input-template">
+    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
+      <li>
+        <div class="input-append" style="margin-bottom: 4px">
+          <input type="text" style="width: 110px" placeholder="${ _('Name, e.g. foo') }" data-bind="textInput: name, valueUpdate: 'afterkeydown'"/>
+          <input type="text" style="width: 150px" placeholder="${ _('Class, e.g. org.hue.Bar') }" data-bind="textInput: class_name, valueUpdate: 'afterkeydown'"/>
+          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
+          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
+        </div>
+      </li>
+    </ul>
+    <div style="min-width: 280px; margin-top: 5px;">
+      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
+        <i class="fa fa-plus"></i>
+      </a>
+    </div>
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function (factory) {
+      if(typeof require === "function") {
+        require(['knockout'], factory);
+      } else {
+        factory(ko);
+      }
+    }(function (ko) {
+      (function () {
+
+        function FunctionListInputViewModel(params) {
+          var self = this;
+          self.values = params.values;
+          params.visibleObservable.subscribe(function (newValue) {
+            if (!newValue) {
+              self.values($.grep(self.values(), function (value) {
+                return value.name() && value.class_name();
+              }))
+            }
+          });
+        }
+
+        FunctionListInputViewModel.prototype.addValue = function () {
+          var self = this;
+          var newValue = {
+            name: ko.observable(''),
+            class_name: ko.observable('')
+          };
+          self.values.push(newValue);
+        };
+
+        FunctionListInputViewModel.prototype.removeValue = function (valueToRemove) {
+          var self = this;
+          self.values.remove(valueToRemove);
+        };
+
+        ko.components.register('function-list-input', {
+          viewModel: FunctionListInputViewModel,
+          template: { element: 'function-list-input-template' }
+        });
+      }());
+    }));
+  </script>
+
+  <script type="text/html" id="hdfs-file-list-input-template">
+    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
+      <li>
+        <div class="input-append" style="margin-bottom: 4px">
+          <input type="text" class="filechooser-input" data-bind="value: path, valueUpdate:'afterkeydown', filechooser: { value: path, isAddon: true }" placeholder="${ _('Path to the file, e.g. hdfs://localhost:8020/user/hue/file.hue') }"/>
+          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
+          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
+        </div>
+      </li>
+    </ul>
+    <div style="min-width: 280px; margin-top: 5px;">
+      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
+        <i class="fa fa-plus"></i>
+      </a>
+    </div>
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function (factory) {
+      if(typeof require === "function") {
+        require(['knockout'], factory);
+      } else {
+        factory(ko);
+      }
+    }(function (ko) {
+      (function () {
+
+        var identifyType = function (path) {
+          switch (path.substr(path.lastIndexOf('.') + 1).toLowerCase()) {
+            case 'jar':
+              return 'jar';
+            case 'zip':
+            case 'tar':
+            case 'rar':
+            case 'bz2':
+            case 'gz':
+            case 'tgz':
+              return 'archive';
+          }
+          return 'file';
+        };
+
+        function HdfsFileListInputViewModel(params) {
+          var self = this;
+          self.values = params.values;
+          $.each(self.values(), function (idx, value) {
+            value.path.subscribe(function (newPath) {
+              value.type(identifyType(newPath));
+            });
+          });
+          params.visibleObservable.subscribe(function (newValue) {
+            if (!newValue) {
+              self.values($.grep(self.values(), function (value) {
+                return value.path();
+              }))
+            }
+          });
+        }
+
+        HdfsFileListInputViewModel.prototype.addValue = function () {
+          var self = this;
+          var newValue = {
+            path: ko.observable(''),
+            type: ko.observable('')
+          };
+          newValue.path.subscribe(function (newPath) {
+            newValue.type(identifyType(newPath));
+          });
+          self.values.push(newValue);
+        };
+
+        HdfsFileListInputViewModel.prototype.removeValue = function (valueToRemove) {
+          var self = this;
+          self.values.remove(valueToRemove);
+        };
+
+        ko.components.register('hdfs-file-list-input', {
+          viewModel: HdfsFileListInputViewModel,
+          template: { element: 'hdfs-file-list-input-template' }
+        });
+      }());
+    }));
+  </script>
+
+  <script type="text/html" id="csv-list-input-template">
+    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
+      <li style="margin-bottom: 4px">
+        <div class="input-append">
+          <!-- ko ifnot: $parent.inputTemplate -->
+          <input type="text" data-bind="textInput: value, valueUpdate: 'afterkeydown', attr: { placeholder: $parent.placeholder }"/>
+          <!-- /ko -->
+          <!-- ko template: { if: $parent.inputTemplate, name: $parent.inputTemplate } --><!-- /ko -->
+          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
+          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
+        </div>
+      </li>
+    </ul>
+    <div style="min-width: 280px; margin-top: 5px;">
+      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
+        <i class="fa fa-plus"></i>
+      </a>
+    </div>
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function (factory) {
+      if(typeof require === "function") {
+        require(['knockout'], factory);
+      } else {
+        factory(ko);
+      }
+    }(function (ko) {
+      (function () {
+        function CsvListInputViewModel(params) {
+          this.valueObservable = params.value;
+          this.isArray = $.isArray(this.valueObservable());
+          this.placeholder = params.placeholder || '';
+          this.inputTemplate = params.inputTemplate || null;
+
+          var initialValues;
+          if (this.isArray) {
+            initialValues = ko.mapping.toJS(this.valueObservable());
+          } else {
+            initialValues = this.valueObservable() != null ? this.valueObservable().split(",") : [];
+          }
+          for (var i = 0; i < initialValues.length; i++) {
+            initialValues[i] = {value: ko.observable(initialValues[i].trim())};
+            initialValues[i].value.subscribe(this.updateValueObservable, this);
+          }
+          this.values = ko.observableArray(initialValues);
+          this.values.subscribe(this.updateValueObservable, this);
+        }
+
+        CsvListInputViewModel.prototype.addValue = function () {
+          var newValue = {value: ko.observable('')};
+          newValue.value.subscribe(this.updateValueObservable, this);
+          this.values.push(newValue);
+        };
+
+        CsvListInputViewModel.prototype.removeValue = function (valueToRemove) {
+          this.values.remove(valueToRemove);
+        };
+
+        CsvListInputViewModel.prototype.updateValueObservable = function () {
+          var cleanValues = $.map(this.values(), function (item) {
+            return item.value();
+          });
+          cleanValues = $.grep(cleanValues, function (value) {
+            return value;
+          });
+          this.valueObservable(this.isArray ? cleanValues : cleanValues.join(','));
+        };
+
+        ko.components.register('csv-list-input', {
+          viewModel: CsvListInputViewModel,
+          template: { element: 'csv-list-input-template' }
+        });
+      }());
+    }));
+  </script>
+</%def>

+ 0 - 24
desktop/libs/notebook/src/notebook/static/notebook/css/notebook.css

@@ -751,30 +751,6 @@ table.airy tr td {
   min-width: 350px;
   min-width: 350px;
 }
 }
 
 
-.spark-property {
-  display: inline-block;
-  vertical-align: top;
-  padding-top:10px;
-  margin-bottom: 20px;
-  position: relative;
-}
-
-.spark-property-remove {
-  position: absolute;
-  top: -8px;
-  z-index: 1000;
-  right: 0;
-}
-
-.property-help {
-  display: inline-block;
-  width: 10px;
-  height: 14px;
-  margin-left: 7px;
-  font-size: 14px;
-  color: #888;
-}
-
 .hover-dropdown {
 .hover-dropdown {
   display: inline-block;
   display: inline-block;
   position: relative;
   position: relative;

+ 4 - 7
desktop/libs/notebook/src/notebook/templates/editor.mako

@@ -19,10 +19,11 @@
   from django.utils.translation import ugettext as _
   from django.utils.translation import ugettext as _
 %>
 %>
 
 
-<%namespace name="koComponents" file="/ko_components.mako" />
+<%namespace name="configKoComponents" file="/config_ko_components.mako" />
 <%namespace name="tableStats" file="/table_stats.mako" />
 <%namespace name="tableStats" file="/table_stats.mako" />
 <%namespace name="assist" file="/assist.mako" />
 <%namespace name="assist" file="/assist.mako" />
 <%namespace name="editorComponents" file="editor_components.mako" />
 <%namespace name="editorComponents" file="editor_components.mako" />
+<%namespace name="notebookKoComponents" file="notebook_ko_components.mako" />
 
 
 ${ commonheader(_('Editor'), editor_type, user, "68px") | n,unicode }
 ${ commonheader(_('Editor'), editor_type, user, "68px") | n,unicode }
 
 
@@ -39,12 +40,8 @@ ${ editorComponents.commonHTML() }
 
 
 ${ tableStats.tableStats() }
 ${ tableStats.tableStats() }
 ${ assist.assistPanel() }
 ${ assist.assistPanel() }
-${ koComponents.csvListInput() }
-${ koComponents.keyValueListInput() }
-${ koComponents.hdfsFileListInput() }
-${ koComponents.functionListInput() }
-${ koComponents.jvmMemoryInput() }
-${ koComponents.downloadSnippetResults() }
+${ configKoComponents.config() }
+${ notebookKoComponents.downloadSnippetResults() }
 
 
 ${ editorComponents.commonJS() }
 ${ editorComponents.commonJS() }
 
 

+ 0 - 54
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -1235,60 +1235,6 @@ ${ hueIcons.symbols() }
   </div>
   </div>
 </script>
 </script>
 
 
-<script type="text/html" id="property">
-  <div data-bind="visibleOnHover: { selector: '.hover-actions' }, css: { 'spark-property' : typeof inline === 'undefined' || inline, 'control-group' : typeof inline !== 'undefined' && ! inline }">
-    <label class="control-label" data-bind="style: { 'width' : typeof inline === 'undefined' || inline ? '120px' : '' }">
-      <!-- ko text: label --><!-- /ko --><!-- ko if: typeof helpText !== 'undefined' --><div class="property-help" data-bind="tooltip: { title: helpText(), placement: 'bottom' }"><i class="fa fa-question-circle-o"></i></div><!-- /ko -->
-    </label>
-    <div class="controls" style="margin-right:10px;" data-bind="style: { 'margin-left' : typeof inline === 'undefined' || inline ? '140px' : '' }">
-      <!-- ko template: { name: 'property-' + type } --><!-- /ko -->
-    </div>
-    <!-- ko if: typeof remove !== "undefined" -->
-    <div class="hover-actions spark-property-remove">
-      <a class="inactive-action" href="javascript:void(0)" data-bind="click: remove" title="${ _('Remove') }">
-        <i class="fa fa-times"></i>
-      </a>
-    </div>
-    <!-- /ko -->
-  </div>
-</script>
-
-<script type="text/html" id="property-jvm">
-  <div data-bind="component: { name: 'jvm-memory-input', params: { value: value } }"></div>
-</script>
-
-<script type="text/html" id="property-number">
-  <input type="text" class="input-small" data-bind="numericTextInput: { value: value, precision: 1, allowEmpty: true }, valueUpdate:'afterkeydown', attr: { 'title': typeof title === 'undefined' ? '' : title }"/>
-</script>
-
-<script type="text/html" id="property-string">
-  <input class="input-small" type="text" data-bind="textInput: value, valueUpdate:'afterkeydown'" />
-</script>
-
-<script type="text/html" id="property-csv">
-  <div data-bind="component: { name: 'csv-list-input', params: { value: value, placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
-</script>
-
-<script type="text/html" id="property-settings">
-  <div data-bind="component: { name: 'key-value-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
-</script>
-
-<script type="text/html" id="property-hdfs-files">
-  <div data-bind="component: { name: 'hdfs-file-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
-</script>
-
-<script type="text/html" id="property-csv-hdfs-files">
-  <div data-bind="component: { name: 'csv-list-input', params: { value: value, inputTemplate: 'property-csv-hdfs-file-input', placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
-</script>
-
-<script type="text/html" id="property-csv-hdfs-file-input">
-  <input type="text" class="filechooser-input" data-bind="value: value, valueUpdate:'afterkeydown', filechooser: { value: value, isAddon: true }" placeholder="${ _('Path to the file, e.g. hdfs://localhost:8020/user/hue/file.hue') }"/>
-</script>
-
-<script type="text/html" id="property-functions">
-  <div data-bind="component: { name: 'function-list-input', params: { values: value, visibleObservable: visibleObservable } }"></div>
-</script>
-
 <script type="text/html" id="snippet-settings">
 <script type="text/html" id="snippet-settings">
   <div class="snippet-settings" data-bind="slideVisible: settingsVisible" style="position: relative; z-index: 100;">
   <div class="snippet-settings" data-bind="slideVisible: settingsVisible" style="position: relative; z-index: 100;">
     <div class="snippet-settings-header">
     <div class="snippet-settings-header">

+ 5 - 8
desktop/libs/notebook/src/notebook/templates/notebook.mako

@@ -21,8 +21,9 @@
 
 
 <%namespace name="tableStats" file="/table_stats.mako" />
 <%namespace name="tableStats" file="/table_stats.mako" />
 <%namespace name="assist" file="/assist.mako" />
 <%namespace name="assist" file="/assist.mako" />
-<%namespace name="koComponents" file="/ko_components.mako" />
+<%namespace name="configKoComponents" file="/config_ko_components.mako" />
 <%namespace name="editorComponents" file="editor_components.mako" />
 <%namespace name="editorComponents" file="editor_components.mako" />
+<%namespace name="notebookKoComponents" file="notebook_ko_components.mako" />
 
 
 ${ commonheader(_('Notebook'), app_name, user, "68px") | n,unicode }
 ${ commonheader(_('Notebook'), app_name, user, "68px") | n,unicode }
 
 
@@ -49,13 +50,9 @@ ${ editorComponents.topBar(editor_type) }
 
 
 ${ tableStats.tableStats() }
 ${ tableStats.tableStats() }
 ${ assist.assistPanel() }
 ${ assist.assistPanel() }
-${ koComponents.csvListInput() }
-${ koComponents.keyValueListInput() }
-${ koComponents.hdfsFileListInput() }
-${ koComponents.functionListInput() }
-${ koComponents.jvmMemoryInput() }
-${ koComponents.addSnippetMenu() }
-${ koComponents.downloadSnippetResults() }
+${ configKoComponents.config() }
+${ notebookKoComponents.addSnippetMenu() }
+${ notebookKoComponents.downloadSnippetResults() }
 
 
 ${ editorComponents.commonJS() }
 ${ editorComponents.commonJS() }
 
 

+ 0 - 343
desktop/core/src/desktop/templates/ko_components.mako → desktop/libs/notebook/src/notebook/templates/notebook_ko_components.mako

@@ -21,349 +21,6 @@ from django.utils.translation import ugettext as _
 from desktop.views import _ko
 from desktop.views import _ko
 %>
 %>
 
 
-<%def name="jvmMemoryInput()">
-  <script type="text/html" id="jvm-memory-input-template">
-    <input type="text" class="input-small" data-bind="numericTextInput: { value: value, precision: 0, allowEmpty: true }" /> <select class="input-mini" data-bind="options: units, value: selectedUnit" />
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function (factory) {
-      if(typeof require === "function") {
-        require(['knockout'], factory);
-      } else {
-        factory(ko);
-      }
-    }(function (ko) {
-      (function () {
-        var JVM_MEM_PATTERN = /([0-9]+)([MG])$/;
-        var UNITS = {'MB': 'M', 'GB': 'G'};
-
-        function JvmMemoryInputViewModel(params) {
-          this.valueObservable = params.value;
-          this.units = Object.keys(UNITS);
-          this.selectedUnit = ko.observable();
-          this.value = ko.observable('');
-
-          var match = JVM_MEM_PATTERN.exec(this.valueObservable());
-          if (match && match.length === 3) {
-            this.value(match[1]);
-            this.selectedUnit(match[2] === 'M' ? 'MB' : 'GB');
-          }
-
-          this.value.subscribe(this.updateValueObservable, this);
-          this.selectedUnit.subscribe(this.updateValueObservable, this);
-        }
-
-        JvmMemoryInputViewModel.prototype.updateValueObservable = function () {
-          if (isNaN(this.value()) || this.value() === '') {
-            this.valueObservable(undefined);
-          } else {
-            this.valueObservable(this.value() + UNITS[this.selectedUnit()]);
-          }
-        };
-
-        ko.components.register('jvm-memory-input', {
-          viewModel: JvmMemoryInputViewModel,
-          template: { element: 'jvm-memory-input-template' }
-        });
-      }());
-    }));
-  </script>
-</%def>
-
-<%def name="keyValueListInput()">
-  <script type="text/html" id="key-value-list-input-template">
-    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
-      <li>
-        <div class="input-append" style="margin-bottom: 4px">
-          <input type="text" style="width: 130px" placeholder="${ _('Key') }" data-bind="textInput: key, valueUpdate: 'afterkeydown'"/>
-          <input type="text" style="width: 130px" placeholder="${ _('Value') }" data-bind="textInput: value, valueUpdate: 'afterkeydown'"/>
-          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
-          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
-        </div>
-      </li>
-    </ul>
-    <div style="min-width: 280px; margin-top: 5px;">
-      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
-        <i class="fa fa-plus"></i>
-      </a>
-    </div>
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function (factory) {
-      if(typeof require === "function") {
-        require(['knockout'], factory);
-      } else {
-        factory(ko);
-      }
-    }(function (ko) {
-      (function () {
-
-        function KeyValueListInputViewModel(params) {
-          var self = this;
-          self.values = params.values;
-          params.visibleObservable.subscribe(function (newValue) {
-            if (!newValue) {
-              self.values($.grep(self.values(), function (value) {
-                return value.key() && value.value();
-              }))
-            }
-          });
-        }
-
-        KeyValueListInputViewModel.prototype.addValue = function () {
-          var self = this;
-          var newValue = {
-            key: ko.observable(''),
-            value: ko.observable('')
-          };
-          self.values.push(newValue);
-        };
-
-        KeyValueListInputViewModel.prototype.removeValue = function (valueToRemove) {
-          var self = this;
-          self.values.remove(valueToRemove);
-        };
-
-        ko.components.register('key-value-list-input', {
-          viewModel: KeyValueListInputViewModel,
-          template: { element: 'key-value-list-input-template' }
-        });
-      }());
-    }));
-  </script>
-</%def>
-
-<%def name="functionListInput()">
-  <script type="text/html" id="function-list-input-template">
-    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
-      <li>
-        <div class="input-append" style="margin-bottom: 4px">
-          <input type="text" style="width: 110px" placeholder="${ _('Name, e.g. foo') }" data-bind="textInput: name, valueUpdate: 'afterkeydown'"/>
-          <input type="text" style="width: 150px" placeholder="${ _('Class, e.g. org.hue.Bar') }" data-bind="textInput: class_name, valueUpdate: 'afterkeydown'"/>
-          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
-          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
-        </div>
-      </li>
-    </ul>
-    <div style="min-width: 280px; margin-top: 5px;">
-      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
-        <i class="fa fa-plus"></i>
-      </a>
-    </div>
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function (factory) {
-      if(typeof require === "function") {
-        require(['knockout'], factory);
-      } else {
-        factory(ko);
-      }
-    }(function (ko) {
-      (function () {
-
-        function FunctionListInputViewModel(params) {
-          var self = this;
-          self.values = params.values;
-          params.visibleObservable.subscribe(function (newValue) {
-            if (!newValue) {
-              self.values($.grep(self.values(), function (value) {
-                return value.name() && value.class_name();
-              }))
-            }
-          });
-        }
-
-        FunctionListInputViewModel.prototype.addValue = function () {
-          var self = this;
-          var newValue = {
-            name: ko.observable(''),
-            class_name: ko.observable('')
-          };
-          self.values.push(newValue);
-        };
-
-        FunctionListInputViewModel.prototype.removeValue = function (valueToRemove) {
-          var self = this;
-          self.values.remove(valueToRemove);
-        };
-
-        ko.components.register('function-list-input', {
-          viewModel: FunctionListInputViewModel,
-          template: { element: 'function-list-input-template' }
-        });
-      }());
-    }));
-  </script>
-</%def>
-
-<%def name="hdfsFileListInput()">
-  <script type="text/html" id="hdfs-file-list-input-template">
-    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
-      <li>
-        <div class="input-append" style="margin-bottom: 4px">
-          <input type="text" class="filechooser-input" data-bind="value: path, valueUpdate:'afterkeydown', filechooser: { value: path, isAddon: true }" placeholder="${ _('Path to the file, e.g. hdfs://localhost:8020/user/hue/file.hue') }"/>
-          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
-          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
-        </div>
-      </li>
-    </ul>
-    <div style="min-width: 280px; margin-top: 5px;">
-      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
-        <i class="fa fa-plus"></i>
-      </a>
-    </div>
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function (factory) {
-      if(typeof require === "function") {
-        require(['knockout'], factory);
-      } else {
-        factory(ko);
-      }
-    }(function (ko) {
-      (function () {
-
-        var identifyType = function (path) {
-          switch (path.substr(path.lastIndexOf('.') + 1).toLowerCase()) {
-            case 'jar':
-              return 'jar'
-            case 'zip':
-            case 'tar':
-            case 'rar':
-            case 'bz2':
-            case 'gz':
-            case 'tgz':
-              return 'archive';
-          }
-          return 'file';
-        }
-
-        function HdfsFileListInputViewModel(params) {
-          var self = this;
-          self.values = params.values;
-          $.each(self.values(), function (idx, value) {
-            value.path.subscribe(function (newPath) {
-              value.type(identifyType(newPath));
-            });
-          })
-          params.visibleObservable.subscribe(function (newValue) {
-            if (!newValue) {
-              self.values($.grep(self.values(), function (value) {
-                return value.path();
-              }))
-            }
-          });
-        }
-
-        HdfsFileListInputViewModel.prototype.addValue = function () {
-          var self = this;
-          var newValue = {
-            path: ko.observable(''),
-            type: ko.observable('')
-          };
-          newValue.path.subscribe(function (newPath) {
-            newValue.type(identifyType(newPath));
-          })
-          self.values.push(newValue);
-        };
-
-        HdfsFileListInputViewModel.prototype.removeValue = function (valueToRemove) {
-          var self = this;
-          self.values.remove(valueToRemove);
-        };
-
-        ko.components.register('hdfs-file-list-input', {
-          viewModel: HdfsFileListInputViewModel,
-          template: { element: 'hdfs-file-list-input-template' }
-        });
-      }());
-    }));
-  </script>
-</%def>
-
-<%def name="csvListInput()">
-  <script type="text/html" id="csv-list-input-template">
-    <ul data-bind="sortable: { data: values, options: { axis: 'y', containment: 'parent' }}, visible: values().length" class="unstyled">
-      <li style="margin-bottom: 4px">
-        <div class="input-append">
-          <!-- ko ifnot: $parent.inputTemplate -->
-          <input type="text" data-bind="textInput: value, valueUpdate: 'afterkeydown', attr: { placeholder: $parent.placeholder }"/>
-          <!-- /ko -->
-          <!-- ko template: { if: $parent.inputTemplate, name: $parent.inputTemplate } --><!-- /ko -->
-          <span class="add-on move-widget muted"><i class="fa fa-arrows"></i></span>
-          <a class="add-on muted" href="javascript: void(0);" data-bind="click: function(){ $parent.removeValue($data); }"><i class="fa fa-minus"></i></a>
-        </div>
-      </li>
-    </ul>
-    <div style="min-width: 280px; margin-top: 5px;">
-      <a class="inactive-action pointer" style="padding: 3px 10px 3px 3px;;" data-bind="click: addValue">
-        <i class="fa fa-plus"></i>
-      </a>
-    </div>
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function (factory) {
-      if(typeof require === "function") {
-        require(['knockout'], factory);
-      } else {
-        factory(ko);
-      }
-    }(function (ko) {
-      (function () {
-        function CsvListInputViewModel(params) {
-          this.valueObservable = params.value;
-          this.isArray = $.isArray(this.valueObservable());
-          this.placeholder = params.placeholder || '';
-          this.inputTemplate = params.inputTemplate || null;
-
-          var initialValues;
-          if (this.isArray) {
-            initialValues = ko.mapping.toJS(this.valueObservable());
-          } else {
-            initialValues = this.valueObservable() != null ? this.valueObservable().split(",") : [];
-          }
-          for (var i = 0; i < initialValues.length; i++) {
-            initialValues[i] = {value: ko.observable(initialValues[i].trim())};
-            initialValues[i].value.subscribe(this.updateValueObservable, this);
-          }
-          this.values = ko.observableArray(initialValues);
-          this.values.subscribe(this.updateValueObservable, this);
-        }
-
-        CsvListInputViewModel.prototype.addValue = function () {
-          var newValue = {value: ko.observable('')};
-          newValue.value.subscribe(this.updateValueObservable, this);
-          this.values.push(newValue);
-        };
-
-        CsvListInputViewModel.prototype.removeValue = function (valueToRemove) {
-          this.values.remove(valueToRemove);
-        };
-
-        CsvListInputViewModel.prototype.updateValueObservable = function () {
-          var cleanValues = $.map(this.values(), function (item) {
-            return item.value();
-          });
-          cleanValues = $.grep(cleanValues, function (value) {
-            return value;
-          });
-          this.valueObservable(this.isArray ? cleanValues : cleanValues.join(','));
-        };
-
-        ko.components.register('csv-list-input', {
-          viewModel: CsvListInputViewModel,
-          template: { element: 'csv-list-input-template' }
-        });
-      }());
-    }));
-  </script>
-</%def>
-
 <%def name="addSnippetMenu()">
 <%def name="addSnippetMenu()">
   <script type="text/html" id="add-snippet-menu-template">
   <script type="text/html" id="add-snippet-menu-template">
     <div class="add-snippet-button" style="position:relative; width:65px; text-align: center;">
     <div class="add-snippet-button" style="position:relative; width:65px; text-align: center;">