fbc43418c92684ec06c589f847250c817ca85593
[myslice.git] / portal / sliceview.py
1 from django.template                 import RequestContext
2 from django.shortcuts                import render_to_response
3
4 from portal.templateviews            import LoginRequiredAutoLogoutView
5
6 from unfold.page                     import Page
7 from manifold.core.query             import Query, AnalyzedQuery
8
9 from myslice.viewutils               import topmenu_items, the_user
10
11 from plugins.raw.raw                 import Raw
12 from plugins.stack.stack             import Stack
13 from plugins.tabs.tabs               import Tabs
14 from plugins.hazelnut                import Hazelnut 
15 from plugins.resources_selected      import ResourcesSelected
16 from plugins.googlemap              import GoogleMap
17 from plugins.senslabmap.senslabmap   import SensLabMap
18 from plugins.querycode.querycode     import QueryCode
19 from plugins.query_editor            import QueryEditor
20 from plugins.active_filters          import ActiveFilters
21 from plugins.quickfilter.quickfilter import QuickFilter
22 from plugins.messages.messages       import Messages
23 #from plugins.updater                 import Updater
24
25 tmp_default_slice='ple.upmc.myslicedemo'
26
27 # temporary : turn off the users part to speed things up
28 do_query_users=True
29
30 class SliceView (LoginRequiredAutoLogoutView):
31
32     def get (self,request, slicename=tmp_default_slice):
33     
34         page = Page(request)
35         page.add_css_files ('css/slice-view.css')
36         page.add_js_chunks ('$(function() { console.log("sliceview: jQuery version " + $.fn.jquery); });')
37         page.add_js_chunks ('$(function() { console.log("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
38         page.expose_js_metadata()
39     
40         metadata = page.get_metadata()
41         resource_md = metadata.details_by_object('resource')
42         resource_fields = [column['name'] for column in resource_md['column']]
43     
44         user_md = metadata.details_by_object('user')
45         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
46     
47         # TODO The query to run is embedded in the URL
48         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
49         main_query.select(
50                 'slice_hrn',
51                 'resource.resource_hrn', 'resource.hostname', 'resource.type', 'resource.network_hrn',
52                 #'lease.urn',
53                 'user.user_hrn',
54                 #'application.measurement_point.counter'
55         )
56     
57         query_resource_all = Query.get('resource').select(resource_fields)
58         if do_query_users:
59             query_user_all = Query.get('user').select(user_fields)
60     
61         aq = AnalyzedQuery(main_query, metadata=metadata)
62         page.enqueue_query(main_query, analyzed_query=aq)
63         page.enqueue_query(query_resource_all)
64         if do_query_users:
65             page.enqueue_query(query_user_all)
66     
67         # ... and for the relations
68         # XXX Let's hardcode resources for now
69         sq_resource    = aq.subquery('resource')
70         sq_user        = aq.subquery('user')
71         sq_lease       = aq.subquery('lease')
72         sq_measurement = aq.subquery('measurement')
73         
74     
75         # Prepare the display according to all metadata
76         # (some parts will be pending, others can be triggered by users).
77         # 
78         # For example slice measurements will not be requested by default...
79     
80         # Create the base layout (Stack)...
81         main_stack = Stack (
82             page=page,
83             title="Slice %s"%slicename,
84             sons=[],
85         )
86     
87         # ... responsible for the slice properties...
88     
89         # a nice header
90         main_stack.insert (
91             Raw (page=page,
92                  togglable=False, 
93                  toggled=True,
94                  html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
95         )
96     
97         # --------------------------------------------------------------------------
98         # ResourcesSelected
99         #
100         main_stack.insert(ResourcesSelected(
101             page                = page,
102             title               = 'Pending operations',
103             query               = main_query,
104             togglable           = True,
105             domid               = 'pending',
106             outline_complete    = True,
107         ))
108     
109 #        main_stack.insert(
110 #            Raw (page=page,togglable=False, toggled=True,html='<b>Description:</b> TODO')
111 #        )
112     
113         # the resources part is made of a Stack, 
114         # with first a Tabs (List, Geographic), 
115         # and second the QueryEditor to tweak the set of attributes to show
116         resources_as_list = Hazelnut( 
117             page       = page,
118             title      = 'Resources as a List',
119             domid      = 'resources_list',
120             # this is the query at the core of the slice list
121             query      = sq_resource,
122             query_all  = query_resource_all,
123             checkboxes = True,
124             datatables_options = { 
125                 # for now we turn off sorting on the checkboxes columns this way
126                 # this of course should be automatic in hazelnut
127                 'aoColumns'     : [None, None, None, None, {'bSortable': False}],
128                 'iDisplayLength': 25,
129                 'bLengthChange' : True,
130                 'bAutiWidth'    : True,
131                 },
132             )
133
134         resources_as_map = GoogleMap(
135             page       = page,
136             title      = 'Geographic view',
137             domid      = 'gmap',
138             # tab's sons preferably turn this off
139             togglable  = False,
140             query      = sq_resource,
141             query_all  = query_resource_all,
142             checkboxes = True,
143             # center on Paris
144             latitude   = 49.,
145             longitude  = 2.2,
146             zoom       = 3,
147         )
148
149         resources_query_editor = QueryEditor(
150             page  = page,
151             query = sq_resource,
152             title = "Select Columns",
153             )
154         resources_active_filters = ActiveFilters(
155             page  = page,
156             query = sq_resource,
157             title = "Active Filters ?",
158             )
159
160         resources_area = Stack (
161             page=page,
162             domid="resources",
163             togglable=True,
164             title="Resources",
165             outline_complete=True,
166             sons = [
167                 Tabs ( page=page, 
168                        sons=[ resources_as_list, resources_as_map, ] ,
169                        active_domid = 'gmap',
170                        ),
171                 Tabs ( page=page,
172                        title="Customize Resources layout",
173                        togglable=True,
174                        toggled='persistent',
175                        domid="customize-resources",
176                        outline_complete=True,
177                        sons = [ resources_query_editor, resources_active_filters, ],
178                        ),
179                 ]
180             )
181
182         main_stack.insert (resources_area)
183
184
185 #        sq_plugin = Tabs (
186 #            page=page,
187 #            title="Slice view for %s"%slicename,
188 #            togglable=True,
189 #            sons=[],
190 #        )
191     
192     
193         ############################################################################
194         # RESOURCES
195         # 
196         # A stack inserted in the subquery tab that will hold all operations
197         # related to resources
198         # 
199         
200 #        stack_resources = Stack(
201 #            page = page,
202 #            title = 'Resources',
203 #            sons=[],
204 #        )
205     
206 #        stack_resources.insert(resource_active_filters)
207 #    
208 #    
209 #        stack_resources.insert(tab_resource_plugins)
210     
211 #        sq_plugin.insert(stack_resources)
212     
213         ############################################################################
214         # USERS
215         # 
216     
217         if do_query_users:
218             tab_users = Tabs(
219                 page                = page,
220                 domid               = 'users',
221                 outline_complete    = True,
222                 togglable           = True,
223                 title               = 'Users',
224                 active_domid        = 'checkboxes2',
225                 )
226             main_stack.insert(tab_users)
227     
228             tab_users.insert(Hazelnut( 
229                 page        = page,
230                 title       = 'Users List',
231                 domid       = 'checkboxes2',
232                 # tab's sons preferably turn this off
233                 togglable   = False,
234                 # this is the query at the core of the slice list
235                 query       = sq_user,
236                 query_all  = query_user_all,
237                 checkboxes  = True,
238                 datatables_options = { 
239                     # for now we turn off sorting on the checkboxes columns this way
240                     # this of course should be automatic in hazelnut
241                     'aoColumns'      : [None, None, None, None, {'bSortable': False}],
242                     'iDisplayLength' : 25,
243                     'bLengthChange'  : True,
244                 },
245             ))
246     
247         tab_measurements = Tabs (
248             page                = page,
249             active_domid        = 'checkboxes3',
250             outline_complete    = True,
251             togglable           = True,
252             title               = 'Measurements',
253             domid               = 'measurements',
254         )
255         main_stack.insert(tab_measurements)
256     
257         tab_measurements.insert(Hazelnut( 
258             page        = page,
259             title       = 'Measurements',
260             domid       = 'checkboxes3',
261             # tab's sons preferably turn this off
262             togglable   = False,
263             # this is the query at the core of the slice list
264             query       = sq_measurement,
265             checkboxes  = True,
266             datatables_options = { 
267                 # for now we turn off sorting on the checkboxes columns this way
268                 # this of course should be automatic in hazelnut
269                 'aoColumns'      : [None, None, None, None, {'bSortable': False}],
270                 'iDisplayLength' : 25,
271                 'bLengthChange'  : True,
272             },
273         ))
274     
275         main_stack.insert(Messages(
276             page   = page,
277             title  = "Runtime messages for slice %s"%slicename,
278             domid  = "msgs-pre",
279             levels = "ALL",
280             # plain messages are probably less nice for production but more reliable for development for now
281             transient = False,
282             # these make sense only in non-transient mode..
283             togglable = True,
284             toggled = 'persistent',
285             outline_complete = True,
286         ))
287     
288     
289         # variables that will get passed to the view-unfold1.html template
290         template_env = {}
291         
292         # define 'unfold1_main' to the template engine - the main contents
293         template_env [ 'unfold1_main' ] = main_stack.render(request)
294     
295         # more general variables expected in the template
296         template_env [ 'title' ] = '%(slicename)s'%locals()
297         # the menu items on the top
298         template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) 
299         # so we can sho who is logged
300         template_env [ 'username' ] = the_user (request) 
301     
302         # don't forget to run the requests
303         page.expose_queries ()
304     
305         # xxx create another plugin with the same query and a different layout (with_datatables)
306         # show that it worls as expected, one single api call to backend and 2 refreshed views
307     
308         # the prelude object in page contains a summary of the requirements() for all plugins
309         # define {js,css}_{files,chunks}
310         prelude_env = page.prelude_env()
311         template_env.update(prelude_env)
312         result=render_to_response ('view-unfold1.html',template_env,
313                                    context_instance=RequestContext(request))
314         return result