From 114043cbf2203977fc4c149578fd49ea684048cf Mon Sep 17 00:00:00 2001 From: Loic & Edelberto Date: Wed, 23 Apr 2014 10:38:33 -0300 Subject: [PATCH] Merging with OneLab latest --- .settings/org.eclipse.core.resources.prefs | 3 + README | 8 + auth/static/js/logout.js | 5 +- debian/control | 13 +- debian/deb-cheat-sheet | 5 + debian/unfold.install | 1 - manifoldapi/manifoldapi.py | 4 +- manifoldapi/static/js/manifold.js | 11 +- plugins/googlemap/static/js/googlemap.js | 2 + plugins/querytable/__init__.py | 4 +- plugins/querytable/static/css/querytable.css | 1 - plugins/querytable/static/js/querytable.js | 63 +- plugins/querytable/templates/querytable.html | 10 +- .../queryupdater/static/js/queryupdater.js | 4 +- plugins/scheduler2/asdf.txt | 0 portal/about.py | 4 +- portal/accountview.py | 3 +- portal/contactview.py | 5 +- portal/dashboardview.py | 2 +- portal/django_passresetview.py | 2 +- portal/documentationview.py | 2 +- portal/institution.py | 40 +- portal/joinview.py | 4 +- portal/manageuserview.py | 2 +- portal/platformsview.py | 2 +- portal/platformview.py | 2 +- portal/resourceview.py | 2 +- portal/slicerequestview.py | 13 +- portal/sliceresourceview.py | 106 ++- portal/slicetabexperiment.py | 4 +- portal/slicetabinfo.py | 2 +- portal/slicetabtestbeds.py | 2 +- portal/sliceview.py | 4 +- portal/sliceviewold.py | 2 +- portal/static/css/fed4fire.css | 806 +++++++----------- portal/static/css/onelab.css | 84 +- portal/static/js/institution.js | 62 +- portal/static/js/myslice.js | 68 +- .../static/js/onelab_slice-resource-view.js | 16 +- portal/supportview.py | 4 +- portal/templates/about.html | 126 ++- portal/templates/account-view.html | 402 +++++---- portal/templates/contact_sent.html | 4 + portal/templates/home-view.html | 95 ++- portal/templates/institution.html | 222 +++-- portal/templates/join_view.html | 257 +++--- portal/templates/manageuserview.html | 4 +- .../onelab/onelab_slice-user-view.html | 29 - .../templates/onelab/onelab_slice-view.html | 2 +- .../onelab/onelab_widget-slice-sections.html | 32 +- portal/templates/password_reset_complete.html | 8 +- portal/templates/password_reset_confirm.html | 8 +- portal/templates/password_reset_done.html | 8 +- portal/templates/password_reset_form.html | 8 +- portal/templates/slice-request-ack-view.html | 2 +- portal/templates/slice-tab-info.html | 24 +- portal/templates/slice-tab-testbeds.html | 17 +- portal/templates/slice_request_email.html | 1 + portal/templates/slice_request_email.txt | 1 + portal/templates/slicerequest_view.html | 125 ++- portal/templates/supportview.html | 175 ++-- portal/templates/user_register_complete.html | 2 +- portal/templates/user_request_email.html | 7 +- portal/templates/user_request_email.txt | 7 +- portal/templates/validate_pending.html | 2 +- portal/urls.py | 4 +- portal/usersview.py | 2 +- portal/validationview.py | 20 +- rest/__init__.py | 40 +- rest/create.py | 3 +- rest/update.py | 15 +- 71 files changed, 1634 insertions(+), 1395 deletions(-) mode change 100644 => 100755 plugins/scheduler2/asdf.txt diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 2bdc1575..f73c991a 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,5 +1,8 @@ eclipse.preferences.version=1 encoding//portal/django_passresetview.py=utf-8 +encoding//portal/forms.py=utf-8 +encoding//portal/migrations/0002_extend_slice.py=utf-8 +encoding//portal/models.py=utf-8 encoding//portal/urls.py=utf-8 encoding//portal/validationview.py=utf-8 encoding//portal/views.py=utf-8 diff --git a/README b/README index 78ffe6c2..2ce46698 100644 --- a/README +++ b/README @@ -60,6 +60,14 @@ when you just need to hit ^C yourself when your static files need to be refreshe $ pip install -r path/to/requirements/file.txt Note. not quite sure what this is about, I could not spot this file.. +=====APACHE Config===== +if are running apache please do: + +$ chown www-data:www-data /var/myslice-f4f + +otherwise you may get the following error: +"DatabaseError: unable to open database file" + ==================== Status *** Authentication *** diff --git a/auth/static/js/logout.js b/auth/static/js/logout.js index 9c9b4532..593eb588 100644 --- a/auth/static/js/logout.js +++ b/auth/static/js/logout.js @@ -4,7 +4,10 @@ function logout () { var username=$(this).data('username'); var msg="Are you sure you want to logout as " + username + " ?"; /* redirect to /logout, see urls.py */ - if (confirm(msg)) window.location="/logout/"; + if (confirm(msg)){ + localStorage.removeItem('user'); + window.location="/logout/"; + } } /* attach this function to the logout button */ $(document).ready(function() { $('#logout').click(logout); $('#logoutbtn').click(logout); }); diff --git a/debian/control b/debian/control index 4a4eb059..0230abd7 100644 --- a/debian/control +++ b/debian/control @@ -3,16 +3,19 @@ Maintainer: Thierry Parmentelat Section: misc Priority: optional Standards-Version: 3.9.2 +# hopefully we do not need manifold at build-time Build-Depends: devscripts, debhelper (>=7.0.50~), debconf, dpatch, python-setuptools, make, python-django X-Python-Version: >= 2.7 -Package: myslice -Architecture: any -Depends: unfold, python-django-south -Description: Myslice plugins, based on django and unfold frontend - # Thierry: the recipe I'm using somehow only works with several packages Package: unfold Architecture: any Depends: python, python-django, python-pyparsing, apache2, libapache2-mod-wsgi, openssl Description: Generic django-based frontend for manifold backends + +# +Package: myslice +Architecture: any +Depends: python-django-south, unfold, manifold +Description: Myslice plugins, based on django and unfold frontend + diff --git a/debian/deb-cheat-sheet b/debian/deb-cheat-sheet index 8524fb80..182c3d3c 100644 --- a/debian/deb-cheat-sheet +++ b/debian/deb-cheat-sheet @@ -16,3 +16,8 @@ dpkg-deb -c myslice_0.2.4.lxc.2013.11.26_amd64.deb dpkg -s myslice dpkg --info -c myslice_0.2.4.lxc.2013.11.26_amd64.deb +--- install from a local .deb +dpkg -i foo.deb +- or, if this has deps that need to be pulled through apt-get: +gdebi foo.deb +(install with apt-get install -y gdebi-core) diff --git a/debian/unfold.install b/debian/unfold.install index fb542506..f058d151 100644 --- a/debian/unfold.install +++ b/debian/unfold.install @@ -1,6 +1,5 @@ usr/lib*/python*/dist-packages/auth usr/lib*/python*/dist-packages/insert_above -usr/lib*/python*/dist-packages/manifold usr/lib*/python*/dist-packages/plugins usr/lib*/python*/dist-packages/unfold usr/lib*/python*/dist-packages/ui diff --git a/manifoldapi/manifoldapi.py b/manifoldapi/manifoldapi.py index b1a1a0cc..b105bf30 100644 --- a/manifoldapi/manifoldapi.py +++ b/manifoldapi/manifoldapi.py @@ -152,7 +152,9 @@ 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" + #raise Exception, "User not authenticated" + host = request.get_host() + return redirect(host) manifold_api_session_auth = request.session['manifold']['auth'] return _execute_query(request, query, manifold_api_session_auth) diff --git a/manifoldapi/static/js/manifold.js b/manifoldapi/static/js/manifold.js index 3d526a67..f0bbc8a6 100644 --- a/manifoldapi/static/js/manifold.js +++ b/manifoldapi/static/js/manifold.js @@ -699,6 +699,7 @@ var manifold = { if (data.code == 2) { // ERROR // We need to make sense of error codes here alert("Your session has expired, please log in again"); + localStorage.removeItem('user'); window.location="/logout/"; if (manifold.asynchroneous_debug) { duration=new Date()-start; @@ -908,9 +909,7 @@ var manifold = { break; case FILTER_ADDED: -// Thierry - this is probably wrong but intended as a hotfix -// http://trac.myslice.info/ticket/32 -// manifold.raise_query_event(query_uuid, event_type, value); + manifold.raise_query_event(query_uuid, event_type, value); break; case FILTER_REMOVED: manifold.raise_query_event(query_uuid, event_type, value); @@ -945,7 +944,11 @@ var manifold = { } // We need to inform about changes in these queries to the respective plugins // Note: query, main_query & update_query have the same UUID - manifold.raise_query_event(query_uuid, event_type, value); + + // http://trac.myslice.info/ticket/32 + // Avoid multiple calls to the same event + //manifold.raise_query_event(query_uuid, event_type, value); + // We are targeting the same object with get and update // The notion of query is bad, we should have a notion of destination, and issue queries on the destination // NOTE: Editing a subquery == editing a local view on the destination diff --git a/plugins/googlemap/static/js/googlemap.js b/plugins/googlemap/static/js/googlemap.js index 6db222d4..8a740b2a 100644 --- a/plugins/googlemap/static/js/googlemap.js +++ b/plugins/googlemap/static/js/googlemap.js @@ -94,6 +94,8 @@ //create empty LatLngBounds object in order to automatically center the map on the displayed objects this.bounds = new google.maps.LatLngBounds(); var center = new google.maps.LatLng(this.options.latitude, this.options.longitude); + + console.log("GoogleMap zoom = "+this.options.zoom); var myOptions = { zoom: this.options.zoom, center: center, diff --git a/plugins/querytable/__init__.py b/plugins/querytable/__init__.py index 6a2bb29a..5a80bb9f 100644 --- a/plugins/querytable/__init__.py +++ b/plugins/querytable/__init__.py @@ -71,7 +71,7 @@ Current implementation makes the following assumptions aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[]) # here 'checkbox' is the class that we give to the dom elem # dom-checkbox is a sorting type that we define in querytable.js - aoColumnDefs.append ( {'aTargets': ['checkbox'], 'sSortDataType': 'dom-checkbox' } ) + #aoColumnDefs.insert (0, {'aTargets': ['checkbox'], 'sSortDataType': 'dom-checkbox' } ) def template_file (self): return "querytable.html" @@ -95,7 +95,7 @@ Current implementation makes the following assumptions 'css_files': [ #"css/dataTables.bootstrap.css", # hopefully temporary, when/if datatables supports sPaginationType=bootstrap3 # for now we use full_numbers, with our own ad hoc css - "css/dataTables.full_numbers.css", + #"css/dataTables.full_numbers.css", #"css/querytable.css" , ], } diff --git a/plugins/querytable/static/css/querytable.css b/plugins/querytable/static/css/querytable.css index edbc683e..a42ab1fe 100644 --- a/plugins/querytable/static/css/querytable.css +++ b/plugins/querytable/static/css/querytable.css @@ -16,7 +16,6 @@ div.QueryTable table.dataTable th { } div.QueryTable table.dataTable th.checkbox { - padding-left: 14px; } div.QueryTable table.dataTable td, div.QueryTable table.dataTable textarea, div.QueryTable table.dataTable input [type="text"] { diff --git a/plugins/querytable/static/js/querytable.js b/plugins/querytable/static/js/querytable.js index 15ee6f1c..5e734a1e 100644 --- a/plugins/querytable/static/js/querytable.js +++ b/plugins/querytable/static/js/querytable.js @@ -91,7 +91,8 @@ var actual_options = { // Customize the position of Datatables elements (length,filter,button,...) // we use a fluid row on top and another on the bottom, making sure we take 12 grid elt's each time - sDom: "<'row'<'col-xs-5'l><'col-xs-1'r><'col-xs-6'f>>t<'row'<'col-xs-5'i><'col-xs-7'p>>", + //sDom: "<'row'<'col-xs-5'l><'col-xs-1'r><'col-xs-6'f>>t<'row'<'col-xs-5'i><'col-xs-7'p>>", + sDom: "<'row'<'col-xs-5'f><'col-xs-1'r><'col-xs-6 columns_selector'>>t<'row'<'col-xs-5'l><'col-xs-7'p>>", // XXX as of sept. 2013, I cannot locate a bootstrap3-friendly mode for now // hopefully this would come with dataTables v1.10 ? // in any case, search for 'sPaginationType' all over the code for more comments @@ -145,6 +146,8 @@ //manifold.raise_event(self.options.query_all_uuid, FIELD_REMOVED, field); self.hide_column(field); }); + $(".dataTables_filter").append("
"); + $(".dataTables_filter input").css("width","100%"); }, // initialize_table /** @@ -194,10 +197,15 @@ var colnames = cols.map(function(x) {return x.sTitle}) var nb_col = cols.length; /* if we've requested checkboxes, then forget about the checkbox column for now */ - if (this.options.checkboxes) nb_col -= 1; - + //if (this.options.checkboxes) nb_col -= 1; + // catch up with the last column if checkboxes were requested + if (this.options.checkboxes) { + // Use a key instead of hostname (hard coded...) + line.push(this.checkbox_html(record)); + } + /* fill in stuff depending on the column name */ - for (var j = 0; j < nb_col; j++) { + for (var j = 1; j < nb_col; j++) { if (typeof colnames[j] == 'undefined') { line.push('...'); } else if (colnames[j] == 'hostname') { @@ -217,10 +225,11 @@ } /* XXX TODO: Remove this and have something consistant */ if(obj=='resource'){ - line.push(' '+record[this.init_key]); + //line.push(' '+record[this.init_key]); }else{ - line.push(' '+record[this.init_key]); + //line.push(' '+record[this.init_key]); } + line.push(record[this.init_key]); } else { if (record[colnames[j]]) line.push(record[colnames[j]]); @@ -229,11 +238,7 @@ } } - // catch up with the last column if checkboxes were requested - if (this.options.checkboxes) { - // Use a key instead of hostname (hard coded...) - line.push(this.checkbox_html(record)); - } + // adding an array in one call is *much* more efficient // this.table.fnAddData(line); @@ -300,7 +305,7 @@ { // Remove corresponding filters this.filters = $.grep(this.filters, function(x) { - return x != filter; + return x == filter; }); this.redraw_table(); }, @@ -397,10 +402,15 @@ switch(data.request) { case FIELD_REQUEST_ADD: case FIELD_REQUEST_ADD_RESET: + // update pending number + $("#badge-pending").data('number', $("#badge-pending").data('number') + 1 ); + $("#badge-pending").text($("#badge-pending").data('number')); this.set_checkbox_from_data(data.value, true); break; case FIELD_REQUEST_REMOVE: case FIELD_REQUEST_REMOVE_RESET: + $("#badge-pending").data('number', $("#badge-pending").data('number') - 1 ); + $("#badge-pending").text($("#badge-pending").data('number')); this.set_checkbox_from_data(data.value, false); break; default: @@ -415,7 +425,7 @@ switch(data.request) { case FIELD_REQUEST_ADD: case FIELD_REQUEST_ADD_RESET: - this.set_checkboxfrom_data(data.value, true); + this.set_checkbox_from_data(data.value, true); break; case FIELD_REQUEST_REMOVE: case FIELD_REQUEST_REMOVE_RESET: @@ -445,18 +455,18 @@ on_all_query_done: function() { - if (debug) messages.debug("1-shot initializing dataTables content with " + this.buffered_lines.length + " lines"); - this.table.fnAddData (this.buffered_lines); - this.buffered_lines=[]; + if (debug) messages.debug("1-shot initializing dataTables content with " + this.buffered_lines.length + " lines"); + this.table.fnAddData (this.buffered_lines); + this.buffered_lines=[]; var self = this; // 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 ("querytable 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 = []; + this.buffered_records_to_check = []; this.received_all_query = true; // unspin once we have received both @@ -490,6 +500,15 @@ if (op == '=' || op == '==') { if ( col_value != value || col_value==null || col_value=="" || col_value=="n/a") ret = false; + }else if (op == 'included') { + $.each(value, function(i,x) { + if(x == col_value){ + ret = true; + return false; + }else{ + ret = false; + } + }); }else if (op == '!=') { if ( col_value == value || col_value==null || col_value=="" || col_value=="n/a") ret = false; @@ -589,10 +608,10 @@ was in fact given as a third argument, and not second as the various online resources had it - go figure */ $.fn.dataTableExt.afnSortData['dom-checkbox'] = function ( oSettings, _, iColumn ) { - return $.map( oSettings.oApi._fnGetTrNodes(oSettings), function (tr, i) { - return result=$('td:eq('+iColumn+') input', tr).prop('checked') ? '1' : '0'; - } ); - } + return $.map( oSettings.oApi._fnGetTrNodes(oSettings), function (tr, i) { + return result=$('td:eq('+iColumn+') input', tr).prop('checked') ? '1' : '0'; + }); + }; })(jQuery); diff --git a/plugins/querytable/templates/querytable.html b/plugins/querytable/templates/querytable.html index bc9cc034..d0f18c05 100644 --- a/plugins/querytable/templates/querytable.html +++ b/plugins/querytable/templates/querytable.html @@ -1,19 +1,19 @@ -
- +
+
+ {% if checkboxes %}{% endif %} {% for column in columns %} {% endfor %} - {% for column in hidden_columns %} {% endfor %} - {% if checkboxes %} {% endif %} + {% for column in hidden_columns %} {% endfor %} + {% if checkboxes %} {% endif %} {% for column in columns %} {% endfor %} {% for column in hidden_columns %} {% endfor %} - {% if checkboxes %} {% endif %}
+/-{{ column }}{{ column }}+/-{{ column }}
+/-{{ column }}{{ column }}+/-
diff --git a/plugins/queryupdater/static/js/queryupdater.js b/plugins/queryupdater/static/js/queryupdater.js index b00f04fd..89afdf3d 100644 --- a/plugins/queryupdater/static/js/queryupdater.js +++ b/plugins/queryupdater/static/js/queryupdater.js @@ -131,7 +131,9 @@ // make sure the change is visible : toggle on the whole plugin // this might have to be made an 'auto-toggle' option of this plugin.. // also it might be needed to be a little finer-grained here - this.toggle_on(); + + // XXX we don't want to show automaticaly the pending when a checkbox is checked + //this.toggle_on(); switch(data.request) { case FIELD_REQUEST_ADD_RESET: diff --git a/plugins/scheduler2/asdf.txt b/plugins/scheduler2/asdf.txt old mode 100644 new mode 100755 diff --git a/portal/about.py b/portal/about.py index 49a890bb..99434a70 100644 --- a/portal/about.py +++ b/portal/about.py @@ -12,7 +12,7 @@ from manifoldapi.manifoldresult import ManifoldResult from ui.topmenu import topmenu_items, the_user from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView class AboutView (FreeAccessView, ThemeView): template_name = 'about.html' @@ -37,7 +37,7 @@ class AboutView (FreeAccessView, ThemeView): env['person'] = None env['theme'] = self.theme - + env['section'] = "About" env['username']=the_user(request) env['topmenu_items'] = topmenu_items(None, request) diff --git a/portal/accountview.py b/portal/accountview.py index 9b0c4666..67c765d9 100644 --- a/portal/accountview.py +++ b/portal/accountview.py @@ -11,7 +11,7 @@ from django.http import HttpResponse, HttpResponseRedirec from django.contrib import messages from django.contrib.auth.decorators import login_required -from theme import ThemeView +from myslice.theme import ThemeView # import json, os, re, itertools @@ -203,6 +203,7 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView): # so we can sho who is logged context['username'] = the_user(self.request) context['theme'] = self.theme + context['section'] = "User account" # context ['firstname'] = config['firstname'] prelude_env = page.prelude_env() context.update(prelude_env) diff --git a/portal/contactview.py b/portal/contactview.py index 13450dfd..44c151c4 100644 --- a/portal/contactview.py +++ b/portal/contactview.py @@ -7,7 +7,7 @@ from ui.topmenu import topmenu_items, the_user from portal.forms import ContactForm -from theme import ThemeView +from myslice.theme import ThemeView # splitting the 2 functions done here # GET is for displaying the empty form @@ -50,7 +50,7 @@ class ContactView (FreeAccessView, ThemeView): else: sender = email - msg = EmailMultiAlternatives(subject, text_content, sender, [recipients]) + msg = EmailMultiAlternatives(subject, text_content, sender, recipients) msg.attach_alternative(html_content, "text/html") msg.send() except Exception, e: @@ -77,4 +77,5 @@ class ContactView (FreeAccessView, ThemeView): 'topmenu_items': topmenu_items('Contact', request), 'theme' : self.theme, 'username': username, + 'section': "Contact" }) diff --git a/portal/dashboardview.py b/portal/dashboardview.py index 2b0ab828..06f02f83 100644 --- a/portal/dashboardview.py +++ b/portal/dashboardview.py @@ -11,7 +11,7 @@ from unfold.loginrequired import LoginRequiredAutoLogoutView from ui.topmenu import topmenu_items_live, the_user -from theme import ThemeView +from myslice.theme import ThemeView #This view requires login class DashboardView (LoginRequiredAutoLogoutView, ThemeView): diff --git a/portal/django_passresetview.py b/portal/django_passresetview.py index 7d7f52e9..a0018b0f 100644 --- a/portal/django_passresetview.py +++ b/portal/django_passresetview.py @@ -87,7 +87,7 @@ from portal.actions import manifold_update_user from portal.forms import PassResetForm from portal.actions import manifold_update_user -from theme import ThemeView +from myslice.theme import ThemeView # 4 views for password reset: # - password_reset sends the mail diff --git a/portal/documentationview.py b/portal/documentationview.py index 6a75a629..ccd42fa1 100644 --- a/portal/documentationview.py +++ b/portal/documentationview.py @@ -12,7 +12,7 @@ from manifoldapi.manifoldresult import ManifoldResult from ui.topmenu import topmenu_items, the_user from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView class DocumentationView (FreeAccessView, ThemeView): template_name = 'documentationview.html' diff --git a/portal/institution.py b/portal/institution.py index 9bc0a868..c53318ba 100644 --- a/portal/institution.py +++ b/portal/institution.py @@ -5,7 +5,7 @@ from django.template import RequestContext from django.shortcuts import render_to_response from django.shortcuts import render -from unfold.loginrequired import FreeAccessView +from unfold.loginrequired import LoginRequiredAutoLogoutView from manifold.core.query import Query from manifoldapi.manifoldapi import execute_query @@ -13,9 +13,10 @@ from manifoldapi.manifoldresult import ManifoldResult from ui.topmenu import topmenu_items, the_user from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView +import json -class InstitutionView (FreeAccessView, ThemeView): +class InstitutionView (LoginRequiredAutoLogoutView, ThemeView): template_name = 'institution.html' # expose this so we can mention the backend URL on the welcome page @@ -40,11 +41,42 @@ class InstitutionView (FreeAccessView, ThemeView): env['user_details'] = user_details[0] except Exception,e: env['error'] = "Please check your Credentials" + + try: + user_local_query = Query().get('local:user').select('config').filter_by('email','==',str(env['person'])) + user_local_details = execute_query(self.request, user_local_query) + user_local = user_local_details[0] + user_local_config = user_local['config'] + user_local_config = json.loads(user_local_config) + user_local_authority = user_local_config.get('authority') + if 'user_details' not in env or 'parent_authority' not in env['user_details'] or env['user_details']['parent_authority'] is None: + env['user_details'] = {'parent_authority': user_local_authority} + except Exception,e: + env['error'] = "Please check your Manifold user config" + ## check user is pi or not + platform_query = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled') + account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config') + platform_details = execute_query(self.request, platform_query) + account_details = execute_query(self.request, account_query) + for platform_detail in platform_details: + for account_detail in account_details: + if platform_detail['platform_id'] == account_detail['platform_id']: + if 'config' in account_detail and account_detail['config'] is not '': + account_config = json.loads(account_detail['config']) + if 'myslice' in platform_detail['platform']: + acc_auth_cred = account_config.get('delegated_authority_credentials','N/A') + # assigning values + if acc_auth_cred == {}: + pi = "is_not_pi" + else: + pi = "is_pi" + else: env['person'] = None env['theme'] = self.theme - + env['section'] = "Institution" + env['pi'] = pi env['username']=the_user(request) env['topmenu_items'] = topmenu_items(None, request) if state: env['state'] = state diff --git a/portal/joinview.py b/portal/joinview.py index abe73f39..c128db3b 100644 --- a/portal/joinview.py +++ b/portal/joinview.py @@ -19,7 +19,7 @@ from manifold.core.query import Query from portal.models import PendingUser,PendingAuthority from portal.actions import authority_get_pi_emails, manifold_add_user,manifold_add_account -from theme import ThemeView +from myslice.theme import ThemeView # since we inherit from FreeAccessView we cannot redefine 'dispatch' # so let's override 'get' and 'post' instead @@ -205,7 +205,7 @@ class JoinView (FreeAccessView, ThemeView): sender = render_to_string(theme.template, ctx) sender = sender.replace('\n', '') - msg = EmailMultiAlternatives(subject, text_content, sender, [recipients]) + msg = EmailMultiAlternatives(subject, text_content, sender, recipients) msg.attach_alternative(html_content, "text/html") msg.send() diff --git a/portal/manageuserview.py b/portal/manageuserview.py index 369d6e95..7687d341 100644 --- a/portal/manageuserview.py +++ b/portal/manageuserview.py @@ -10,7 +10,7 @@ from ui.topmenu import topmenu_items_live, the_user from django.http import HttpResponse, HttpResponseRedirect from django.contrib import messages from django.contrib.auth.decorators import login_required -from theme import ThemeView +from myslice.theme import ThemeView # import json, os, re, itertools diff --git a/portal/platformsview.py b/portal/platformsview.py index eef773a3..c31cd174 100644 --- a/portal/platformsview.py +++ b/portal/platformsview.py @@ -5,7 +5,7 @@ from unfold.loginrequired import FreeAccessView from ui.topmenu import topmenu_items_live, the_user from plugins.querytable import QueryTable -from theme import ThemeView +from myslice.theme import ThemeView # View for platforms class PlatformsView(FreeAccessView, ThemeView): diff --git a/portal/platformview.py b/portal/platformview.py index d70c99b5..b0fc3ec7 100644 --- a/portal/platformview.py +++ b/portal/platformview.py @@ -15,7 +15,7 @@ from ui.topmenu import topmenu_items_live, the_user from plugins.querytable import QueryTable from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView # View for 1 platform and its details class PlatformView(FreeAccessView, ThemeView): diff --git a/portal/resourceview.py b/portal/resourceview.py index a407725a..d670645b 100644 --- a/portal/resourceview.py +++ b/portal/resourceview.py @@ -10,7 +10,7 @@ from plugins.lists.simplelist import SimpleList from plugins.slicestat import SliceStat from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView # View for 1 platform and its details class ResourceView(FreeAccessView, ThemeView): diff --git a/portal/slicerequestview.py b/portal/slicerequestview.py index dfa46585..213fd318 100644 --- a/portal/slicerequestview.py +++ b/portal/slicerequestview.py @@ -1,4 +1,6 @@ from django.shortcuts import render +from django.contrib.sites.models import Site + from unfold.page import Page @@ -10,7 +12,7 @@ from portal.forms import SliceRequestForm from unfold.loginrequired import LoginRequiredAutoLogoutView from ui.topmenu import topmenu_items_live, the_user -from theme import ThemeView +from myslice.theme import ThemeView import json, time @@ -63,6 +65,11 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView): if method == 'POST': # The form has been submitted + + # get the domain url + current_site = Site.objects.get_current() + current_site = current_site.domain + slice_request = { 'type' : 'slice', 'id' : None, @@ -73,6 +80,7 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView): 'number_of_nodes' : wsgi_request.POST.get('number_of_nodes', ''), 'type_of_nodes' : wsgi_request.POST.get('type_of_nodes', ''), 'purpose' : wsgi_request.POST.get('purpose', ''), + 'current_site' : current_site } authority_hrn = slice_request['authority_hrn'] @@ -110,7 +118,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView): 'user_hrn': user_hrn, 'cc_myself': True, 'authorities': authorities, - 'theme': self.theme + 'theme': self.theme, + 'section': "Slice request" } template_env.update(slice_request) template_env.update(page.prelude_env()) diff --git a/portal/sliceresourceview.py b/portal/sliceresourceview.py index 520a72eb..b02b0cac 100644 --- a/portal/sliceresourceview.py +++ b/portal/sliceresourceview.py @@ -11,15 +11,16 @@ from django.http import HttpResponse from django.shortcuts import render from unfold.page import Page -from manifold.core.query import Query, AnalyzedQuery -from manifoldapi.manifoldapi import execute_query from myslice.configengine import ConfigEngine from plugins.querytable import QueryTable from plugins.googlemap import GoogleMap from plugins.queryupdater import QueryUpdater +from plugins.testbeds import TestbedsPlugin +from plugins.scheduler2 import Scheduler2 +from plugins.columns_editor import ColumnsEditor -from theme import ThemeView +from myslice.theme import ThemeView class SliceResourceView (LoginRequiredView, ThemeView): template_name = "slice-resource-view.html" @@ -49,7 +50,7 @@ class SliceResourceView (LoginRequiredView, ThemeView): 'resource.hostname', 'resource.type', 'resource.network_hrn', 'lease.urn', - 'user.user_hrn', + #'user.user_hrn', #'application.measurement_point.counter' ) # for internal use in the querytable plugin; @@ -57,13 +58,23 @@ class SliceResourceView (LoginRequiredView, ThemeView): main_query_init_key = 'urn' aq = AnalyzedQuery(main_query, metadata=metadata) page.enqueue_query(main_query, analyzed_query=aq) + sq_resource = aq.subquery('resource') + sq_lease = aq.subquery('lease') query_resource_all = Query.get('resource').select(resource_fields) page.enqueue_query(query_resource_all) - sq_resource = aq.subquery('resource') - sq_lease = aq.subquery('lease') + # leases query + lease_md = metadata.details_by_object('lease') + lease_fields = [column['name'] for column in lease_md['column']] + query_all_lease = Query.get('lease').select(lease_fields) + page.enqueue_query(query_all_lease) + + # -------------------------------------------------------------------------- + # ALL RESOURCES LIST + # resources as a list using datatable plugin + list_resources = QueryTable( page = page, domid = 'resources-list', @@ -79,8 +90,41 @@ class SliceResourceView (LoginRequiredView, ThemeView): }, ) + # -------------------------------------------------------------------------- - # RESOURCES + # RESERVED RESOURCES LIST + # resources as a list using datatable plugin + + list_reserved_resources = QueryTable( + page = page, + domid = 'resources-reserved-list', + title = 'List view', + query = sq_resource, + query_all = sq_resource, + init_key = "urn", + checkboxes = True, + datatables_options = { + 'iDisplayLength': 25, + 'bLengthChange' : True, + 'bAutoWidth' : True, + }, + ) + + # -------------------------------------------------------------------------- + # COLUMNS EDITOR + # list of fields to be applied on the query + # this will add/remove columns in QueryTable plugin + + filter_column_editor = ColumnsEditor( + page = page, + query = sq_resource, + query_all = query_resource_all, + title = "Select Columns", + domid = 'select-columns', + ) + + # -------------------------------------------------------------------------- + # RESOURCES MAP # the resources part is made of a Tabs (Geographic, List), map_resources = GoogleMap( @@ -99,7 +143,21 @@ class SliceResourceView (LoginRequiredView, ThemeView): # center on Paris latitude = 49., longitude = 9, - zoom = 4, + zoom = 8, + ) + + # -------------------------------------------------------------------------- + # LEASES Nitos Scheduler + # Display the leases reservation timeslots of the resources + + resources_as_scheduler2 = Scheduler2( + page = page, + domid = 'scheduler', + title = 'Scheduler', + # this is the query at the core of the slice list + query = sq_resource, + query_all_resources = query_resource_all, + query_lease = query_all_lease, ) # -------------------------------------------------------------------------- @@ -116,9 +174,41 @@ class SliceResourceView (LoginRequiredView, ThemeView): outline_complete = True, ) + # -------------------------------------------------------------------------- + # NETWORKS + # testbeds as a list of filters + + network_md = metadata.details_by_object('network') + network_fields = [column['name'] for column in network_md['column']] + + query_network = Query.get('network').select(network_fields) + page.enqueue_query(query_network) + + filter_testbeds = TestbedsPlugin( + page = page, + domid = 'testbeds-filter', + title = 'Filter by testbeds', + query = sq_resource, + query_all = query_resource_all, + query_network = query_network, + init_key = "network_hrn", + checkboxes = True, + datatables_options = { + 'iDisplayLength': 25, + 'bLengthChange' : True, + 'bAutoWidth' : True, + }, + ) + template_env = {} template_env['list_resources'] = list_resources.render(self.request) +# template_env['list_reserved_resources'] = list_reserved_resources.render(self.request) + + template_env['columns_editor'] = filter_column_editor.render(self.request) + + template_env['filter_testbeds'] = filter_testbeds.render(self.request) template_env['map_resources'] = map_resources.render(self.request) + template_env['scheduler'] = resources_as_scheduler2.render(self.request) template_env['pending_resources'] = pending_resources.render(self.request) template_env["theme"] = self.theme template_env["username"] = request.user diff --git a/portal/slicetabexperiment.py b/portal/slicetabexperiment.py index f13c9d80..cca8afbd 100644 --- a/portal/slicetabexperiment.py +++ b/portal/slicetabexperiment.py @@ -12,10 +12,10 @@ from manifoldapi.manifoldresult import ManifoldResult from ui.topmenu import topmenu_items, the_user from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView class ExperimentView (FreeAccessView, ThemeView): - template_name = 'experimentview.html' + template_name = 'slice-tab-experiment.html' def get (self, request, slicename, state=None): diff --git a/portal/slicetabinfo.py b/portal/slicetabinfo.py index 7e7b78ea..fc7fa291 100644 --- a/portal/slicetabinfo.py +++ b/portal/slicetabinfo.py @@ -14,7 +14,7 @@ from unfold.page import Page from manifold.core.query import Query, AnalyzedQuery from manifoldapi.manifoldapi import execute_query -from theme import ThemeView +from myslice.theme import ThemeView class SliceInfoView (LoginRequiredView, ThemeView): template_name = "slice-tab-info.html" diff --git a/portal/slicetabtestbeds.py b/portal/slicetabtestbeds.py index a93f6787..abd6ce65 100644 --- a/portal/slicetabtestbeds.py +++ b/portal/slicetabtestbeds.py @@ -3,7 +3,7 @@ from django.shortcuts import render_to_response from unfold.loginrequired import LoginRequiredView -from theme import ThemeView +from myslice.theme import ThemeView class SliceTabTestbeds (LoginRequiredView, ThemeView): template_name = "slice-tab-testbeds.html" diff --git a/portal/sliceview.py b/portal/sliceview.py index 008222c1..e79b48e8 100644 --- a/portal/sliceview.py +++ b/portal/sliceview.py @@ -14,10 +14,10 @@ from unfold.page import Page from manifold.core.query import Query, AnalyzedQuery from manifoldapi.manifoldapi import execute_query -from theme import ThemeView +from myslice.theme import ThemeView class SliceView (LoginRequiredView, ThemeView): template_name = "slice-view.html" def get(self, request, slicename): - return render_to_response(self.template, {"slice": slicename, "theme": self.theme, "username": request.user, "section":"slice"}, context_instance=RequestContext(request)) + return render_to_response(self.template, {"slice": slicename, "theme": self.theme, "username": request.user, "section": "Slice %s" % slicename }, context_instance=RequestContext(request)) diff --git a/portal/sliceviewold.py b/portal/sliceviewold.py index e7991537..7cf80f93 100644 --- a/portal/sliceviewold.py +++ b/portal/sliceviewold.py @@ -31,7 +31,7 @@ from plugins.slicestat import SliceStat from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView tmp_default_slice='ple.upmc.myslicedemo' diff --git a/portal/static/css/fed4fire.css b/portal/static/css/fed4fire.css index a014b34d..e8a798ce 100644 --- a/portal/static/css/fed4fire.css +++ b/portal/static/css/fed4fire.css @@ -1,476 +1,63 @@ -/* @override unfold/static/css/plugin.css */ -/* GENERAL */ -body { - padding-top: 60px; - padding-bottom: 20px; -} -*/ -/* center the buttons vertically in the header */ -div.topmenu { padding-top: 40px; } -ul.logged-in { - padding-top: 12px; -} -button.logged-in { - font-size: small; - margin-left: 5px; -} -li.username { - margin-bottom: 10px; - font-size: x-small; -} - -.logoTxt{ - font-size: 35px; - position: absolute; - margin-left: 20px; - font-family: verdana,arial,sans-serif; - font-weight: bold; -} -a{ - color: #777777; - text-decoration: none; -} -a:hover{ - color: red; - text-decoration: none; -} -.container { - padding: 0 !important; - color: black; - background-color: white; - margin: 0; - width: 100%; - max-width: 100%; - min-height: 100% !important; - height: 100% !important; - font-family: Ubuntu, Arial, sans-serif !important; -} -div.f4f-title{ - margin-top:20px; - margin-bottom:20px; - text-align: center; - border: 1px solid #61210B; - background-color: orange; -} -.container h1 { - color: #777777; - margin-top: 5px; -} -table { - color:black; -} - -.container h1, .container h2 { - color: #fff !important; -} - -div.plugin-outline-complete, -div.plugin-outline-body { - border: 0px solid; - border-radius: 0; - border-color: #ccc; - -webkit-transition: padding 200ms ease-out; - -moz-transition: padding 200ms ease-out; - -o-transition: padding 200ms ease-out; - transition: padding 0.2s ease-out; - padding: 20px; - margin: 0; -} -/* -div.plugin-outline-complete:hover, -div.plugin-outline-body:hover { - padding: 80px 80px 120px 80px; -} -*/ -a.plugin-tooltip { - font-size: 130%; - font-style: normal; - font-weight: bold; - padding: 5px; - color: #333; - font-family: Ubuntu, Arial, sans-serif; - text-transform: uppercase; -} - -a.plugin-tooltip:hover { - color: #fff; - text-decoration: none; -} - - - -/* LIST VIEW */ - -h2.well.well-lg { - border-radius:0; - border: 0; - font-family: Ubuntu, arial, sans-serif; - /* text-transform: ; */ - font-weight: normal; - font-size: 40px; - /* color: #30196d; */ - color: white; - margin-bottom: 0px; - margin-top: 0; - padding: 40px; - opacity: 1; - text-align: center; - background-color: #30196d; -} - -#complete-resources { -/* background-color: #92f79e ; */ - background-color: #B8B2FF ; -} - -#complete-filters { -/* background-color: #4af25d; */ - background-color: #add7ff; -} - -#complete-users { -/* background-color: #ff7394 ; */ - background-color: #add7ff ; -} -/* -#complete-measurements { - background-color: ; -} -*/ -#complete-pending { -/* background-color: #add7ff ; */ - background-color: #B8B2FF ; - -} - -#complete-customize-resources { - background-color: #efdfdf; -} - -#complete-msgs-pre { - background-color: #ccc; -} - -#complete-resources, -#complete-filters, -#complete-users, -#complete-measurements, -#complete-pending, -#complete-customize-resources, -#complete-msgs-pre { - opacity: 1; - text-align: center; - color: #333; -} - -#complete-resources:hover, -#complete-filters:hover, -#complete-users:hover, -#complete-measurements:hover, -#complete-pending:hover, -#complete-customize-resources:hover, -#complete-msgs-pre:hover { - opacity: 1; -} - -.nav.nav-tabs { - font-family: Ubuntu, Arial, sans-serif; - border: 0 !important; - border-bottom: 3px solid #fff !important; - margin-bottom: 40px; -} - -.nav.nav-tabs li.active a { - color: red; - border-left: 0px solid #572bc9; - border-top: 0px solid #572bc9; - border-right: 0px solid #572bc9; - background-color: orange; -} - -.nav.nav-tabs li a { - color: #333; - border: 0 !important; - margin-right: 5px; -} - -.nav.nav-tabs li a:hover { - color: #333; - background: red; - color: #fff; - border: 0 !important; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - background-color: orange; -} - -/* TOPMENU.CSS */ +html { height: 100% } body { - /* background: #30196d !important; */ - /* background: black !important; */ - background: white !important; - padding-top: 0px; - padding-bottom: 0px; -} - -.navbar-fixed-top { - position: relative !important; -} - -.navbar-nav li a:hover { - color: red !important; -} - -.navbar-nav li.active a { - background: #eee !important; - background-color: orange; - color: #572bc9 ; -} - -.navbar-nav li.active a { - background: #eee ; -} - -/* Thierry : turning this off -ul.logged-in { - padding-top: 25px; -} -Thierry */ -button.logged-in { - font-size: 1em; - font-weight: bold; - margin-left: 5px; - margin-top: -5px; - /* background: #572bc9; */ - background: #FFD69B; - border: 1px solid orange; - color: #777777; - padding: 5px 15px; - border-radius:5px; -} - -button.logged-in:hover { - /* background: #4af25d; */ - background: orange; - border: 1px solid #777777; - color: #777777; -} -li.username { - margin-bottom: 10px; - font-size: 0.8em; - text-transform: none; - font-weight: normal; - color: #999; -} - - -/* BOOTSTRAP */ - - -ul.pagination li a { - /* background: ; */ - color: #572bc9; - font-family: Ubuntu, Arial, sans-serif; -} - -ul.pagination li.active a { - /* background: #572bc9; */ - background: orange; - border: 1px solid red; -} - -.btn.btn-default { - /* background: #572bc9; */ - background: #FFD69B; - color: #777777; - font-family: Ubuntu, Arial, sans-serif; - font-weight: bold; - border-color: #eea236; -} - -.btn.btn-default:hover { - /* background: #4af25d; */ - /* background: #ff7394; */ - background: orange; - color: #333; - font-family: Ubuntu, Arial, sans-serif; - font-weight: bold; - border-color: #927143; + background-color:white; + color:black; + margin:0; + padding:0; + height: 100%; } - -input { - border-radius: 3px; - border: none; - border: 1px solid #ccc; +a, a:active, a:focus { + outline: 0; } -div.dataTables_length label, -div.dataTables_filter label, -div.dataTables_info { - font-family: Ubuntu, Arial, sans-serif ; +h1 { + border-bottom:1px solid #DDDDDD; + padding:0 0 0 0; + margin:0 0 0 0; + font-size:18pt; } - - - - -/* QUERYTABLE */ - -div.QueryTable table.dataTable th { - font: bold 12px/22px Ubuntu, Arial, sans-serif; - color: #333 ; - border-right: 0px solid #333 ; - border-bottom: 0px solid #C1DAD7 ; - border-top: 0px solid #C1DAD7 ; - letter-spacing: 1px; - text-transform: uppercase; - text-align: left; - padding: 8px 12px 4px 20px; +h1 img { vertical-align:middle; - background: url('../img/tablesort-header.png') no-repeat ; + margin-bottom:6px; } - -div.QueryTable table.dataTable td, div.QueryTable table.dataTable textarea, div.QueryTable table.dataTable input [type="text"] { - font: normal 12px Ubuntu, Arial, Helvetica, sans-serif; - border-right: 0px solid #fff ; - border-bottom: 1px solid #fff ; +h2 { + font-size:14pt; + color:#333333; } - -div.QueryTable table.dataTable thead { - background: url('../img/tablesort-header.png') repeat-x ; - background-color: #caebea; +h3 { + font-size:13pt; + color:#201E62; } -div.QueryTable table.dataTable tfoot { - background: url('../img/tablesort-header.png') repeat-x ; - /* background-color: # ; */ +div.wrapper { + width:980px; + margin:0 auto; + position:relative; } - - -/* QUERY EDITOR */ - -table.query-editor { - margin: 40px auto ; - clear: both; - /* width: 80%;*/ - width: 100% ; - font-family: Ubuntu; +div.container { + width:980px; + margin:25px auto; } - -.query-editor-spacer, -.plugin.QueryUpdater, -.plugin.Tabs { - margin-top: 60px !important; -/* Thierry : turning this off -.plugin.Tabs -Thierry */ -{ - margin-top: 60px ; ->>>>>>> 804932e8a431ddbf0d7c56457625457967b48d4c:portal/static/css/onelab_marko.css +div.wide { + margin:25px auto; + padding:0 25px; } -table.query-editor td { - padding: 5px 5px ; - font: normal 12px Ubuntu, Arial, sans-serif ; +span.label { + font-size:11pt; + color:gray; + font-weight:normal; + padding:0; } - - - -/* DASHBOARD */ - -#ms-dashboard-profile, -#ms-dashboard-testbeds, -#ms-dashboard-slices { - -webkit-transition: all 50ms ease-out; - -moz-transition: all 50ms ease-out; - -o-transition: all 50ms ease-out; - transition: all 0.05s ease-out; - padding-top: 140px; - padding-bottom: 60px; - margin-top: 60px; - color: #777777; - font-family: Ubuntu, Arial, sans-serif; +/***** Notifications *****/ +.warning { + border: 1px solid red; + margin: 20px 60px; + padding: 10px 20px; + color: red; + background-color: #f2dbdb; text-align: center; - -} - -#ms-dashboard-profile:hover, -#ms-dashboard-testbeds:hover, -#ms-dashboard-slices:hover { - margin-top: 65px; -} - -#ms-dashboard-profile { - background: url("../img/icon_users_color.png") top center no-repeat; -} - -#ms-dashboard-testbeds { - background: url("../img/icon_testbed_color.png") top center no-repeat; -} - -#ms-dashboard-slices { - background: url("../img/icon_slices_color.png") top center no-repeat; -} - -.ms-dashboard-content ul { - list-style-type: none ; - padding-left: 0; - text-align: center ; -} - -.ms-dashboard-content { - padding: 0 !important; -} - -.ms-dashboard-content a { -/* color: #ff7394 !important; */ - color: orange !important; -/* color: #ff0099 !important; */ -} - -.ms-dashboard-content a:hover { - color: red !important; -} -.ms-dashboard-caption h2 { - font-family: Ubuntu, Arial, sans-serif; - border-bottom: 0 !important; - text-transform: uppercase; - color: #777777 !important; -} - -#ms-dashboard-profile>div.ms-dashboard-caption { - background: no-repeat url(#) ; - padding-left: 0 ; -} - -#ms-dashboard-testbeds>div.ms-dashboard-caption { - background: no-repeat url(#) ; - padding-left: 0 ; -} - -#ms-dashboard-slices>div.ms-dashboard-caption { - background: no-repeat url(#) ; - padding-left: 0 ; -} - -.simplelist { - font-size: 100%; - text-align: center !important; - margin: 0 auto; -} - -/*** NEW CSS STYLES FOR ONLEAB ***/ - -body { - background-color:white; - color:black; -} -div.wrapper { - width:980px; - margin:0 auto; - position:relative; } /* HEADER */ div#header { @@ -506,7 +93,7 @@ div#secondary li:last-child { } div#navigation { - background-color:black; + background-color:orange; width:100%; height:40px; } @@ -544,10 +131,47 @@ div#navigation li:last-child { margin-right:0; } +div#navigation li.active { + padding:5px; + padding-top: 15px; + min-height: 40px; + margin-top: 0px; + background-color:gray; + color:#FF0000; +} +div#navigation li.slices { + position:relative; + cursor:pointer; +} +div#navigation .dropdown-menu { + color:white; + padding:0 15px 15px 15px; + margin-top:5px; + margin-left:-16px; + background-color:orange; +} +div#navigation .dropdown-menu a { + color:white; +} + +div#menu-slice-list{ + display:none; + position:absolute; + background-color:orange; + padding:15px; + left:-15px; + z-index:10; +} + +div#navigation .dropdown-menu li:first-child { + border-bottom:1px solid white; + padding-bottom:5px; + +} /* HOME DASHBOARD */ div#home-dashboard { color:black; - margin:25px 0; + margin:0 auto 25px auto; } div#home-dashboard table { margin:25px; @@ -564,12 +188,34 @@ div#home-dashboard table tr:first-child td { color:#270A5A; } div#home-dashboard table tr:last-child td { + vertical-align:top; + padding:25px 0; +} +div#home-dashboard table tr:last-child td.logged-in { + border-right:1px solid #DDDDDD; + padding:25px; +} +div#home-dashboard table tr:last-child td.support { + border-left:1px solid #DDDDDD; + padding:25px; +} +div#home-dashboard table tr:last-child td:first-child { +} +div#home-dashboard table tr:last-child td:last-child { + border-right:0; +} +div#home-dashboard table tr:last-child td.logged-in div { text-align:left; + padding:25px 0; +} +div#home-dashboard table tr:last-child td.support div { + text-align:left; + padding:25px 0; +} +div#home-dashboard div.login-widget { + padding:20px; } div#home-dashboard table td.support { - font-size:14pt; - vertical-align:top; - padding-left:11%; } div#home-dashboard table td.support a { } @@ -577,6 +223,23 @@ div#home-dashboard table td.support a:hover { text-decoration:none; } +div#home-dashboard div#manager { + display:none; +} + +div#home-dashboard div#home-slice-list { + margin:25px 0; + padding:0 25px; + text-align:left; +} +div#home-dashboard div#home-slice-list ul { + list-style: none; + padding:0; + margin:0; +} +div#home-dashboard div#home-slice-list li { + +} .login-submit { vertical-align:middle; @@ -598,31 +261,222 @@ div#home-dashboard table td.support a:hover { } /**/ -/* NAV TABS */ +/**/ +/* WELL */ +div.well { +} +/**/ +/* BUTTON */ +.btn.btn-default { + font-weight: bold; +} + +.btn.btn-default:hover { + font-weight: bold; +} +/**/ +/* TABLE */ +table.table { + margin:0; +} +table.table thead { + padding:0; +} +table.table tbody { + padding:0; +} +table.table tr { + padding:0; +} +table.table td { + padding:0; +} +/* INSTITUTION */ +div#institution { + color:black; +} +.form-hint { + font-size:11pt; + font-style:italic; + color:gray; +} + -.nav.nav-tabs { +.form-hint { + font-size:11pt; + font-style:italic; + color:gray; } -.nav.nav-tabs li.active a { - + + +/* TICKET REQUEST */ +div#ticket-request { + color:black; +} +.form-hint { + font-size:11pt; + font-style:italic; + color:gray; +} +div#ticket-request p { + margin:20px 0; } -.nav.nav-tabs li a { +ul.nav-tabs {} +ul.nav-tabs ul {} +ul.nav-tabs li {} + +ul.nav-section li a { + border-bottom:0; +} +ul.nav-section li:first-child { + padding:0; +} +ul.nav-section li:first-child a { + font-weight:bold; + padding:6px 15px 4px 15px; +} +ul.nav-section li:first-child.active a { + padding:6px 15px 3px 15px; +} +ul.nav-section li:first-child img { + margin:0 4px 1px 0; + padding:0; } -.nav.nav-tabs li a:hover { +ul.nav-resources { + margin:15px 0; +} +ul.nav-resources a { + padding: 4px 10px 5px 10px; } -/**/ -/* WELL */ -div.well { + +/* SLICE VIEW */ + + +div#slice-view { + margin:0; } -/**/ -/* BUTTON */ -.btn.btn-default { +div.list-group-item { + border:0; + background-color:white; + font-weight:bold; + padding-left:0; +} +a.list-group-item { + border:0; + background-color:white; + padding:3px 0 3px 10px; + border-left:2pt white solid; +} +a.list-group-item.active, a.list-group-item.active:hover { font-weight: bold; + color:black; + background-color:transparent; + border-left:2pt blue solid; +} +a.list-group-item.active:hover { + background-color:#dddddd; +} +a.list-group-item:hover { + border-left:2pt blue solid; +} +a.list-group-item p.list-group-item-text { + font-size:9pt; + font-style:italic; + font-weight: normal; + color: black !important; +} + +div#slice-info { + margin-top:25px; +} +div#slice-info table { + width:100%; + margin:0 auto; +} +div#slice-info table td:first-child { + text-align:right; + font-weight:bold; + padding-right:15px; +} +div#slice-info td { + padding:5px; +} + +/* SLICE VIEW sections */ +.slice-sections, .slice-pending { + margin:0; + padding:0; +} +.slice-sections ul, .slice-pending ul { + margin:0; + padding:0; +} +.slice-pending ul { + width:400px; + margin:0 auto 15px auto; +} +.slice-sections li { + text-align:left; + margin:0; + padding:0; +} +.slice-pending li { + padding-right:15px; +} +.slice-sections li a, .slice-pending li a { + font-size:14px; + color:black; + padding:0; +} +.slice-sections li.active a, .slice-pending li.active a { + color:#201E62; + background-color:#EFEFEF; + text-decoration:underline; + padding:0; +} +.slice-sections ul.nav-pills li a:hover, .slice-pending ul.nav-pills li a:hover { + text-decoration:underline; + background-color:#EFEFEF; + color:black; +} +.slice-sections ul.nav-pills li.active, .slice-pending ul.nav-pills li.active { + +} +.slice-sections li:first-child, .slice-sections li:first-child a { + color:#201E62; + font-weight:bold; +} +.slice-experiment { + text-align:right; + padding:0; +} +.slice-experiment button { + margin:3px 0 0 0; + background-color:#CC4125; + color:white; +} + +.slice-pending { +} +.slice-pending button { + font-size:9pt; + margin:-2px 0 0 0; + padding:3px 5px; +} +.slice-pending button.apply { +} +.slice-pending button.clear { +} +tr.active, tr.active td { + background-color:#FFFFCC !important; +} + +div.dataTables_filter label{ + float:left; + width:400px; } -.btn.btn-default:hover { - font-weight: bold; -} \ No newline at end of file diff --git a/portal/static/css/onelab.css b/portal/static/css/onelab.css index c39de29b..0a0559a6 100644 --- a/portal/static/css/onelab.css +++ b/portal/static/css/onelab.css @@ -15,11 +15,12 @@ h1 { border-bottom:1px solid #DDDDDD; padding:0 0 0 0; margin:0 0 0 0; - font-size:18pt; + font-size:14pt; } h1 img { vertical-align:middle; - margin-bottom:6px; + margin-bottom:4px; + margin-right:10px; } h2 { font-size:14pt; @@ -261,21 +262,6 @@ div#home-dashboard div#home-slice-list li { } /**/ -/* NAV TABS */ - -.nav.nav-tabs { -} - -.nav.nav-tabs li.active a { - -} - -.nav.nav-tabs li a { -} - -.nav.nav-tabs li a:hover { -} - /**/ /* WELL */ div.well { @@ -338,19 +324,24 @@ div#ticket-request p { margin:20px 0; } -/* SLICE VIEW */ -ul.nav-sliceview {} -ul.nav-sliceview li { - +ul.nav-tabs {} +ul.nav-tabs ul {} +ul.nav-tabs li {} + +ul.nav-section li a { + border-bottom:0; } -ul.nav-sliceview li:first-child { +ul.nav-section li:first-child { padding:0; } -ul.nav-sliceview li:first-child a { +ul.nav-section li:first-child a { font-weight:bold; padding:6px 15px 4px 15px; } -ul.nav-sliceview li:first-child img { +ul.nav-section li:first-child.active a { + padding:6px 15px 3px 15px; +} +ul.nav-section li:first-child img { margin:0 4px 1px 0; padding:0; } @@ -362,7 +353,7 @@ ul.nav-resources a { padding: 4px 10px 5px 10px; } - +/* SLICE VIEW */ div#slice-view { @@ -370,22 +361,57 @@ div#slice-view { } div.list-group-item { border:0; + -moz-border-radius: 0; + border-radius: 0; background-color:white; font-weight:bold; padding-left:0; } a.list-group-item { + -moz-border-radius: 0; + border-radius: 0; border:0; background-color:white; - padding:3px 0 3px 10px; + padding:3px 2px 3px 10px; border-left:2pt white solid; } -a.list-group-item.active, a.list-group-item:hover { +a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus { + -moz-border-radius: 0; + border-radius: 0; + font-weight: bold; + color:black; + background-color:#F5F5F5; + border-left:2pt blue solid; +} + +a.list-group-item:hover { + -moz-border-radius: 0; + border-radius: 0; border-left:2pt blue solid; } a.list-group-item p.list-group-item-text { + -moz-border-radius: 0; + border-radius: 0; font-size:9pt; font-style:italic; + font-weight: normal; + color: black !important; +} + +div#slice-info { + margin-top:25px; +} +div#slice-info table { + width:100%; + margin:0 auto; +} +div#slice-info table td:first-child { + text-align:right; + font-weight:bold; + padding-right:15px; +} +div#slice-info td { + padding:5px; } /* SLICE VIEW sections */ @@ -456,3 +482,7 @@ a.list-group-item p.list-group-item-text { tr.active, tr.active td { background-color:#FFFFCC !important; } +div.dataTables_filter label{ + float:left; + width:400px; +} diff --git a/portal/static/js/institution.js b/portal/static/js/institution.js index 1ddb3e3f..5595b3e0 100644 --- a/portal/static/js/institution.js +++ b/portal/static/js/institution.js @@ -1,42 +1,22 @@ $(document).ready(function() { - $('li#nav-institution').addClass("active"); - - $('a.home-tab').click(function() { - $('ul.nav-tabs li').removeClass('active'); - $(this).parent().addClass('active'); - $('div.home-panel').hide(); - $('div#'+$(this).data('panel')).show(); - }); - var url = window.location; - if(url.hash) { - // Fragment exists - tab = url.href.split("#")[1]; - tab_exists = $('div#'+tab).length; - if (tab_exists) { - $('ul.nav-tabs li').removeClass('active'); - $('li#'+tab+'-tab').addClass('active'); - $('div.home-panel').hide(); - $('div#'+tab).show(); - } - } + loadedTabs = []; + + $('.nav-tabs a').click(function (e) { + e.preventDefault(); + $(this).tab('show'); + id = $(this).attr('href').substr(1); + if (!(id in loadedTabs)) { + switch(id) { + case 'users': + //loadUsers(); + loadedTabs[id] = true; + break; + } + } + + }); /* TODO: factorize into functions */ - $('button#deleteusers').click(function() { - $('input:checkbox.user').each(function (index) { - if(this.checked){ - var record_id = this.id; - $.post("/delete/user/",{'filters':{'user_hrn':this.id}}, function(data) { - if(data.success){ - $('tr[id="'+record_id+'"]').fadeOut("slow"); - $('tr[id="'+record_id+'"]').remove(); - }else{ - alert("Rest Error for "+record_id+": "+data.error); - } - }); - - } - }); - }); $('button#deleteslices').click(function() { $('input:checkbox.slice').each(function (index) { if(this.checked){ @@ -86,3 +66,13 @@ $(document).ready(function() { */ }); }); + +/*function loadUsers() { + $('div#users table').load('/table/user/', + { + 'fields' : [ 'user_hrn', 'user_first_name', 'user_last_name', 'user_email', 'user_phone' ], + 'filters' : { 'parent_authority' : $('div#users').data('authority') }, + 'options' : [ 'checkbox' ] + } + ); +}*/ diff --git a/portal/static/js/myslice.js b/portal/static/js/myslice.js index 7038e53e..2f866553 100644 --- a/portal/static/js/myslice.js +++ b/portal/static/js/myslice.js @@ -6,24 +6,6 @@ function list() { this.elements = []; } -list.prototype.save = function() { - for (var prop in this) { - if (typeof this[prop] != 'function') { - console.log("prop: " + prop); - } else { - console.log("func: " + prop); - } - } - //localStorage.setItem(name, JSON.stringify(value)); -}; - -list.prototype.load = function(name) { - this.pending = JSON.parse(localStorage.getItem(name)); - if (!this.pending) { - this.pending = []; - } -}; - list.prototype.add = function(element) { if (!this.has(element)) { this.elements.push(element); @@ -60,14 +42,14 @@ function resources() { }; }; -function users() { +function leases() { this.pending = { toremove: new list(), toadd: new list(), }; }; -function leases() { +function users() { this.pending = { toremove: new list(), toadd: new list(), @@ -83,27 +65,19 @@ function slice(name) { this.users = new users(); this.leases = new leases(); -}; -slice.prototype.pending = function() { - -}; -slice.prototype.reserve = function() { - -}; -slice.prototype.unreserve = function() { - }; + /* * User */ -function user(u) { - this.u = u; - this.testbeds = {}; - this.slices = {}; +function user(user) { + this.user = user; + this.testbeds = new list(); + this.slices = new list(); - for (i = 0; i < this.u.slices.length; i++) { - this.slices[this.u.slices[i]] = new slice(this.u.slices[i]); + for (i = 0; i < this.user.slices.length; i++) { + this.slices[this.user.slices[i]] = new slice(this.user.slices[i]); } }; @@ -113,7 +87,7 @@ user.prototype.slice = function(name) { user.prototype.list = function() { for (s in this.slices) { - for (o in s) { + for (o in s) { if (typeof o != 'function') { console.log(o); } else { @@ -128,7 +102,25 @@ user.prototype.list = function() { */ var myslice = { user: {}, - + + user: function() { + if ($.isEmptyObject(this.user)) { + //this.login(function() { return this.user; }); + this.user = JSON.parse(localStorage.getItem('user')); + } + return this.user; + }, + + login: function(fn) { + user = localStorage.getItem('user'); + if($.isEmptyObject(user)){ + $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) { + //myslice.user = new user(data[0]); + localStorage.setItem('user', JSON.stringify(data[0])); + }); + } + }, + getSlices: function(name) { }, @@ -197,6 +189,8 @@ var myslice = { $(document).ready(function() { + //console.log(myslice.user().slices); + // $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function(data) { // myslice.user = new user(data[0]); // console.log(myslice.user.slices); diff --git a/portal/static/js/onelab_slice-resource-view.js b/portal/static/js/onelab_slice-resource-view.js index a4180933..1f997d06 100644 --- a/portal/static/js/onelab_slice-resource-view.js +++ b/portal/static/js/onelab_slice-resource-view.js @@ -3,6 +3,11 @@ $(document).ready(function() { $('.'+this.id).trigger('show'); }); + $('a.sl-platform').click(function (e) { + $('.'+this.id).trigger('show'); + }); + + $('ul.nav-resources a').click(function() { $('ul.nav-resources li').removeClass('active'); $(this).parent().addClass('active'); @@ -14,11 +19,18 @@ $(document).ready(function() { } */ }); + $('div.list-resources a').click(function() { + $('div.list-resources a').removeClass('active'); + $(this).addClass('active'); + $('div.panel').hide(); + $('div#'+$(this).data('panel')).show(); + + }); $.get("/rest/network", function(data) { - var list = '
Testbeds
'; + var list = '
Testbeds
'; for(i=0; i'+data[i].network_longname+'

'+data[i].network_hrn+'

'; + list += ''+data[i].network_longname+'

'+data[i].network_hrn+'

'; } $('#select-platform').html(list); }).done(function() { diff --git a/portal/supportview.py b/portal/supportview.py index bbb5b495..5bd0d754 100644 --- a/portal/supportview.py +++ b/portal/supportview.py @@ -12,7 +12,7 @@ from manifoldapi.manifoldresult import ManifoldResult from ui.topmenu import topmenu_items, the_user from myslice.configengine import ConfigEngine -from theme import ThemeView +from myslice.theme import ThemeView class SupportView (FreeAccessView, ThemeView): template_name = 'supportview.html' @@ -33,7 +33,7 @@ class SupportView (FreeAccessView, ThemeView): env['person'] = None env['theme'] = self.theme - + env['section'] = "Support" env['username']=the_user(request) diff --git a/portal/templates/about.html b/portal/templates/about.html index 9b124f28..4c4817a5 100644 --- a/portal/templates/about.html +++ b/portal/templates/about.html @@ -1,41 +1,99 @@ -{% extends "layout.html" %} +{% extends "layout_wide.html" %} {% block content %} -
-

About MySlice About

+
+
-
-

A ready-made and easily customisable user interface for your testbed.

- -

- MySlice is an ambitious project aiming to support researchers throughout the lifecycle of experiments that can run on a variety - of testbeds spanning different administrative domains and networking technologies. Its basic principle is to bring together - available resources with useful information (characteristics, performance, network measurements). -

-

- MySlice inititiave started in Janury 2011 by offering annotation services for the first ederated experimental resources. Today, - MySlice has taken a big step toward becoming a tand-alone web framework, which will present all available resources from testbeds - across the world, interconnected through the Slice-based Facility Architecture (SFA) and annotated by the TopHat measurement system. -

-

- Our framework is built with standard programming tools (php and javascript for the front-end and python for the back-end) - and has a modular structure based on the concept of plugins for implementing different core functionalities (query editing, - data display, and resource allocation). -

-

- The goal is to enable developers with expertise on different testbed technologies and different experimental - practices to work in parallel for optimizing the tools presented to the users allowing them for a wide range of choices - according to their own requirements. Opening in this way the development of web-based user tools for experimentation and - sharing effort and information can increase significantly the chances for the achievement of our challenging objective. -

-

- You can access the code at git.myslice.info. If you need write access to the git repository you need first to send - your public key to support@myslice.info. -

-

- Go to the MySlice web site or the OneLab public web site -

+ +
+
+
+

+ OneLab Portal is a central place to get acess to all OneLab testbeds.In order to get access to the portal, + an experimenter needs to register to the portal. The portal administrative body + is responsible to accept or reject newly registered users. +

+

+ To learn more about OneLab visit: http://onelab.eu/ +

+

+ If you have any questions regarding using the portal visit: OneLab support +

+

+ OneLab portal is a community effot. To get more information about OneLab portal team visit: + http://myslice.info/community +

+
+
+
+
+

A ready-made and easily customisable user interface for your testbed.

+

+ MySlice is an ambitious project aiming to support researchers throughout the lifecycle of experiments that can run on a variety + of testbeds spanning different administrative domains and networking technologies. Its basic principle is to bring together + available resources with useful information (characteristics, performance, network measurements). +

+

+ MySlice inititiave started in Janury 2011 by offering annotation services for the first ederated experimental resources. Today, + MySlice has taken a big step toward becoming a tand-alone web framework, which will present all available resources from testbeds + across the world, interconnected through the Slice-based Facility Architecture (SFA) and annotated by the TopHat measurement system. +

+

+ Our framework is built with standard programming tools (python and javascript for the front-end and python for the back-end) + and has a modular structure based on the concept of plugins for implementing different core functionalities (query editing, + data display, and resource allocation). +

+

+ The goal is to enable developers with expertise on different testbed technologies and different experimental + practices to work in parallel for optimizing the tools presented to the users allowing them for a wide range of choices + according to their own requirements. Opening in this way the development of web-based user tools for experimentation and + sharing effort and information can increase significantly the chances for the achievement of our challenging objective. +

+
+
+

Portal Components

+
Myslice (Web Frontend)
+

+ MySlice is an ambitious project aiming to support researchers throughout the + lifecycle of experiments that can run on a variety of testbeds spanning different + administrative domains and networking technologies. Its basic principle is to bring + together available resources with useful information (characteristics, performance, network measurements). +

+

More Info: http://myslice.info/

+

Code: Git Repository (read only)

+

+ If you need write access to the git repository you need first to send your public key to support@myslice.info. +

+ + +
Manifold (Portal backend)
+

Manifold is the backend that is running behind the portal.

+

Documentation: http://trac.myslice.info/

+

Code: Git Repository (read only)

+ +
OneLab Registry
+

It's a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper (Registry Only mode).

+

More Info: SFA Registry

+
+
+ + + {% endblock %} diff --git a/portal/templates/account-view.html b/portal/templates/account-view.html index f435500c..353a83c2 100644 --- a/portal/templates/account-view.html +++ b/portal/templates/account-view.html @@ -1,4 +1,4 @@ -{% extends "layout.html" %} +{% extends "layout_wide.html" %} {% block content %} @@ -9,156 +9,159 @@ {% endfor %} {% endif %} - -
-

User Account

+ +
+
+ +
-
- - - - {% endblock %} diff --git a/portal/templates/institution.html b/portal/templates/institution.html index ca9fe5a6..8ec395b2 100644 --- a/portal/templates/institution.html +++ b/portal/templates/institution.html @@ -1,70 +1,74 @@ -{% extends "layout.html" %} +{% extends "layout_wide.html" %} + {% block head %} {% endblock head %} + {% block content %} -
-

Institution: {{user_details.parent_authority}}

+ -
- -
-
Loading Authority
- -
- - +
+
+
+
Loading Authority
+ +
+
+ +
+
+
Loading Slices
+ {%if 'is_pi' in pi %} +
+ +
+ {%endif%} +
+
+
+ {%if 'is_pi' in pi %} + + {%else%} + + {%endif%} +
Loading Slices
+ +
{% endblock %} diff --git a/portal/templates/join_view.html b/portal/templates/join_view.html index 576458ad..8576d1a5 100644 --- a/portal/templates/join_view.html +++ b/portal/templates/join_view.html @@ -4,17 +4,22 @@
-

Join Federation Join the OneLab Federation

+
+

Join Federation Join the OneLab Federation

+
- -

+

+

OneLab welcomes companies, universities, and research laboratories to join the OneLab Federation of Testbeds.
+

+

We are supported by the European Commision through its 7th Framework Programs and FIRE initiative (Future Internet Research and Experimentation), as well as by other national and international funding initiatives.

If you wish to become a new member of OneLab Federation, you should first consult the Membership Agreement.

+
{% if errors %} @@ -26,138 +31,150 @@
{% endif %} - +
- + {% csrf_token %} -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+

Postal address

+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ +

Principal Investigator Information

+ +
+ + +
+
+ + -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Site Information

- +
+

Site Information

+ +
+ + +
+
+ + -
 

Principal Investigator Information

 

Postal address

 
-
- +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+

Site Registration Information

+

+ A membership agreement document will be sent to your email address as a PDF file. +

+ Please print and sign a copy of the agreement and send it to: +

+ Ciro Scognamiglio
+ UPMC - LIP6
+ Campus Jussieu
+ Couloir 26-00, bureau 102
+ Boite courrier 169
+ 4 place Jussieu
+ F-75252 PARIS cedex 05 - FRANCE
+

+ Once your membership has been processed we will contact you to welcome you as a member. +

+ If you have any questions about membership, contact the OneLab Support team. +

+
-
-

-A membership agreement document will be sent to your email address as a PDF file. -

-Please print and sign a copy of the agreement and send it to: -

-Ciro Scognamiglio
-UPMC - LIP6
-Campus Jussieu
-Couloir 26-00, bureau 102
-Boite courrier 169
-4 place Jussieu
-F-75252 PARIS cedex 05 - FRANCE
-

-Once your membership has been processed we will contact you to welcome you as a member. -

-If you have any questions about membership, contact the OneLab Support team. -

+
+ +
+ -{% endblock %} diff --git a/portal/templates/onelab/onelab_slice-view.html b/portal/templates/onelab/onelab_slice-view.html index 0444a823..cf9ee7d8 100644 --- a/portal/templates/onelab/onelab_slice-view.html +++ b/portal/templates/onelab/onelab_slice-view.html @@ -6,7 +6,7 @@ {% block content %} -
+
{% include theme|add:"_widget-slice-sections.html" %} diff --git a/portal/templates/onelab/onelab_widget-slice-sections.html b/portal/templates/onelab/onelab_widget-slice-sections.html index 47dea177..bf64b8d8 100644 --- a/portal/templates/onelab/onelab_widget-slice-sections.html +++ b/portal/templates/onelab/onelab_widget-slice-sections.html @@ -1,17 +1,26 @@ -