* edit myslice/config.py and enter the details of your manifold backend
+$ apt-get install python-django-south
* init django
$ ./manage.py syncdb
$ ./manage.py migrate
* run a local server:
-$ manage.py runserver 0.0.0.0:8000
+$ ./manage.py runserver 0.0.0.0:8000
-- or -- my advice:
$ devel/server-loop.sh
when you just need to hit ^C yourself when your static files need to be refreshed - see below
except:
print "metadata.work_offline: failed to decode %s"%offline_filename
manifold_api = ManifoldAPI(self.auth)
- fields = ['table', 'column.name', 'column.qualifier', 'column.type', 'column.is_array', 'column.description', 'column.default', 'key', 'capability']
+ fields = ['table', 'column.name', 'column.qualifier', 'column.type',
+ 'column.is_array', 'column.description', 'column.default', 'key', 'capability']
#fields = ['table', 'column.column',
# 'column.description','column.header', 'column.title',
# 'column.unit', 'column.info_type',
# 'column.resource_type', 'column.value_type',
# 'column.allowed_values', 'column.platforms.platform',
# 'column.platforms.platform_url']
- result = manifold_api.forward({
- 'action': 'get',
- 'object': 'local:object', # proposed to replace metadata:table
- 'fields': fields
- })
+ request={ 'action': 'get',
+ 'object': 'local:object', # proposed to replace metadata:table
+ 'fields': fields ,
+ }
+ result = manifold_api.forward(request)
+ # xxx need a way to export error messages to the UI
if result['code'] == 1: # warning
- messages.warning(request, result['description'])
+ # messages.warning(request, result['description'])
+ print ("METADATA WARNING -",request,result['description'])
elif result['code'] == 2:
- messages.error(request, result['description'])
+ # messages.error(request, result['description'])
+ print ("METADATA ERROR -",request,result['description'])
# XXX FAIL HERE XXX
+ return
rows = result.ok_value()
# API errors will be handled by the outer logic
* \brief We use js function closure to be able to pass the query (array)
* to the callback function used when data is received
*/
- success_closure: function(query, publish_uuid, callback /*domid*/) {
+ success_closure: function(query, publish_uuid, callback) {
return function(data, textStatus) {
- manifold.asynchroneous_success(data, query, publish_uuid, callback /*domid*/);
+ manifold.asynchroneous_success(data, query, publish_uuid, callback);
}
},
// manifold.raise_record_event(sq.query_uuid, IN_PROGRESS);
//});
- $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback /*domid*/));
+ $.post(manifold.proxy_url, {'json': query_json} , manifold.success_closure(query, null, callback));
},
- // Executes all async. queries
- // input queries are specified as a list of {'query_uuid': <query_uuid>, 'id': <possibly null>}
- asynchroneous_exec : function (query_publish_dom_tuples) {
- // start spinners
-
- // in case the spin stuff was not loaded, let's make sure we proceed to the exit
- //try {
- // if (manifold.asynchroneous_debug)
- // messages.debug("Turning on spin with " + jQuery(".need-spin").length + " matches for .need-spin");
- // jQuery('.need-spin').spin(manifold.spin_presets);
- //} catch (err) { messages.debug("Cannot turn on spins " + err); }
+ // Executes all async. queries - intended for the javascript header to initialize queries
+ // input queries are specified as a list of {'query_uuid': <query_uuid> }
+ // each plugin is responsible for managing its spinner through on_query_in_progress
+ asynchroneous_exec : function (query_exec_tuples) {
// Loop through input array, and use publish_uuid to publish back results
- jQuery.each(query_publish_dom_tuples, function(index, tuple) {
+ $.each(query_exec_tuples, function(index, tuple) {
var query=manifold.find_query(tuple.query_uuid);
var query_json=JSON.stringify (query);
var publish_uuid=tuple.publish_uuid;
// not quite sure what happens if we send a string directly, as POST data is named..
// this gets reconstructed on the proxy side with ManifoldQuery.fill_from_POST
- jQuery.post(manifold.proxy_url, {'json':query_json},
- manifold.success_closure(query, publish_uuid, tuple.callback /*domid*/));
+ $.post(manifold.proxy_url, {'json':query_json},
+ manifold.success_closure(query, publish_uuid, tuple.callback));
})
},
* \brief Forward a query to the manifold backend
* \param query (dict) the query to be executed asynchronously
* \param callback (function) the function to be called when the query terminates
- * Deprecated:
- * \param domid (string) the domid to be notified about the results (null for using the pub/sub system
*/
- forward: function(query, callback /*domid*/) {
+ forward: function(query, callback) {
var query_json = JSON.stringify(query);
$.post(manifold.proxy_url, {'json': query_json} ,
- manifold.success_closure(query, query.query_uuid, callback/*domid*/));
+ manifold.success_closure(query, query.query_uuid, callback));
},
/*!
/* Publish an update announce */
var channel="/results/" + query.query_uuid + "/changed";
if (manifold.publish_result_debug) messages.debug(".. publish_result OLD API (3) " + channel);
- jQuery.publish(channel, [result, query]);
+ $.publish(channel, [result, query]);
if (manifold.publish_result_debug) messages.debug(".. publish_result - END (4) q=" + query.__repr());
},
if (manifold.publish_result_debug) messages.debug (">>>>> publish_result_rec " + query.object);
if (manifold.query_expects_unique_result(query)) {
/* Also publish subqueries */
- jQuery.each(query.subqueries, function(object, subquery) {
+ $.each(query.subqueries, function(object, subquery) {
manifold.publish_result_rec(subquery, result[0][object]);
/* TODO remove object from result */
});
}
},
- // if set domid allows the result to be directed to just one plugin
+ // if set callback is provided it is called
// most of the time publish_uuid will be query.query_uuid
// however in some cases we wish to publish the result under a different uuid
// e.g. an updater wants to publish its result as if from the original (get) query
- asynchroneous_success : function (data, query, publish_uuid, callback /*domid*/) {
+ asynchroneous_success : function (data, query, publish_uuid, callback) {
// xxx should have a nicer declaration of that enum in sync with the python code somehow
var start = new Date();
if (manifold.asynchroneous_debug)
messages.debug(">>>>>>>>>> asynchroneous_success query.object=" + query.object);
- /* If a callback has been specified, we redirect results to it */
- if (!!callback) {
- callback(data);
- if (manifold.asynchroneous_debug) {
- duration=new Date()-start;
- messages.debug ("<<<<<<<<<< asynchroneous_success " + query.object + " -- callback ended " + duration + " ms");
- }
- return;
- }
-
if (data.code == 2) { // ERROR
// We need to make sense of error codes here
alert("Your session has expired, please log in again");
if (publish_uuid)
$.publish("/results/" + publish_uuid + "/failed", [data.code, data.description] );
-/* DEMO - Debug Messages desactivated
- $("#notifications").notify("create", "sticky", {
- title: 'Warning',
- text: data.description
- },{
- expires: false,
- speed: 1000
- });
-*/
}
+
+ // If a callback has been specified, we redirect results to it
+ if (!!callback) {
+ callback(data);
+ if (manifold.asynchroneous_debug) {
+ duration=new Date()-start;
+ messages.debug ("<<<<<<<<<< asynchroneous_success " + query.object + " -- callback ended " + duration + " ms");
+ }
+ return;
+ }
+
if (manifold.asynchroneous_debug)
messages.debug ("========== asynchroneous_success " + query.object + " -- before process_query_records");
raise_event_handler: function(type, query_uuid, event_type, value) {
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
+ if (query_uuid === undefined) {
+ messages.warning("undefined query in raise_event_handler");
+ return;
+ }
+ // notify the change to objects that either listen to this channel specifically,
+ // or to the wildcard channel
var channels = [ manifold.get_channel(type, query_uuid), manifold.get_channel(type, '*') ];
$.each(channels, function(i, channel) {
// retrieve DOM checkbox and make sure it is checked/unchecked
set_checkbox: function(record, checked) {
var hrn=this.record_hrn (record);
- if (! hrn) { messages.warning ("googlemap.set_checkbox: record has no hrn"); return; }
+ if (! hrn) {
+ try {messages.warning ("googlemap.set_checkbox: record has no hrn -- hostname="+record.hostname); }
+ catch (err) {messages.warning ("googlemap.set_checkbox: record has no hrn"); }
+ return;
+ }
var checkbox_s = this.by_hrn [ hrn ];
if (! checkbox_s ) { messages.warning ("googlemap.set_checkbox: could not spot checkbox for hrn "+hrn); return; }
checkbox_s.checkbox.prop('checked',checked);
var debug=false;
debug=true
- $.fn.SimpleList = function( method ) {
- /* Method calling logic */
- if ( methods[method] ) {
- return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
- } else if ( typeof method === 'object' || ! method ) {
- return methods.init.apply( this, arguments );
- } else {
- $.error( 'Method ' + method + ' does not exist on jQuery.SimpleList' );
- }
- };
+ var SimpleList = Plugin.extend ({
- var methods = {
- init : function( options ) {
- return this.each(function(){
- var $this = $(this), data = $this.data('SimpleList');
- /* Subscribe to query updates */
- var channel='/results/' + options.query_uuid + '/changed';
- /* passing $this as 2nd arg: callbacks will retrieve $this as e.data */
- $.subscribe(channel, $this, update_plugin);
- if (debug) window.messages.debug('subscribing to ' + channel);
- $this.data('SimpleList', options);
- });
- },
- destroy : function( ) {
- if (debug) messages.debug("SimpleList.destroy...");
- return this.each(function(){
- var $this = $(this), data = $this.data('SimpleList');
- // xxx not too sure what this is about
- $(window).unbind('SimpleList');
- $this.removeData('SimpleList');
- });
- },
- update : function( content ) {
- if (debug) messages.debug("SimpleList.update...");
- },
- }; // methods
+ init: function (options, element) {
+ this._super (options, element);
+ this.buffered_records=[];
+ this.listen_query(options.query_uuid);
+ },
- /* Private methods */
- // complexity here is mostly because a datatables-enabled table cannot
- // be updated in a "normal" way using .html()
- function update_plugin(e, rows) {
- // e.data is what we passed in second argument to subscribe
- // so here it is the jquery object attached to the plugin <div>
- var $plugindiv = e.data;
- var options = $plugindiv.data().SimpleList;
- var classname=options.classname;
- // locate the <table> element; with datatables in the way,
- // this might not be a direct son of the div-plugin
- var $table = $plugindiv.find("table."+classname).first();
- // also we may or may not have a header
- var $tbody = $table.find("tbody."+classname).first();
- var use_datatables = $table.hasClass("with-datatables");
- if (debug)
- messages.debug($plugindiv.attr('id') + " udt= " + use_datatables + " rows="+rows.length);
-
- // clear the spinning wheel: look up an ancestor that has the need-spin class
- // do this before we might return
- $plugindiv.closest('.need-spin').spin(false);
+ on_query_in_progress: function() {
+ messages.debug("on_query_in_progress");
+ this.spin();
+ },
- if (rows.length == 0) {
- if (use_datatables)
- datatables_set_message ($table, $tbody, unfold.warning("No result"));
- else
- regular_set_message ($table, $tbody, unfold.warning("No result"));
- return;
- }
+ on_query_done: function() {
+ this._display_table();
+ this.unspin();
+ },
+
+ on_new_record: function(record) {
+ this.buffered_records.push(record);
+ },
- if (typeof rows[0].error != 'undefined') {
- var error="ERROR: " + rows[0].error;
- if (use_datatables)
- datatables_set_message ($table, $tbody, unfold.error(error));
- else
- regular_set_message ($table, $tbody, unfold.error(error));
- return;
- }
+ /* Private methods */
- if (use_datatables)
- datatables_update_table($table, $tbody, rows, options.key);
- else
- regular_update_table($table, $tbody, rows, options.key, classname);
+ _display_table: function() {
+ var self=this;
+ var $plugindiv = this.elmt();
+ var options = this.options;
+ var classname=options.classname;
+ // locate the <table> element; with datatables in the way,
+ // this might not be a direct son of the div-plugin
+ var $table = $plugindiv.find("table."+classname).first();
+ // also we may or may not have a header
+ var $tbody = $table.find("tbody."+classname).first();
+ var use_datatables = $table.hasClass("with-datatables");
+ var rows=self.buffered_records;
+ self.buffered_records=[];
+ if (debug)
+ messages.debug($plugindiv.attr('id') + " udt= " + use_datatables + " rows="+rows.length);
+
+ if (rows.length == 0) {
+ if (use_datatables)
+ this._datatables_set_message ($table, $tbody, unfold.warning("No result"));
+ else
+ this._regular_set_message ($table, $tbody, unfold.warning("No result"));
+ return;
+ }
- }
+ if (typeof rows[0].error != 'undefined') {
+ var error="ERROR: " + rows[0].error;
+ if (use_datatables)
+ this._datatables_set_message ($table, $tbody, unfold.error(error));
+ else
+ this._regular_set_message ($table, $tbody, unfold.error(error));
+ return;
+ }
- // hard-wire a separate presentation depending on the key being used....
- function cell(key, value) {
- if (key == 'slice.slice_hrn') {
- return "<i class='icon-play-circle'></i><a href='/portal/slice/" + value + "'>" + value + "</a>";
- } else if (key == 'platform') {
- return "<i class='icon-play-circle'></i><a href='/portal/platform/" + value + "'>" + value + "</a>";
- } else {
- return value;
- }
- }
+ if (use_datatables)
+ this._datatables_update_table($table, $tbody, rows, options.key);
+ else
+ this._regular_update_table($table, $tbody, rows, options.key, classname);
+ },
- function regular_set_message ($table, $tbody, message) {
- $tbody.html("<tr><td>"+message+"</td></tr>");
- }
+ _regular_set_message: function ($table, $tbody, message) {
+ $tbody.html("<tr><td>"+message+"</td></tr>");
+ },
- function regular_update_table ($table, $tbody, rows, key, classname) {
- if (debug)
- messages.debug('regular_update_table ' + rows.length + " rows" + " key=" + key + " classname=" + classname);
- var html=$.map(rows, function (row) {
- value = row;
- $.each(key.split('.'), function(i, k) {
- if ($.isArray(value)) {
- value = $.map(value, function(val, i) { return val[k]});
- } else {
- value = value[k];
- }
- });
+ _regular_update_table: function ($table, $tbody, rows, key, classname) {
+ if (debug)
+ messages.debug('regular_update_table ' + rows.length + " rows" + " key=" + key + " classname=" + classname);
+ var self=this;
+ var html=$.map(rows, function (row) {
+ var value = row;
+ $.each(key.split('.'), function(i, k) {
+ if ($.isArray(value)) {
+ value = $.map(value, function(val, i) { return val[k]});
+ } else {
+ value = value[k];
+ }
+ });
if ($.isArray(value)) {
- x = $.map(value, function(val, i) {
- messages.debug("loop.loop val="+val+" i="+i);
- return html_row ( cell (key, val), classname); });
- return x;
- } else {
- return html_row ( cell (key, value), classname);
- }
- }).join();
- $tbody.html(html);
- }
+ return $.map(value, function(val, i) {
+ return self._html_row ( self._cell (key, val), classname);
+ });
+ } else {
+ return self._html_row ( self._cell (key, value), classname);
+ }
+ }).join();
+ $tbody.html(html);
+ },
- function datatables_set_message ($table, $tbody, message) {
- $table.dataTable().fnClearTable();
- $table.dataTable().fnAddData( [ message ] );
- $table.dataTable().fnDraw();
- }
+ _datatables_set_message: function ($table, $tbody, message) {
+ $table.dataTable().fnClearTable();
+ $table.dataTable().fnAddData( [ message ] );
+ $table.dataTable().fnDraw();
+ },
- function datatables_update_table ($table, $tbody, rows, key) {
- 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.
- // this is wrong indeed so let's work around that
- $table.dataTable().fnAddData( $.map(rows, function (row) { return [[ cell (key,row[key]) ]] }) );
- $table.dataTable().fnDraw();
- }
+ _datatables_update_table: function ($table, $tbody, rows, key) {
+ 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.
+ // 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]) ]] }) );
+ $table.dataTable().fnDraw();
+ },
- function html_row (cell, classname) {
- return "<tr><td class='"+classname+"'>"+cell+"</td></tr>";
- }
+ _html_row: function (cell, classname) {
+ return "<tr><td class='"+classname+"'>"+cell+"</td></tr>";
+ },
+ // hard-wire a separate presentation depending on the key being used....
+ _cell: function (key, value) {
+ if (key == 'slice.slice_hrn') {
+ return "<i class='icon-play-circle'></i><a href='/portal/slice/" + value + "'>" + value + "</a>";
+ } else if (key == 'platform') {
+ return "<i class='icon-play-circle'></i><a href='/portal/platform/" + value + "'>" + value + "</a>";
+ } else {
+ return value;
+ }
+ },
+ });
+
+ $.plugin('SimpleList', SimpleList);
+
})( jQuery );
def json_settings_list (self):
return [ 'plugin_uuid', 'levels' ]
- # and we don't need a spin wheel
- def start_with_spin (self):
- return False
}
def json_settings_list (self): return ['plugin_uuid','query_uuid']
-
- # because we have a link to a query it looks like we need a spin, let's make this right
- def start_with_spin (self): return False
on_new_record: function(record)
{
if (this.received_all_query) {
- // if the 'all' query has been dealt with already we may turn on the checkbox
- if (debug) messages.debug("turning on checkbox for record "+record[this.key]);
+ // if the 'all' query has been dealt with already we may turn on the checkbox
+ if (debug) messages.debug("turning on checkbox for record "+record[this.key]);
this.set_checkbox(record, true);
- } else {
- // otherwise we need to remember that and do it later on
- if (debug) messages.debug("Remembering record to check " + record[this.key]);
+ } else {
+ // otherwise we need to remember that and do it later on
+ if (debug) messages.debug("Remembering record to check " + record[this.key]);
this.buffered_records_to_check.push(record);
- }
+ }
},
on_clear_records: function()
def json_settings_list (self):
return ['plugin_uuid', 'domid', 'query_uuid']
- def export_json_settings (self):
- return True
def json_settings_list (self):
return []
- def export_json_settings(self):
- return True
# private_key = k.as_pem()
# private_key = ''.join(private_key.split())
# public_key = "ssh-rsa " + public_key
- keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + '}'
+ # now we overwrite the config field with keypair
+ # once there will be user_hrn, we need to keep user_hrn and change only the keypair
+ # see submit_name section for implementing this
# keypair = re.sub("\r", "", keypair)
# keypair = re.sub("\n", "\\n", keypair)
# #keypair = keypair.rstrip('\r\n')
# keypair = ''.join(keypair.split())
# updating maniolf local:account table
+ account_config = json.loads(account_detail['config'])
+ # preserving user_hrn
+ user_hrn = account_config.get('user_hrn','N/A')
+ keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
+ updated_config = json.dumps(account_config)
+
user_params = { 'config': keypair, 'auth_type':'managed'}
manifold_update_account(request,user_params)
messages.success(request, 'Sucess: New Keypair Generated!')
file_extension = os.path.splitext(file_name)[1]
allowed_extension = ['.pub','.txt']
if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
- file_content = '{"user_public_key":"'+ file_content +'"}'
+ account_config = json.loads(account_detail['config'])
+ # preserving user_hrn
+ user_hrn = account_config.get('user_hrn','N/A')
+ file_content = '{"user_public_key":"'+ file_content + '", "user_hrn":"'+ user_hrn +'"}'
#file_content = re.sub("\r", "", file_content)
#file_content = re.sub("\n", "\\n",file_content)
file_content = ''.join(file_content.split())
reg_auth = request.POST.get('authority_hrn', '')
reg_login = request.POST.get('login', '')
reg_email = request.POST.get('email','').lower()
-
+ #prepare user_hrn
+ split_email = reg_email.split("@")[0]
+ split_email = split_email.replace(".", "_")
+ user_hrn = reg_auth + '.' + split_email
+
#POST value validation
if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
# private_key = ''.join(private_key.split())
# public_key = "ssh-rsa " + public_key
# Saving to DB
- keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + '}'
+ keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
#keypair = re.sub("\r", "", keypair)
#keypair = re.sub("\n", "\\n", keypair)
#keypair = keypair.rstrip('\r\n')
file_extension = os.path.splitext(file_name)[1]
allowed_extension = ['.pub','.txt']
if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
- keypair = '{"user_public_key":"'+ file_content +'"}'
+ keypair = '{"user_public_key":"'+ file_content + '", "user_hrn":"'+ user_hrn +'"}'
keypair = re.sub("\r", "", keypair)
keypair = re.sub("\n", "\\n",keypair)
keypair = ''.join(keypair.split())
'first_name' : reg_fname,
'last_name' : reg_lname,
'authority_hrn' : reg_auth,
- 'email' : reg_email,
+ 'email' : reg_email,
+ 'user_hrn' : user_hrn,
'keypair' : 'Public Key :' + public_key,
'cc_myself' : True # form.cleaned_data['cc_myself']
}
-
recipients = authority_get_pi_emails(request,reg_auth)
if ctx['cc_myself']:
-
+/* if window enlarged wider than background picture */
+body {
+ background: black !important;
+}
/* TOPMENU.CSS */
-/*
- * This file is included in tophat_render.php
- */
// Escape special characters in jQuery Selector
function escape_id( myid ) {
return "#" + myid.replace( /(:|\.|\[|\])/g, "\\$1" );
<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/onelab.css" />
<div class="onelab-title well-lg">
<h2>Onelab Support</h2>
- <h4>If you have already registered, then please <a href="mailto:support@myslice.info">send an e-mail</a>
+ <h4>If you have already registered, then please send an <a href="mailto:support@myslice.info">e-mail</a>
or <a href="http://trac.myslice.info/" >visit us</a></h4>
</div>
/* this is to get the content below the navbar */
body {
padding-top: 60px;
- padding-bottom: 20px;
}
/* center the buttons vertically in the header */
div.topmenu { padding-top: 7px; }
ul.logged-in {
- padding-top: 12px;
+ padding-top: 14px;
}
button.logged-in {
font-size: small;
# queue of queries with maybe a domid, see enqueue_query
self._queue=[]
# global prelude object
- self.prelude=Prelude(css_files='css/plugin.css')
- print "Loading... CSS OneLab"
- self.prelude=Prelude(css_files='css/onelab_marko.css')
-# self.prelude=Prelude(css_files=['css/plugin.css','css/onelab_marko.css',])
+ self.prelude=Prelude(css_files=['css/plugin.css','css/onelab_marko.css',])
# record known plugins hashed on their domid
def record_plugin (self, plugin):
result={'query_uuid':a}
if b: result['domid']=b
return result
- env['query_publish_dom_tuples'] = [ query_publish_dom_tuple (a,b) for (a,b) in self._queue ]
+ env['query_exec_tuples'] = [ query_publish_dom_tuple (a,b) for (a,b) in self._queue ]
javascript = render_to_string ("page-queries.js",env)
self.add_js_chunks (javascript)
# self.reset_queue()
self.expose_js_manifold_config()
-# DEPRECATED # # needs to be called explicitly and only when metadata is actually required
-# DEPRECATED # # in particular user needs to be logged
-# DEPRECATED # def get_metadata (self):
-# DEPRECATED # # look in session's cache - we don't want to retrieve this for every request
-# DEPRECATED # session=self.request.session
-# DEPRECATED # if 'manifold' not in session:
-# DEPRECATED # print "Page.expose_js_metadata: no 'manifold' in session... - cannot retrieve metadata - skipping"
-# DEPRECATED # return
-# DEPRECATED # manifold=session['manifold']
-# DEPRECATED # # if cached, use it
-# DEPRECATED # if 'metadata' in manifold and isinstance(manifold['metadata'],MetaData):
-# DEPRECATED # if debug: print "Page.get_metadata: return cached value"
-# DEPRECATED # return manifold['metadata']
-# DEPRECATED # # otherwise retrieve it
-# DEPRECATED # manifold_api_session_auth = session['manifold']['auth']
-# DEPRECATED # print "get_metadata(), manifold_api_session_auth =", session['manifold']['auth']
-# DEPRECATED # metadata=MetaData (manifold_api_session_auth)
-# DEPRECATED # metadata.fetch()
-# DEPRECATED # # store it for next time
-# DEPRECATED # manifold['metadata']=metadata
-# DEPRECATED # if debug: print "Page.get_metadata: return new value"
-# DEPRECATED # return metadata
-
# needs to be called explicitly and only when metadata is actually required
# in particular user needs to be logged
def get_metadata (self):
return metadata
def expose_js_metadata (self):
- # export in this js global...
- self.add_js_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";")
+ # 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() + ";")
def expose_js_manifold_config (self):
config=Config()
- self.add_js_chunks(config.manifold_js_export())
+ self.add_js_init_chunks(config.manifold_js_export())
#################### requirements/prelude management
# just forward to self.prelude - see decorator above
@to_prelude
def add_css_files (self):pass
@to_prelude
+ def add_js_init_chunks (self):pass
+ @to_prelude
def add_js_chunks (self):pass
@to_prelude
def add_css_chunks (self):pass
def export_json_settings (self):
return 'query_uuid' in self.json_settings_list()
- # by default we create a timer if there's a query attached, redefine to change this behaviour
- def start_with_spin (self):
- return self.export_json_settings()
-
# returns the html code for that plugin
# in essence, wraps the results of self.render_content ()
def render (self, request):
# shove this into plugin.html
env = {}
env ['plugin_content']= plugin_content
- # need_spin is used in plugin.html
- self.need_spin=self.start_with_spin()
env.update(self.__dict__)
# translate high-level 'toggled' into 4 different booleans
self.need_toggle = False
env ['settings_json' ] = self.settings_json()
# compute plugin-specific initialization
js_init = render_to_string ( 'plugin-init.js', env )
- self.add_js_chunks (js_init)
+ # make sure this happens first in js
+ self.add_js_init_chunks (js_init)
# interpret the result of requirements ()
self.handle_requirements (request)
@to_prelude
def add_css_files (self):pass
@to_prelude
+ def add_js_init_chunks (self):pass
+ @to_prelude
def add_js_chunks (self):pass
@to_prelude
def add_css_chunks (self):pass
#
# whether we export the json settings to js
# def export_json_settings (self)
- #
- # whether we show an initial spinner
- # def start_with_spin (self)
from django.template.loader import render_to_string
-debug=True
+debug=False
+# the need for js_init_chunks is because we need to have the plugins initialized
+# before the queries fly
+# and when writing a view it is not very easy to remember in which order
+# all the js initialization will end up, so we use these 2 categories
+# as a simple way to enforce this dependency
+# far from perfect but good enough for now
class Prelude:
- """A class for collecting dependencies on js/css files or fragments"""
+ """A class for collecting dependencies on js/css stuff
+ files are expected from your 'static' area, typically 'css/foo.css' or 'js/foo.js'
+ fragments (chunks) is for raw code
+ you can specify a string or a list of strings
+ js_init_chunks get collated with js_chunks but come first
+ """
- keys=[ 'js_files','css_files','js_chunks', 'css_chunks' ]
- def __init__ (self, js_files=None, css_files=None, js_chunks=None, css_chunks=None):
+ keys=[ 'js_files', 'css_files', 'js_init_chunks', 'js_chunks', 'css_chunks' ]
+ def __init__ (self, js_files=None, css_files=None, js_init_chunks=None, js_chunks=None, css_chunks=None):
# it's tempting to use sets but sets are not ordered..
self.js_files = Prelude._normalize(js_files)
self.css_files = Prelude._normalize(css_files)
+ self.js_init_chunks = Prelude._normalize(js_init_chunks)
self.js_chunks = Prelude._normalize(js_chunks)
self.css_chunks= Prelude._normalize(css_chunks)
def add_css_files (self, x):
for i in Prelude._normalize (x):
if i not in self.css_files: self.css_files.append(i)
+ def add_js_init_chunks (self, x):
+ self.js_init_chunks += Prelude._normalize (x)
def add_js_chunks (self, x):
self.js_chunks += Prelude._normalize (x)
def add_css_chunks (self, x):
def inspect_string (self,msg):
result = 'Prelude.inspect %s (%s) with '%(msg,self)
- result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in ['js_files','js_chunks','css_files','css_chunks'] ] )
+ result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in Prelude.keys ] )
return result
def inspect (self,msg):
print self.inspect_string(msg)
env={}
env['js_urls'] = [ Prelude.full_url (js_file) for js_file in self.js_files ]
env['css_urls'] = [ Prelude.full_url (css_file) for css_file in self.css_files ]
- env['js_chunks']= self.js_chunks
+ env['all_js_chunks']= self.js_init_chunks + self.js_chunks
env['css_chunks']=self.css_chunks
if debug:
- print "prelude has %d js_files, %d css files, %d js chunks and %d css_chunks"%\
- (len(self.js_files),len(self.css_files),len(self.js_chunks),len(self.css_chunks),)
+ print "prelude has %d js_files, %d css files, (%d+%d) js chunks and %d css_chunks"%\
+ (len(self.js_files),len(self.css_files),len(self.js_init_chunks),len(self.js_chunks),len(self.css_chunks),)
# render this with prelude.html and put the result in header_prelude
header_prelude = render_to_string ('prelude.html',env)
return { 'header_prelude' : header_prelude }
{% for json in queries_json %}manifold.insert_query({{ json|safe }});
{% endfor %}
$(document).ready(function () {
-var query_publish_dom_tuples = new Array();
-{% for d in query_publish_dom_tuples %}try {query_publish_dom_tuples.push({'query_uuid':"{{ d.query_uuid }}"{%if d.domid %},'domid':"{{ d.domid }}"{% endif %}}) }
-catch(err){messages.debug ("Could not expose query {{ d.query_uuid }}")}
+var query_exec_tuples = [];
+{% for tuple in query_exec_tuples %} query_exec_tuples.push({'query_uuid':"{{ tuple.query_uuid }}"});
{% endfor %}
-manifold.asynchroneous_exec(query_publish_dom_tuples);
+manifold.asynchroneous_exec(query_exec_tuples);
})
{% if visible %}
-<div id='complete-{{ domid }}' class='{% if need_toggle %}plugin-toggle{% endif %}{% if need_spin %} need-spin{% endif %}{% if persistent_toggle %} persistent-toggle{% endif %}{% if outline_complete %} plugin-outline-complete{% endif %}'>
+<div id='complete-{{ domid }}' class='{% if need_toggle %}plugin-toggle{% endif %}{% if persistent_toggle %} persistent-toggle{% endif %}{% if outline_complete %} plugin-outline-complete{% endif %}'>
{% if togglable %}
<h4 id='show-{{ domid }}' class='plugin-show'{% if not display_show_button %} style='display:none;'{% endif %}>
<span class="glyphicon glyphicon-chevron-right"></span>
{% endfor %}
{% for css_url in css_urls %} <link rel='stylesheet' type='text/css' href='{{ css_url|safe }}' />
{% endfor %}
-<script type="text/javascript"> {% for js_chunk in js_chunks %} {{ js_chunk|safe }} {% endfor %} </script>
+<script type="text/javascript"> {% for js_chunk in all_js_chunks %} {{ js_chunk|safe }} {% endfor %} </script>
<style type="text/css"> {% for css_chunk in css_chunks %} {{ css_chunk|safe }} {% endfor %} </style>