\r
$scope._create_new_lease = function(resource_urn, start_time, end_time)\r
{\r
- var lease_key, new_lease;\r
+ var lease_key, new_lease, data;\r
\r
lease_key = manifold.metadata.get_key('lease');\r
\r
new_lease.hashCode = manifold.record_hashcode(lease_key.sort());\r
new_lease.equals = manifold.record_equals(lease_key);\r
\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, SET_ADD, new_lease);\r
+ data = {\r
+ state: STATE_SET,\r
+ key : null,\r
+ op : STATE_SET_ADD,\r
+ value: new_lease\r
+ }\r
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
/* Add to local cache also, unless we listen to events from outside */\r
if (!(resource_urn in $scope._leases_by_resource))\r
$scope._leases_by_resource[resource_urn] = [];\r
\r
$scope._remove_lease = function(other)\r
{\r
- var lease_key, other_key;\r
+ var lease_key, other_key, data;\r
\r
lease_key = manifold.metadata.get_key('lease');\r
\r
other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
other_key.equals = manifold.record_equals(lease_key);\r
\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, SET_REMOVED, other_key);\r
+ data = {\r
+ state: STATE_SET,\r
+ key : null,\r
+ op : STATE_SET_REMOVE,\r
+ value: other_key\r
+ }\r
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
/* Remove from local cache also, unless we listen to events from outside */\r
- $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });\r
+ $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });\r
\r
}\r
\r
$scope.select = function(index, model_lease, model_resource)\r
{\r
+ var data, resource_granularity;\r
+\r
+ //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity;\r
+\r
console.log("Selected", index, model_lease, model_resource);\r
\r
var day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
- var start_time = day_timestamp + index * model_resource.granularity;\r
- var end_time = day_timestamp + (index + 1) * model_resource.granularity;\r
+ var start_time = day_timestamp + index * model_resource.granularity; // XXX resource_granularity\r
+ var end_time = day_timestamp + (index + 1) * model_resource.granularity; //\r
var start_date = new Date(start_time * 1000);\r
var end_date = new Date(end_time * 1000);\r
\r
other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
other_key.equals = manifold.record_equals(lease_key);\r
\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, SET_REMOVED, other_key);\r
+ data = {\r
+ state: STATE_SET,\r
+ key : null,\r
+ op : STATE_SET_REMOVE,\r
+ value: other_key\r
+ }\r
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
/* Remove from local cache also, unless we listen to events from outside */\r
- $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
+ $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
return false; // ~ break\r
});\r
\r
/* The lease 'other' is just after, and there should not exist\r
* any other lease after it */\r
end_time = other.end_time;\r
- // XXX SET_ADD and SET_REMOVE should accept full objects\r
other_key = {\r
resource: other.resource,\r
start_time: other.start_time,\r
other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
other_key.equals = manifold.record_equals(lease_key);\r
\r
- manifold.raise_event($scope.instance.options.query_lease_uuid, SET_REMOVED, other_key);\r
+ data = {\r
+ state: STATE_SET,\r
+ key : null,\r
+ op : STATE_SET_REMOVE,\r
+ value: other_key\r
+ }\r
+ manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
/* Remove from local cache also, unless we listen to events from outside */\r
- $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
+ $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
return false; // ~ break\r
});\r
}\r
\r
$scope._create_new_lease(model_resource.urn, start_time, end_time);\r
- model_lease.status = 'pendingin'; \r
+ model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected';\r
// unless the exact same lease already existed (pending_out status for the lease, not the cell !!)\r
\r
break;\r
}\r
\r
// cf comment in previous switch case\r
- model_lease.status = 'pendingout'; \r
+ model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free';\r
\r
break;\r
\r
}\r
\r
\r
- //$scope._dump_leases();\r
+ $scope._dump_leases();\r
};\r
\r
$scope._dump_leases = function()\r
* be updated when resources arrive. Should be the pgcd in fact XXX */\r
this._granularity = DEFAULT_GRANULARITY;\r
scope.granularity = this._granularity;\r
- this._all_slots = this._generate_all_slots();\r
-\r
- // A list of {id, time} dictionaries representing the slots for the given day\r
- scope.slots = this._all_slots;\r
this.scope_resources_by_key = {};\r
\r
this.do_resize();\r
do_resize: function()\r
{\r
var scope = this._get_scope();\r
+ var num_hidden_cells, new_max, lcm;\r
+\r
+ // do_resize has to be called when the window is resized, or one parameter changes\r
+ // e.g. when new resources have been received\r
+ //\r
+ this.resource_granularities = [3600, 1800]; //, 2400]; /* s */\r
+\r
+ /* Compute the slot length to accommodate all resources. This\r
+ * is the GCD of all resource granularities. */\r
+ this._slot_length = this._gcdn(this.resource_granularities);\r
\r
$('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH);\r
//self get width might need fix depending on the template \r
\r
/* Number of visible cells...*/\r
this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH);\r
+\r
/* ...should be a multiple of the lcm of all encountered granularities. */\r
- // XXX Should be updated everytime a new resource is added\r
- this._lcm_colspan = this._lcm(this._granularity, RESOURCE_DEFAULT_GRANULARITY) / this._granularity;\r
- this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % this._lcm_colspan;\r
+ lcm = this._lcmn(this.resource_granularities) / this._slot_length;\r
+ this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm;\r
+\r
+ // A list of {id, time} dictionaries representing the slots for the given day\r
+ this._all_slots = this._generate_all_slots();\r
+\r
/* scope also needs this value */\r
+ scope.slots = this._all_slots;\r
+ scope.slot_length = this._slot_length;\r
scope.num_visible_cells = this._num_visible_cells;\r
- scope.lcm_colspan = this._lcm_colspan;\r
+ scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ?\r
\r
- // Slider max value\r
+ /* Redraw... */\r
+ this._scope_clear_leases();\r
+ this._set_all_lease_slots();\r
\r
+ // Slider max value\r
if ($('#tblSlider').data('slider') != undefined) {\r
- var new_max = (this._all_slots.length - this._num_visible_cells) / this._lcm_colspan;\r
- $('#tblSlider').slider('setAttribute', 'max', new_max);\r
+ num_hidden_cells = this._all_slots.length - this._num_visible_cells;\r
+\r
+ $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells);\r
+ $('#tblSlider').slider('setValue', scope.from, true);\r
}\r
+ this._get_scope().$apply();\r
+\r
\r
},\r
\r
var resource = jQuery.extend(true, {}, record);\r
\r
// Fix granularity\r
- resource.granularity = typeof(resource.granularity) == "number" ? resource.granularity : RESOURCE_DEFAULT_GRANULARITY;\r
+ //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity;\r
+ if (typeof(resource.granularity) != "number")\r
+ resource.granularity = RESOURCE_DEFAULT_GRANULARITY;\r
resource.leases = []; // a list of occupied timeslots\r
\r
self.scope_resources_by_key[resource['urn']] = resource;\r
\r
_scope_clear_leases: function()\r
{\r
+ var time, now;\r
var self = this;\r
var scope = this._get_scope();\r
\r
+ now = new Date().getTime();\r
+\r
// Setup leases with a default free status...\r
$.each(this.scope_resources_by_key, function(resource_key, resource) {\r
resource.leases = [];\r
- var colspan_lease = resource.granularity / self._granularity; //eg. 3600 / 1800 => 2 cells\r
+ var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells\r
+ time = SchedulerDateSelected.getTime();\r
for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity\r
resource.leases.push({\r
id: 'coucou',\r
- status: 'free', // 'selected', 'reserved', 'maintenance' XXX pending ??\r
+ status: (time < now) ? 'disabled': 'free', // 'selected', 'reserved', 'maintenance' XXX pending ??\r
});\r
+ time += resource.granularity * 1000;\r
}\r
});\r
\r
\r
_scope_set_leases: function()\r
{\r
+ var status;\r
var self = this;\r
var scope = this._get_scope();\r
\r
- var leases = manifold.query_store.get_records(this.options.query_lease_uuid);\r
- $.each(leases, function(i, lease) {\r
-\r
- console.log("SET LEASES", new Date(lease.start_time* 1000));\r
- console.log(" ", new Date(lease.end_time* 1000));\r
+ manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
+ console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000));\r
// XXX We should ensure leases are correctly merged, otherwise our algorithm won't work\r
\r
// Populate leases by resource array: this will help us merging leases later\r
+\r
+ // let's only put _our_ leases\r
+ lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET);\r
+ if (lease_status != STATE_SET_IN)\r
+ return true; // ~continue\r
if (!(lease.resource in scope._leases_by_resource))\r
scope._leases_by_resource[lease.resource] = [];\r
scope._leases_by_resource[lease.resource].push(lease);\r
\r
- var resource = self.scope_resources_by_key[lease.resource];\r
- var day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
+ });\r
\r
- var id_start = (lease.start_time - day_timestamp) / resource.granularity;\r
- if (id_start < 0) {\r
- /* Some leases might be in the past */\r
- id_start = 0;\r
- }\r
- \r
- var id_end = (lease.end_time - day_timestamp) / resource.granularity - 1;\r
- var colspan_lease = resource.granularity / self._granularity; //eg. 3600 / 1800 => 2 cells\r
- if (id_end >= self._all_slots.length / colspan_lease) {\r
- /* Limit the display to the current day */\r
- id_end = self._all_slots.length / colspan_lease\r
- }\r
+ this._set_all_lease_slots();\r
+ },\r
\r
- for (i = id_start; i <= id_end; i++)\r
- // the same slots might be affected multiple times.\r
- // PENDING_IN + PENDING_OUT => IN \r
- //\r
- // RESERVED vs SELECTED !\r
- //\r
- // PENDING !!\r
- resource.leases[i].status = 'selected'; \r
+ _set_all_lease_slots: function()\r
+ {\r
+ var self = this;\r
+ \r
+ manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
+ self._set_lease_slots(lease_key, lease);\r
});\r
},\r
\r
on_leases_filter_removed: function(filter) { this._get_scope().$apply(); },\r
on_leases_filter_clear: function() { this._get_scope().$apply(); },\r
\r
+ on_field_state_changed: function(data)\r
+ {\r
+ /*\r
+ this._set_lease_slots(lease_key, lease);\r
+\r
+ switch(data.state) {\r
+ case STATE_SET:\r
+ switch(data.op) {\r
+ case STATE_SET_IN:\r
+ case STATE_SET_IN_SUCCESS:\r
+ case STATE_SET_OUT_FAILURE:\r
+ this.set_checkbox_from_data(data.value, true);\r
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
+ break; \r
+ case STATE_SET_OUT:\r
+ case STATE_SET_OUT_SUCCESS:\r
+ case STATE_SET_IN_FAILURE:\r
+ this.set_checkbox_from_data(data.value, false);\r
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
+ break;\r
+ case STATE_SET_IN_PENDING:\r
+ this.set_checkbox_from_data(data.key, true);\r
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);\r
+ break; \r
+ case STATE_SET_OUT_PENDING:\r
+ this.set_checkbox_from_data(data.key, false);\r
+ this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case STATE_WARNINGS:\r
+ this.change_status(data.key, data.value);\r
+ break;\r
+ }\r
+ */\r
+ },\r
+\r
+\r
/* INTERNAL FUNCTIONS */\r
\r
+ _set_lease_slots: function(lease_key, lease)\r
+ {\r
+ var resource, lease_status, lease_class;\r
+ var day_timestamp, id_start, id_end, colspan_lease;\r
+\r
+ resource = this.scope_resources_by_key[lease.resource];\r
+ day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
+ id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity);\r
+\r
+ /* Some leases might be in the past */\r
+ if (id_start < 0)\r
+ id_start = 0;\r
+ /* Leases in the future: ignore */\r
+ if (id_start >= this._all_slots.length)\r
+ return true; // ~ continue\r
+\r
+ id_end = Math.ceil((lease.end_time - day_timestamp) / resource.granularity);\r
+ colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells\r
+ if (id_end >= this._all_slots.length / colspan_lease) {\r
+ /* Limit the display to the current day */\r
+ id_end = this._all_slots.length / colspan_lease\r
+ }\r
+ lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET);\r
+ // the same slots might be affected multiple times.\r
+ // PENDING_IN + PENDING_OUT => IN \r
+ //\r
+ // RESERVED vs SELECTED !\r
+ //\r
+ // PENDING !!\r
+ switch(lease_status) {\r
+ case STATE_SET_IN:\r
+ lease_class = 'selected'; // my leases\r
+ lease_success = '';\r
+ break;\r
+ case STATE_SET_IN_SUCCESS:\r
+ lease_class = 'selected'; // my leases\r
+ lease_success = 'success';\r
+ case STATE_SET_OUT_FAILURE:\r
+ lease_class = 'selected'; // my leases\r
+ lease_success = 'failure';\r
+ break;\r
+ case STATE_SET_OUT:\r
+ lease_class = 'reserved'; // other leases\r
+ lease_success = '';\r
+ break;\r
+ case STATE_SET_OUT_SUCCESS:\r
+ lease_class = 'free'; // other leases\r
+ lease_success = 'success';\r
+ break;\r
+ case STATE_SET_IN_FAILURE:\r
+ lease_class = 'free'; // other leases\r
+ lease_success = 'failure';\r
+ break;\r
+ case STATE_SET_IN_PENDING:\r
+ lease_class = 'pendingin';\r
+ lease_success = '';\r
+ break;\r
+ case STATE_SET_OUT_PENDING:\r
+ // pending_in & pending_out == IN == replacement\r
+ if (resource.leases[i].status == 'pendingin')\r
+ lease_class = 'pendingin'\r
+ else\r
+ lease_class = 'pendingout';\r
+ lease_success = '';\r
+ break;\r
+ \r
+ }\r
+\r
+ for (i = id_start; i < id_end; i++) {\r
+ resource.leases[i].status = lease_class;\r
+ resource.leases[i].success = lease_success;\r
+ }\r
+ },\r
+\r
/* XXX IN TEMPLATE XXX\r
if (SchedulerDataViewData.length == 0) {\r
$("#plugin-scheduler").hide();\r
_initUI: function() \r
{\r
var self = this;\r
+ var scope = self._get_scope();\r
+\r
+ var num_hidden_cells;\r
\r
$("#DateToRes").datepicker({\r
+ dateFormat: "D, d M yy",\r
onRender: function(date) {\r
return date.valueOf() < now.valueOf() ? 'disabled' : '';\r
}\r
SchedulerDateSelected = new Date(ev.date);\r
SchedulerDateSelected.setHours(0,0,0,0);\r
// Set slider to origin\r
- $('#tblSlider').slider('setValue', 0); // XXX\r
+ //$('#tblSlider').slider('setValue', 0); // XXX\r
// Refresh leases\r
self._scope_clear_leases();\r
- self._scope_set_leases();\r
+ self._set_all_lease_slots();\r
// Refresh display\r
self._get_scope().$apply();\r
}).datepicker('setValue', SchedulerDateSelected); //.data('datepicker');\r
\r
//init Slider\r
+ num_hidden_cells = self._all_slots.length - self._num_visible_cells;\r
+ init_cell = (new Date().getHours() - 1) * 3600 / self._granularity;\r
+ if (init_cell > num_hidden_cells)\r
+ init_cell = num_hidden_cells;\r
+\r
$('#tblSlider').slider({\r
min: 0,\r
- max: (self._all_slots.length - self._num_visible_cells) / self._lcm_colspan,\r
- value: 0,\r
+ max: num_hidden_cells,\r
+ value: init_cell,\r
}).on('slide', function(ev) {\r
var scope = self._get_scope();\r
- scope.from = ev.value * self._lcm_colspan;\r
+ scope.from = ev.value;\r
scope.$apply();\r
});\r
+ scope.from = init_cell;\r
+ scope.$apply();\r
\r
$("#plugin-scheduler-loader").hide();\r
$("#plugin-scheduler").show();\r
},\r
\r
- // GUI EVENTS\r
-\r
- // TO BE REMOVED\r
- _on_submit : function()\r
- {\r
- var leasesForCommit = new Array();\r
- var tmpDateTime = SchedulerDateSelected;\r
- for (var i = 0; i < SchedulerData.length; i++)\r
- {\r
- var tpmR = SchedulerData[i];\r
- //for capturing start and end of the lease\r
- var newLeaseStarted = false;\r
- for (var j = 0; j < tpmR.leases.length; j++) {\r
- var tpmL = tpmR.leases[j];\r
- if (newLeaseStarted == false && tpmL.status == 'selected') {\r
- //get date of the slot\r
- tmpDateTime = schedulerGetDateTimeFromSlotId(tpmL.id, tmpDateTime);\r
- var unixStartTime = tmpDateTime.getTime() / 1000;\r
- //add lease object\r
- leasesForCommit.push({\r
- resource: tpmR.id,\r
- //granularity: tpmR.granularity,\r
- //lease_type: null,\r
- //slice: null,\r
- start_time: unixStartTime,\r
- end_time: null,\r
- //duration: null\r
- });\r
- console.log(tpmR.id);\r
- newLeaseStarted = true;\r
- } else if (newLeaseStarted == true && tpmL.status != 'selected') {\r
- //get date of the slot\r
- tmpDateTime = schedulerGetDateTimeFromSlotId(tpmL.id, tmpDateTime);\r
- var unixEndTime = tmpDateTime.getTime() / 1000;\r
- //upate end_time\r
- var tmpCL = leasesForCommit[leasesForCommit.length - 1];\r
- tmpCL.end_time = unixEndTime;\r
- //tmpCL.duration = schedulerFindDuration(tmpCL.start_time, tmpCL.end_time, tmpCL.granularity);\r
- newLeaseStarted = false;\r
- }\r
- }\r
- }\r
- console.log(leasesForCommit);\r
- for (var i = 0; i < leasesForCommit.length; i++) {\r
- manifold.raise_event(scheduler2Instance.options.query_lease_uuid, SET_ADD, leasesForCommit[i]);\r
- }\r
- },\r
- \r
// PRIVATE METHODS\r
\r
/**\r
return (y==0) ? x : this._gcd(y, x % y);\r
},\r
\r
+ _gcdn : function(array)\r
+ {\r
+ var self = this;\r
+ return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); });\r
+ },\r
+\r
/**\r
* Least common multiple\r
*/\r
{\r
return x * y / this._gcd(x, y);\r
},\r
+\r
+ _lcmn : function(array)\r
+ {\r
+ var self = this;\r
+ return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); });\r
+ },\r
\r
_pad_str : function(i)\r
{\r
/// ...and add the slot to the list of results\r
slots.push({ id: i, time: tmpTime });\r
// Increment the date with the granularity\r
- d = new Date(d.getTime() + this._granularity * 1000);\r
+ d = new Date(d.getTime() + this._slot_length * 1000);\r
i++;\r
}\r
return slots;\r