Browse Source

HUE-2727 [spark] Style the session properties

Johan Ahlen 10 years ago
parent
commit
99a6d71

+ 31 - 7
apps/spark/src/spark/static/spark/js/spark.ko.js

@@ -540,8 +540,29 @@ var Snippet = function (vm, notebook, snippet) {
       self.progress(0);
     }
   };
-}
+};
+
+var Session = function(vm, session) {
+  var self = this;
+  ko.mapping.fromJS(session, {}, self);
 
+  self.selectedSessionProperty = ko.observable('');
+
+  if (! ko.isObservable(self.properties)) {
+    self.properties = ko.observableArray();
+  }
+
+  this.availableNewProperties = ko.computed(function() {
+    var addedIndex = {};
+    $.each(self.properties(), function(index, property) {
+      addedIndex[property.name()] = true;
+    });
+    var result = $.grep(vm.availableSessionProperties(), function(property) {
+      return ! addedIndex[property.name];
+    });
+    return result;
+  });
+};
 
 var Notebook = function (vm, notebook) {
   var self = this;
@@ -552,7 +573,11 @@ var Notebook = function (vm, notebook) {
   self.description = ko.observable(typeof notebook.description != "undefined" && notebook.description != null ? notebook.description: '');
   self.snippets = ko.observableArray();
   self.selectedSnippet = ko.observable(vm.availableSnippets()[0].type());
-  self.sessions = ko.mapping.fromJS(typeof notebook.sessions != "undefined" && notebook.sessions != null ? notebook.sessions : []);
+  self.sessions = ko.mapping.fromJS(typeof notebook.sessions != "undefined" && notebook.sessions != null ? notebook.sessions : [], {
+    create: function(value) {
+      return new Session(vm, value.data);
+    }
+  });
 
   self.getSession = function (session_type) {
     var _s = null;
@@ -567,7 +592,7 @@ var Notebook = function (vm, notebook) {
 
   self.restartSession = function (session) {
     self.closeSession(session);
-    self.createSession(session);
+    self.createSession({'type': session.type() });
   };
 
   self.addSession = function (session) {
@@ -607,10 +632,10 @@ var Notebook = function (vm, notebook) {
 
     $.post("/spark/api/create_session", {
       notebook: ko.mapping.toJSON(self.getContext()),
-      session: ko.mapping.toJSON(session), // e.g. {'type': 'hive', 'properties': [{'driverCores': '2'}]}
+      session: ko.mapping.toJSON(session) // e.g. {'type': 'hive', 'properties': [{'driverCores': '2'}]}
     }, function (data) {
       if (data.status == 0) {
-        self.addSession(ko.mapping.fromJS(data.session));
+        self.addSession(new Session(vm, data.session));
         $.each(snippets, function(index, snippet) {
           snippet.status('ready');
         });
@@ -793,10 +818,9 @@ function EditorViewModel(notebooks, options) {
 
   self.availableSessionProperties = ko.computed(function () { // Only Spark
     return ko.utils.arrayFilter(options.session_properties, function (item) {
-        return item.name != '' // Could filter out the ones already selected + yarn only or not
+        return item.name != ''; // Could filter out the ones already selected + yarn only or not
       });
   });
-  self.selectedSessionProperties = ko.observable();
   self.getSessionProperties = function(name) {
     var _prop = null;
     $.each(options.session_properties, function(index, prop) {

+ 41 - 49
apps/spark/src/spark/templates/editor_components.mako

@@ -389,9 +389,9 @@ from django.utils.translation import ugettext as _
 </script>
 
 <script type="text/html" id="property">
-  <div class="reveals-actions spark-property">
-    <label class="control-label" style="width:100px" data-bind="text: label"></label>
-    <div class="controls" style="margin-left:120px">
+  <div class="reveals-actions" data-bind="css: { 'spark-property' : typeof inline === 'undefined' || inline, 'control-group' : typeof inline !== 'undefined' && ! inline }">
+    <label class="control-label" data-bind="text: label, style: { 'width' : typeof inline === 'undefined' || inline ? '120px' : '' }"></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 ifnot: typeof remove === "undefined" -->
@@ -417,7 +417,7 @@ from django.utils.translation import ugettext as _
 </script>
 
 <script type="text/html" id="property-csv">
-  <div data-bind="component: { name: 'csv-list-input', params: { value: value, addLabel: typeof addLabel === 'undefined' ? '' : addLabel, placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
+  <div data-bind="component: { name: 'csv-list-input', params: { value: value, placeholder: typeof placeholder === 'undefined' ? '' : placeholder } }"></div>
 </script>
 
 <script type="text/html" id="snippet-settings">
@@ -431,9 +431,9 @@ 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') }', addLabel: '${ _('Archive') }' }} --><!-- /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') }', addLabel: '${ _('File') }' }} --><!-- /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') }', addLabel: '${ _('Setting') }' }} --><!-- /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.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>
     <a class="pointer demi-modal-chevron" data-bind="click: function() { settingsVisible(! settingsVisible()) }"><i class="fa fa-chevron-up"></i></a>
@@ -633,7 +633,7 @@ from django.utils.translation import ugettext as _
         </div>
       </div>
       <!-- /ko -->
-      <!-- ko template: { if: typeof properties.arguments != 'undefined', name: 'property', data: { type: 'csv', label: '${ _('Arguments') }', value: properties.arguments, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. -foo=bar') }', addLabel: '${ _('Argument') }' }} --><!-- /ko -->
+      <!-- ko template: { if: typeof properties.arguments != 'undefined', name: 'property', data: { type: 'csv', label: '${ _('Arguments') }', value: properties.arguments, title: '${ _('The YARN queue to submit to (Default: default)') }', placeholder: '${ _('e.g. -foo=bar') }', inline: false }} --><!-- /ko -->
     </form>
   </div>
 
@@ -790,48 +790,40 @@ from django.utils.translation import ugettext as _
             <!-- ko foreach: sessions -->
               <!-- ko if: ['pyspark', 'scala'].indexOf(type()) != -1 && typeof properties != 'undefined' -->
               <h4 data-bind="text: $root.getSnippetName(type())" style="clear:left;"></h4>
-
-              <!-- ko foreach: properties -->
-              <div class="control-group">
-                <label class="control-label" data-bind="name"></label>
-                <div class="controls">
-                  <span data-bind="text: name"></span>
-                  <!-- ko with: $root.getSessionProperties(name()) -->
-                    <!-- ko if: type == 'jvm' -->
-                      ## problem with ko actually, cf generated code
-                      ## <jvm-memory-input params="value: executorMemory"></jvm>
-                      <input class="input-small" type="text" data-bind="value: $parent.value" />
-                    <!-- /ko -->
-                    <!-- ko if: type == 'number' -->
-                    <input class="input-small" type="text" data-bind="value: $parent.value" />
-                    <!-- /ko -->
-                    <!-- ko if: type == 'string' -->
-                    <input class="input-small" type="text" data-bind="value: $parent.value" />
-                    <!-- /ko -->
-                    <!-- ko if: type == 'csv' -->
-                    <input class="input-small" type="text" data-bind="value: $parent.value" />
-                    <!-- /ko -->
-                  <!-- /ko -->
-                  <a href="javascript:void(0)" data-bind="click: function(data) { $parent.properties.remove(data) }">
-                    <i class="fa fa-minus"></i>
-                  </a>
-                </div>
+              <div style="display:block; width:100%;">
+                <!-- ko foreach: properties -->
+                  <!-- ko template: {
+                    name: 'property',
+                    data: {
+                      type: $root.getSessionProperties(name()).type,
+                      label: $root.getSessionProperties(name()).nice_name,
+                      value: value,
+                      remove: function () { $parent.properties.remove($data) }
+                    }
+                  } --><!-- /ko -->
+                <!-- /ko -->
+              </div>
+              <div style="clear:both; padding-left: 120px;">
+                <!-- ko if: availableNewProperties().length -->
+                <select data-bind="options: availableNewProperties,
+                         optionsText: 'nice_name',
+                         optionsValue: 'name',
+                         value: selectedSessionProperty,
+                         optionsCaption: '${ _('Choose a property...') }'"></select>
+                <a class="pointer" style="padding:5px;" data-bind="click: selectedSessionProperty() && function() {
+                    properties.push(ko.mapping.fromJS({'name': selectedSessionProperty(), 'value': ''}));
+                    selectedSessionProperty('');
+                  }" style="margin-left:10px;vertical-align: text-top;">
+                  <i class="fa fa-plus"></i>
+                </a>
+                <!-- /ko -->
+                <a style="float: right;" class="btn pointer" title="${ _('Restart session') }" data-dismiss="modal" rel="tooltip" data-bind="click: function() { $root.selectedNotebook().restartSession($data) }">
+                  <i class="fa fa-refresh"></i> ${ _('Recreate') }
+                </a>
+                <a style="margin-right: 5px; float: right;" class="btn pointer" title="${ _('Close session') }" data-dismiss="modal" rel="tooltip" data-bind="click: function() { $root.selectedNotebook().closeSession($data) }">
+                  <i class="fa fa-times"></i> ${ _('Close') }
+                </a>
               </div>
-              <!-- /ko -->
-
-              <select data-bind="options: $root.availableSessionProperties,
-                       optionsText: 'nice_name',
-                       optionsValue: 'name',
-                       value: $root.selectedSessionProperties,
-                       optionsCaption: 'Choose...'"></select>
-              <i class="fa fa-plus" data-bind="click: function() { properties.push(ko.mapping.fromJS({'name': $root.selectedSessionProperties(), 'value': ''})); $root.selectedSessionProperties(''); }"></i>
-
-              <a style="float: right;" class="btn pointer" title="${ _('Restart session') }" data-dismiss="modal" rel="tooltip" data-bind="click: function() { $root.selectedNotebook().restartSession($parent) }">
-                <i class="fa fa-refresh"></i> ${ _('Recreate') }
-              </a>
-              <a style="float: right;" class="btn pointer" title="${ _('Close session') }" data-dismiss="modal" rel="tooltip" data-bind="click: function() { $root.selectedNotebook().closeSession($parent) }">
-                <i class="fa fa-times"></i> ${ _('Close') }
-              </a>
               <!-- /ko -->
             <!-- /ko -->
             </br>

+ 3 - 3
desktop/core/src/desktop/templates/ko_components.mako

@@ -524,7 +524,7 @@ from django.utils.translation import ugettext as _
 
 <%def name="jvmMemoryInput()">
   <script type="text/html" id="jvm-memory-input-template">
-    <input type="text" class="input-small" data-bind="textInput: value" /> <select class="input-mini" data-bind="options: units, value: selectedUnit" />
+    <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">
@@ -536,10 +536,10 @@ from django.utils.translation import ugettext as _
         this.valueObservable = params.value;
         this.units = Object.keys(UNITS);
         this.selectedUnit = ko.observable();
-        this.value = ko.observable().extend({ 'numeric' : 0 });
+        this.value = ko.observable('');
 
         var match = JVM_MEM_PATTERN.exec(this.valueObservable());
-        if (match.length === 3) {
+        if (match && match.length === 3) {
           this.value(match[1]);
           this.selectedUnit(match[2] === 'M' ? 'MB' : 'GB');
         }