X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=planetlab%2Fslices%2Fleases.js;h=9082601bcd161ab0170af61cfb9b6c726e7f7bac;hb=621f5f2521d88af260fe7b4ed416826662929669;hp=d34826d5324cc8906a8904f08b548979801bad1a;hpb=384c981dd2dbfc8fe15a5d72480183b556e12780;p=plewww.git diff --git a/planetlab/slices/leases.js b/planetlab/slices/leases.js index d34826d..9082601 100644 --- a/planetlab/slices/leases.js +++ b/planetlab/slices/leases.js @@ -1,21 +1,42 @@ +/* Thierry Parmentelat -- INRIA */ + /* need to put some place else in CSS ? */ +// space for the nodenames +var x_nodelabel = 200; +// right space after the nodename - removed from the above +var x_sep=20; +// height for the (two) rows of timelabels +var y_header = 12; +// space between nodes +var y_sep = 10; + +// 1-grain leases attributes +// leases_w is configurable from html +//var leases_w = 20; +var y_node = 15; +var radius= 6; + +var anim_delay=350; /* decorations / headers */ +/* note: looks like the 'font' attr is not effective... */ -var txt_nodename = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#008"}; -var txt_timeslot = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#008"}; +// vertical rules var attr_rules={'fill':"#888", 'stroke-dasharray':'- ', 'stroke-width':0.5}; -var x_nodename = 200; -var x_sep=10; -var y_header = 12 -var y_sep = 20 +// set font-size separately in here rather than depend on the height +var txt_timelabel = {"font": 'Times, "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', + stroke: "none", fill: "#008", 'font-size': 9}; +var txt_allnodes = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#404"}; +var txt_nodelabel = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#008"}; + +var attr_timebutton = {'fill':'#bbf', 'stroke': '#338','stroke-width':1, + 'stroke-linecap':'round', 'stroke-linejoin':'miter', 'stroke-miterlimit':3}; +var attr_daymarker = {'stroke':'#000','stroke-width':2}; +var attr_half_daymarker = {'stroke':'#444','stroke-width':2}; /* lease dimensions and colors */ -var anim_delay=500; -var x_grain = 24; -var y_node = 15; -var radius= 6; +/* refrain from using gradient color, seems to not be animated properly */ /* lease was originally free and is still free */ var attr_lease_free_free={'fill':"#def", 'stroke-width':0.5, 'stroke-dasharray':''}; /* lease was originally free and is now set for our usage */ @@ -24,72 +45,187 @@ var attr_lease_free_mine={'fill':"green", 'stroke-width':1, 'stroke-dasharray':' var attr_lease_mine_mine={'fill':"#beb", 'stroke-width':0.5, 'stroke-dasharray':''}; /* was mine and is about to be released */ var attr_lease_mine_free={'fill':"white", 'stroke-width':1, 'stroke-dasharray':'-..'}; -// refrained from using gradient color, was not animated properly -// var color_lease_mine_free="0-#fff-#def:50-#fff"; var attr_lease_other={'fill':"#f88"}; /* other slices name */ -var txt_slice = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#444", - "font-size": 15 }; +var txt_otherslice = {"font": '"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif', stroke: "none", fill: "#444", + "font-size": 12 }; //////////////////////////////////////////////////////////// // the scheduler object -function Scheduler (slicename, axisx, axisy, data) { +function Scheduler () { + + // xxx-hacky dunno how to retrieve this object from an ajax callback + Scheduler.scheduler=this; - this.slicename=slicename; - this.axisx=axisx; - this.axisy=axisy; - this.data=data; + // the data contains slice names, and lease_id, we need this to find our own leases (mine) + this.paper=null; + + //////////////////// + // store the result of an ajax request in the leases_data table + this.set_html = function (html_data) { + var table_text = $$("table#leases_data")[0].innerHTML; + $$("table#leases_data")[0].innerHTML=html_data; + table_text = $$("table#leases_data")[0].innerHTML; + return true; + } + + //////////////////// + // the names of the hidden fields that hold the input to this class + // are hard-wired for now + this.parse_html = function () { + + var table = $$("table#leases_data")[0]; + // no reservable nodes - no data + if ( ! table) return false; + + // the nodelabels + var data = [], axisx = [], axisy = []; + table.getElementsBySelector("tbody>tr>th").each(function (cell) { + axisy.push(getInnerText(cell)); + }); + // test for at least one entry; other wise this means we haven't retrieved + // the html dta yet + if (axisy.length <1) return false; + + // the timeslot labels + table.getElementsBySelector("thead>tr>th").each(function (cell) { + /* [0]: timestamp -- [1]: displayable*/ + axisx.push(getInnerText(cell).split("&")); + }); + + // leases - expect colspan to describe length in grains + // the text contents is expected to be lease_id & slicename + table.getElementsBySelector("tbody>tr>td").each(function (cell) { + var cell_data; + var slice_attributes=getInnerText(cell).split('&'); + // booked leases come with lease id and slice name + if (slice_attributes.length == 2) { + // leases is booked : slice_id, slice_name, duration in grains + cell_data=new Array (slice_attributes[0], slice_attributes[1], cell.colSpan); + } else { + cell_data = new Array ('','',cell.colSpan); + } + data.push(cell_data); + }); - // utilities to keep track of all the leases - this.leases=[]; - this.append_lease = function (lease) { - this.leases.push(lease); + this.axisx=axisx; + this.axisy=axisy; + this.data=data; + return true; } // how many time slots - this.nb_grains = function () { return axisx.length;} + this.nb_grains = function () { return this.axisx.length;} - this.init = function (id) { - this.total_width = x_nodename + this.nb_grains()*x_grain; - this.total_height = 2*y_header + this.axisy.length*(y_node+y_sep); - paper = Raphael (id, this.total_width, this.total_height); + //////////////////// + // draw + this.draw_area = function (canvas_id) { + this.total_width = x_nodelabel + this.nb_grains()*this.leases_w; + this.total_height = 2*y_header /* the timelabels */ + + 2*y_sep /* extra space */ + + y_node /* all-nodes & timebuttons row */ + + (this.axisy.length)*(y_node+y_sep); /* the regular nodes and preceding space */ + // reuse for paper if exists with same size, or (re-)create otherwise + var paper; + if (this.paper == null) { + paper = Raphael (canvas_id, this.total_width+x_sep, this.total_height); + } else if (this.paper.width==this.total_width && this.paper.height==this.total_height) { + paper=this.paper; + paper.clear(); + } else { + $$("#"+canvas_id)[0].innerHTML=""; + paper = Raphael (canvas_id, this.total_width+x_sep, this.total_height); + } + this.paper=paper; + + // the path for the triangle-shaped buttons + this.timebutton_path="M1,0L"+(this.leases_w-1)+",0L"+(this.leases_w/2)+","+y_header+"L1,0"; + + var axisx=this.axisx; + + var axisy=this.axisy; + // maintain the list of nodelabels for the 'all nodes' button + this.nodelabels=[]; - // create the time slots legend + ////////// create the time slots legend var top=0; - var left=x_nodename; + var left=x_nodelabel; + + var daymarker_height= 2*y_header+2*y_sep + (axisy.length+1)*(y_node+y_sep); + var daymarker_path="M0,0L0," + daymarker_height; + + var half_daymarker_off= 2*y_header+y_sep; + var half_daymarker_path="M0," + half_daymarker_off + "L0," + daymarker_height; var col=0; for (var i=0, len=axisx.length; i < len; ++i) { // pick the printable part - timeslot=axisx[i][1]; + var timelabel=axisx[i][1]; var y = top+y_header; if (col%2 == 0) y += y_header; col +=1; - var timelabel=paper.text(left,y,timeslot).attr(txt_timeslot) - .attr({"font-size":y_header, "text-anchor":"middle"}); + // display time label + var timelabel=paper.text(left,y,timelabel).attr(txt_timelabel) + .attr({"text-anchor":"middle"}); + // draw vertical line var path_spec="M"+left+" "+(y+y_header/2)+"L"+left+" "+this.total_height; var rule=paper.path(path_spec).attr(attr_rules); - left+=x_grain; + // show a day marker when relevant + var timestamp=parseInt(axisx[i][0]); + if ( (timestamp%(24*3600))==0) { + paper.path(daymarker_path).attr({'translation':left+','+top}).attr(attr_daymarker); + } else if ( (timestamp%(12*3600))==0) { + paper.path(half_daymarker_path).attr({'translation':left+','+top}).attr(attr_daymarker); + } + left+=(this.leases_w); } - // move to the lines below: - top += 2*y_header+y_sep; - + ////////// the row with the timeslot buttons (the one labeled 'All nodes') + this.granularity=axisx[1][0]-axisx[0][0]; + + // move two lines down + top += 2*y_header+2*y_sep; + left=x_nodelabel; + // all nodes buttons + var allnodes = paper.text (x_nodelabel-x_sep,top+y_node/2,"All nodes").attr(txt_allnodes) + .attr ({"font-size":y_node, "text-anchor":"end","baseline":"bottom"}); + allnodes.scheduler=this; + allnodes.click(allnodes_methods.click); + // timeslot buttons + for (var i=0, len=axisx.length; i < len; ++i) { + var timebutton=paper.path(this.timebutton_path).attr({'translation':left+','+top}).attr(attr_timebutton); + timebutton.from_time=axisx[i][0]; + timebutton.scheduler=this; + timebutton.click(timebutton_methods.click); + left+=(this.leases_w); + } + + //////// the body of the scheduler : loop on nodes + top += y_node+y_sep; var data_index=0; + this.leases=[]; for (var i=0, len=axisy.length; i0) ? 1 : 0; + for (var i=0, len=scheduler.nodelabels.length; i=until_time) { + if (scan.current == "free") relevant_free.push(scan); + else if (scan.current == "mine") relevant_mine.push(scan); + } + } +// window.console.log("Found " + relevant_free.length + " free and " + relevant_mine.length + " mine"); + /* decide what to do, whether book or release */ + if (relevant_mine.length==0 && relevant_free.length==0) { + alert ("Nothing to do in this timeslot on the selected nodes"); + return; + } + // if at least one is free, let's book + if (relevant_free.length > 0) { + for (var i=0, len=relevant_free.length; i=this.until_time) - if (scan.current == "free") lease_methods.init_mine(scan,lease_methods.click_free); - } - } + lease_methods.init_mine(this,lease_methods.click_free); }, init_mine: function (lease, unclick) { @@ -216,30 +464,20 @@ var lease_methods = { var scheduler = this.scheduler; // this lease was originally free but is now marked for booking // we free just this lease - if (scheduler.mode=='node') { - lease_methods.init_free(this, lease_methods.click_mine); - } else { - for (var i=0, len=scheduler.leases.length; i=this.until_time) { - if (scan.current == "mine") lease_methods.init_free(scan,lease_methods.click_mine); - } - // the other ones just remain as they are - } - } + lease_methods.init_free(this, lease_methods.click_mine); }, init_other: function (lease, slicename) { lease.animate (attr_lease_other,anim_delay); /* a text obj to display the name of the slice that owns that lease */ - var slicelabel = paper.text (lease.attr("x")+lease.attr("width")/2, - lease.attr("y")+lease.attr("height")/2,slicename).attr(txt_slice); + var otherslicelabel = lease.scheduler.paper.text (lease.attr("x")+lease.attr("width")/2, + // xxx + lease.attr("y")+lease.attr("height")/2,slicename).attr(txt_otherslice); /* hide it right away */ - slicelabel.hide(); + otherslicelabel.hide(); /* record it */ - lease.label=slicelabel; + lease.label=otherslicelabel; lease.hover ( function (e) { this.label.toFront(); this.label.show(); }, function (e) { this.label.hide(); } ); }, @@ -247,37 +485,13 @@ var lease_methods = { function init_scheduler () { // Grab the data - var data = [], axisx = [], axisy = []; - var table = $$("table#leases_data")[0]; - // no reservable nodes - no data - if ( ! table) return; - // the nodenames - table.getElementsBySelector("tbody>tr>th").each(function (cell) { - axisy.push(getInnerText(cell)); - }); - // the timeslot labels - table.getElementsBySelector("thead>tr>th").each(function (cell) { - /* [0]: timestamp -- [1]: displayable*/ - axisx.push(getInnerText(cell).split("&")); - }); - // leases - expect colspan to describe length in grains - table.getElementsBySelector("tbody>tr>td").each(function (cell) { - data.push(new Array (getInnerText(cell),cell.colSpan)); - }); - // slicename : the upper-left cell - var scheduler = new Scheduler (getInnerText(table.getElementsBySelector("thead>tr>td")[0]), axisx, axisy, data); - table.hide(); - // leases_area is a
created by slice.php as a placeholder - scheduler.init ("leases_area"); - - var submit=$$("button#leases_submit")[0]; - submit.onclick = function () { scheduler.submit(); } - var clear=$$("button#leases_clear")[0]; - clear.onclick = function () { scheduler.clear(); } - - var node_button=$$("input#leases_mode_node")[0]; - var timeslot_button=$$("input#leases_mode_timeslot")[0]; - scheduler.init_mode ('timeslot',node_button,timeslot_button); + var scheduler = new Scheduler (); + // parse the table with data, and if not empty, draw the scheduler + scheduler.refresh(); + + // attach behaviour to buttons + $("leases_submit").onclick = function () { scheduler.submit(); } + $("leases_refresh").onclick = function () { scheduler.refresh();} }