Chrysostomos for scheduler
[unfold.git] / plugins / scheduler2 / static / js / scheduler2.js
1 /*\r
2 #\r
3 # Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece\r
4 #\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
11 #\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
14 #\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
21 # THE SOFTWARE.\r
22 #\r
23 #\r
24 # This is a MySlice plugin for the NITOS Scheduler\r
25 # Nitos Scheduler v1\r
26 #\r
27 */\r
28 \r
29 /* some params */\r
30 //is ctrl keyboard button pressed\r
31 var schedulerCtrlPressed = false;\r
32 //table Id\r
33 var schedulerTblId = "scheduler-reservation-table";\r
34 var schedulerTblFirstColWidth = 150;\r
35 //Some Data\r
36 var schedulerSlotsPerHour = 6;\r
37 var schedulerMaxRows = 12;\r
38 var SchedulerData = [];\r
39 var SchedulerSlots = [];\r
40 var SchedulerDataViewData = [];\r
41 var SchedulerSlotsViewData = [];\r
42 var SchedulerTotalCells;\r
43 var SchedulerTotalVisibleCells;\r
44 //Help Variables\r
45 var _schedulerCurrentCellPosition = 0;\r
46 var _leasesDone = false;\r
47 var _resourcesDone = false;\r
48 //Enable Debug\r
49 var schedulerDebug = true;\r
50 //tmp to delete\r
51 var tmpSchedulerLeases = [];\r
52 \r
53 (function ($) {\r
54     var scheduler2 = Plugin.extend({\r
55 \r
56         /** XXX to check\r
57          * @brief Plugin constructor\r
58          * @param options : an associative array of setting values\r
59          * @param element : \r
60          * @return : a jQuery collection of objects on which the plugin is\r
61          *     applied, which allows to maintain chainability of calls\r
62          */\r
63         init: function (options, element) {\r
64             this.classname="scheduler2";\r
65             // Call the parent constructor, see FAQ when forgotten\r
66             this._super(options, element);\r
67             // We need to remember the active filter for datatables filtering
68             this.filters = Array();\r
69 \r
70 \r
71             SchedulerSlots = schedulerGetSlots(60/schedulerSlotsPerHour);\r
72             //selection from table \r
73             $(window).keydown(function (evt) {\r
74                 if (evt.which == 17) { // ctrl\r
75                     schedulerCtrlPressed = true;\r
76                 }\r
77             }).keyup(function (evt) {\r
78                 if (evt.which == 17) { // ctrl\r
79                     schedulerCtrlPressed = false;\r
80                 }\r
81             });\r
82             $("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);\r
83 \r
84             // Explain this will allow query events to be handled\r
85             // What happens when we don't define some events ?\r
86             // Some can be less efficient\r
87 \r
88             if (schedulerDebug) console.time("Listening_to_queries");\r
89             /* Listening to queries */\r
90
91             this.listen_query(options.query_uuid);
92             this.listen_query(options.query_all_uuid, 'all');\r
93             this.listen_query(options.query_all_resources_uuid, 'all_resources');\r
94             this.listen_query(options.query_lease_uuid, 'lease');\r
95             //this.listen_query(options.query_lease_uuid, 'lease');\r
96             if (schedulerDebug) console.timeEnd("Listening_to_queries");\r
97 \r
98         },\r
99 \r
100         /* Handlers */\r
101 \r
102         /* all_ev QUERY HANDLERS Start */\r
103         on_all_ev_clear_records: function (data) {\r
104             //alert('all_ev clear_records');\r
105         },\r
106         on_all_ev_query_in_progress: function (data) {\r
107            // alert('all_ev query_in_progress');\r
108         },\r
109         on_all_ev_new_record: function (data) {\r
110             //alert('all_ev new_record');\r
111         },\r
112         on_all_ev_query_done: function (data) {\r
113             //alert('all_ev query_done');\r
114         },\r
115         //another plugin has modified something, that requires you to update your display. \r
116         on_all_ev_field_state_changed: function (data) {\r
117             //alert('all_ev query_done');\r
118         },\r
119         /* all_ev QUERY HANDLERS End */\r
120         /* all_resources QUERY HANDLERS Start */\r
121         on_all_resources_clear_records: function (data) {\r
122             //data is empty on load\r
123         },\r
124         on_all_resources_query_in_progress: function (data) {\r
125             //data is empty on load\r
126         },\r
127         on_all_resources_new_record: function (data) {\r
128             //alert(data.toSource());\r
129             if (data.exclusive == true){\r
130                 SchedulerData.push({\r
131                     id: data.urn,\r
132                     index: SchedulerData.length,\r
133                     name: data.hrn,\r
134                     granularity: data.granularity,\r
135                     leases: schedulerGetLeases(60 / schedulerSlotsPerHour),\r
136                     type: data.type,\r
137                     org_resource: data\r
138                 });\r
139                 if (schedulerDebug && SchedulerData[SchedulerData.length - 1].org_resource.network_hrn == 'omf') {\r
140                     SchedulerData[SchedulerData.length - 1].granularity = 30;\r
141                 }\r
142             }\r
143             //alert(data.toSource());\r
144 \r
145         },\r
146         on_all_resources_query_done: function (data) {\r
147             _resourcesDone = true;\r
148             this._initScheduler();\r
149         },\r
150         //another plugin has modified something, that requires you to update your display. \r
151         on_all_resources_field_state_changed: function (data) {\r
152             //alert('all_resources query_done');\r
153         },\r
154         /* all_resources QUERY HANDLERS End */\r
155         /* lease QUERY HANDLERS Start */\r
156         on_lease_clear_records: function (data) { console.log('clear_records'); },\r
157         on_lease_query_in_progress: function (data) { console.log('lease_query_in_progress'); },\r
158         on_lease_new_record: function (data) {\r
159             tmpSchedulerLeases.push({\r
160                 id: schedulerGetSlotId(data.start_time, data.duration, data.granularity),\r
161                 slice: data.slice,\r
162                 status: 'reserved',\r
163                 resource: data.resource,\r
164                 network: data.network,\r
165                 start_time: new Date(data.start_time * 1000),\r
166                 start_time_unixtimestamp: data.start_time,\r
167                 lease_type: data.lease_type,\r
168                 granularity: data.granularity,\r
169                 duration: data.duration\r
170             });\r
171             //console.log(data.toSource()); console.log('lease_new_record');\r
172         },\r
173         on_lease_query_done: function (data) {\r
174             _leasesDone = true;\r
175             this._initScheduler();\r
176             // console.log('lease_query_done');\r
177         },\r
178         //another plugin has modified something, that requires you to update your display. \r
179         on_lease_field_state_changed: function (data) { console.log('lease_field_state_changed'); },\r
180         /* lease QUERY HANDLERS End */\r
181 \r
182 \r
183         // no prefix\r
184         on_filter_added: function (filter) {\r
185             this.filters.push(filter);\r
186             this._SetFiletredResources(this.filters);\r
187             //angular and UI\r
188             var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
189             if (SchedulerDataViewData.length == 0) {\r
190                 $("#plugin-scheduler").hide();\r
191                 $("#plugin-scheduler-empty").show();\r
192                 tmpScope.clearStuff();\r
193             } else {\r
194                 $("#plugin-scheduler-empty").hide();\r
195                 $("#plugin-scheduler").show();\r
196                 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
197             }\r
198         },
199
200         on_filter_removed: function (filter) {
201             // Remove corresponding filters
202             this.filters = $.grep(this.filters, function (x) {\r
203                 return x == filter;\r
204             });\r
205             this._SetFiletredResources(this.filters);\r
206             //angular and UI\r
207             var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
208             if (SchedulerDataViewData.length == 0) {\r
209                 $("#plugin-scheduler").hide();\r
210                 $("#plugin-scheduler-empty").show();\r
211                 tmpScope.clearStuff();\r
212             } else {\r
213                 $("#plugin-scheduler-empty").hide();\r
214                 $("#plugin-scheduler").show();\r
215                 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
216             }\r
217         },
218
219         on_filter_clear: function () {\r
220             this.filters = [];\r
221             this._SetFiletredResources(this.filters);\r
222             //angular and UI\r
223             var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
224             if (SchedulerDataViewData.length == 0) {\r
225                 $("#plugin-scheduler").hide();\r
226                 $("#plugin-scheduler-empty").show();\r
227                 tmpScope.clearStuff();\r
228             } else {\r
229                 $("#plugin-scheduler-empty").hide();\r
230                 $("#plugin-scheduler").show();\r
231                 tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
232             }\r
233         },\r
234 \r
235         // ... be sure to list all events here\r
236 \r
237         /* RECORD HANDLERS */\r
238         on_all_new_record: function (record) {\r
239             //alert('on_all_new_record');\r
240         },\r
241 \r
242         debug : function (logTxt) {\r
243             if (typeof window.console != 'undefined') {\r
244                 console.debug(logTxt);\r
245             }\r
246         },\r
247 \r
248         /* INTERNAL FUNCTIONS */\r
249         _initScheduler: function () {\r
250             if (_resourcesDone && _leasesDone)\r
251             {\r
252                 SchedulerDataViewData = SchedulerData;\r
253                 /* GUI setup and event binding */\r
254                 this._FixLeases();\r
255                 this._initUI();\r
256             }\r
257         },\r
258 \r
259         _initUI: function () {\r
260             //alert(1);\r
261             if (schedulerDebug) console.time("_initUI");\r
262             //init DatePicker Start\r
263             $("#DateToRes").datepicker({\r
264                 dateFormat: "yy-mm-dd",\r
265                 minDate: 0,\r
266                 numberOfMonths: 3\r
267             }).change(function () {\r
268                 //Scheduler2.loadWithDate();\r
269             }).click(function () {\r
270                 $("#ui-datepicker-div").css("z-index", 5);\r
271             });\r
272             //End init DatePicker\r
273             \r
274             //init Table\r
275             this._FixTable();\r
276             //End init Table\r
277 \r
278             //init Slider\r
279             $('#tblSlider').slider({\r
280                 min: 0,\r
281                 max: SchedulerTotalCells - SchedulerTotalVisibleCells,\r
282                 value: 0,\r
283                 slide: function (event, ui) {\r
284                     //$("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]);\r
285                     //console.log(ui.value);\r
286                     var angScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
287                     if (_schedulerCurrentCellPosition > ui.value) {\r
288                         angScope.moveBackSlot(ui.value, ui.value + SchedulerTotalVisibleCells);\r
289                     }\r
290                     else if (_schedulerCurrentCellPosition < ui.value) {\r
291                         angScope.moveFrontSlot(ui.value, ui.value + SchedulerTotalVisibleCells);\r
292                     }\r
293                     _schedulerCurrentCellPosition = ui.value;\r
294                 }\r
295             });\r
296             //End init Slider\r
297 \r
298             //other stuff\r
299             $("#plugin-scheduler-loader").hide();\r
300             $("#plugin-scheduler").show();\r
301             //fixOddEvenClasses();\r
302             //$("#" + schedulerTblId + " td:not([class])").addClass("free");\r
303             if (schedulerDebug) console.timeEnd("_initUI");\r
304         },\r
305 \r
306         _FixLeases  : function () {\r
307             for (var i = 0; i < tmpSchedulerLeases.length; i++) {\r
308                 var tmpLea = tmpSchedulerLeases[i];\r
309                 var tmpRes = schedulerFindResourceById(SchedulerData, tmpLea.resource);\r
310                 if (tmpRes != null) {\r
311                     //alert(tmpLea.id + '-' + tmpLea.start_time);\r
312                     tmpRes.leases[tmpLea.id] = tmpLea;\r
313                 }\r
314             }\r
315         },\r
316 \r
317         _FixTable: function () {\r
318             var colWidth = 50;\r
319             SchedulerTotalCells = SchedulerSlots.length;\r
320             $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", schedulerTblFirstColWidth); //.css("display", "block");\r
321             //this get width might need fix depending on the template \r
322             var tblwidth = $('#scheduler-tab').parent().outerWidth();\r
323             SchedulerTotalVisibleCells = parseInt((tblwidth - schedulerTblFirstColWidth) / colWidth);\r
324 \r
325             //if (SchedulerData.length == 0) {\r
326             //    //puth some test data\r
327             //    SchedulerData.push({ name: 'xyz+aaa', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+aaa', type: 'node' });\r
328             //    SchedulerData.push({ name: 'xyz+bbb', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+bbb', type: 'node' });\r
329             //    SchedulerData.push({ name: 'xyz+ccc', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'xyz+ccc', type: 'node' });\r
330             //    SchedulerData.push({ name: 'nitos1', leases: schedulerGetLeases(60 / schedulerSlotsPerHour), urn: 'nitos1', type: 'node' });\r
331             //}\r
332             var tmpScope = angular.element(document.getElementById('SchedulerCtrl')).scope();\r
333             tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
334 \r
335         },\r
336 \r
337         _SetFiletredResources : function (filters) {\r
338             if (filters.length > 0) {\r
339                 SchedulerDataViewData = new Array();\r
340                 var tmpAddIt = true;\r
341                 for (var i = 0; i < SchedulerData.length; i++) {\r
342                     loopfilters:\r
343                     for (var f = 0; f < filters.length; f++) {\r
344                         tmpAddIt = this._FilterResource(SchedulerData[i], filters[f]);\r
345                         if (tmpAddIt == false) break loopfilters;\r
346                     }\r
347                     if (tmpAddIt) {\r
348                         SchedulerDataViewData.push(SchedulerData[i]);\r
349                     }\r
350                 }\r
351             } else {\r
352                 SchedulerDataViewData = SchedulerData;\r
353             }\r
354         },\r
355 \r
356         _FilterResource: function (resource, filter) {\r
357             var key = filter[0];\r
358             var op = filter[1];\r
359             var value = filter[2];\r
360             var colValue = resource.org_resource[key];\r
361             var ret = true;\r
362             if (schedulerDebug &&  colValue == 'omf') colValue = 'nitos';\r
363 \r
364             if (op == '=' || op == '==') {\r
365                 if (colValue != value || colValue == null || colValue == "" || colValue == "n/a")
366                     ret = false;\r
367             } else if (op == 'included') {\r
368                 $.each(value, function (i, x) {\r
369                     if (x == colValue) {\r
370                         ret = true;\r
371                         return false;\r
372                     } else {\r
373                         ret = false;\r
374                     }\r
375                 });\r
376             } else if (op == '!=') {\r
377                 if (colValue == value || colValue == null || colValue == "" || colValue == "n/a")
378                     ret = false;\r
379             }\r
380 \r
381             return ret;\r
382         },\r
383 \r
384         _SetPeriodInPage: function (start, end) {\r
385         }\r
386     });\r
387 \r
388     //Sched2 = new Scheduler2();\r
389 \r
390     /* Plugin registration */\r
391     $.plugin('Scheduler2', scheduler2);\r
392 \r
393     // TODO Here use cases for instanciating plugins in different ways like in the pastie.\r
394 \r
395 \r
396 })(jQuery);\r
397 \r
398 \r
399 \r