X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=plugins%2Fscheduler2%2Fstatic%2Fjs%2Fscheduler2.js;h=6b55b92afd4cf67fa1ab8a401aa2192fa7eb3462;hb=cb3a40dfdc1c79ca57458d1c18732334d58734fd;hp=0b5339fe1ba9d827d813ddfc050870a45f43ef7d;hpb=376307342a51ecd274fc8c0d24a14030c73cd292;p=myslice.git diff --git a/plugins/scheduler2/static/js/scheduler2.js b/plugins/scheduler2/static/js/scheduler2.js index 0b5339fe..6b55b92a 100755 --- a/plugins/scheduler2/static/js/scheduler2.js +++ b/plugins/scheduler2/static/js/scheduler2.js @@ -232,13 +232,15 @@ var SCHEDULER_COLWIDTH = 50; $scope.select = function(index, model_lease, model_resource) { - var data; + var data, resource_granularity; + + //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity; console.log("Selected", index, model_lease, model_resource); var day_timestamp = SchedulerDateSelected.getTime() / 1000; - var start_time = day_timestamp + index * model_resource.granularity; - var end_time = day_timestamp + (index + 1) * model_resource.granularity; + var start_time = day_timestamp + index * model_resource.granularity; // XXX resource_granularity + var end_time = day_timestamp + (index + 1) * model_resource.granularity; // var start_date = new Date(start_time * 1000); var end_date = new Date(end_time * 1000); @@ -313,7 +315,7 @@ var SCHEDULER_COLWIDTH = 50; } $scope._create_new_lease(model_resource.urn, start_time, end_time); - model_lease.status = 'pendingin'; + model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected'; // unless the exact same lease already existed (pending_out status for the lease, not the cell !!) break; @@ -351,7 +353,7 @@ var SCHEDULER_COLWIDTH = 50; } // cf comment in previous switch case - model_lease.status = 'pendingout'; + model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free'; break; @@ -478,10 +480,6 @@ var SCHEDULER_COLWIDTH = 50; * be updated when resources arrive. Should be the pgcd in fact XXX */ this._granularity = DEFAULT_GRANULARITY; scope.granularity = this._granularity; - this._all_slots = this._generate_all_slots(); - - // A list of {id, time} dictionaries representing the slots for the given day - scope.slots = this._all_slots; this.scope_resources_by_key = {}; this.do_resize(); @@ -495,6 +493,16 @@ var SCHEDULER_COLWIDTH = 50; do_resize: function() { var scope = this._get_scope(); + var num_hidden_cells, new_max, lcm; + + // do_resize has to be called when the window is resized, or one parameter changes + // e.g. when new resources have been received + // + this.resource_granularities = [3600, 1800]; //, 2400]; /* s */ + + /* Compute the slot length to accommodate all resources. This + * is the GCD of all resource granularities. */ + this._slot_length = this._gcdn(this.resource_granularities); $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH); //self get width might need fix depending on the template @@ -502,20 +510,33 @@ var SCHEDULER_COLWIDTH = 50; /* Number of visible cells...*/ this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH); + /* ...should be a multiple of the lcm of all encountered granularities. */ - // XXX Should be updated everytime a new resource is added - this._lcm_colspan = this._lcm(this._granularity, RESOURCE_DEFAULT_GRANULARITY) / this._granularity; - this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % this._lcm_colspan; + lcm = this._lcmn(this.resource_granularities) / this._slot_length; + this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm; + + // A list of {id, time} dictionaries representing the slots for the given day + this._all_slots = this._generate_all_slots(); + /* scope also needs this value */ + scope.slots = this._all_slots; + scope.slot_length = this._slot_length; scope.num_visible_cells = this._num_visible_cells; - scope.lcm_colspan = this._lcm_colspan; + scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ? - // Slider max value + /* Redraw... */ + this._scope_clear_leases(); + this._set_all_lease_slots(); + // Slider max value if ($('#tblSlider').data('slider') != undefined) { - var new_max = (this._all_slots.length - this._num_visible_cells) / this._lcm_colspan; - $('#tblSlider').slider('setAttribute', 'max', new_max); + num_hidden_cells = this._all_slots.length - this._num_visible_cells; + + $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells); + $('#tblSlider').slider('setValue', scope.from, true); } + this._get_scope().$apply(); + }, @@ -557,7 +578,9 @@ var SCHEDULER_COLWIDTH = 50; var resource = jQuery.extend(true, {}, record); // Fix granularity - resource.granularity = typeof(resource.granularity) == "number" ? resource.granularity : RESOURCE_DEFAULT_GRANULARITY; + //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity; + if (typeof(resource.granularity) != "number") + resource.granularity = RESOURCE_DEFAULT_GRANULARITY; resource.leases = []; // a list of occupied timeslots self.scope_resources_by_key[resource['urn']] = resource; @@ -567,18 +590,23 @@ var SCHEDULER_COLWIDTH = 50; _scope_clear_leases: function() { + var time, now; var self = this; var scope = this._get_scope(); + now = new Date().getTime(); + // Setup leases with a default free status... $.each(this.scope_resources_by_key, function(resource_key, resource) { resource.leases = []; - var colspan_lease = resource.granularity / self._granularity; //eg. 3600 / 1800 => 2 cells + var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells + time = SchedulerDateSelected.getTime(); for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity resource.leases.push({ id: 'coucou', - status: 'free', // 'selected', 'reserved', 'maintenance' XXX pending ?? + status: (time < now) ? 'disabled': 'free', // 'selected', 'reserved', 'maintenance' XXX pending ?? }); + time += resource.granularity * 1000; } }); @@ -586,45 +614,35 @@ var SCHEDULER_COLWIDTH = 50; _scope_set_leases: function() { + var status; var self = this; var scope = this._get_scope(); - var leases = manifold.query_store.get_records(this.options.query_lease_uuid); - $.each(leases, function(i, lease) { - - console.log("SET LEASES", new Date(lease.start_time* 1000)); - console.log(" ", new Date(lease.end_time* 1000)); + manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) { + console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000)); // XXX We should ensure leases are correctly merged, otherwise our algorithm won't work // Populate leases by resource array: this will help us merging leases later + + // let's only put _our_ leases + lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET); + if (lease_status != STATE_SET_IN) + return true; // ~continue if (!(lease.resource in scope._leases_by_resource)) scope._leases_by_resource[lease.resource] = []; scope._leases_by_resource[lease.resource].push(lease); - var resource = self.scope_resources_by_key[lease.resource]; - var day_timestamp = SchedulerDateSelected.getTime() / 1000; + }); - var id_start = (lease.start_time - day_timestamp) / resource.granularity; - if (id_start < 0) { - /* Some leases might be in the past */ - id_start = 0; - } - - var id_end = (lease.end_time - day_timestamp) / resource.granularity - 1; - var colspan_lease = resource.granularity / self._granularity; //eg. 3600 / 1800 => 2 cells - if (id_end >= self._all_slots.length / colspan_lease) { - /* Limit the display to the current day */ - id_end = self._all_slots.length / colspan_lease - } + this._set_all_lease_slots(); + }, - for (i = id_start; i <= id_end; i++) - // the same slots might be affected multiple times. - // PENDING_IN + PENDING_OUT => IN - // - // RESERVED vs SELECTED ! - // - // PENDING !! - resource.leases[i].status = 'selected'; + _set_all_lease_slots: function() + { + var self = this; + + manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) { + self._set_lease_slots(lease_key, lease); }); }, @@ -658,8 +676,121 @@ var SCHEDULER_COLWIDTH = 50; on_leases_filter_removed: function(filter) { this._get_scope().$apply(); }, on_leases_filter_clear: function() { this._get_scope().$apply(); }, + on_field_state_changed: function(data) + { + /* + this._set_lease_slots(lease_key, lease); + + switch(data.state) { + case STATE_SET: + switch(data.op) { + case STATE_SET_IN: + case STATE_SET_IN_SUCCESS: + case STATE_SET_OUT_FAILURE: + this.set_checkbox_from_data(data.value, true); + this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET); + break; + case STATE_SET_OUT: + case STATE_SET_OUT_SUCCESS: + case STATE_SET_IN_FAILURE: + this.set_checkbox_from_data(data.value, false); + this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET); + break; + case STATE_SET_IN_PENDING: + this.set_checkbox_from_data(data.key, true); + this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED); + break; + case STATE_SET_OUT_PENDING: + this.set_checkbox_from_data(data.key, false); + this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED); + break; + } + break; + + case STATE_WARNINGS: + this.change_status(data.key, data.value); + break; + } + */ + }, + + /* INTERNAL FUNCTIONS */ + _set_lease_slots: function(lease_key, lease) + { + var resource, lease_status, lease_class; + var day_timestamp, id_start, id_end, colspan_lease; + + resource = this.scope_resources_by_key[lease.resource]; + day_timestamp = SchedulerDateSelected.getTime() / 1000; + id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity); + + /* Some leases might be in the past */ + if (id_start < 0) + id_start = 0; + /* Leases in the future: ignore */ + if (id_start >= this._all_slots.length) + return true; // ~ continue + + id_end = Math.ceil((lease.end_time - day_timestamp) / resource.granularity); + colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells + if (id_end >= this._all_slots.length / colspan_lease) { + /* Limit the display to the current day */ + id_end = this._all_slots.length / colspan_lease + } + lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET); + // the same slots might be affected multiple times. + // PENDING_IN + PENDING_OUT => IN + // + // RESERVED vs SELECTED ! + // + // PENDING !! + switch(lease_status) { + case STATE_SET_IN: + lease_class = 'selected'; // my leases + lease_success = ''; + break; + case STATE_SET_IN_SUCCESS: + lease_class = 'selected'; // my leases + lease_success = 'success'; + case STATE_SET_OUT_FAILURE: + lease_class = 'selected'; // my leases + lease_success = 'failure'; + break; + case STATE_SET_OUT: + lease_class = 'reserved'; // other leases + lease_success = ''; + break; + case STATE_SET_OUT_SUCCESS: + lease_class = 'free'; // other leases + lease_success = 'success'; + break; + case STATE_SET_IN_FAILURE: + lease_class = 'free'; // other leases + lease_success = 'failure'; + break; + case STATE_SET_IN_PENDING: + lease_class = 'pendingin'; + lease_success = ''; + break; + case STATE_SET_OUT_PENDING: + // pending_in & pending_out == IN == replacement + if (resource.leases[i].status == 'pendingin') + lease_class = 'pendingin' + else + lease_class = 'pendingout'; + lease_success = ''; + break; + + } + + for (i = id_start; i < id_end; i++) { + resource.leases[i].status = lease_class; + resource.leases[i].success = lease_success; + } + }, + /* XXX IN TEMPLATE XXX if (SchedulerDataViewData.length == 0) { $("#plugin-scheduler").hide(); @@ -679,8 +810,12 @@ var SCHEDULER_COLWIDTH = 50; _initUI: function() { var self = this; + var scope = self._get_scope(); + + var num_hidden_cells; $("#DateToRes").datepicker({ + dateFormat: "D, d M yy", onRender: function(date) { return date.valueOf() < now.valueOf() ? 'disabled' : ''; } @@ -688,24 +823,31 @@ var SCHEDULER_COLWIDTH = 50; SchedulerDateSelected = new Date(ev.date); SchedulerDateSelected.setHours(0,0,0,0); // Set slider to origin - $('#tblSlider').slider('setValue', 0); // XXX + //$('#tblSlider').slider('setValue', 0); // XXX // Refresh leases self._scope_clear_leases(); - self._scope_set_leases(); + self._set_all_lease_slots(); // Refresh display self._get_scope().$apply(); }).datepicker('setValue', SchedulerDateSelected); //.data('datepicker'); //init Slider + num_hidden_cells = self._all_slots.length - self._num_visible_cells; + init_cell = (new Date().getHours() - 1) * 3600 / self._granularity; + if (init_cell > num_hidden_cells) + init_cell = num_hidden_cells; + $('#tblSlider').slider({ min: 0, - max: (self._all_slots.length - self._num_visible_cells) / self._lcm_colspan, - value: 0, + max: num_hidden_cells, + value: init_cell, }).on('slide', function(ev) { var scope = self._get_scope(); - scope.from = ev.value * self._lcm_colspan; + scope.from = ev.value; scope.$apply(); }); + scope.from = init_cell; + scope.$apply(); $("#plugin-scheduler-loader").hide(); $("#plugin-scheduler").show(); @@ -721,6 +863,12 @@ var SCHEDULER_COLWIDTH = 50; return (y==0) ? x : this._gcd(y, x % y); }, + _gcdn : function(array) + { + var self = this; + return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); }); + }, + /** * Least common multiple */ @@ -728,6 +876,12 @@ var SCHEDULER_COLWIDTH = 50; { return x * y / this._gcd(x, y); }, + + _lcmn : function(array) + { + var self = this; + return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); }); + }, _pad_str : function(i) { @@ -754,7 +908,7 @@ var SCHEDULER_COLWIDTH = 50; /// ...and add the slot to the list of results slots.push({ id: i, time: tmpTime }); // Increment the date with the granularity - d = new Date(d.getTime() + this._granularity * 1000); + d = new Date(d.getTime() + this._slot_length * 1000); i++; } return slots;