From: Yasin Date: Mon, 16 Dec 2013 13:15:11 +0000 (+0100) Subject: Merge branch 'master' of ssh://git.onelab.eu/git/myslice X-Git-Tag: myslice-0.3-0~59^2~3 X-Git-Url: http://git.onelab.eu/?p=myslice.git;a=commitdiff_plain;h=d9bbe0a36624c6fe558c05307964be1b3ed4e3b1;hp=ba0a2b7732c0ef93fd8f50d897227f344075a2fa Merge branch 'master' of ssh://git.onelab.eu/git/myslice --- diff --git a/.gitignore b/.gitignore index ed36fe74..bb1d472f 100644 --- a/.gitignore +++ b/.gitignore @@ -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.* diff --git a/manifold/manifoldapi.py b/manifold/manifoldapi.py index 25b80f9c..6639d484 100644 --- a/manifold/manifoldapi.py +++ b/manifold/manifoldapi.py @@ -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) diff --git a/manifold/manifoldproxy.py b/manifold/manifoldproxy.py index 3577fe5a..d43a3cd4 100644 --- a/manifold/manifoldproxy.py +++ b/manifold/manifoldproxy.py @@ -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: diff --git a/manifold/static/js/manifold.js b/manifold/static/js/manifold.js index 1bb5b975..3d526a67 100644 --- a/manifold/static/js/manifold.js +++ b/manifold/static/js/manifold.js @@ -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]); } }); }, diff --git a/manifold/static/js/plugin.js b/manifold/static/js/plugin.js index 41d8e8b0..4530b518 100644 --- a/manifold/static/js/plugin.js +++ b/manifold/static/js/plugin.js @@ -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 */ diff --git a/myslice/settings.py b/myslice/settings.py index ff355e40..5c2d29cc 100644 --- a/myslice/settings.py +++ b/myslice/settings.py @@ -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. diff --git a/myslice/urls.py b/myslice/urls.py index b204797b..64197267 100644 --- a/myslice/urls.py +++ b/myslice/urls.py @@ -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\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) diff --git a/plugins/form/__init__.py b/plugins/form/__init__.py index ff569d5f..d4dce756 100644 --- a/plugins/form/__init__.py +++ b/plugins/form/__init__.py @@ -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'] } diff --git a/plugins/googlemap/__init__.py b/plugins/googlemap/__init__.py index 583b8dd5..a769f7f8 100644 --- a/plugins/googlemap/__init__.py +++ b/plugins/googlemap/__init__.py @@ -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", diff --git a/plugins/googlemap/static/js/googlemap.js b/plugins/googlemap/static/js/googlemap.js index 764f1b49..91ece995 100644 --- a/plugins/googlemap/static/js/googlemap.js +++ b/plugins/googlemap/static/js/googlemap.js @@ -38,10 +38,11 @@ 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; @@ -76,7 +77,11 @@ 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 */ @@ -95,8 +100,7 @@ } 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 @@ -203,7 +207,7 @@ /*************************** 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); @@ -213,17 +217,17 @@ }, 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(); } @@ -231,7 +235,7 @@ }, 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: @@ -250,22 +254,22 @@ // 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 = []; @@ -294,8 +298,6 @@ }); // reset googlemap.in_set_backlog = []; - - if (debug) messages.debug("unspinning"); this.unspin(); } this.received_all = true; diff --git a/plugins/lists/simplelist.py b/plugins/lists/simplelist.py index 26510303..c817d9bf 100644 --- a/plugins/lists/simplelist.py +++ b/plugins/lists/simplelist.py @@ -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" ], diff --git a/plugins/lists/static/js/simplelist.js b/plugins/lists/static/js/simplelist.js index a8f90b94..2bed5b43 100644 --- a/plugins/lists/static/js/simplelist.js +++ b/plugins/lists/static/js/simplelist.js @@ -19,7 +19,7 @@ on_query_in_progress: function() { messages.debug("on_query_in_progress"); - this.spin(); + this.spin(true); }, on_query_done: function() { @@ -110,7 +110,8 @@ 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]) ]] }) ); diff --git a/plugins/maddash/__init__.py b/plugins/maddash/__init__.py index 0447ff4d..9de64bc0 100644 --- a/plugins/maddash/__init__.py +++ b/plugins/maddash/__init__.py @@ -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' : [ diff --git a/plugins/querycode/__init__.py b/plugins/querycode/__init__.py index d46a8421..0a2391fb 100644 --- a/plugins/querycode/__init__.py +++ b/plugins/querycode/__init__.py @@ -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 diff --git a/plugins/querygrid/__init__.py b/plugins/querygrid/__init__.py index 5b0c4662..22a2aabd 100644 --- a/plugins/querygrid/__init__.py +++ b/plugins/querygrid/__init__.py @@ -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 ? diff --git a/plugins/querytable/__init__.py b/plugins/querytable/__init__.py index b435b38e..0b1d29df 100644 --- a/plugins/querytable/__init__.py +++ b/plugins/querytable/__init__.py @@ -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", diff --git a/plugins/querytable/static/js/querytable.js b/plugins/querytable/static/js/querytable.js index 935c0878..bcb81927 100644 --- a/plugins/querytable/static/js/querytable.js +++ b/plugins/querytable/static/js/querytable.js @@ -31,12 +31,11 @@ // 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; @@ -69,25 +68,17 @@ /* 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 */ @@ -178,7 +169,6 @@ 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 @@ -271,7 +261,7 @@ 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); @@ -280,7 +270,7 @@ // 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); @@ -369,8 +359,6 @@ // 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); } }, @@ -453,7 +441,7 @@ // 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 = []; diff --git a/plugins/scheduler/__init__.py b/plugins/scheduler/__init__.py index c21e96b6..caaaa521 100644 --- a/plugins/scheduler/__init__.py +++ b/plugins/scheduler/__init__.py @@ -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", ], diff --git a/plugins/senslabmap/__init__.py b/plugins/senslabmap/__init__.py index 03b06a4d..8b8075cc 100644 --- a/plugins/senslabmap/__init__.py +++ b/plugins/senslabmap/__init__.py @@ -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", diff --git a/plugins/tabs/static/js/tabs.js b/plugins/tabs/static/js/tabs.js index 4612dd25..7c7f159c 100644 --- a/plugins/tabs/static/js/tabs.js +++ b/plugins/tabs/static/js/tabs.js @@ -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 index 00000000..2006e799 --- /dev/null +++ b/plugins/topmenuvalidation/__init__.py @@ -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 index 00000000..6cfc383c --- /dev/null +++ b/plugins/topmenuvalidation/static/js/topmenuvalidation.js @@ -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); diff --git a/portal/accountview.py b/portal/accountview.py index 66eb91e4..0d4059f0 100644 --- a/portal/accountview.py +++ b/portal/accountview.py @@ -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]} diff --git a/portal/dashboardview.py b/portal/dashboardview.py index 44a3ea91..41177823 100644 --- a/portal/dashboardview.py +++ b/portal/dashboardview.py @@ -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) diff --git a/portal/sliceview.py b/portal/sliceview.py index 2d77bdfe..318ee347 100644 --- a/portal/sliceview.py +++ b/portal/sliceview.py @@ -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) diff --git a/trash/dashboard.py b/sample/dashboardview.py similarity index 100% rename from trash/dashboard.py rename to sample/dashboardview.py diff --git a/trash/pluginview.py b/sample/pluginview.py similarity index 100% rename from trash/pluginview.py rename to sample/pluginview.py diff --git a/trash/simplegridview.py b/sample/querygridview.py similarity index 98% rename from trash/simplegridview.py rename to sample/querygridview.py index 014e1435..ef8d9937 100644 --- a/trash/simplegridview.py +++ b/sample/querygridview.py @@ -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'): diff --git a/trash/simpletableview.py b/sample/querytableview.py similarity index 98% rename from trash/simpletableview.py rename to sample/querytableview.py index e0fd770a..2e08abc8 100644 --- a/trash/simpletableview.py +++ b/sample/querytableview.py @@ -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 index 00000000..605cb3cd --- /dev/null +++ b/sample/scrollview.py @@ -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/trash/static/css/dashboard.css b/sample/static/css/dashboard.css similarity index 100% rename from trash/static/css/dashboard.css rename to sample/static/css/dashboard.css diff --git a/trash/static/css/sample.css b/sample/static/css/sample.css similarity index 100% rename from trash/static/css/sample.css rename to sample/static/css/sample.css diff --git a/sample/tabview.py b/sample/tabview.py new file mode 100644 index 00000000..167788ee --- /dev/null +++ b/sample/tabview.py @@ -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/trash/templates/view-scroll.html b/sample/templates/view-scroll.html similarity index 100% rename from trash/templates/view-scroll.html rename to sample/templates/view-scroll.html diff --git a/trash/templates/view-tab.html b/sample/templates/view-tab.html similarity index 100% rename from trash/templates/view-tab.html rename to sample/templates/view-tab.html diff --git a/trash/templates/view-unfold2.html b/sample/templates/view-unfold2.html similarity index 100% rename from trash/templates/view-unfold2.html rename to sample/templates/view-unfold2.html diff --git a/sample/topmenuvalidationview.py b/sample/topmenuvalidationview.py new file mode 100644 index 00000000..27b420e9 --- /dev/null +++ b/sample/topmenuvalidationview.py @@ -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'] = '

Some title

' + + # 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 diff --git a/trash/trashutils.py b/sample/trashutils.py similarity index 100% rename from trash/trashutils.py rename to sample/trashutils.py diff --git a/sample/urls.py b/sample/urls.py index d56b5dc9..9494fe80 100644 --- a/sample/urls.py +++ b/sample/urls.py @@ -5,6 +5,7 @@ # # Authors: # Jordan Augé +# 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 @@ -23,7 +24,19 @@ 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[\w\.]+)/?$', sample.querytableview.QueryTableView.as_view()), + url(r'^querygrid/(?P[\w\.]+)/?$', sample.querygridview.QueryGridView.as_view()), + url(r'^topmenuvalidation/(?P[\w\._]+)/?$', sample.topmenuvalidationview.TopmenuValidationView.as_view()), ) diff --git a/trash/__init__.py b/trash/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/trash/sampleviews.py b/trash/sampleviews.py deleted file mode 100644 index e1c66d8c..00000000 --- a/trash/sampleviews.py +++ /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 index 5e14d977..00000000 --- a/trash/urls.py +++ /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[\w\.]+)/?$', trash.simpletableview.SimpleTableView.as_view()), - url(r'^simplegrid/(?P[\w\.]+)/?$', trash.simplegridview.SimpleGridView.as_view()), -) diff --git a/ui/templates/base.html b/ui/templates/base.html index 908f0f40..49a57ad1 100644 --- a/ui/templates/base.html +++ b/ui/templates/base.html @@ -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" %} diff --git a/ui/templates/widget-topmenu.html b/ui/templates/widget-topmenu.html index dbcbe1fc..089bd3cf 100644 --- a/ui/templates/widget-topmenu.html +++ b/ui/templates/widget-topmenu.html @@ -22,13 +22,15 @@ {{ d.label }} {% else %} - {% if d.is_active %}
  • {% else %}
  • {% endif %} +
  • {{ d.label }}
  • {% endif %} {% endfor %} diff --git a/ui/topmenu.py b/ui/topmenu.py index 860e180b..6b152c8b 100644 --- a/ui/topmenu.py +++ b/ui/topmenu.py @@ -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) + diff --git a/unfold/page.py b/unfold/page.py index 0d3a81e6..07ce237a 100644 --- a/unfold/page.py +++ b/unfold/page.py @@ -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() diff --git a/unfold/static/js/plugin_helper.js b/unfold/static/js/plugin-helper.js similarity index 100% rename from unfold/static/js/plugin_helper.js rename to unfold/static/js/plugin-helper.js diff --git a/unfold/static/js/spin.presets.js b/unfold/static/js/spin-presets.js similarity index 89% rename from unfold/static/js/spin.presets.js rename to unfold/static/js/spin-presets.js index 46115b17..33be023b 100644 --- a/unfold/static/js/spin.presets.js +++ b/unfold/static/js/spin-presets.js @@ -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 -}; +}}