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