Merge branch 'master' of ssh://git.onelab.eu/git/myslice
authorYasin <mohammed-yasin.rahman@lip6.fr>
Mon, 16 Dec 2013 13:15:11 +0000 (14:15 +0100)
committerYasin <mohammed-yasin.rahman@lip6.fr>
Mon, 16 Dec 2013 13:15:11 +0000 (14:15 +0100)
48 files changed:
.gitignore
manifold/manifoldapi.py
manifold/manifoldproxy.py
manifold/static/js/manifold.js
manifold/static/js/plugin.js
myslice/settings.py
myslice/urls.py
plugins/form/__init__.py
plugins/googlemap/__init__.py
plugins/googlemap/static/js/googlemap.js
plugins/lists/simplelist.py
plugins/lists/static/js/simplelist.js
plugins/maddash/__init__.py
plugins/querycode/__init__.py
plugins/querygrid/__init__.py
plugins/querytable/__init__.py
plugins/querytable/static/js/querytable.js
plugins/scheduler/__init__.py
plugins/senslabmap/__init__.py
plugins/tabs/static/js/tabs.js
plugins/topmenuvalidation/__init__.py [new file with mode: 0644]
plugins/topmenuvalidation/static/js/topmenuvalidation.js [new file with mode: 0644]
portal/accountview.py
portal/dashboardview.py
portal/sliceview.py
sample/dashboardview.py [moved from trash/dashboard.py with 100% similarity]
sample/pluginview.py [moved from trash/pluginview.py with 100% similarity]
sample/querygridview.py [moved from trash/simplegridview.py with 98% similarity]
sample/querytableview.py [moved from trash/simpletableview.py with 98% similarity]
sample/scrollview.py [new file with mode: 0644]
sample/static/css/dashboard.css [moved from trash/static/css/dashboard.css with 100% similarity]
sample/static/css/sample.css [moved from trash/static/css/sample.css with 100% similarity]
sample/tabview.py [new file with mode: 0644]
sample/templates/view-scroll.html [moved from trash/templates/view-scroll.html with 100% similarity]
sample/templates/view-tab.html [moved from trash/templates/view-tab.html with 100% similarity]
sample/templates/view-unfold2.html [moved from trash/templates/view-unfold2.html with 100% similarity]
sample/topmenuvalidationview.py [new file with mode: 0644]
sample/trashutils.py [moved from trash/trashutils.py with 100% similarity]
sample/urls.py
trash/__init__.py [deleted file]
trash/sampleviews.py [deleted file]
trash/urls.py [deleted file]
ui/templates/base.html
ui/templates/widget-topmenu.html
ui/topmenu.py
unfold/page.py
unfold/static/js/plugin-helper.js [moved from unfold/static/js/plugin_helper.js with 100% similarity]
unfold/static/js/spin-presets.js [moved from unfold/static/js/spin.presets.js with 89% similarity]

index ed36fe7..bb1d472 100644 (file)
@@ -15,3 +15,7 @@ build/
 plugins/*/*.css
 plugins/*/*.js
 plugins/*/*.html
+# myslice.ini* is not intended to be under git as it may contain keys and other specifics
+myslice.ini*
+# other junk
+foo.*
index 25b80f9..6639d48 100644 (file)
@@ -135,8 +135,11 @@ def _execute_query(request, query, manifold_api_session_auth):
         # this is gross; at the very least we need to logout() 
         # but most importantly there is a need to refine that test, since 
         # code==2 does not necessarily mean an expired session
-        # del request.session['manifold']
-        raise Exception, 'Error running query: %r' % result
+        # XXX only if we know it is the issue
+        del request.session['manifold']
+        # Flush django session
+        request.session.flush()
+        #raise Exception, 'Error running query: %r' % result
     
     if result['code'] == 1:
         print "WARNING" 
@@ -149,6 +152,7 @@ def _execute_query(request, query, manifold_api_session_auth):
 
 def execute_query(request, query):
     if not 'manifold' in request.session or not 'auth' in request.session['manifold']:
+        request.session.flush()
         raise Exception, "User not authenticated"
     manifold_api_session_auth = request.session['manifold']['auth']
     return _execute_query(request, query, manifold_api_session_auth)
index 3577fe5..d43a3cd 100644 (file)
@@ -16,10 +16,6 @@ from myslice.config             import Config
 debug=False
 #debug=True
 
-# add artificial delay in s
-debug_spin=0
-#debug_spin=1
-
 # pretend the server only returns - empty lists to 'get' requests - this is to mimick 
 # misconfigurations or expired credentials or similar corner case situations
 debug_empty=False
@@ -81,12 +77,6 @@ with the query passed using POST"""
 
         json_answer=json.dumps(result)
 
-        # this is an artificial delay added for debugging purposes only
-        if debug_spin>0:
-            print "Adding additional artificial delay",debug_spin
-            import time
-            time.sleep(debug_spin)
-
         return HttpResponse (json_answer, mimetype="application/json")
 
     except Exception,e:
index 1bb5b97..3d526a6 100644 (file)
@@ -186,19 +186,6 @@ var manifold = {
 
     separator: '__',
 
-    spin_presets: {},
-
-    spin: function(locator, active /*= true */) {
-        active = typeof active !== 'undefined' ? active : true;
-        try {
-            if (active) {
-                $(locator).spin(manifold.spin_presets);
-            } else {
-                $(locator).spin(false);
-            }
-        } catch (err) { messages.debug("Cannot turn spins on/off " + err); }
-    },
-
     get_type: function(variable) {
         switch(Object.toType(variable)) {
             case 'number':
@@ -317,7 +304,7 @@ var manifold = {
     // reasonably low-noise, shows manifold requests coming in and out
     asynchroneous_debug : true,
     // print our more details on result publication and related callbacks
-    publish_result_debug : false,
+    pubsub_debug : false,
 
     /**
      * \brief We use js function closure to be able to pass the query (array)
@@ -356,7 +343,7 @@ var manifold = {
             var publish_uuid=tuple.publish_uuid;
             // by default we publish using the same uuid of course
             if (publish_uuid==undefined) publish_uuid=query.query_uuid;
-            if (manifold.publish_result_debug) {
+            if (manifold.pubsub_debug) {
                 messages.debug("sending POST on " + manifold.proxy_url + query.__repr());
             }
 
@@ -409,27 +396,29 @@ var manifold = {
 
         // NEW PLUGIN API
         manifold.raise_record_event(query.query_uuid, CLEAR_RECORDS);
-        if (manifold.publish_result_debug)
+        if (manifold.pubsub_debug)
             messages.debug(".. publish_result (1) ");
         var count=0;
         $.each(result, function(i, record) {
             manifold.raise_record_event(query.query_uuid, NEW_RECORD, record);
             count += 1;
         });
-        if (manifold.publish_result_debug) 
-            messages.debug(".. publish_result NEW API (2) count=" + count);
+        if (manifold.pubsub_debug) 
+            messages.debug(".. publish_result (2) has used NEW API on " + count + " records");
         manifold.raise_record_event(query.query_uuid, DONE);
+        if (manifold.pubsub_debug) 
+            messages.debug(".. publish_result (3) has used NEW API to say DONE");
 
         // OLD PLUGIN API BELOW
         /* Publish an update announce */
         var channel="/results/" + query.query_uuid + "/changed";
-        if (manifold.publish_result_debug) 
-            messages.debug(".. publish_result OLD API (3) " + channel);
+        if (manifold.pubsub_debug) 
+            messages.debug(".. publish_result (4) OLD API on channel" + channel);
 
         $.publish(channel, [result, query]);
 
-        if (manifold.publish_result_debug) 
-            messages.debug(".. publish_result - END (4) q=" + query.__repr());
+        if (manifold.pubsub_debug) 
+            messages.debug(".. publish_result (5) END q=" + query.__repr());
     },
 
     /*!
@@ -446,7 +435,7 @@ var manifold = {
          * otherwise, publish the main object as well as subqueries
          * XXX how much recursive are we ?
          */
-        if (manifold.publish_result_debug)
+        if (manifold.pubsub_debug)
             messages.debug (">>>>> publish_result_rec " + query.object);
         if (manifold.query_expects_unique_result(query)) {
             /* Also publish subqueries */
@@ -455,12 +444,12 @@ var manifold = {
                 /* TODO remove object from result */
             });
         }
-        if (manifold.publish_result_debug) 
+        if (manifold.pubsub_debug) 
             messages.debug ("===== publish_result_rec " + query.object);
 
         manifold.publish_result(query, result);
 
-        if (manifold.publish_result_debug) 
+        if (manifold.pubsub_debug) 
             messages.debug ("<<<<< publish_result_rec " + query.object);
     },
 
@@ -736,7 +725,7 @@ var manifold = {
         }
 
         if (manifold.asynchroneous_debug) 
-            messages.debug ("========== asynchroneous_success " + query.object + " -- before process_query_records");
+            messages.debug ("========== asynchroneous_success " + query.object + " -- before process_query_records [" + query.query_uuid +"]");
 
         // once everything is checked we can use the 'value' part of the manifoldresult
         var result=data.value;
@@ -760,10 +749,12 @@ var manifold = {
      **************************************************************************/ 
 
     raise_event_handler: function(type, query_uuid, event_type, value) {
+       if (manifold.pubsub_debug)
+           messages.debug("raise_event_handler, quuid="+query_uuid+" type="+type+" event_type="+event_type);
         if ((type != 'query') && (type != 'record'))
             throw 'Incorrect type for manifold.raise_event()';
         // xxx we observe quite a lot of incoming calls with an undefined query_uuid
-        // this should be fixed upstream
+        // this should be fixed upstream in manifold I expect
         if (query_uuid === undefined) {
             messages.warning("undefined query in raise_event_handler");
             return;
@@ -775,9 +766,11 @@ var manifold = {
 
         $.each(channels, function(i, channel) {
             if (value === undefined) {
-                $('.plugin').trigger(channel, [event_type]);
+               if (manifold.pubsub_debug) messages.debug("triggering [no value] on channel="+channel+" and event_type="+event_type);
+                $('.pubsub').trigger(channel, [event_type]);
             } else {
-                $('.plugin').trigger(channel, [event_type, value]);
+               if (manifold.pubsub_debug) messages.debug("triggering [value="+value+"] on channel="+channel+" and event_type="+event_type);
+                $('.pubsub').trigger(channel, [event_type, value]);
             }
         });
     },
index 41d8e8b..4530b51 100644 (file)
@@ -30,6 +30,9 @@ var Plugin = Class.extend({
         // reference and a normal reference
         this.element  = element;
         this.$element = $(element);
+       // programmatically add specific class for publishing events
+       // used in manifold.js for triggering API events
+       if ( ! this.$element.hasClass('pubsub')) this.$element.addClass('pubsub');
 
         // return this so we can chain/use the bridge with less code.
         return this;
@@ -261,13 +264,18 @@ var Plugin = Class.extend({
     },
 
     /* SPIN */
-
-    spin: function() {
-        manifold.spin(this.element);
+    // use spin() to get our default spin settings (called presets)
+    // use spin(true) to get spin's builtin defaults
+    // you can also call spin_presets() yourself and tweak what you need to, like topmenuvalidation does
+    spin: function (presets) {
+       var presets = ( presets === undefined ) ? spin_presets() : presets;
+       try { this.$element.spin(presets); }
+       catch (err) { messages.debug("Cannot turn on spin " + err); }
     },
 
     unspin: function() {
-        manifold.spin(this.element, false);
+       try { this.$element.spin(false); }
+       catch (err) { messages.debug("Cannot turn off spin " + err); }
     },
 
     /* TEMPLATE */
index ff355e4..5c2d29c 100644 (file)
@@ -34,6 +34,14 @@ if not os.path.isdir (os.path.join(HTTPROOT,"static")):
 if not os.path.isdir(ROOT): raise Exception,"Cannot find ROOT %s for unfold"%ROOT
 if not os.path.isdir(HTTPROOT): raise Exception,"Cannot find HTTPROOT %s for unfold"%HTTPROOT
 
+# dec 2013 - we currently have 2 auxiliary subdirs with various utilities
+# that we do not wish to package 
+# * sandbox is for plugin developers
+# * sample is for various test views
+# for each of these, if we find a directory of that name under ROOT, it then gets
+# inserted in INSTALLED_APPS and its urls get included (see urls.py)
+auxiliaries = [ 'sandbox', 'sample', ]
+
 ####################
 ADMINS = (
     # ('your_name', 'your_email@test.com'),
@@ -169,7 +177,7 @@ TEMPLATE_DIRS = (
     os.path.join(HTTPROOT,"templates"),
 )
 
-INSTALLED_APPS = (
+INSTALLED_APPS = [
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
@@ -194,18 +202,11 @@ INSTALLED_APPS = (
     # Uncomment the next line to enable admin documentation:
     # 'django.contrib.admindocs',
     'portal',
-    # temporary - not packaged
-    # 'trash',
-    'sample',
-    'sandbox'
-# DEPRECATED #    'django.contrib.formtools',
-# DEPRECATED ##    'crispy_forms',
-# DEPRECATED #
-# DEPRECATED #    # User registration
-# DEPRECATED #    'django.contrib.auth',
-# DEPRECATED #    'django.contrib.sites',
-# DEPRECATED #    'registration',
-)
+]
+for aux in auxiliaries:
+    if os.path.isdir(os.path.join(ROOT,aux)): 
+        print "Using devel auxiliary",aux
+        INSTALLED_APPS.append(aux)
 
 ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window; you may, of course, use a different value.
 
index b204797..6419726 100644 (file)
@@ -9,6 +9,8 @@ from django.conf      import settings
 from django.template.loader import add_to_builtins
 add_to_builtins('insert_above.templatetags.insert_tags')
 
+from settings import auxiliaries, INSTALLED_APPS
+
 import portal.platformsview
 import portal.dashboardview
 import portal.homeview
@@ -28,7 +30,7 @@ the_after_login_view=dashboard_view
 # might need another one ?
 the_login_view=home_view
 
-urlpatterns = patterns(
+urls = [
     '',
     # Examples:
     # url(r'^$', 'myslice.views.home', name='home'),
@@ -39,31 +41,28 @@ urlpatterns = patterns(
     # url(r'^admin/', include(admin.site.urls)),
     #
     # default / view
-    #
     (r'^/?$', the_default_view),
     #
     # login / logout
-    #
     (r'^login-ok/?$', the_after_login_view, {'state': 'Welcome to MySlice'} ),
+    #
     # seems to be what login_required uses to redirect ...
     (r'^accounts/login/$', the_login_view),
     (r'^login/?$', the_login_view),
     (r'^logout/?$', 'auth.views.logout_user'),
     #
     # the manifold proxy
-    #
     (r'^manifold/proxy/(?P<format>\w+)/?$', 'manifold.manifoldproxy.proxy'),
     #
     # Portal
     url(r'^portal/', include('portal.urls')),
-    # Sandbox
-    url(r'^sandbox/', include('sandbox.urls')),
-    url(r'^sample/', include('sample.urls')),
-    # Debug
-#    url(r'^debug/', include('debug_platform.urls')),
-    #
-    # various trash views - bound to go away 
-    #
-#    url(r'^trash/', include('trash.urls')),
+]
+
+#this one would not match the convention
+# url(r'^debug/', include('debug_platform.urls')),
+# but it was commented out anyways
+for aux in auxiliaries:
+    if aux in INSTALLED_APPS:
+        urls.append ( url ( r'^%s/'%aux, include ('%s.urls'%aux )))
 
-)
+urlpatterns = patterns(*urls)
index ff569d5..d4dce75 100644 (file)
@@ -33,7 +33,7 @@ class CreateForm (Plugin):
     
     def requirements (self):
         # Some should be included by default by manifold
-        return { 'js_files'     : ['js/manifold.js', 'js/spin.presets.js', 'js/spin.min.js', 'js/jquery.spin.js',
+        return { 'js_files'     : ['js/manifold.js', 'js/spin-presets.js', 'js/spin.min.js', 'js/jquery.spin.js',
                                    'js/form.js', 'js/jquery.validate.js', ],
                  'css_files'    : ['css/form.css'] 
                  }
index 583b8dd..a769f7f 100644 (file)
@@ -35,7 +35,7 @@ class GoogleMap (Plugin):
                            "/js/googlemap.js",
                            "/js/markerclusterer.js",
                             "js/manifold.js", "js/manifold-query.js", 
-                            "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                            "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
                             "js/unfold-helper.js",
                            ],
             'css_files' : [ "css/googlemap.css",
index 764f1b4..91ece99 100644 (file)
            this.by_id = {};
            this.by_init_id = {};
 
-            /* XXX Events */
+            /* Events */
+           // xx somehow non of these triggers at all for now
             this.elmt().on('show', this, this.on_show);
-            // TODO in destructor
-            // $(window).unbind('QueryTable');
+            this.elmt().on('shown.bs.tab', this, this.on_show);
+            this.elmt().on('resize', this, this.on_resize);
 
             var query = manifold.query_store.find_analyzed_query(this.options.query_uuid);
             this.object = query.object;
            if (debug) messages.debug("googlemap.on_show");
             var googlemap = e.data;
             google.maps.event.trigger(googlemap.map, 'resize');
-        }, // on_show
+        }, 
+       // dummy to see if this triggers at all
+        on_resize: function(e) {
+           if (debug) messages.debug("googlemap.on_resize ...");
+        }, 
 
         /* GUI EVENTS */
 
             }
            
             var domid = this.options.plugin_uuid + '--' + 'googlemap';
-               var elmt = document.getElementById(domid);
-               if (debug) messages.debug("gmap.initialize_map based on  domid=" + domid + " elmt=" + elmt);
+           var elmt = document.getElementById(domid);
             this.map = new google.maps.Map(elmt, myOptions);
             this.infowindow = new google.maps.InfoWindow();
         }, // initialize_map
 
         /*************************** RECORD HANDLER ***************************/
         on_new_record: function(record) {
-           if (debug_deep) messages.debug("on_new_record");
+           if (debug_deep) messages.debug("googlemap.on_new_record");
             if (this.received_all)
                 // update checkbox for record
                 this.set_checkbox_from_record(record, true);
         },
 
         on_clear_records: function(record) {
-           if (debug_deep) messages.debug("on_clear_records");
+           if (debug_deep) messages.debug("googlemap.on_clear_records");
         },
 
         // Could be the default in parent
         on_query_in_progress: function() {
-           if (debug) messages.debug("on_query_in_progress (spinning)");
+           if (debug) messages.debug("googlemap.on_query_in_progress (spinning)");
             this.spin();
         },
 
         on_query_done: function() {
-               if (debug) messages.debug("on_query_done");         
+               if (debug) messages.debug("googlemap.on_query_done");       
             if (this.received_all) {
                 this.unspin();
                }
         },
 
         on_field_state_changed: function(data) {
-           if (debug_deep) messages.debug("on_field_state_changed");       
+           if (debug_deep) messages.debug("googlemap.on_field_state_changed");     
             switch(data.request) {
             case FIELD_REQUEST_ADD:
             case FIELD_REQUEST_ADD_RESET:
         // all : this 
 
         on_all_new_record: function(record) {
-           if (debug_deep) messages.debug("on_all_new_record");
+           if (debug_deep) messages.debug("googlemap.on_all_new_record");
             this.new_record(record);
         },
 
         on_all_clear_records: function() {
-           if (debug) messages.debug("on_all_clear_records");      
+           if (debug) messages.debug("googlemap.on_all_clear_records");            
         },
 
         on_all_query_in_progress: function() {
-           if (debug) messages.debug("on_all_query_in_progress (spinning)");
+           if (debug) messages.debug("googlemap.on_all_query_in_progress (spinning)");
             // XXX parent
             this.spin();
         },
 
         on_all_query_done: function() {
-           if (debug) messages.debug("on_all_query_done");
+           if (debug) messages.debug("googlemap.on_all_query_done");
 
             // MarkerClusterer
             var markers = [];
                 });
                // reset 
                googlemap.in_set_backlog = [];
-
-               if (debug) messages.debug("unspinning");
                 this.unspin();
             }
             this.received_all = true;
index 2651030..c817d9b 100644 (file)
@@ -27,7 +27,7 @@ class SimpleList (Plugin) :
         reqs = {
             'js_files' : [ "js/simplelist.js", 
                            "js/manifold.js", "js/manifold-query.js", 
-                           "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                           "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
                            "js/unfold-helper.js",
                            ] ,
             'css_files': [ "css/simplelist.css" ],
index a8f90b9..2bed5b4 100644 (file)
@@ -19,7 +19,7 @@
 
         on_query_in_progress: function() {
            messages.debug("on_query_in_progress");
-            this.spin();
+            this.spin(true);
         },
 
         on_query_done: function() {
            if (debug) messages.debug('datatables_update_table ' + rows.length + " rows");
            $table.dataTable().fnClearTable();
            // the lambda here returns a [[]] because $.map is kind of broken; as per the doc:
-           // The function can return any value to add to the array. A returned array will be flattened into the resulting array.
+           // The function can return any value to add to the array. 
+           // A returned array will be flattened into the resulting array.
            // this is wrong indeed so let's work around that
            var self=this;
            $table.dataTable().fnAddData( $.map(rows, function (row) { return [[ self._cell (key,row[key]) ]] }) );
index 0447ff4..9de64bc 100644 (file)
@@ -26,7 +26,7 @@ class MadDash (Plugin):
                 'js/jquery.tipsy.js',
                 'js/buffer.js', 'js/maddash.js',
                 'js/manifold.js', 'js/manifold-query.js',
-                'js/spin.presets.js', 'js/spin.min.js', 'js/jquery.spin.js', 
+                'js/spin-presets.js', 'js/spin.min.js', 'js/jquery.spin.js', 
                 'js/unfold-helper.js',
             ],
             'css_files' : [ 
index d46a842..0a2391f 100644 (file)
@@ -14,7 +14,7 @@ class QueryCode (Plugin):
             'js_files' : [ 
                 "js/querycode.js", 
                 "js/manifold.js", "js/manifold-query.js",
-                "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
                 "js/shAutoloader.js","js/shCore.js","js/shBrushPython.js","js/shBrushRuby.js",
                 ] ,
 # thierry: see this file for details of why we turn this off for now            
index 5b0c466..22a2aab 100644 (file)
@@ -87,7 +87,7 @@ Current implementation makes the following assumptions
     def requirements (self):
         reqs = {
             'js_files' : [ 
-                "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
 # this one was in the slickgrid demo 
 # http://mleibman.github.io/SlickGrid/examples/example-checkbox-row-select.html
 # but triggers js errors when included - probably/maybe because of the jquery version ?
index b435b38..0b1d29d 100644 (file)
@@ -84,7 +84,7 @@ Current implementation makes the following assumptions
 
     def requirements (self):
         reqs = {
-            'js_files' : [ "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+            'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
                            "js/dataTables.js", "js/dataTables.bootstrap.js", "js/with-datatables.js",
                            "js/manifold.js", "js/manifold-query.js", 
                            "js/unfold-helper.js",
index 935c087..bcb8192 100644 (file)
            // an internal buffer for keeping lines and display them in one call to fnAddData
            this.buffered_lines = [];
 
-            /* XXX Events XXX */
-            // this.$element.on('show.Datatables', this.on_show);
+            /* Events */
+           // xx somehow non of these triggers at all for now
             this.elmt().on('show', this, this.on_show);
-            // Unbind all events using namespacing
-            // TODO in destructor
-            // $(window).unbind('QueryTable');
+            this.elmt().on('shown.bs.tab', this, this.on_show);
+            this.elmt().on('resize', this, this.on_resize);
 
             var query = manifold.query_store.find_analyzed_query(this.options.query_uuid);
             this.object = query.object;
 
         /* PLUGIN EVENTS */
 
-        on_show: function(e)
-        {
+        on_show: function(e) {
+           if (debug) messages.debug("querytable.on_show");
             var self = e.data;
+            self.table.fnAdjustColumnSizing();
+       },        
 
-            self.table.fnAdjustColumnSizing()
-        
-            /* Refresh dataTabeles if click on the menu to display it : fix dataTables 1.9.x Bug */        
-            /* temp disabled... useful ? -- jordan
-            $(this).each(function(i,elt) {
-                if (jQuery(elt).hasClass('dataTables')) {
-                    var myDiv=jQuery('#querytable-' + this.id).parent();
-                    if(myDiv.height()==0) {
-                        var oTable=$('#querytable-' + this.id).dataTable();            
-                        oTable.fnDraw();
-                    }
-                }
-            });
-            */
-        }, // on_show
+        on_resize: function(e) {
+           if (debug) messages.debug("querytable.on_resize");
+            var self = e.data;
+            self.table.fnAdjustColumnSizing();
+       },        
 
         /* GUI EVENTS */
 
             result += " class='querytable-checkbox'";
         // compute id from canonical_key
            var id = record[this.canonical_key]
-//         if (debug) messages.debug("checkbox_html, id="+id);
         // compute init_id form init_key
            var init_id=record[this.init_key];
         // set id - for retrieving from an id, or for posting events upon user's clicks
        set_checkbox_from_record: function (record, checked) {
             if (checked === undefined) checked = true;
            var init_id = record[this.init_key];
-           if (debug) messages.debug("set_checkbox_from_record, init_id="+init_id);
+           if (debug) messages.debug("querytable.set_checkbox_from_record, init_id="+init_id);
            // using table.$ to search inside elements that are not visible
            var element = this.table.$('[init_id="'+init_id+'"]');
            element.attr('checked',checked);
        // id relates to canonical_key
        set_checkbox_from_data: function (id, checked) {
             if (checked === undefined) checked = true;
-           if (debug) messages.debug("set_checkbox_from_data, id="+id);
+           if (debug) messages.debug("querytable.set_checkbox_from_data, id="+id);
            // using table.$ to search inside elements that are not visible
            var element = this.table.$("[id='"+id+"']");
            element.attr('checked',checked);
                // if the 'all' query has been dealt with already we may turn on the checkbox
                 this.set_checkbox_from_record(record, true);
             } else {
-               // otherwise we need to remember that and do it later on
-               if (debug) messages.debug("Remembering record to check " + record[this.init_key]);
                 this.buffered_records_to_check.push(record);
             }
         },
            // if we've already received the slice query, we have not been able to set 
            // checkboxes on the fly at that time (dom not yet created)
             $.each(this.buffered_records_to_check, function(i, record) {
-               if (debug) messages.debug ("delayed turning on checkbox " + i + " record= " + record);
+               if (debug) messages.debug ("querytable delayed turning on checkbox " + i + " record= " + record);
                 self.set_checkbox_from_record(record, true);
             });
            this.buffered_records_to_check = [];
index c21e96b..caaaa52 100644 (file)
@@ -27,7 +27,7 @@ class Scheduler(Plugin):
                            #"//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js",
                             "js/raphael.js",
                             "js/manifold.js", "js/manifold-query.js", 
-                            "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                            "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
                             "js/unfold-helper.js",
                             "js/jquery-ui-timepicker-addon.js", "js/jquery-ui-sliderAccess.js",
                            ],
index 03b06a4..8b8075c 100644 (file)
@@ -21,7 +21,7 @@ class SensLabMap (Plugin):
     def requirements (self):
         reqs = {
             'js_files' : [ "js/senslabmap.js",
-                           "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js",
+                           "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
                            "js/three.min.js", "js/jquery-mousewheel.min.js", "js/map.js",
                            ],
             'css_files': [ "css/senslabmap.css",
index 4612dd2..7c7f159 100644 (file)
@@ -1,6 +1,6 @@
 // storing tabs active component in localStorage
 //
-// based on plugin_helper.js, extended to store the domid of an active tab
+// based on plugin-helper.js, extended to store the domid of an active tab
 //
 
 var tabs_helper = {
diff --git a/plugins/topmenuvalidation/__init__.py b/plugins/topmenuvalidation/__init__.py
new file mode 100644 (file)
index 0000000..2006e79
--- /dev/null
@@ -0,0 +1,76 @@
+from unfold.plugin import Plugin
+
+class TopmenuValidation (Plugin):
+
+    """This plugin is designed to work together with topmenu.
+    
+It will check to see if user has PI rights at least on one authority, 
+and if so will enable corresponding validation button in topmenu.
+
+A realistic example would have incoming query as
+
+Query.get('ple:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+
+"""
+
+    def __init__ (self, query=None, button_domid=None, **settings):
+        Plugin.__init__ (self, **settings)
+        # set defaults
+        if query is None: 
+            query = Query.get('ple:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+        if button_domid is None: button_domid="topmenu-validate"
+        self.query=query
+        self.button_domid=button_domid
+
+    # this does not have any materialization
+    def render_content (self, request):
+        return ""
+    
+    def requirements (self):
+        return { 'js_files': [ 'js/topmenuvalidation.js', 'js/manifold-query.js', 
+                               "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js", 
+                               ], }
+
+    def json_settings_list (self):
+        return [ 'query_uuid', 'button_domid', ]
+
+#################### here is an extract previously in topmenu.py
+#import json
+#from pprint import pprint
+#from manifold.manifoldapi       import execute_query
+#from manifold.core.query        import Query
+###        # ** Where am I a PI **
+###        # For this we need to ask SFA (of all authorities) = PI function
+###        user_query  = Query().get('local:user').select('config','email')
+###        user_details = execute_query(request, user_query)
+###
+###        # Required: the user must have an authority in its user.config
+###        # XXX Temporary solution
+###        # not always found in user_details...
+###        config={}
+#### Deactivated until fixed 
+####        if user_details is not None:
+####            for user_detail in user_details:
+####                #email = user_detail['email']
+####                if user_detail['config']:
+####                    config = json.loads(user_detail['config'])
+####            user_detail['authority'] = config.get('authority',"Unknown Authority")
+####            print "topmenu: %s", (user_detail['authority'])
+####            if user_detail['authority'] is not None:
+####                sub_authority = user_detail['authority'].split('.')
+####                root_authority = sub_authority[0]
+####                pi_authorities_query = Query.get(root_authority+':user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+####        else:
+####            pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+####        try:
+####            pi_authorities_tmp = execute_query(request, pi_authorities_query)
+####        except:
+####            pi_authorities_tmp = set()
+####        pi_authorities = set()
+####        for pa in pi_authorities_tmp:
+####            if 'pi_authorities' in pa:
+####                pi_authorities |= set(pa['pi_authorities'])
+####        print "pi_authorities =", pi_authorities
+####        if len(pi_authorities) > 0:
+####            result.append({'label':'Validation', 'href': '/portal/validate/'})
+###        result.append({'label':'Validation', 'href': '/portal/validate/'})
diff --git a/plugins/topmenuvalidation/static/js/topmenuvalidation.js b/plugins/topmenuvalidation/static/js/topmenuvalidation.js
new file mode 100644 (file)
index 0000000..6cfc383
--- /dev/null
@@ -0,0 +1,44 @@
+// first application is for the 'validation' button in the topmenu
+// if the subject query is non empty, then we turn on the subject button
+// that is provided through button_domid
+
+(function($){
+
+    var debug=false;
+//    debug=true
+
+    var TopmenuValidation = Plugin.extend({
+
+        init: function(options, element) {
+            this._super(options, element);
+            this.listen_query(options.query_uuid);
+           this.triggered=false;
+       },
+
+        // Could be the default in parent
+        on_query_in_progress: function() {
+           var presets = spin_presets();
+           presets.radius=5;
+           presets.length=4;
+           presets.lines=7;
+           presets.width=2;
+            this.spin(presets);
+        },
+
+       // we have received at least one answer: we'll do something
+       on_new_record: function (record) {
+           // we only need to act on the first record
+           if (this.triggered) return;
+           $('#'+this.options.button_domid).removeClass('disabled');
+           this.unspin();
+           this.triggered=true;
+        },
+       // for reference only, since there is nothing we need to do at this point
+       on_query_done: function() {
+           if (!this.triggered) this.unspin();
+       },
+    });
+
+    $.plugin('TopmenuValidation', TopmenuValidation);
+
+})(jQuery);
index 66eb91e..0d4059f 100644 (file)
@@ -66,7 +66,7 @@ class AccountView(LoginRequiredAutoLogoutView):
         pub_key_list = []
           
         for platform_detail in platform_details:
-            if 'sfa' in platform_detail['gateway_type'] and platform_detail['disabled']==0:
+            if 'sfa' in platform_detail['gateway_type']:
                 total_platform = platform_detail['platform']
                 total_platform_list.append(total_platform)
                 
@@ -152,7 +152,10 @@ class AccountView(LoginRequiredAutoLogoutView):
                         platform_access_list.append(platform_access)
        
         # Removing the platform which already has access
+        print platform_access_list
+        print total_platform_list
         for platform in platform_access_list:
+            print platform
             total_platform_list.remove(platform)
         # we could use zip. this one is used if columns have unequal rows 
         platform_list = [{'platform_no_access': t[0]}
index 44a3ea9..4117782 100644 (file)
@@ -1,4 +1,7 @@
+import json
 from manifold.core.query         import Query
+from manifold.manifoldapi        import execute_query
+
 from unfold.page                 import Page
 
 from plugins.lists.testbedlist   import TestbedList
@@ -21,10 +24,28 @@ class DashboardView (LoginRequiredAutoLogoutView):
         #messages.info(self.request, 'You have logged in')
         page = Page(self.request)
 
+        print "Dashboard page"
         # Slow...
         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
         testbed_query  = Query().get('network').select('network_hrn','platform')
         # DEMO GEC18 Query only PLE
+        user_query  = Query().get('local:user').select('config','email')
+        user_details = execute_query(self.request, user_query)
+
+        # not always found in user_details...
+        config={}
+  #      for user_detail in user_details:
+  #          #email = user_detail['email']
+  #          if user_detail['config']:
+  #              config = json.loads(user_detail['config'])
+  #      user_detail['authority'] = config.get('authority',"Unknown Authority")
+#
+#        print user_detail
+#        if user_detail['authority'] is not None:
+#            sub_authority = user_detail['authority'].split('.')
+#            root_authority = sub_authority[0]
+#            slice_query = Query().get(root_authority+':user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
+#        else:
         slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
         page.enqueue_query(slice_query)
         page.enqueue_query(testbed_query)
index 2d77bdf..318ee34 100644 (file)
@@ -1,3 +1,4 @@
+import json
 from django.template                 import RequestContext
 from django.shortcuts                import render_to_response
 
@@ -5,8 +6,9 @@ from unfold.loginrequired            import LoginRequiredAutoLogoutView
 
 from unfold.page                     import Page
 from manifold.core.query             import Query, AnalyzedQuery
+from manifold.manifoldapi            import execute_query
 
-from ui.topmenu                      import topmenu_items, the_user
+from ui.topmenu                      import topmenu_items_live, the_user
 
 from plugins.raw                     import Raw
 from plugins.stack                   import Stack
@@ -56,8 +58,9 @@ class SliceView (LoginRequiredAutoLogoutView):
         page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
         config=Config()
         page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
+
         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']]
@@ -81,14 +84,37 @@ class SliceView (LoginRequiredAutoLogoutView):
         main_query_init_key = 'hostname'
     
         query_resource_all = Query.get('resource').select(resource_fields)
-        if do_query_users:
-            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)
         if do_query_users:
-            page.enqueue_query(query_user_all)
+            # Required: the user must have an authority in its user.config
+            # XXX Temporary solution
+            user_query  = Query().get('local:user').select('config','email')
+            user_details = execute_query(self.request, user_query)
+            
+            # not always found in user_details...
+            config={}
+#            for user_detail in user_details:
+#                #email = user_detail['email']
+#                if user_detail['config']:
+#                    config = json.loads(user_detail['config'])
+#            user_detail['authority'] = config.get('authority',"Unknown Authority")
+#
+#            if user_detail['authority'] is not None:
+#                sub_authority = user_detail['authority'].split('.')
+#                root_authority = sub_authority[0]
+#                query_user_all = Query.get(root_authority+':user').select(user_fields)
+#
+#                # XXX TODO this filter doesn't work - to be improved in Manifold
+#                #.filter_by('authority.authority_hrn', '=', user_detail['authority'])
+#
+#                page.enqueue_query(query_user_all)
+#            else:
+#                print "authority of the user is not in local:user db"
+            query_user_all = Query.get('user').select(user_fields)
+            #    query_user_all = None
     
         # ... and for the relations
         # XXX Let's hardcode resources for now
@@ -264,7 +290,7 @@ class SliceView (LoginRequiredAutoLogoutView):
         # --------------------------------------------------------------------------
         # USERS
     
-        if do_query_users:
+        if do_query_users and query_user_all is not None:
             tab_users = Tabs(
                 page                = page,
                 domid               = 'users',
@@ -394,7 +420,6 @@ class SliceView (LoginRequiredAutoLogoutView):
                     outline_complete = True,
                     ))
     
-    
         # variables that will get passed to the view-unfold1.html template
         template_env = {}
         
@@ -404,7 +429,7 @@ class SliceView (LoginRequiredAutoLogoutView):
         # 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
+        template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page
         # so we can sho who is logged
         template_env [ 'username' ] = the_user (request) 
     
similarity index 100%
rename from trash/dashboard.py
rename to sample/dashboardview.py
similarity index 100%
rename from trash/pluginview.py
rename to sample/pluginview.py
similarity index 98%
rename from trash/simplegridview.py
rename to sample/querygridview.py
index 014e143..ef8d993 100644 (file)
@@ -11,7 +11,7 @@ from ui.topmenu import topmenu_items, the_user
 
 from plugins.querygrid import QueryGrid
 
-class SimpleGridView (TemplateView):
+class QueryGridView (TemplateView):
 
     def get (self, request, slicename='ple.inria.f14'):
 
similarity index 98%
rename from trash/simpletableview.py
rename to sample/querytableview.py
index e0fd770..2e08abc 100644 (file)
@@ -11,7 +11,7 @@ from ui.topmenu import topmenu_items, the_user
 
 from plugins.querytable import QueryTable
 
-class SimpleTableView (TemplateView):
+class QueryTableView (TemplateView):
 
     def get (self, request, slicename='ple.inria.f14'):
 
diff --git a/sample/scrollview.py b/sample/scrollview.py
new file mode 100644 (file)
index 0000000..605cb3c
--- /dev/null
@@ -0,0 +1,20 @@
+from django.core.context_processors import csrf
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.contrib.auth.decorators import login_required
+
+from unfold.prelude import Prelude
+
+from ui.topmenu import topmenu_items, the_user
+# tmp
+from trash.trashutils import lorem, hard_wired_slice_names
+
+def scroll_view (request):
+    return render_to_response ('view-scroll.html',
+                               {'title':'Toy page for scrolling',
+                                'topmenu_items': topmenu_items('scroll',request),
+                                'username':the_user (request),
+                                'lorem':lorem,
+                                },
+                               context_instance=RequestContext(request))
+
diff --git a/sample/tabview.py b/sample/tabview.py
new file mode 100644 (file)
index 0000000..167788e
--- /dev/null
@@ -0,0 +1,27 @@
+from django.core.context_processors import csrf
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.contrib.auth.decorators import login_required
+
+from unfold.prelude import Prelude
+
+from ui.topmenu import topmenu_items, the_user
+# tmp
+from trash.trashutils import lorem, hard_wired_slice_names
+
+@login_required
+def tab_view (request):
+    print "request", request.__class__
+    print request
+    prelude=Prelude( js_files='js/bootstrap.js', css_files='css/bootstrap.css')
+    prelude_env = prelude.prelude_env()
+
+    tab_env = {'title':'Page for playing with Tabs',
+               'topmenu_items': topmenu_items('tab',request),
+               'username':the_user (request),
+               'lorem': lorem,                                
+               }
+    tab_env.update (prelude_env)
+    return render_to_response ('view-tab.html', tab_env,
+                               context_instance=RequestContext(request))
+
diff --git a/sample/topmenuvalidationview.py b/sample/topmenuvalidationview.py
new file mode 100644 (file)
index 0000000..27b420e
--- /dev/null
@@ -0,0 +1,48 @@
+# just one instance of validator
+from django.views.generic.base import TemplateView
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+
+from manifold.core.query import Query, AnalyzedQuery
+
+from unfold.page import Page
+
+from ui.topmenu import topmenu_items_live, the_user
+
+class TopmenuValidationView (TemplateView):
+
+    # mention a user name in the URL as .../trash/simpletopmenuvalidation/ple.inria.thierry_parmentelat
+    def get (self, request, username='ple.inria.thierry_parmentelat'):
+
+        if username=='logged': username='$user_hrn'
+
+        page=Page(request)
+
+        # variables that will get passed to the view-unfold1.html template
+        template_env = {}
+        
+        # write something of our own instead
+        template_env ['unfold_main'] = '<h1>Some title </h1>'
+        
+        # more general variables expected in the template
+        template_env [ 'title' ] = 'simple topmenuvalidation %(username)s'%locals()
+        # the menu items on the top
+        template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page) 
+        # so we can see who is logged
+        template_env [ 'username' ] = the_user (request) 
+    
+        # don't forget to run the requests
+        page.expose_queries ()
+
+        # the prelude object in page contains a summary of the requirements() for all plugins
+        # define {js,css}_{files,chunks}
+        prelude_env = page.prelude_env()
+
+#        print prelude_env.keys()
+#        for k in [ 'js_files' ] :
+#            print 'prelude_env',prelude_env,k,prelude_env[k]
+
+        template_env.update(prelude_env)
+        result=render_to_response ('view-unfold1.html',template_env,
+                                   context_instance=RequestContext(request))
+        return result
similarity index 100%
rename from trash/trashutils.py
rename to sample/trashutils.py
index d56b5dc..9494fe8 100644 (file)
@@ -5,6 +5,7 @@
 #
 # Authors:
 #   Jordan AugĂ© <jordan.auge@lip6.fr>
+#   thierry.parmentelat@inria.fr
 # Copyright 2013, UPMC Sorbonne UniversitĂ©s / LIP6
 #
 # This program is free software; you can redistribute it and/or modify it under
 from django.conf.urls import patterns, url
 from sample.views     import WebSocketsView, WebSockets2View
 
-urlpatterns = patterns('',
-    url(r'^websockets/?$', WebSocketsView.as_view(), name='websockets'),
-    url(r'^websockets2/?$', WebSockets2View.as_view(), name='websockets2'),
+import sample.querytableview
+import sample.querygridview
+import sample.topmenuvalidationview
+
+urlpatterns = patterns(
+    '',
+    url(r'^websockets/?$',                                      WebSocketsView.as_view(), name='websockets'),
+    url(r'^websockets2/?$',                                     WebSockets2View.as_view(), name='websockets2'),
+    url(r'^tab/?$',                                             'sample.tabview.tab_view'),
+    url(r'^scroll/?$',                                          'sample.scrollview.scroll_view'),
+    url(r'^plugin/?$',                                          'sample.pluginview.test_plugin_view'),
+    url(r'^dashboard/?$',                                       'sample.dashboardview.dashboard_view'),
+    url(r'^querytable/(?P<slicename>[\w\.]+)/?$',               sample.querytableview.QueryTableView.as_view()),
+    url(r'^querygrid/(?P<slicename>[\w\.]+)/?$',                sample.querygridview.QueryGridView.as_view()),
+    url(r'^topmenuvalidation/(?P<username>[\w\._]+)/?$',        sample.topmenuvalidationview.TopmenuValidationView.as_view()),
 )
diff --git a/trash/__init__.py b/trash/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/trash/sampleviews.py b/trash/sampleviews.py
deleted file mode 100644 (file)
index e1c66d8..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-# Create your views here.
-from django.core.context_processors import csrf
-from django.template import RequestContext
-from django.shortcuts import render_to_response
-from django.contrib.auth.decorators import login_required
-
-from unfold.prelude import Prelude
-
-from ui.topmenu import topmenu_items, the_user
-# tmp
-from trash.trashutils import lorem, hard_wired_slice_names
-
-@login_required
-def tab_view (request):
-    print "request", request.__class__
-    print request
-    prelude=Prelude( js_files='js/bootstrap.js', css_files='css/bootstrap.css')
-    prelude_env = prelude.prelude_env()
-
-    tab_env = {'title':'Page for playing with Tabs',
-               'topmenu_items': topmenu_items('tab',request),
-               'username':the_user (request),
-               'lorem': lorem,                                
-               }
-    tab_env.update (prelude_env)
-    return render_to_response ('view-tab.html', tab_env,
-                               context_instance=RequestContext(request))
-
-def scroll_view (request):
-    return render_to_response ('view-scroll.html',
-                               {'title':'Toy page for scrolling',
-                                'topmenu_items': topmenu_items('scroll',request),
-                                'username':the_user (request),
-                                'lorem':lorem,
-                                },
-                               context_instance=RequestContext(request))
-
-@login_required
-def test_plugin_view (request):
-
-    page = Page(request)
-    
-    # variables that will get passed to this template
-    template_env = {}
-    
-    main_plugin = \
-        Stack ( page=page,
-                title='title for the vertical layout',
-                sons = [ StaticList (page=page,
-                                     title='StaticList - with datatables - starts toggled off',
-                                     list=hard_wired_list, 
-                                     header='Hard wired header', 
-                                     foo='the value for foo',
-                                     with_datatables=True,
-                                     toggled=False),
-                         Tabs (page=page,
-                               title='Sample Tabs',
-                               domid='test-tabs',
-                               # *** we select this one to be the active tab ***
-                               active_domid='son2',
-                               sons = [ Raw (page=page,
-                                             title='a raw plugin',
-                                             domid='son0',
-                                             togglable=False,
-                                             html= 3*lorem_p,
-                                             ),
-                                        StaticList(page=page,
-                                                   title='a slice list',
-                                                   domid='son1',
-                                                   togglable=False,
-                                                   header="static list but not togglable",
-                                                   list=hard_wired_slice_names,
-                                                   ),
-                                        Raw (page=page,
-                                             title='raw title',
-                                             domid='son2',
-                                             togglable=False,
-                                             html=lorem) ]),
-                         StaticList (page=page,
-                                     title='SimpleList with slice names', 
-                                     list=hard_wired_slice_names,
-                                     ),
-                         QuickFilter (page=page,
-                                      title='QuickFilter in main content',
-                                      criterias=quickfilter_criterias,
-                                      ) ] )
-    # define 'unfold_main' to the template engine
-    template_env [ 'unfold_main' ] = main_plugin.render(request)
-
-    ##########
-    related_plugin = StaticList (page=page,
-                                 title='SliceList plugin',domid='slicelist1',
-                                 with_datatables='yes', 
-                                 list=hard_wired_slice_names, 
-                                 header='Slices')
-    # likewise but on the side view
-    template_env [ 'unfold_margin' ] = related_plugin.render (request)
-
-    # more general variables expected in the template
-    template_env [ 'title' ] = 'Test Plugin View' 
-    template_env [ 'topmenu_items' ] = topmenu_items('plugin', request) 
-    template_env [ 'username' ] = the_user (request) 
-
-    # we don't have anythong asynchroneous, and manifold.js is not loaded
-#    page.expose_queries ()
-
-    # 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)
-    return render_to_response ('view-unfold2.html',template_env,
-                               context_instance=RequestContext(request))
-                               
diff --git a/trash/urls.py b/trash/urls.py
deleted file mode 100644 (file)
index 5e14d97..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.conf.urls           import patterns, include, url
-
-import trash.simpletableview
-import trash.simplegridview
-
-urlpatterns = patterns(
-    '',
-    url(r'^tab/?$',          'trash.sampleviews.tab_view'),
-    url(r'^scroll/?$',          'trash.sampleviews.scroll_view'),
-    url(r'^plugin/?$',          'trash.pluginview.test_plugin_view'),
-    url(r'^dashboard/?$',       'trash.dashboard.dashboard_view'),
-    url(r'^simpletable/(?P<slicename>[\w\.]+)/?$', trash.simpletableview.SimpleTableView.as_view()),
-    url(r'^simplegrid/(?P<slicename>[\w\.]+)/?$', trash.simplegridview.SimpleGridView.as_view()),
-)
index 908f0f4..49a57ad 100644 (file)
@@ -14,7 +14,7 @@
 {% insert_str prelude "js/jquery.html5storage.min.js" %}
 {% insert_str prelude "js/messages-runtime.js" %}
 {% insert_str prelude "js/class.js" %}
-{% insert_str prelude "js/plugin_helper.js" %}
+{% insert_str prelude "js/plugin-helper.js" %}
 {% insert_str prelude "js/mustache.js" %}
 {% insert_str prelude "js/plugin.js" %}
 {% insert_str prelude "js/manifold.js" %}
index dbcbe1f..089bd3c 100644 (file)
          <a class="dropdown-toggle" data-toggle="dropdown" href="{{ d.href }}">{{ d.label }}<b class="caret"></b></a>
          <ul class="dropdown-menu">
            {% for dd in d.contents %}
-           {% if dd.is_active %}<li class='active'>{% else %}<li class='other'>{% endif %}
+           <li class='{% if dd.is_active %}active{% else %}other{% endif %}{% if dd.disabled %} disabled{%endif%}'
+           {% if dd.domid %} id='{{dd.domid}}'{% endif %}>
            <a href="{{ dd.href }}"> {{ dd.label }} </a> </li>
            {% endfor %}
          </ul>
         </li>
         {% else %} 
-       {% if d.is_active %} <li class='active'> {% else %} <li class='other'> {% endif %}
+       <li class='{% if d.is_active %}active{% else %}other{% endif %}{% if d.disabled %} disabled{%endif%}'
+       {% if d.domid %} id='{{d.domid}}'{% endif %}>
        <a href="{{ d.href }}"> {{ d.label }} </a> </li>
        {% endif %}
        {% endfor %}
index 860e180..6b152c8 100644 (file)
@@ -1,36 +1,34 @@
-from pprint import pprint
-from manifold.manifoldapi       import execute_query
-from manifold.core.query        import Query
 # a set of utilities to help make the global layout consistent across views
 
+def the_user (request):
+    "retrieves logged in user's email, or empty string"
+    if not request.user.is_authenticated (): 
+        return ''
+    else: 
+        return request.user.email
+
 # dropdowns are kind of ad hoc for now, and limited to one level
 # [ 
 # ### a regular first-level button
-# {'label':...,'href':...}, 
+# {'label':...,'href':..., ['domid':.., 'disabled':...]}, 
 # ### a dropdown
 # { 'label': ..., 'href'=..., 'dropdown':True, 'contents': [ { 'label':.., 'href'} ] }
 # , ..]
 
+# see also templates/widget-topmenu.html for how these items are put together
+# and plugins/topmenuvalidation for how this hident button is turned on when necessary
+
 # current: the beginning of the label in the menu that you want to outline
-def topmenu_items (current,request=None):
+def topmenu_items_static (current, request):
     has_user=request.user.is_authenticated()
     result=[]
+    print request.user
     if has_user:
         result.append({'label':'Dashboard', 'href': '/portal/dashboard/'})
         result.append({'label':'Request a slice', 'href': '/portal/slice_request/'})
-        # ** Where am I a PI **
-        # For this we need to ask SFA (of all authorities) = PI function
-        pi_authorities_query = Query.get('ple:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
-        try:
-            pi_authorities_tmp = execute_query(request, pi_authorities_query)
-        except:
-            pi_authorities_tmp = set()
-        pi_authorities = set()
-        for pa in pi_authorities_tmp:
-            pi_authorities |= set(pa['pi_authorities'])
-        print "pi_authorities =", pi_authorities
-        if len(pi_authorities) > 0:
-            result.append({'label':'Validation', 'href': '/portal/validate/'})
+        # always create a disabled button for validation, and let the 
+        # topmenuvalidation plugin handle that asynchroneously, based on this domid
+        result.append({'label':'Validation', 'href': '/portal/validate/', 'domid':'topmenu-validation', 'disabled':True})
         dropdown = []
         dropdown.append({'label':'Platforms', 'href': '/portal/platforms/'})
         dropdown.append({'label':'My Account', 'href': '/portal/account/'})
@@ -42,8 +40,8 @@ def topmenu_items (current,request=None):
         result.append({'label':'Platforms', 'href': '/portal/platforms/'})
         result.append({'label':'Register', 'href': '/portal/register/'})
         result.append({'label':'Contact Support', 'href': '/portal/contact/'})
+
     # mark active if the provided 'current', even if shorter, matches the beginning of d['label']
-    
     if current is not None:
         current=current.lower()
         curlen=len(current)
@@ -57,9 +55,34 @@ def topmenu_items (current,request=None):
                 for dd in d['contents']: mark_active(dd,d)
     return result
 
-def the_user (request):
-    "retrieves logged in user's email, or empty string"
-    if not request.user.is_authenticated (): 
-        return ''
-    else: 
-        return request.user.email
+# tmp - transition phase
+def topmenu_items (current, request):
+    print "WARNING -- please now use topmenu_items_live (label, page) toplevel_items is deprecated -- WARNING"
+    return topmenu_items_static (current, request)
+
+# integrated helper function for an animated menu
+from unfold.page import Page
+from manifold.core.query import Query
+from plugins.topmenuvalidation import TopmenuValidation
+
+### this is now the 'live' version, that has plugins 
+# for asynchronous management of topmenu
+def topmenu_items_live (current, page):
+    request=page.request
+    query_pi_auths = Query.get('ple:user').filter_by('user_hrn', '==', '$user_hrn' ).select('pi_authorities')
+    page.enqueue_query(query_pi_auths)
+#        # even though this plugin does not have any html materialization, the corresponding domid
+#        # must exist because it is searched at init-time to create the JS plugin
+#        # so we simply piggy-back the target button created in the topmenu
+    topmenuvalidation = TopmenuValidation (
+        page=page, 
+        # see above
+        domid='topmenu-validation',
+        query=query_pi_auths,
+        # this one is the target for a $.show() when the query comes back
+        button_domid="topmenu-validation")
+        # although the result does not matter, rendering is required for the JS init code to make it in the page
+    topmenuvalidation.render(request)
+
+    return topmenu_items_static (current, request)
+
index 0d3a81e..07ce237 100644 (file)
@@ -120,7 +120,7 @@ class Page:
     def expose_js_metadata (self):
         # expose global MANIFOLD_METADATA as a js variable
         # xxx this is fetched synchroneously..
-        self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";")
+        self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";\n")
 
     def expose_js_manifold_config (self):
         config=Config()
similarity index 89%
rename from unfold/static/js/spin.presets.js
rename to unfold/static/js/spin-presets.js
index 46115b1..33be023 100644 (file)
@@ -1,4 +1,4 @@
-var spin_presets={
+function spin_presets() { return {
   lines: 13, // The number of lines to draw
   length: 7, // The length of each line
   width: 4, // The line thickness
@@ -6,7 +6,7 @@ var spin_presets={
   corners: 1, // Corner roundness (0..1)
   rotate: 0, // The rotation offset
   color: '#f00', // #rgb or #rrggbb
-  speed: 0.3, // Rounds per second
+  speed: 0.7, // Rounds per second
   trail: 60, // Afterglow percentage
   shadow: false, // Whether to render a shadow
   hwaccel: true, // Whether to use hardware acceleration
@@ -14,4 +14,4 @@ var spin_presets={
   zIndex: 2e9, // The z-index (defaults to 2000000000)
   top: 'auto', // Top position relative to parent in px
   left: 'auto' // Left position relative to parent in px
-};
+}}