You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/04/26 12:19:00 UTC
[29/31] tez git commit: TEZ-3227. Tez UI: Replace UI1 with UI2 (sree)
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/em-swimlane.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/em-swimlane.js b/tez-ui/src/main/webapp/app/components/em-swimlane.js
new file mode 100644
index 0000000..0c8b589
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/em-swimlane.js
@@ -0,0 +1,171 @@
+/**
+ * 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';
+
+import Processor from '../utils/processor';
+import Process from '../utils/process';
+
+export default Ember.Component.extend({
+
+ classNames: ["em-swimlane"],
+
+ processes: [],
+ processor: Processor.create(),
+
+ nameComponent: "em-swimlane-process-name",
+ visualComponent: "em-swimlane-process-visual",
+
+ tooltipContents: null,
+ focusedProcess: null,
+ scroll: 0,
+
+ consolidate: false,
+
+ zoom: 100,
+
+ startTime: Ember.computed("processes.@each.startEvent", function () {
+ var startTime = this.get("processes.0.startEvent.time");
+ this.get("processes").forEach(function (process) {
+ var time = process.get("startEvent.time");
+ if(startTime > time){
+ startTime = time;
+ }
+ });
+ return startTime;
+ }),
+ endTime: Ember.computed("processes.@each.endEvent", function () {
+ var endTime = this.get("processes.0.endEvent.time");
+ this.get("processes").forEach(function (process) {
+ var time = process.get("endEvent.time");
+ if(endTime < time){
+ endTime = time;
+ }
+ });
+ return endTime;
+ }),
+
+ processorSetup: Ember.on("init", Ember.observer("startTime", "endTime", "processes.length", function () {
+ this.get("processor").setProperties({
+ startTime: this.get("startTime"),
+ endTime: this.get("endTime"),
+ processCount: this.get("processes.length")
+ });
+ })),
+
+ didInsertElement: function () {
+ this.onZoom();
+ this.listenScroll();
+ },
+
+ onZoom: Ember.observer("zoom", function () {
+ var zoom = this.get("zoom");
+ this.$(".zoom-panel").css("width", `${zoom}%`);
+ }),
+
+ listenScroll: function () {
+ var that = this;
+ this.$(".process-visuals").scroll(function () {
+ that.set("scroll", Ember.$(this).scrollLeft());
+ });
+ },
+
+ willDestroy: function () {
+ // Release listeners
+ },
+
+ normalizedProcesses: Ember.computed("processes.@each.blockers", function () {
+ var processes = this.get("processes"),
+ normalizedProcesses,
+ idHash = {},
+ containsBlockers = false,
+ processor = this.get("processor");
+
+ // Validate and reset blocking
+ processes.forEach(function (process) {
+ if(!(process instanceof Process)) {
+ Ember.Logger.error("em-swimlane : Unknown type, must be of type Process");
+ }
+
+ if(process.get("blockers.length")) {
+ containsBlockers = true;
+ }
+ process.set("blocking", Ember.A());
+ });
+
+ if(containsBlockers) {
+ normalizedProcesses = [];
+
+ // Recreate blocking list
+ processes.forEach(function (process) {
+ var blockers = process.get("blockers");
+ if(blockers) {
+ blockers.forEach(function (blocker) {
+ blocker.get("blocking").push(process);
+ });
+ }
+ });
+
+ // Give an array of the processes in blocking order
+ processes.forEach(function (process) {
+ if(process.get("blocking.length") === 0) { // The root processes
+ normalizedProcesses.push(process);
+ normalizedProcesses.push.apply(normalizedProcesses, process.getAllBlockers());
+ }
+ });
+ normalizedProcesses.reverse();
+ normalizedProcesses = normalizedProcesses.filter(function (process, index) {
+ // Filters out the recurring processes in the list (after graph traversal), we just
+ // need the top processes
+ var id = process.get("_id");
+ if(idHash[id] === undefined) {
+ idHash[id] = index;
+ }
+ return idHash[id] === index;
+ });
+ }
+ else {
+ normalizedProcesses = processes;
+ }
+
+ // Set process colors & index
+ normalizedProcesses.forEach(function (process, index) {
+ process.setProperties({
+ color: processor.createProcessColor(index),
+ index: index
+ });
+ });
+
+ return Ember.A(normalizedProcesses);
+ }),
+
+ actions: {
+ showTooltip: function (type, process, options) {
+ this.set("tooltipContents", process.getTooltipContents(type, options));
+ this.set("focusedProcess", process);
+ },
+ hideTooltip: function () {
+ this.set("tooltipContents", null);
+ this.set("focusedProcess", null);
+ },
+ click: function (type, process, options) {
+ this.sendAction("click", type, process, options);
+ }
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/em-table-status-cell.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/em-table-status-cell.js b/tez-ui/src/main/webapp/app/components/em-table-status-cell.js
new file mode 100644
index 0000000..7751719
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/em-table-status-cell.js
@@ -0,0 +1,36 @@
+/**
+ * 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({
+
+ content: null,
+
+ classNames: ["em-table-status-cell"],
+
+ statusName: Ember.computed("content", function () {
+ var status = this.get("content");
+
+ if(status) {
+ status = status.toString().dasherize();
+ status = "status-" + status;
+ }
+ return status;
+ }),
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/em-tooltip.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/em-tooltip.js b/tez-ui/src/main/webapp/app/components/em-tooltip.js
new file mode 100644
index 0000000..33e30cb
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/em-tooltip.js
@@ -0,0 +1,159 @@
+/**
+ * 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 = 15, // 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: ["arrowPos"],
+
+ x: 0,
+ y: 0,
+
+ _contents: null,
+ show: false,
+ arrowPos: 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 = Math.max(bubbleElement.width(), 0),
+ bubbleOffset = bubbleWidth >> 1;
+
+ if(x - bubbleOffset - TIP_PADDING < 0) {
+ bubbleOffset = x - TIP_PADDING;
+ }
+ else if(x + TIP_PADDING + bubbleOffset > winWidth) {
+ bubbleOffset = x - (winWidth - bubbleWidth) + TIP_PADDING;
+ }
+
+ 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(x > TIP_PADDING && x < winWidth - TIP_PADDING) {
+ if(!showAbove) {
+ y -= tip.height();
+ this.set("arrowPos", "below");
+ }
+ else {
+ this.set("arrowPos", "above");
+ }
+ }
+ else {
+ this.set("arrowPos", null);
+ }
+
+ 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/13132ec7/tez-ui/src/main/webapp/app/components/error-bar.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/error-bar.js b/tez-ui/src/main/webapp/app/components/error-bar.js
new file mode 100644
index 0000000..1086010
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/error-bar.js
@@ -0,0 +1,109 @@
+/**
+ * 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 DISPLAY_TIME = 30 * 1000;
+
+export default Ember.Component.extend({
+
+ error: null,
+
+ visible: false,
+ detailsAvailable: false,
+
+ classNames: ['error-bar'],
+ classNameBindings: ['visible', 'detailsAvailable'],
+
+ code: null,
+ message: null,
+ details: null,
+ stack: null,
+
+ showDetails: false,
+
+ displayTimerId: 0,
+
+ _errorObserver: Ember.observer("error", function () {
+ var error = this.get("error"),
+
+ code = Ember.get(error, "errors.0.status"),
+ title = Ember.get(error, "errors.0.title"),
+ message = error.message || "Error",
+ details = Ember.get(error, "errors.0.detail") || "",
+ stack = error.stack,
+ lineEndIndex = Math.min(message.indexOf('\n'), message.indexOf('<br'));
+
+ if(code === "0") {
+ code = "";
+ }
+
+ if(title) {
+ message += ". " + title;
+ }
+
+ if(lineEndIndex > 0) {
+ if(details) {
+ details = "\n" + details;
+ }
+ details = message.substr(lineEndIndex) + details;
+ message = message.substr(0, lineEndIndex);
+ }
+
+ if(details) {
+ details += "\n";
+ }
+
+ if(error) {
+ this.setProperties({
+ code: code,
+ message: message,
+ details: details,
+ stack: stack,
+
+ detailsAvailable: !!(details || stack),
+ visible: true
+ });
+
+ this.clearTimer();
+ this.set("displayTimerId", setTimeout(this.close.bind(this), DISPLAY_TIME));
+ }
+ else {
+ this.close();
+ }
+ }),
+
+ clearTimer: function () {
+ clearTimeout(this.get("displayTimerId"));
+ },
+ close: function () {
+ this.set("visible", false);
+ this.clearTimer();
+ },
+
+ actions: {
+ toggleDetailsDisplay: function () {
+ this.toggleProperty("showDetails");
+ this.clearTimer();
+ },
+ close: function () {
+ this.close();
+ }
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/stats-link.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/stats-link.js b/tez-ui/src/main/webapp/app/components/stats-link.js
new file mode 100644
index 0000000..0fb56df
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/stats-link.js
@@ -0,0 +1,33 @@
+/**
+ * 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({
+ value: null,
+ routeName: null,
+ statsType: null,
+
+ searchText: Ember.computed.oneWay("statsType"),
+ _statsType: Ember.computed("statsType", function () {
+ var type = this.get("statsType");
+ if(type) {
+ return Ember.String.capitalize(type.toLowerCase());
+ }
+ })
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/tab-n-refresh.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/tab-n-refresh.js b/tez-ui/src/main/webapp/app/components/tab-n-refresh.js
new file mode 100644
index 0000000..6ac6454
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/tab-n-refresh.js
@@ -0,0 +1,57 @@
+/**
+ * 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({
+ init: function () {
+ this._super();
+ this.setApplication();
+ },
+
+ autoRefreshEnabled: false,
+ autoRefreshVisible: true,
+
+ setApplication: function () {
+ var application = this.get("targetObject.container").lookup('controller:application');
+ this.set("application", application);
+ },
+
+ autoRefreshObserver: Ember.observer("autoRefreshEnabled", function () {
+ this.get('targetObject').send('autoRefreshChanged', this.get("autoRefreshEnabled"));
+ }),
+
+ normalizedTabs: Ember.computed("tabs", "application.currentPath", function () {
+ var tabs = this.get("tabs") || [],
+ activeRouteName = this.get("application.currentPath");
+
+ return tabs.map(function (tab) {
+ return {
+ text: tab.text,
+ routeName: tab.routeName,
+ active: tab.routeName === activeRouteName
+ };
+ });
+ }),
+
+ actions: {
+ refresh: function () {
+ this.get('targetObject').send('reload');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/table-controls.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/table-controls.js b/tez-ui/src/main/webapp/app/components/table-controls.js
new file mode 100644
index 0000000..9923711
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/table-controls.js
@@ -0,0 +1,29 @@
+/**
+ * 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({
+ classNames: ['table-controls'],
+
+ actions: {
+ cogClicked: function () {
+ this.get('targetObject.targetObject').send('openColumnSelector');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/components/zip-download-modal.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/zip-download-modal.js b/tez-ui/src/main/webapp/app/components/zip-download-modal.js
new file mode 100644
index 0000000..c55b34e
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/components/zip-download-modal.js
@@ -0,0 +1,43 @@
+/**
+ * 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({
+ classNames: ['zip-download-modal'],
+ content: null,
+
+ _onSuccess: Ember.observer("content.downloader.succeeded", function () {
+ if(this.get("content.downloader.succeeded")) {
+ Ember.run.later(this, "close");
+ }
+ }),
+
+ close: function () {
+ Ember.$(".simple-modal").modal("hide");
+ },
+
+ actions: {
+ cancel: function () {
+ var downloader = this.get("content.downloader");
+ if(downloader) {
+ downloader.cancel();
+ }
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/abstract.js b/tez-ui/src/main/webapp/app/controllers/abstract.js
new file mode 100644
index 0000000..863a63f
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/abstract.js
@@ -0,0 +1,50 @@
+/**
+ * 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';
+
+import NameMixin from '../mixins/name';
+
+export default Ember.Controller.extend(NameMixin, {
+ // Must be set by inheriting classes
+ breadcrumbs: null,
+
+ // Must be set from abstract route
+ loadTime: null,
+ isLoading: false,
+
+ init: function () {
+ this._super();
+ Ember.run.later(this, "setBreadcrumbs");
+ },
+
+ loaded: Ember.computed("model", "isLoading", function () {
+ return this.get("model") && !this.get("isLoading");
+ }),
+
+ crumbObserver: Ember.observer("breadcrumbs", function () {
+ Ember.run.later(this, "setBreadcrumbs");
+ }),
+
+ setBreadcrumbs: function () {
+ var crumbs = {},
+ name = this.get("name");
+ crumbs[name] = this.get("breadcrumbs");
+ this.send("setBreadcrumbs", crumbs);
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/app.js b/tez-ui/src/main/webapp/app/controllers/app.js
new file mode 100644
index 0000000..f379e80
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/app.js
@@ -0,0 +1,44 @@
+/**
+ * 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';
+
+import ParentController from './parent';
+
+export default ParentController.extend({
+ breadcrumbs: Ember.computed("model.appID", "model.app.name", function () {
+ var name = this.get("model.app.name") || this.get("model.appID");
+
+ return [{
+ text: `Application [ ${name} ]`,
+ routeName: "app.index",
+ model: this.get("model.entityID")
+ }];
+ }),
+
+ tabs: [{
+ text: "Application Details",
+ routeName: "app.index"
+ }, {
+ text: "DAGs",
+ routeName: "app.dags"
+ }, {
+ text: "Configurations",
+ routeName: "app.configs"
+ }]
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/app/configs.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/app/configs.js b/tez-ui/src/main/webapp/app/controllers/app/configs.js
new file mode 100644
index 0000000..838abc1
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/app/configs.js
@@ -0,0 +1,60 @@
+/*global more*/
+/**
+ * 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';
+
+import TableController from '../table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+var MoreObject = more.Object;
+
+export default TableController.extend({
+ searchText: "tez",
+
+ breadcrumbs: [{
+ text: "Configurations",
+ routeName: "app.configs",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'configName',
+ headerTitle: 'Configuration Name',
+ contentPath: 'configName',
+ }, {
+ id: 'configValue',
+ headerTitle: 'Configuration Value',
+ contentPath: 'configValue',
+ }]),
+
+ configs: Ember.computed("model.configs", function () {
+ var configs = this.get("model.configs"),
+ configRows = [];
+
+ if(configs) {
+ MoreObject.forEach(configs, function (key, value) {
+ configRows.push(Ember.Object.create({
+ configName: key,
+ configValue: value
+ }));
+ });
+ }
+
+ return Ember.A(configRows);
+ })
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/app/dags.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/app/dags.js b/tez-ui/src/main/webapp/app/controllers/app/dags.js
new file mode 100644
index 0000000..e0c5e68
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/app/dags.js
@@ -0,0 +1,98 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+ breadcrumbs: [{
+ text: "DAGs",
+ routeName: "app.dags",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'name',
+ headerTitle: 'Dag Name',
+ contentPath: 'name',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "dag",
+ model: row.get("entityID"),
+ text: row.get("name")
+ };
+ }
+ },{
+ id: 'entityID',
+ headerTitle: 'Id',
+ contentPath: 'entityID'
+ },{
+ id: 'submitter',
+ headerTitle: 'Submitter',
+ contentPath: 'submitter'
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'status',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ },{
+ id: 'queue',
+ headerTitle: 'Queue',
+ contentPath: 'queue'
+ },{
+ id: 'callerID',
+ headerTitle: 'Context ID',
+ contentPath: 'callerID'
+ },{
+ id: 'logs',
+ headerTitle: 'Logs',
+ contentPath: 'containerLogs',
+ cellComponentName: "em-table-linked-cell",
+ cellDefinition: {
+ target: "_blank"
+ }
+ }]),
+
+ getCounterColumns: function () {
+ return this._super().concat(this.get('env.app.tables.defaultColumns.dagCounters'));
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/app/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/app/index.js b/tez-ui/src/main/webapp/app/controllers/app/index.js
new file mode 100644
index 0000000..7f7bc78
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/app/index.js
@@ -0,0 +1,33 @@
+/**
+ * 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';
+import PageController from '../page';
+
+export default PageController.extend({
+
+ trackingURL: Ember.computed("model.appID", function () {
+ return [
+ this.get("hosts.rm"),
+ this.get("env.app.namespaces.web.rm"),
+ "app",
+ this.get("model.appID")
+ ].join("/");
+ })
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/application.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/application.js b/tez-ui/src/main/webapp/app/controllers/application.js
new file mode 100644
index 0000000..4911a16
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/application.js
@@ -0,0 +1,40 @@
+/**
+ * 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 BREADCRUMB_PREFIX = [{
+ text: "All DAGs",
+ routeName: 'application'
+}];
+
+export default Ember.Controller.extend({
+ breadcrumbs: null,
+ appError: null,
+
+ prefixedBreadcrumbs: Ember.computed("breadcrumbs", function () {
+ var prefix = BREADCRUMB_PREFIX,
+ breadcrumbs = this.get('breadcrumbs');
+
+ if(Array.isArray(breadcrumbs)) {
+ prefix = prefix.concat(breadcrumbs);
+ }
+
+ return prefix;
+ })
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/attempt.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/attempt.js b/tez-ui/src/main/webapp/app/controllers/attempt.js
new file mode 100644
index 0000000..b10fc7f
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/attempt.js
@@ -0,0 +1,56 @@
+/**
+ * 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';
+
+import ParentController from './parent';
+
+export default ParentController.extend({
+ breadcrumbs: Ember.computed("model.dag", function () {
+ var dagName = this.get("model.dag.name"),
+ vertexName = this.get("model.vertexName"),
+ taskIndex = this.get("model.taskIndex"),
+ attemptNo = this.get("model.index");
+
+ return [{
+ text: `DAG [ ${dagName} ]`,
+ routeName: "dag.index",
+ model: this.get("model.dagID")
+ },{
+ text: `Vertex [ ${vertexName} ]`,
+ routeName: "vertex.index",
+ model: this.get("model.vertexID")
+ },{
+ text: `Task [ ${taskIndex} ]`,
+ routeName: "task.index",
+ model: this.get("model.taskID")
+ },{
+ text: `Attempt [ ${attemptNo} ]`,
+ routeName: "attempt.index",
+ model: this.get("model.entityID")
+ }];
+ }),
+
+ tabs: [{
+ text: "Attempt Details",
+ routeName: "attempt.index"
+ },{
+ text: "Attempt Counters",
+ routeName: "attempt.counters"
+ }]
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/attempt/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/attempt/counters.js b/tez-ui/src/main/webapp/app/controllers/attempt/counters.js
new file mode 100644
index 0000000..1a93c80
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/attempt/counters.js
@@ -0,0 +1,26 @@
+/**
+ * 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 CountersTableController from '../counters-table';
+
+export default CountersTableController.extend({
+ breadcrumbs: [{
+ text: "Attempt Counters",
+ routeName: "attempt.counters",
+ }],
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/attempt/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/attempt/index.js b/tez-ui/src/main/webapp/app/controllers/attempt/index.js
new file mode 100644
index 0000000..9745328
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/attempt/index.js
@@ -0,0 +1,22 @@
+/**
+ * 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 PageController from '../page';
+
+export default PageController.extend({
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/counters-table.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/counters-table.js b/tez-ui/src/main/webapp/app/controllers/counters-table.js
new file mode 100644
index 0000000..42361b4
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/counters-table.js
@@ -0,0 +1,74 @@
+/*global more*/
+/**
+ * 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';
+
+import TableController from './table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+var MoreObject = more.Object;
+
+export default TableController.extend({
+ counters: Ember.A(),
+ countersCount: 0, // Because Ember.Array doesn't handle length well
+
+ columns: ColumnDefinition.make([{
+ id: 'groupName',
+ headerTitle: 'Group Name',
+ contentPath: 'groupName',
+ }, {
+ id: 'counterName',
+ headerTitle: 'Counter Name',
+ contentPath: 'counterName',
+ }, {
+ id: 'counterValue',
+ headerTitle: 'Counter Value',
+ contentPath: 'counterValue',
+ observePath: true
+ }]),
+
+ _countersObserver: Ember.observer("model.counterGroupsHash", function () {
+ var counterGroupsHash = this.get("model.counterGroupsHash"),
+ counters = this.get("counters"),
+ counterIndex = 0;
+
+ if(counterGroupsHash) {
+ MoreObject.forEach(counterGroupsHash, function (groupName, countersHash) {
+ if(countersHash) {
+ MoreObject.forEach(countersHash, function (counterName, counterValue) {
+ let counterRow = counters.get(counterIndex);
+ if(!counterRow) {
+ counterRow = Ember.Object.create();
+ counters.push(counterRow);
+ }
+
+ counterRow.setProperties({
+ groupName: groupName,
+ counterName: counterName,
+ counterValue: counterValue
+ });
+ counterIndex++;
+ });
+ }
+ });
+ }
+
+ this.set("countersCount", counterIndex);
+ })
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag.js b/tez-ui/src/main/webapp/app/controllers/dag.js
new file mode 100644
index 0000000..46200b8
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag.js
@@ -0,0 +1,56 @@
+/**
+ * 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';
+
+import ParentController from './parent';
+
+export default ParentController.extend({
+ breadcrumbs: Ember.computed("model", function () {
+ var name = this.get("model.name");
+
+ return [{
+ text: `DAG [ ${name} ]`,
+ routeName: "dag.index.index",
+ model: this.get("model.entityID")
+ }];
+ }),
+
+ tabs: [{
+ text: "DAG Details",
+ routeName: "dag.index.index"
+ }, {
+ text: "DAG Counters",
+ routeName: "dag.counters"
+ }, {
+ text: "Graphical View",
+ routeName: "dag.graphical"
+ }, {
+ text: "All Vertices",
+ routeName: "dag.vertices"
+ }, {
+ text: "All Tasks",
+ routeName: "dag.tasks"
+ }, {
+ text: "All Task Attempts",
+ routeName: "dag.attempts"
+ }, {
+ text: "Vertex Swimlane",
+ routeName: "dag.swimlane"
+ }]
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/attempts.js b/tez-ui/src/main/webapp/app/controllers/dag/attempts.js
new file mode 100644
index 0000000..9f9ba15
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/attempts.js
@@ -0,0 +1,120 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+ breadcrumbs: [{
+ text: "All Task Attempts",
+ routeName: "dag.attempts",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'index',
+ headerTitle: 'Attempt No',
+ contentPath: 'index',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "attempt",
+ model: row.get("entityID"),
+ text: row.get("index")
+ };
+ }
+ },{
+ id: 'taskIndex',
+ headerTitle: 'Task Index',
+ contentPath: 'taskIndex',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "task",
+ model: row.get("taskID"),
+ text: row.get("taskIndex")
+ };
+ }
+ },{
+ id: 'vertexName',
+ headerTitle: 'Vertex Index',
+ contentPath: 'vertexName',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "vertex",
+ model: row.get("vertexID"),
+ text: row.get("vertexName")
+ };
+ }
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'status',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ },{
+ id: 'containerID',
+ headerTitle: 'Container',
+ contentPath: 'containerID'
+ },{
+ id: 'nodeID',
+ headerTitle: 'Node',
+ contentPath: 'nodeID'
+ }, {
+ id: 'log',
+ headerTitle: 'Log',
+ contentPath: 'logURL',
+ cellComponentName: 'em-table-linked-cell',
+ cellDefinition: {
+ target: "_blank"
+ },
+ getCellContent: function (row) {
+ return [{
+ href: row.get("logURL"),
+ text: "View"
+ }, {
+ href: row.get("logURL"),
+ text: "Download",
+ download: true
+ }];
+ }
+ }])
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/counters.js b/tez-ui/src/main/webapp/app/controllers/dag/counters.js
new file mode 100644
index 0000000..c54fd7e
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/counters.js
@@ -0,0 +1,26 @@
+/**
+ * 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 CountersTableController from '../counters-table';
+
+export default CountersTableController.extend({
+ breadcrumbs: [{
+ text: "DAG Counters",
+ routeName: "dag.counters",
+ }],
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/graphical.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/graphical.js b/tez-ui/src/main/webapp/app/controllers/dag/graphical.js
new file mode 100644
index 0000000..535f32b
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/graphical.js
@@ -0,0 +1,174 @@
+/**
+ * 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';
+
+import MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+
+ columnSelectorTitle: 'Customize vertex tooltip',
+
+ breadcrumbs: [{
+ text: "Graphical View",
+ routeName: "dag.graphical",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'name',
+ headerTitle: 'Vertex Name',
+ contentPath: 'name',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "vertex",
+ model: row.get("entityID"),
+ text: row.get("name")
+ };
+ }
+ },{
+ id: 'entityID',
+ headerTitle: 'Vertex Id',
+ contentPath: 'entityID'
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'finalStatus',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ },{
+ id: 'firstTaskStartTime',
+ headerTitle: 'First Task Start Time',
+ contentPath: 'firstTaskStartTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'totalTasks',
+ headerTitle: 'Tasks',
+ contentPath: 'totalTasks',
+ },{
+ id: 'succeededTasks',
+ headerTitle: 'Succeeded Tasks',
+ contentPath: 'succeededTasks',
+ observePath: true
+ },{
+ id: 'runningTasks',
+ headerTitle: 'Running Tasks',
+ contentPath: 'runningTasks',
+ observePath: true
+ },{
+ id: 'pendingTasks',
+ headerTitle: 'Pending Tasks',
+ contentPath: 'pendingTasks',
+ observePath: true
+ },{
+ id: 'processorClassName',
+ headerTitle: 'Processor Class',
+ contentPath: 'processorClassName',
+ }]),
+
+ redirect: function (details) {
+ switch(details.type) {
+ case 'vertex':
+ this.transitionToRoute('vertex.index', details.d.get('data.entityID'));
+ break;
+ case 'task':
+ this.transitionToRoute('vertex.tasks', details.d.get('data.entityID'));
+ break;
+ case 'io':
+ break;
+ case 'input':
+ break;
+ case 'output':
+ break;
+ }
+ },
+
+ actions: {
+ entityClicked: function (details) {
+
+ /**
+ * In IE 11 under Windows 7, mouse events are not delivered to the page
+ * anymore at all after a SVG use element that was under the mouse is
+ * removed from the DOM in the event listener in response to a mouse click.
+ * See https://connect.microsoft.com/IE/feedback/details/796745
+ *
+ * This condition and related actions must be removed once the bug is fixed
+ * in all supported IE versions
+ */
+ if(this.get("env.ENV.isIE")) {
+ var pageType = details.type === "io" ? "additionals" : details.type,
+ message = `You will be redirected to ${pageType} page`;
+
+ alert(message);
+ }
+ this.redirect(details);
+ }
+ },
+
+ viewData: Ember.computed("model", function () {
+ var model = this.get("model"),
+ dag, vertices, entities;
+
+ if(!model) {
+ return {};
+ }
+
+ dag = this.get('model.firstObject.dag');
+ vertices = this.get('model.firstObject.dag.vertices') || [];
+ entities = {};
+
+ model.forEach(function (vertexData) {
+ entities[vertexData.get('name')] = vertexData;
+ });
+
+ vertices.forEach(function (vertex) {
+ vertex.data = entities[vertex.vertexName];
+ });
+
+ return {
+ vertices: vertices,
+ edges: dag.get('edges'),
+ vertexGroups: dag.get('vertexGroups')
+ };
+ })
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/index.js b/tez-ui/src/main/webapp/app/controllers/dag/index.js
new file mode 100644
index 0000000..9745328
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/index.js
@@ -0,0 +1,22 @@
+/**
+ * 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 PageController from '../page';
+
+export default PageController.extend({
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/index/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/index/index.js b/tez-ui/src/main/webapp/app/controllers/dag/index/index.js
new file mode 100644
index 0000000..2937a2b
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/index/index.js
@@ -0,0 +1,129 @@
+/**
+ * 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';
+
+import MultiTableController from '../../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+ columns: ColumnDefinition.make([{
+ id: 'name',
+ headerTitle: 'Vertex Name',
+ contentPath: 'name',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "vertex",
+ model: row.get("entityID"),
+ text: row.get("name")
+ };
+ }
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'status',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'totalTasks',
+ headerTitle: 'Total Tasks',
+ contentPath: 'totalTasks',
+ observePath: true
+ },{
+ id: 'succeededTasks',
+ headerTitle: 'Succeeded Tasks',
+ contentPath: 'succeededTasks',
+ observePath: true
+ },{
+ id: 'runningTasks',
+ headerTitle: 'Running Tasks',
+ contentPath: 'runningTasks',
+ observePath: true
+ },{
+ id: 'pendingTasks',
+ headerTitle: 'Pending Tasks',
+ contentPath: 'pendingTasks',
+ observePath: true
+ },{
+ id: 'failedTaskAttempts',
+ headerTitle: 'Failed Task Attempts',
+ contentPath: 'failedTaskAttempts',
+ observePath: true
+ },{
+ id: 'killedTaskAttempts',
+ headerTitle: 'Killed Task Attempts',
+ contentPath: 'killedTaskAttempts',
+ observePath: true
+ }]),
+
+ stats: Ember.computed("model.@each.loadTime", function () {
+ var vertices = this.get("model");
+
+ if(vertices) {
+ let succeededVertices = 0,
+ succeededTasks = 0,
+ totalTasks =0,
+
+ failedTasks = 0,
+ killedTasks = 0,
+ failedTaskAttempts = 0,
+ killedTaskAttempts = 0;
+
+ vertices.forEach(function (vertex) {
+ if(vertex.get("status") === "SUCCEEDED") {
+ succeededVertices++;
+ }
+
+ succeededTasks += vertex.get("succeededTasks");
+ totalTasks += vertex.get("totalTasks");
+
+ failedTasks += vertex.get("failedTasks");
+ killedTasks += vertex.get("killedTasks");
+
+ failedTaskAttempts += vertex.get("failedTaskAttempts");
+ killedTaskAttempts += vertex.get("killedTaskAttempts");
+ });
+
+ return {
+ succeededVertices: succeededVertices,
+ totalVertices: vertices.get("length"),
+
+ succeededTasks: succeededTasks,
+ totalTasks: totalTasks,
+
+ failedTasks: failedTasks,
+ killedTasks: killedTasks,
+
+ failedTaskAttempts: failedTaskAttempts,
+ killedTaskAttempts: killedTaskAttempts
+ };
+ }
+ }),
+
+ beforeSort: function () {
+ return true;
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/swimlane.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/swimlane.js b/tez-ui/src/main/webapp/app/controllers/dag/swimlane.js
new file mode 100644
index 0000000..259d72f
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/swimlane.js
@@ -0,0 +1,151 @@
+/**
+ * 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';
+
+import MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+import VertexProcess from '../../utils/vertex-process';
+
+import fullscreen from 'em-tgraph/utils/fullscreen';
+
+export default MultiTableController.extend({
+
+ zoom: 100,
+
+ columnSelectorTitle: 'Customize vertex tooltip',
+
+ breadcrumbs: [{
+ text: "Vertex Swimlane",
+ routeName: "dag.swimlane",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'entityID',
+ headerTitle: 'Vertex Id',
+ contentPath: 'entityID'
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'finalStatus',
+ },{
+ 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"),
+
+ 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;
+ processes.push(process);
+ });
+
+ // Add process(vertex) dependencies based on dagPlan
+ if(dagPlanEdges) {
+ dagPlanEdges.forEach(function (edge) {
+ var process = processHash[edge.outputVertexName];
+ if(process && processHash[edge.inputVertexName]) {
+ process.blockers.push(processHash[edge.inputVertexName]);
+ process.edgeHash.set(edge.inputVertexName, edge);
+ }
+ });
+ }
+
+ return Ember.A(processes);
+ }),
+
+ actions: {
+ toggleFullscreen: function () {
+ var swimlaneElement = Ember.$(".swimlane-page").get(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/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/tasks.js b/tez-ui/src/main/webapp/app/controllers/dag/tasks.js
new file mode 100644
index 0000000..113d37e
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/tasks.js
@@ -0,0 +1,82 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+ breadcrumbs: [{
+ text: "All Tasks",
+ routeName: "dag.tasks",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'index',
+ headerTitle: 'Task Index',
+ contentPath: 'index',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "task",
+ model: row.get("entityID"),
+ text: row.get("index")
+ };
+ }
+ },{
+ id: 'vertexName',
+ headerTitle: 'Vertex Name',
+ contentPath: 'vertexName',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "vertex",
+ model: row.get("vertexID"),
+ text: row.get("vertexName")
+ };
+ }
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'status',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ }])
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dag/vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dag/vertices.js b/tez-ui/src/main/webapp/app/controllers/dag/vertices.js
new file mode 100644
index 0000000..283f2d1
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dag/vertices.js
@@ -0,0 +1,122 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+export default MultiTableController.extend({
+ breadcrumbs: [{
+ text: "All Vertices",
+ routeName: "dag.vertices",
+ }],
+
+ columns: ColumnDefinition.make([{
+ id: 'name',
+ headerTitle: 'Vertex Name',
+ contentPath: 'name',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "vertex",
+ model: row.get("entityID"),
+ text: row.get("name")
+ };
+ }
+ },{
+ id: 'entityID',
+ headerTitle: 'Vertex Id',
+ contentPath: 'entityID'
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'finalStatus',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ },{
+ id: 'firstTaskStartTime',
+ headerTitle: 'First Task Start Time',
+ contentPath: 'firstTaskStartTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'totalTasks',
+ headerTitle: 'Tasks',
+ contentPath: 'totalTasks',
+ },{
+ id: 'succeededTasks',
+ headerTitle: 'Succeeded Tasks',
+ contentPath: 'succeededTasks',
+ observePath: true
+ },{
+ id: 'runningTasks',
+ headerTitle: 'Running Tasks',
+ contentPath: 'runningTasks',
+ observePath: true
+ },{
+ id: 'pendingTasks',
+ headerTitle: 'Pending Tasks',
+ contentPath: 'pendingTasks',
+ observePath: true
+ },{
+ id: 'processorClassName',
+ headerTitle: 'Processor Class',
+ contentPath: 'processorClassName',
+ }]),
+
+ beforeSort: function (columnDefinition) {
+ if(this._super(columnDefinition)) {
+ if(this.get("polling.isReady")) {
+ let columnName = columnDefinition.get("headerTitle");
+ switch(columnDefinition.get("contentPath")) {
+ case "succeededTasks":
+ case "runningTasks":
+ case "pendingTasks":
+ this.send("openModal", {
+ title: "Cannot sort!",
+ content: `Sorting on ${columnName} is disabled for running DAGs!`
+ });
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/dags.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/dags.js b/tez-ui/src/main/webapp/app/controllers/dags.js
new file mode 100644
index 0000000..b35c693
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/dags.js
@@ -0,0 +1,166 @@
+/**
+ * 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';
+
+import TableController from './table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+import TableDefinition from 'em-table/utils/table-definition';
+
+export default TableController.extend({
+
+ queryParams: ["dagName", "dagID", "submitter", "status", "appID", "callerID"],
+ dagName: "",
+ dagID: "",
+ submitter: "",
+ status: "",
+ appID: "",
+ callerID: "",
+
+ // Because pageNo is a query param added by table controller, and in the current design
+ // we don't want page to be a query param as only the first page will be loaded first.
+ pageNum: 1,
+
+ breadcrumbs: [],
+
+ moreAvailable: false,
+ loadingMore: false,
+
+ headerComponentNames: ['dags-page-search', 'table-controls', 'dags-pagination-ui'],
+
+ _definition: TableDefinition.create(),
+ // Using computed, as observer won't fire if the property is not used
+ definition: Ember.computed("dagName", "dagID", "submitter", "status",
+ "appID", "callerID", "pageNum", "moreAvailable", "loadingMore", function () {
+
+ var definition = this.get("_definition");
+
+ definition.setProperties({
+ dagName: this.get("dagName"),
+ dagID: this.get("dagID"),
+ submitter: this.get("submitter"),
+ status: this.get("status"),
+ appID: this.get("appID"),
+ callerID: this.get("callerID"),
+
+ pageNum: this.get("pageNum"),
+
+ moreAvailable: this.get("moreAvailable"),
+ loadingMore: this.get("loadingMore")
+ });
+
+ return definition;
+ }),
+
+ columns: ColumnDefinition.make([{
+ id: 'name',
+ headerTitle: 'Dag Name',
+ contentPath: 'name',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "dag",
+ model: row.get("entityID"),
+ text: row.get("name")
+ };
+ }
+ },{
+ id: 'entityID',
+ headerTitle: 'Id',
+ contentPath: 'entityID'
+ },{
+ id: 'submitter',
+ headerTitle: 'Submitter',
+ contentPath: 'submitter'
+ },{
+ id: 'status',
+ headerTitle: 'Status',
+ contentPath: 'status',
+ cellComponentName: 'em-table-status-cell',
+ observePath: true
+ },{
+ id: 'progress',
+ headerTitle: 'Progress',
+ contentPath: 'progress',
+ cellComponentName: 'em-table-progress-cell',
+ observePath: true
+ },{
+ id: 'startTime',
+ headerTitle: 'Start Time',
+ contentPath: 'startTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'endTime',
+ headerTitle: 'End Time',
+ contentPath: 'endTime',
+ cellComponentName: 'date-formatter',
+ },{
+ id: 'duration',
+ headerTitle: 'Duration',
+ contentPath: 'duration',
+ cellDefinition: {
+ type: 'duration'
+ }
+ },{
+ id: 'appID',
+ headerTitle: 'Application Id',
+ contentPath: 'appID',
+ cellComponentName: 'em-table-linked-cell',
+ getCellContent: function (row) {
+ return {
+ routeName: "app",
+ model: row.get("appID"),
+ text: row.get("appID")
+ };
+ }
+ },{
+ id: 'queue',
+ headerTitle: 'Queue',
+ contentPath: 'queue'
+ },{
+ id: 'callerID',
+ headerTitle: 'Caller ID',
+ contentPath: 'callerID'
+ },{
+ id: 'callerType',
+ headerTitle: 'Caller Type',
+ contentPath: 'callerType'
+ },{
+ id: 'logs',
+ headerTitle: 'Logs',
+ contentPath: 'containerLogs',
+ cellComponentName: "em-table-linked-cell",
+ cellDefinition: {
+ target: "_blank"
+ }
+ }]),
+
+ getCounterColumns: function () {
+ return this._super().concat(this.get('env.app.tables.defaultColumns.dagCounters'));
+ },
+
+ actions: {
+ search: function (properties) {
+ this.setProperties(properties);
+ },
+ pageChanged: function (pageNum) {
+ this.set("pageNum", pageNum);
+ },
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/multi-table.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/multi-table.js b/tez-ui/src/main/webapp/app/controllers/multi-table.js
new file mode 100644
index 0000000..3a11830
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/multi-table.js
@@ -0,0 +1,37 @@
+/**
+ * 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';
+
+import TableController from './table';
+import CounterColumnDefinition from '../utils/counter-column-definition';
+
+export default TableController.extend({
+
+ _visibleColumnsObserver: Ember.on("init", Ember.observer("visibleColumns", function () {
+ Ember.run.later(this, "sendCountersChanged");
+ })),
+
+ sendCountersChanged: function () {
+ var visibleCounters = this.get("visibleColumns").filter(function (definition) {
+ return definition instanceof CounterColumnDefinition;
+ });
+ this.send("countersToPollChanged", visibleCounters);
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/page.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/page.js b/tez-ui/src/main/webapp/app/controllers/page.js
new file mode 100644
index 0000000..14ad6b5
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/page.js
@@ -0,0 +1,23 @@
+/**
+ * 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 AbstractController from './abstract';
+
+export default AbstractController.extend({
+ // Any page specific
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/parent.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/parent.js b/tez-ui/src/main/webapp/app/controllers/parent.js
new file mode 100644
index 0000000..089ed77
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/parent.js
@@ -0,0 +1,30 @@
+/**
+ * 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';
+
+import AbstractController from './abstract';
+
+export default AbstractController.extend({
+ polling: Ember.inject.service("pollster"),
+ actions: {
+ autoRefreshChanged: function (state) {
+ this.get("polling").set("active", state);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/table.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/table.js b/tez-ui/src/main/webapp/app/controllers/table.js
new file mode 100644
index 0000000..f0bce1c
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/table.js
@@ -0,0 +1,166 @@
+/*global more*/
+/**
+ * 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';
+
+import AbstractController from './abstract';
+import TableDefinition from 'em-table/utils/table-definition';
+import isIOCounter from '../utils/misc';
+
+import CounterColumnDefinition from '../utils/counter-column-definition';
+
+var MoreObject = more.Object;
+
+export default AbstractController.extend({
+ queryParams: ["rowCount", "searchText", "sortColumnId", "sortOrder", "pageNo"],
+ rowCount: 10,
+ searchText: "",
+ sortColumnId: "",
+ sortOrder: "",
+ pageNo: 1,
+
+ columns: [],
+
+ headerComponentNames: ['em-table-search-ui', 'table-controls', 'em-table-pagination-ui'],
+
+ visibleColumnIDs: {},
+ columnSelectorTitle: 'Column Selector',
+ columnSelectorMessage: "",
+
+ polling: Ember.inject.service("pollster"),
+
+ definition: Ember.computed("model", function () {
+ return TableDefinition.create({
+ rowCount: this.get("rowCount"),
+ searchText: this.get("searchText"),
+ sortColumnId: this.get("sortColumnId"),
+ sortOrder: this.get("sortOrder"),
+ pageNo: this.get("pageNo")
+ });
+ }),
+
+ storageID: Ember.computed("name", function () {
+ return this.get("name") + ":visibleColumnIDs";
+ }),
+
+ initVisibleColumns: Ember.on("init", Ember.observer("columns", function () { //To reset on entity change
+ var visibleColumnIDs = this.get("localStorage").get(this.get("storageID")) || {};
+
+ this.get('columns').forEach(function (config) {
+ if(visibleColumnIDs[config.id] !== false) {
+ visibleColumnIDs[config.id] = true;
+ }
+ });
+
+ this.set('visibleColumnIDs', visibleColumnIDs);
+ })),
+
+ beforeSort: function (columnDefinition) {
+ if(this.get("polling.isReady")) {
+ let columnName = columnDefinition.get("headerTitle");
+ switch(columnDefinition.get("contentPath")) {
+ case "counterGroupsHash":
+ columnName = "Counters";
+ /* falls through */
+ case "status":
+ case "progress":
+ this.send("openModal", {
+ title: "Cannot sort!",
+ content: `Sorting on ${columnName} is disabled for running DAGs!`
+ });
+ return false;
+ }
+ }
+ return true;
+ },
+
+ allColumns: Ember.computed("columns", function () {
+ var columns = this.get("columns"),
+ counters = this.getCounterColumns(),
+ beforeSort = this.get("beforeSort").bind(this);
+
+ columns = columns.concat(CounterColumnDefinition.make(counters));
+
+ columns.forEach(function (column) {
+ column.set("beforeSort", beforeSort);
+ });
+
+ return columns;
+ }),
+
+ visibleColumns: Ember.computed('visibleColumnIDs', 'allColumns', function() {
+ var visibleColumnIDs = this.visibleColumnIDs;
+ return this.get('allColumns').filter(function (column) {
+ return visibleColumnIDs[column.get("id")];
+ });
+ }),
+
+ getCounterColumns: function () {
+ return this.get('env.app.tables.defaultColumns.counters');
+ },
+
+ actions: {
+ searchChanged: function (searchText) {
+ this.set("searchText", searchText);
+ },
+ sortChanged: function (sortColumnId, sortOrder) {
+ this.setProperties({
+ sortColumnId,
+ sortOrder
+ });
+ },
+ rowCountChanged: function (rowCount) {
+ this.set("rowCount", rowCount);
+ },
+ pageChanged: function (pageNum) {
+ this.set("pageNo", pageNum);
+ },
+
+ rowsChanged: function (rows) {
+ this.send("setPollingRecords", rows);
+ },
+
+ // Column selection actions
+ openColumnSelector: function () {
+ this.send("openModal", "column-selector", {
+ title: this.get('columnSelectorTitle'),
+ targetObject: this,
+ content: {
+ message: this.get('columnSelectorMessage'),
+ columns: this.get('allColumns'),
+ visibleColumnIDs: this.get('visibleColumnIDs')
+ }
+ });
+ },
+ columnsSelected: function (visibleColumnIDs) {
+ var columnIDs = {};
+
+ MoreObject.forEach(visibleColumnIDs, function (key, value) {
+ if(!isIOCounter(key)) {
+ columnIDs[key] = value;
+ }
+ });
+
+ if(!MoreObject.equals(columnIDs, this.get("visibleColumnIDs"))) {
+ this.get("localStorage").set(this.get("storageID"), columnIDs);
+ this.set('visibleColumnIDs', columnIDs);
+ }
+ }
+ }
+});