# shove this into plugin.html
env = {}
env ['plugin_content']= plugin_content
+ self.need_spin=self.is_asynchroneous()
env.update(self.__dict__)
result = render_to_string ('plugin.html',env)
}(jQuery));
-function executeFunctionByName(functionName, context /*, args */) {
- var args = Array.prototype.slice.call(arguments).splice(2);
- var namespaces = functionName.split(".");
- var func = namespaces.pop();
- for(var i = 0; i < namespaces.length; i++) {
- context = context[namespaces[i]];
- }
- return context[func].apply(this, args);
-}
+//function executeFunctionByName(functionName, context /*, args */) {
+// var args = Array.prototype.slice.call(arguments).splice(2);
+// var namespaces = functionName.split(".");
+// var func = namespaces.pop();
+// for(var i = 0; i < namespaces.length; i++) {
+// context = context[namespaces[i]];
+// }
+// return context[func].apply(this, args);
+//}
{#<!--begin {{ classname }}{{ domid }}-->#}
{% if visible %}
-<div class='plugin-toggle need-spin' id='toggle-{{ domid }}'>
+<div class='plugin-toggle{% if need_spin %} need-spin{% endif %}' id='toggle-{{ domid }}'>
{% if togglable %}
{% if not toggled %}
<p id='show-{{ domid }}' class='plugin-show'><i class="icon-hand-right"></i> Show {{ title }} ({{ classname }})</p>
--- /dev/null
+from engine.plugin import Plugin
+
+class QueryCode (Plugin):
+
+ def __init__ (self, query, **settings):
+ Plugin.__init__ (self, **settings)
+ self.query=query
+
+ def template_file (self):
+ return "querycode.html"
+
+ def requirements (self):
+ return {
+ 'js_files' : [ "js/querycode.js", "js/plugin.js", "js/query.js", "js/onavail.js",
+ "js/manifold-pubsub.js", "js/manifold-async.js", "spin/spin.all.js",
+# Plugins::add_js('/QueryCode/beautyofcode/scripts/shCore.js');
+# Plugins::add_js('/QueryCode/beautyofcode/scripts/shBrushPython.js');
+# Plugins::add_js('/QueryCode/beautyofcode/scripts/shBrushRuby.js');
+# Plugins::add_js('/QueryCode/beautyofcode/scripts/shAutoloader.js');
+ ] ,
+ 'css_files': [ "css/querycode.css" ,
+# Plugins::add_css('/QueryCode/beautyofcode/styles/shCore.css');
+# Plugins::add_css('/QueryCode/beautyofcode/styles/shCoreDefault.css');
+# Plugins::add_css('/QueryCode/beautyofcode/styles/shThemeDefault.css');
+ ],
+ }
+
+ def json_settings_list (self): return ['plugin_uuid', 'query','query_uuid']
+
--- /dev/null
+body { font-family:Arial, Helvetica, Sans-Serif; font-size:0.8em;}
+
+#report {
+border-collapse:collapse;
+width: 100%;
+}
+#report h4 { margin:0px; padding:0px;}
+#report img { float:right;}
+#report ul { margin:10px 0 10px 40px; padding:0px;}
+#report th { background:#C7DDEE; color:#000; padding:7px 15px; text-align:left;}
+#report td { background:#fff; color:#000; padding:7px 15px; }
+#report tr.odd td { background:#D7DDE3; cursor:pointer; }
+#report div.arrow { background:transparent url(images/arrows.png) no-repeat scroll 0px -16px; width:16px; height:16px; display:block;}
+#report div.up { background-position:0px 0px;}
+
+div.info{
+ position:relative; /*this is the key*/
+ float: right;
+ z-index:24;
+ background: url(images/tooltip.png) no-repeat;
+ //background-color:#ccc;
+ width: 16px;
+ height: 16px;
+ color:#000;
+ text-decoration:none}
+
+div.info:hover{
+ z-index:25;
+ //background-color:#ff0
+}
+
+div.info span{display: none}
+
+div.info:hover span{ /*the span will display just on :hover state*/
+ display:block;
+ position:absolute;
+ //top:1em;
+ left:-22em;
+ width: 20em;
+ font-size: 8pt;
+ border:1px solid #ccdddd;
+ background-color:#ddeeee;
+ color:#000;
+ text-align: left;
+ padding: 0em 0em 0em 1em;
+}
+
+div.method {
+ padding: 10px;
+ background-color: #fafafa;
+ border-top: solid 1px black;
+ border-left: solid 1px black;
+ border-right: solid 1px black;
+}
+div.ts {
+ padding: 10px;
+ background-color: #f5f5f5;
+ border-left: solid 1px black;
+ border-right: solid 1px black;
+}
+div.input {
+ padding: 10px;
+ background-color: #fafafa;
+ border-left: solid 1px black;
+ border-right: solid 1px black;
+}
+div.output {
+ padding: 10px;
+ background-color: #f5f5f5;
+ border-left: solid 1px black;
+ border-right: solid 1px black;
+ border-bottom: solid 1px black;
+}
+
+#viz {
+ padding: 10px;
+ background-color: #fafafa;
+ border: solid 1px black;
+ margin-bottom: 10px;
+}
+
+#colcfg {
+ padding: 10px;
+ background-color: #fafafa;
+ border: solid 1px black;
+ margin-bottom: 10px;
+}
+
+#results {
+ border-top: solid 1px black;
+ margin-top: 20px;
+ padding-top: 20px;
+}
+
+td.center {
+ background: #ffffff;
+}
+
+#boxes {
+ font-family: Arial, sans-serif;
+ list-style-type: none;
+ margin: 0px;
+ padding: 0px;
+ width: 100%;
+}
+#boxes li {
+ list-style-type: none;
+ cursor: move;
+ position: relative;
+ float: left;
+ margin: 2px 2px 0px 0px;
+ //width: 33px;
+ height: 33px;
+ border: 1px solid #e0e0e0;
+ text-align: center;
+ padding: 5px;
+ background-color: #fafafa;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+table tr.even.row_selected td {
+ background-color: #B0BED9;
+}
+
+table tr.odd.row_selected td {
+ background-color: #9FAFD1;
+}
+
+#coltab tr {
+ margin: 0px;
+}
+
+#coltab td {
+ margin: 0px;
+ border-bottom: none; //1px solid #E9E9E9;
+ padding: 0px;
+}
+
+div.out{background-color:white; color:black}
+div.in{background-color:#CAE8EA; color:#4f6b72}
+div.selected{background-color:gray; color:black}
+div.invisible{display:none}
+
+div.clean{
+ border: 1px solid #850000;
+}
+
+.clean td, .clean th{
+ border: 2px solid #bbb;
+ background: #ddd;
+ padding: 5px 10px;
+ text-align: center;
+ border-radius: 2px;
+}
+
+.clean table{
+ margin: auto;
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+
+.clean caption{
+ font-weight: bold;
+
+}
+
+.gvChart,.clean{
+ border: 2px solid #850000;
+ border-radius: 5px;
+ -moz-border-radius: 10px;
+ width: 720px;
+
+ margin: auto;
+ margin-top: 20px;
+}
+
+pre{
+ background: #eee;
+ padding: 10px;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ white-space: pre-wrap;
+}
+
--- /dev/null
+/**
+ * MySlice QueryCode plugin
+ * URL: http://trac.myslice.info
+ * Description: display code for a target query in python or ruby
+ * Author: The MySlice Team
+ * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
+ * License: GPLv3
+ */
+
+querycode_debug=false;
+querycode_debug=true;
+
+function debug_object (msg, o) {
+ var keys=[];
+ for (var k in o) keys.push(k);
+ console.log (msg + " Keys : " + keys);
+}
+
+(function($) {
+
+ var methods = {
+ init : function (options) {
+ return this.each(function() {
+ var $this=$(this);
+ var data=$this.data('QueryCode');
+ if ( ! data ) {
+ // Subscribe to query updates
+ var channel='/results/' + options.query_uuid + '/updated';
+ /* passing $this as 2nd arg: callbacks will retrieve $this as e.data */
+ $.subscribe(channel, $this, update_plugin);
+ if (querycode_debug) window.console.log('subscribing to ' + channel);
+ $this.data('QueryCode', {options: options});
+ // react to changes to the language selector
+ $this.find(".querycode-lang").change(change_language);
+ }
+ });
+
+ console.log("temporarily turned off SyntaxHighlighter ...");
+// SyntaxHighlighter.all();
+
+ },
+
+// destroy : function( ) {
+// if (querycode_debug) console.log("QueryCode.destroy...");
+// },
+// update : function( content ) {
+// if (querycode_debug) console.log("QueryCode.update...");
+// },
+ trigger : function () {
+ var channel='/results/' + $(this).data.QueryCode.options.query_uuid + '/updated';
+ publish(channel,"trigger");
+ }
+
+
+ } // methods
+
+ $.fn.QueryCode = 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.QueryCode' );
+ }
+ };
+
+ // we retrieve the plugindiv as e.data - cf the 2nd arg to subscribe
+ function update_plugin (e) {
+ var $plugindiv=e.data;
+ do_update ($plugindiv);
+ }
+
+ // linked to 'change' on the selector; this=the selector dom
+ function change_language (e) {
+ var $plugindiv = $(this).closest(".plugin");
+ do_update($plugindiv);
+ }
+
+ function do_update ($plugindiv) {
+ // just in case
+ $plugindiv.closest('.need-spin').spin(false);
+
+ var lang=$plugindiv.find(".querycode-lang").val();
+ var dom=$plugindiv.find(".querycode-viz");
+ var query = $plugindiv.data().QueryCode.options.query;
+ funname="translate_query_as_" + lang;
+ fun=eval(funname);
+ if ( ! fun) {
+ console.log("Cannot find translator function for lang " + lang);
+ return;
+ }
+ html_code=fun(query);
+ dom.html(html_code);
+ console.log("turned off SyntaxHighlighter.highlight");
+// SyntaxHighlighter.highlight()
+
+ }
+
+
+ // private stuff
+ function translate_query_as_ruby (query) {
+ debug_object("query_ruby entering -- query=" + query, query);
+ var output = '# Connection to XMLRPC server\n';
+ output += 'require "xmlrpc/client"\n';
+ output += 'require "pp"\n';
+ output += '\n';
+ output += 'XMLRPC::Config.module_eval do\n';
+ output += ' remove_const :ENABLE_NIL_PARSER\n';
+ output += ' const_set :ENABLE_NIL_PARSER, true\n';
+ output += 'end\n';
+ output += 'srv = XMLRPC::Client.new2("https://www.top-hat.info/API/")\n';
+ //output += 'tophat = xmlrpclib.ServerProxy("' . (TOPHAT_API_PORT == 443 ? 'http' : 'https') . '://' . TOPHAT_API_HOST . ':' . TOPHAT_API_PORT . TOPHAT_API_PATH . '", allow_none=True)\n\n';
+ output += '\n';
+ output += '# Authentication token\n';
+ output += 'auth = {"AuthMethod" => "password", "Username" => "guest", "AuthString" => "guest"}\n';
+ output += '\n';
+
+ ifs = '';
+ $.each(query.filters, function(i, value) {
+ if (ifs != '') ifs += ', ';
+ ifs += '"';
+ if (value[1] != "=")
+ ifs += value[1];
+ ifs += value[0] + '" => "' + value[2] + '"';
+ });
+ ifs = '{' + ifs + '}';
+
+ ofs = '';
+ $.each(query.fields, function(index, value) {
+ if (ofs != '')
+ ofs += ', ';
+ ofs += '"' + value + '"';
+ });
+ ofs = '[' + ofs + ']';
+
+ output += 'pp srv.call("' + query.action +'", auth, "' + query.method + '", "' + query.timestamp + '", ' + ifs + ', ' + ofs + ')';
+
+ var output = '<pre class="brush: ruby; toolbar: false;">' + output + "</pre>";
+ return output;
+
+ }
+
+ function translate_query_as_python (query) {
+ // xxx tmp
+ var TOPHAT_API_HOST="hostname", TOPHAT_API_PORT=443, TOPHAT_API_PATH="/path";
+ var proto = (TOPHAT_API_PORT == 443 ? 'https' : 'http');
+ var output = '# Connection to XMLRPC server\n';
+ output += 'import xmlrpclib\n';
+ output += 'srv = xmlrpclib.ServerProxy("' + proto + '://' + TOPHAT_API_HOST + ':' + TOPHAT_API_PORT + TOPHAT_API_PATH + '", allow_none=True)\n\n';
+ output += '# Authentication token\n';
+ output += 'auth = {"AuthMethod": "password", "Username": "name.surname@domain.name", "AuthString": "mypassword"}\n\n';
+
+ ifs = '';
+ $.each(query.filters, function(i, value) {
+ if (ifs != '')
+ ifs += ', ';
+ //ifs += '"'
+ //if (value[1] != "=")
+ // ifs += value[1];
+ ifs += '["' + value[0] + '", "' + value[1] + '", "' + value[2] + '"]';
+ });
+ ifs = '[' + ifs + ']';
+
+ ofs = '';
+ $.each(query.fields, function(index, value) {
+ if (ofs != '')
+ ofs += ', ';
+ ofs += '"' + value + '"';
+ });
+ ofs = '[' + ofs + ']';
+
+ output += 'srv.' + query.action + '(auth, "' + query.method + '", ' + ifs + ', {}, ' + ofs + ')';
+ var output = '<pre class="brush: python; toolbar: false;">' + output + "</pre>";
+ return output;
+ }
+
+
+
+ // get these plugins to update their contents upon loading
+ // manually publishing on the right channel
+// $(function () { $(".QueryCode").each(function () { this.trigger(); })})
+
+})(jQuery); // end closure wrapper
+
/**
* MySlice SimpleList plugin
- * Version: 0.1.0
- * URL: http://www.myslice.info
+ * URL: http://trac.myslice.info
* Description: display simple lists like slices or testbeds
- * Requires:
* Author: The MySlice Team
* Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
* License: GPLv3
*/
-simplelist_debug=true;
+simplelist_debug=false;
+//simplelist_debug=true;
(function($){
var methods = {
init : function( options ) {
return this.each(function(){
- var $this = $(this);
- var data = $this.data('SimpleList');
- /* create an empty DOM object */
- var SimpleList = $('<div />', { text : $this.attr('title') });
+ var $this = $(this), data = $this.data('SimpleList');
// If the plugin hasn't been initialized yet
if ( ! data ) {
/* Subscribe to query updates */
/* passing $this as 2nd arg: callbacks will retrieve $this as e.data */
$.subscribe(channel, $this, update_plugin);
if (simplelist_debug) window.console.log('subscribing to ' + channel);
- $this.data('SimpleList', {options: options, SimpleList : SimpleList});
+ $this.data('SimpleList', {options: options});
}
});
},
destroy : function( ) {
+ if (simplelist_debug) console.log("SimpleList.destroy...");
return this.each(function(){
var $this = $(this), data = $this.data('SimpleList');
+ // xxx not too sure what this is about
$(window).unbind('SimpleList');
- data.SimpleList.remove();
$this.removeData('SimpleList');
- })
- },
- update : function( content ) { }
- };
+ });
+ },
+ update : function( content ) {
+ if (simplelist_debug) console.log("SimpleList.update...");
+ },
+ }; // methods
$.fn.SimpleList = function( method ) {
/* Method calling logic */
};
/* 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 $this=e.data;
+ var $plugindiv=e.data;
// locate the <table> element; with datatables in the way,
// this might not be a direct son of the div-plugin
- var $table=$this.find("table.simplelist").first();
+ var $table=$plugindiv.find("table.simplelist").first();
// also we may or may not have a header
var $tbody=$table.find("tbody.simplelist").first();
var use_datatables = $table.hasClass("with-datatables");
- if (simplelist_debug) console.log($this.attr('id') + " udt= " + use_datatables);
+ if (simplelist_debug) console.log($plugindiv.attr('id') + " udt= " + use_datatables);
// clear the spinning wheel: look up an ancestor that has the need-spin class
// do this before we might return
- $this.closest('.need-spin').spin(false);
+ $plugindiv.closest('.need-spin').spin(false);
if (rows.length == 0) {
if (use_datatables) datatables_set_message ("No result");
else regular_set_message (error);
return;
}
- var options = e.data.data().SimpleList.options;
+ var options = $plugindiv.data().SimpleList.options;
if (use_datatables) datatables_update_table ($table,$tbody,rows,options.key);
else regular_update_table ($table,$tbody,rows,options.key);
}
function regular_update_table ($table, $tbody, rows, key) {
- console.log('regular_update_table ' + rows.length + " rows");
+ if (simplelist_debug) console.log('regular_update_table ' + rows.length + " rows");
var html=$.map(rows, function (row) { return html_row ( cell (key, row[key])); }).join();
- console.log("html="+html);
$tbody.html(html);
}
}
function datatables_update_table ($table, $tbody, rows, key) {
- console.log('datatables_update_table ' + rows.length + " rows");
+ if (simplelist_debug) console.log('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.
--- /dev/null
+<strong>Choose your language:</strong>
+<select class='querycode-lang'>
+ <option>python</option>
+ <option>ruby</option>
+</select>
+<br/>
+<div class='querycode-viz'></div>
from engine.page import Page
from engine.manifoldquery import ManifoldQuery
+from plugins.verticallayout import VerticalLayout
from plugins.slicelist import SliceList
+from plugins.querycode import QueryCode
#
from myslice.viewutils import topmenu_items, the_user
sort='slice_hrn',)
page.enqueue_query (slices_query)
- main_plugin = SliceList ( # setting visible attributes first
+ main_plugin = VerticalLayout (
page=page,
- title='Asynchroneous SliceList',
- header='slices list',
- with_datatables=False,
- toggled=True,
- # this is the query at the core of the slice list
- query=slices_query,
- )
+ title="Putting stuff together",
+ sons=[
+ SliceList ( # setting visible attributes first
+ page=page,
+ title='Asynchroneous SliceList',
+ header='slices list',
+ with_datatables=False,
+ toggled=False,
+ # this is the query at the core of the slice list
+ query=slices_query,
+ ),
+ QueryCode (
+ page=page,
+ title="Vizualize your query",
+ query=slices_query,
+ ),
+ ])
# variables that will get passed to the view-plugin.html template
template_env = {}