From: Yasin Date: Wed, 4 Sep 2013 09:11:28 +0000 (+0200) Subject: Fix merge conflict: MyAccount X-Git-Tag: myslice-0.2-1~24 X-Git-Url: http://git.onelab.eu/?p=myslice.git;a=commitdiff_plain;h=8c8f04ea43ed69b7a81c90f456b1153a4167a72f;hp=c15eb339cc9b7955f77b7cbb6e3466e0ce49b7e4 Fix merge conflict: MyAccount --- diff --git a/auth/backend.py b/auth/backend.py deleted file mode 100644 index 4c93676a..00000000 --- a/auth/backend.py +++ /dev/null @@ -1,40 +0,0 @@ -# import the User object -from django.contrib.auth.models import User - -import time - -# Name my backend 'MyCustomBackend' -class MyCustomBackend: - - hard_wired_users = { 'jean': '1234', - 'root': '2345', - 'jacques': '3456', - } - - - # Create an authentication method - # This is called by the standard Django login procedure - def authenticate(self, token=None): - username=token['username'] - password=token['password'] - users=MyCustomBackend.hard_wired_users - if username not in users: return None - if password != users[username]: return None - try: - # Check if the user exists in Django's local database - user = User.objects.get(email=username) - except User.DoesNotExist: - print 'creating django user',username - # Create a user in Django's local database - # warning: the trick here is pass current time as an id, and name as email - # create_user(username, email=None, password=None) - user = User.objects.create_user(time.time(), username, 'password-doesnt-matter') - - return user - - # Required for your backend to work properly - unchanged in most scenarios - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None diff --git a/auth/manifoldbackend.py b/auth/manifoldbackend.py index f763291a..529ef0fc 100644 --- a/auth/manifoldbackend.py +++ b/auth/manifoldbackend.py @@ -21,18 +21,6 @@ class ManifoldBackend: auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password} api = ManifoldAPI(auth) -#old # Authenticate user and get session key -#old # the new API would expect Get('local:session') instead -#old session_result = api.GetSession() -#old session = session_result.ok_value() -#old if not session: -#old print "GetSession failed",session_result.error() -#old return -#old print 'DEALING with session',session -#old #self.session = session -#old # Change GetSession() at some point to return expires as well -#old expires = time.time() + (24 * 60 * 60) - sessions_result = api.forward(Query.create('local:session').to_dict()) print "result" sessions = sessions_result.ok_value() diff --git a/auth/views.py b/auth/views.py index f650c14e..6380cf2d 100644 --- a/auth/views.py +++ b/auth/views.py @@ -5,17 +5,15 @@ from django.shortcuts import render_to_response from django.contrib.auth import authenticate, login, logout from django.http import HttpResponseRedirect -from auth.backend import MyCustomBackend - from myslice.viewutils import topmenu_items, the_user from myslice.config import Config def login_user(request): state = "Please log in below..." username = password = '' - env={'hard_wired_users':MyCustomBackend.hard_wired_users, - 'manifold_url':Config.manifold_url, - } + env={ + 'manifold_url':Config.manifold_url, + } if request.POST: username = request.POST.get('username') diff --git a/myslice/settings.py b/myslice/settings.py index df4f6d7c..25c2a26e 100644 --- a/myslice/settings.py +++ b/myslice/settings.py @@ -231,7 +231,7 @@ LOGGING = { } } -AUTHENTICATION_BACKENDS = ( 'auth.backend.MyCustomBackend', 'auth.manifoldbackend.ManifoldBackend', ) +AUTHENTICATION_BACKENDS = ( 'auth.manifoldbackend.ManifoldBackend', ) ### the view to redirect malformed (i.e. with a wrong CSRF) incoming requests # without this setting django will return a 403 forbidden error, which is fine diff --git a/myslice/urls.py b/myslice/urls.py index ef1f30ce..891eaafa 100644 --- a/myslice/urls.py +++ b/myslice/urls.py @@ -9,8 +9,11 @@ from django.conf import settings from django.template.loader import add_to_builtins add_to_builtins('insert_above.templatetags.insert_tags') +import portal.sliceview + # main entry point (set to the / URL) default_view='trash.pluginview.test_plugin_view' +#default_view='portal.views.PlatformsView' # where to be redirected after login after_login_view='trash.dashboard.dashboard_view' @@ -39,15 +42,18 @@ urlpatterns = patterns( # the manifold proxy # (r'^manifold/proxy/(?P\w+)/?$', 'manifold.manifoldproxy.proxy'), + # + # the slice view + # + (r'^slice/?$', portal.sliceview.SliceView.as_view()), + (r'^slice/(?P[\w\.]+)/?$', portal.sliceview.SliceView.as_view()), # # various trash views # - (r'^tab/?$', 'trash.sampleviews.tab_view'), - (r'^scroll/?$', 'trash.sampleviews.scroll_view'), - (r'^plugin/?$', 'trash.pluginview.test_plugin_view'), - (r'^dashboard/?$', 'trash.dashboard.dashboard_view'), - (r'^slice/?$', 'trash.sliceview.slice_view'), - (r'^slice/(?P[\w\.]+)/?$', 'trash.sliceview.slice_view'), + (r'^tab/?$', 'trash.sampleviews.tab_view'), + (r'^scroll/?$', 'trash.sampleviews.scroll_view'), + (r'^plugin/?$', 'trash.pluginview.test_plugin_view'), + (r'^dashboard/?$', 'trash.dashboard.dashboard_view'), # Portal url(r'^portal/', include('portal.urls')), # Portal diff --git a/myslice/viewutils.py b/myslice/viewutils.py index b9309e1b..7fbdc77f 100644 --- a/myslice/viewutils.py +++ b/myslice/viewutils.py @@ -1,20 +1,5 @@ # a set of utilities to help make the global layout consistent across views -# this -standard_topmenu_items = [ -# { 'label':'Tab', 'href': '/tab/'}, -# { 'label':'Scroll', 'href': '/scroll/'}, -# { 'label':'One Plugin', 'href': '/plugin/'}, -# Thierry : using this goes to some test slice that not every one is in -# besides, the topmenu needs to be shrunk down horizontally -# otherwise the topmenu takes more vertical space than avail. and the layout is broken -# { 'label':'Slice', 'href': '/slice/'}, - #{'label':'My Account', 'href': '/portal/account/'} - ] - -#login_out_items = { False: { 'label':'Login', 'href':'/login/'}, -# True: { 'label':'Logout', 'href':'/logout/'}} - def topmenu_items (current,request=None): has_user=request.user.is_authenticated() result=[] @@ -45,37 +30,3 @@ def the_user (request): else: return request.user.email -# temporary for sample views -lorem=""" -Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum. -""" - -lorem_p = "

"+lorem+"

" - -hard_wired_slice_names = [] -for site in [ 'inria', 'upmc' , 'ibbt' ]: - for slice in [ 'foo', 'bar', 'tutu', 'test', 'omf', 'heartbeat' ]: - hard_wired_slice_names.append ("ple.%s.%s"%(site,slice)) - -# having html tags right here is not a real use case -hard_wired_list=[] -hard_wired_list.append("this hard-wired list") -hard_wired_list.append("is defined") -hard_wired_list.append("in plugins.simplelist.py") -hard_wired_list.append("which in turn relies on") -hard_wired_list.append("template widget-template.html") -hard_wired_list.append("while it should of course") -hard_wired_list.append("instead issue a query") -hard_wired_list.append("and fill the DOM in js from there") -hard_wired_list.append("it would however maybe make sense") -hard_wired_list.append("to offer the option to 'datatablify'") -hard_wired_list.append("the list from the python code") -hard_wired_list.append("just like a standard plugin can be set as visible or not") -hard_wired_list.append("") -hard_wired_list.append("OTOH and IMHO, there should be two separate and explicit subclasses of SimpleList for slices or testbeds") - -quickfilter_criterias = [ - {'key': 'Slice', 'values': ['slice1','slice2']}, - {'key': 'Type', 'values': ['type1','type2']}, - {'key': 'Network', 'values': ['net1','net2']}, - ] diff --git a/portal/sliceview.py b/portal/sliceview.py new file mode 100644 index 00000000..d233c434 --- /dev/null +++ b/portal/sliceview.py @@ -0,0 +1,288 @@ +# Create your views here. + +from django.template import RequestContext +from django.shortcuts import render_to_response +from django.contrib.auth.decorators import login_required + +from portal.templateviews import LoginRequiredView,LogoutOnManifoldExceptionView + +from unfold.page import Page +from manifold.core.query import Query, AnalyzedQuery +from manifold.manifoldresult import ManifoldException +from manifold.metadata import MetaData as Metadata + +from myslice.viewutils import topmenu_items, the_user + +from plugins.raw.raw import Raw +from plugins.stack.stack import Stack +from plugins.tabs.tabs import Tabs +from plugins.lists.slicelist import SliceList +from plugins.hazelnut import Hazelnut +from plugins.resources_selected import ResourcesSelected +from plugins.googlemaps import GoogleMaps +from plugins.senslabmap.senslabmap import SensLabMap +from plugins.querycode.querycode import QueryCode +from plugins.query_editor import QueryEditor +from plugins.active_filters import ActiveFilters +from plugins.quickfilter.quickfilter import QuickFilter +from plugins.messages.messages import Messages +#from plugins.updater import Updater + +tmp_default_slice='ple.upmc.myslicedemo' +debug = True + +class SliceView (LoginRequiredView, LogoutOnManifoldExceptionView): + +# def __init__ (self, slicename=None): +# self.slicename = slicename or tmp_default_slice + + def get_or_logout (self,request, slicename=tmp_default_slice): + + page = Page(request) + page.expose_js_metadata() + + metadata = page.get_metadata() + resource_md = metadata.details_by_object('resource') + resource_fields = [column['name'] for column in resource_md['column']] + + user_md = metadata.details_by_object('user') + user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']] + + # TODO The query to run is embedded in the URL + main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename) + main_query.select( + 'slice_hrn', + 'resource.resource_hrn', 'resource.hostname', 'resource.type', 'resource.network_hrn', + #'lease.urn', + 'user.user_hrn', + #'application.measurement_point.counter' + ) + + query_resource_all = Query.get('resource').select(resource_fields) + query_user_all = Query.get('user').select(user_fields) + + aq = AnalyzedQuery(main_query, metadata=metadata) + page.enqueue_query(main_query, analyzed_query=aq) + page.enqueue_query(query_resource_all) + page.enqueue_query(query_user_all) + + # Prepare the display according to all metadata + # (some parts will be pending, others can be triggered by users). + # + # For example slice measurements will not be requested by default... + + # Create the base layout (Stack)... + main_plugin = Stack ( + page=page, + title="Slice !!view for %s"%slicename, + sons=[], + ) + + # ... responsible for the slice properties... + + + main_plugin.insert ( + Raw (page=page,togglable=False, toggled=True,html="

Slice page for %s

"%slicename) + ) + + main_plugin.insert( + Raw (page=page,togglable=False, toggled=True,html='Description: TODO') + ) + + sq_plugin = Tabs ( + page=page, + title="Slice view for %s"%slicename, + togglable=False, + sons=[], + ) + + + # ... and for the relations + # XXX Let's hardcode resources for now + sq_resource = aq.subquery('resource') + sq_user = aq.subquery('user') + sq_lease = aq.subquery('lease') + sq_measurement = aq.subquery('measurement') + + + ############################################################################ + # RESOURCES + # + # A stack inserted in the subquery tab that will hold all operations + # related to resources + # + + stack_resources = Stack( + page = page, + title = 'Resources', + sons=[], + ) + + resource_query_editor = QueryEditor( + page = page, + query = sq_resource, + ) + stack_resources.insert(resource_query_editor) + + resource_active_filters = ActiveFilters( + page = page, + query = sq_resource, + ) + stack_resources.insert(resource_active_filters) + + # -------------------------------------------------------------------------- + # Different displays = DataTables + GoogleMaps + # + tab_resource_plugins = Tabs( + page = page, + sons = [] + ) + + tab_resource_plugins.insert(Hazelnut( + page = page, + title = 'List', + domid = 'checkboxes', + # this is the query at the core of the slice list + query = sq_resource, + query_all = query_resource_all, + checkboxes = True, + datatables_options = { + # for now we turn off sorting on the checkboxes columns this way + # this of course should be automatic in hazelnut + 'aoColumns' : [None, None, None, None, {'bSortable': False}], + 'iDisplayLength' : 25, + 'bLengthChange' : True, + }, + )) + + tab_resource_plugins.insert(GoogleMaps( + page = page, + title = 'Geographic view', + domid = 'gmap', + # tab's sons preferably turn this off + togglable = False, + query = sq_resource, + query_all = query_resource_all, + checkboxes = True, + # center on Paris + latitude = 49., + longitude = 2.2, + zoom = 3, + )) + + stack_resources.insert(tab_resource_plugins) + + sq_plugin.insert(stack_resources) + + ############################################################################ + # USERS + # + + tab_users = Tabs( + page = page, + title = 'Users', + domid = 'thetabs2', + # activeid = 'checkboxes', + active_domid = 'checkboxes2', + ) + sq_plugin.insert(tab_users) + + tab_users.insert(Hazelnut( + page = page, + title = 'List', + domid = 'checkboxes2', + # tab's sons preferably turn this off + togglable = False, + # this is the query at the core of the slice list + query = sq_user, + query_all = query_user_all, + checkboxes = True, + datatables_options = { + # for now we turn off sorting on the checkboxes columns this way + # this of course should be automatic in hazelnut + 'aoColumns' : [None, None, None, None, {'bSortable': False}], + 'iDisplayLength' : 25, + 'bLengthChange' : True, + }, + )) + + tab_measurements = Tabs ( + page = page, + title = 'Measurements', + domid = 'thetabs3', + # activeid = 'checkboxes', + active_domid = 'checkboxes3', + ) + sq_plugin.insert(tab_measurements) + + tab_measurements.insert(Hazelnut( + page = page, + title = 'List', + domid = 'checkboxes3', + # tab's sons preferably turn this off + togglable = False, + # this is the query at the core of the slice list + query = sq_measurement, + checkboxes = True, + datatables_options = { + # for now we turn off sorting on the checkboxes columns this way + # this of course should be automatic in hazelnut + 'aoColumns' : [None, None, None, None, {'bSortable': False}], + 'iDisplayLength' : 25, + 'bLengthChange' : True, + }, + )) + + main_plugin.insert(sq_plugin) + + # -------------------------------------------------------------------------- + # ResourcesSelected + # + main_plugin.insert(ResourcesSelected( + page = page, + title = 'Pending operations', + query = main_query, + togglable = True, + )) + + main_plugin.insert(Messages( + page = page, + title = "Runtime messages for slice %s"%slicename, + domid = "msgs-pre", + levels = "ALL", + )) + # main_plugin.insert(Updater( + # page = page, + # title = "wont show up as non togglable by default", + # query = main_query, + # label = "Update slice", + # )) + + + + # variables that will get passed to the view-unfold1.html template + template_env = {} + + # define 'unfold1_main' to the template engine - the main contents + template_env [ 'unfold1_main' ] = main_plugin.render(request) + + # more general variables expected in the template + template_env [ 'title' ] = '%(slicename)s'%locals() + # the menu items on the top + template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) + # so we can sho who is logged + template_env [ 'username' ] = the_user (request) + + # don't forget to run the requests + page.expose_queries () + + # xxx create another plugin with the same query and a different layout (with_datatables) + # show that it worls as expected, one single api call to backend and 2 refreshed views + + # the prelude object in page contains a summary of the requirements() for all plugins + # define {js,css}_{files,chunks} + prelude_env = page.prelude_env() + template_env.update(prelude_env) + result=render_to_response ('view-unfold1.html',template_env, + context_instance=RequestContext(request)) + return result diff --git a/portal/templates/my_account.html b/portal/templates/my_account.html index f7439f11..68ac2453 100644 --- a/portal/templates/my_account.html +++ b/portal/templates/my_account.html @@ -34,134 +34,134 @@
-
-

MySlice Account

-
-
-
-
-
- {% csrf_token %} - - - - - - - - - - - - - - - +
+

MySlice Account

+
+
+
+
+ + {% csrf_token %} +
-
Personal Details
-
Email - {{ person.email }} - -
Password - - ******** - - - - - - - - - - - - -
Enter password: - -
Confirm password: - - -
-
-
Full Name - {{ fullname }} - - - -
- - - -
- -
+ + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - +

For better + security we recommend that you + download and delete your + private key from the + server. Always store your + private key in a secure + location.

+ + -
+
Personal Details
+
Email + {{ person.email }} + +
Password + + ******** + + + + + + + + + + + + +
Enter password: + +
Confirm password: + + +
+
+
Full Name + {{ fullname }} + + + +
+ + + +
+ +
Affiliation - {{ affiliation }} - -
Generate Keys - - - -
Public Key - - - ******** - - -
-
- - - - -
-
- -
- - -
Private Key ******** - - -
+
Affiliation + {{ affiliation }} + +
Generate Keys + + + +
Public Key + + + ******** + + +
+
+ + + + +
+
+ +
+ + +
Private Key ******** + + +
-

For better - security we recommend that you - download and delete your - private key from the - server. Always store your - private key in a secure - location.

-
-
-
-
- + +
-
+ + + + {% endblock %} diff --git a/portal/templateviews.py b/portal/templateviews.py new file mode 100644 index 00000000..0d76fcd5 --- /dev/null +++ b/portal/templateviews.py @@ -0,0 +1,52 @@ +from django.contrib.auth.decorators import login_required +from django.utils.decorators import method_decorator +from django.http import HttpResponseRedirect +# for 'as_view' that we need to call in urls.py and the like +from django.views.generic.base import TemplateView + +from manifold.manifoldresult import ManifoldException + +########## the base class for views that require a login +class LoginRequiredView (TemplateView): + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(LoginRequiredView, self).dispatch(*args, **kwargs) + + +########## the base class for views that need to protect against ManifoldException +# a decorator for view classes to catch manifold exceptions +# by design views should not directly exercise a manifold query +# given that these are asynchroneous, you would expect a view to just +# return a mundane skeleton +# however of course this is not always true, +# e.g. we deal with metadata some other way, and so +# it is often a good idea for a view to monitor these exceptions +# and to take this opportunity to logout people + +def logout_on_manifold_exception (view_as_a_function): + def wrapped (request, *args, **kwds): + try: + return view_as_a_function(request,*args, **kwds) + except ManifoldException, manifold_result: + # xxx we need a means to display this message to user... + from django.contrib.auth import logout + logout(request) + return HttpResponseRedirect ('/') + except Exception, e: + # xxx we need to sugarcoat this error message in some error template... + print "Unexpected exception",e + import traceback + traceback.print_exc() + return HttpResponseRedirect ('/') + return wrapped + +# at first sight this matters only for views that require login +# however we prefer this to be explicit +# i.e. a user class has to inherit both LoginRequiredView and LogoutOnManifoldExceptionView + +class LogoutOnManifoldExceptionView (TemplateView): + + @logout_on_manifold_exception + def get (self, request, *args, **kwds): + return self.get_or_logout (request, *args, **kwds) diff --git a/trash/dashboard.py b/trash/dashboard.py index 07e60238..e996477f 100644 --- a/trash/dashboard.py +++ b/trash/dashboard.py @@ -16,7 +16,7 @@ from plugins.lists.slicelist import SliceList from plugins.querycode.querycode import QueryCode from plugins.quickfilter.quickfilter import QuickFilter -from myslice.viewutils import quickfilter_criterias +from trash.trashutils import quickfilter_criterias # from myslice.viewutils import topmenu_items, the_user diff --git a/trash/pluginview.py b/trash/pluginview.py index be17ee22..236744f0 100644 --- a/trash/pluginview.py +++ b/trash/pluginview.py @@ -21,7 +21,7 @@ from plugins.hazelnut import Hazelnut from plugins.updater import Updater from myslice.viewutils import topmenu_items, the_user -from myslice.viewutils import hard_wired_slice_names, hard_wired_list, lorem_p, lorem, quickfilter_criterias +from trash.trashutils import hard_wired_slice_names, hard_wired_list, lorem_p, lorem, quickfilter_criterias @login_required def test_plugin_view (request): diff --git a/trash/sampleviews.py b/trash/sampleviews.py index 81ad313c..0207d4da 100644 --- a/trash/sampleviews.py +++ b/trash/sampleviews.py @@ -8,7 +8,7 @@ from unfold.prelude import Prelude from myslice.viewutils import topmenu_items, the_user # tmp -from myslice.viewutils import lorem, hard_wired_slice_names +from trash.trashutils import lorem, hard_wired_slice_names @login_required def tab_view (request): diff --git a/trash/sliceview.py b/trash/sliceview.py deleted file mode 100644 index 55578e35..00000000 --- a/trash/sliceview.py +++ /dev/null @@ -1,301 +0,0 @@ -# Create your views here. - -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.contrib.auth.decorators import login_required -from django.http import HttpResponseRedirect - -from unfold.page import Page -from manifold.core.query import Query, AnalyzedQuery -from manifold.manifoldresult import ManifoldException -from manifold.metadata import MetaData as Metadata -from myslice.viewutils import quickfilter_criterias, topmenu_items, the_user - -from plugins.raw.raw import Raw -from plugins.stack.stack import Stack -from plugins.tabs.tabs import Tabs -from plugins.lists.slicelist import SliceList -from plugins.hazelnut import Hazelnut -from plugins.resources_selected import ResourcesSelected -from plugins.googlemaps import GoogleMaps -from plugins.senslabmap.senslabmap import SensLabMap -from plugins.querycode.querycode import QueryCode -from plugins.query_editor import QueryEditor -from plugins.active_filters import ActiveFilters -from plugins.quickfilter.quickfilter import QuickFilter -from plugins.messages.messages import Messages -#from plugins.updater import Updater - -tmp_default_slice='ple.upmc.myslicedemo' -debug = True - -@login_required -def slice_view (request, slicename=tmp_default_slice): - # xxx Thierry - ugly hack - # fetching metadata here might fail - e.g. with an expired session.. - # let's catch this early on and log out our user if needed - # it should of course be handled in a more generic way - try: - return _slice_view(request,slicename) - except ManifoldException, manifold_result: - # xxx needs a means to display this message to user... - from django.contrib.auth import logout - logout(request) - return HttpResponseRedirect ('/') - except Exception, e: - # xxx we need to sugarcoat this error message in some error template... - print "Unexpected exception",e - import traceback - traceback.print_exc() - # return ... - -def _slice_view (request, slicename): - - page = Page(request) - page.expose_js_metadata() - - metadata = page.get_metadata() - resource_md = metadata.details_by_object('resource') - resource_fields = [column['name'] for column in resource_md['column']] - - user_md = metadata.details_by_object('user') - user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']] - - # TODO The query to run is embedded in the URL - main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename) - main_query.select( - 'slice_hrn', - 'resource.resource_hrn', 'resource.hostname', 'resource.type', 'resource.network_hrn', - #'lease.urn', - 'user.user_hrn', - #'application.measurement_point.counter' - ) - - query_resource_all = Query.get('resource').select(resource_fields) - query_user_all = Query.get('user').select(user_fields) - - aq = AnalyzedQuery(main_query, metadata=metadata) - page.enqueue_query(main_query, analyzed_query=aq) - page.enqueue_query(query_resource_all) - page.enqueue_query(query_user_all) - - # Prepare the display according to all metadata - # (some parts will be pending, others can be triggered by users). - # - # For example slice measurements will not be requested by default... - - # Create the base layout (Stack)... - main_plugin = Stack ( - page=page, - title="Slice !!view for %s"%slicename, - sons=[], - ) - - # ... responsible for the slice properties... - - - main_plugin.insert ( - Raw (page=page,togglable=False, toggled=True,html="

Slice page for %s

"%slicename) - ) - - main_plugin.insert( - Raw (page=page,togglable=False, toggled=True,html='Description: TODO') - ) - - sq_plugin = Tabs ( - page=page, - title="Slice view for %s"%slicename, - togglable=False, - sons=[], - ) - - - # ... and for the relations - # XXX Let's hardcode resources for now - sq_resource = aq.subquery('resource') - sq_user = aq.subquery('user') - sq_lease = aq.subquery('lease') - sq_measurement = aq.subquery('measurement') - - - ############################################################################ - # RESOURCES - # - # A stack inserted in the subquery tab that will hold all operations - # related to resources - # - - stack_resources = Stack( - page = page, - title = 'Resources', - sons=[], - ) - - resource_query_editor = QueryEditor( - page = page, - query = sq_resource, - ) - stack_resources.insert(resource_query_editor) - - resource_active_filters = ActiveFilters( - page = page, - query = sq_resource, - ) - stack_resources.insert(resource_active_filters) - - # -------------------------------------------------------------------------- - # Different displays = DataTables + GoogleMaps - # - tab_resource_plugins = Tabs( - page = page, - sons = [] - ) - - tab_resource_plugins.insert(Hazelnut( - page = page, - title = 'List', - domid = 'checkboxes', - # this is the query at the core of the slice list - query = sq_resource, - query_all = query_resource_all, - checkboxes = True, - datatables_options = { - # for now we turn off sorting on the checkboxes columns this way - # this of course should be automatic in hazelnut - 'aoColumns' : [None, None, None, None, {'bSortable': False}], - 'iDisplayLength' : 25, - 'bLengthChange' : True, - }, - )) - - tab_resource_plugins.insert(GoogleMaps( - page = page, - title = 'Geographic view', - domid = 'gmap', - # tab's sons preferably turn this off - togglable = False, - query = sq_resource, - query_all = query_resource_all, - checkboxes = True, - # center on Paris - latitude = 49., - longitude = 2.2, - zoom = 3, - )) - - stack_resources.insert(tab_resource_plugins) - - sq_plugin.insert(stack_resources) - - ############################################################################ - # USERS - # - - tab_users = Tabs( - page = page, - title = 'Users', - domid = 'thetabs2', - # activeid = 'checkboxes', - active_domid = 'checkboxes2', - ) - sq_plugin.insert(tab_users) - - tab_users.insert(Hazelnut( - page = page, - title = 'List', - domid = 'checkboxes2', - # tab's sons preferably turn this off - togglable = False, - # this is the query at the core of the slice list - query = sq_user, - query_all = query_user_all, - checkboxes = True, - datatables_options = { - # for now we turn off sorting on the checkboxes columns this way - # this of course should be automatic in hazelnut - 'aoColumns' : [None, None, None, None, {'bSortable': False}], - 'iDisplayLength' : 25, - 'bLengthChange' : True, - }, - )) - - tab_measurements = Tabs ( - page = page, - title = 'Measurements', - domid = 'thetabs3', - # activeid = 'checkboxes', - active_domid = 'checkboxes3', - ) - sq_plugin.insert(tab_measurements) - - tab_measurements.insert(Hazelnut( - page = page, - title = 'List', - domid = 'checkboxes3', - # tab's sons preferably turn this off - togglable = False, - # this is the query at the core of the slice list - query = sq_measurement, - checkboxes = True, - datatables_options = { - # for now we turn off sorting on the checkboxes columns this way - # this of course should be automatic in hazelnut - 'aoColumns' : [None, None, None, None, {'bSortable': False}], - 'iDisplayLength' : 25, - 'bLengthChange' : True, - }, - )) - - main_plugin.insert(sq_plugin) - - # -------------------------------------------------------------------------- - # ResourcesSelected - # - main_plugin.insert(ResourcesSelected( - page = page, - title = 'Pending operations', - query = main_query, - togglable = True, - )) - - main_plugin.insert(Messages( - page = page, - title = "Runtime messages for slice %s"%slicename, - domid = "msgs-pre", - levels = "ALL", - )) -# main_plugin.insert(Updater( -# page = page, -# title = "wont show up as non togglable by default", -# query = main_query, -# label = "Update slice", -# )) - - - - # variables that will get passed to the view-unfold1.html template - template_env = {} - - # define 'unfold1_main' to the template engine - the main contents - template_env [ 'unfold1_main' ] = main_plugin.render(request) - - # more general variables expected in the template - template_env [ 'title' ] = '%(slicename)s (test view that combines various plugins)'%locals() - # the menu items on the top - template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) - # so we can sho who is logged - template_env [ 'username' ] = the_user (request) - - # don't forget to run the requests - page.expose_queries () - - # xxx create another plugin with the same query and a different layout (with_datatables) - # show that it worls as expected, one single api call to backend and 2 refreshed views - - # the prelude object in page contains a summary of the requirements() for all plugins - # define {js,css}_{files,chunks} - prelude_env = page.prelude_env() - template_env.update(prelude_env) - result=render_to_response ('view-unfold1.html',template_env, - context_instance=RequestContext(request)) - return result diff --git a/trash/trashutils.py b/trash/trashutils.py new file mode 100644 index 00000000..dd470133 --- /dev/null +++ b/trash/trashutils.py @@ -0,0 +1,52 @@ +# a set of utilities to help make the global layout consistent across views + +# this +standard_topmenu_items = [ +# { 'label':'Tab', 'href': '/tab/'}, +# { 'label':'Scroll', 'href': '/scroll/'}, +# { 'label':'One Plugin', 'href': '/plugin/'}, +# Thierry : using this goes to some test slice that not every one is in +# besides, the topmenu needs to be shrunk down horizontally +# otherwise the topmenu takes more vertical space than avail. and the layout is broken +# { 'label':'Slice', 'href': '/slice/'}, + #{'label':'My Account', 'href': '/portal/account/'} + ] + +#login_out_items = { False: { 'label':'Login', 'href':'/login/'}, +# True: { 'label':'Logout', 'href':'/logout/'}} + +# temporary for sample views +lorem=""" +Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum. +""" + +lorem_p = "

"+lorem+"

" + +hard_wired_slice_names = [] +for site in [ 'inria', 'upmc' , 'ibbt' ]: + for slice in [ 'foo', 'bar', 'tutu', 'test', 'omf', 'heartbeat' ]: + hard_wired_slice_names.append ("ple.%s.%s"%(site,slice)) + +# having html tags right here is not a real use case +hard_wired_list=[] +hard_wired_list.append("this hard-wired list") +hard_wired_list.append("is defined") +hard_wired_list.append("in plugins.simplelist.py") +hard_wired_list.append("which in turn relies on") +hard_wired_list.append("template widget-template.html") +hard_wired_list.append("while it should of course") +hard_wired_list.append("instead issue a query") +hard_wired_list.append("and fill the DOM in js from there") +hard_wired_list.append("it would however maybe make sense") +hard_wired_list.append("to offer the option to 'datatablify'") +hard_wired_list.append("the list from the python code") +hard_wired_list.append("just like a standard plugin can be set as visible or not") +hard_wired_list.append("") +hard_wired_list.append("OTOH and IMHO, there should be two separate and explicit subclasses of SimpleList for slices or testbeds") + +quickfilter_criterias = [ + {'key': 'Slice', 'values': ['slice1','slice2']}, + {'key': 'Type', 'values': ['type1','type2']}, + {'key': 'Network', 'values': ['net1','net2']}, + ] + diff --git a/views/templates/view-login.html b/views/templates/view-login.html index 8d15f968..305b5c6d 100644 --- a/views/templates/view-login.html +++ b/views/templates/view-login.html @@ -6,18 +6,13 @@ {% block unfold2_main %}
@@ -37,6 +32,7 @@ testbeds including PlanetLab Europe, the NITOS wireless testbed, and other federated testbeds.

+

This UI server is connected to the manifold backend running at {{ manifold_url }}.

{% endblock unfold2_main %}