p.login-status {
+ padding-top: 10px;
font-weight: bold;
}
{% insert_str prelude 'css/login.css' %}
<p class='login-status'> {{ state }} </p>
-<!--<a href="/" alt="Home"><img class="logo" src="{{ STATIC_URL }}img/myslice-logo.png" alt="MySlice" /></a>-->
-<div class='well well-lg'>
+<div class='well'>
<form action="/login/" method="post">
{% csrf_token %}
{% if next %}
usr/share/unfold/ui
usr/share/unfold/myslice
usr/share/unfold/sample
-usr/share/unfold/trash
-usr/share/unfold/debug_platform
manage.py usr/share/unfold/
apache/myslice.conf /etc/apache2/sites-available
def __repr__ (self): return "ManifoldAPI[%s]"%self.url
+ def _print_value (self, value):
+ print "+++",'value',
+ if isinstance (value,list): print "[%d]"%len(value),
+ elif isinstance (value,dict): print "{%d}"%len(value),
+ print mytruncate (value,80)
+
# a one-liner to give a hint of what the return value looks like
def _print_result (self, result):
if not result: print "[no/empty result]"
print "result is a dict with %d keys : %s"%(len(result),result.keys())
for (k,v) in result.iteritems():
if v is None: continue
- print '+++',k,':',mytruncate (v,60)
+ if k=='value': self._print_value(v)
+ else: print '+++',k,':',mytruncate (v,30)
else: print "[dont know how to display result] %s"%result
# xxx temporary code for scaffolding a ManifolResult on top of an API that does not expose error info
// 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); }
+// start spinners - be robust if the spin stuff was not loaded for any reason
+// turned off because each plugin is responsible for doing that through on_query_in_progress
+// try {
+// var subjects=$(".need-spin");
+// if (manifold.asynchroneous_debug) {
+// messages.debug("Turning on spin with " + subjects.length + " matches for .need-spin");
+// $.map (subjects, function (subject) { messages.debug("need-spin: "+ subject.id);});
+// }
+// subjects.spin(manifold.spin_presets);
+// } catch (err) { messages.debug("Cannot turn on spins " + err); }
// Loop through input array, and use publish_uuid to publish back results
- jQuery.each(query_publish_dom_tuples, function(index, tuple) {
+ $.each(query_publish_dom_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 /*domid*/));
})
},
/* 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 */
});
+# NOTE
+# in real-life we use a debian packaging, so this fedora packaging is very rough
+# it turns out we need to have one specfile for the PL build..
+# in any case the contents here should be more carefully split
+# into several components pieces for generic and plugins and all that...
+
%define name myslice
%define version 0.2
%define taglevel 4
class SimpleList (Plugin) :
# only deal with our own stuff here and let Plugin handle the rest
- def __init__ (self, key, with_datatables=False, **settings):
+ def __init__ (self, key, with_datatables=False, classname=None, **settings):
Plugin.__init__ (self, **settings)
self.key=key
self.with_datatables = with_datatables
+ # the DOM classname
+ self.classname = classname if classname is not None else "simplelist"
# SimpleList is useless per se anyways
def template_file (self):
header=getattr(self,'header',None)
if header: env['header']=header
env['with_datatables']= "yes" if self.with_datatables else ""
+ env['classname']=self.classname
return env
def requirements (self):
reqs['js_files'].append ("js/with-datatables.js")
return reqs
- def json_settings_list (self): return ['plugin_uuid','query_uuid','key']
+ def json_settings_list (self): return ['plugin_uuid','query_uuid','key','classname']
class SliceList (SimpleList):
def __init__ (self, **settings):
- SimpleList.__init__(self, key='slice_hrn', **settings)
+ SimpleList.__init__(self, key='slice.slice_hrn', classname='slicelist', **settings)
# writing a js plugin for that would be overkill, just use SimpleList
def plugin_classname (self):
return 'SimpleList'
+
+ def requirements (self):
+ req = SimpleList.requirements(self)
+ req['css_files'] += [ 'css/slicelist.css' ]
+ return req
tbody.simplelist i {
padding-right: 8px;
}
-/* make previous next buttons a bit nicer */
-div.paging_two_button>a { padding: 0px 4px 0px 4px; }
-/* ---------- */
-/* xxx this probably should be separated in something related to datatables */
-select {
- width: auto;
-}
-div.dataTables_filter input[type=text] {
- width: 60;
+.simplelist {
+ font-size: 100%;
+ text-align: center !important;
+ margin: 0 auto;
}
--- /dev/null
+/* font size for regular (non datatable'd) slicelists */
+tbody.slicelist {
+ font-size: 150%;
+}
+/* datatable'd tables behave differently */
+table.with-datatables>tbody.slicelist {
+ font-size: 80%;
+}
+/* larger headers */
+thead.slicelist>tr>th {
+ font-size: 150%;
+ padding: 10px 10px 20px 10px;
+}
+/* some space after the arrow */
+tbody.slicelist i {
+ padding-right: 8px;
+}
+
+.slicelist {
+ font-size: 100%;
+ text-align: center !important;
+ margin: 0 auto;
+}
--- /dev/null
+/* font size for regular (non datatable'd) testbedlists */
+tbody.testbedlist {
+ font-size: 300%;
+}
+/* datatable'd tables behave differently */
+table.with-datatables>tbody.testbedlist {
+ font-size: 80%;
+}
+/* larger headers */
+thead.testbedlist>tr>th {
+ font-size: 150%;
+ padding: 10px 10px 20px 10px;
+}
+/* some space after the arrow */
+tbody.testbedlist i {
+ padding-right: 8px;
+}
+
+.testbedlist {
+ font-size: 100%;
+ text-align: center !important;
+ margin: 0 auto;
+}
(function($){
var debug=false;
- // debug=true
+ 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);
+ },
+
+ on_query_in_progress: function() {
+ messages.debug("on_query_in_progress");
+ this.spin();
+ },
+
+ on_query_done: function() {
+ this._display_table();
+ this.unspin();
+ },
+
+ on_new_record: function(record) {
+ this.buffered_records.push(record);
+ },
/* 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;
- // 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.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 (debug)
- messages.debug($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
- $plugindiv.closest('.need-spin').spin(false);
- 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;
- }
+ _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)
- datatables_set_message ($table, $tbody, unfold.error(error));
- else
- regular_set_message ($table, $tbody, unfold.error(error));
- 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;
+ }
- var options = $plugindiv.data().SimpleList;
if (use_datatables)
- datatables_update_table($table, $tbody, rows, options.key);
+ this._datatables_update_table($table, $tbody, rows, options.key);
else
- regular_update_table($table, $tbody, rows, options.key);
-
- }
-
- // 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;
- }
- }
+ 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) {
- if (debug)
- messages.debug('regular_update_table ' + rows.length + " rows");
+ _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) {
- 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) { return html_row ( cell (key, val)); });
- return x;
- } else {
- return html_row ( cell (key, value));
- }
- }).join();
- $tbody.html(html);
- }
+ 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)) {
+ 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) {
- return "<tr><td class='simplelist'>"+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 );
class StaticList (Plugin) :
+ """ StaticList allows you to display an html list
+ that you provide the contents for in the 'list' input argument
+ It is static in the sense that no query is going to be used to
+ manage this contents
+ """
+
# only deal with our own stuff here and let Plugin handle the rest
def __init__ (self, list=[], with_datatables=False, **settings):
Plugin.__init__ (self, **settings)
-<table class='simplelist{%if with_datatables %} with-datatables{% endif %}'>
-{% if header %} <thead class='simplelist'><tr><th class='simplelist'>{{ header }}</th></tr></thead> {% endif %}
-<tbody class='simplelist'></tbody>
+<table class='{{ classname }}{%if with_datatables %} with-datatables{% endif %}'>
+{% if header %} <thead class='{{ classname }}'><tr><th class='{{ classname }}'>{{ header }}</th></tr></thead> {% endif %}
+<tbody class='{{ classname }}'></tbody>
</table>
--- /dev/null
+from plugins.lists.simplelist import SimpleList
+
+class TestbedList (SimpleList):
+
+ def __init__ (self, **settings):
+ SimpleList.__init__(self, key='platform', classname='testbedlist', **settings)
+
+ # writing a js plugin for that would be overkill, just use SimpleList
+ def plugin_classname (self):
+ return 'SimpleList'
+
+ def requirements (self):
+ req = SimpleList.requirements(self)
+ req['css_files'] += [ 'css/testbedlist.css' ]
+ return req
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()
from manifold.core.query import Query
from unfold.page import Page
-from plugins.lists.simplelist import SimpleList
+from plugins.lists.testbedlist import TestbedList
+from plugins.lists.slicelist import SliceList
from unfold.loginrequired import LoginRequiredAutoLogoutView
# Slow...
#slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
- auth_query = Query().get('network').select('network_hrn','platform')
+ testbed_query = Query().get('network').select('network_hrn','platform')
# DEMO GEC18 Query only PLE
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(auth_query)
+ page.enqueue_query(testbed_query)
page.expose_js_metadata()
page.expose_queries()
- slicelist = SimpleList(
- title = None,
+ slicelist = SliceList(
page = page,
- key = 'slice.slice_hrn',
+ title = "slices",
query = slice_query,
)
- # XXX TODO: plugins/lists/static/js/simplelist.js => hardcoded keys that give links : slice_hrn & platform
- authlist = SimpleList(
- title = None,
+ testbedlist = TestbedList(
page = page,
- key = 'platform',
- query = auth_query,
+ title = "testbeds",
+ query = testbed_query,
)
context = super(DashboardView, self).get_context_data(**kwargs)
context['person'] = self.request.user
- context['networks'] = authlist.render(self.request)
+ context['testbeds'] = testbedlist.render(self.request)
context['slices'] = slicelist.render(self.request)
# XXX This is repeated in all pages
context.update(page.prelude_env())
return context
-
-
-
/* GENERAL */
.container {
- padding: 0 !important;
- color: #fff;
+ padding: 0 !important;
+ color: #fff;
background: url(http://new.fit-equipex.fr/images/background.jpg) no-repeat;
margin: 0;
width: 100%;
-
+/* if window enlarged wider than background picture */
+body {
+ background: black !important;
+}
/* TOPMENU.CSS */
+/* Thierry : turning this off
body {
- /* background: #30196d !important; */
- background: black !important;
+ *//* background: #30196d !important; *//*
+ background: black !important;
padding-top: 60px;
padding-bottom: 0px;
}
+Thierry */
/* Thierry : turning this off
div.topmenu {
.query-editor-spacer,
.plugin.QueryUpdater,
-.plugin.Tabs {
+/* Thierry : turning this off
+.plugin.Tabs
+Thierry */
+{
margin-top: 60px !important;
}
padding-left: 0 !important;
}
-.simplelist {
- font-size: 100%;
- text-align: center !important;
- margin: 0 auto;
-}
-/*
- * This file is included in tophat_render.php
- */
// Escape special characters in jQuery Selector
function escape_id( myid ) {
return "#" + myid.replace( /(:|\.|\[|\])/g, "\\$1" );
<h2>Testbeds</h2>
</div>
<div class='ms-dashboard-content' id='tophat__list__platform__network_name'>
- {{networks}}
+ {{testbeds}}
</div>
</div>
--- /dev/null
+/* single column layout - layout-unfold1.html */
+#unfold1-main {
+}
+/* dual column layout - layout-unfold2.html */
+#unfold2-main {
+}
+#unfold2-margin {
+/* trying to set a right padding here results in undesired results (spans beyond right end) */
+}
+++ /dev/null
-/* this relates to the unfold-layout1 template */
-#unfold2-main {
-}
-#unfold2-margin {
- padding: 10;
-/* background-color: #fff2ff; */
-}
{% insert_str prelude "js/plugin.js" %}
{% insert_str prelude "js/manifold.js" %}
{% insert_str prelude "js/topmenu.js" %}
-{% insert_str prelude "css/layout-unfold2.css" %}
+{% insert_str prelude "css/layout-unfold.css" %}
{% insert_str prelude "css/manifold.css" %}
{% insert_str prelude "css/plugin.css" %}
{% insert_str prelude "css/onelab_marko.css" %}
result.append({'label':'Request a slice', 'href': '/portal/slice_request/'})
result.append({'label':'Validation', 'href': '/portal/validate/'})
dropdown = []
+ dropdown.append({'label':'Platforms', 'href': '/portal/platforms/'})
dropdown.append({'label':'My Account', 'href': '/portal/account/'})
dropdown.append({'label':'Contact Support', 'href': '/portal/contact/'})
result.append({'label': 'More', 'href':"#", 'dropdown':True, 'contents':dropdown})
# 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):