Преглед на файлове

[spark] Use the HDFS file chooser for file-related session and snippet properties

With this change the HDFS file chooser will be used instead of text input for the properties that accept a list of files. To support this I've adjusted the csv-list-input KO component to accept an optional template to use for the input.
Johan Ahlen преди 10 години
родител
ревизия
8f6131a

+ 4 - 4
apps/spark/src/spark/models.py

@@ -286,16 +286,16 @@ class HS2Api(Api):
 
 class SparkApi(Api):
   PROPERTIES = [
-    {'name': 'jars', 'nice_name': _('Jars'), 'default': '', 'type': 'csv', 'is_yarn': False},
-    {'name': 'files', 'nice_name': _('Files'), 'default': '', 'type': 'csv', 'is_yarn': False},
-    {'name': 'pyFiles', 'nice_name': _('pyFiles'), 'default': '', 'type': 'csv', 'is_yarn': False},
+    {'name': 'jars', 'nice_name': _('Jars'), 'default': '', 'type': 'csv-hdfs-files', 'is_yarn': False},
+    {'name': 'files', 'nice_name': _('Files'), 'default': '', 'type': 'csv-hdfs-files', 'is_yarn': False},
+    {'name': 'pyFiles', 'nice_name': _('pyFiles'), 'default': '', 'type': 'csv-hdfs-files', 'is_yarn': False},
 
     {'name': 'driverMemory', 'nice_name': _('Driver Memory'), 'default': '1', 'type': 'jvm', 'is_yarn': False},
 
     {'name': 'driverCores', 'nice_name': _('Driver Cores'), 'default': '1', 'type': 'number', 'is_yarn': True},
     {'name': 'executorCores', 'nice_name': _('Executor Cores'), 'default': '1', 'type': 'number', 'is_yarn': True},
     {'name': 'queue', 'nice_name': _('Queue'), 'default': '1', 'type': 'string', 'is_yarn': True},
-    {'name': 'archives', 'nice_name': _('Archives'), 'default': '', 'type': 'csv', 'is_yarn': True},
+    {'name': 'archives', 'nice_name': _('Archives'), 'default': '', 'type': 'csv-hdfs-files', 'is_yarn': True},
     {'name': 'numExecutors', 'nice_name': _('Executors Numbers'), 'default': '1', 'type': 'number', 'is_yarn': True},
   ]
 

+ 11 - 3
apps/spark/src/spark/templates/editor_components.mako

@@ -420,6 +420,14 @@ from django.utils.translation import ugettext as _
   <div data-bind="component: { name: 'csv-list-input', params: { value: value, placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></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="snippet-settings">
   <div class="snippet-settings" data-bind="slideVisible: settingsVisible" style="position: relative; z-index: 100;">
     <div class="snippet-settings-header">
@@ -431,8 +439,8 @@ from django.utils.translation import ugettext as _
         <!-- ko template: { if: typeof properties.executorCores != 'undefined', name: 'property', data: { type: 'number', label: '${ _('Executor Cores') }', value: properties.executorCores, title: '${ _('Number of cores per executor (Default: 1)') }' }} --><!-- /ko -->
         <!-- ko template: { if: typeof properties.numExecutors != 'undefined', name: 'property', data: { type: 'number', label: '${ _('Executors') }', value: properties.numExecutors, title: '${ _('Number of executors to launch (Default: 2)') }' }} --><!-- /ko -->
         <!-- ko template: { if: typeof properties.queue != 'undefined', name: 'property', data: { type: 'string', label: '${ _('Queue') }', value: properties.queue, title: '${ _('The YARN queue to submit to (Default: default)') }' }} --><!-- /ko -->
-        <!-- ko template: { if: typeof properties.archives != 'undefined', name: 'property', data: { type: 'csv', label: '${ _('Archives') }', value: properties.archives, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. archive.dat') }'}} --><!-- /ko -->
-        <!-- ko template: { if: typeof properties.files != 'undefined', name: 'property', data: { type: 'csv', label: '${ _('Files') }', value: properties.files, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. file.dat') }'}} --><!-- /ko -->
+        <!-- ko template: { if: typeof properties.archives != 'undefined', name: 'property', data: { type: 'csv-hdfs-files', label: '${ _('Archives') }', value: properties.archives, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. archive.dat') }'}} --><!-- /ko -->
+        <!-- ko template: { if: typeof properties.files != 'undefined', name: 'property', data: { type: 'csv-hdfs-files', label: '${ _('Files') }', value: properties.files, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. file.dat') }'}} --><!-- /ko -->
         <!-- ko template: { if: typeof properties.settings != 'undefined', name: 'property', data: { type: 'csv', label: '${ _('Settings') }', value: properties.settings, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. foo') }'}} --><!-- /ko -->
       </form>
     </div>
@@ -746,7 +754,7 @@ from django.utils.translation import ugettext as _
   </div>
 </script>
 
-<div id="chooseFile" class="modal hide fade">
+<div id="chooseFile" class="modal hide fade" style="z-index: 10000;">
   <div class="modal-header">
       <a href="#" class="close" data-dismiss="modal">&times;</a>
       <h3>${_('Choose a file')}</h3>

+ 9 - 3
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -1392,13 +1392,19 @@ ko.bindingHandlers.filechooser = {
       });
     }
 
-    self.after(getFileBrowseButton(self, true, valueAccessor, true, allBindingsAccessor));
+    self.after(getFileBrowseButton(self, true, valueAccessor, true, allBindingsAccessor, valueAccessor().isAddon));
   }
 };
 
 
-function getFileBrowseButton(inputElement, selectFolder, valueAccessor, stripHdfsPrefix, allBindingsAccessor) {
-  var _btn = $("<button>").addClass("btn").addClass("fileChooserBtn").text("..").click(function (e) {
+function getFileBrowseButton(inputElement, selectFolder, valueAccessor, stripHdfsPrefix, allBindingsAccessor, isAddon) {
+  var _btn;
+  if (isAddon) {
+    _btn = $("<span>").addClass("add-on muted pointer").text("..");
+  } else {
+    _btn = $("<button>").addClass("btn").addClass("fileChooserBtn").text("..");
+  }
+  _btn.click(function (e) {
     e.preventDefault();
     $("html").addClass("modal-open");
     // check if it's a relative path

+ 4 - 0
desktop/core/src/desktop/templates/ko_components.mako

@@ -579,7 +579,10 @@ from django.utils.translation import ugettext as _
     <ul data-bind="sortable: values, 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>
         </div>
         <a href="#" data-bind="click: function(){ $parent.removeValue(this); }">
@@ -600,6 +603,7 @@ from django.utils.translation import ugettext as _
         this.valueObservable = params.value;
         this.isArray = $.isArray(this.valueObservable());
         this.placeholder = params.placeholder || '';
+        this.inputTemplate = params.inputTemplate || null;
 
         var initialValues = this.isArray ? this.valueObservable() : this.valueObservable().split(",");
         for (var i = 0; i < initialValues.length; i++) {