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