Fix merge conflict: MyAccount
authorYasin <mohammed-yasin.rahman@lip6.fr>
Wed, 4 Sep 2013 09:11:28 +0000 (11:11 +0200)
committerYasin <mohammed-yasin.rahman@lip6.fr>
Wed, 4 Sep 2013 09:11:28 +0000 (11:11 +0200)
15 files changed:
auth/backend.py [deleted file]
auth/manifoldbackend.py
auth/views.py
myslice/settings.py
myslice/urls.py
myslice/viewutils.py
portal/sliceview.py [new file with mode: 0644]
portal/templates/my_account.html
portal/templateviews.py [new file with mode: 0644]
trash/dashboard.py
trash/pluginview.py
trash/sampleviews.py
trash/sliceview.py [deleted file]
trash/trashutils.py [new file with mode: 0644]
views/templates/view-login.html

diff --git a/auth/backend.py b/auth/backend.py
deleted file mode 100644 (file)
index 4c93676..0000000
+++ /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
index f763291..529ef0f 100644 (file)
@@ -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()
index f650c14..6380cf2 100644 (file)
@@ -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')
index df4f6d7..25c2a26 100644 (file)
@@ -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
index ef1f30c..891eaaf 100644 (file)
@@ -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<format>\w+)/?$', 'manifold.manifoldproxy.proxy'),
+    # 
+    # the slice view
+    #
+    (r'^slice/?$',                        portal.sliceview.SliceView.as_view()),
+    (r'^slice/(?P<slicename>[\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<slicename>[\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
index b9309e1..7fbdc77 100644 (file)
@@ -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 <code>mazim placerat</code> 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 = "<p>"+lorem+"</p>"
-
-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 (file)
index 0000000..d233c43
--- /dev/null
@@ -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="<h2> Slice page for %s</h2>"%slicename)
+        )
+    
+        main_plugin.insert(
+            Raw (page=page,togglable=False, toggled=True,html='<b>Description:</b> 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
index f7439f1..68ac245 100644 (file)
 
 
 <div class='ms-dashboard-panel' id='ms-dashboard-slices' style=" display:block; float:none"  >
-    <div class='ms-dashboard-caption'>
-      <h2>MySlice  Account</h2>
-    </div>
-    <div class='ms-dashboard-content' id='tophat__list__user_hrn'>
-            <div id="main">
-                    <div id="middle" align="center">
-                       <form id="editForm"  method="POST" action="acc_process" enctype="multipart/form-data">
-                                               {% csrf_token %}
-                       <table class="profile">          
-                                    <tr class="odd">
-                                            <td colspan="2">
-                                                <div id="info">Personal Details</div>
-                                            </td>
-                                    </tr>
-                                <tr class="even">
-                                            <td class="key">Email</td>
-                                            <td class="value">
-                                                   <span id="emailval" class="value" >{{ person.email }}</span>
-                                                   <img class="logo" src="{{STATIC_URL}}/img/ques_icon.png" onclick="emailAlert()"  title="To change your email please contact the administrator" style="height: 20px; width: 20px; position: absolute; left: 625px; left: 900px; margin-top: -9px;">
-                                            </td>
-                                    </tr>
-                                <tr class="odd">
-                                            <td class="key">Password</td>
-                                            <td class="value"> 
-                                                <button class="edit" type="button" title="Password" name="edit_pass" id="edit_pass">Edit</button>
-                                                    <span id="passval"class="value">******** </span>
-                                                    <span class="hide_this" id="span_pass">
-                                                            <button type="button" class="cancel" title="Cancel" id="cancel_pass_change"> Cancel </button>
-                                                                <div style='display:none;' id="pass_form">
-                                                                    <input type='hidden'  value='' /></div>
-                                                                    <table id="edit_password">
-                                                                            <tr>
-                                                                                    <td>Enter password: </td>
-                                                                                    <td class="field"> 
-                                                                                        <input type="password" name="password" id="password" />
-                                                                                    </td>
-                                                                            </tr>
-                                                                            <tr>
-                                                                                    <td>Confirm password: </td>
-                                                                                    <td class="field"> 
-                                                                                        <input type="password" name="confirmpassword" id="confirmpassword" /> 
-                                                                                        <input type="submit" name="submit_pass" value="Save"/> 
-                                                                                    </td>
-                                                                            </tr>
-                                                                    </table>
-                                                    </span>    
-                                            </td>
-                                </tr>
-                                <tr class="even">
-                                            <td class="key">Full Name</td>
-                                            <td class="value">
-                                                    <span id="nameval" class="value" >{{ fullname }} </span>
-                                                    <span class="hide_this" id="span_name">
-                                                            <button type="button" class="cancel" title="Cancel" id="cancel_name_change"> Cancel </button>
-                                                            
-                                                                <div style='display:none;'><input type='hidden'  name='nameform'  /></div>
-                                                                    <input id="fname" type="text" name="fname" class="required"  maxlength="200" value="{{firstname}}" />
-                                                                    <input id="lname" type="text" name="lname" class="required"  maxlength="200" value="{{lastname}}" />
-                                                                    <input type="submit" name="submit_name" value="Save"/>
-                                                    </span>
-                                                    <button class="edit" type="button"title="Full Name" id="edit_name">Edit</button>
-                                            </td>
+  <div class='ms-dashboard-caption'>
+    <h2>MySlice  Account</h2>
+  </div>
+  <div class='ms-dashboard-content' id='tophat__list__user_hrn'>
+    <div id="main">
+      <div id="middle" align="center">
+       <form id="editForm"  method="POST" action="acc_process" enctype="multipart/form-data">
+         {% csrf_token %}
+         <table class="profile">          
+           <tr class="odd">
+             <td colspan="2">
+               <div id="info">Personal Details</div>
+             </td>
+           </tr>
+           <tr class="even">
+             <td class="key">Email</td>
+             <td class="value">
+               <span id="emailval" class="value" >{{ person.email }}</span>
+               <img class="logo" src="{{STATIC_URL}}/img/ques_icon.png" onclick="emailAlert()"  title="To change your email please contact the administrator" style="height: 20px; width: 20px; position: absolute; left: 625px; left: 900px; margin-top: -9px;">
+               </td>
+             </tr>
+             <tr class="odd">
+               <td class="key">Password</td>
+               <td class="value"> 
+                 <button class="edit" type="button" title="Password" name="edit_pass" id="edit_pass">Edit</button>
+                 <span id="passval"class="value">******** </span>
+                 <span class="hide_this" id="span_pass">
+                   <button type="button" class="cancel" title="Cancel" id="cancel_pass_change"> Cancel </button>
+                   <div style='display:none;' id="pass_form">
+                   <input type='hidden'  value='' /></div>
+                   <table id="edit_password">
+                     <tr>
+                       <td>Enter password: </td>
+                       <td class="field"> 
+                         <input type="password" name="password" id="password" />
+                       </td>
+                     </tr>
+                     <tr>
+                       <td>Confirm password: </td>
+                       <td class="field"> 
+                         <input type="password" name="confirmpassword" id="confirmpassword" /> 
+                         <input type="submit" name="submit_pass" value="Save"/> 
+                       </td>
+                     </tr>
+                   </table>
+                 </span>       
+               </td>
+             </tr>
+             <tr class="even">
+               <td class="key">Full Name</td>
+               <td class="value">
+                 <span id="nameval" class="value" >{{ fullname }} </span>
+                 <span class="hide_this" id="span_name">
+                   <button type="button" class="cancel" title="Cancel" id="cancel_name_change"> Cancel </button>
+                   
+                   <div style='display:none;'><input type='hidden'  name='nameform'  /></div>
+                   <input id="fname" type="text" name="fname" class="required"  maxlength="200" value="{{firstname}}" />
+                   <input id="lname" type="text" name="lname" class="required"  maxlength="200" value="{{lastname}}" />
+                   <input type="submit" name="submit_name" value="Save"/>
+                 </span>
+                 <button class="edit" type="button"title="Full Name" id="edit_name">Edit</button>
+               </td>
 
-                                </tr>
-                                <tr class="odd">
-                                            <td class="key">Affiliation</td>
-                                            <td class="value">
-                                                    <span id="affval" class="value">{{ affiliation }}</span>
-                                                    <img class="logo" src="{{STATIC_URL}}/img/ques_icon.png" onclick="affAlert()"  title="To change your affiliation please contact the administrator" style="height: 20px; width: 20px; position: absolute; left: 625px; left: 900px; ">
-                                            </td>
-                                    </tr>
-                            
-                        <tr class="even">
-                                    <td class="key">Generate Keys</td>
-                                    <td> 
-                                        </div>
-                                            <button id="generate_keypair" name="generate" type="submit" onclick="myFunction()" title="Generate a new key pair. After it is generated, you will need to download your public and private keys again.">Generate a new Key Pair </button>
-                                         </div>
-                                    </td> 
-                            </tr>
-                            <tr class="odd">
-                                    <td class="key">Public Key
-                                    </td>
-                                    <td class="value">
-                                            
-                                            <span id="keyval" class="value">******** </span>
-                                            <span class="hide_this" id="span_upload">
-                                                    <button type="button" class="cancel" title="Cancel" id="cancel_upload"> Cancel </button>
-                                                        <div style='display:none;'>
-                                                            <input type='hidden'  name='upload'  /></div>
-                                                            <input type="file" name="pubkey" class="required" id="pubkey"/> 
-                                                            
-                                                            <button name="upload_key" id="upload_key"  type="submit" title="Delete your private key">Upload </button>
-                                                            
-                                            </span>
-                                                <div style='display:none;'>
-                                                    <input type='hidden'  name='dload'  />
-                                                </div> 
-                                                    <button type="submit" name="dl_pubkey" class="download" title="Download your public key" id="dl_file"> Download </button>
-                                             <button id="upload_file" type="button" title="Upload a public key"> Upload </button>       
-                                    </td>
-                            </tr>
-                                    <tr class="even" id="pkey_row" display="none">
-                                            <td class="key">Private Key </td>
-                                            <td class="value">********<a href="#">
-                                                 <button type="submit" name="dl_pkey" class="download" title="Download your privaye key" id="dl_pkey"> Download </button>
-                                                 <button id="delete" name="delete" type="submit" title="Delete your private key">Delete </button>
-                                            </td>
-                                    </tr>
-                                    <tr class="odd">
-                                            <td colspan="2">
+             </tr>
+             <tr class="odd">
+               <td class="key">Affiliation</td>
+               <td class="value">
+                 <span id="affval" class="value">{{ affiliation }}</span>
+                 <img class="logo" src="{{STATIC_URL}}/img/ques_icon.png" onclick="affAlert()"  title="To change your affiliation please contact the administrator" style="height: 20px; width: 20px; position: absolute; left: 625px; left: 900px; ">
+                 </td>
+               </tr>
+               
+               <tr class="even">
+                 <td class="key">Generate Keys</td>
+                 <td> 
+                 </div>
+                 <button id="generate_keypair" name="generate" type="submit" onclick="myFunction()" title="Generate a new key pair. After it is generated, you will need to download your public and private keys again.">Generate a new Key Pair </button>
+               </div>
+             </td> 
+           </tr>
+           <tr class="odd">
+             <td class="key">Public Key
+             </td>
+             <td class="value">
+               
+               <span id="keyval" class="value">******** </span>
+               <span class="hide_this" id="span_upload">
+                 <button type="button" class="cancel" title="Cancel" id="cancel_upload"> Cancel </button>
+                 <div style='display:none;'>
+                 <input type='hidden'  name='upload'  /></div>
+                 <input type="file" name="pubkey" class="required" id="pubkey"/> 
+                 
+                 <button name="upload_key" id="upload_key"  type="submit" title="Delete your private key">Upload </button>
+                 
+               </span>
+               <div style='display:none;'>
+                 <input type='hidden'  name='dload'  />
+               </div> 
+               <button type="submit" name="dl_pubkey" class="download" title="Download your public key" id="dl_file"> Download </button>
+               <button id="upload_file" type="button" title="Upload a public key"> Upload </button>       
+             </td>
+           </tr>
+           <tr class="even" id="pkey_row" display="none">
+             <td class="key">Private Key </td>
+             <td class="value">********<a href="#">
+             <button type="submit" name="dl_pkey" class="download" title="Download your privaye key" id="dl_pkey"> Download </button>
+             <button id="delete" name="delete" type="submit" title="Delete your private key">Delete </button>
+           </td>
+         </tr>
+         <tr class="odd">
+           <td colspan="2">
 
-                                                    <p class="warning" id="pkey_del_msg"> 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. </p>
-                                            </td>
-                                    </tr>
+             <p class="warning" id="pkey_del_msg"> 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. </p>
+           </td>
+         </tr>
 
-                            </table>
-                          </form>
-                    </div>
-            </div>
-       
+       </table>
+      </form>
     </div>
- </div>
+  </div>
+  
+</div>
+</div>
 
 {% endblock %}
diff --git a/portal/templateviews.py b/portal/templateviews.py
new file mode 100644 (file)
index 0000000..0d76fcd
--- /dev/null
@@ -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)
index 07e6023..e996477 100644 (file)
@@ -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
index be17ee2..236744f 100644 (file)
@@ -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):
index 81ad313..0207d4d 100644 (file)
@@ -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 (file)
index 55578e3..0000000
+++ /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="<h2> Slice page for %s</h2>"%slicename)
-    )
-
-    main_plugin.insert(
-        Raw (page=page,togglable=False, toggled=True,html='<b>Description:</b> 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 (file)
index 0000000..dd47013
--- /dev/null
@@ -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 <code>mazim placerat</code> 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 = "<p>"+lorem+"</p>"
+
+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']},
+    ]
+
index 8d15f96..305b5c6 100644 (file)
@@ -6,18 +6,13 @@
 
 {% block unfold2_main %}
 <!--
-<code> This page is currently connected to two authentication systems:</code>
+<code> This page is currently connected to one authentication system:</code>
 <ul>
 <li> A manifold server, located at <code>{{ manifold_url }}</code>, (configured in <code>myslice/config.py</code>), and</li>
-<li>
-as a proof of concept, a set of hardwired user accounts, see <code>auth/backend.py</code> for more details. However these won't of course have the ability to run real queries at the backend so it's more for testing login and all this.
-Currently hard wired users are:
-<ul>
-  {% for k,v in hard_wired_users.iteritems %}
-  <li class='well'> Name= <code>{{ k }}</code>, Password= <code>{{ v }}</code> </li>
-  {% endfor %}
 </ul>
-</li></ul>
+<p>
+as a proof of concept, a set of hardwired user accounts used to be available but as these would not let you do anything valuable with the backend it is now turned off.
+</p>
 -->
 <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/register.css" />
 <div style='padding: 20px;'>
@@ -37,6 +32,7 @@ testbeds including PlanetLab Europe, the NITOS wireless testbed, and other
 federated testbeds.
   </p>
   <div class="item-separator"></div>
+<p>This UI server is connected to the manifold backend running at <code>{{ manifold_url }}</code>.</p>
 </div>
 
 {% endblock unfold2_main %}