| /** |
| * Licensed 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. |
| */ |
| var Task = new Class({ |
| data: {}, |
| |
| initialize: function(taskId, taskType) { |
| this.taskType = taskType |
| this.taskId = taskId |
| this.visible = false |
| this.setElement() |
| }, |
| |
| // task[active.task_id.processes.waiting] |
| taskStr: function(components) { |
| return 'task[' + ([this.taskType, this.taskId].append(components).join()) + ']' |
| }, |
| |
| transitionElement: function(dom_id, newval) { |
| if (!$(dom_id)) { |
| // alert('could not find dom_id' + dom_id) |
| return |
| } |
| |
| curval = $(dom_id).innerHTML |
| |
| // handle specialcases |
| newval = this.translateElement(dom_id, newval) |
| |
| if (newval != curval) { |
| $(dom_id).innerHTML = newval |
| var morphElement = new Fx.Morph(dom_id, { |
| duration: 'long', |
| transition: Fx.Transitions.Sine.easeOut |
| }); |
| morphElement.start({ 'color': ["#00FF00", "#222222"]}) |
| } |
| }, |
| |
| applyUpdate: function(update) { |
| this.data = update |
| this.updateElement() |
| }, |
| |
| /* |
| TODO(wickman) Instead do the 2-3 necessary transition functions, then make |
| a schema that maps attributes to the appropriate transition function. |
| */ |
| translateElement: function(dom_id, value) { |
| if (dom_id === this.taskStr(['processes', 'running']) || |
| dom_id === this.taskStr(['processes', 'waiting']) || |
| dom_id === this.taskStr(['processes', 'success']) || |
| dom_id === this.taskStr(['processes', 'failed'])) { |
| return value.length |
| } |
| |
| if (dom_id == this.taskStr(['resource_consumption', 'cpu'])) { |
| if (value) { |
| return value.toFixed(2) |
| } |
| } |
| |
| return value |
| }, |
| |
| /* |
| TODO(wickman) Ditto to above. |
| */ |
| updateElement: function() { |
| for (prefix_attr in this.data) { |
| if (this.data.hasOwnProperty(prefix_attr)) { |
| if (prefix_attr == "task_id") { |
| this.transitionElement(this.taskStr([prefix_attr]), this.translateUid(this.data[prefix_attr])) |
| } else if (instanceOf(this.data[prefix_attr], String) || instanceOf(this.data[prefix_attr], Number)) { |
| this.transitionElement(this.taskStr([prefix_attr]), this.data[prefix_attr]) |
| } else if (instanceOf(this.data[prefix_attr], Object)) { |
| for (suffix_attr in this.data[prefix_attr]) |
| if (this.data[prefix_attr].hasOwnProperty(suffix_attr)) |
| this.transitionElement(this.taskStr([prefix_attr, suffix_attr]), |
| this.data[prefix_attr][suffix_attr]) |
| } |
| } |
| } |
| }, |
| |
| translateUid: function(taskId) { |
| return "<a href='/task/" + taskId + "'>" + taskId + "</a>" |
| }, |
| |
| setElement: function() { |
| this.element = new Element('tr', { |
| 'id': 'task[' + this.taskType + '][' + this.taskId + ']'}).adopt( |
| new Element('td', { 'id': this.taskStr(['task_id']), 'html': this.translateUid(this.taskId)}), |
| new Element('td', { 'id': this.taskStr(['name']) }), |
| new Element('td', { 'id': this.taskStr(['resource_consumption', 'cpu']) }), |
| new Element('td', { 'id': this.taskStr(['resource_consumption', 'ram']) }), |
| new Element('td', { 'id': this.taskStr(['resource_consumption', 'disk']) }), |
| new Element('td', { 'id': this.taskStr(['processes', 'waiting']) }), |
| new Element('td', { 'id': this.taskStr(['processes', 'running']) }), |
| new Element('td', { 'id': this.taskStr(['processes', 'success']) }), |
| new Element('td', { 'id': this.taskStr(['processes', 'failed']) })) |
| } |
| }) |
| |
| var TableManager = new Class({ |
| activeTasks: {}, |
| visibleChildren: [], |
| |
| initialize: function(tableType) { |
| this.tableType = tableType |
| this.setElement() |
| this.getChildren() |
| this.startPolling() |
| }, |
| |
| setElement: function() { |
| this.element = new Element('table', { 'id': 'table[' + this.tableType + ']', 'class': 'common-table zebra-striped', 'cellpadding': '0' }) |
| this.element.adopt( |
| new Element('thead'). |
| adopt(new Element('tr', { 'id': 'task[' + this.tableType + '][superheader]', 'class': 'meta-headers' }) |
| .adopt(new Element('th', { 'html': "", 'colspan': 2 }), |
| new Element('th', { 'html': "consumed", 'colspan': 3 }), |
| new Element('th', { 'html': "processes", 'colspan': 4 }) |
| ) |
| ) |
| .adopt(new Element('tr', { 'id': 'task[' + this.tableType + '][header]' }) |
| .adopt(new Element('th', { 'id': 'task[' + this.tableType + '][header][task_id]', 'html': "task_id" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][name]', 'html': "name" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][resource_consumption][cpu]', 'html': "cpu" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][resource_consumption][ram]', 'html': "ram" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][resource_consumption][disk]','html': "disk" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][processes][waiting]', 'html': "waiting" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][processes][running]', 'html': "running"}), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][processes][success]', 'html': "success" }), |
| new Element('th', { 'id': 'task[' + this.tableType + '][header][processes][failed]', 'html': "failed" }) |
| ) |
| ) |
| ) |
| this.tbody = new Element('tbody', { 'id': this.tableType + '_tbody' }) |
| this.element.adopt(this.tbody) |
| }, |
| |
| toElement: function() { |
| return this.element |
| }, |
| |
| startPolling: function() { |
| this.taskIdPoller = setInterval(this.tableType + 'TableManager.getChildren();', 2500) |
| this.dataPoller = setInterval(this.tableType + 'TableManager.refreshVisibleChildren();', 5300) |
| }, |
| |
| getChildren: function() { |
| new Request.JSON({ |
| 'url': '/j/task_ids/' + this.tableType + '/-20', |
| 'method': 'get', |
| 'onComplete': function(response) { |
| if (response) { |
| var newChildren = Array.from(response.task_ids) |
| this.visibleChildren = newChildren |
| |
| // first set all children to invisible |
| for (taskId in this.activeTasks) { |
| this.activeTasks[taskId].visible = false |
| } |
| |
| // set new children visible |
| for (var k = 0; k < newChildren.length; k++) { |
| if (!(newChildren[k] in this.activeTasks)) { |
| this.activeTasks[newChildren[k]] = new Task(newChildren[k], this.tableType) |
| } |
| this.activeTasks[newChildren[k]].visible = true |
| } |
| |
| // clear then adopt them |
| while (this.tbody.childNodes.length > 0) |
| this.tbody.removeChild(this.tbody.firstChild); |
| for (var k = 0; k < newChildren.length; k++) |
| this.tbody.adopt(this.activeTasks[newChildren[k]].element) |
| } else { |
| clearInterval(this.taskIdPoller) |
| } |
| }.bind(this) |
| }).send() |
| }, |
| |
| refreshVisibleChildren: function() { |
| // first get visible children |
| new Request.JSON({ |
| 'url': '/j/task', |
| 'method': 'get', |
| 'data': { 'task_id': this.visibleChildren.join() }, |
| 'onComplete': function(response) { |
| if (response) { |
| if (!response) return; |
| for (taskId in response) { |
| if (response.hasOwnProperty(taskId)) |
| this.activeTasks[taskId].applyUpdate(response[taskId]) |
| } |
| } else { |
| clearInterval(this.dataPoller) |
| } |
| }.bind(this) |
| }).send() |
| }, |
| }) |