1 /** @namespace data.opresult */
3 /* Capitalize the first letter of every word in a string. */
4 function cap_first(str) {
5 var a = str.split(" ");
8 for (var i = 0; i < len; i++) {
9 a[i] = a[i][0].toUpperCase() + a[i].substring(1);
15 /* Format an operation string.
17 * Operation strings look like "OP_DO_SOMETHING". They should be formatted to
18 * appear as "Do Something". */
19 function format_op(op, stat) {
20 op = op.substring(3).toLowerCase();
21 op = op.replace(/_/g, " ");
22 str = cap_first(op) + ": " + cap_first(stat);
26 function JobPoller() {
29 var get_interval_speed;
30 var get_jobs_url = '';
31 var messages = $('#messages');
37 var get_xhr = undefined;
41 this.init = function (url, new_cluster, new_callback, new_errback) {
44 cluster = new_cluster;
45 callback = new_callback==undefined ? $.noop : new_callback;
46 errback = new_errback==undefined ? $.noop : new_errback;
49 // poll for active jobs. This maintains the list of jobs that are being
50 // actively queried for updates. This will pull in new jobs started elsewhere
51 this.poll = function (interval) {
52 interval = interval==undefined ? poller.SLOW : interval;
53 if (get_interval_speed != interval) {
54 if (get_interval != undefined) {
55 clearInterval(get_interval);
57 get_interval_speed = interval;
58 get_interval = setInterval(poller.get_jobs, interval);
63 // get list of active jobs
64 this.get_jobs = function () {
65 /* Run the AJAX call. if a call is pending, just skip this one */
66 if (get_xhr == undefined) {
70 success: function(data) {
72 process_get_jobs(data);
79 // process list of active jobs. This will import new jobs if any are not being
81 function process_get_jobs(data) {
84 var job_data = data[i];
85 if (job_data.status == 'success') {
88 poller.render_job(job_data);
89 active.push(job_data.id);
90 if (job_data.status == 'error') {
96 // clear any jobs that weren't in the active list any more
97 $('#messages').children('.job').each(function(){
98 var job_id = this.id.substring(4);
99 if (active.indexOf(job_id) == -1) {
100 if (!$(this).hasClass('error')) {
107 if (data.length==0) {
108 poller.poll(poller.SLOW);
110 poller.poll(poller.FAST);
115 function active_op(data) {
116 /* Find a sub-operation which has not successfully completed. */
117 for (var sub_op = 0; sub_op < data['opstatus'].length; sub_op++) {
118 if (data['opstatus'][sub_op] != 'success') {
126 this.render_job = function (data) {
127 var job_id = data['id'];
128 var html = $('#job_'+job_id);
129 var op_index = active_op(data);
130 var status = data['status'];
131 var op = format_op(data['ops'][op_index]['OP_ID'], status);
132 var new_job = (html.length==0);
135 html = $("<li class='job'><h3>"+op+"</h3></li>");
136 html.attr('id', 'job_'+job_id);
137 html.addClass(status);
138 $('#messages').append(html);
139 html.append('<div class="scrollable"><div class="detector"></div></div>');
142 var error = undefined;
143 var scrollable = html.children('.scrollable');
145 if (status=='running' || status=='error') {
146 html.addClass(status);
148 if (data.status == 'error' && html.find('pre.error').length==0) {
149 var reason = data.opresult[op_index][1][0];
150 var href = cluster + "/job/" + job_id + "/clear/";
152 .append("<a class='clear' title='clear error' href='"+href+"'></a>");
153 error = $("<pre class='error'>" + reason + "</pre>");
154 scrollable.prepend(error);
155 actions_enabled = true;
156 $('#actions a').removeClass('disabled');
159 // append log messages that are not already displayed
160 var current_log_count = html.find(".op_log ul li").length;
161 if (data['oplog'][op_index].length != 0) {
162 var log_html = html.find('.op_log');
163 if (log_html.length==0){
164 log_html = $("<pre class='op_log'><ul></ul></pre>");
165 scrollable.append(log_html);
167 var log = data['oplog'][op_index];
168 for (var i=current_log_count; i<log.length; i++) {
169 log_html.children("ul")
170 .append("<li>"+log[i][3]+"</li>");
174 // XXX hack to ensure log area is same width as error area.
175 var width = undefined;
176 if (log_html != undefined) {
177 width = $(html).find('.scrollable .detector').width();
178 width -= (log_html.innerWidth() - log_html.width()); // subtract padding
179 log_html.width(width);
180 $(html).find('.scrollable').css('display', 'block')
181 } else if (error != undefined) {
182 width = error.width();
183 $(html).find('.scrollable .detector').width(width);
184 $(html).find('.scrollable').css('display', 'block')
189 $("#messages a.clear").live("click", function(event){
190 event.preventDefault();
191 var error = $(this).parent().parent();
192 $.post(this.href, function(){