Improved testbed plugin to support facility_name and testbed_name filters
[myslice.git] / plugins / testbeds / static / js / testbeds.js
1 /**
2  * TestbedsPlugin: List of testbeds plugin
3  * Version:     0.1
4  * Description: TODO -> generalize to a list of possible filters
5  *              This file is part of the Manifold project 
6  * Requires:    js/plugin.js
7  * URL:         http://www.myslice.info
8  * Author:      Loïc Baron <loic.baron@lip6.fr>
9  * Copyright:   Copyright 2012-2013 UPMC Sorbonne Universités
10  * License:     GPLv3
11  */
12
13 // XXX Inherit from an AngularPlugin class ?
14 (function (ng, app) {
15
16     // Define our Controller constructor.
17     function Controller($scope) {
18         /* Contructor */
19
20         /* Plugin instance */
21         $scope.instance = null;
22
23         $scope.facility_names = Array();
24         $scope.testbed_names = new Object();
25
26         /* Models */
27         //$scope.testbeds = Array();
28         $scope._facility_active = new Object();
29         $scope._testbed_active  = new Object();
30
31         $scope.is_facility_active = function(facility)
32         {
33             return (($scope._facility_active[facility] === undefined) || $scope._facility_active[facility]);
34         };
35
36         $scope.is_testbed_active = function(facility, testbed)
37         {
38             return (($scope._testbed_active[facility] === undefined) || 
39                     ($scope._testbed_active[facility][testbed] === undefined) || 
40                     ($scope._testbed_active[facility][testbed]));
41         };
42
43         $scope.set_facility_active = function(facility, value)
44         {
45             $scope._facility_active[facility] = value;
46         };
47
48         $scope.set_testbed_active = function(facility, testbed, value)
49         {
50             if ($scope._testbed_active[facility] === undefined)
51                 $scope._testbed_active[facility] = new Object();
52             $scope._testbed_active[facility][testbed] = value;
53         };
54     
55         /* Click event */
56
57         $scope.select_facility = function(facility)
58         {
59             var selected, prev_selected, num, num_selected, num_prev_selected, filter;
60
61             prev_selected = $.map($scope.facility_names, function(x, i) {
62                 return $scope.is_facility_active(x) ? x : null;
63             });
64
65             $scope.set_facility_active(facility, ! $scope.is_facility_active(facility));
66
67             selected = $.map($scope.facility_names, function(x, i) {
68                 return $scope.is_facility_active(x) ? x : null;
69             });
70
71             num = $scope.facility_names.length;
72             prev_num_selected = prev_selected.length;
73             num_selected = selected.length;
74
75             if ((prev_num_selected != 0) && (prev_num_selected != num)) {
76                 // Remove previous filter
77                 filter = ['facility_name', 'included', prev_selected];
78                 manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
79             }
80
81             if (num_selected != num) {
82                 filter = ['facility_name', 'included', selected];
83                 manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
84             }
85         };
86
87         $scope.select_testbed = function(facility, testbed)
88         {
89             var selected, prev_selected, num, num_selected, num_prev_selected, filter;
90
91             prev_selected = Array();
92             $.each($scope.facility_names, function(i, facility_name) {
93                 $.each($scope.testbed_names[facility_name], function(j, testbed_name) {
94                     if ($scope.is_testbed_active(facility_name, testbed_name)) {
95                         // XXX We should have a joint facility/testbed filter
96                         prev_selected.push(testbed_name);
97                     }
98                 });
99
100             });
101
102             $scope.set_testbed_active(facility, testbed, ! $scope.is_testbed_active(facility, testbed));
103
104             selected = Array();
105             $.each($scope.facility_names, function(i, facility_name) {
106                 $.each($scope.testbed_names[facility_name], function(j, testbed_name) {
107                     if ($scope.is_testbed_active(facility_name, testbed_name)) {
108                         // XXX We should have a joint facility/testbed filter
109                         selected.push(testbed_name);
110                     }
111                 });
112
113             });
114
115             num = 0;
116             $.each($scope.facility_names, function(i, facility_name) {
117                 num += $scope.testbed_names[facility_name].length;
118             });
119             prev_num_selected = prev_selected.length;
120             num_selected = selected.length;
121
122             if ((prev_num_selected != 0) && (prev_num_selected != num)) {
123                 // Remove previous filter
124                 // XXX We should have a joint facility/testbed filter
125                 filter = ['testbed_name', 'included', prev_selected];
126                 manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
127             }
128
129             if (num_selected != num) {
130                 // XXX We should have a joint facility/testbed filter
131                 filter = ['testbed_name', 'included', selected];
132                 manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
133             }
134         };
135
136         /* Return object reference */
137         return (this);
138     }
139
140     // Define the Controller as the constructor function.
141     app.controller("TestbedsCtrl", Controller);
142
143 })(angular, ManifoldApp);
144
145 (function($){
146     var TestbedsPlugin = Plugin.extend({
147
148         /** XXX to check
149          * @brief Plugin constructor
150          * @param options : an associative array of setting values
151          * @param element : 
152          * @return : a jQuery collection of objects on which the plugin is
153          *     applied, which allows to maintain chainability of calls
154          */
155         init: function(options, element) 
156         {
157             // Call the parent constructor, see FAQ when forgotten
158             this._super(options, element);
159
160             /* Member variables */
161             this.testbeds = Array();
162
163             this._get_scope().instance = this;
164
165             /* Handlers */
166             this.listen_query(options.query_uuid);
167             this.listen_query(options.query_networks_uuid, 'networks');
168         },
169
170
171         /* HANDLERS */
172
173         /* When a filter is added/removed, update the list of filters local to the plugin */
174         /*
175         on_filter_added: function(filter)
176         {
177             this.filters.push(filter);
178             if(filter[0]=='network_hrn'){
179                 if(filter[1]=='included'){
180                     $.each(filter[2], function(value){
181                         $("#testbeds-filter_"+value).addClass("active");
182                     });
183                 }else if(filter[1]=='=' || filter[1]=='=='){
184                     $("#testbeds-filter_"+filter[2]).addClass("active");
185                 }
186                 // XXX NAMING
187                 // XXX How to display unsupported filters
188                 // XXX Constants for operators
189             }
190         },
191         on_filter_removed: function(filter)
192         {
193             this.filters = $.grep(this.filters, function(x) {
194                 return x == filter;
195             });
196             if(filter[0]=='network_hrn'){
197                 if(filter[1]=='included'){
198                     $.each(filter[2], function(value){
199                         $("#testbeds-filter_"+value).removeClass("active");
200                     });
201                 }else if(filter[1]=='=' || filter[1]=='=='){
202                     $("#testbeds-filter_"+filter[2]).removeClass("active");
203                 }
204             }
205         },
206         */
207         // ... be sure to list all events here
208
209         on_query_done: function()
210         {
211             var scope, query_ext, resources;
212             scope = this._get_scope();
213             query_ext = manifold.query_store.find_analyzed_query_ext(this.options.query_uuid);
214             resources = query_ext.records.values();
215
216             $.each(resources, function(i, resource) {
217                 if ($.inArray(resource.facility_name, scope.facility_names) == -1)
218                     scope.facility_names.push(resource.facility_name);
219                 if (scope.testbed_names[resource.facility_name] === undefined)
220                     scope.testbed_names[resource.facility_name] = Array();
221                 if ($.inArray(resource.testbed_name, scope.testbed_names[resource.facility_name]) == -1)
222                     scope.testbed_names[resource.facility_name].push(resource.testbed_name);
223             });
224
225             scope.$apply();
226         },
227
228         /*
229         on_networks_query_done: function()
230         {
231             var scope = this._get_scope();
232             var query_ext = manifold.query_store.find_analyzed_query_ext(this.options.query_networks_uuid);
233             scope.testbeds = query_ext.records.values();
234             $.each(scope.testbeds, function(i, testbed) { testbed.active = true });
235             scope.$apply();
236         },
237 */
238
239         /* INTERNAL FUNCTIONS */
240
241         _get_scope : function()
242         {
243             return angular.element('[ng-controller=TestbedsCtrl]').scope()
244         },
245
246 /*
247         _addFilter: function(key, op, value)
248         {
249             values = Array();
250             // get the previous list of values for this key, ex: [ple,nitos]
251             // remove the previous filter
252             network_filter = $.grep(this.filters, function(x) {
253                 return x[0] == "network_hrn";
254             });
255             if(network_filter.length > 0){
256                 $.each(network_filter, function(i,f){
257                     values = f[2];
258                 });
259             }
260             // Add the new value to list of values, ex: wilab
261             values.push(value);
262             
263             // Update the filter with the new list of values, ex: [ple,nitos,wilab]
264             manifold.raise_event(this.options.query_uuid, FILTER_ADDED, [key, op, values]);
265         },
266
267         _removeFilter: function(key, op, value)
268         {
269             console.log("remove "+value);
270             var self = this;
271             values = Array();
272             // get the previous list of values for this key, ex: [ple,nitos,wilab]
273             // remove the previous filter
274             network_filter = $.grep(this.filters, function(x) {
275                 return x[0] == "network_hrn";
276             });
277             if(network_filter.length > 0){
278                 $.each(network_filter, function(i,f){
279                     values = f[2];
280                     manifold.raise_event(self.options.query_uuid, FILTER_REMOVED, [key, op, values]);
281                 });
282             }
283
284             // remove the value from the list of values, ex: wilab
285             values = $.grep(values, function(x) {
286                 return x != value;
287             });
288             if(values.length>0){
289                 // Update the filter with the new list of values, ex: [ple,nitos]
290                 manifold.raise_event(this.options.query_uuid, FILTER_ADDED, [key, op, values]);
291             }
292         }
293 */
294     });
295
296     /* Plugin registration */
297     $.plugin('TestbedsPlugin', TestbedsPlugin);
298
299     // TODO Here use cases for instanciating plugins in different ways like in the pastie.
300
301 })(jQuery);