Browse Source

HUE-3666 [core] Autocomplete plugin to select and filter from all the documents

Enrico Berti 9 years ago
parent
commit
900b8f9e1b

+ 4 - 0
apps/oozie/src/oozie/static/oozie/css/workflow-editor.css

@@ -306,3 +306,7 @@ ul.unstyled li {
 .zoom-in {
   cursor: zoom-in;
 }
+
+.ui-autocomplete {
+  z-index: 4000;
+}

+ 82 - 63
apps/oozie/src/oozie/static/oozie/js/workflow-editor.ko.js

@@ -72,7 +72,7 @@ function loadLayout(viewModel, json_layout) {
 
 // End dashboard lib
 
-var Node = function (node) {
+var Node = function (node, vm) {
   var self = this;
 
   var type = typeof node.widgetType != "undefined" ? node.widgetType : node.type;
@@ -84,6 +84,32 @@ var Node = function (node) {
   self.properties = ko.mapping.fromJS(typeof node.properties != "undefined" && node.properties != null ? node.properties : {});
   self.children = ko.mapping.fromJS(typeof node.children != "undefined" && node.children != null ? node.children : []);
 
+  self.associatedDocument = ko.observable();
+
+  function setAssociatedDocument(uuid) {
+    if (vm.documentStore[uuid]){
+      self.associatedDocument(vm.documentStore[uuid]);
+    }
+    $.get('/desktop/api2/doc/', {
+      uuid: uuid
+    }, function(data){
+      if (data && data.document){
+        self.associatedDocument(ko.mapping.fromJS(data.document));
+        vm.documentStore[uuid] = self.associatedDocument();
+      }
+    });
+  }
+
+  if (node.properties.uuid){
+    setAssociatedDocument(node.properties.uuid);
+  }
+
+  if (self.properties.uuid){
+    self.properties.uuid.subscribe(function(val){
+      setAssociatedDocument(val);
+    });
+  }
+
   self.actionParameters = ko.observableArray([]);
   self.actionParametersUI = ko.computed(function () {
     if (typeof self.properties.parameters != "undefined") {
@@ -183,7 +209,11 @@ var Workflow = function (vm, workflow) {
   self.uuid = ko.observable(typeof workflow.uuid != "undefined" && workflow.uuid != null ? workflow.uuid : UUID());
   self.name = ko.observable(typeof workflow.name != "undefined" && workflow.name != null ? workflow.name : "");
 
-  self.tracker = new ChangeTracker(self, ko); // from ko.common-dashboard.js
+  self.tracker = new ChangeTracker(self, ko, {
+    ignore: [
+      "associatedDocument"
+    ]
+  }); // from ko.common-dashboard.js
 
   self.isDirty = ko.computed(function () {
     return self.tracker().somethingHasChanged();
@@ -244,7 +274,7 @@ var Workflow = function (vm, workflow) {
   self.loadNodes = function (workflow) {
     var nodes = []
     $.each(workflow.nodes, function (index, node) {
-      var _node = new Node(node);
+      var _node = new Node(node, vm);
       nodes.push(_node);
     });
     self.nodes(nodes)
@@ -293,7 +323,7 @@ var Workflow = function (vm, workflow) {
           var node = self.movedNode;
           self.movedNode = null;
         } else {
-          var node = new Node(_node);
+          var node = new Node(_node, vm);
           node.fetch_parameters();
         }
 
@@ -309,8 +339,8 @@ var Workflow = function (vm, workflow) {
             vm.currentlyCreatedJoin.properties['fork_id'] = vm.currentlyCreatedFork.id;
             vm.currentlyCreatedFork.properties['join_id'] = vm.currentlyCreatedJoin.id;
 
-            var fork = new Node(vm.currentlyCreatedFork);
-            var join = new Node(vm.currentlyCreatedJoin);
+            var fork = new Node(vm.currentlyCreatedFork, vm);
+            var join = new Node(vm.currentlyCreatedJoin, vm);
 
             self.nodes.push(fork);
             self.nodes.push(join);
@@ -506,32 +536,52 @@ var WorkflowEditorViewModel = function (layout_json, workflow_json, credentials_
     self.workflow_properties = ko.mapping.fromJS(workflow_properties_json);
     loadLayout(self, layout_json);
     self.workflow.loadNodes(workflow_json);
-
-    self.getDocuments('query-hive', self.hiveQueries);
-    self.getDocuments('query-java', self.javaQueries);
-    self.getDocuments('query-spark2', self.sparkApps);
-    self.getDocuments('query-pig', self.pigScripts);
-    self.getDocuments('query-sqoop1', self.sqoopScripts);
-    self.getDocuments('query-distcp', self.distCpScripts);
-    self.getDocuments('query-shell', self.shellScripts);
-    self.getDocuments('query-mapreduce', self.mapReduceScripts);
   };
 
-  self.getDocuments = function(type, destination) {
-	$.get('/desktop/api2/docs/', {
-	    type: type,
-	    include_trashed: false,
-	    sort: '-last_modified',
-	    limit: 100
-	}, function(data) {
-	  if (data && data.documents) {
-	    var queries = [];
-	    $.each(data.documents, function(index, query) {
-	      queries.push(ko.mapping.fromJS(query));
-	    });
-	    destination(queries);
-	  }
-	});
+  self.documentStore = {};
+  self.documentsAutocompleteSource = function (request, callback) {
+    var TYPE_MAP = {
+      'hive': 'query-hive',
+      'impala': 'query-impala',
+      'java': 'query-java',
+      'spark': 'query-spark2',
+      'pig': 'query-pig',
+      'sqoop': 'query-sqoop1',
+      'distcp-doc': 'query-distcp',
+      'mapreduce-doc': 'query-mapreduce'
+    }
+    var type = 'query-hive';
+    if (this.options && typeof this.options.type === 'function') {
+      type = TYPE_MAP[this.options.type()] ? TYPE_MAP[this.options.type()] : this.options.type();
+    }
+    $.get('/desktop/api2/docs/', {
+      type: type,
+      text: request.term,
+      include_trashed: false,
+      limit: 100
+    }, function (data) {
+      if (data && data.documents) {
+        var docs = [];
+        if (data.documents.length > 0) {
+          $.each(data.documents, function (index, doc) {
+            docs.push({
+              data: {name: doc.name, type: doc.type, description: doc.description},
+              value: doc.uuid,
+              label: doc.name
+            });
+            self.documentStore[doc.uuid] = ko.mapping.fromJS(doc);
+          });
+        }
+        else {
+          docs.push({
+            data: {name: 'No matches found', description: ''},
+            label: 'No matches found',
+            value: ''
+          });
+        }
+        callback(docs);
+      }
+    });
   };
 
   self.addActionProperties = ko.observableArray([]);
@@ -557,42 +607,11 @@ var WorkflowEditorViewModel = function (layout_json, workflow_json, credentials_
 
 
   self.subworkflows = ko.observableArray(getOtherSubworkflows(self, subworkflows_json));
-  self.hiveQueries = ko.observableArray();
-  self.javaQueries = ko.observableArray();
-  self.sparkApps = ko.observableArray();
-  self.pigScripts = ko.observableArray();
-  self.sqoopScripts = ko.observableArray();
-  self.distCpScripts = ko.observableArray();
-  self.shellScripts = ko.observableArray();
-  self.mapReduceScripts = ko.observableArray();
   self.history = ko.mapping.fromJS(history_json);
 
   self.getDocumentById = function (type, uuid) {
-    var _query = null;
-    if (type.indexOf('java') != -1) {
-      data = self.javaQueries();
-    } else if (type.indexOf('spark') != -1) {
-      data = self.sparkApps();
-    } else if (type.indexOf('pig') != -1) {
-      data = self.pigScripts();
-    } else if (type.indexOf('sqoop1') != -1) {
-      data = self.sqoopScripts();
-    } else if (type.indexOf('distcp') != -1) {
-      data = self.distCpScripts();
-    } else if (type.indexOf('shell') != -1) {
-      data = self.shellScripts();
-    } else if (type.indexOf('mapreduce') != -1) {
-      data = self.mapReduceScripts();
-    } else {
-      data = self.hiveQueries();
-    }
-    $.each(data, function (index, query) {
-      if (query.uuid() == uuid) {
-        _query = query;
-        return false;
-      }
-    });
-    return _query;
+    var doc = self.documentStore[uuid];
+    return doc;
   };
 
   self.getSubWorkflow = function (uuid) {

+ 53 - 233
apps/oozie/src/oozie/templates/editor2/common_workflow.mako

@@ -29,6 +29,15 @@
 
 <%def name="render()">
 
+<script type="text/html" id="doc-search-autocomp-item">
+  <a>
+    <div>
+      <strong style="font-size: 14px;" data-bind="html: name"></strong>
+      <div style="width: 190px; overflow: hidden; white-space: nowrap; text-overflow:ellipsis; font-size: 12px;" class="muted" data-bind="text: description"></div>
+    </div>
+  </a>
+</script>
+
 <div data-bind="css: {'dashboard': true, 'readonly': ! isEditing()}">
   <!-- ko if: $root.workflow.properties.imported -->
     <div class="alert alert-warn" style="margin-top: 93px; margin-bottom: 0; border: none; text-align: center">
@@ -603,6 +612,42 @@
  <!-- /ko -->
 </script>
 
+<script type="text/html" id="common-document-widget">
+  <div data-bind="visible: ! $root.isEditing()">
+      <span data-bind="template: { name: 'logs-icon' }"></span>
+      <!-- ko with: associatedDocument -->
+        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
+        <br/>
+        <span data-bind='text: description' class="muted"></span>
+      <!-- /ko -->
+    </div>
+
+    <div data-bind="visible: $root.isEditing">
+      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
+        <!-- ko if: associatedDocument -->
+          <input placeholder="${ _('Search your documents...') }" type="text" data-bind="autocomplete: {
+              source: $root.documentsAutocompleteSource,
+              minLength: 0,
+              type: associatedDocument().type,
+              create: function (event, ui) { this.value = ko.dataFor(event.target).associatedDocument().name(); return false;},
+              select: function (event, ui) { ko.dataFor(event.target).properties.uuid(ui.item.value); this.value = ui.item.label; return false;},
+              focus: function (event, ui) { this.value = ui.item.label; return false;},
+              change: function (event, ui) { this.value = ko.dataFor(event.target).associatedDocument().name(); return false;},
+              itemTemplate: 'doc-search-autocomp-item'
+            }, valueUpdate: 'afterkeydown'">
+          <a href="#" data-bind="attr: { href: associatedDocument().absoluteUrl() }" target="_blank" title="${ _('Open') }">
+            <i class="fa fa-external-link-square"></i>
+          </a>
+          <div data-bind='text: associatedDocument().description' style="padding: 3px; margin-top: 2px" class="muted"></div>
+        <!-- /ko -->
+        <div class="row-fluid">
+          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
+          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
+        </div>
+      </div>
+    </div>
+
+</script>
 
 <script type="text/html" id="param-fs-link">
   <!-- ko if: path.split('=', 2)[1] && path.split('=', 2)[1].charAt(0) == '/' -->
@@ -817,35 +862,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.pigScripts, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Pig program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -985,32 +1002,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById('spark2', properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById('spark2', properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.sparkApps, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Java program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -1101,40 +1093,11 @@
   <!-- /ko -->
 </script>
 
-
 <script type="text/html" id="hive-document-widget">
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.hiveQueries, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Hive query name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -1179,35 +1142,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.javaQueries, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Java program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -1396,36 +1331,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById('query-sqoop1', properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById('query-sqoop1', properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById('query-sqoop1', properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById('query-sqoop1', properties.uuid()) -->
-          <select data-bind="options: $root.sqoopScripts, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Sqoop program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -1565,36 +1471,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.mapReduceScripts, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('MapReduce program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -1774,35 +1651,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.shellScripts, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('Shell program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">
@@ -2346,36 +2195,7 @@
   <!-- ko if: $root.workflow.getNodeById(id()) -->
   <div class="row-fluid" data-bind="with: $root.workflow.getNodeById(id())" style="padding: 10px">
 
-    <div data-bind="visible: ! $root.isEditing()">
-      <span data-bind="template: { name: 'logs-icon' }"></span>
-      <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-      <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-        <a data-bind="attr: { href: absoluteUrl() }" target="_blank"><span data-bind='text: name'></span></a>
-        <br/>
-        <span data-bind='text: description' class="muted"></span>
-      <!-- /ko -->
-      <!-- /ko -->
-    </div>
-
-    <div data-bind="visible: $root.isEditing">
-      <div data-bind="visible: ! $parent.ooziePropertiesExpanded()" class="nowrap">
-        <!-- ko if: $root.getDocumentById(type(), properties.uuid()) -->
-        <!-- ko with: $root.getDocumentById(type(), properties.uuid()) -->
-          <select data-bind="options: $root.distCpScripts, optionsText: 'name', optionsValue: 'uuid', value: $parent.properties.uuid, select2Version4:{ placeholder: '${ _ko('DistCp program name...')}'}"></select>
-          <a href="#" data-bind="attr: { href: absoluteUrl() }" target="_blank" title="${ _('Open') }">
-            <i class="fa fa-external-link-square"></i>
-          </a>
-          <div data-bind='text: description' style="padding: 3px; margin-top: 2px" class="muted"></div>
-        <!-- /ko -->
-        <!-- /ko -->
-
-        <div class="row-fluid">
-          <div class="span6" data-bind="template: { name: 'common-properties-parameters' }"></div>
-          <div class="span6" data-bind="template: { name: 'common-properties-files' }"></div>
-        </div>
-
-      </div>
-    </div>
+    <span data-bind="template: { name: 'common-document-widget' }"></span>
 
     <div data-bind="visible: $parent.ooziePropertiesExpanded">
       <ul class="nav nav-tabs">

+ 8 - 3
apps/oozie/src/oozie/templates/editor2/workflow_editor.mako

@@ -334,14 +334,19 @@ ${ workflow.render() }
           <select data-bind="options: $root.subworkflows, optionsText: 'name', optionsValue: 'value', value: value"></select>
           <!-- /ko -->
           <!-- ko if: ['hive', 'java', 'spark', 'pig', 'sqoop', 'distcp-doc', 'shell-doc', 'mapreduce-doc'].indexOf(type()) != -1 -->
-          <select data-bind="options: type() == 'java' ? $root.javaQueries() : (type() == 'spark' ? $root.sparkApps() : (type() == 'pig' ? $root.pigScripts() : (type() == 'sqoop' ? $root.sqoopScripts() : (type() == 'distcp-doc' ? $root.distCpScripts() : (type() == 'shell-doc' ? $root.shellScripts() : (type() == 'mapreduce-doc' ? $root.mapReduceScripts() : $root.hiveQueries())))))), optionsText: 'name', optionsValue: 'uuid', value: value, select2Version4:{ placeholder: '${ _ko('Document name...')}'}"></select>
+          <input placeholder="${ _('Search your documents...') }" type="text" data-bind="autocomplete: {
+            source: $root.documentsAutocompleteSource,
+            minLength: 0,
+            type: type,
+            select: function (event, ui) { ko.dataFor(event.target).value(ui.item.value); this.value = ui.item.label; return false;},
+            focus: function (event, ui) { this.value = ui.item.label; return false;},
+            itemTemplate: 'doc-search-autocomp-item'
+          }, valueUpdate: 'afterkeydown'">
           <!-- ko if: $root.getDocumentById(type(), value()) -->
             <!-- ko with: $root.getDocumentById(type(), value()) -->
               <a href="#" data-bind="attr: { href: $data.absoluteUrl() }" target="_blank" title="${ _('Open') }">
                 <i class="fa fa-external-link-square"></i>
               </a>
-              </br>
-              <span data-bind='text: $data.description' class="muted"></span>
             <!-- /ko -->
           <!-- /ko -->
           <!-- /ko -->

+ 3 - 1
desktop/core/src/desktop/static/desktop/js/ko.common-dashboard.js

@@ -285,7 +285,7 @@ function setLayout(colSizes, vm) {
   $(document).trigger("setLayout");
 }
 
-function ChangeTracker(objectToTrack, ko) {
+function ChangeTracker(objectToTrack, ko, mappingOptions) {
   var hashFunction = typeof ko.mapping !== 'undefined' ? ko.mapping.toJSON : ko.toJSON;
   var lastCleanState = ko.observable(hashFunction(objectToTrack));
 
@@ -295,6 +295,8 @@ function ChangeTracker(objectToTrack, ko) {
     ]
   };
 
+  $.extend(MAPPING, mappingOptions);
+
   var result = {
     somethingHasChanged: ko.dependentObservable(function () {
       $(document).trigger("viewmodelHasChanged");