Browse Source

AMBARI-5141. Selecting operator in Tez DAG vertex should show operator table (alexantonenko)

Alex Antonenko 11 years ago
parent
commit
e2a743ba07

+ 1 - 4
ambari-web/app/styles/application.less

@@ -5715,16 +5715,13 @@ i.icon-asterisks {
     }
     }
   }
   }
   #tez-vertex-details-section-body {
   #tez-vertex-details-section-body {
-    table {
-      margin-bottom: 5px;
-    }
     td {
     td {
       border-top: none;
       border-top: none;
     }
     }
     tr td:first-child {
     tr td:first-child {
       font-weight: bold;
       font-weight: bold;
       width: 20%;
       width: 20%;
-      overflow: scroll;
+      overflow: auto;
     }
     }
     textarea {
     textarea {
       width: 95%;
       width: 95%;

+ 24 - 0
ambari-web/app/styles/apps.less

@@ -278,6 +278,30 @@
     }
     }
   }
   }
 }
 }
+#hover-op-table{
+  margin-bottom: 2px;
+  td{
+    padding: 2px;
+    word-wrap: break-word;
+  }
+}
+
+#hive-job-details{
+  #operator-table{
+    td {
+      border-top: 1px solid #dddddd;
+    }
+    tr td:first-child{
+       width: 20%;
+       overflow: auto;
+    }
+    td:first-child + td,
+    th:first-child + th {
+      width: 80%;
+    }
+  }
+}
+
 
 
 #jobs {
 #jobs {
 
 

+ 17 - 6
ambari-web/app/templates/main/jobs/hive_job_details.hbs

@@ -172,13 +172,24 @@
                         <td>{{view.selectedVertexIODisplay.records.write}}</td>
                         <td>{{view.selectedVertexIODisplay.records.write}}</td>
                       </tr>
                       </tr>
                     {{/if}}
                     {{/if}}
-                    <tr>
-                      <td>{{t jobs.hive.tez.operatorPlan}}</td>
-                      <td></td>
-                      <td></td>
-                    </tr>
                   </table>
                   </table>
-                  {{view Ember.TextArea valueBinding="view.selectedVertex.operationPlan" rows="15" id="tez-vertex-operator-plan-textarea"}}
+                  <p>{{t jobs.hive.tez.operatorPlan}}</p>
+                  <table id="operator-table" class="table table-bordered table-striped">
+                    <thead>
+                      <tr>
+                        <th>{{t common.name}}</th>
+                        <th>{{t common.value}}</th>
+                      </tr>
+                    </thead>
+                    <tbody>
+                      {{#each keys in view.operatorPlan}}
+                        <tr>
+                          <td>{{keys.name}}</td>
+                          <td>{{keys.value}}</td>
+                        </tr>
+                      {{/each}}
+                    </tbody>
+                  </table>
                 </div>
                 </div>
               </div>
               </div>
             </div>
             </div>

+ 20 - 0
ambari-web/app/templates/main/jobs/hover_op_table.hbs

@@ -0,0 +1,20 @@
+<table id="hover-op-table" class="table table-bordered">
+    <thead>
+    <tr>
+        <th>{{t common.name}}</th>
+        <th>{{t common.value}}</th>
+    </tr>
+    </thead>
+    <tbody>
+    {{#each keys in content}}
+        <tr>
+            <td>
+              {{keys.name}}
+            </td>
+            <td>
+              {{keys.value}}
+            </td>
+        </tr>
+    {{/each}}
+    </tbody>
+</table>

+ 30 - 0
ambari-web/app/utils/helper.js

@@ -36,6 +36,36 @@ String.prototype.capitalize = function () {
   return this.charAt(0).toUpperCase() + this.slice(1);
   return this.charAt(0).toUpperCase() + this.slice(1);
 };
 };
 
 
+// Use: stringvalue.findIn(multi_dimensional_array_or_object)
+/***Example:
+ var tofind = 'emotion';
+ var person = {'name': 'Bob Loblaw', 'age': '28', 'personality': {'smart': 'yes', 'funny': 'yes', 'emotion': 'happy'} };
+ tofind.findIn(person)
+ ***/
+String.prototype.findIn = function (multi) {
+  multi = multi || '';
+  var val = this.valueOf();
+  if(typeof multi == 'object' || typeof multi == 'array')
+  {
+    if(val in multi)
+    {
+      return multi[val];
+    }
+    else
+    {
+      for(var x in multi)
+      {
+        var found = this.findIn(multi[x]);
+        if(found != false)
+        {
+          return found;
+        }
+      }
+    }
+  }
+  return false;
+};
+
 /**
 /**
  * Replace {i} with argument. where i is number of argument to replace with
  * Replace {i} with argument. where i is number of argument to replace with
  * @return {String}
  * @return {String}

+ 32 - 56
ambari-web/app/views/main/jobs/hive_job_details_tez_dag_view.js

@@ -292,6 +292,25 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
       'content.tezDag.vertices.@each.recordReadCount', 'content.tezDag.vertices.@each.recordWriteCount',
       'content.tezDag.vertices.@each.recordReadCount', 'content.tezDag.vertices.@each.recordWriteCount',
       'content.tezDag.vertices.@each.state', 'content.tezDag.vertices.@each.spilledRecords'),
       'content.tezDag.vertices.@each.state', 'content.tezDag.vertices.@each.spilledRecords'),
 
 
+  createOperationPlanObj: function (vertexName, op) {
+    var operatorPlanObj = [];
+    var text = this.get('content.tezDag.vertices').findProperty('name', vertexName).get('operationPlan');
+    text = text.replace(/:"/g,'"');
+    var jsonText =  $.parseJSON(text);
+    var jsonText = op.findIn(jsonText);
+    for (var key in jsonText) {
+      if (jsonText.hasOwnProperty(key) && typeof(jsonText[key]) == "string") {
+        operatorPlanObj.push(
+          {
+            name: key,
+            value: jsonText[key]
+          }
+        );
+      }
+    }
+    return operatorPlanObj;
+  },
+
   /**
   /**
    * Determines layout and creates Tez graph. In the process it populates the
    * Determines layout and creates Tez graph. In the process it populates the
    * visual model into 'dagVisualModel' field.
    * visual model into 'dagVisualModel' field.
@@ -574,7 +593,6 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
     //
     //
     // Draw SVG
     // Draw SVG
     //
     //
-    var self = this;
     var force = d3.layout.force().nodes(dagVisualModel.nodes).links(dagVisualModel.links).start();
     var force = d3.layout.force().nodes(dagVisualModel.nodes).links(dagVisualModel.links).start();
     var nodeDragData = {
     var nodeDragData = {
       nodeRelativeX : 0,
       nodeRelativeX : 0,
@@ -648,61 +666,15 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
           }
           }
           return opCount[op];
           return opCount[op];
         }).on('mousedown', function(op) {
         }).on('mousedown', function(op) {
-          var opIndex = this.getAttribute ? this.getAttribute("opIndex") : null;
-          if (numberUtils.validateInteger(opIndex) == null) {
-            console.log("Clicked on operator: ", op, " [", opIndex, "]");
-            var textArea = document.getElementById('tez-vertex-operator-plan-textarea');
-            if (textArea && textArea.value) {
-              var text = textArea.value;
-              var opText = "\"" + op + "\"";
-              var count = 1;
-              var index = text.indexOf(opText);
-              while (index > -1 && count < opIndex) {
-                index = text.indexOf(opText, index + 1);
-                count++;
-              }
-              if (index > -1) {
-                var start = index;
-                var end = index;
-                var matchCount = 0;
-                var splits = text.substring(start).split(/({|})/);
-                splits.every(function(s) {
-                  if (s == '{') {
-                    matchCount++;
-                  } else if (s == '}') {
-                    matchCount--;
-                    if (matchCount == 0) {
-                      end += s.length;
-                      return false;
-                    }
-                  }
-                  end += s.length;
-                  return true;
-                });
-                textArea.setSelectionRange(start, end);
-                // Now scroll to the selection
-                var lines = 0;
-                var totalLines = 0;
-                var index = text.indexOf("\n");
-                while (index > 0) {
-                  index = text.indexOf("\n", index + 1);
-                  if (index < start) {
-                    lines++;
-                  }
-                  totalLines++;
-                }
-                console.log("Selection is from row ", lines, " out of ", totalLines);
-                lines -= 5;
-                var lineHeight = Math.floor(textArea.scrollHeight / totalLines);
-                var scrollHeight = Math.round(lines * lineHeight);
-                textArea.scrollTop = scrollHeight;
-              }
-            }
-          }
-        });
-        opGroups.append("rect").attr("class", "operation svg-tooltip ").attr("width", "50").attr("height", "16").attr("title", function(op) {
-          return op;
-        });
+          var operatorPlanObj = self.createOperationPlanObj(n.name, op);
+          self.get('parentView').set('operatorPlan', operatorPlanObj);
+        }).on('mouseover', function(op) {
+          var operatorPlanObj = self.createOperationPlanObj(n.name, op);
+          var template = App.HoverOpTable.create({content: operatorPlanObj}) ;
+          $(event.currentTarget).find('.svg-tooltip').attr('title', template.renderToBuffer().string()).tooltip('fixTitle').tooltip('show');
+        })
+
+        opGroups.append("rect").attr("class", "operation svg-tooltip ").attr("width", "50").attr("height", "16");
         opGroups.append("text").attr("x", "2").attr("dy", "1em").text(function(op) {
         opGroups.append("text").attr("x", "2").attr("dy", "1em").text(function(op) {
           return op != null ? op.split(' ')[0] : '';
           return op != null ? op.split(' ')[0] : '';
         });
         });
@@ -916,3 +888,7 @@ App.MainHiveJobDetailsTezDagView = Em.View.extend({
   }
   }
 
 
 });
 });
+
+App.HoverOpTable = Ember.View.extend({
+  templateName : require('templates/main/jobs/hover_op_table')
+});

+ 1 - 0
ambari-web/app/views/main/jobs/hive_job_details_view.js

@@ -26,6 +26,7 @@ App.MainHiveJobDetailsView = Em.View.extend({
   templateName : require('templates/main/jobs/hive_job_details'),
   templateName : require('templates/main/jobs/hive_job_details'),
 
 
   selectedVertex : null,
   selectedVertex : null,
+  operatorPlan: [],
   content : null,
   content : null,
   zoomScaleFrom : 1,
   zoomScaleFrom : 1,
   zoomScaleTo: 2,
   zoomScaleTo: 2,