Repository: tez Updated Branches: refs/heads/master 8a233ecc1 -> 182c9970a
TEZ-3171. Tez UI 2: Swimlane - Tooltip, zoom & redirection (sree) Project: http://git-wip-us.apache.org/repos/asf/tez/repo Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/182c9970 Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/182c9970 Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/182c9970 Branch: refs/heads/master Commit: 182c9970a792cb47b958daff5e64a89a3b6174b6 Parents: 8a233ec Author: Sreenath Somarajapuram <[email protected]> Authored: Sat Mar 26 00:20:14 2016 +0530 Committer: Sreenath Somarajapuram <[email protected]> Committed: Sat Mar 26 00:20:14 2016 +0530 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../components/em-swimlane-blocking-event.js | 16 ++ .../app/components/em-swimlane-event-bar.js | 23 ++- .../webapp/app/components/em-swimlane-event.js | 21 ++- .../app/components/em-swimlane-process-line.js | 54 +++++++ .../app/components/em-swimlane-process-name.js | 19 ++- .../components/em-swimlane-process-visual.js | 42 ++++- .../main/webapp/app/components/em-swimlane.js | 23 ++- .../main/webapp/app/components/em-tooltip.js | 158 +++++++++++++++++++ .../main/webapp/app/controllers/dag/swimlane.js | 98 ++++++++++-- tez-ui2/src/main/webapp/app/styles/app.less | 1 + .../src/main/webapp/app/styles/em-swimlane.less | 77 ++++----- .../src/main/webapp/app/styles/em-tooltip.less | 117 ++++++++++++++ .../main/webapp/app/styles/swimlane-page.less | 17 ++ .../templates/components/em-swimlane-event.hbs | 2 +- .../components/em-swimlane-process-line.hbs | 19 +++ .../components/em-swimlane-process-visual.hbs | 32 +++- .../app/templates/components/em-swimlane.hbs | 30 ++-- .../app/templates/components/em-tooltip.hbs | 54 +++++++ .../main/webapp/app/templates/dag/swimlane.hbs | 7 + tez-ui2/src/main/webapp/app/utils/process.js | 7 + .../src/main/webapp/app/utils/vertex-process.js | 51 +++++- .../components/em-swimlane-process-line-test.js | 65 ++++++++ .../em-swimlane-process-visual-test.js | 3 +- .../integration/components/em-swimlane-test.js | 7 + .../integration/components/em-tooltip-test.js | 80 ++++++++++ .../webapp/tests/unit/utils/process-test.js | 1 + .../tests/unit/utils/vertex-process-test.js | 80 ++++++++++ 28 files changed, 1022 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 7c4939c..4b1e91c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1891,6 +1891,7 @@ ALL CHANGES TEZ-3160. Tez UI 2: Swimlane - Create swimlane page & component (sree) TEZ-3170. Tez UI 2: Swimlane - Display computed events, event bars & dependencies (sree) TEZ-3152. Tez UI 2: Build fails when run by multiple users or when node_modules is old (sree) + TEZ-3171. Tez UI 2: Swimlane - Tooltip, zoom & redirection (sree) Release 0.2.0-incubating: 2013-11-30 http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js index a58ded8..c40bec9 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js @@ -47,4 +47,20 @@ export default Ember.Component.extend({ }); }), + sendMouseAction: function (name, mouseEvent) { + this.sendAction(name, "blocking-event", this.get("process"), { + mouseEvent: mouseEvent, + blocking: this.get("blocking"), + blockingEvent: this.get("blockingEvent") + }); + }, + + mouseEnter: function (mouseEvent) { + this.sendMouseAction("showTooltip", mouseEvent); + }, + + mouseLeave: function (mouseEvent) { + this.sendMouseAction("hideTooltip", mouseEvent); + }, + }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js index e0e835e..7afb312 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js @@ -62,6 +62,27 @@ export default Ember.Component.extend({ else { this.$().hide(); } - }) + }), + + sendMouseAction: function (name, mouseEvent) { + this.sendAction(name, "event-bar", this.get("process"), { + mouseEvent: mouseEvent, + bar: this.get("bar"), + fromEvent: this.get("fromEvent"), + toEvent: this.get("toEvent") + }); + }, + + mouseEnter: function (mouseEvent) { + this.sendMouseAction("showTooltip", mouseEvent); + }, + + mouseLeave: function (mouseEvent) { + this.sendMouseAction("hideTooltip", mouseEvent); + }, + + mouseUp: function (mouseEvent) { + this.sendMouseAction("click", mouseEvent); + } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js index 5eb6f0a..c4d31ca 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js @@ -35,10 +35,23 @@ export default Ember.Component.extend({ this.$(".event-bubble").css("border-color", color); }), - actions: { - showTooltip: function () { - console.log(this.get("event.name")); - } + sendMouseAction: function (name, mouseEvent) { + this.sendAction(name, "event", this.get("process"), { + mouseEvent: mouseEvent, + events: [this.get("event")] + }); + }, + + mouseEnter: function (mouseEvent) { + this.sendMouseAction("showTooltip", mouseEvent); + }, + + mouseLeave: function (mouseEvent) { + this.sendMouseAction("hideTooltip", mouseEvent); + }, + + mouseUp: function (mouseEvent) { + this.sendMouseAction("click", mouseEvent); } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-process-line.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-line.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-line.js new file mode 100644 index 0000000..ab4972b --- /dev/null +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-line.js @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + + process: null, + startEvent: null, + endEvent: null, + + didInsertElement: Ember.observer("startEvent.pos", "endEvent.pos", function () { + this.$(".process-line").css({ + left: this.get("startEvent.pos") + "%", + right: (100 - this.get("endEvent.pos")) + "%", + "background-color": this.get("process").getColor() + }); + }), + + sendMouseAction: function (name, mouseEvent) { + this.sendAction(name, "process-line", this.get("process"), { + mouseEvent: mouseEvent, + }); + }, + + mouseEnter: function (mouseEvent) { + this.sendMouseAction("showTooltip", mouseEvent); + }, + + mouseLeave: function (mouseEvent) { + this.sendMouseAction("hideTooltip", mouseEvent); + }, + + mouseUp: function (mouseEvent) { + this.sendMouseAction("click", mouseEvent); + } + + +}); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-process-name.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-name.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-name.js index f2b7ca9..eea897d 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-name.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-name.js @@ -21,8 +21,25 @@ import Ember from 'ember'; export default Ember.Component.extend({ process: null, - definition: null, classNames: ["em-swimlane-process-name"], + sendMouseAction: function (name, mouseEvent) { + this.sendAction(name, "process-name", this.get("process"), { + mouseEvent: mouseEvent, + }); + }, + + mouseEnter: function (mouseEvent) { + this.sendMouseAction("showTooltip", mouseEvent); + }, + + mouseLeave: function (mouseEvent) { + this.sendMouseAction("hideTooltip", mouseEvent); + }, + + mouseUp: function (mouseEvent) { + this.sendMouseAction("click", mouseEvent); + } + }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js index 5942cf1..caa7603 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js @@ -18,6 +18,8 @@ import Ember from 'ember'; +const BUBBLE_RADIUS = 8; // Same as that in css + export default Ember.Component.extend({ process: null, definition: null, @@ -71,12 +73,38 @@ export default Ember.Component.extend({ }); }), - drawEventWindow: Ember.observer("startEvent.pos", "endEvent.pos", function () { - this.$(".event-window-line").css({ - left: this.get("startEvent.pos") + "%", - right: (100 - this.get("endEvent.pos")) + "%", - "background-color": this.get("process").getColor() - }); - }) + actions: { + showTooltip: function(type, process, options) { + + if(type === "event") { + let mouseEvent = options.mouseEvent, + normalizedEvents = this.get("normalizedEvents"), + events = []; + + this.$(".em-swimlane-event").each(function (index) { + var offset = Ember.$(this).offset(); + + if(mouseEvent.clientX >= offset.left - BUBBLE_RADIUS && + mouseEvent.clientX <= offset.left + BUBBLE_RADIUS && + mouseEvent.clientY >= offset.top - BUBBLE_RADIUS && + mouseEvent.clientY <= offset.top + BUBBLE_RADIUS) { + events.push(normalizedEvents[index]); + } + }); + + if(events.length) { + options.events = events; + } + } + + this.sendAction("showTooltip", type, process, options); + }, + hideTooltip: function(type, process, options) { + this.sendAction("hideTooltip", type, process, options); + }, + click: function (type, process, options) { + this.sendAction("click", type, process, options); + } + } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-swimlane.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane.js b/tez-ui2/src/main/webapp/app/components/em-swimlane.js index 3f22c50..c05461f 100644 --- a/tez-ui2/src/main/webapp/app/components/em-swimlane.js +++ b/tez-ui2/src/main/webapp/app/components/em-swimlane.js @@ -44,6 +44,15 @@ export default Ember.Component.extend({ eventBars: [], + tooltipContents: null, + + zoom: 100, + + didInsertElement: Ember.observer("zoom", function () { + var zoom = this.get("zoom"); + this.$(".zoom-panel").css("width", `${zoom}%`); + }), + timeWindow: Ember.computed("startTime", "endTime", function () { return Math.max(0, this.get("endTime") - this.get("startTime")); }), @@ -111,6 +120,18 @@ export default Ember.Component.extend({ }); return Ember.A(normalizedProcesses); - }) + }), + + actions: { + showTooltip: function (type, process, options) { + this.set("tooltipContents", process.getTooltipContents(type, options)); + }, + hideTooltip: function () { + this.set("tooltipContents", null); + }, + click: function (type, process, options) { + this.sendAction("click", type, process, options); + } + } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/components/em-tooltip.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/components/em-tooltip.js b/tez-ui2/src/main/webapp/app/components/em-tooltip.js new file mode 100644 index 0000000..093ca3d --- /dev/null +++ b/tez-ui2/src/main/webapp/app/components/em-tooltip.js @@ -0,0 +1,158 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import Ember from 'ember'; + +const TIP_PADDING = 10, // As in em-tooltip.css + FADE_TIME = 150; + +export default Ember.Component.extend({ + + title: null, + description: null, + properties: null, + contents: null, + + classNames: ["em-tooltip"], + classNameBindings: ["aboveOrBelow"], + + x: 0, + y: 0, + + _contents: null, + show: false, + aboveOrBelow: null, + + window: null, + tip: null, + bubbles: null, + + _contentObserver: Ember.on("init", Ember.observer("title", "description", "properties", "contents", function () { + var contents, + tip = this.get("tip"); + + if(this.get("title") || this.get("description") || this.get("properties")){ + contents = [{ + title: this.get("title"), + description: this.get("description"), + properties: this.get("properties"), + }]; + } + else if(Array.isArray(this.get("contents"))){ + contents = this.get("contents"); + } + + this.set("show", false); + if(contents) { + if(tip) { + tip.hide(); + } + this.set("_contents", contents); + + Ember.run.later(this, function () { + this.set("bubbles", this.$(".bubble")); + this.set("show", true); + this.renderTip(); + }); + } + else if(tip){ + tip.stop(true).fadeOut(FADE_TIME); + } + })), + + didInsertElement: function () { + this.setProperties({ + window: Ember.$(window), + tip: this.$(), + }); + Ember.$(document).on("mousemove", this, this.onMouseMove); + }, + + willDestroyElement: function () { + Ember.$(document).off("mousemove", this.onMouseMove); + }, + + onMouseMove: function (event) { + event.data.setProperties({ + x: event.clientX, + y: event.clientY + }); + + if(Ember.get(event, "data.tip")) { + event.data.renderTip(); + } + }, + + getBubbleOffset: function (x, bubbleElement, winWidth) { + var bubbleWidth = bubbleElement.width(), + bubbleOffset = (bubbleWidth - TIP_PADDING) >> 1; + + if(bubbleWidth < 0) { + bubbleWidth = 0; + } + + if(x - bubbleOffset < 0) { + bubbleOffset = x; + } + else if(x + TIP_PADDING + bubbleOffset > winWidth) { + bubbleOffset = x - (winWidth - bubbleWidth); + } + + return -bubbleOffset; + }, + + renderTip: function () { + if(this.get("show")) { + let x = this.get("x"), + y = this.get("y"), + + winHeight = this.get("window").height(), + winWidth = this.get("window").width(), + + showAbove = y < (winHeight >> 1), + + that = this, + tip = this.get("tip"); + + if(!showAbove) { + y -= tip.height(); + this.set("aboveOrBelow", "below"); + } + else { + this.set("aboveOrBelow", "above"); + } + + tip.css({ + left: `${x}px`, + top: `${y}px`, + }); + + tip.fadeIn({ + duration: FADE_TIME, + start: function () { + that.get("bubbles").each(function () { + var bubble = Ember.$(this), + bubbleOffset = that.getBubbleOffset(x, bubble, winWidth); + bubble.css("left", `${bubbleOffset}px`); + }); + } + }); + } + } + +}); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js b/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js index 1699708..cf69e1f 100644 --- a/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js +++ b/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js @@ -25,32 +25,96 @@ import VertexProcess from '../../utils/vertex-process'; import fullscreen from 'em-tgraph/utils/fullscreen'; export default MultiTableController.extend({ + + zoom: 100, + breadcrumbs: [{ text: "Vertex Swimlane", routeName: "dag.swimlane", }], - columns: ColumnDefinition.make([]), - - actions: { - toggleFullscreen: function () { - var swimlaneElement = Ember.$(".swimlane-page")[0]; - if(swimlaneElement){ - fullscreen.toggle(swimlaneElement); - } + columns: ColumnDefinition.make([{ + id: 'entityID', + headerTitle: 'Vertex Id', + contentPath: 'entityID' + },{ + id: 'status', + headerTitle: 'Status', + contentPath: 'status', + },{ + id: 'progress', + headerTitle: 'Progress', + contentPath: 'progress', + cellDefinition: { + type: 'number', + format: '0%' + } + },{ + id: 'startTime', + headerTitle: 'Start Time', + contentPath: 'startTime', + cellDefinition: { + type: 'date' + } + },{ + id: 'endTime', + headerTitle: 'End Time', + contentPath: 'endTime', + cellDefinition: { + type: 'date' + } + },{ + id: 'duration', + headerTitle: 'Duration', + contentPath: 'duration', + cellDefinition: { + type: 'duration' } - }, + },{ + id: 'firstTaskStartTime', + headerTitle: 'First Task Start Time', + contentPath: 'firstTaskStartTime', + cellDefinition: { + type: 'date' + } + },{ + id: 'totalTasks', + headerTitle: 'Tasks', + contentPath: 'totalTasks', + },{ + id: 'succeededTasks', + headerTitle: 'Succeeded Tasks', + contentPath: 'succeededTasks', + },{ + id: 'runningTasks', + headerTitle: 'Running Tasks', + contentPath: 'runningTasks', + },{ + id: 'pendingTasks', + headerTitle: 'Pending Tasks', + contentPath: 'pendingTasks', + },{ + id: 'processorClassName', + headerTitle: 'Processor Class', + contentPath: 'processorClassName', + }]), processes: Ember.computed("model", function () { var processes = [], processHash = {}, - dagPlanEdges = this.get("model.firstObject.dag.edges"); + dagPlanEdges = this.get("model.firstObject.dag.edges"), + + that = this, + getVisibleProps = function () { + return that.get("visibleColumns"); + }; // Create process instances for each vertices this.get("model").forEach(function (vertex) { var process = VertexProcess.create({ vertex: vertex, + getVisibleProps: getVisibleProps, blockers: Ember.A() }); processHash[vertex.get("name")] = process; @@ -74,5 +138,17 @@ export default MultiTableController.extend({ }, { fromEvent: "BLOCKING_VERTICES_COMPLETE", toEvent: "VERTEX_TASK_FINISH", - }] + }], + + actions: { + toggleFullscreen: function () { + var swimlaneElement = Ember.$(".swimlane-page")[0]; + if(swimlaneElement){ + fullscreen.toggle(swimlaneElement); + } + }, + click: function (type, process) { + this.transitionToRoute('vertex.index', process.get('vertex.entityID')); + } + } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/styles/app.less ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/styles/app.less b/tez-ui2/src/main/webapp/app/styles/app.less index 0202486..7275650 100644 --- a/tez-ui2/src/main/webapp/app/styles/app.less +++ b/tez-ui2/src/main/webapp/app/styles/app.less @@ -30,6 +30,7 @@ @import "caller-info"; @import "date-formatter"; @import "em-swimlane"; +@import "em-tooltip"; // Modals @import "column-selector"; http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/styles/em-swimlane.less ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/styles/em-swimlane.less b/tez-ui2/src/main/webapp/app/styles/em-swimlane.less index a982712..2deb4db 100644 --- a/tez-ui2/src/main/webapp/app/styles/em-swimlane.less +++ b/tez-ui2/src/main/webapp/app/styles/em-swimlane.less @@ -28,10 +28,13 @@ border-right: 1px solid @border-color; } .process-visuals { + .force-scrollbar; + position: absolute; left: 100px; right: 0px; top: 0px; + overflow: auto; } } @@ -51,9 +54,11 @@ position: relative; height: 30px; - margin-left: 10px; + margin: 0px 10px; - cursor: pointer; + .process-line, .event-bar, .event-bubble { + cursor: pointer; + } .base-line { position: relative; @@ -63,7 +68,7 @@ border-top: 1px dotted @border-color; } - .event-window-line { + .process-line { position: absolute; top: unit(unit(@process-height) * 0.5 - 1, get-unit(@process-height)); height: 3px; @@ -78,48 +83,46 @@ border: 1px solid; margin-right: -1px; } -} -.em-swimlane-event { - position: absolute; - top: unit(unit(@process-height) * 0.5, get-unit(@process-height)); - - .event-line { + .em-swimlane-event { position: absolute; - top: -9px; - height: 18px; - border-left: 1px solid; - } + top: unit(unit(@process-height) * 0.5, get-unit(@process-height)); - .event-bubble { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - - -webkit-transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s; /* Safari */ - transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s; - transition-timing-function: cubic-bezier(1.44); - - border-radius: 7px; - border: 0px solid; - background-color: white; - } -} + .event-line { + position: absolute; + top: -9px; + height: 18px; + border-left: 1px solid; + } -.em-swimlane-blocking-event { - position: absolute; - top: unit(unit(@process-height) * 0.5, get-unit(@process-height)); + .event-bubble { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + + -webkit-transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s; /* Safari */ + transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s; + transition-timing-function: cubic-bezier(1.44); + + border-radius: 7px; + border: 0px solid; + background-color: white; + } + } - .event-line { + .em-swimlane-blocking-event { position: absolute; - top: 0px; - border-left: 1px solid; + top: unit(unit(@process-height) * 0.5, get-unit(@process-height)); + + .event-line { + position: absolute; + top: 0px; + border-left: 1px solid; + } } -} -.em-swimlane-process-visual { &:hover { .event-bubble { top: -7px; http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/styles/em-tooltip.less ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/styles/em-tooltip.less b/tez-ui2/src/main/webapp/app/styles/em-tooltip.less new file mode 100644 index 0000000..ab2a19e --- /dev/null +++ b/tez-ui2/src/main/webapp/app/styles/em-tooltip.less @@ -0,0 +1,117 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +.em-tooltip { + .no-select; + .no-mouse; + + position: fixed; + width: 820px; //2 * (td width + padding) + + top: 10px; + left: 20px; + + .bubble-container { + margin-bottom: 5px; + + .bubble { + display: inline-block; + max-width: 820px; + margin-left: -11px; // Border radius + arrow margin-left + + position: relative; + padding: 10px; + + font-family: helvetica; + background: rgba(0, 0, 0, 0.8); + color: #fff; + border-radius: 5px; + + .tip-title, .tip-desc, .tip-props { + border-top: 1px solid rgba(255, 255, 255, 0.4); + text-align: center; + + padding: 0px 2px; + + &:first-child { + border-top: none; + } + } + + .tip-title { + font-size: 1.1em; + } + + .tip-props { + table { + display: inline; + table-layout:fixed; + + td { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + max-width: 400px; + + text-align: right; + } + td:nth-child(1) { + padding-right: 10px; + text-align: left; + } + td:nth-child(2) { + text-align: right; + padding-left: 10px; + border-left: 1px solid rgba(255, 255, 255, 0.4); + } + } + } + } + } + + &.below:after, &.above:before { + display: block; + box-sizing: border-box; + + font-size: 12px; + line-height: 9px; + + color: rgba(0, 0, 0, 0.8); + margin-left: -6px; // Half of font size + } + + &.above { + margin-top: 20px; + + &:before { + margin-bottom: -2px; + content: "\25B2"; + } + } + + &.below { + .bubble-container { + margin-top: 5px; + margin-bottom: 0px; + } + + &:after { + content: "\25BC"; + } + } +} http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/styles/swimlane-page.less ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/styles/swimlane-page.less b/tez-ui2/src/main/webapp/app/styles/swimlane-page.less index e31371f..c9ae374 100644 --- a/tez-ui2/src/main/webapp/app/styles/swimlane-page.less +++ b/tez-ui2/src/main/webapp/app/styles/swimlane-page.less @@ -41,6 +41,23 @@ } } + .zoom-range { + .no-wrap; + display: inline-block; + width: 300px; + + margin-right: 5px; + padding-right: 5px; + border-right: 1px solid @border-color; + + input { + width: 200px; + display: inline-block; + margin-top: 5px; + vertical-align: text-bottom; + } + } + .fa-compress { display: none; } http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs index 9b6330f..e5ddfa9 100644 --- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs +++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs @@ -17,4 +17,4 @@ }} <div class="event-line"></div> -<div class="event-bubble" {{action "showTooltip" on="mouseEnter"}}></div> \ No newline at end of file +<div class="event-bubble"></div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-line.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-line.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-line.hbs new file mode 100644 index 0000000..bd790fa --- /dev/null +++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-line.hbs @@ -0,0 +1,19 @@ +{{! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. +}} + +<div class="process-line"></div> http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs index 6e4603d..cbb025c 100644 --- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs +++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs @@ -17,9 +17,23 @@ }} <div class="base-line"></div> -<div class="event-window-line"></div> +{{em-swimlane-process-line + process=process + startEvent=startEvent + endEvent=endEvent + showTooltip="showTooltip" + hideTooltip="hideTooltip" + click="click" +}} {{#each process.blocking as |blocking|}} - {{em-swimlane-blocking-event process=process blocking=blocking events=normalizedEvents}} + {{em-swimlane-blocking-event + process=process + blocking=blocking + events=normalizedEvents + showTooltip="showTooltip" + hideTooltip="hideTooltip" + click="click" + }} {{/each}} {{#each eventBars as |bar index|}} {{em-swimlane-event-bar @@ -27,8 +41,18 @@ bar=bar barIndex=index bars=eventBars - process=process}} + process=process + showTooltip="showTooltip" + hideTooltip="hideTooltip" + click="click" + }} {{/each}} {{#each normalizedEvents as |event|}} - {{em-swimlane-event process=process event=event}} + {{em-swimlane-event + process=process + event=event + showTooltip="showTooltip" + hideTooltip="hideTooltip" + click="click" + }} {{/each}} http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs index a4777f0..ad0cbe2 100644 --- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs +++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs @@ -18,17 +18,27 @@ <div class="process-names"> {{#each normalizedProcesses as |process|}} - {{em-swimlane-process-name process=process definition=processDefinition}} - {{/each}} -</div><div class="process-visuals"> - {{#each normalizedProcesses as |process|}} - {{em-swimlane-process-visual + {{em-swimlane-process-name process=process - definition=processDefinition - eventBars=eventBars - startTime=startTime - endTime=endTime - timeWindow=timeWindow + click="click" }} {{/each}} +</div><div class="process-visuals"> + <div class="zoom-panel"> + {{#each normalizedProcesses as |process|}} + {{em-swimlane-process-visual + process=process + definition=processDefinition + eventBars=eventBars + startTime=startTime + endTime=endTime + timeWindow=timeWindow + showTooltip="showTooltip" + hideTooltip="hideTooltip" + click="click" + }} + {{/each}} + </div> </div> + +{{em-tooltip contents=tooltipContents}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/components/em-tooltip.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-tooltip.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-tooltip.hbs new file mode 100644 index 0000000..65f33db --- /dev/null +++ b/tez-ui2/src/main/webapp/app/templates/components/em-tooltip.hbs @@ -0,0 +1,54 @@ +{{! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. +}} + +{{#each _contents as |content|}} + + <div class="bubble-container"> + <div class="bubble"> + {{#if content.title}}{{show_}} + <div class="tip-title">{{content.title}}</div> + {{/if}} + {{#if content.description}} + <div class="tip-desc">{{content.description}}</div> + {{/if}} + {{#if content.properties}} + <div class="tip-props"> + <table> + {{#each content.properties as |prop|}} + <tr> + <td> + {{prop.name}} + </td> + <td> + {{txt prop.value + type=prop.type + format=prop.format + timeZone=prop.timeZone + valueFormat=prop.valueFormat + valueTimeZone=prop.valueTimeZone + valueUnit=prop.valueUnit}} + </td> + </tr> + {{/each}} + </table> + </div> + {{/if}} + </div> + </div> + +{{/each}} http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs b/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs index a2b2cbe..6d9b885 100644 --- a/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs +++ b/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs @@ -19,6 +19,11 @@ {{#if loaded}} <div class="swimlane-page"> <div class="button-panel"> + <div class="zoom-range"> + {{zoom}}% + {{input type="range" value=zoom min=100 max=1000}} + </div> + <i class='fa fa-cog fa-border' {{action 'openColumnSelector'}} title="Customize vertex tooltip"></i> <i class='fa fa-expand fa-border' {{action 'toggleFullscreen'}} title="Toggle fullscreen"></i> <i class='fa fa-compress fa-border' {{action 'toggleFullscreen'}} title="Toggle fullscreen"></i> </div> @@ -29,6 +34,8 @@ eventBars=eventBars startTime=model.firstObject.dag.startTime endTime=model.firstObject.dag.endTime + zoom=zoom + click="click" }} </div> {{else}} http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/utils/process.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/utils/process.js b/tez-ui2/src/main/webapp/app/utils/process.js index eba3e72..d0f06a7 100644 --- a/tez-ui2/src/main/webapp/app/utils/process.js +++ b/tez-ui2/src/main/webapp/app/utils/process.js @@ -96,6 +96,13 @@ export default Ember.Object.extend({ parentHash[currentId] = false; return blockers; + }, + + getTooltipContents: function (type/*, options*/) { + return [{ + title: this.get("name"), + description: "Mouse on : " + type + }]; } }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/app/utils/vertex-process.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/utils/vertex-process.js b/tez-ui2/src/main/webapp/app/utils/vertex-process.js index e48532d..b99c822 100644 --- a/tez-ui2/src/main/webapp/app/utils/vertex-process.js +++ b/tez-ui2/src/main/webapp/app/utils/vertex-process.js @@ -36,6 +36,8 @@ export default Process.extend({ blockingEventName: "VERTEX_FINISHED", + getVisibleProps: null, + events: Ember.computed( "[email protected]", "vertex.firstTaskStartTime", @@ -45,7 +47,7 @@ export default Process.extend({ var events = this.get("vertex.events").map(function (event) { return { name: event.eventtype, - test: EVENT_TEXTS[event.eventtype], + text: EVENT_TEXTS[event.eventtype], time: event.timestamp }; }), @@ -57,7 +59,7 @@ export default Process.extend({ let type = "VERTEX_TASK_START"; events.push({ name: type, - test: EVENT_TEXTS[type], + text: EVENT_TEXTS[type], time: firstTaskStartTime }); } @@ -66,7 +68,7 @@ export default Process.extend({ let type = "VERTEX_TASK_FINISH"; events.push({ name: type, - test: EVENT_TEXTS[type], + text: EVENT_TEXTS[type], time: lastTaskFinishTime }); } @@ -75,7 +77,7 @@ export default Process.extend({ let type = "BLOCKING_VERTICES_COMPLETE"; events.push({ name: type, - test: EVENT_TEXTS[type], + text: EVENT_TEXTS[type], time: unblockTime }); } @@ -106,4 +108,45 @@ export default Process.extend({ return time; }), + getTooltipContents: function (type, options) { + var contents, + that = this; + + switch(type) { + case "event-bar": + case "process-line": + let properties = this.getVisibleProps().map(function (definition) { + return { + name: definition.get("headerTitle"), + value: that.get("vertex").get(definition.get("contentPath")), + type: Ember.get(definition, "cellDefinition.type"), + format: Ember.get(definition, "cellDefinition.format") + }; + }); + + contents = [{ + title: this.get("name"), + properties: properties + }]; + break; + case "event": + contents = options.events.map(function (event) { + return { + title: event.text, + properties: [{ + name: "Type", + value: event.name, + }, { + name: "Time", + value: event.time, + type: "date" + }] + }; + }); + break; + } + + return contents; + } + }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-line-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-line-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-line-test.js new file mode 100644 index 0000000..0dd8ead --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-line-test.js @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +import wait from 'ember-test-helpers/wait'; +import Ember from 'ember'; + +import Process from 'tez-ui/utils/process'; + +moduleForComponent('em-swimlane-process-line', 'Integration | Component | em swimlane process line', { + integration: true +}); + +test('Basic creation test', function(assert) { + this.set("process", Process.create()); + + this.render(hbs`{{em-swimlane-process-line process=process}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#em-swimlane-process-line process=process}} + template block text + {{/em-swimlane-process-line}} + `); + + assert.equal(this.$().text().trim(), ''); +}); + +test('start-end event test', function(assert) { + var startEvent = Ember.Object.create({ + pos: 50 + }), + endEvent = Ember.Object.create({ + pos: 70 + }); + + this.set("process", Process.create()); + this.set("startEvent", startEvent); + this.set("endEvent", endEvent); + + this.render(hbs`{{em-swimlane-process-line process=process startEvent=startEvent endEvent=endEvent}}`); + + return wait().then(() => { + assert.equal(this.$(".process-line").eq(0).attr("style").trim(), "left: 50%; right: 30%;", "process-line"); + }); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js index ffc7b56..4eb6b1b 100644 --- a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js +++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js @@ -60,11 +60,10 @@ test('Events test', function(assert) { return wait().then(() => { var events = this.$(".em-swimlane-event"); - assert.equal(events.length, 2); assert.equal(events.eq(0).attr("style").trim(), "left: 50%;", "em-swimlane-event 1 left"); assert.equal(events.eq(1).attr("style").trim(), "left: 70%;", "em-swimlane-event 2 left"); - assert.equal(this.$(".event-window-line").eq(0).attr("style").trim(), "left: 50%; right: 30%;", "event-window-line"); + assert.equal(this.$(".process-line").eq(0).attr("style").trim(), "left: 50%; right: 30%;", "process-line"); }); }); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js index 59e543d..e0ab7c7 100644 --- a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js +++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js @@ -84,3 +84,10 @@ test('Normalization (Blocker based sorting) test - On a graph', function(assert) assert.equal(names.eq(3).text().trim(), p3.name); assert.equal(names.eq(4).text().trim(), p5.name); }); + +test('Zoom test', function(assert) { + this.set("processes", [Process.create()]); + + this.render(hbs`{{em-swimlane processes=processes zoom=500}}`); + assert.equal(this.$(".zoom-panel").attr("style").trim(), "width: 500%;"); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/integration/components/em-tooltip-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-tooltip-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-tooltip-test.js new file mode 100644 index 0000000..73a957b --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/integration/components/em-tooltip-test.js @@ -0,0 +1,80 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('em-tooltip', 'Integration | Component | em tooltip', { + integration: true +}); + +test('Basic creation test', function(assert) { + + this.render(hbs`{{em-tooltip}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#em-tooltip}} + template block text + {{/em-tooltip}} + `); + + assert.equal(this.$().text().trim(), ''); +}); + +test('Title test', function(assert) { + this.set("title", "TestTitle"); + this.render(hbs`{{em-tooltip title=title}}`); + + assert.equal(this.$().text().trim(), 'TestTitle'); +}); + +test('Description test', function(assert) { + this.set("desc", "TestDesc"); + this.render(hbs`{{em-tooltip description=desc}}`); + + assert.equal(this.$().text().trim(), 'TestDesc'); +}); + +test('Properties test', function(assert) { + this.set("properties", [{ + name: "p1", value: "v1" + }, { + name: "p2", value: "v2" + }]); + this.render(hbs`{{em-tooltip properties=properties}}`); + + assert.equal(this.$("tr").length, 2); +}); + +test('Contents test', function(assert) { + this.set("contents", [{ + title: "p1", + properties: [{}, {}] + }, { + title: "p2", + properties: [{}, {}, {}] + }]); + + this.render(hbs`{{em-tooltip contents=contents}}`); + + assert.equal(this.$(".bubble").length, 2); + assert.equal(this.$("tr").length, 2 + 3); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js b/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js index ffab868..6069d7b 100644 --- a/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js +++ b/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js @@ -29,6 +29,7 @@ test('Basic creation test', function(assert) { assert.ok(process.startEvent); assert.ok(process.endEvent); assert.ok(process.getAllBlockers); + assert.ok(process.getTooltipContents); }); test('getColor test', function(assert) { http://git-wip-us.apache.org/repos/asf/tez/blob/182c9970/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js b/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js index 85c0d0f..05ffc40 100644 --- a/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js +++ b/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js @@ -34,6 +34,8 @@ test('Basic creation test', function(assert) { assert.ok(process.events); assert.ok(process.unblockTime); + + assert.ok(process.getTooltipContents); }); test('unblockTime test', function(assert) { @@ -96,3 +98,81 @@ test('events test', function(assert) { assert.equal(process.get("events.length"), 5); assert.equal(process.get("events.4.time"), 30); }); + +test('getTooltipContents-event test', function(assert) { + var process = VertexProcess.create(); + + var eventTooltip = process.getTooltipContents("event", { + events: [{ + text: "TestEventText1", + name: "TestEventName1", + time: 10 + }, { + text: "TestEventText2", + name: "TestEventName2", + time: 20 + }] + }); + + assert.equal(eventTooltip.length, 2); + + assert.equal(eventTooltip[0].title, "TestEventText1"); + assert.equal(eventTooltip[0].properties.length, 2); + assert.equal(eventTooltip[0].properties[0].name, "Type"); + assert.equal(eventTooltip[0].properties[0].value, "TestEventName1"); + assert.equal(eventTooltip[0].properties[1].name, "Time"); + assert.equal(eventTooltip[0].properties[1].value, 10); + + assert.equal(eventTooltip[1].title, "TestEventText2"); + assert.equal(eventTooltip[1].properties.length, 2); + assert.equal(eventTooltip[1].properties[0].name, "Type"); + assert.equal(eventTooltip[1].properties[0].value, "TestEventName2"); + assert.equal(eventTooltip[1].properties[1].name, "Time"); + assert.equal(eventTooltip[1].properties[1].value, 20); + +}); + +test('getTooltipContents-process test', function(assert) { + var process = VertexProcess.create({ + name: "TestName", + vertex: Ember.Object.create({ + prop1: "val1", + prop2: "val2", + prop3: "val3" + }), + getVisibleProps: function () { + return [Ember.Object.create({ + id: "prop1", + headerTitle: "Prop 1", + contentPath: "prop1" + }), Ember.Object.create({ + id: "prop2", + headerTitle: "Prop 2", + contentPath: "prop2" + })]; + } + }); + + var processTooltip = process.getTooltipContents("event-bar")[0]; + assert.equal(processTooltip.title, "TestName"); + + assert.equal(processTooltip.properties.length, 2); + + assert.equal(processTooltip.properties[0].name, "Prop 1"); + assert.equal(processTooltip.properties[0].value, "val1"); + + assert.equal(processTooltip.properties[1].name, "Prop 2"); + assert.equal(processTooltip.properties[1].value, "val2"); + + processTooltip = process.getTooltipContents("process-line")[0]; + assert.equal(processTooltip.title, "TestName"); + + assert.equal(processTooltip.properties.length, 2); + + assert.equal(processTooltip.properties[0].name, "Prop 1"); + assert.equal(processTooltip.properties[0].value, "val1"); + + assert.equal(processTooltip.properties[1].name, "Prop 2"); + assert.equal(processTooltip.properties[1].value, "val2"); + +});
