hazelnuts with checkboxes enabled can be sorted by that column - e.g. to see users...
[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 tmp_default_slice='ple.upmc.myslicedemo'
25
26 # temporary : turn off the users part to speed things up
27 do_query_users=True
28
29 class SliceView (LoginRequiredAutoLogoutView):
30
31     def get (self,request, slicename=tmp_default_slice):
32     
33         page = Page(request)
34         page.add_css_files ('css/slice-view.css')
35         page.add_js_files  ( [ "js/common.functions.js" ] )
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 (Pending Operations)
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         # --------------------------------------------------------------------------
110         # RESOURCES
111         # the resources part is made of a Tabs (Geographic, List), 
112
113         resources_as_map = GoogleMap(
114             page       = page,
115             title      = 'Geographic view',
116             domid      = 'resources-map',
117             # tab's sons preferably turn this off
118             togglable  = False,
119             query      = sq_resource,
120             query_all  = query_resource_all,
121             checkboxes = True,
122             # center on Paris
123             latitude   = 49.,
124             longitude  = 9,
125             zoom       = 4,
126         )
127
128         resources_as_list = Hazelnut( 
129             page       = page,
130             domid      = 'resources-list',
131             # this is the query at the core of the slice list
132             query      = sq_resource,
133             query_all  = query_resource_all,
134             checkboxes = True,
135             datatables_options = { 
136                 'iDisplayLength': 25,
137                 'bLengthChange' : True,
138                 'bAutoWidth'    : True,
139                 },
140             )
141
142         resources_query_editor = QueryEditor(
143             page  = page,
144             query = query_resource_all,
145             title = "Select Columns",
146             )
147         resources_active_filters = ActiveFilters(
148             page  = page,
149             query = sq_resource,
150             title = "Active Filters ?",
151             )
152
153         # List area itself is a Stack with hazelnut on top,
154         # and a togglable tabs for customization plugins 
155         resources_as_list_area = Stack(
156             page        = page,
157             title       = 'Resources as a List',
158             domid       = 'resources-list-area',
159             sons= [ resources_as_list, 
160                     Tabs ( page=page,
161                            title="Customize Resources layout",
162                            togglable=True,
163                            toggled='persistent',
164                            domid="customize-resources",
165                            outline_complete=True,
166                            sons = [ resources_query_editor, resources_active_filters, ],
167                            ),
168                     ],
169             )
170         resources_area = Tabs ( page=page, 
171                                 domid="resources",
172                                 togglable=True,
173                                 title="Resources",
174                                 outline_complete=True,
175                                 sons=[ resources_as_map, resources_as_list_area, ],
176                                 active_domid = 'resources-map',
177                                 )
178         main_stack.insert (resources_area)
179
180
181         # --------------------------------------------------------------------------
182         # USERS
183     
184         if do_query_users:
185             tab_users = Tabs(
186                 page                = page,
187                 domid               = 'users',
188                 outline_complete    = True,
189                 togglable           = True,
190                 title               = 'Users',
191                 active_domid        = 'checkboxes2',
192                 )
193             main_stack.insert(tab_users)
194     
195             tab_users.insert(Hazelnut( 
196                 page        = page,
197                 title       = 'Users List',
198                 domid       = 'checkboxes2',
199                 # tab's sons preferably turn this off
200                 togglable   = False,
201                 # this is the query at the core of the slice list
202                 query       = sq_user,
203                 query_all  = query_user_all,
204                 checkboxes  = True,
205                 datatables_options = { 
206                     'iDisplayLength' : 25,
207                     'bLengthChange'  : True,
208                     'bAutoWidth'     : True,
209                 },
210             ))
211     
212         # --------------------------------------------------------------------------
213         # MEASUREMENTS
214         tab_measurements = Tabs (
215             page                = page,
216             active_domid        = 'checkboxes3',
217             outline_complete    = True,
218             togglable           = True,
219             title               = 'Measurements',
220             domid               = 'measurements',
221         )
222         main_stack.insert(tab_measurements)
223     
224         tab_measurements.insert(Hazelnut( 
225             page        = page,
226             title       = 'Measurements',
227             domid       = 'checkboxes3',
228             # tab's sons preferably turn this off
229             togglable   = False,
230             # this is the query at the core of the slice list
231             query       = sq_measurement,
232             checkboxes  = True,
233             datatables_options = { 
234                 'iDisplayLength' : 25,
235                 'bLengthChange'  : True,
236                 'bAutoWidth'     : True,
237             },
238         ))
239     
240         # --------------------------------------------------------------------------
241         # MESSAGES (we use transient=False for now)
242         main_stack.insert(Messages(
243             page   = page,
244             title  = "Runtime messages for slice %s"%slicename,
245             domid  = "msgs-pre",
246             levels = "ALL",
247             # plain messages are probably less nice for production but more reliable for development for now
248             transient = False,
249             # these make sense only in non-transient mode..
250             togglable = True,
251             toggled = 'persistent',
252             outline_complete = True,
253         ))
254     
255     
256         # variables that will get passed to the view-unfold1.html template
257         template_env = {}
258         
259         # define 'unfold1_main' to the template engine - the main contents
260         template_env [ 'unfold1_main' ] = main_stack.render(request)
261     
262         # more general variables expected in the template
263         template_env [ 'title' ] = '%(slicename)s'%locals()
264         # the menu items on the top
265         template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) 
266         # so we can sho who is logged
267         template_env [ 'username' ] = the_user (request) 
268     
269         # don't forget to run the requests
270         page.expose_queries ()
271     
272         # xxx create another plugin with the same query and a different layout (with_datatables)
273         # show that it worls as expected, one single api call to backend and 2 refreshed views
274     
275         # the prelude object in page contains a summary of the requirements() for all plugins
276         # define {js,css}_{files,chunks}
277         prelude_env = page.prelude_env()
278         template_env.update(prelude_env)
279         result=render_to_response ('view-unfold1.html',template_env,
280                                    context_instance=RequestContext(request))
281         return result