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("[email protected]", 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("[email protected]", 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("[email protected]", 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("[email protected]", 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); + } + } + } +});
