3 # Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece
\r
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
\r
6 # of this software and associated documentation files (the "Software"), to deal
\r
7 # in the Software without restriction, including without limitation the rights
\r
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
9 # copies of the Software, and to permit persons to whom the Software is
\r
10 # furnished to do so, subject to the following conditions:
\r
12 # The above copyright notice and this permission notice shall be included in
\r
13 # all copies or substantial portions of the Software.
\r
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\r
24 # This is a MySlice plugin for the NITOS Scheduler
\r
25 # Nitos Scheduler v1
\r
31 var scheduler2Instance;
\r
32 //is ctrl keyboard button pressed
\r
33 var schedulerCtrlPressed = false;
\r
35 var schedulerTblId = "scheduler-reservation-table";
\r
36 var schedulerTblFirstColWidth = 150;
\r
38 var schedulerSlotsPerHour = 6;
\r
39 var schedulerMaxRows = 12;
\r
40 var SchedulerData = [];
\r
41 var SchedulerSlots = [];
\r
42 var SchedulerDateSelected = new Date();
\r
43 var SchedulerDataViewData = [];
\r
44 var SchedulerSlotsViewData = [];
\r
45 var SchedulerTotalCells;
\r
46 var SchedulerTotalVisibleCells;
\r
48 var _schedulerCurrentCellPosition = 0;
\r
49 var _leasesDone = false;
\r
50 var _resourcesDone = false;
\r
52 var schedulerDebug = true;
\r
54 var tmpSchedulerLeases = [];
\r
57 scheduler2 = Plugin.extend({
\r
60 * @brief Plugin constructor
\r
61 * @param options : an associative array of setting values
\r
63 * @return : a jQuery collection of objects on which the plugin is
\r
64 * applied, which allows to maintain chainability of calls
\r
66 init: function (options, element) {
\r
67 this.classname="scheduler2";
\r
68 // Call the parent constructor, see FAQ when forgotten
\r
69 this._super(options, element);
\r
70 scheduler2Instance = this;
\r
71 // We need to remember the active filter for datatables filtering
72 this.filters = Array();
\r
75 SchedulerSlots = schedulerGetSlots(60/schedulerSlotsPerHour);
\r
76 //selection from table
\r
77 $(window).keydown(function (evt) {
\r
78 if (evt.which == 17) { // ctrl
\r
79 schedulerCtrlPressed = true;
\r
81 }).keyup(function (evt) {
\r
82 if (evt.which == 17) { // ctrl
\r
83 schedulerCtrlPressed = false;
\r
86 $("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);
\r
88 // Explain this will allow query events to be handled
\r
89 // What happens when we don't define some events ?
\r
90 // Some can be less efficient
\r
92 if (schedulerDebug) console.time("Listening_to_queries");
\r
93 /* Listening to queries */
\r
95 this.listen_query(options.query_uuid);
96 this.listen_query(options.query_all_uuid, 'all');
\r
97 this.listen_query(options.query_all_resources_uuid, 'all_resources');
\r
98 this.listen_query(options.query_lease_uuid, 'lease');
\r
99 //this.listen_query(options.query_lease_uuid, 'lease');
\r
100 if (schedulerDebug) console.timeEnd("Listening_to_queries");
\r
106 /* all_ev QUERY HANDLERS Start */
\r
107 on_all_ev_clear_records: function (data) {
\r
108 //alert('all_ev clear_records');
\r
110 on_all_ev_query_in_progress: function (data) {
\r
111 // alert('all_ev query_in_progress');
\r
113 on_all_ev_new_record: function (data) {
\r
114 //alert('all_ev new_record');
\r
116 on_all_ev_query_done: function (data) {
\r
117 //alert('all_ev query_done');
\r
119 //another plugin has modified something, that requires you to update your display.
\r
120 on_all_ev_field_state_changed: function (data) {
\r
121 //alert('all_ev query_done');
\r
123 /* all_ev QUERY HANDLERS End */
\r
124 /* all_resources QUERY HANDLERS Start */
\r
125 on_all_resources_clear_records: function (data) {
\r
126 //data is empty on load
\r
128 on_all_resources_query_in_progress: function (data) {
\r
129 //data is empty on load
\r
131 on_all_resources_new_record: function (data) {
\r
132 //alert(data.toSource());
\r
133 if (data.exclusive == true){
\r
134 SchedulerData.push({
\r
136 index: SchedulerData.length,
\r
138 granularity: data.granularity,
\r
139 leases: schedulerGetLeases(60 / schedulerSlotsPerHour, data.granularity),
\r
143 if (schedulerDebug && SchedulerData[SchedulerData.length - 1].org_resource.network_hrn == 'omf') {
\r
144 SchedulerData[SchedulerData.length - 1].granularity = 1800;
\r
147 //alert(data.toSource());
\r
150 on_all_resources_query_done: function (data) {
\r
151 _resourcesDone = true;
\r
152 this._initScheduler();
\r
154 //another plugin has modified something, that requires you to update your display.
\r
155 on_all_resources_field_state_changed: function (data) {
\r
156 //alert('all_resources query_done');
\r
158 /* all_resources QUERY HANDLERS End */
\r
159 /* lease QUERY HANDLERS Start */
\r
160 on_lease_clear_records: function (data) { console.log('clear_records'); },
\r
161 on_lease_query_in_progress: function (data) { console.log('lease_query_in_progress'); },
\r
162 on_lease_new_record: function (data) {
\r
163 if (data.resource.indexOf("nitos")>-1){
\r
164 tmpSchedulerLeases.push({
\r
165 id: schedulerGetSlotId(data.start_time, data.duration, data.granularity),
\r
166 end_id: schedulerGetSlotId(data.end_time, data.duration, data.granularity),
\r
168 status: 'reserved',
\r
169 resource: data.resource,
\r
170 network: data.network,
\r
171 start_time: new Date(data.start_time * 1000),
\r
172 start_time_unixtimestamp: data.start_time,
\r
173 end_time: new Date(data.end_time * 1000),
\r
174 end_time_unixtimestamp: data.end_time,
\r
175 lease_type: data.lease_type,
\r
176 granularity: data.granularity,
\r
177 duration: data.duration
\r
180 //console.log(data.toSource()); console.log('lease_new_record');
\r
182 on_lease_query_done: function (data) {
\r
183 _leasesDone = true;
\r
184 this._initScheduler();
\r
185 // console.log('lease_query_done');
\r
187 //another plugin has modified something, that requires you to update your display.
\r
188 on_lease_field_state_changed: function (data) { console.log('lease_field_state_changed'); },
\r
189 /* lease QUERY HANDLERS End */
\r
193 on_filter_added: function (filter) {
\r
194 this.filters.push(filter);
\r
195 this._SetFiletredResources(this.filters);
\r
197 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
198 if (SchedulerDataViewData.length == 0) {
\r
199 $("#plugin-scheduler").hide();
\r
200 $("#plugin-scheduler-empty").show();
\r
201 tmpScope.clearStuff();
\r
203 $("#plugin-scheduler-empty").hide();
\r
204 $("#plugin-scheduler").show();
\r
205 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
\r
209 on_filter_removed: function (filter) {
210 // Remove corresponding filters
211 this.filters = $.grep(this.filters, function (x) {
\r
212 return x == filter;
\r
214 this._SetFiletredResources(this.filters);
\r
216 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
217 if (SchedulerDataViewData.length == 0) {
\r
218 $("#plugin-scheduler").hide();
\r
219 $("#plugin-scheduler-empty").show();
\r
220 tmpScope.clearStuff();
\r
222 $("#plugin-scheduler-empty").hide();
\r
223 $("#plugin-scheduler").show();
\r
224 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
\r
228 on_filter_clear: function () {
\r
230 this._SetFiletredResources(this.filters);
\r
232 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
233 if (SchedulerDataViewData.length == 0) {
\r
234 $("#plugin-scheduler").hide();
\r
235 $("#plugin-scheduler-empty").show();
\r
236 tmpScope.clearStuff();
\r
238 $("#plugin-scheduler-empty").hide();
\r
239 $("#plugin-scheduler").show();
\r
240 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
\r
244 // ... be sure to list all events here
\r
246 /* RECORD HANDLERS */
\r
247 on_all_new_record: function (record) {
\r
248 //alert('on_all_new_record');
\r
251 debug : function (logTxt) {
\r
252 if (typeof window.console != 'undefined') {
\r
253 console.debug(logTxt);
\r
257 /* INTERNAL FUNCTIONS */
\r
258 _initScheduler: function () {
\r
259 if (_resourcesDone && _leasesDone)
\r
261 SchedulerDataViewData = SchedulerData;
\r
262 /* GUI setup and event binding */
\r
268 _initUI: function () {
\r
270 if (schedulerDebug) console.time("_initUI");
\r
271 //init DatePicker Start
\r
272 $("#DateToRes").datepicker({
\r
273 dateFormat: "yy-mm-dd",
\r
276 }).change(function () {
\r
277 //Scheduler2.loadWithDate();
\r
278 SchedulerDateSelected = $("#DateToRes").datepicker("getDate");
\r
279 if (SchedulerDateSelected != null && SchedulerDateSelected != '') {
\r
280 for (var i=0; i < SchedulerData.length; i++) {
\r
281 SchedulerData[i].leases = schedulerGetLeases(60 / schedulerSlotsPerHour, SchedulerData[i].granularity);
\r
283 scheduler2Instance._FixLeases();
\r
284 $('#tblSlider').slider('value', 0);
\r
285 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
286 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
\r
288 alert("Please select a date, so the scheduler can reserve leases.");
\r
290 }).datepicker('setDate', SchedulerDateSelected);
\r
291 /*.click(function () {
\r
292 $("#ui-datepicker-div").css("z-index", 5);
\r
294 //End init DatePicker
\r
301 $('#tblSlider').slider({
\r
303 max: SchedulerTotalCells - SchedulerTotalVisibleCells,
\r
305 slide: function (event, ui) {
\r
306 //$("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]);
\r
307 //console.log(ui.value);
\r
308 var angScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
309 if (_schedulerCurrentCellPosition > ui.value) {
\r
310 angScope.moveBackSlot(ui.value, ui.value + SchedulerTotalVisibleCells);
\r
312 else if (_schedulerCurrentCellPosition < ui.value) {
\r
313 angScope.moveFrontSlot(ui.value, ui.value + SchedulerTotalVisibleCells);
\r
315 _schedulerCurrentCellPosition = ui.value;
\r
321 $("#plugin-scheduler-loader").hide();
\r
322 $("#plugin-scheduler").show();
\r
323 //fixOddEvenClasses();
\r
324 //$("#" + schedulerTblId + " td:not([class])").addClass("free");
\r
325 if (schedulerDebug) console.timeEnd("_initUI");
\r
328 _FixLeases : function () {
\r
329 for (var i = 0; i < tmpSchedulerLeases.length; i++) {
\r
330 var tmpLea = tmpSchedulerLeases[i];
\r
331 if ((schedulerCompareOnDay(tmpLea.start_time, SchedulerDateSelected) == 0) ||
\r
332 (tmpLea.start_time <= SchedulerDateSelected && SchedulerDateSelected <= tmpLea.end_time) ||
\r
333 (schedulerCompareOnDay(tmpLea.end_time, SchedulerDateSelected) == 0)) {
\r
334 var tmpRes = schedulerFindResourceById(SchedulerData, tmpLea.resource);
\r
335 if (tmpRes != null) {
\r
336 //Replace Lease with current lease from the manifold
\r
337 var orgLease = tmpRes.leases[tmpLea.id];
\r
338 tmpLea['groupid'] = orgLease.groupid;
\r
339 tmpLea['groupIndex'] = orgLease.groupIndex;
\r
340 if (orgLease.groupIndex != 0) {
\r
341 if (!window.console) {
\r
342 console.warn('there is an error with the leases of the resource :' + tmpRes.name + '\n The lease start in the middle of the granularity!' + '\n The Scheduler plugin might not work!');
\r
345 tmpRes.leases[tmpLea.id] = tmpLea;
\r
346 this._ExtractLeaseSlots(tmpRes, tmpRes.leases[tmpLea.id]);
\r
352 _ExtractLeaseSlots: function (tmpRes, lease) {
\r
353 var tmpStartDate = lease.start_time;
\r
354 var tmpEndDate = lease.end_time;
\r
355 var startLoop; var toLoop;
\r
356 if (schedulerCompareOnDay(lease.start_time,lease.end_time) == 0) {
\r
358 startLoop = lease.id;
\r
359 toLoop = lease.end_id;
\r
360 } else if (lease.start_time < SchedulerDateSelected && SchedulerDateSelected < lease.end_time) {
\r
361 //one hole day (more than 3days)
\r
363 toLoop = tmpRes.leases.length;
\r
364 } else if (schedulerCompareOnDay(lease.start_time, SchedulerDateSelected) == 0) {
\r
365 //the same day and extends
\r
366 startLoop = lease.id;
\r
367 toLoop = tmpRes.leases.length;
\r
368 } else if (schedulerCompareOnDay(lease.end_time, SchedulerDateSelected) == 0) {
\r
369 //extends to the last say
\r
371 toLoop = lease.end_id;
\r
373 //var minutGran = tmpRes.granularity * 60;
\r
374 for (var li = lease.id; li < toLoop; li++) {
\r
375 tmpRes.leases[li].status = 'reserved';
\r
379 //tmpRes.leases[tmpLea.id
\r
382 _FixTable: function () {
\r
384 SchedulerTotalCells = SchedulerSlots.length;
\r
385 $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", schedulerTblFirstColWidth); //.css("display", "block");
\r
386 //this get width might need fix depending on the template
\r
387 var tblwidth = $('#scheduler-tab').parent().outerWidth();
\r
388 SchedulerTotalVisibleCells = parseInt((tblwidth - schedulerTblFirstColWidth) / colWidth);
\r
390 //if (SchedulerData.length == 0) {
\r
391 // //puth some test data
\r
392 // SchedulerData.push({ name: 'xyz+aaa', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+aaa', type: 'node' });
\r
393 // SchedulerData.push({ name: 'xyz+bbb', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+bbb', type: 'node' });
\r
394 // SchedulerData.push({ name: 'xyz+ccc', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+ccc', type: 'node' });
\r
395 // SchedulerData.push({ name: 'nitos1', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'nitos1', type: 'node' });
\r
397 var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();
\r
398 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
\r
402 _SetFiletredResources : function (filters) {
\r
403 if (filters.length > 0) {
\r
404 SchedulerDataViewData = new Array();
\r
405 var tmpAddIt = true;
\r
406 for (var i = 0; i < SchedulerData.length; i++) {
\r
408 for (var f = 0; f < filters.length; f++) {
\r
409 tmpAddIt = this._FilterResource(SchedulerData[i], filters[f]);
\r
410 if (tmpAddIt == false) break loopfilters;
\r
413 SchedulerDataViewData.push(SchedulerData[i]);
\r
417 SchedulerDataViewData = SchedulerData;
\r
421 _FilterResource: function (resource, filter) {
\r
422 var key = filter[0];
\r
423 var op = filter[1];
\r
424 var value = filter[2];
\r
425 var colValue = resource.org_resource[key];
\r
427 if (schedulerDebug && colValue == 'omf') colValue = 'nitos';
\r
429 if (op == '=' || op == '==') {
\r
430 if (colValue != value || colValue == null || colValue == "" || colValue == "n/a")
432 } else if (op == 'included') {
\r
433 $.each(value, function (i, x) {
\r
434 if (x == colValue) {
\r
441 } else if (op == '!=') {
\r
442 if (colValue == value || colValue == null || colValue == "" || colValue == "n/a")
449 _SetPeriodInPage: function (start, end) {
\r
453 //Sched2 = new Scheduler2();
\r
455 /* Plugin registration */
\r
456 $.plugin('Scheduler2', scheduler2);
\r
458 // TODO Here use cases for instanciating plugins in different ways like in the pastie.
\r