Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorLoic Baron <loic.baron@lip6.fr>
Mon, 9 Mar 2015 18:53:49 +0000 (19:53 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Mon, 9 Mar 2015 18:53:49 +0000 (19:53 +0100)
Conflicts:
portal/joinview.py
portal/registrationview.py

116 files changed:
.settings/org.eclipse.core.resources.prefs
Makefile
README
auth/static/js/logout.js
debian/deb-cheat-sheet [deleted file]
devel/server-loop.sh
manifoldapi/manifoldapi.py
manifoldapi/static/js/manifold.js
myslice/configengine.py
myslice/myslice.ini.onelab [new file with mode: 0644]
myslice/settings.py
myslice/urls.py
plugins/apply/templates/apply.html
plugins/filter_status/templates/filter_status.html
plugins/scheduler2/static/js/scheduler2.js
plugins/testbeds/static/js/testbeds.js
plugins/testbeds/templates/testbeds.html
portal/accountview.py
portal/actions.py
portal/dashboardview.py
portal/emailactivationview.py
portal/homeview.py
portal/institution.py
portal/managementtababout.py
portal/managementtabrequests.py
portal/manageuserview.py
portal/migrations/0010_project.py [new file with mode: 0644]
portal/migrations/0011_join.py [new file with mode: 0644]
portal/migrations/0012_initial.py [new file with mode: 0644]
portal/models.py
portal/projectrequestview.py [new file with mode: 0644]
portal/registrationview.py
portal/slicerequestview.py
portal/sliceresourceview.py
portal/slicetabexperiment.py
portal/static/css/account_view.css
portal/static/css/fed4fire.css
portal/static/css/jquery-ui.css [new file with mode: 0644]
portal/static/css/onelab.css
portal/static/css/smartfire.css
portal/static/icons/iotlab.png [new file with mode: 0644]
portal/static/icons/mobile.png [new file with mode: 0644]
portal/static/icons/planetlab.png [new file with mode: 0644]
portal/static/icons/wireless.png [new file with mode: 0644]
portal/static/img/bg-smartfire.png [new file with mode: 0644]
portal/static/js/institution.js
portal/static/js/myslice.js
portal/templates/_widget-no_credentials.html [new file with mode: 0644]
portal/templates/_widget-slice-sections.html
portal/templates/_widget-topmenu.html
portal/templates/_widget-tradeoff.html [new file with mode: 0644]
portal/templates/account-view.html
portal/templates/base.html
portal/templates/fed4fire/fed4fire_about.html
portal/templates/fed4fire/fed4fire_account-view.html
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_institution.html
portal/templates/fed4fire/fed4fire_projectrequest_view.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_registration_view.html
portal/templates/fed4fire/fed4fire_slice-tab-experiment.html [deleted file]
portal/templates/fed4fire/fed4fire_slicerequest_view.html
portal/templates/fed4fire/fed4fire_widget-topmenu.html
portal/templates/home-view.html
portal/templates/institution.html
portal/templates/management-tab-requests.html
portal/templates/manageuserview.html
portal/templates/onelab/onelab_account-view.html
portal/templates/onelab/onelab_home-view.html
portal/templates/onelab/onelab_institution.html [deleted file]
portal/templates/onelab/onelab_registration_view.html
portal/templates/onelab/onelab_slicerequest_view.html
portal/templates/onelab/onelab_widget-topmenu.html
portal/templates/project-request-ack-view.html [new file with mode: 0644]
portal/templates/project-request-done-view.html [new file with mode: 0644]
portal/templates/registration_view.html
portal/templates/servicedirectory.html
portal/templates/slice-request-done-view.html
portal/templates/slice-request-view.html [deleted file]
portal/templates/slice-resource-view.html
portal/templates/slice-tab-experiment.html
portal/templates/smartfire/smartfire_account-view.html
portal/templates/smartfire/smartfire_activate_user.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_activate_user.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_authority_request_denied.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_authority_request_denied.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_authority_request_email.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_authority_request_email.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_authority_request_email_subject.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_contact_support_email.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_contact_support_email.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_contact_support_email_subject.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_email_activation.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_email_default_recipients.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_email_default_sender.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_home-view.html
portal/templates/smartfire/smartfire_slice_request_denied.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_slice_request_denied.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_slice_request_email_subject.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_slice_request_validated.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_slice_request_validated.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_denied.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_denied.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_email.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_email.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_email_subject.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_validated.html [new file with mode: 0644]
portal/templates/smartfire/smartfire_user_request_validated.txt [new file with mode: 0644]
portal/templates/smartfire/smartfire_widget-login-user.html
portal/templates/smartfire/smartfire_widget-topmenu.html
portal/templates/user_register_email.txt [deleted file]
portal/templates/user_register_email_subject.txt [deleted file]
portal/urls.py
portal/validationview.py
rest/__init__.py
rest/cache.py [new file with mode: 0644]
sla/urls.py

index f73c991..dad9009 100644 (file)
@@ -2,7 +2,10 @@ 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/migrations/0005_extend_user.py=utf-8
+encoding//portal/migrations/0008_extend_user.py=utf-8
+encoding//portal/migrations/0009_initial.py=utf-8
+encoding//portal/migrations/0010_project.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
index 69725db..80d49c4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -110,8 +110,9 @@ ftags: force
 
 #################### sync : push current code on a box running myslice
 # this for now targets deployments based on the debian packaging
-SSHURL:=root@$(MYSLICEBOX):/
-SSHCOMMAND:=ssh root@$(MYSLICEBOX)
+SSHUSER    ?= root
+SSHURL     := $(SSHUSER)@$(MYSLICEBOX):
+SSHCOMMAND := ssh $(SSHUSER)@$(MYSLICEBOX)
 
 ### rsync options
 # the config file should probably not be overridden ??
@@ -163,3 +164,14 @@ ifeq (,$(MYSLICEBOX))
 else
        +$(SSHCOMMAND) apachectl restart
 endif
+
+#SSHUSER=tparment
+#MYSLICEBOX=srv-diana.inria.fr
+sync-devel:
+ifeq (,$(MYSLICEBOX))
+       @echo "you need to set MYSLICEBOX, like in e.g."
+       @echo "  $(MAKE) MYSLICEBOX=srv-diana.inria.fr "$@""
+       @exit 1
+else
+       +$(RSYNC) --relative $$(git ls-files) $(SSHURL)myslice/
+endif
diff --git a/README b/README
index 8c6e7ef..4e4e195 100644 (file)
--- a/README
+++ b/README
@@ -1,48 +1,66 @@
 This file documents the contents of this module
 change
-Last update 18 DEC. 2014
+Last update 20 FEB. 2015
 
-See the devel/ subdir for more devel-oriented doc.
+Installation
+=================================================================
+Recommended OS
+===============
+Debian GNU/Linux 7.5 (wheezy) x64
 
-==================== 1 minute howto
+PYTHON DEPENDENCIES
+=====================
+sudo apt-get install python-pip or sudo easy_install pip==1.4.1
+sudo apt-get install python-dev (for paramiko and pyOpenSSL)
+sudo apt-get install libffi-dev (for pyOpenSSL)
 
-*  REQUIREMENTS  is to have python + django (1.5.2) installed django
-** should be straightforward
-** see devel/django-install.txt in case of trouble
-$ apt-get install python-pip or sudo easy_install pip==1.4.1
-$ pip install django=="1.5.2
+$ pip install django=="1.5.2"
 $ apt-get install python-django-south
 $ pip install requests
 $ pip install djangorestframework
 $ pip install django-celery
 $ pip install geopy
 $ pip install paramiko
+$ pip install pyparsing
+$ pip install python-dateutil
+$ pip instal pyOpenSSL
 
-* git clone git://git.onelab.eu/myslice.git
--- or --
-* git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
+MYSLICE
+=======
+git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
+cd myslice
+git checkout onelab
 
-* edit/create myslice/myslice.ini and enter the details of your manifold backend
+edit/create myslice/myslice.ini and enter the details of your manifold backend
+
+mkdir /var/unfold
+copy unfold.sqlite3 to /var/unfold
 
-$ apt-get install python-django-south
-* init django
-** when django prompts for creating an admin account, create it and 
-** keep the username and password safe
 $ ./manage.py syncdb
 $ ./manage.py migrate
 
-* gather static files
-$ ./manage.py collectstatic 
--- or --
-$ ./manage.py collectstatic --noinput
--- or --
-$ make static (which is a shorthand for cleaning up and run manage collectstatic --noinput)
+use the unfold.sqlite3 i gave to u
+
+$ make redo
+$ ./devel/server-loop.sh
+
+MANIFOLD
+==========
+git clone git://git.onelab.eu/manifold.git
+cd manifold
+git checkout devel
+make && make install
+
+SFA
+===
+$ git clone -b geni-v3 git://git.onelab.eu/sfa.git
+$ cd sfa 
+$ git checkout geni-v3
 
-* gather templates files 
-  for now we still seem to rely on a make-based templates-collection process
-  that creates templates/ 
-$ make templates [$ make redo (each time when you pull, do that and restart the server)]
+$ make version
+$ python ./setup.py install
 
+=====================================================================
 
 ## Whenever doing a git pull the following operations are recommended:
 
index 593eb58..3419b9d 100644 (file)
@@ -5,7 +5,7 @@ function logout () {
     var msg="Are you sure you want to logout as " + username + " ?";
     /* redirect to /logout, see urls.py */
     if (confirm(msg)){
-        localStorage.removeItem('user');
+        localStorage.clear();
         window.location="/logout/";
     }
 }
diff --git a/debian/deb-cheat-sheet b/debian/deb-cheat-sheet
deleted file mode 100644 (file)
index 3d3f1bc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
---- search package name
-apt-cache search emacs
---- install one package
-apt-get install emacs23-nox
---- preparing upgrade (fetch and index latest versions of the repos)
-apt-get update 
---- actually update one package
-apt-get upgrade myslice
---- list packages
-dpkg -l
-dpkg -l '*foo*'
---- list (files for) one package 
-dpkg -L myslice
-dpkg-deb -c myslice_0.2.4.lxc.2013.11.26_amd64.deb
---- detailed info (e.g. to see complete version that is truncated in dpkg -l)
-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)
-
---- find which package a file belongs to
-apt-file search /path/to/file
-(can be installed with : sudo apt-get install apt-file)
index c77258f..78e1da1 100755 (executable)
@@ -2,9 +2,8 @@
 DIRNAME=$(dirname $0)
 cd $DIRNAME/..
 
-# default port : if hostname starts with z -> use 8080 ; otherwise take 80
-#hostname | grep -q '^z' && port=8080 || port=8080
-hostname | grep -q '^z' && port=8080 || port=80
+# default port : if hostname starts with z or with srv- -> use 8000 ; otherwise take 80
+hostname | egrep -q '^(z|srv-)' && port=8000 || port=80
 [[ -n "$@" ]] && port=$1
 
 while true; do 
index a8b2ab9..8ba7e15 100644 (file)
@@ -41,6 +41,7 @@ class ManifoldAPI:
         self.calls = {}
         self.multicall = False
         self.url = ConfigEngine().manifold_url()
+        # for more debug on this link, set verbose=True
         self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
 
     def __repr__ (self): return "ManifoldAPI[%s]"%self.url
index c880831..517ab69 100644 (file)
@@ -737,6 +737,12 @@ var manifold = {
                 } else {
                     console.log('Unknown field');
                 }
+            // FIX if the record contains a string instead of a key:value 
+            // example: select resource, slice_hrn from slice where slice_hrn=='xxx'
+            // Result will be {slice_hrn:'xxx', resource:'urn+zzz'}
+            // We don't have this resource:{urn:'urn+zzz'}
+            } else if(typeof(record) === 'string'){
+                return record;
             } else {
                 return record[fields];
             }
@@ -979,7 +985,8 @@ var manifold = {
             Loop per platform, allows a progressive loading per AM platform
             Update is run on all platforms at the same time to get a final answer, we don't manage partial answers yet...
         */
-        if((query.object == 'resource' || query.object == 'lease' || query.object == 'slice') && query.action != "update"){
+        // Removed slice from the per platform query - it's quick enough...
+        if((query.object == 'resource' || query.object == 'lease') && query.action != "update"){
             var obj = query.object;
             $.post("/rest/platform/", function( data ) {
                 $.each(data, function(index, p) {
index 3d92bb1..4b40cb2 100644 (file)
@@ -36,7 +36,7 @@ class ConfigEngine(object):
     default_myslice_theme           = 'onelab'
 
     #iotlab dev url
-    default_iotlab_url = "https://devgrenoble.senslab.info/rest/admin/users"
+    default_iotlab_url = "https://devwww.iot-lab.info/rest/admin/users"
     default_iotlab_admin_user = "xxx"
     default_iotlab_admin_password= "yyy"
 
diff --git a/myslice/myslice.ini.onelab b/myslice/myslice.ini.onelab
new file mode 100644 (file)
index 0000000..7cfe494
--- /dev/null
@@ -0,0 +1,2 @@
+[manifold]
+url = https://portal.onelab.eu:7080/
index 5c75970..f9f439e 100644 (file)
@@ -1,5 +1,7 @@
 # Django settings for unfold project.
 
+from __future__ import print_function
+
 import os.path
 
 import djcelery
@@ -13,7 +15,9 @@ except:
     building=True
 
 DEBUG = True
-TEMPLATE_DEBUG = DEBUG
+
+# show the various settings as we go
+DEBUG_SETTINGS = False
 
 # compute ROOT from where this file is installed
 # should fit every need including developers
@@ -48,6 +52,10 @@ except:
 HTTPROOT="/var/www/myslice/"
 # the place to store local data, like e.g. the sqlite db
 DATAROOT="/var/unfold"
+if not os.path.isdir(DATAROOT):
+    print("WARNING: {} is a non-existing directory".format(DATAROOT))
+    print("consequently we assume development mode and re-route DATAROOT to {}".format(ROOT))
+    DATAROOT=ROOT
 # if not there, then we assume it's from a devel tree
 if not os.path.isdir (os.path.join(HTTPROOT,"static")):
     HTTPROOT=ROOT
@@ -55,6 +63,11 @@ if not os.path.isdir (os.path.join(HTTPROOT,"static")):
 if not os.path.isdir(ROOT): raise Exception,"Cannot find ROOT %s for unfold"%ROOT
 if not os.path.isdir(HTTPROOT): raise Exception,"Cannot find HTTPROOT %s for unfold"%HTTPROOT
 
+if DEBUG_SETTINGS:
+    print('ROOT', ROOT)
+    print('DATAROOT', DATAROOT)
+    print('HTTPROOT', HTTPROOT)
+
 # dec 2013 - we currently have 2 auxiliary subdirs with various utilities
 # that we do not wish to package 
 # * sandbox is for plugin developers
@@ -101,6 +114,9 @@ DATABASES = {
     }
 }
 
+if DEBUG_SETTINGS:
+    print('DATABASE NAME',DATABASES['default']['NAME'])
+
 # Local time zone for this installation. Choices can be found here:
 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
 # although not all choices may be available on all operating systems.
@@ -252,7 +268,7 @@ BROKER_URL = "amqp://myslice:myslice@localhost:5672/myslice"
 
 for aux in auxiliaries:
     if os.path.isdir(os.path.join(ROOT,aux)): 
-        print "Using devel auxiliary",aux
+        print("Using devel auxiliary",aux)
         INSTALLED_APPS.append(aux)
 
 ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window; you may, of course, use a different value.
index c815148..ca150a4 100644 (file)
@@ -92,6 +92,7 @@ urls = [
     (r'^create/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.create.dispatch'),
     (r'^delete/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.delete.dispatch'),
     (r'^credentials/(?P<action>[^/]+)/?$', 'rest.credentials.dispatch'),
+    (r'^cache/(?P<action>[^/]+)/?$', 'rest.cache.dispatch'),
     (r'^initscript/(?P<action>[^/]+)/?$', 'rest.initscript.dispatch'),
     #
     # REST monitoring
@@ -131,7 +132,7 @@ urls = [
     url(r'^portal/', include('portal.urls')),
 
     # SLA
-    url(r'^sla/', include('sla.urls')),
+#    url(r'^sla/', include('sla.urls')),
 ]
 
 #this one would not match the convention
index f05af49..9e251b7 100644 (file)
@@ -1,16 +1,18 @@
-<div id={{ domid }}>
-  <!-- Modal - columns selector -->
+<div id="{{ domid }}" class="sl-filter-resources">
+    <button class="btn btn-onelab btn-apply"  id="{{domid}}__apply" data-toggle="modal" data-target="#{{domid}}__apply__window">Apply</button>
+</div> 
+<!-- Modal - columns selector -->
   <div class="modal fade" id="{{domid}}__apply__window" tabindex="-1" role="dialog" aria-labelledby="{{domid}}__apply__label" aria-hidden="true">
     <div class="modal-dialog modal-dialog-large">
       <div class="modal-content">
         <div class="modal-header">
           <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
             <h4 class="modal-title" id="{{domid}}__apply__label">
-                Applying pending changes...                    
+                 Applying pending changes...                
             </h4>
             <div>
-               <img id="applyloading" src="/static/img/loading.gif" /> &nbsp;&nbsp;
-               Please be patient, this operation can take a minute or two.
+                <img id="applyloading" src="/static/img/loading.gif" /> &nbsp;&nbsp;
+                Please be patient, this operation can take a minute or two.
             </div>
         </div>
         <div class="modal-body">
         </div>
       </div>
     </div>
-  </div>
-
-  
-  <!-- Button toolbar -->
-  <button class="btn btn-onelab btn-apply"  id="{{domid}}__apply" data-toggle="modal" data-target="#{{domid}}__apply__window">Apply</button>
-  <!-- <button class="btn btn-default btn-sm" id="{{domid}}__cancel">Cancel</button> -->
-</div> 
+  </div>
\ No newline at end of file
index 8350eb1..3d1c44b 100644 (file)
@@ -1,5 +1,5 @@
-<div id={{ domid }}>
-  <span class="list-group-item-heading sl-resources" style='font-size:inherit;'>View:</span>
+<div id="{{ domid }}" class="sl-filter-resources">
+  <span class="list-group-item-heading sl-resources">View:</span>
   
   <a href="#" 
      class="list-group-item sl-resources active" 
@@ -28,7 +28,7 @@
      title="View resources that you have selected to add to your slice, that require configuration before they can be reserved. Hover you mouse over the symbol next to the checkbox for more details."
      rel='tooltip'>
        Unconfigured
-       <span class="badge" id="badge-unconfigured" style="display:none;"></span></a>
+       <span class="badge" id="badge-unconfigured" style="display:none;"></span>
   </a>
   
   <a href="#" class="list-group-item sl-resources" 
@@ -38,6 +38,6 @@
      title="View pending changes to your slice: resources that you have selected to add, and resources that you have selected to remove. Click on the Apply button to apply those changes, or on the Cancel button to cancel them."
      rel='tooltip'>
        Pending
-       <span class="badge" id="badge-pending" style="display:none;"></span></a>
+       <span class="badge" id="badge-pending" style="display:none;"></span>
   </a>
 </div> 
index 6b55b92..a72341e 100755 (executable)
-/*\r
-#\r
-# Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece\r
-#\r
-# Permission is hereby granted, free of charge, to any person obtaining a copy\r
-# of this software and associated documentation files (the "Software"), to deal\r
-# in the Software without restriction, including without limitation the rights\r
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-# copies of the Software, and to permit persons to whom the Software is\r
-# furnished to do so, subject to the following conditions:\r
-#\r
-# The above copyright notice and this permission notice shall be included in\r
-# all copies or substantial portions of the Software.\r
-#\r
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\r
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-# THE SOFTWARE.\r
-#\r
-#\r
-# This is a MySlice plugin for the NITOS Scheduler\r
-# Nitos Scheduler v1\r
-#\r
-*/\r
-\r
-// XXX groupid = all slots those that go with a min granularity\r
-\r
-/* some params */\r
-var scheduler2;\r
-var scheduler2Instance;\r
-//is ctrl keyboard button pressed\r
-var schedulerCtrlPressed = false;\r
-//table Id\r
-var schedulerTblId = "scheduler-reservation-table";\r
-var SCHEDULER_FIRST_COLWIDTH = 200;\r
-\r
-\r
-/* Number of scheduler slots per hour. Used to define granularity. Should be inferred from resources XXX */\r
-var schedulerSlotsPerHour = 6;\r
-var RESOURCE_DEFAULT_GRANULARITY    = 1800 /* s */; // should be computed automatically from resource information\r
-var DEFAULT_GRANULARITY             = 1800 /* s */; // should be computed automatically from resource information. Test with 600\r
-var DEFAULT_PAGE_RANGE = 5;\r
-\r
-var schedulerMaxRows = 12;\r
-\r
-/* All resources */\r
-var SchedulerData = [];\r
-\r
-/* ??? */\r
-var SchedulerSlots = [];\r
-\r
-var SchedulerDateSelected = new Date();\r
-// Round to midnight\r
-SchedulerDateSelected.setHours(0,0,0,0);\r
-\r
-/* Filtered resources */\r
-var SchedulerDataViewData = [];\r
-\r
-var SchedulerSlotsViewData = [];\r
-//Help Variables\r
-var _schedulerCurrentCellPosition = 0;\r
-//Enable Debug\r
-var schedulerDebug = true;\r
-//tmp to delete\r
-var tmpSchedulerLeases = [];\r
-\r
-var SCHEDULER_COLWIDTH = 50;\r
-\r
-\r
-/******************************************************************************\r
- *                             ANGULAR CONTROLLER                             *\r
- ******************************************************************************/\r
-\r
-// Create a private execution space for our controller. When\r
-// executing this function expression, we're going to pass in\r
-// the Angular reference and our application module.\r
-(function (ng, app) {\r
-\r
-    // Define our Controller constructor.\r
-    function Controller($scope) {\r
-\r
-        // Store the scope so we can reference it in our\r
-        // class methods\r
-        this.scope = $scope;\r
-\r
-        // Set up the default scope value.\r
-        this.scope.errorMessage = null;\r
-        this.scope.name = "";\r
-\r
-        //Pagin\r
-        $scope.current_page = 1;\r
-        this.scope.items_per_page = 10;\r
-        $scope.from = 0; // JORDAN\r
-\r
-        $scope.instance = null;\r
-        $scope.resources = new Array();\r
-        $scope.slots = SchedulerSlotsViewData;\r
-        $scope.granularity = DEFAULT_GRANULARITY; /* Will be setup */\r
-        //$scope.msg = "hello";\r
-\r
-        angular.element(document).ready(function() {\r
-            //console.log('Hello World');\r
-            //alert('Hello World');\r
-            //afterAngularRendered();\r
-        });\r
-\r
-        // Pagination\r
-\r
-        $scope.range = function() {\r
-            var range_size = $scope.page_count() > DEFAULT_PAGE_RANGE ? DEFAULT_PAGE_RANGE : $scope.page_count();\r
-            var ret = [];\r
-            var start;\r
-\r
-            start = $scope.current_page;\r
-            if ( start > $scope.page_count()-range_size ) {\r
-              start = $scope.page_count()-range_size+1;\r
-            }\r
-\r
-            for (var i=start; i<start+range_size; i++) {\r
-              ret.push(i);\r
-            }\r
-            return ret;\r
-        };\r
-\r
-        $scope.prevPage = function() {\r
-          if ($scope.current_page > 1) {\r
-            $scope.current_page--;\r
-          }\r
-        };\r
-\r
-        $scope.prevPageDisabled = function() {\r
-          return $scope.current_page === 1 ? "disabled" : "";\r
-        };\r
-  \r
-        $scope.page_count = function()\r
-        {\r
-            // XXX need visible resources only\r
-            var query_ext, visible_resources_length;\r
-            if (!$scope.instance)\r
-                return 0;\r
-            query_ext = manifold.query_store.find_analyzed_query_ext($scope.instance.options.query_uuid);\r
-            var visible_resources_length = 0;\r
-            query_ext.state.each(function(i, state) {\r
-                if (state[STATE_VISIBLE])\r
-                    visible_resources_length++;\r
-            });\r
-            return Math.ceil(visible_resources_length/$scope.items_per_page);\r
-        };\r
-  \r
-        $scope.nextPage = function() {\r
-          if ($scope.current_page < $scope.page_count()) {\r
-            $scope.current_page++;\r
-          }\r
-        };\r
-  \r
-        $scope.nextPageDisabled = function() {\r
-          return $scope.current_page === $scope.page_count() ? "disabled" : "";\r
-        }; \r
-\r
-        $scope.setPage = function(n) {\r
-            $scope.current_page = n;\r
-        };\r
-        // END pagination\r
-\r
-        // FILTER\r
-\r
-        $scope.filter_visible = function(resource)\r
-        {\r
-            return manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource['urn'], STATE_VISIBLE);\r
-        };\r
-\r
-        // SELECTION\r
-\r
-        $scope._create_new_lease = function(resource_urn, start_time, end_time)\r
-        {\r
-            var lease_key, new_lease, data;\r
-\r
-            lease_key = manifold.metadata.get_key('lease');\r
-\r
-            new_lease = {\r
-                resource:   resource_urn,\r
-                start_time: start_time,\r
-                end_time:   end_time,\r
-            };\r
-\r
-            // This is needed to create a hashable object\r
-            new_lease.hashCode = manifold.record_hashcode(lease_key.sort());\r
-            new_lease.equals   = manifold.record_equals(lease_key);\r
-\r
-            data = {\r
-                state: STATE_SET,\r
-                key  : null,\r
-                op   : STATE_SET_ADD,\r
-                value: new_lease\r
-            }\r
-            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
-            /* Add to local cache also, unless we listen to events from outside */\r
-            if (!(resource_urn in $scope._leases_by_resource))\r
-                $scope._leases_by_resource[resource_urn] = [];\r
-            $scope._leases_by_resource[resource_urn].push(new_lease);\r
-        }\r
-\r
-        $scope._remove_lease = function(other)\r
-        {\r
-            var lease_key, other_key, data;\r
-\r
-            lease_key = manifold.metadata.get_key('lease');\r
-\r
-            // XXX This could be a manifold.record_get_value\r
-            other_key = {\r
-                resource:   other.resource,\r
-                start_time: other.start_time,\r
-                end_time:   other.end_time\r
-            }\r
-            other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
-            other_key.equals   = manifold.record_equals(lease_key);\r
-\r
-            data = {\r
-                state: STATE_SET,\r
-                key  : null,\r
-                op   : STATE_SET_REMOVE,\r
-                value: other_key\r
-            }\r
-            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
-            /* Remove from local cache also, unless we listen to events from outside */\r
-            $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });\r
-\r
-        }\r
-\r
-        $scope.select = function(index, model_lease, model_resource)\r
-        {\r
-            var data, resource_granularity;\r
-\r
-            //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity;\r
-\r
-            console.log("Selected", index, model_lease, model_resource);\r
-\r
-            var day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
-            var start_time = day_timestamp + index       * model_resource.granularity; // XXX resource_granularity\r
-            var end_time   = day_timestamp + (index + 1) * model_resource.granularity; //\r
-            var start_date = new Date(start_time * 1000);\r
-            var end_date   = new Date(end_time   * 1000);\r
-\r
-            var lease_key = manifold.metadata.get_key('lease');\r
-\r
-            // We search for leases in the cache we previously constructed\r
-            var resource_leases = $scope._leases_by_resource[model_resource.urn];\r
-\r
-            switch (model_lease.status)\r
-            {\r
-                case 'free': // out\r
-                case 'pendingout':\r
-                    if (resource_leases) {\r
-                        /* Search for leases before */\r
-                        $.each(resource_leases, function(i, other) {\r
-                            if (other.end_time != start_time)\r
-                                return true; // ~ continue\r
-        \r
-                            /* The lease 'other' is just before, and there should not exist\r
-                             * any other lease before it */\r
-                            start_time = other.start_time;\r
-        \r
-                            other_key = {\r
-                                resource:   other.resource,\r
-                                start_time: other.start_time,\r
-                                end_time:   other.end_time\r
-                            }\r
-                            // This is needed to create a hashable object\r
-                            other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
-                            other_key.equals   = manifold.record_equals(lease_key);\r
-        \r
-                            data = {\r
-                                state: STATE_SET,\r
-                                key  : null,\r
-                                op   : STATE_SET_REMOVE,\r
-                                value: other_key\r
-                            }\r
-                            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
-                            /* Remove from local cache also, unless we listen to events from outside */\r
-                            $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
-                            return false; // ~ break\r
-                        });\r
-        \r
-                        /* Search for leases after */\r
-                        $.each(resource_leases, function(i, other) {\r
-                            if (other.start_time != end_time)\r
-                                return true; // ~ continue\r
-        \r
-                            /* The lease 'other' is just after, and there should not exist\r
-                             * any other lease after it */\r
-                            end_time = other.end_time;\r
-                            other_key = {\r
-                                resource:   other.resource,\r
-                                start_time: other.start_time,\r
-                                end_time:   other.end_time\r
-                            }\r
-                            // This is needed to create a hashable object\r
-                            other_key.hashCode = manifold.record_hashcode(lease_key.sort());\r
-                            other_key.equals   = manifold.record_equals(lease_key);\r
-        \r
-                            data = {\r
-                                state: STATE_SET,\r
-                                key  : null,\r
-                                op   : STATE_SET_REMOVE,\r
-                                value: other_key\r
-                            }\r
-                            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);\r
-                            /* Remove from local cache also, unless we listen to events from outside */\r
-                            $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });\r
-                            return false; // ~ break\r
-                        });\r
-                    }\r
-        \r
-                    $scope._create_new_lease(model_resource.urn, start_time, end_time);\r
-                    model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected';\r
-                    // unless the exact same lease already existed (pending_out status for the lease, not the cell !!)\r
-\r
-                    break;\r
-\r
-                case 'selected':\r
-                case 'pendingin':\r
-                    // We remove the cell\r
-\r
-                    /* We search for leases including this cell. Either 0, 1 or 2.\r
-                     * 0 : NOT POSSIBLE, should be checked.\r
-                     * 1 : either IN or OUT, we have make no change in the session\r
-                     * 2 : both will be pending, since we have made a change in the session\r
-                    * /!\ need to properly remove pending_in leases when removed again\r
-                     */\r
-                    if (resource_leases) {\r
-                        $.each(resource_leases, function(i, other) {\r
-                            if ((other.start_time <= start_time) && (other.end_time >= end_time)) {\r
-                                // The cell is part of this lease.\r
-\r
-                                // If the cell is not at the beginning of the lease, we recreate a lease with cells before\r
-                                if (start_time > other.start_time) {\r
-                                    $scope._create_new_lease(model_resource.urn, other.start_time, start_time);\r
-                                }\r
-\r
-                                // If the cell is not at the end of the lease, we recreate a lease with cells after\r
-                                if (end_time < other.end_time) {\r
-                                    $scope._create_new_lease(model_resource.urn, end_time, other.end_time);\r
-                                }\r
-                                \r
-                                // The other lease will be removed\r
-                                $scope._remove_lease(other);\r
-                            }\r
-                            // NOTE: We can interrupt the search if we know that there is a single lease (depending on the status).\r
-                        });\r
-                    }\r
-                \r
-                    // cf comment in previous switch case\r
-                    model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free';\r
-\r
-                    break;\r
-\r
-                case 'reserved':\r
-                case 'maintainance':\r
-                    // Do nothing\r
-                    break;\r
-            }\r
-            \r
-\r
-            $scope._dump_leases();\r
-        };\r
-  \r
-        $scope._dump_leases = function()\r
-        {\r
-            // DEBUG: display all leases and their status in the log\r
-            var leases = manifold.query_store.get_records($scope.instance.options.query_lease_uuid);\r
-            console.log("--------------------");\r
-            $.each(leases, function(i, lease) {\r
-                var key = manifold.metadata.get_key('lease');\r
-                var lease_key = manifold.record_get_value(lease, key);\r
-                var state = manifold.query_store.get_record_state($scope.instance.options.query_lease_uuid, lease_key, STATE_SET);\r
-                var state_str;\r
-                switch(state) {\r
-                    case STATE_SET_IN:\r
-                        state_str = 'STATE_SET_IN';\r
-                        break;\r
-                    case STATE_SET_OUT:\r
-                        state_str = 'STATE_SET_OUT';\r
-                        break;\r
-                    case STATE_SET_IN_PENDING:\r
-                        state_str = 'STATE_SET_IN_PENDING';\r
-                        break;\r
-                    case STATE_SET_OUT_PENDING:\r
-                        state_str = 'STATE_SET_OUT_PENDING';\r
-                        break;\r
-                    case STATE_SET_IN_SUCCESS:\r
-                        state_str = 'STATE_SET_IN_SUCCESS';\r
-                        break;\r
-                    case STATE_SET_OUT_SUCCESS:\r
-                        state_str = 'STATE_SET_OUT_SUCCESS';\r
-                        break;\r
-                    case STATE_SET_IN_FAILURE:\r
-                        state_str = 'STATE_SET_IN_FAILURE';\r
-                        break;\r
-                    case STATE_SET_OUT_FAILURE:\r
-                        state_str = 'STATE_SET_OUT_FAILURE';\r
-                        break;\r
-                }\r
-                console.log("LEASE", new Date(lease.start_time * 1000), new Date(lease.end_time * 1000), lease.resource, state_str);\r
-            });\r
-        };\r
-\r
-        // Return this object reference.\r
-        return (this);\r
-\r
-    }\r
-\r
-    // Define the Controller as the constructor function.\r
-    app.controller("SchedulerCtrl", Controller);\r
-\r
-})(angular, ManifoldApp);\r
-\r
-/******************************************************************************\r
- *                              MANIFOLD PLUGIN                               *\r
- ******************************************************************************/\r
-\r
-(function($) {\r
-        scheduler2 = Plugin.extend({\r
-\r
-            /** XXX to check\r
-         * @brief Plugin constructor\r
-         * @param options : an associative array of setting values\r
-         * @param element : \r
-         * @return : a jQuery collection of objects on which the plugin is\r
-         *     applied, which allows to maintain chainability of calls\r
-         */\r
-            init: function(options, element) {\r
-                // Call the parent constructor, see FAQ when forgotten\r
-                this._super(options, element);\r
-\r
-                var scope = this._get_scope()\r
-                scope.instance = this;\r
-\r
-                // XXX not needed\r
-                scheduler2Instance = this;\r
-\r
-                // We need to remember the active filter for datatables filtering\r
-                // XXX not needed\r
-                this.filters = Array();\r
-\r
-                // XXX BETTER !!!!\r
-                $(window).delegate('*', 'keypress', function (evt){\r
-                        alert("erm");\r
-                      });\r
-\r
-                $(window).keydown(function(evt) {\r
-                    if (evt.which == 17) { // ctrl\r
-                        schedulerCtrlPressed = true;\r
-                    }\r
-                }).keyup(function(evt) {\r
-                    if (evt.which == 17) { // ctrl\r
-                        schedulerCtrlPressed = false;\r
-                    }\r
-                });\r
-\r
-                // XXX naming\r
-                //$("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);\r
-\r
-                this._resources_received = false;\r
-                this._leases_received = false;\r
-                \r
-                scope._leases_by_resource = {};\r
-\r
-                /* Listening to queries */\r
-                this.listen_query(options.query_uuid, 'resources');\r
-                this.listen_query(options.query_lease_uuid, 'leases');\r
-\r
-                this.elmt().on('show', this, this.on_show);\r
-                this.elmt().on('shown.bs.tab', this, this.on_show);\r
-                this.elmt().on('resize', this, this.on_resize);\r
-\r
-                /* Generate slots according to the default granularity. Should\r
-                 * be updated when resources arrive.  Should be the pgcd in fact XXX */\r
-                this._granularity = DEFAULT_GRANULARITY;\r
-                scope.granularity = this._granularity;\r
-                this.scope_resources_by_key = {};\r
-\r
-                this.do_resize();\r
-    \r
-                scope.from = 0;\r
-\r
-                this._initUI();\r
-\r
-            },\r
-\r
-            do_resize: function()\r
-            {\r
-                var scope = this._get_scope();\r
-                var num_hidden_cells, new_max, lcm;\r
-\r
-                // do_resize has to be called when the window is resized, or one parameter changes\r
-                // e.g. when new resources have been received\r
-                //\r
-                this.resource_granularities = [3600, 1800]; //, 2400]; /* s */\r
-\r
-                /* Compute the slot length to accommodate all resources. This\r
-                 * is the GCD of all resource granularities. */\r
-                this._slot_length = this._gcdn(this.resource_granularities);\r
-\r
-                $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH);\r
-                //self get width might need fix depending on the template \r
-                var tblwidth = $('#scheduler-reservation-table').parent().outerWidth();\r
-\r
-                /* Number of visible cells...*/\r
-                this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH);\r
-\r
-                /* ...should be a multiple of the lcm of all encountered granularities. */\r
-                lcm = this._lcmn(this.resource_granularities) / this._slot_length;\r
-                this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm;\r
-\r
-                // A list of {id, time} dictionaries representing the slots for the given day\r
-                this._all_slots = this._generate_all_slots();\r
-\r
-                /* scope also needs this value */\r
-                scope.slots = this._all_slots;\r
-                scope.slot_length = this._slot_length;\r
-                scope.num_visible_cells = this._num_visible_cells;\r
-                scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ?\r
-\r
-                /* Redraw... */\r
-                this._scope_clear_leases();\r
-                this._set_all_lease_slots();\r
-\r
-                // Slider max value\r
-                if ($('#tblSlider').data('slider') != undefined) {\r
-                    num_hidden_cells = this._all_slots.length - this._num_visible_cells;\r
-\r
-                    $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells);\r
-                    $('#tblSlider').slider('setValue', scope.from, true);\r
-                }\r
-                this._get_scope().$apply();\r
-\r
-\r
-            },\r
-\r
-            on_show: function(e)\r
-            {\r
-                var self = e.data;\r
-                self.do_resize();\r
-                self._get_scope().$apply();\r
-            },\r
-\r
-            on_resize: function(e)\r
-            {\r
-                var self = e.data;\r
-                self.do_resize();\r
-                self._get_scope().$apply();\r
-            },\r
-\r
-            /* Handlers */\r
-\r
-            _get_scope : function()\r
-            {\r
-                return angular.element(document.getElementById('SchedulerCtrl')).scope();\r
-            },\r
-            \r
-            _scope_set_resources : function()\r
-            {\r
-                var self = this;\r
-                var scope = this._get_scope();\r
-\r
-                var records = manifold.query_store.get_records(this.options.query_uuid);\r
-\r
-                scope.resources = [];\r
-\r
-                $.each(records, function(i, record) {\r
-                    if (!record.exclusive)\r
-                        return true; // ~ continue\r
-\r
-                    // copy not to modify original record\r
-                    var resource = jQuery.extend(true, {}, record);\r
-\r
-                    // Fix granularity\r
-                    //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity;\r
-                    if (typeof(resource.granularity) != "number")\r
-                        resource.granularity = RESOURCE_DEFAULT_GRANULARITY;\r
-                    resource.leases = []; // a list of occupied timeslots\r
-\r
-                    self.scope_resources_by_key[resource['urn']] = resource;\r
-                    scope.resources.push(resource);\r
-                });\r
-            },\r
-\r
-            _scope_clear_leases: function()\r
-            {\r
-                var time, now;\r
-                var self = this;\r
-                var scope = this._get_scope();\r
-\r
-                now = new Date().getTime();\r
-\r
-                // Setup leases with a default free status...\r
-                $.each(this.scope_resources_by_key, function(resource_key, resource) {\r
-                    resource.leases = [];\r
-                    var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells\r
-                    time = SchedulerDateSelected.getTime();\r
-                    for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity\r
-                        resource.leases.push({\r
-                            id:     'coucou',\r
-                            status: (time < now) ? 'disabled':  'free', // 'selected', 'reserved', 'maintenance' XXX pending ??\r
-                        });\r
-                        time += resource.granularity * 1000;\r
-                    }\r
-                });\r
-\r
-            },\r
-\r
-            _scope_set_leases: function()\r
-            {\r
-                    var status;\r
-                var self = this;\r
-                var scope = this._get_scope();\r
-            \r
-                manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
-                    console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000));\r
-                    // XXX We should ensure leases are correctly merged, otherwise our algorithm won't work\r
-\r
-                    // Populate leases by resource array: this will help us merging leases later\r
-\r
-                    // let's only put _our_ leases\r
-                    lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET);\r
-                    if (lease_status != STATE_SET_IN)\r
-                        return true; // ~continue\r
-                    if (!(lease.resource in scope._leases_by_resource))\r
-                        scope._leases_by_resource[lease.resource] = [];\r
-                    scope._leases_by_resource[lease.resource].push(lease);\r
-\r
-                });\r
-\r
-                this._set_all_lease_slots();\r
-            },\r
-\r
-            _set_all_lease_slots: function()\r
-            {\r
-                var self = this;\r
-            \r
-                manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {\r
-                    self._set_lease_slots(lease_key, lease);\r
-                });\r
-            },\r
-\r
-            on_resources_query_done: function(data)\r
-            {\r
-                this._resources_received = true;\r
-                this._scope_set_resources();\r
-                this._scope_clear_leases();\r
-                if (this._leases_received)\r
-                    this._scope_set_leases();\r
-                    \r
-                this._get_scope().$apply();\r
-            },\r
-\r
-            on_leases_query_done: function(data)\r
-            {\r
-                this._leases_received = true;\r
-                if (this._resources_received) {\r
-                    this._scope_set_leases();\r
-                    this._get_scope().$apply();\r
-                }\r
-            },\r
-\r
-            /* Filters on resources */\r
-            on_resources_filter_added:   function(filter) { this._get_scope().$apply(); },\r
-            on_resources_filter_removed: function(filter) { this._get_scope().$apply(); },\r
-            on_resources_filter_clear:   function()       { this._get_scope().$apply(); },\r
-\r
-            /* Filters on leases ? */\r
-            on_leases_filter_added:      function(filter) { this._get_scope().$apply(); },\r
-            on_leases_filter_removed:    function(filter) { this._get_scope().$apply(); },\r
-            on_leases_filter_clear:      function()       { this._get_scope().$apply(); },\r
-\r
-            on_field_state_changed: function(data)\r
-            {\r
-                /*\r
-                this._set_lease_slots(lease_key, lease);\r
-\r
-                switch(data.state) {\r
-                    case STATE_SET:\r
-                        switch(data.op) {\r
-                            case STATE_SET_IN:\r
-                            case STATE_SET_IN_SUCCESS:\r
-                            case STATE_SET_OUT_FAILURE:\r
-                                this.set_checkbox_from_data(data.value, true);\r
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
-                                break;  \r
-                            case STATE_SET_OUT:\r
-                            case STATE_SET_OUT_SUCCESS:\r
-                            case STATE_SET_IN_FAILURE:\r
-                                this.set_checkbox_from_data(data.value, false);\r
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);\r
-                                break;\r
-                            case STATE_SET_IN_PENDING:\r
-                                this.set_checkbox_from_data(data.key, true);\r
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);\r
-                                break;  \r
-                            case STATE_SET_OUT_PENDING:\r
-                                this.set_checkbox_from_data(data.key, false);\r
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);\r
-                                break;\r
-                        }\r
-                        break;\r
-\r
-                    case STATE_WARNINGS:\r
-                        this.change_status(data.key, data.value);\r
-                        break;\r
-                }\r
-                */\r
-            },\r
-\r
-\r
-            /* INTERNAL FUNCTIONS */\r
-\r
-            _set_lease_slots: function(lease_key, lease)\r
-            {\r
-                var resource, lease_status, lease_class;\r
-                var day_timestamp, id_start, id_end, colspan_lease;\r
-\r
-                resource = this.scope_resources_by_key[lease.resource];\r
-                day_timestamp = SchedulerDateSelected.getTime() / 1000;\r
-                id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity);\r
-\r
-                /* Some leases might be in the past */\r
-                if (id_start < 0)\r
-                    id_start = 0;\r
-                /* Leases in the future: ignore */\r
-                if (id_start >= this._all_slots.length)\r
-                    return true; // ~ continue\r
-\r
-                id_end   = Math.ceil((lease.end_time   - day_timestamp) / resource.granularity);\r
-                colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells\r
-                if (id_end >= this._all_slots.length / colspan_lease) {\r
-                    /* Limit the display to the current day */\r
-                    id_end = this._all_slots.length / colspan_lease\r
-                }\r
-                lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET);\r
-                // the same slots might be affected multiple times.\r
-                // PENDING_IN + PENDING_OUT => IN \r
-                //\r
-                // RESERVED vs SELECTED !\r
-                //\r
-                // PENDING !!\r
-                switch(lease_status) {\r
-                    case STATE_SET_IN:\r
-                        lease_class = 'selected'; // my leases\r
-                        lease_success = '';\r
-                        break;\r
-                    case STATE_SET_IN_SUCCESS:\r
-                        lease_class = 'selected'; // my leases\r
-                        lease_success = 'success';\r
-                    case STATE_SET_OUT_FAILURE:\r
-                        lease_class = 'selected'; // my leases\r
-                        lease_success = 'failure';\r
-                        break;\r
-                    case STATE_SET_OUT:\r
-                        lease_class = 'reserved'; // other leases\r
-                        lease_success = '';\r
-                        break;\r
-                    case STATE_SET_OUT_SUCCESS:\r
-                        lease_class = 'free'; // other leases\r
-                        lease_success = 'success';\r
-                        break;\r
-                    case STATE_SET_IN_FAILURE:\r
-                        lease_class = 'free'; // other leases\r
-                        lease_success = 'failure';\r
-                        break;\r
-                    case STATE_SET_IN_PENDING:\r
-                        lease_class = 'pendingin';\r
-                        lease_success = '';\r
-                        break;\r
-                    case STATE_SET_OUT_PENDING:\r
-                        // pending_in & pending_out == IN == replacement\r
-                        if (resource.leases[i].status == 'pendingin')\r
-                            lease_class = 'pendingin'\r
-                        else\r
-                            lease_class = 'pendingout';\r
-                        lease_success = '';\r
-                        break;\r
-                \r
-                }\r
-\r
-                for (i = id_start; i < id_end; i++) {\r
-                    resource.leases[i].status = lease_class;\r
-                    resource.leases[i].success = lease_success;\r
-                }\r
-            },\r
-\r
-/* XXX IN TEMPLATE XXX\r
-                if (SchedulerDataViewData.length == 0) {\r
-                    $("#plugin-scheduler").hide();\r
-                    $("#plugin-scheduler-empty").show();\r
-                    tmpScope.clearStuff();\r
-                } else {\r
-                    $("#plugin-scheduler-empty").hide();\r
-                    $("#plugin-scheduler").show();\r
-                    // initSchedulerResources\r
-                    tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);\r
-                }\r
-*/\r
-\r
-            /**\r
-             * Initialize the date picker, the table, the slider and the buttons. Once done, display scheduler.\r
-             */\r
-            _initUI: function() \r
-            {\r
-                var self = this;\r
-                var scope = self._get_scope();\r
-\r
-                var num_hidden_cells;\r
-\r
-                $("#DateToRes").datepicker({\r
-                       dateFormat: "D, d M yy",\r
-                    onRender: function(date) {\r
-                        return date.valueOf() < now.valueOf() ? 'disabled' : '';\r
-                    }\r
-                }).on('changeDate', function(ev) {\r
-                    SchedulerDateSelected = new Date(ev.date);\r
-                    SchedulerDateSelected.setHours(0,0,0,0);\r
-                    // Set slider to origin\r
-                    //$('#tblSlider').slider('setValue', 0); // XXX\r
-                    // Refresh leases\r
-                    self._scope_clear_leases();\r
-                    self._set_all_lease_slots();\r
-                    // Refresh display\r
-                    self._get_scope().$apply();\r
-                }).datepicker('setValue', SchedulerDateSelected); //.data('datepicker');\r
-\r
-                //init Slider\r
-                num_hidden_cells = self._all_slots.length - self._num_visible_cells;\r
-                init_cell = (new Date().getHours() - 1) * 3600 / self._granularity;\r
-                if (init_cell > num_hidden_cells)\r
-                    init_cell = num_hidden_cells;\r
-\r
-                $('#tblSlider').slider({\r
-                    min: 0,\r
-                    max: num_hidden_cells,\r
-                    value: init_cell,\r
-                }).on('slide', function(ev) {\r
-                    var scope = self._get_scope();\r
-                    scope.from = ev.value;\r
-                    scope.$apply();\r
-                });\r
-                scope.from = init_cell;\r
-                scope.$apply();\r
-\r
-                $("#plugin-scheduler-loader").hide();\r
-                $("#plugin-scheduler").show();\r
-            },\r
-\r
-        // PRIVATE METHODS\r
-\r
-        /**\r
-         * Greatest common divisor\r
-         */\r
-        _gcd : function(x, y)\r
-        {\r
-            return (y==0) ? x : this._gcd(y, x % y);\r
-        },\r
-\r
-        _gcdn : function(array)\r
-        {\r
-            var self = this;\r
-            return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); });\r
-        },\r
-\r
-        /**\r
-         * Least common multiple\r
-         */\r
-        _lcm : function(x, y)\r
-        {\r
-            return x * y / this._gcd(x, y);\r
-        },\r
-\r
-        _lcmn : function(array)\r
-        {\r
-            var self = this;\r
-            return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); });\r
-        },\r
-    \r
-        _pad_str : function(i)\r
-        {\r
-            return (i < 10) ? "0" + i : "" + i;\r
-        },\r
-\r
-        /**\r
-         * Member variables used:\r
-         *   _granularity\r
-         * \r
-         * Returns:\r
-         *   A list of {id, time} dictionaries.\r
-         */\r
-        _generate_all_slots: function()\r
-        {\r
-            var slots = [];\r
-            // Start with a random date (a first of a month), only time will matter\r
-            var d = new Date(2014, 1, 1, 0, 0, 0, 0);\r
-            var i = 0;\r
-            // Loop until we change the day\r
-            while (d.getDate() == 1) {\r
-                // Nicely format the time...\r
-                var tmpTime = this._pad_str(d.getHours()) + ':' + this._pad_str(d.getMinutes());\r
-                /// ...and add the slot to the list of results\r
-                slots.push({ id: i, time: tmpTime });\r
-                // Increment the date with the granularity\r
-                d = new Date(d.getTime() + this._slot_length * 1000);\r
-                i++;\r
-            }\r
-            return slots;\r
-\r
-        },\r
-    });\r
-\r
-    /* Plugin registration */\r
-    $.plugin('Scheduler2', scheduler2);\r
-\r
-})(jQuery);\r
-\r
-\r
-\r
+/*
+#
+# Copyright (c) 2013 NITLab, University of Thessaly, CERTH, Greece
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+# This is a MySlice plugin for the NITOS Scheduler
+# Nitos Scheduler v1
+#
+*/
+
+// XXX groupid = all slots those that go with a min granularity
+
+/* some params */
+var scheduler2;
+var scheduler2Instance;
+//is ctrl keyboard button pressed
+var schedulerCtrlPressed = false;
+//table Id
+var schedulerTblId = "scheduler-reservation-table";
+var SCHEDULER_FIRST_COLWIDTH = 200;
+
+
+/* Number of scheduler slots per hour. Used to define granularity. Should be inferred from resources XXX */
+var schedulerSlotsPerHour = 6;
+var RESOURCE_DEFAULT_GRANULARITY    = 1800 /* s */; // should be computed automatically from resource information
+var DEFAULT_GRANULARITY             = 1800 /* s */; // should be computed automatically from resource information. Test with 600
+var DEFAULT_PAGE_RANGE = 5;
+
+var schedulerMaxRows = 12;
+
+/* All resources */
+var SchedulerData = [];
+
+/* ??? */
+var SchedulerSlots = [];
+
+var SchedulerDateSelected = new Date();
+// Round to midnight
+SchedulerDateSelected.setHours(0,0,0,0);
+
+/* Filtered resources */
+var SchedulerDataViewData = [];
+
+var SchedulerSlotsViewData = [];
+//Help Variables
+var _schedulerCurrentCellPosition = 0;
+//Enable Debug
+var schedulerDebug = true;
+//tmp to delete
+var tmpSchedulerLeases = [];
+
+var SCHEDULER_COLWIDTH = 50;
+
+
+/******************************************************************************
+ *                             ANGULAR CONTROLLER                             *
+ ******************************************************************************/
+
+// Create a private execution space for our controller. When
+// executing this function expression, we're going to pass in
+// the Angular reference and our application module.
+(function (ng, app) {
+
+    // Define our Controller constructor.
+    function Controller($scope) {
+
+        // Store the scope so we can reference it in our
+        // class methods
+        this.scope = $scope;
+
+        // Set up the default scope value.
+        this.scope.errorMessage = null;
+        this.scope.name = "";
+
+        //Pagin
+        $scope.current_page = 1;
+        this.scope.items_per_page = 10;
+        $scope.from = 0; // JORDAN
+
+        $scope.instance = null;
+        $scope.resources = new Array();
+        $scope.slots = SchedulerSlotsViewData;
+        $scope.granularity = DEFAULT_GRANULARITY; /* Will be setup */
+        //$scope.msg = "hello";
+
+        angular.element(document).ready(function() {
+            //console.log('Hello World');
+            //alert('Hello World');
+            //afterAngularRendered();
+        });
+
+        // Pagination
+
+        $scope.range = function() {
+            var range_size = $scope.page_count() > DEFAULT_PAGE_RANGE ? DEFAULT_PAGE_RANGE : $scope.page_count();
+            var ret = [];
+            var start;
+
+            start = $scope.current_page;
+            if ( start > $scope.page_count()-range_size ) {
+              start = $scope.page_count()-range_size+1;
+            }
+
+            for (var i=start; i<start+range_size; i++) {
+              ret.push(i);
+            }
+            return ret;
+        };
+
+        $scope.prevPage = function() {
+          if ($scope.current_page > 1) {
+            $scope.current_page--;
+          }
+        };
+
+        $scope.prevPageDisabled = function() {
+          return $scope.current_page === 1 ? "disabled" : "";
+        };
+  
+        $scope.page_count = function()
+        {
+            // XXX need visible resources only
+            var query_ext, visible_resources_length;
+            if (!$scope.instance)
+                return 0;
+            query_ext = manifold.query_store.find_analyzed_query_ext($scope.instance.options.query_uuid);
+            var visible_resources_length = 0;
+            query_ext.state.each(function(i, state) {
+                if (state[STATE_VISIBLE])
+                    visible_resources_length++;
+            });
+            return Math.ceil(visible_resources_length/$scope.items_per_page);
+        };
+  
+        $scope.nextPage = function() {
+          if ($scope.current_page < $scope.page_count()) {
+            $scope.current_page++;
+          }
+        };
+  
+        $scope.nextPageDisabled = function() {
+          return $scope.current_page === $scope.page_count() ? "disabled" : "";
+        }; 
+
+        $scope.setPage = function(n) {
+            $scope.current_page = n;
+        };
+        // END pagination
+
+        // FILTER
+
+        $scope.filter_visible = function(resource)
+        {
+            return manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource['urn'], STATE_VISIBLE);
+        };
+
+        // SELECTION
+
+        $scope._create_new_lease = function(resource_urn, start_time, end_time)
+        {
+            var lease_key, new_lease, data;
+
+            lease_key = manifold.metadata.get_key('lease');
+
+            new_lease = {
+                resource:   resource_urn,
+                start_time: start_time,
+                end_time:   end_time,
+            };
+
+            // This is needed to create a hashable object
+            new_lease.hashCode = manifold.record_hashcode(lease_key.sort());
+            new_lease.equals   = manifold.record_equals(lease_key);
+
+            data = {
+                state: STATE_SET,
+                key  : null,
+                op   : STATE_SET_ADD,
+                value: new_lease
+            }
+            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+            /* Add to local cache also, unless we listen to events from outside */
+            if (!(resource_urn in $scope._leases_by_resource))
+                $scope._leases_by_resource[resource_urn] = [];
+            $scope._leases_by_resource[resource_urn].push(new_lease);
+        }
+
+        $scope._remove_lease = function(other)
+        {
+            var lease_key, other_key, data;
+
+            lease_key = manifold.metadata.get_key('lease');
+
+            // XXX This could be a manifold.record_get_value
+            other_key = {
+                resource:   other.resource,
+                start_time: other.start_time,
+                end_time:   other.end_time
+            }
+            other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+            other_key.equals   = manifold.record_equals(lease_key);
+
+            data = {
+                state: STATE_SET,
+                key  : null,
+                op   : STATE_SET_REMOVE,
+                value: other_key
+            }
+            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+            /* Remove from local cache also, unless we listen to events from outside */
+            $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });
+
+        }
+
+        $scope.select = function(index, model_lease, model_resource)
+        {
+            var data, resource_granularity;
+
+            //resource_granularity = model_resource.granularity === undefined ? RESOURCE_DEFAULT_GRANULARITY : model_resource.granularity;
+
+            console.log("Selected", index, model_lease, model_resource);
+
+            var day_timestamp = SchedulerDateSelected.getTime() / 1000;
+            var start_time = day_timestamp + index       * model_resource.granularity; // XXX resource_granularity
+            var end_time   = day_timestamp + (index + 1) * model_resource.granularity; //
+            var start_date = new Date(start_time * 1000);
+            var end_date   = new Date(end_time   * 1000);
+
+            var lease_key = manifold.metadata.get_key('lease');
+
+            // We search for leases in the cache we previously constructed
+            var resource_leases = $scope._leases_by_resource[model_resource.urn];
+
+            switch (model_lease.status)
+            {
+                case 'free': // out
+                case 'pendingout':
+                    if (resource_leases) {
+                        /* Search for leases before */
+                        $.each(resource_leases, function(i, other) {
+                            if (other.end_time != start_time)
+                                return true; // ~ continue
+        
+                            /* The lease 'other' is just before, and there should not exist
+                             * any other lease before it */
+                            start_time = other.start_time;
+        
+                            other_key = {
+                                resource:   other.resource,
+                                start_time: other.start_time,
+                                end_time:   other.end_time
+                            }
+                            // This is needed to create a hashable object
+                            other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+                            other_key.equals   = manifold.record_equals(lease_key);
+        
+                            data = {
+                                state: STATE_SET,
+                                key  : null,
+                                op   : STATE_SET_REMOVE,
+                                value: other_key
+                            }
+                            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+                            /* Remove from local cache also, unless we listen to events from outside */
+                            $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });
+                            return false; // ~ break
+                        });
+        
+                        /* Search for leases after */
+                        $.each(resource_leases, function(i, other) {
+                            if (other.start_time != end_time)
+                                return true; // ~ continue
+        
+                            /* The lease 'other' is just after, and there should not exist
+                             * any other lease after it */
+                            end_time = other.end_time;
+                            other_key = {
+                                resource:   other.resource,
+                                start_time: other.start_time,
+                                end_time:   other.end_time
+                            }
+                            // This is needed to create a hashable object
+                            other_key.hashCode = manifold.record_hashcode(lease_key.sort());
+                            other_key.equals   = manifold.record_equals(lease_key);
+        
+                            data = {
+                                state: STATE_SET,
+                                key  : null,
+                                op   : STATE_SET_REMOVE,
+                                value: other_key
+                            }
+                            manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+                            /* Remove from local cache also, unless we listen to events from outside */
+                            $scope._leases_by_resource[model_resource.urn] = $.grep($scope._leases_by_resource[model_resource.urn], function(x) { return x != other; });
+                            return false; // ~ break
+                        });
+                    }
+        
+                    $scope._create_new_lease(model_resource.urn, start_time, end_time);
+                    model_lease.status = (model_lease.status == 'free') ? 'pendingin' : 'selected';
+                    // unless the exact same lease already existed (pending_out status for the lease, not the cell !!)
+
+                    break;
+
+                case 'selected':
+                case 'pendingin':
+                    // We remove the cell
+
+                    /* We search for leases including this cell. Either 0, 1 or 2.
+                     * 0 : NOT POSSIBLE, should be checked.
+                     * 1 : either IN or OUT, we have make no change in the session
+                     * 2 : both will be pending, since we have made a change in the session
+                    * /!\ need to properly remove pending_in leases when removed again
+                     */
+                    if (resource_leases) {
+                        $.each(resource_leases, function(i, other) {
+                            if ((other.start_time <= start_time) && (other.end_time >= end_time)) {
+                                // The cell is part of this lease.
+
+                                // If the cell is not at the beginning of the lease, we recreate a lease with cells before
+                                if (start_time > other.start_time) {
+                                    $scope._create_new_lease(model_resource.urn, other.start_time, start_time);
+                                }
+
+                                // If the cell is not at the end of the lease, we recreate a lease with cells after
+                                if (end_time < other.end_time) {
+                                    $scope._create_new_lease(model_resource.urn, end_time, other.end_time);
+                                }
+                                
+                                // The other lease will be removed
+                                $scope._remove_lease(other);
+                            }
+                            // NOTE: We can interrupt the search if we know that there is a single lease (depending on the status).
+                        });
+                    }
+                
+                    // cf comment in previous switch case
+                    model_lease.status = (model_lease.status == 'selected') ? 'pendingout' : 'free';
+
+                    break;
+
+                case 'reserved':
+                case 'maintainance':
+                    // Do nothing
+                    break;
+            }
+            
+
+            $scope._dump_leases();
+        };
+  
+        $scope._dump_leases = function()
+        {
+            // DEBUG: display all leases and their status in the log
+            var leases = manifold.query_store.get_records($scope.instance.options.query_lease_uuid);
+            console.log("--------------------");
+            $.each(leases, function(i, lease) {
+                var key = manifold.metadata.get_key('lease');
+                var lease_key = manifold.record_get_value(lease, key);
+                var state = manifold.query_store.get_record_state($scope.instance.options.query_lease_uuid, lease_key, STATE_SET);
+                var state_str;
+                switch(state) {
+                    case STATE_SET_IN:
+                        state_str = 'STATE_SET_IN';
+                        break;
+                    case STATE_SET_OUT:
+                        state_str = 'STATE_SET_OUT';
+                        break;
+                    case STATE_SET_IN_PENDING:
+                        state_str = 'STATE_SET_IN_PENDING';
+                        break;
+                    case STATE_SET_OUT_PENDING:
+                        state_str = 'STATE_SET_OUT_PENDING';
+                        break;
+                    case STATE_SET_IN_SUCCESS:
+                        state_str = 'STATE_SET_IN_SUCCESS';
+                        break;
+                    case STATE_SET_OUT_SUCCESS:
+                        state_str = 'STATE_SET_OUT_SUCCESS';
+                        break;
+                    case STATE_SET_IN_FAILURE:
+                        state_str = 'STATE_SET_IN_FAILURE';
+                        break;
+                    case STATE_SET_OUT_FAILURE:
+                        state_str = 'STATE_SET_OUT_FAILURE';
+                        break;
+                }
+                console.log("LEASE", new Date(lease.start_time * 1000), new Date(lease.end_time * 1000), lease.resource, state_str);
+            });
+        };
+
+        // Return this object reference.
+        return (this);
+
+    }
+
+    // Define the Controller as the constructor function.
+    app.controller("SchedulerCtrl", Controller);
+
+})(angular, ManifoldApp);
+
+/******************************************************************************
+ *                              MANIFOLD PLUGIN                               *
+ ******************************************************************************/
+
+(function($) {
+        scheduler2 = Plugin.extend({
+
+            /** XXX to check
+         * @brief Plugin constructor
+         * @param options : an associative array of setting values
+         * @param element : 
+         * @return : a jQuery collection of objects on which the plugin is
+         *     applied, which allows to maintain chainability of calls
+         */
+            init: function(options, element) {
+                // Call the parent constructor, see FAQ when forgotten
+                this._super(options, element);
+
+                var scope = this._get_scope()
+                scope.instance = this;
+
+                // XXX not needed
+                scheduler2Instance = this;
+
+                // We need to remember the active filter for datatables filtering
+                // XXX not needed
+                this.filters = Array();
+
+                // XXX BETTER !!!!
+                $(window).delegate('*', 'keypress', function (evt){
+                        alert("erm");
+                      });
+
+                $(window).keydown(function(evt) {
+                    if (evt.which == 17) { // ctrl
+                        schedulerCtrlPressed = true;
+                    }
+                }).keyup(function(evt) {
+                    if (evt.which == 17) { // ctrl
+                        schedulerCtrlPressed = false;
+                    }
+                });
+
+                // XXX naming
+                //$("#" + schedulerTblId).on('mousedown', 'td', rangeMouseDown).on('mouseup', 'td', rangeMouseUp).on('mousemove', 'td', rangeMouseMove);
+
+                this._resources_received = false;
+                this._leases_received = false;
+                
+                scope._leases_by_resource = {};
+
+                /* Listening to queries */
+                this.listen_query(options.query_uuid, 'resources');
+                this.listen_query(options.query_lease_uuid, 'leases');
+
+                this.elmt().on('show', this, this.on_show);
+                this.elmt().on('shown.bs.tab', this, this.on_show);
+                this.elmt().on('resize', this, this.on_resize);
+
+                /* Generate slots according to the default granularity. Should
+                 * be updated when resources arrive.  Should be the pgcd in fact XXX */
+                this._granularity = DEFAULT_GRANULARITY;
+                scope.granularity = this._granularity;
+                this.scope_resources_by_key = {};
+
+                this.do_resize();
+    
+                scope.from = 0;
+
+                this._initUI();
+
+            },
+
+            do_resize: function()
+            {
+                var scope = this._get_scope();
+                var num_hidden_cells, new_max, lcm;
+
+                // do_resize has to be called when the window is resized, or one parameter changes
+                // e.g. when new resources have been received
+                //
+                this.resource_granularities = [3600, 1800]; //, 2400]; /* s */
+
+                /* Compute the slot length to accommodate all resources. This
+                 * is the GCD of all resource granularities. */
+                this._slot_length = this._gcdn(this.resource_granularities);
+
+                $('#' + schedulerTblId + ' thead tr th:eq(0)').css("width", SCHEDULER_FIRST_COLWIDTH);
+                //self get width might need fix depending on the template 
+                var tblwidth = $('#scheduler-reservation-table').parent().outerWidth();
+
+                /* Number of visible cells...*/
+                this._num_visible_cells = parseInt((tblwidth - SCHEDULER_FIRST_COLWIDTH) / SCHEDULER_COLWIDTH);
+
+                /* ...should be a multiple of the lcm of all encountered granularities. */
+                lcm = this._lcmn(this.resource_granularities) / this._slot_length;
+                this._num_visible_cells = this._num_visible_cells - this._num_visible_cells % lcm;
+
+                // A list of {id, time} dictionaries representing the slots for the given day
+                this._all_slots = this._generate_all_slots();
+
+                /* scope also needs this value */
+                scope.slots = this._all_slots;
+                scope.slot_length = this._slot_length;
+                scope.num_visible_cells = this._num_visible_cells;
+                scope.lcm_colspan = this._lcmn(this.resource_granularities); // XXX WHY ?
+
+                /* Redraw... */
+                this._scope_clear_leases();
+                this._set_all_lease_slots();
+
+                // Slider max value
+                if ($('#tblSlider').data('slider') != undefined) {
+                    num_hidden_cells = this._all_slots.length - this._num_visible_cells;
+
+                    $('#tblSlider').slider('setAttribute', 'max', num_hidden_cells);
+                    $('#tblSlider').slider('setValue', scope.from, true);
+                }
+                this._get_scope().$apply();
+
+
+            },
+
+            on_show: function(e)
+            {
+                var self = e.data;
+                self.do_resize();
+                self._get_scope().$apply();
+            },
+
+            on_resize: function(e)
+            {
+                var self = e.data;
+                self.do_resize();
+                self._get_scope().$apply();
+            },
+
+            /* Handlers */
+
+            _get_scope : function()
+            {
+                return angular.element(document.getElementById('SchedulerCtrl')).scope();
+            },
+            
+            _scope_set_resources : function()
+            {
+                var self = this;
+                var scope = this._get_scope();
+
+                var records = manifold.query_store.get_records(this.options.query_uuid);
+
+                scope.resources = [];
+
+                $.each(records, function(i, record) {
+                    if (!record.exclusive)
+                        return true; // ~ continue
+
+                    // copy not to modify original record
+                    var resource = jQuery.extend(true, {}, record);
+
+                    // Fix granularity
+                    //resource_granularity = ((resource.granularity === undefined) || (typeof(resource.granularity) != "number")) ? RESOURCE_DEFAULT_GRANULARITY : resource.granularity;
+                    if (typeof(resource.granularity) != "number")
+                        resource.granularity = RESOURCE_DEFAULT_GRANULARITY;
+                    resource.leases = []; // a list of occupied timeslots
+
+                    self.scope_resources_by_key[resource['urn']] = resource;
+                    scope.resources.push(resource);
+                });
+            },
+
+            _scope_clear_leases: function()
+            {
+                var time, now;
+                var self = this;
+                var scope = this._get_scope();
+
+                now = new Date().getTime();
+
+                // Setup leases with a default free status...
+                $.each(this.scope_resources_by_key, function(resource_key, resource) {
+                    resource.leases = [];
+                    var colspan_lease = resource.granularity / self._slot_length; //eg. 3600 / 1800 => 2 cells
+                    time = SchedulerDateSelected.getTime();
+                    for (i=0; i < self._all_slots.length / colspan_lease; i++) { // divide by granularity
+                        resource.leases.push({
+                            id:     'coucou',
+                            status: (time < now) ? 'disabled':  'free', // 'selected', 'reserved', 'maintenance' XXX pending ??
+                        });
+                        time += resource.granularity * 1000;
+                    }
+                });
+
+            },
+
+            _scope_set_leases: function()
+            {
+                    var status;
+                var self = this;
+                var scope = this._get_scope();
+            
+                manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {
+                    //console.log("SET LEASES", lease.resource, new Date(lease.start_time* 1000), new Date(lease.end_time* 1000));
+                    // XXX We should ensure leases are correctly merged, otherwise our algorithm won't work
+
+                    // Populate leases by resource array: this will help us merging leases later
+
+                    // let's only put _our_ leases
+                    lease_status = manifold.query_store.get_record_state(self.options.query_lease_uuid, lease_key, STATE_SET);
+                    if (lease_status != STATE_SET_IN)
+                        return true; // ~continue
+                    if (!(lease.resource in scope._leases_by_resource))
+                        scope._leases_by_resource[lease.resource] = [];
+                    scope._leases_by_resource[lease.resource].push(lease);
+
+                });
+
+                this._set_all_lease_slots();
+            },
+
+            _set_all_lease_slots: function()
+            {
+                var self = this;
+            
+                manifold.query_store.iter_records(this.options.query_lease_uuid, function(lease_key, lease) {
+                    self._set_lease_slots(lease_key, lease);
+                });
+            },
+
+            on_resources_query_done: function(data)
+            {
+                this._resources_received = true;
+                this._scope_set_resources();
+                this._scope_clear_leases();
+                if (this._leases_received)
+                    this._scope_set_leases();
+                    
+                this._get_scope().$apply();
+            },
+
+            on_leases_query_done: function(data)
+            {
+                this._leases_received = true;
+                if (this._resources_received) {
+                    this._scope_set_leases();
+                    this._get_scope().$apply();
+                }
+            },
+
+            /* Filters on resources */
+            on_resources_filter_added:   function(filter) { this._get_scope().$apply(); },
+            on_resources_filter_removed: function(filter) { this._get_scope().$apply(); },
+            on_resources_filter_clear:   function()       { this._get_scope().$apply(); },
+
+            /* Filters on leases ? */
+            on_leases_filter_added:      function(filter) { this._get_scope().$apply(); },
+            on_leases_filter_removed:    function(filter) { this._get_scope().$apply(); },
+            on_leases_filter_clear:      function()       { this._get_scope().$apply(); },
+
+            on_field_state_changed: function(data)
+            {
+                /*
+                this._set_lease_slots(lease_key, lease);
+
+                switch(data.state) {
+                    case STATE_SET:
+                        switch(data.op) {
+                            case STATE_SET_IN:
+                            case STATE_SET_IN_SUCCESS:
+                            case STATE_SET_OUT_FAILURE:
+                                this.set_checkbox_from_data(data.value, true);
+                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                break;  
+                            case STATE_SET_OUT:
+                            case STATE_SET_OUT_SUCCESS:
+                            case STATE_SET_IN_FAILURE:
+                                this.set_checkbox_from_data(data.value, false);
+                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                break;
+                            case STATE_SET_IN_PENDING:
+                                this.set_checkbox_from_data(data.key, true);
+                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);
+                                break;  
+                            case STATE_SET_OUT_PENDING:
+                                this.set_checkbox_from_data(data.key, false);
+                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);
+                                break;
+                        }
+                        break;
+
+                    case STATE_WARNINGS:
+                        this.change_status(data.key, data.value);
+                        break;
+                }
+                */
+            },
+
+
+            /* INTERNAL FUNCTIONS */
+
+            _set_lease_slots: function(lease_key, lease)
+            {
+                var resource, lease_status, lease_class;
+                var day_timestamp, id_start, id_end, colspan_lease;
+
+                resource = this.scope_resources_by_key[lease.resource];
+                day_timestamp = SchedulerDateSelected.getTime() / 1000;
+                if(resource === undefined){
+                    console.log('resource undefined = '+lease.resource);
+                    return;
+                }
+                id_start = Math.floor((lease.start_time - day_timestamp) / resource.granularity);
+
+                /* Some leases might be in the past */
+                if (id_start < 0)
+                    id_start = 0;
+                /* Leases in the future: ignore */
+                if (id_start >= this._all_slots.length)
+                    return true; // ~ continue
+
+                id_end   = Math.ceil((lease.end_time   - day_timestamp) / resource.granularity);
+                colspan_lease = resource.granularity / this._slot_length; //eg. 3600 / 1800 => 2 cells
+                if (id_end >= this._all_slots.length / colspan_lease) {
+                    /* Limit the display to the current day */
+                    id_end = this._all_slots.length / colspan_lease
+                }
+                lease_status = manifold.query_store.get_record_state(this.options.query_lease_uuid, lease_key, STATE_SET);
+                // the same slots might be affected multiple times.
+                // PENDING_IN + PENDING_OUT => IN 
+                //
+                // RESERVED vs SELECTED !
+                //
+                // PENDING !!
+                switch(lease_status) {
+                    case STATE_SET_IN:
+                        lease_class = 'selected'; // my leases
+                        lease_success = '';
+                        break;
+                    case STATE_SET_IN_SUCCESS:
+                        lease_class = 'selected'; // my leases
+                        lease_success = 'success';
+                    case STATE_SET_OUT_FAILURE:
+                        lease_class = 'selected'; // my leases
+                        lease_success = 'failure';
+                        break;
+                    case STATE_SET_OUT:
+                        lease_class = 'reserved'; // other leases
+                        lease_success = '';
+                        break;
+                    case STATE_SET_OUT_SUCCESS:
+                        lease_class = 'free'; // other leases
+                        lease_success = 'success';
+                        break;
+                    case STATE_SET_IN_FAILURE:
+                        lease_class = 'free'; // other leases
+                        lease_success = 'failure';
+                        break;
+                    case STATE_SET_IN_PENDING:
+                        lease_class = 'pendingin';
+                        lease_success = '';
+                        break;
+                    case STATE_SET_OUT_PENDING:
+                        // pending_in & pending_out == IN == replacement
+                        if (resource.leases[i].status == 'pendingin')
+                            lease_class = 'pendingin'
+                        else
+                            lease_class = 'pendingout';
+                        lease_success = '';
+                        break;
+                
+                }
+
+                for (i = id_start; i < id_end; i++) {
+                    resource.leases[i].status = lease_class;
+                    resource.leases[i].success = lease_success;
+                }
+            },
+
+/* XXX IN TEMPLATE XXX
+                if (SchedulerDataViewData.length == 0) {
+                    $("#plugin-scheduler").hide();
+                    $("#plugin-scheduler-empty").show();
+                    tmpScope.clearStuff();
+                } else {
+                    $("#plugin-scheduler-empty").hide();
+                    $("#plugin-scheduler").show();
+                    // initSchedulerResources
+                    tmpScope.initSchedulerResources(schedulerMaxRows < SchedulerDataViewData.length ? schedulerMaxRows : SchedulerDataViewData.length);
+                }
+*/
+
+            /**
+             * Initialize the date picker, the table, the slider and the buttons. Once done, display scheduler.
+             */
+            _initUI: function() 
+            {
+                var self = this;
+                var scope = self._get_scope();
+
+                var num_hidden_cells;
+
+                $("#DateToRes").datepicker({
+                       dateFormat: "D, d M yy",
+                    onRender: function(date) {
+                        return date.valueOf() < now.valueOf() ? 'disabled' : '';
+                    }
+                }).on('changeDate', function(ev) {
+                    SchedulerDateSelected = new Date(ev.date);
+                    SchedulerDateSelected.setHours(0,0,0,0);
+                    // Set slider to origin
+                    //$('#tblSlider').slider('setValue', 0); // XXX
+                    // Refresh leases
+                    self._scope_clear_leases();
+                    self._set_all_lease_slots();
+                    // Refresh display
+                    self._get_scope().$apply();
+                }).datepicker('setValue', SchedulerDateSelected); //.data('datepicker');
+
+                //init Slider
+                num_hidden_cells = self._all_slots.length - self._num_visible_cells;
+                init_cell = (new Date().getHours() - 1) * 3600 / self._granularity;
+                if (init_cell > num_hidden_cells)
+                    init_cell = num_hidden_cells;
+
+                $('#tblSlider').slider({
+                    min: 0,
+                    max: num_hidden_cells,
+                    value: init_cell,
+                }).on('slide', function(ev) {
+                    var scope = self._get_scope();
+                    scope.from = ev.value;
+                    scope.$apply();
+                });
+                scope.from = init_cell;
+                scope.$apply();
+
+                $("#plugin-scheduler-loader").hide();
+                $("#plugin-scheduler").show();
+            },
+
+        // PRIVATE METHODS
+
+        /**
+         * Greatest common divisor
+         */
+        _gcd : function(x, y)
+        {
+            return (y==0) ? x : this._gcd(y, x % y);
+        },
+
+        _gcdn : function(array)
+        {
+            var self = this;
+            return array.reduce(function(prev, cur, idx, arr) { return self._gcd(prev, cur); });
+        },
+
+        /**
+         * Least common multiple
+         */
+        _lcm : function(x, y)
+        {
+            return x * y / this._gcd(x, y);
+        },
+
+        _lcmn : function(array)
+        {
+            var self = this;
+            return array.reduce(function(prev, cur, idx, arr) { return self._lcm(prev, cur); });
+        },
+    
+        _pad_str : function(i)
+        {
+            return (i < 10) ? "0" + i : "" + i;
+        },
+
+        /**
+         * Member variables used:
+         *   _granularity
+         * 
+         * Returns:
+         *   A list of {id, time} dictionaries.
+         */
+        _generate_all_slots: function()
+        {
+            var slots = [];
+            // Start with a random date (a first of a month), only time will matter
+            var d = new Date(2014, 1, 1, 0, 0, 0, 0);
+            var i = 0;
+            // Loop until we change the day
+            while (d.getDate() == 1) {
+                // Nicely format the time...
+                var tmpTime = this._pad_str(d.getHours()) + ':' + this._pad_str(d.getMinutes());
+                /// ...and add the slot to the list of results
+                slots.push({ id: i, time: tmpTime });
+                // Increment the date with the granularity
+                d = new Date(d.getTime() + this._slot_length * 1000);
+                i++;
+            }
+            return slots;
+
+        },
+    });
+
+    /* Plugin registration */
+    $.plugin('Scheduler2', scheduler2);
+
+})(jQuery);
+
+
+
index e628a67..ba40d00 100644 (file)
                 $scope._testbed_active[facility] = new Object();
             $scope._testbed_active[facility][testbed] = value;
         };
+        
+        $scope.tolower = function(string) {
+            return string.toLowerCase(string);  
+        };
     
         /* Click event */
 
         {
             var selected, prev_selected, num, num_selected, num_prev_selected, filter;
 
-            prev_selected = $.map($scope.facility_names, function(x, i) {
-                return $scope.is_facility_active(x) ? x : null;
-            });
+            // prev_selected = $.map($scope.facility_names, function(x, i) {
+                // return $scope.is_facility_active(x) ? x : null;
+            // });
 
             $scope.set_facility_active(facility, ! $scope.is_facility_active(facility));
-
-            selected = $.map($scope.facility_names, function(x, i) {
-                return $scope.is_facility_active(x) ? x : null;
+            
+            $.each($scope.testbed_names[facility], function(j, testbed_name) {
+                $scope.select_testbed(facility, testbed_name);
             });
-
-            num = $scope.facility_names.length;
-            prev_num_selected = prev_selected.length;
-            num_selected = selected.length;
-
-            if ((prev_num_selected != 0) && (prev_num_selected != num)) {
-                // Remove previous filter
-                filter = ['facility_name', 'included', prev_selected];
-                manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
-            }
-
-            if (num_selected != num) {
-                filter = ['facility_name', 'included', selected];
-                manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
-            }
+            console.log($scope);
+            // selected = $.map($scope.facility_names, function(x, i) {
+                // return $scope.is_facility_active(x) ? x : null;
+            // });
+
+            // num = $scope.facility_names.length;
+            // prev_num_selected = prev_selected.length;
+            // num_selected = selected.length;
+
+            // if ((prev_num_selected != 0) && (prev_num_selected != num)) {
+                // // Remove previous filter
+                // filter = ['facility_name', 'included', prev_selected];
+                // manifold.raise_event($scope.instance.options.query_uuid, FILTER_REMOVED, filter);
+            // }
+// 
+            // if (num_selected != num) {
+                // filter = ['facility_name', 'included', selected];
+                // manifold.raise_event($scope.instance.options.query_uuid, FILTER_ADDED, filter);
+            // }
         };
 
         $scope.select_testbed = function(facility, testbed)
 
         _get_scope : function()
         {
-            return angular.element('[ng-controller=TestbedsCtrl]').scope()
+            return angular.element('[ng-controller=TestbedsCtrl]').scope();
         },
 
 /*
index 296e5ef..755bc35 100644 (file)
@@ -1,34 +1,27 @@
-<div id={{ domid }} ng-controller="TestbedsCtrl">
-
-<div class="list-group-item sl-platform"><span class="list-group-item-heading">Facilities</span></div>
-
-<div ng-repeat="facility_name in facility_names">
-       <a href="#" 
-          class="list-group-item sl-platform"
-          ng-class="{active: is_facility_active(facility_name)}"
-          id="facility-filter_{[{ facility_name }]}"
-          ng-click="select_facility(facility_name)"
-          data-platform="{[{ facility_name }]}">
-       <span class="list-group-item-heading">{[{ facility_name }]}</span>
-       </a>
-       <div ng-repeat="testbed_name in testbed_names[facility_name]">
-               <a href="#" 
-                  class="list-group-item sl-platform"
-                  ng-class="{active: is_testbed_active(facility_name, testbed_name)}"
-                  id="testbeds-filter_{[{ testbed_name }]}"
-                ng-click="select_testbed(facility_name, testbed_name)"
-                  data-platform="{[{ testbed_name }]}">
-               <span class="list-group-item-heading">&nbsp;&nbsp;{[{testbed_name}]}</span>
-               </a>
-       </div>
-</div>
-
-<!--
-<style>
-a.sl-platform  {
-    text-transform: uppercase;
-}
-
-</style>
--->
+<div id="{{ domid }}" class="sl-filter-facilities" ng-controller="TestbedsCtrl">
+    <h4>
+       Facilities
+    </h4>
+    <div>
+        <div class="sl-facilities" ng-repeat="facility_name in facility_names">
+            <a href="#" 
+               class="sl-facility"
+               ng-class="{active: is_facility_active(facility_name)}"
+               id="facility-filter_{[{ facility_name }]}"
+               ng-click="select_facility(facility_name)"
+               data-platform="{[{ facility_name }]}">
+               <img class="sl-image" src="/static/icons/{[{ tolower(facility_name) }]}.png" /> {[{ facility_name }]}
+            </a>
+            <div class="sl-testbeds" ng-repeat="testbed_name in testbed_names[facility_name]">
+                <a href="#" 
+                   class="sl-testbed"
+                   ng-class="{active: is_testbed_active(facility_name, testbed_name)}"
+                   id="testbeds-filter_{[{ testbed_name }]}"
+                   ng-click="select_testbed(facility_name, testbed_name)"
+                   data-platform="{[{ testbed_name }]}">
+                    <input ng-checked="is_testbed_active(facility_name, testbed_name)" type="checkbox">&nbsp;{[{testbed_name}]}
+                </a>
+            </div>
+        </div>
+    </div>
 </div>
index 4d25c61..dfda182 100644 (file)
@@ -1,7 +1,5 @@
 from unfold.loginrequired               import LoginRequiredAutoLogoutView
 #
-from sfa.trust.credential               import Credential
-from sfa.trust.certificate              import Keypair
 #
 from manifold.core.query                import Query
 from manifoldapi.manifoldapi            import execute_query
@@ -40,8 +38,8 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css" ] )
 
         # Execute a Query to delegate credentials if necessary
-        sfa_user_query  = Query().get('myslice:user').select('user_hrn').filter_by('user_hrn','==','$user_hrn')
-        sfa_user_result = execute_query(self.request, sfa_user_query)
+        #sfa_user_query  = Query().get('myslice:user').select('user_hrn').filter_by('user_hrn','==','$user_hrn')
+        #sfa_user_result = execute_query(self.request, sfa_user_query)
 
         user_query  = Query().get('local:user').select('config','email','status')
         user_details = execute_query(self.request, user_query)
@@ -271,6 +269,9 @@ def get_myslice_account(request):
 @login_required
 #my_acc form value processing
 def account_process(request):
+    from sfa.trust.credential               import Credential
+    from sfa.trust.certificate              import Keypair
+
     user_query  = Query().get('local:user').select('user_id','email','password','config')
     user_details = execute_query(request, user_query)
     
@@ -297,7 +298,7 @@ def account_process(request):
     for account_detail in account_details:
         for platform_detail in platform_details:
             # Add reference account to the platforms
-            if 'add_'+platform_detail['platform'] in request.POST:
+            if 'add_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'add_'+platform_detail['platform']:
                 platform_id = platform_detail['platform_id']
                 user_params = {'platform_id': platform_id, 'user_id': user_id, 'auth_type': "reference", 'config': '{"reference_platform": "myslice"}'}
                 manifold_add_account(request,user_params)
@@ -305,7 +306,7 @@ def account_process(request):
                 return HttpResponseRedirect("/portal/account/")
 
             # Delete reference account from the platforms
-            if 'delete_'+platform_detail['platform'] in request.POST:
+            if 'delete_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'delete_'+platform_detail['platform']:
                 platform_id = platform_detail['platform_id']
                 user_params = {'user_id':user_id}
                 manifold_delete_account(request,platform_id, user_id, user_params)
@@ -330,7 +331,7 @@ def account_process(request):
             slice_cred.append(value)
         # special case: download each slice credentials separately 
         for i in range(0, len(slice_list)):
-            if 'dl_'+slice_list[i] in request.POST:
+            if 'dl_'+slice_list[i] in request.POST or request.POST['button_value'] == 'dl_'+slice_list[i]:
                 slice_detail = "Slice name: " + slice_list[i] +"\nSlice Credentials: \n"+ slice_cred[i]
                 response = HttpResponse(slice_detail, content_type='text/plain')
                 response['Content-Disposition'] = 'attachment; filename="slice_credential.txt"'
@@ -345,7 +346,7 @@ def account_process(request):
             auth_cred.append(value)
         # special case: download each slice credentials separately
         for i in range(0, len(auth_list)):
-            if 'dl_'+auth_list[i] in request.POST:
+            if 'dl_'+auth_list[i] in request.POST or request.POST['button_value'] == 'dl_'+auth_list[i]:
                 auth_detail = "Authority: " + auth_list[i] +"\nAuthority Credentials: \n"+ auth_cred[i]
                 response = HttpResponse(auth_detail, content_type='text/plain')
                 response['Content-Disposition'] = 'attachment; filename="auth_credential.txt"'
@@ -417,7 +418,6 @@ def account_process(request):
                         sfa_update_user(request, user_hrn, user_pub_key)
                         result_sfa_user = sfa_get_user(request, user_hrn, public_key)
                         try:
-                            result_sfa_user = result_sfa_user[0]
                             if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
                                 # updating manifold
                                 updated_config = json.dumps(account_config) 
@@ -426,7 +426,7 @@ def account_process(request):
                                 messages.success(request, 'Sucess: New Keypair Generated! Delegation of your credentials will be automatic.')
                             else:
                                 raise Exception,"Keys are not matching"
-                        except Exception,e:
+                        except Exception, e:
                             messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
                             print "Exception in accountview ", e
                         return HttpResponseRedirect("/portal/account/")
@@ -467,7 +467,7 @@ def account_process(request):
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
-    elif 'dl_pubkey' in request.POST:
+    elif 'dl_pubkey' in request.POST or request.POST['button_value'] == 'dl_pubkey':
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
@@ -482,7 +482,7 @@ def account_process(request):
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
                
-    elif 'dl_pkey' in request.POST:
+    elif 'dl_pkey' in request.POST or request.POST['button_value'] == 'dl_pkey':
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
@@ -501,7 +501,7 @@ def account_process(request):
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
     
-    elif 'delete' in request.POST:
+    elif 'delete' in request.POST or request.POST['button_value'] == 'delete':
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
@@ -527,7 +527,7 @@ def account_process(request):
             return HttpResponseRedirect("/portal/account/")
     
     # download identity for jfed
-    elif 'dl_identity' in request.POST:
+    elif 'dl_identity' in request.POST or request.POST['button_value'] == 'dl_identity':
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
@@ -550,7 +550,7 @@ def account_process(request):
             return HttpResponseRedirect("/portal/account/")
 
     # Download sfi_config
-    elif 'dl_sfi_config' in request.POST:
+    elif 'dl_sfi_config' in request.POST or request.POST['button_value'] == 'dl_sfi_config':
         platform_detail = get_myslice_platform(request)
         platform_config = json.loads(platform_detail['config'])
         account_detail = get_myslice_account(request)
@@ -584,7 +584,7 @@ def account_process(request):
         return response
 
     #clear all creds
-    elif 'clear_cred' in request.POST:
+    elif 'clear_cred' in request.POST or request.POST['button_value'] == 'clear_cred':
         try:
             result = clear_user_creds(request, user_email)
             if result is not None: 
@@ -597,7 +597,7 @@ def account_process(request):
         return HttpResponseRedirect("/portal/account/")
 
     # Download delegated_user_cred
-    elif 'dl_user_cred' in request.POST:
+    elif 'dl_user_cred' in request.POST or request.POST['button_value'] == 'dl_user_cred':
         if 'delegated_user_credential' in account_config:
             user_cred = account_config['delegated_user_credential']
             response = HttpResponse(user_cred, content_type='text/plain')
@@ -608,7 +608,7 @@ def account_process(request):
             return HttpResponseRedirect("/portal/account/")
 
     # Download user_cert
-    elif 'dl_user_cert' in request.POST:
+    elif 'dl_user_cert' in request.POST or request.POST['button_value'] == 'dl_user_cert':
         if 'user_credential' in account_config:
             user_cred = account_config['user_credential']
             obj_cred = Credential(string=user_cred)
@@ -631,7 +631,7 @@ def account_process(request):
             return HttpResponseRedirect("/portal/account/")
 
     # Download user p12 = private_key + Certificate
-    elif 'dl_user_p12' in request.POST:
+    elif 'dl_user_p12' in request.POST or request.POST['button_value'] == 'dl_user_p12':
         if 'user_credential' in account_config and 'user_private_key' in account_config:
             user_cred = account_config['user_credential']
             obj_cred = Credential(string=user_cred)
@@ -673,8 +673,6 @@ def account_process(request):
             messages.error(request, 'Download error: User private key or credential is not stored in the server')
             return HttpResponseRedirect("/portal/account/")
 
-
-
     else:
         messages.info(request, 'Under Construction. Please try again later!')
         return HttpResponseRedirect("/portal/account/")
index e8a4d01..047288d 100644 (file)
@@ -1,17 +1,19 @@
-from django.http                import HttpResponse
-from manifold.core.query        import Query
-from manifoldapi.manifoldapi    import execute_query,execute_admin_query
-from portal.models              import PendingUser, PendingSlice, PendingAuthority
+from django.http                    import HttpResponse
+from manifold.core.query            import Query
+from manifoldapi.manifoldapi        import execute_query,execute_admin_query
+from portal.models                  import PendingUser, PendingSlice, PendingAuthority, PendingProject, PendingJoin
+from unfold.page                    import Page
+
 import json
 
-from django.contrib.auth.models  import User
-from django.contrib.sites.models import Site
-from django.contrib.auth        import get_user_model
-from django.template.loader     import render_to_string
-from django.core.mail           import EmailMultiAlternatives, send_mail
+from django.contrib.auth.models     import User
+from django.contrib.sites.models    import Site
+from django.contrib.auth            import get_user_model
+from django.template.loader         import render_to_string
+from django.core.mail               import EmailMultiAlternatives, send_mail
 
-from myslice.theme              import ThemeView
-from myslice.configengine       import ConfigEngine
+from myslice.theme                  import ThemeView
+from myslice.configengine           import ConfigEngine
 
 
 theme = ThemeView()
@@ -24,14 +26,18 @@ import activity.slice
 #from sfa.util.xrn                import Xrn 
 
 
-# Get the list of authorities
-
+# Get the list of pis in a given authority
 def authority_get_pis(request, authority_hrn):
+    # CACHE PB with fields
+    page = Page(request)
+    metadata = page.get_metadata()
+    auth_md = metadata.details_by_object('authority')
+    auth_fields = [column['name'] for column in auth_md['column']]
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
+    query = Query.get('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).select(auth_fields)
     results = execute_admin_query(request, query)
-    print "authority_get_pis = %s" % results
+    #print "authority_get_pis = %s" % results
     # NOTE: temporarily commented. Because results is giving empty list. 
     # Needs more debugging
     #if not results:
@@ -40,6 +46,80 @@ def authority_get_pis(request, authority_hrn):
     #return result['pi_users']
     return results
 
+#check the user is pi or not in the registry
+def authority_check_pis(request, user_email):
+    try:
+        user_query  = Query().get('local:user').filter_by('email', '==', user_email).select('user_id','email','password','config')
+        user_details = execute_admin_query(request, user_query)
+    
+        # getting the authority_hrn
+        for user_detail in user_details:
+            user_id = user_detail['user_id']
+            if user_detail['config']:
+                config = json.loads(user_detail['config'])
+                authority_hrn = config.get('authority','Unknown Authority')
+        account_query  = Query().get('local:account').filter_by('user_id', '==', user_id).select('user_id','platform_id','auth_type','config')
+        account_details = execute_admin_query(request, account_query)
+    
+        platform_query  = Query().get('local:platform').select('platform_id','platform')
+        platform_details = execute_admin_query(request, platform_query)
+    
+        for account_detail in account_details:
+            for platform_detail in platform_details:
+                if platform_detail['platform_id'] == account_detail['platform_id']:
+                    if 'myslice' in platform_detail['platform']:
+                        account_config = json.loads(account_detail['config'])
+                        user_hrn = account_config.get('user_hrn','N/A')
+
+        pi_status = False
+        pis = authority_get_pis (request, authority_hrn)
+        for pi in pis:
+            pi_list = pi['pi_users']
+
+        if user_hrn in pi_list:
+            pi_status = True
+        return pi_status
+
+    except Exception,e:
+        print "Exception in actions.py in authority_check_pis %s" % e
+        return None
+
+
+def authority_add_pis(request, authority_hrn,user_hrn):
+    try:
+        # getting pis of the authority of the user
+        pis = authority_get_pis (request, authority_hrn)
+        for pi in pis:
+            pi_list = pi['pi_users']
+   
+        updated_pi_list = pi_list.append(user_hrn) 
+        query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+        results = execute_query(request,query)
+        newpis = authority_get_pis (request, authority_hrn)
+        return newpis
+    except Exception,e: 
+        print "Exception in actions.py in authority_add_pis %s" % e
+        return None
+
+
+def authority_remove_pis(request, authority_hrn,user_hrn):
+    try:
+        # getting pis of the authority of the user
+        pis = authority_get_pis (request, authority_hrn)
+        for pi in pis:
+            pi_list = pi['pi_users']
+        updated_pi_list = pi_list.remove(user_hrn) 
+        query = Query.update('authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+        results = execute_query(request,query)
+        newpis = authority_get_pis (request, authority_hrn)
+        return newpis
+    except Exception,e: 
+        print "Exception in actions.py in authority_remove_pis %s" % e
+        return None
+
+
 def authority_get_pi_emails(request, authority_hrn):
     pi_users = authority_get_pis(request,authority_hrn)
     print "pi_users = %s" % pi_users
@@ -99,28 +179,35 @@ def clear_user_creds(request, user_email):
         return None
 
 def is_pi(wsgi_request, user_hrn, authority_hrn):
-    # XXX could be done in a single query !
-
-    # seauthorities from user where user_hrn == "ple.upmc.jordan_auge"
-
-    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
-    results = execute_admin_query(wsgi_request, query)
-    if not results:
-        # XXX Warning ?
-        return False
-    result = results[0]
-    user_authority_hrns = result.get('pi_authorities', [])
-    return authority_hrn in user_authority_hrns
+    # authorities from user where user_hrn == "ple.upmc.jordan_auge"
+    print "#### actions.py is_pi authority_hrn = ", authority_hrn
+    try:
+        # CACHE PB with fields
+        page = Page(wsgi_request)
+        metadata = page.get_metadata()
+        user_md = metadata.details_by_object('user')
+        user_fields = [column['name'] for column in user_md['column']]
+        
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+        query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
+        #query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
+        results = execute_query(wsgi_request, query)
+        print "is_pi results = ", results
+        for user_detail in results:
+            if authority_hrn in user_detail['pi_authorities']:
+                return True
+    except Exception,e:
+        print "Exception in actions.py in is_pi %s" % e
+    return False
     
 # SFA get record
 
-def sfa_get_user(request, user_hrn, pub):
+def sfa_get_user(request, user_hrn, pub=None):
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query_sfa_user = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn)
     result_sfa_user = execute_admin_query(request, query_sfa_user)
-    return result_sfa_user                        
+    return result_sfa_user[0]                        
 
 def sfa_update_user(request, user_hrn, user_params):
     # user_params: keys [public_key] 
@@ -135,7 +222,7 @@ def sfa_update_user(request, user_hrn, user_params):
 def sfa_add_authority(request, authority_params):
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.create('authority').set(authority_params).select('authority_hrn')
+    query = Query.create('myslice:authority').set(authority_params).select('authority_hrn')
     results = execute_query(request, query)
     print "sfa_add_auth results=",results
     if not results:
@@ -267,6 +354,29 @@ def make_request_slice(slice):
     request['purpose'] = slice.purpose
     return request
 
+def make_request_project(project):
+    request = {}
+    request['type'] = 'project'
+    request['id'] = project.id
+    request['user_hrn'] = project.user_hrn
+    request['email'] = project.email
+    request['timestamp'] = project.created
+    request['authority_hrn'] = project.authority_hrn
+    request['project_name'] = project.project_name
+    request['purpose'] = project.purpose
+    return request
+
+def make_request_join(join):
+    request = {}
+    request['type'] = 'join'
+    request['id'] = join.id
+    request['user_hrn'] = join.user_hrn
+    request['email'] = join.email
+    request['timestamp'] = join.created
+    request['authority_hrn'] = join.authority_hrn
+    request['project_name'] = join.project_name
+    return request
+
 def make_request_authority(authority):
     request = {}
     request['type']                  = 'authority'
@@ -288,7 +398,8 @@ def make_request_authority(authority):
     request['timestamp']             = authority.created
     return request
 
-def make_requests(pending_users, pending_slices, pending_authorities):
+def make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins):
+    print "$$$$$$$$$$$$$$$  make_request"
     requests = []
     for user in pending_users:
         requests.append(make_request_user(user))
@@ -296,10 +407,15 @@ def make_requests(pending_users, pending_slices, pending_authorities):
         requests.append(make_request_slice(slice))
     for authority in pending_authorities:
         requests.append(make_request_authority(authority))
+    for project in pending_projects:
+        requests.append(make_request_project(project))
+    for join in pending_joins:
+        requests.append(make_request_join(join))
     return requests   
 
 def get_request_by_id(ids):
-    sorted_ids = { 'user': [], 'slice': [], 'authority': [] }
+    print "$$$$$$$$$$$$$$$$  get_request_by_id"
+    sorted_ids = { 'user': [], 'slice': [], 'authority': [], 'project': [], 'join': [] }
     for type__id in ids:
         type, id = type__id.split('__')
         sorted_ids[type].append(id)
@@ -308,40 +424,53 @@ def get_request_by_id(ids):
         pending_users  = PendingUser.objects.all()
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
+        pending_projects = PendingProject.objects.all()
+        pending_joins = PendingJoin.objects.all()
     else:
         pending_users  = PendingUser.objects.filter(id__in=sorted_ids['user']).all()
         pending_slices = PendingSlice.objects.filter(id__in=sorted_ids['slice']).all()
         pending_authorities = PendingAuthority.objects.filter(id__in=sorted_ids['authority']).all()
+        pending_projects = PendingProject.objects.filter(id__in=sorted_ids['project']).all()
+        pending_joins = PendingJoin.objects.filter(id__in=sorted_ids['join']).all()
 
-    return make_requests(pending_users, pending_slices, pending_authorities)
+    return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
 
 def get_requests(authority_hrns=None):
-    print "get_request_by_authority auth_hrns = ", authority_hrns
+    print "$$$$$$$$$$$$$   get_request_by_authority auth_hrns = ", authority_hrns
     if not authority_hrns:
         ## get those pending users who have confirmed their emails
         pending_users  = PendingUser.objects.filter(status__iexact = 'True')
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
+        pending_projects = PendingProject.objects.all()
+        pending_joins = PendingJoin.objects.all()
     else:
         pending_users  = PendingUser.objects
         pending_slices = PendingSlice.objects
         pending_authorities = PendingAuthority.objects
+        pending_projects = PendingProject.objects
+        pending_joins = PendingJoin.objects
         from django.db.models import Q
         list_user_Q = list()
         list_slice_Q = list()
         list_auth_Q = list()
+        list_proj_Q = list()
+        list_join_Q = list()
         for hrn in authority_hrns:
             list_user_Q.append(Q(authority_hrn__startswith=hrn, status__iexact = 'True'))
             list_slice_Q.append(Q(authority_hrn__startswith=hrn))
             list_auth_Q.append(Q(site_authority__startswith=hrn))
-            print "startswith hrn = ",hrn
+            list_proj_Q.append(Q(authority_hrn__startswith=hrn))
+            list_join_Q.append(Q(authority_hrn__startswith=hrn))
         from operator import __or__ as OR
         pending_users        = pending_users.filter(reduce(OR, list_user_Q))
         pending_slices       = pending_slices.filter(reduce(OR, list_slice_Q))
         pending_authorities  = pending_authorities.filter(reduce(OR, list_auth_Q))
+        pending_projects     = pending_projects.filter(reduce(OR, list_proj_Q))
+        pending_joins        = pending_joins.filter(reduce(OR, list_join_Q))
         #pending_authorities  = pending_authorities.all() #filter(reduce(OR, list_Q))
 
-    return make_requests(pending_users, pending_slices, pending_authorities)
+    return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
 
 # XXX Is it in sync with the form fields ?
 
@@ -391,6 +520,10 @@ def portal_validate_request(wsgi_request, request_ids):
                 request_status['SFA slice'] = {'status': True }
                 PendingSlice.objects.get(id=request['id']).delete()
 
+                # Clear user's Credentials
+                sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
+                clear_user_creds(wsgi_request,sfa_user['user_email'])
+
             except Exception, e:
                 request_status['SFA slice'] = {'status': False, 'description': str(e)}
 
@@ -418,6 +551,43 @@ def portal_validate_request(wsgi_request, request_ids):
             except Exception, e:
                 request_status['SFA authority'] = {'status': False, 'description': str(e)}
 
+        elif request['type'] == 'project':
+            try:
+                hrn = request['authority_hrn'] + '.' + request['project_name']
+
+                # Only hrn is required for Manifold Query 
+                sfa_authority_params = {
+                    'authority_hrn'        : hrn
+                }
+                sfa_add_authority(wsgi_request, sfa_authority_params)
+                request_status['SFA project'] = {'status': True }
+                PendingProject.objects.get(id=request['id']).delete()
+                
+                # Add user as a PI of the project
+                authority_add_pis(wsgi_request, hrn , request['user_hrn'])
+
+                # Clear user's Credentials
+                #sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
+                clear_user_creds(wsgi_request,request['email'])
+
+            except Exception, e:
+                request_status['SFA project'] = {'status': False, 'description': str(e)}
+
+        elif request['type'] == 'join':
+            try:
+                # Add user as a PI of the project
+                authority_add_pis(wsgi_request, request['authority_hrn'] , request['user_hrn'])
+
+                request_status['SFA join'] = {'status': True }
+                PendingJoin.objects.get(id=request['id']).delete()
+
+                # Clear user's Credentials
+                clear_user_creds(wsgi_request,request['email'])
+
+            except Exception, e:
+                request_status['SFA join'] = {'status': False, 'description': str(e)+' - '+str(request)}
+        else:
+            request_status['other'] = {'status': False, 'description': 'unknown type of request'}
         # XXX Remove from Pendings in database
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
@@ -591,6 +761,15 @@ def portal_reject_request(wsgi_request, request_ids):
 
             PendingAuthority.objects.get(id=request['id']).delete()
 
+        # XXX TMP we should send an email to the user to inform him/her
+        elif request['type'] == 'project':
+            request_status['SFA project'] = {'status': True }
+            PendingProject.objects.get(id=request['id']).delete()
+
+        elif request['type'] == 'join':
+            request_status['SFA join'] = {'status': True }
+            PendingJoin.objects.get(id=request['id']).delete()
+
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
     return status
@@ -621,9 +800,16 @@ def create_slice(wsgi_request, request):
     # Add User to Slice if we have the user_hrn in pendingslice table
     user_hrn = request.get('user_hrn', None)
     user_hrns = list([user_hrn]) if user_hrn else list()
-    
+   
+    # CACHE PB with fields
+    page = Page(wsgi_request)
+    metadata = page.get_metadata()
+    user_md = metadata.details_by_object('user')
+    user_fields = [column['name'] for column in user_md['column']]
+
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    user_query  = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+    #user_query  = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+    user_query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
     user_details_sfa = execute_admin_query(wsgi_request, user_query)
     if not user_details_sfa:
         raise Exception, "User %s doesn't exist, validate user before validating slice" % user_hrn
@@ -710,6 +896,57 @@ def create_pending_slice(wsgi_request, request, email):
     except Exception, e:
         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
+
+def create_pending_project(wsgi_request, request):
+    """
+    """
+
+    # Insert an entry in the PendingProject table
+    s = PendingProject(
+        project_name    = request['project_name'],
+        user_hrn        = request['user_hrn'],
+        email           = request['email'],
+        authority_hrn   = request['authority_hrn'],
+        purpose         = request['purpose'],
+    )
+    s.save()
+
+def create_pending_join(wsgi_request, request):
+    """
+    """
+
+    # Insert an entry in the PendingJoin table
+    s = PendingJoin(
+        user_hrn        = request['user_hrn'],
+        email           = request['email'],
+        project_name    = request['project_name'],
+        authority_hrn   = request['authority_hrn'],
+    )
+    s.save()
+
+
+#     try:
+#         # Send an email: the recipients are the PI of the authority
+#         recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+# 
+#         theme.template_name = 'slice_request_email.txt' 
+#         text_content = render_to_string(theme.template, request)
+#     
+#         theme.template_name = 'slice_request_email.html' 
+#         html_content = render_to_string(theme.template, request)
+#     
+#         theme.template_name = 'slice_request_email_subject.txt'
+#         subject = render_to_string(theme.template, request)
+#         subject = subject.replace('\n', '')
+#     
+#         sender = email
+#         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
+#         msg.attach_alternative(html_content, "text/html")
+#         msg.send()
+#     except Exception, e:
+#         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+
+
 #-------------------------------------------------------------------------------
 # REQUESTS - Users
 #-------------------------------------------------------------------------------
@@ -823,10 +1060,11 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
     import requests
     import time
     from requests.auth import HTTPBasicAuth
-    
-    URL_REST = ConfigEngine.default_iotlab_url
-    LOGIN_ADMIN = ConfigEngine.default_iotlab_admin_user
-    PASSWORD_ADMIN = ConfigEngine.default_iotlab_admin_password
+   
+    engine = ConfigEngine() 
+    URL_REST = engine.iotlab_url()
+    LOGIN_ADMIN = engine.iotlab_admin_user()
+    PASSWORD_ADMIN = engine.iotlab_admin_password()
 
     auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
     headers = {'content-type': 'application/json'}
index 06f02f8..0de9b93 100644 (file)
@@ -49,7 +49,7 @@ class DashboardView (LoginRequiredAutoLogoutView, ThemeView):
 #        else:
         print "SLICE QUERY"
         print "-" * 80
-        slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('slices.slice_hrn')
+        slice_query = Query().get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('slices.slice_hrn')
         page.enqueue_query(slice_query)
         page.enqueue_query(testbed_query)
 
index 533cccf..4424c2e 100644 (file)
@@ -29,12 +29,16 @@ class ActivateEmailView(FreeAccessView, ThemeView):
         if pending_authorities:
             return False                        
         pending_user_email = pending_user.email
-        query = Query.get('myplcuser').filter_by('email', '==', pending_user_email).select('enabled')
-        results = execute_admin_query(self.request, query)
-        for result in results:
-            # User is enabled in PLE
-            if 'enabled' in result and result['enabled']==True:
-                return True
+        try:
+            query = Query.get('myplcuser').filter_by('email', '==', pending_user_email).select('enabled')
+            results = execute_admin_query(self.request, query)
+            for result in results:
+                # User is enabled in PLE
+                if 'enabled' in result and result['enabled']==True:
+                    return True
+        except Exception, e:
+            print "Exception in myplc query = ",e
+
         return False
 
     def dispatch(self, *args, **kwargs):
index 3e9514f..1fe1d2a 100644 (file)
@@ -19,6 +19,7 @@ from myslice.configengine               import ConfigEngine
 from myslice.theme                      import ThemeView
 from portal.account                     import Account, get_expiration
 from portal.models                      import PendingSlice
+from portal.actions                     import authority_check_pis
 
 import json, time
 import activity.user
@@ -89,10 +90,12 @@ class HomeView (FreeAccessView, ThemeView):
                                             acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
                                             acc_user_cred = account_config.get('delegated_user_credential','N/A')
                     # assigning values
-                    if acc_auth_cred=={} or acc_auth_cred=='N/A':
-                        pi = "is_not_pi"
-                    else:
-                        pi = "is_pi"
+                    #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+                    #    pi = "is_not_pi"
+                    #else:
+                    #    pi = "is_pi"
+                    user_email = str(self.request.user)                   
+                    pi = authority_check_pis(self.request, user_email)
 
                     # check if the user has creds or not
                     if acc_user_cred == {} or acc_user_cred == 'N/A':
@@ -156,11 +159,12 @@ class HomeView (FreeAccessView, ThemeView):
                                         acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
                                         acc_user_cred = account_config.get('delegated_user_credential','N/A')
             # assigning values
-            if acc_auth_cred=={} or acc_auth_cred=='N/A':
-                pi = "is_not_pi"
-            else:
-                pi = "is_pi"
-
+            #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+            #    pi = "is_not_pi"
+            #else:
+            #    pi = "is_pi"
+            user_email = str(self.request.user) 
+            pi = authority_check_pis(self.request, user_email)
             # check if the user has creds or not
             if acc_user_cred == {} or acc_user_cred == 'N/A':
                 user_cred = 'no_creds'
index 6dd1b20..8a00435 100644 (file)
@@ -5,6 +5,7 @@ from django.template                import RequestContext
 from django.shortcuts               import render_to_response
 from django.shortcuts               import render
 
+from unfold.page                    import Page
 from unfold.loginrequired           import LoginRequiredAutoLogoutView
 
 from manifold.core.query            import Query
@@ -13,7 +14,8 @@ from manifoldapi.manifoldresult     import ManifoldResult
 from ui.topmenu                     import topmenu_items, the_user
 from myslice.configengine           import ConfigEngine
 
-from myslice.theme                          import ThemeView
+from portal.actions                 import is_pi, authority_check_pis
+from myslice.theme                  import ThemeView
 import json
 
 class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
@@ -30,50 +32,46 @@ class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
         env['theme'] = self.theme
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
-    def get (self, request, state=None):
+    def get (self, request, authority_hrn=None, state=None):
         env = self.default_env()
-
         if request.user.is_authenticated(): 
             env['person'] = self.request.user
-            user_query  = Query().get('user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
-            user_details = execute_query(self.request, user_query)
-            try:
-                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 == {} or acc_auth_cred == 'N/A':
-                pi = "is_not_pi"
+            if authority_hrn is None: 
+                # CACHE PB with fields
+                page = Page(request)
+                metadata = page.get_metadata()
+                user_md = metadata.details_by_object('user')
+                user_fields = [column['name'] for column in user_md['column']]
+                
+                # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+                user_query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==','$user_hrn')
+                #user_query  = Query().get('myslice:user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
+                user_details = execute_query(self.request, user_query)
+                try:
+                    env['user_details'] = user_details[0]
+                except Exception,e:
+                    # If the Query fails, check in local DB 
+                    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 Credentials"
             else:
-                pi = "is_pi"
+                env['project'] = True
+                env['user_details'] = {'parent_authority': authority_hrn}
 
         else: 
             env['person'] = None
-    
+        print "BEFORE  ####------####  is_pi"
+        pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority']) 
+        print "is_pi = ",is_pi
+
         env['theme'] = self.theme
         env['section'] = "Institution"
         env['pi'] = pi 
index 8bd1cdc..ec39f8f 100644 (file)
@@ -21,23 +21,22 @@ class ManagementAboutView (FreeAccessView, ThemeView):
 
     def get (self, request):
         
+        authority_contacts = {}
+        authority = {'authority_hrn':'fed4fire.upmc'}
         if request.user.is_authenticated(): 
-            user_query  = Query().get('user').select('user_hrn','parent_authority').filter_by('user_hrn','==','$user_hrn')
-            user_details = execute_query(self.request, user_query)
-            
             user_local_query  = Query().get('local:user').select('config').filter_by('email','==',str(self.request.user))
             user_local_details = execute_query(self.request, user_local_query)
             user_authority = json.loads(user_local_details[0]['config']).get('authority')
+            print "**************________    management about  = ",user_authority
             # XXX Should be done using Metadata
             # select column.name from local:object where table=='authority'
             authority_query = Query().get('authority').select('authority_hrn', 'name', 'address', 'enabled','description', 
                                                               'scientific', 'city', 'name', 'url', 'country', 'enabled', 'longitude', 
-                                                              'tech', 'latitude', 'pi_users', 'parent_authority', 'onelab_membership', 
+                                                              'tech', 'latitude', 'pi_users', 'onelab_membership', 
                                                               'postcode').filter_by('authority_hrn','==',user_authority)
             authority_details = execute_query(self.request, authority_query)
             
             if authority_details :
-                authority_contacts = {}
                 authority = authority_details[0]
                 if 'scientific' in authority and authority['scientific'] is not None:
                     authority_contacts['scientific'] = [ x.strip()[1:-1] for x in authority['scientific'][1:-1].split(',') ]
index 7c0b222..2c80e41 100644 (file)
@@ -7,6 +7,8 @@ from manifoldapi.manifoldapi         import execute_query
 from django.views.generic.base      import TemplateView
 
 from unfold.loginrequired           import LoginRequiredView
+from unfold.page                    import Page
+
 from django.http                    import HttpResponse
 from django.shortcuts               import render
 
@@ -85,9 +87,15 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
                         credential_authorities.add(authority_hrn)
 
+            # CACHE PB with fields
+            page = Page(self.request)
+            metadata = page.get_metadata()
+            user_md = metadata.details_by_object('user')
+            user_fields = [column['name'] for column in user_md['column']]
+
             # ** Where am I a PI **
             # For this we need to ask SFA (of all authorities) = PI function
-            pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+            pi_authorities_query = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select(user_fields)
             pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
             pi_authorities = set()
             try:
index 52a69da..1be4e82 100644 (file)
@@ -2,7 +2,8 @@ from unfold.loginrequired               import LoginRequiredAutoLogoutView
 #
 from manifold.core.query                import Query
 from manifoldapi.manifoldapi            import execute_query, execute_admin_query
-from portal.actions                     import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account, sfa_update_user
+from portal.actions                     import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account
+from portal.actions                     import sfa_update_user, authority_get_pis, authority_add_pis, authority_remove_pis,authority_check_pis ,clear_user_creds
 #
 from unfold.page                        import Page    
 from ui.topmenu                         import topmenu_items_live, the_user
@@ -52,6 +53,8 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
             #email = user_detail['email']
             if user_detail['config']:
                 config = json.loads(user_detail['config'])
+                authority_hrn = config.get('authority','Unknown Authority')
+                
 
         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
         account_query  = Query().get('local:account').filter_by('user_id', '==', user_id).select('user_id','platform_id','auth_type','config')
@@ -101,11 +104,15 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
                         account_usr_hrn = account_config.get('user_hrn','N/A')
                         account_pub_key = account_config.get('user_public_key','N/A')
                         account_reference = account_config.get ('reference_platform','N/A')
+
                     # credentials of myslice platform
                     if 'myslice' in platform_detail['platform']:
                         acc_user_cred = account_config.get('delegated_user_credential','N/A')
                         acc_slice_cred = account_config.get('delegated_slice_credentials','N/A')
                         acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+                        #usr_hrn of myslice platform. used to check pi or no
+                        account_usr_hrn_myslice = account_config.get('user_hrn','N/A')
+
 
                         if 'N/A' not in acc_user_cred:
                             exp_date = re.search('<expires>(.*)</expires>', acc_user_cred)
@@ -140,8 +147,7 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
 
                             my_auths = [{'auth_name': t[0], 'cred_exp': t[1]}
                                 for t in zip(auth_list, auth_cred_exp_list)]
-
-
+                       
                     # for reference accounts
                     if 'reference' in account_detail['auth_type']:
                         account_type = 'Reference'
@@ -184,6 +190,9 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
         platform_list = [{'platform_no_access': t[0]}
             for t in itertools.izip_longest(total_platform_list)]
 
+        ## check pi or no
+        pi_status = authority_check_pis(self.request, user_email)
+
         context = super(UserView, self).get_context_data(**kwargs)
         context['principal_acc'] = principal_acc_list
         context['ref_acc'] = ref_acc_list
@@ -198,6 +207,7 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
         context['fullname'] = context['firstname'] +' '+ context['lastname']
         context['authority'] = config.get('authority',"Unknown Authority")
         context['user_private_key'] = account_priv_key
+        context['pi'] = pi_status
         
         # XXX This is repeated in all pages
         # more general variables expected in the template
@@ -462,27 +472,51 @@ def user_process(request, **kwargs):
 
     #clear all creds
     elif 'clear_cred' in request.POST:
+        clear_user_creds(request, user_email)
+        messages.success(request, 'All Credentials cleared')
+        return HttpResponseRedirect(redirect_url)
+
+    #make a user PI
+    elif 'makepi' in request.POST:
+        # getting user's authority_hrn
+        config={}
+        for user_config in user_details:
+            if user_config['config']:
+                user_config = json.loads(user_config['config'])
+                authority_hrn = user_config.get('authority','Unknown Authority')
+
+        #getting user_hrn
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
                     if 'myslice' in platform_detail['platform']:
                         account_config = json.loads(account_detail['config'])
-                        user_cred = account_config.get('delegated_user_credential','N/A')
-                        if 'N/A' not in user_cred:
-                            user_hrn = account_config.get('user_hrn','N/A')
-                            user_pub_key = json.dumps(account_config.get('user_public_key','N/A'))
-                            user_priv_key = json.dumps(account_config.get('user_private_key','N/A'))
-                            updated_config = '{"user_public_key":'+ user_pub_key + ', "user_private_key":'+ user_priv_key + ', "user_hrn":"'+ user_hrn + '"}'
-                            user_params = { 'config': updated_config}
-                            manifold_update_account(request, user_id,user_params)
-                            messages.success(request, 'All Credentials cleared')
-                            return HttpResponseRedirect(redirect_url)
-                        else:
-                            messages.error(request, 'Delete error: Credentials are not stored in the server')
-                            return HttpResponseRedirect(redirect_url)
-        else:
-            messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
-            return HttpResponseRedirect(redirect_url)
+                        user_hrn = account_config.get('user_hrn','N/A')
+    
+        authority_add_pis(request, authority_hrn, user_hrn)
+        clear_user_creds(request, user_email)
+        messages.success(request, 'User upgraded to PI')
+        return HttpResponseRedirect(redirect_url)
+
+    elif 'removepi' in request.POST:
+        # getting user's authority_hrn
+        config={}
+        for user_config in user_details:
+            if user_config['config']:
+                user_config = json.loads(user_config['config'])
+                authority_hrn = user_config.get('authority','Unknown Authority')
+        #getting user_hrn
+        for account_detail in account_details:
+            for platform_detail in platform_details:
+                if platform_detail['platform_id'] == account_detail['platform_id']:
+                    if 'myslice' in platform_detail['platform']:
+                        account_config = json.loads(account_detail['config'])
+                        user_hrn = account_config.get('user_hrn','N/A')
+        authority_remove_pis(request, authority_hrn, user_hrn)
+        clear_user_creds(request, user_email)
+        messages.success(request, 'PI downgraded to user')
+        return HttpResponseRedirect(redirect_url)
+        
 
 
     # Download delegated_user_cred
diff --git a/portal/migrations/0010_project.py b/portal/migrations/0010_project.py
new file mode 100644 (file)
index 0000000..7046204
--- /dev/null
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'PendingProject'
+        db.create_table(u'portal_pendingproject', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('project_name', self.gf('django.db.models.fields.TextField')()),
+            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+            ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingProject'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'PendingProject'
+        db.delete_table(u'portal_pendingproject')
+
+
+    models = {
+        u'portal.institution': {
+            'Meta': {'object_name': 'Institution'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingauthority': {
+            'Meta': {'object_name': 'PendingAuthority'},
+            'address_city': ('django.db.models.fields.TextField', [], {}),
+            'address_country': ('django.db.models.fields.TextField', [], {}),
+            'address_line1': ('django.db.models.fields.TextField', [], {}),
+            'address_line2': ('django.db.models.fields.TextField', [], {}),
+            'address_line3': ('django.db.models.fields.TextField', [], {}),
+            'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+            'address_state': ('django.db.models.fields.TextField', [], {}),
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+            'site_authority': ('django.db.models.fields.TextField', [], {}),
+            'site_latitude': ('django.db.models.fields.TextField', [], {}),
+            'site_longitude': ('django.db.models.fields.TextField', [], {}),
+            'site_name': ('django.db.models.fields.TextField', [], {}),
+            'site_url': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingproject': {
+            'Meta': {'object_name': 'PendingProject'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project_name': ('django.db.models.fields.TextField', [], {}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingslice': {
+            'Meta': {'object_name': 'PendingSlice'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'slice_name': ('django.db.models.fields.TextField', [], {}),
+            'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendinguser': {
+            'Meta': {'object_name': 'PendingUser'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+            'email_hash': ('django.db.models.fields.TextField', [], {}),
+            'first_name': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_name': ('django.db.models.fields.TextField', [], {}),
+            'login': ('django.db.models.fields.TextField', [], {}),
+            'password': ('django.db.models.fields.TextField', [], {}),
+            'pi': ('django.db.models.fields.TextField', [], {}),
+            'private_key': ('django.db.models.fields.TextField', [], {}),
+            'public_key': ('django.db.models.fields.TextField', [], {}),
+            'status': ('django.db.models.fields.TextField', [], {}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        }
+    }
+
+    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0011_join.py b/portal/migrations/0011_join.py
new file mode 100644 (file)
index 0000000..f403289
--- /dev/null
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        "Write your forwards methods here."
+        # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
+
+    def backwards(self, orm):
+        "Write your backwards methods here."
+
+    models = {
+        u'portal.institution': {
+            'Meta': {'object_name': 'Institution'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingauthority': {
+            'Meta': {'object_name': 'PendingAuthority'},
+            'address_city': ('django.db.models.fields.TextField', [], {}),
+            'address_country': ('django.db.models.fields.TextField', [], {}),
+            'address_line1': ('django.db.models.fields.TextField', [], {}),
+            'address_line2': ('django.db.models.fields.TextField', [], {}),
+            'address_line3': ('django.db.models.fields.TextField', [], {}),
+            'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+            'address_state': ('django.db.models.fields.TextField', [], {}),
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+            'site_authority': ('django.db.models.fields.TextField', [], {}),
+            'site_latitude': ('django.db.models.fields.TextField', [], {}),
+            'site_longitude': ('django.db.models.fields.TextField', [], {}),
+            'site_name': ('django.db.models.fields.TextField', [], {}),
+            'site_url': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingjoin': {
+            'Meta': {'object_name': 'PendingJoin'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingproject': {
+            'Meta': {'object_name': 'PendingProject'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project_name': ('django.db.models.fields.TextField', [], {}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingslice': {
+            'Meta': {'object_name': 'PendingSlice'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'slice_name': ('django.db.models.fields.TextField', [], {}),
+            'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendinguser': {
+            'Meta': {'object_name': 'PendingUser'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+            'email_hash': ('django.db.models.fields.TextField', [], {}),
+            'first_name': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_name': ('django.db.models.fields.TextField', [], {}),
+            'login': ('django.db.models.fields.TextField', [], {}),
+            'password': ('django.db.models.fields.TextField', [], {}),
+            'pi': ('django.db.models.fields.TextField', [], {}),
+            'private_key': ('django.db.models.fields.TextField', [], {}),
+            'public_key': ('django.db.models.fields.TextField', [], {}),
+            'status': ('django.db.models.fields.TextField', [], {}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        }
+    }
+
+    complete_apps = ['portal']
+    symmetrical = True
diff --git a/portal/migrations/0012_initial.py b/portal/migrations/0012_initial.py
new file mode 100644 (file)
index 0000000..9b58fae
--- /dev/null
@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Institution'
+        db.create_table(u'portal_institution', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.TextField')()),
+        ))
+        db.send_create_signal(u'portal', ['Institution'])
+
+        # Adding model 'PendingUser'
+        db.create_table(u'portal_pendinguser', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('first_name', self.gf('django.db.models.fields.TextField')()),
+            ('last_name', self.gf('django.db.models.fields.TextField')()),
+            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)),
+            ('password', self.gf('django.db.models.fields.TextField')()),
+            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('public_key', self.gf('django.db.models.fields.TextField')()),
+            ('private_key', self.gf('django.db.models.fields.TextField')()),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('login', self.gf('django.db.models.fields.TextField')()),
+            ('pi', self.gf('django.db.models.fields.TextField')()),
+            ('email_hash', self.gf('django.db.models.fields.TextField')()),
+            ('status', self.gf('django.db.models.fields.TextField')()),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingUser'])
+
+        # Adding model 'PendingAuthority'
+        db.create_table(u'portal_pendingauthority', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('site_name', self.gf('django.db.models.fields.TextField')()),
+            ('site_authority', self.gf('django.db.models.fields.TextField')()),
+            ('site_abbreviated_name', self.gf('django.db.models.fields.TextField')()),
+            ('site_url', self.gf('django.db.models.fields.TextField')()),
+            ('site_latitude', self.gf('django.db.models.fields.TextField')()),
+            ('site_longitude', self.gf('django.db.models.fields.TextField')()),
+            ('address_line1', self.gf('django.db.models.fields.TextField')()),
+            ('address_line2', self.gf('django.db.models.fields.TextField')()),
+            ('address_line3', self.gf('django.db.models.fields.TextField')()),
+            ('address_city', self.gf('django.db.models.fields.TextField')()),
+            ('address_postalcode', self.gf('django.db.models.fields.TextField')()),
+            ('address_state', self.gf('django.db.models.fields.TextField')()),
+            ('address_country', self.gf('django.db.models.fields.TextField')()),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingAuthority'])
+
+        # Adding model 'PendingSlice'
+        db.create_table(u'portal_pendingslice', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('slice_name', self.gf('django.db.models.fields.TextField')()),
+            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+            ('number_of_nodes', self.gf('django.db.models.fields.TextField')(default=0)),
+            ('type_of_nodes', self.gf('django.db.models.fields.TextField')(default='NA')),
+            ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingSlice'])
+
+        # Adding model 'PendingProject'
+        db.create_table(u'portal_pendingproject', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('project_name', self.gf('django.db.models.fields.TextField')()),
+            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('email', self.gf('django.db.models.fields.TextField')()),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
+            ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingProject'])
+
+        # Adding model 'PendingJoin'
+        db.create_table(u'portal_pendingjoin', (
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('email', self.gf('django.db.models.fields.TextField')()),
+            ('project_name', self.gf('django.db.models.fields.TextField')(null=True)),
+            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
+            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal(u'portal', ['PendingJoin'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Institution'
+        db.delete_table(u'portal_institution')
+
+        # Deleting model 'PendingUser'
+        db.delete_table(u'portal_pendinguser')
+
+        # Deleting model 'PendingAuthority'
+        db.delete_table(u'portal_pendingauthority')
+
+        # Deleting model 'PendingSlice'
+        db.delete_table(u'portal_pendingslice')
+
+        # Deleting model 'PendingProject'
+        db.delete_table(u'portal_pendingproject')
+
+        # Deleting model 'PendingJoin'
+        db.delete_table(u'portal_pendingjoin')
+
+
+    models = {
+        u'portal.institution': {
+            'Meta': {'object_name': 'Institution'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingauthority': {
+            'Meta': {'object_name': 'PendingAuthority'},
+            'address_city': ('django.db.models.fields.TextField', [], {}),
+            'address_country': ('django.db.models.fields.TextField', [], {}),
+            'address_line1': ('django.db.models.fields.TextField', [], {}),
+            'address_line2': ('django.db.models.fields.TextField', [], {}),
+            'address_line3': ('django.db.models.fields.TextField', [], {}),
+            'address_postalcode': ('django.db.models.fields.TextField', [], {}),
+            'address_state': ('django.db.models.fields.TextField', [], {}),
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
+            'site_authority': ('django.db.models.fields.TextField', [], {}),
+            'site_latitude': ('django.db.models.fields.TextField', [], {}),
+            'site_longitude': ('django.db.models.fields.TextField', [], {}),
+            'site_name': ('django.db.models.fields.TextField', [], {}),
+            'site_url': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingjoin': {
+            'Meta': {'object_name': 'PendingJoin'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingproject': {
+            'Meta': {'object_name': 'PendingProject'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project_name': ('django.db.models.fields.TextField', [], {}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendingslice': {
+            'Meta': {'object_name': 'PendingSlice'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
+            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'slice_name': ('django.db.models.fields.TextField', [], {}),
+            'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        },
+        u'portal.pendinguser': {
+            'Meta': {'object_name': 'PendingUser'},
+            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+            'email_hash': ('django.db.models.fields.TextField', [], {}),
+            'first_name': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_name': ('django.db.models.fields.TextField', [], {}),
+            'login': ('django.db.models.fields.TextField', [], {}),
+            'password': ('django.db.models.fields.TextField', [], {}),
+            'pi': ('django.db.models.fields.TextField', [], {}),
+            'private_key': ('django.db.models.fields.TextField', [], {}),
+            'public_key': ('django.db.models.fields.TextField', [], {}),
+            'status': ('django.db.models.fields.TextField', [], {}),
+            'user_hrn': ('django.db.models.fields.TextField', [], {})
+        }
+    }
+
+    complete_apps = ['portal']
\ No newline at end of file
index cc484b5..f578d93 100644 (file)
@@ -96,3 +96,18 @@ class PendingSlice(models.Model):
     type_of_nodes   = models.TextField(default='NA')
     purpose         = models.TextField(default='NA')
     created         = models.DateTimeField(auto_now_add = True)
+    
+class PendingProject(models.Model):
+    project_name    = models.TextField()
+    user_hrn        = models.TextField()
+    email           = models.TextField()
+    authority_hrn   = models.TextField(null=True)
+    purpose         = models.TextField(default='NA')
+    created         = models.DateTimeField(auto_now_add = True)
+
+class PendingJoin(models.Model):
+    user_hrn        = models.TextField()
+    email           = models.TextField()
+    project_name    = models.TextField(null=True)
+    authority_hrn   = models.TextField()
+    created         = models.DateTimeField(auto_now_add = True)
diff --git a/portal/projectrequestview.py b/portal/projectrequestview.py
new file mode 100644 (file)
index 0000000..8a48428
--- /dev/null
@@ -0,0 +1,320 @@
+from django.shortcuts           import render
+from django.contrib.sites.models import Site
+
+from manifold.core.query        import Query
+from manifoldapi.manifoldapi    import execute_admin_query, execute_query
+
+from unfold.loginrequired       import LoginRequiredAutoLogoutView
+
+from portal.actions import create_pending_project, create_pending_join, sfa_add_authority, authority_add_pis, is_pi
+from portal.models import PendingProject, PendingJoin
+
+from myslice.theme import ThemeView
+
+import json, time, re
+
+class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
+    template_name = 'projectrequest_view.html'
+    
+    def getAuthorities(self, request):
+        authorities_query = Query.get('authority').select('name', 'authority_hrn')
+        authorities = execute_admin_query(request, authorities_query)
+        if authorities is not None:
+            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+            authorities = sorted(authorities, key=lambda k: k['name'])
+        return authorities
+    
+    def getUserAuthority(self, request):
+        # Get user_email (XXX Would deserve to be simplified)
+        user_query  = Query().get('local:user').select('email','config')
+        user_details = execute_query(request, user_query)
+        for user_detail in user_details:
+            user_config = json.loads(user_detail['config'])
+            user_authority = user_config.get('authority','N/A')
+        return user_authority
+    
+    def getUserHrn(self, request):
+        user_hrn = None
+        
+        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+        account_details = execute_query(request, account_query)
+
+        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+        platform_details = execute_query(request, platform_query)
+        
+        # getting user_hrn from local:account
+        for account_detail in account_details:
+            for platform_detail in platform_details:
+                if platform_detail['platform_id'] == account_detail['platform_id']:
+                    # taking user_hrn only from myslice account
+                    # NOTE: we should later handle accounts filter_by auth_type= managed OR user
+                    if 'myslice' in platform_detail['platform']:
+                        account_config = json.loads(account_detail['config'])
+                        user_hrn = account_config.get('user_hrn','N/A')
+        return user_hrn        
+
+    def getUserEmail(self, request):
+        # Get user_email (XXX Would deserve to be simplified)
+        user_query  = Query().get('local:user').select('email','config')
+        user_details = execute_query(request, user_query)
+        user_email = user_details[0].get('email')
+        return user_email
+                   
+    def post(self, request):
+        return self.handle_request(request, 'POST')
+
+    def get(self, request):
+        return self.handle_request(request, 'GET')
+
+    def handle_request(self, wsgi_request, method):
+        errors = []
+        authority_hrn = None
+        authority_name = None
+        
+        #errors.append(wsgi_request.POST)
+
+        user_hrn = self.getUserHrn(wsgi_request)
+
+        user_email = self.getUserEmail(wsgi_request)
+        
+        authorities = self.getAuthorities(wsgi_request)
+        
+        user_authority = self.getUserAuthority(wsgi_request)
+        
+        # getting the org from authority
+        for authority in authorities:
+            if authority['authority_hrn'] == user_authority:
+                authority_name = authority['name']
+        
+        if method == 'POST' :
+        
+            if 'join' in wsgi_request.POST:
+                post = {
+                    'user_hrn'          : user_hrn,
+                    'email'             : user_email,
+                    'project_name'      : wsgi_request.POST.get('project_name', ''),
+                    'authority_hrn'     : wsgi_request.POST.get('project_name', ''),
+                }
+
+            else:
+                post = {
+                    'user_hrn'          : user_hrn,
+                    'email'             : user_email,
+                    'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
+                    'project_name'      : wsgi_request.POST.get('project_name', ''),
+                    'purpose'           : wsgi_request.POST.get('purpose', ''),
+                }
+
+                if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
+                    errors.append('Organization is mandatory')
+    
+                if (post['purpose'] is None or post['purpose'] == ''):
+                    errors.append('Project purpose is mandatory')
+
+                if (re.search(r'^[A-Za-z0-9_]*$', post['project_name']) == None):
+                    errors.append('Project name may contain only letters, numbers, and underscore.')
+
+            # What kind of project name is valid?
+            if (post['project_name'] is None or post['project_name'] == ''):
+                errors.append('Project name is mandatory')
+            
+            if not errors:
+                print "is_pi on auth_hrn = ", user_authority
+                if is_pi(wsgi_request, user_hrn, user_authority):
+                    # PIs can directly create/join project in their own authority...
+                    if 'join' in wsgi_request.POST:
+                        authority_add_pis(wsgi_request, post['project_name'], user_hrn)
+                    else:
+                        hrn = post['authority_hrn'] + '.' + post['project_name']
+                        sfa_add_authority(wsgi_request, {'authority_hrn':hrn})
+                        authority_add_pis(wsgi_request, hrn, user_hrn)
+                    self.template_name = 'project-request-done-view.html'
+                else:
+                    # Otherwise a wsgi_request is sent to the PI
+                    if 'join' in wsgi_request.POST:
+                        create_pending_join(wsgi_request, post)
+                    else:
+                        create_pending_project(wsgi_request, post)
+                    self.template_name = 'project-request-ack-view.html'
+
+        # retrieves the pending projects creation list
+        pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
+        # retrieves the pending join a project list
+        pending_join_projects = PendingJoin.objects.all().filter(user_hrn=user_hrn)
+
+        root_authority = user_authority.split('.', 1)[0]                  
+        env = {
+               'errors':        errors,
+               'username':      wsgi_request.user,
+               'theme':         self.theme,
+               'authorities':   authorities,
+               'authority_hrn': user_authority,
+               'root_authority_hrn': root_authority,
+               'pending_projects': pending_projects,
+               'pending_join_projects': pending_join_projects,
+        }
+        return render(wsgi_request, self.template, env)
+    
+        
+    
+        """
+        """
+        errors = []
+        slice_name =''
+        purpose=''
+        url=''
+        authority_hrn = None
+        authority_name = None
+        # Retrieve the list of authorities
+        authorities_query = Query.get('authority').select('name', 'authority_hrn')
+        authorities = execute_admin_query(wsgi_request, authorities_query)
+        if authorities is not None:
+            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+            authorities = sorted(authorities, key=lambda k: k['name'])
+
+        # Get user_email (XXX Would deserve to be simplified)
+        user_query  = Query().get('local:user').select('email','config')
+        user_details = execute_query(wsgi_request, user_query)
+        user_email = user_details[0].get('email')
+        # getting user_hrn
+        for user_detail in user_details:
+            user_config = json.loads(user_detail['config'])
+            user_authority = user_config.get('authority','N/A')              
+        # getting the org from authority        
+        for authority in authorities:
+            if authority['authority_hrn'] == user_authority:
+                authority_name = authority['name']
+
+        # Handle the case when we use only hrn and not name
+        if authority_name is None:
+            authority_name = user_authority
+        #
+        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+        account_details = execute_query(wsgi_request, account_query)
+        #
+        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+        platform_details = execute_query(wsgi_request, platform_query)
+        
+        user_hrn = None
+        # getting user_hrn from local:account
+        for account_detail in account_details:
+            for platform_detail in platform_details:
+                if platform_detail['platform_id'] == account_detail['platform_id']:
+                    # taking user_hrn only from myslice account
+                    # NOTE: we should later handle accounts filter_by auth_type= managed OR user
+                    if 'myslice' in platform_detail['platform']:
+                        account_config = json.loads(account_detail['config'])
+                        user_hrn = account_config.get('user_hrn','N/A')
+                        acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+
+
+        # checking if pi or not
+        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
+            pi = "is_not_pi"
+        else:
+            pi = "is_pi"
+
+
+        # Page rendering
+#         page = Page(wsgi_request)
+#         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
+#         page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+#         page.expose_js_metadata()
+
+        if method == 'POST':
+            # The form has been submitted
+
+            # get the domain url
+#             current_site = Site.objects.get_current()
+#             current_site = current_site.domain
+            
+            # getting the authority_hrn from the selected organization
+            for authority in authorities:
+                if authority['name'] == wsgi_request.POST.get('org_name', ''):
+                    authority_hrn = authority['authority_hrn']
+
+            # Handle the case when we use only hrn and not name
+            if authority_hrn is None:
+                authority_hrn = wsgi_request.POST.get('org_name', '')
+
+            slice_request = {
+                'type'              : 'slice',
+                'id'                : None,
+                'user_hrn'          : user_hrn,
+                'email'             : user_email,
+                'timestamp'         : time.time(),
+                'authority_hrn'     : authority_hrn,
+                'organization'      : wsgi_request.POST.get('org_name', ''),
+                'slice_name'        : wsgi_request.POST.get('slice_name', ''),
+                'url'               : wsgi_request.POST.get('url', ''),
+                'purpose'           : wsgi_request.POST.get('purpose', ''),
+                'current_site'      : current_site
+            }
+            
+            # create slice_hrn based on authority_hrn and slice_name
+#             slice_name = slice_request['slice_name']
+            req_slice_hrn = authority_hrn + '.' + slice_name
+            # comparing requested slice_hrn with the existing slice_hrn 
+            slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
+            slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
+            for _slice in slice_details_sfa:
+                if _slice['slice_hrn'] == req_slice_hrn:
+                    errors.append('Slice already exists. Please use a different slice name.')
+            
+
+            # What kind of slice name is valid?
+            if (slice_name is None or slice_name == ''):
+                errors.append('Slice name is mandatory')
+            
+            if (re.search(r'^[A-Za-z0-9_]*$', slice_name) == None):
+                errors.append('Slice name may contain only letters, numbers, and underscore.')
+            
+            organization = slice_request['organization']    
+            if (organization is None or organization == ''):
+                errors.append('Organization is mandatory')
+
+
+    
+            purpose = slice_request['purpose']
+            if (purpose is None or purpose == ''):
+                errors.append('Experiment purpose is mandatory')
+
+            url = slice_request['url']
+
+            if not errors:
+                if is_pi(wsgi_request, user_hrn, authority_hrn):
+                    # PIs can directly create slices in their own authority...
+                    create_slice(wsgi_request, slice_request)
+                    clear_user_creds(wsgi_request, user_email)
+                    self.template_name = 'slice-request-done-view.html'
+                else:
+                    # Otherwise a wsgi_request is sent to the PI
+                    create_pending_slice(wsgi_request, slice_request, user_email)
+                    self.template_name = 'slice-request-ack-view.html'
+                
+                # log user activity
+                activity.user.slice(wsgi_request)
+                
+                return render(wsgi_request, self.template, {'theme': self.theme}) # Redirect after POST
+        else:
+            slice_request = {}
+
+        template_env = {
+            'username': wsgi_request.user.email,
+            'errors': errors,
+            'slice_name': slice_name,
+            'purpose': purpose,
+            'email': user_email,
+            'user_hrn': user_hrn,
+            'url': url,
+            'pi': pi,
+            'authority_name': authority_name,        
+            'authority_hrn': user_authority,        
+            'cc_myself': True,
+            'authorities': authorities,
+            'theme': self.theme,
+            'section': "Slice request"
+        }
+        template_env.update(slice_request)
+        template_env.update(page.prelude_env())
+        return render(wsgi_request, self.template, template_env)
index 8749f53..c54bcab 100644 (file)
@@ -45,6 +45,7 @@ class RegistrationView (FreeAccessView, ThemeView):
         authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
         if authorities is not None:
+            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
             authorities = sorted(authorities, key=lambda k: k['name'])
         
         print "############ BREAKPOINT 1 #################"
@@ -138,7 +139,7 @@ class RegistrationView (FreeAccessView, ThemeView):
                 # sqlite3 /var/unfold/unfold.sqlite3
                 # select email from auth_user;
                 if UserModel._default_manager.filter(email__iexact = user_request['email']): 
-                    errors.append('<a href="/contact">Contact OneLab support</a> or try with another email.')
+                    errors.append('<a href="/contact">Contact support</a> or try with another email.')
 
                 # XXX TODO: Factorize with portal/accountview.py
                 # XXX TODO: Factorize with portal/registrationview.py
index e6683bd..a880d39 100644 (file)
@@ -7,7 +7,7 @@ from unfold.page                import Page
 from manifold.core.query        import Query
 from manifoldapi.manifoldapi    import execute_admin_query, execute_query
 
-from portal.actions             import is_pi, create_slice, create_pending_slice, clear_user_creds
+from portal.actions             import is_pi, create_slice, create_pending_slice, clear_user_creds, authority_check_pis
 #from portal.forms               import SliceRequestForm
 from unfold.loginrequired       import LoginRequiredAutoLogoutView
 from ui.topmenu                 import topmenu_items_live, the_user
@@ -42,7 +42,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
         authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
         if authorities is not None:
-            authorities = sorted(authorities)
+            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
+            authorities = sorted(authorities, key=lambda k: k['name'])
 
         # Get user_email (XXX Would deserve to be simplified)
         user_query  = Query().get('local:user').select('email','config')
@@ -60,14 +61,14 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
         # Handle the case when we use only hrn and not name
         if authority_name is None:
             authority_name = user_authority
-        #
+        
         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
         account_details = execute_query(wsgi_request, account_query)
-        #
+        
         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
         platform_details = execute_query(wsgi_request, platform_query)
         user_hrn = None
-        # getting user_hrn from local:account
+        #getting user_hrn from local:account
         for account_detail in account_details:
             for platform_detail in platform_details:
                 if platform_detail['platform_id'] == account_detail['platform_id']:
@@ -76,20 +77,22 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
                     if 'myslice' in platform_detail['platform']:
                         account_config = json.loads(account_detail['config'])
                         user_hrn = account_config.get('user_hrn','N/A')
-                        acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+        #                acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
 
 
         # checking if pi or not
-        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-            pi = "is_not_pi"
-        else:
-            pi = "is_pi"
+        #if acc_auth_cred == {} or acc_auth_cred == 'N/A':
+        #    pi = "is_not_pi"
+        #else:
+        #    pi = "is_pi"
 
+        pi = authority_check_pis (wsgi_request, user_email)
+        print "SLICEREQUESTVIEW.PY -----  pi=",pi
 
         # Page rendering
         page = Page(wsgi_request)
         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
-        page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+        page.add_css_files ( [ "css/jquery-ui.css" ] )
         page.expose_js_metadata()
 
         if method == 'POST':
@@ -108,6 +111,11 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             if authority_hrn is None:
                 authority_hrn = wsgi_request.POST.get('org_name', '')
 
+            # Handle project if used
+            project = wsgi_request.POST.get('project', None)
+            if project is not None and project != '':
+                authority_hrn = project
+
             slice_request = {
                 'type'              : 'slice',
                 'id'                : None,
@@ -126,7 +134,7 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             slice_name = slice_request['slice_name']
             req_slice_hrn = authority_hrn + '.' + slice_name
             # comparing requested slice_hrn with the existing slice_hrn 
-            slice_query  = Query().get('slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
+            slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
             slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
             for _slice in slice_details_sfa:
                 if _slice['slice_hrn'] == req_slice_hrn:
index 3f0c3b4..c394345 100644 (file)
@@ -60,7 +60,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
 
         query_resource_all = Query.get('resource').select(resource_fields)
-        page.enqueue_query(query_resource_all)
+        #page.enqueue_query(query_resource_all)
 
         # leases query
         #lease_md = metadata.details_by_object('lease')
index ca94231..324ee0a 100644 (file)
@@ -17,6 +17,8 @@ from myslice.configengine import ConfigEngine
 from myslice.theme import ThemeView
 from myslice.configengine import ConfigEngine
 
+from sfa.planetlab.plxrn import hash_loginbase
+
 import urllib2,json
 
 class ExperimentView (FreeAccessView, ThemeView):
@@ -26,12 +28,14 @@ class ExperimentView (FreeAccessView, ThemeView):
   
         username = self.request.user    
         
-        split_slicename = slicename.split('.')
-        ple_slicename = split_slicename[0] + '8' + split_slicename[1] + '_' + split_slicename[2]
-
-        query_current_resources = Query.get('slice').select('resource').filter_by('slice_hrn','==',slicename)
+        query_current_resources = Query.get('slice').select('resource','parent_authority').filter_by('slice_hrn','==',slicename)
         current_resources = execute_query(request, query_current_resources)
 
+        parent_authority = current_resources[0]['parent_authority']
+        
+        split_slicename = slicename.split('.')
+        ple_slicename = hash_loginbase(parent_authority) + '_' + split_slicename[-1]
+
         ple_resource_list=[]
         nitos_resource_list=[]
         nitos_paris_resource_list=[]
index bcb2950..f1ba3d8 100644 (file)
@@ -128,6 +128,15 @@ table.profile form{
   margin-right: 15px;
 
 }
+
+#makepi {
+  position:relative;
+  width: 215px;
+  float: right;
+  margin-right: 15px;
+
+}
+
 #edit_password table {
  display:inline;
  margin: auto;
index 49771c2..70de2a8 100644 (file)
@@ -13,10 +13,9 @@ a, a:active, a:focus {
 
 h1 {
     border-bottom:1px solid #DDDDDD;
-    padding:0 0 0 0;
-    margin:0 0 0 0;
+    padding:0;
+    margin:25px 0;
     font-size:14pt;
-    margin-top: 12px;
 }
 h1 img {
     vertical-align:middle;
@@ -31,6 +30,23 @@ h3 {
     font-size:13pt;
     color:#201E62;
 }
+input[type=checkbox] {
+  min-width:5px !important;
+  margin-left:0 !important;
+}
+input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number] {
+    min-width:260px;
+    padding:6px;
+    border:1pt solid #CCCCCC;
+    vertical-align:bottom;
+    border-radius:0;
+}
+
+textarea {
+    padding:6px;
+    border:1pt solid #CCCCCC !important;
+    border-radius:0 !important;
+}
 
 div.wrapper {
     width:980px;
@@ -44,7 +60,7 @@ div.wrapper {
 
 
 div.wide {
-    margin:25px auto;
+    margin:0 auto 25px auto;
     padding:0 25px;
 }
 
@@ -70,13 +86,10 @@ div#header {
 }
 
 div#secondary {
-    
 }
 
 div#secondary ul {
-    position:absolute;
-    top:20px;
-    right:0;
+       float:right;
 }
 
 div#secondary li {
@@ -100,6 +113,7 @@ div#navigation {
     background-color:orange;
     width:100%;
     height:40px;
+    text-align: center;
 }
 div#navigation div.wrapper {
     text-align:center;
@@ -115,21 +129,26 @@ div#navigation ul {
 div#navigation li {
     color:white;
     font-family:helvetica, sans-serif;
-    font-size:10pt ;
-    font-weight:normal;
+    font-size:9pt ;
+    font-weight:bold;
     line-height:0.8em;
     letter-spacing:0.6pt;
     list-style:none;
     float:left;
     padding:0;
-    margin:15px 25px 0 0;
+    margin:16px 25px 0 0;
 }
 div#navigation li a {
-    color:white;
+    color:#003333;
+}
+div#navigation .iconlogout {
+    margin-top:-10px;
+    margin-right:2px;
+    color:#003333;
 }
 div#navigation li a:hover {
     text-decoration:none;
-    color:#B8B2FF;
+    color:white;
 }
 div#navigation li:last-child {
     margin-right:0;
@@ -337,6 +356,7 @@ ul.nav-section li a {
 ul.nav-section li:first-child {
     padding:0;
 }
+/* it used to give space for the icon, which has been removed
 ul.nav-section li:first-child a {
     font-weight:bold;
     padding:6px 15px 4px 15px;
@@ -344,6 +364,8 @@ ul.nav-section li:first-child a {
 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;
@@ -363,37 +385,54 @@ ul.nav-resources a {
 div#slice-view {
     margin:0;
 }
-div.list-group-item {
-    border:0;
-    background-color:white;
-    font-weight:bold;
-    padding-left:0;
+
+/* FACILITY/TESTBED filters */
+div.sl-filter-facilities {
+    padding:0 5px;
 }
-a.list-group-item {
-    border:0;
-    background-color:white;
-    padding:3px 0 3px 10px;
-    border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+    margin-bottom:15px;
+    
 }
-a.list-group-item.active, a.list-group-item.active:hover {
-    font-weight: bold;
+img.sl-image {
+    margin:0 5px 5px 0;
+    padding:0;
+    vertical-align:middle;
+}
+a.sl-facility {
+    color:gray;
+    text-decoration:none;
+}
+a.sl-facility:hover {
+    color:#342961;
+}
+a.sl-facility.active {
     color:black;
-    background-color:transparent;
-    border-left:2pt blue solid;
+    text-decoration:none;
 }
-a.list-group-item.active:hover {
-    background-color:#dddddd;
+a.sl-facility::before {
+    content: " ";
 }
-a.list-group-item:hover {
-    border-left:2pt blue solid;
+div.sl-facilities {
+    border-bottom:#CCCCCC 1px solid;
+    padding-bottom:15px;
+    margin-bottom:15px;
 }
-a.list-group-item p.list-group-item-text {
-    font-size:9pt;
-    font-style:italic;
-    font-weight: normal;
-    color: black !important;
+div.sl-facilities:last-child {
+    border:0;
+}
+a.sl-testbed {
+    color:gray;
+    text-decoration:none;
+    margin-left:25px;
+    margin-bottom:5px;
+}
+a.sl-testbed:hover {
+    color:#342961;
+}
+a.sl-testbed.active {
+    color:black;
 }
-
 div#slice-info {
     margin-top:25px;
 }
@@ -483,12 +522,51 @@ div.dataTables_filter label{
     width:400px;
 }
 
+div.sl-filter-resources {
+    margin:10px 0;
+    text-align:center;
+}
+span.sl-resources {
+    font-size:9pt;
+    color:gray;
+}
+a.sl-resources {
+    font-size:9pt;
+    border:0;
+    padding:2px 8px;
+    margin:0 5px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+    text-align: center;
+}
+a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
+    border:0;
+    padding:2px 8px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+    background-color:#FFA500;
+    color:#000000;
+}
+a.sl-resources:first-child {
+}
+button.btn-apply {
+    background-color:#FFA500;
+    border-bottom: 2pt solid #FFCA00;
+    color:black;
+    font-size:13px;
+    padding:2px 8px;
+    margin:0 5px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+    text-align: center;
+}
+
 /**/
 .header {
   -moz-box-shadow:    0 0 1px rgba(82,82,82,0.6);
   -webkit-box-shadow: 0 0 1px rgba(82,82,82,0.6);
   box-shadow:         0 0 1px rgba(82,82,82,0.6);
-  height:61px;
+  height:60#px;
   background-color:white;
 }
 div.navigation {
@@ -588,7 +666,11 @@ div.dataTables_filter label{
     float:left;
     width:400px;
 }
-
+div.breadcrumbs {
+    margin:15px 0;
+    color:gray;
+    font-size:10pt;
+}
 /* Service Directory */
 
 div#appservices div.row {
diff --git a/portal/static/css/jquery-ui.css b/portal/static/css/jquery-ui.css
new file mode 100644 (file)
index 0000000..ec69f79
--- /dev/null
@@ -0,0 +1,1225 @@
+/*! jQuery UI - v1.11.2 - 2014-10-16
+* http://jqueryui.com
+* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+    display: none;
+}
+.ui-helper-hidden-accessible {
+    border: 0;
+    clip: rect(0 0 0 0);
+    height: 1px;
+    margin: -1px;
+    overflow: hidden;
+    padding: 0;
+    position: absolute;
+    width: 1px;
+}
+.ui-helper-reset {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    outline: 0;
+    line-height: 1.3;
+    text-decoration: none;
+    font-size: 100%;
+    list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+    content: "";
+    display: table;
+    border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+    clear: both;
+}
+.ui-helper-clearfix {
+    min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+    width: 100%;
+    height: 100%;
+    top: 0;
+    left: 0;
+    position: absolute;
+    opacity: 0;
+    filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+    z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+    cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+    display: block;
+    text-indent: -99999px;
+    overflow: hidden;
+    background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+}
+.ui-accordion .ui-accordion-header {
+    display: block;
+    cursor: pointer;
+    position: relative;
+    margin: 2px 0 0 0;
+    padding: .5em .5em .5em .7em;
+    min-height: 0; /* support: IE7 */
+    font-size: 100%;
+}
+.ui-accordion .ui-accordion-icons {
+    padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+    padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+    position: absolute;
+    left: .5em;
+    top: 50%;
+    margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+    padding: 1em 2.2em;
+    border-top: 0;
+    overflow: auto;
+}
+.ui-autocomplete {
+    position: absolute;
+    top: 0;
+    left: 0;
+    cursor: default;
+}
+.ui-button {
+    display: inline-block;
+    position: relative;
+    padding: 0;
+    line-height: normal;
+    margin-right: .1em;
+    cursor: pointer;
+    vertical-align: middle;
+    text-align: center;
+    overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+    text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+    width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+    width: 2.4em;
+}
+.ui-button-icons-only {
+    width: 3.4em;
+}
+button.ui-button-icons-only {
+    width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+    display: block;
+    line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+    padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+    padding: .4em;
+    text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+    padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+    padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+    padding-left: 2.1em;
+    padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+    padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+    position: absolute;
+    top: 50%;
+    margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+    left: 50%;
+    margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+    left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+    right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+    margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+    margin-left: 0;
+    margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+}
+.ui-datepicker {
+    width: 17em;
+    padding: .2em .2em 0;
+    display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+    position: relative;
+    padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+    position: absolute;
+    top: 2px;
+    width: 1.8em;
+    height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+    top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+    left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+    right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+    left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+    right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+    display: block;
+    position: absolute;
+    left: 50%;
+    margin-left: -8px;
+    top: 50%;
+    margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+    margin: 0 2.3em;
+    line-height: 1.8em;
+    text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+    font-size: 1em;
+    margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+    width: 45%;
+}
+.ui-datepicker table {
+    width: 100%;
+    font-size: .9em;
+    border-collapse: collapse;
+    margin: 0 0 .4em;
+}
+.ui-datepicker th {
+    padding: .7em .3em;
+    text-align: center;
+    font-weight: bold;
+    border: 0;
+}
+.ui-datepicker td {
+    border: 0;
+    padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+    display: block;
+    padding: .2em;
+    text-align: right;
+    text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+    background-image: none;
+    margin: .7em 0 0 0;
+    padding: 0 .2em;
+    border-left: 0;
+    border-right: 0;
+    border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+    float: right;
+    margin: .5em .2em .4em;
+    cursor: pointer;
+    padding: .2em .6em .3em .6em;
+    width: auto;
+    overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+    float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+    width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+    float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+    width: 95%;
+    margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+    width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+    width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+    width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+    border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+    clear: left;
+}
+.ui-datepicker-row-break {
+    clear: both;
+    width: 100%;
+    font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+    direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+    right: 2px;
+    left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+    left: 2px;
+    right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+    right: 1px;
+    left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+    left: 1px;
+    right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+    clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+    float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+    float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+    border-right-width: 0;
+    border-left-width: 1px;
+}
+.ui-dialog {
+    overflow: hidden;
+    position: absolute;
+    top: 0;
+    left: 0;
+    padding: .2em;
+    outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+    padding: .4em 1em;
+    position: relative;
+}
+.ui-dialog .ui-dialog-title {
+    float: left;
+    margin: .1em 0;
+    white-space: nowrap;
+    width: 90%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+    position: absolute;
+    right: .3em;
+    top: 50%;
+    width: 20px;
+    margin: -10px 0 0 0;
+    padding: 1px;
+    height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+    position: relative;
+    border: 0;
+    padding: .5em 1em;
+    background: none;
+    overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+    text-align: left;
+    border-width: 1px 0 0 0;
+    background-image: none;
+    margin-top: .5em;
+    padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+    float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+    margin: .5em .4em .5em 0;
+    cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+    width: 12px;
+    height: 12px;
+    right: -5px;
+    bottom: -5px;
+    background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+    cursor: move;
+}
+.ui-draggable-handle {
+    -ms-touch-action: none;
+    touch-action: none;
+}
+.ui-menu {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+    display: block;
+    outline: none;
+}
+.ui-menu .ui-menu {
+    position: absolute;
+}
+.ui-menu .ui-menu-item {
+    position: relative;
+    margin: 0;
+    padding: 3px 1em 3px .4em;
+    cursor: pointer;
+    min-height: 0; /* support: IE7 */
+    /* support: IE10, see #8844 */
+    list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-divider {
+    margin: 5px 0;
+    height: 0;
+    font-size: 0;
+    line-height: 0;
+    border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+    margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+    position: relative;
+}
+.ui-menu-icons .ui-menu-item {
+    padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: .2em;
+    margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+    left: auto;
+    right: 0;
+}
+.ui-progressbar {
+    height: 2em;
+    text-align: left;
+    overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+    margin: -1px;
+    height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+    background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+    height: 100%;
+    filter: alpha(opacity=25); /* support: IE8 */
+    opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+    background-image: none;
+}
+.ui-resizable {
+    position: relative;
+}
+.ui-resizable-handle {
+    position: absolute;
+    font-size: 0.1px;
+    display: block;
+    -ms-touch-action: none;
+    touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+    display: none;
+}
+.ui-resizable-n {
+    cursor: n-resize;
+    height: 7px;
+    width: 100%;
+    top: -5px;
+    left: 0;
+}
+.ui-resizable-s {
+    cursor: s-resize;
+    height: 7px;
+    width: 100%;
+    bottom: -5px;
+    left: 0;
+}
+.ui-resizable-e {
+    cursor: e-resize;
+    width: 7px;
+    right: -5px;
+    top: 0;
+    height: 100%;
+}
+.ui-resizable-w {
+    cursor: w-resize;
+    width: 7px;
+    left: -5px;
+    top: 0;
+    height: 100%;
+}
+.ui-resizable-se {
+    cursor: se-resize;
+    width: 12px;
+    height: 12px;
+    right: 1px;
+    bottom: 1px;
+}
+.ui-resizable-sw {
+    cursor: sw-resize;
+    width: 9px;
+    height: 9px;
+    left: -5px;
+    bottom: -5px;
+}
+.ui-resizable-nw {
+    cursor: nw-resize;
+    width: 9px;
+    height: 9px;
+    left: -5px;
+    top: -5px;
+}
+.ui-resizable-ne {
+    cursor: ne-resize;
+    width: 9px;
+    height: 9px;
+    right: -5px;
+    top: -5px;
+}
+.ui-selectable {
+    -ms-touch-action: none;
+    touch-action: none;
+}
+.ui-selectable-helper {
+    position: absolute;
+    z-index: 100;
+    border: 1px dotted black;
+}
+.ui-selectmenu-menu {
+    padding: 0;
+    margin: 0;
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+    overflow: auto;
+    /* Support: IE7 */
+    overflow-x: hidden;
+    padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+    font-size: 1em;
+    font-weight: bold;
+    line-height: 1.5;
+    padding: 2px 0.4em;
+    margin: 0.5em 0 0 0;
+    height: auto;
+    border: 0;
+}
+.ui-selectmenu-open {
+    display: block;
+}
+.ui-selectmenu-button {
+    display: inline-block;
+    overflow: hidden;
+    position: relative;
+    text-decoration: none;
+    cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+    right: 0.5em;
+    left: auto;
+    margin-top: -8px;
+    position: absolute;
+    top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+    text-align: left;
+    padding: 0.4em 2.1em 0.4em 1em;
+    display: block;
+    line-height: 1.4;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+.ui-slider {
+    position: relative;
+    text-align: left;
+}
+.ui-slider .ui-slider-handle {
+    position: absolute;
+    z-index: 2;
+    width: 1.2em;
+    height: 1.2em;
+    cursor: default;
+    -ms-touch-action: none;
+    touch-action: none;
+}
+.ui-slider .ui-slider-range {
+    position: absolute;
+    z-index: 1;
+    font-size: .7em;
+    display: block;
+    border: 0;
+    background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+    filter: inherit;
+}
+
+.ui-slider-horizontal {
+    height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+    top: -.3em;
+    margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+    top: 0;
+    height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+    left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+    right: 0;
+}
+
+.ui-slider-vertical {
+    width: .8em;
+    height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+    left: -.3em;
+    margin-left: 0;
+    margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+    left: 0;
+    width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+    bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+    top: 0;
+}
+.ui-sortable-handle {
+    -ms-touch-action: none;
+    touch-action: none;
+}
+.ui-spinner {
+    position: relative;
+    display: inline-block;
+    overflow: hidden;
+    padding: 0;
+    vertical-align: middle;
+}
+.ui-spinner-input {
+    border: none;
+    background: none;
+    color: inherit;
+    padding: 0;
+    margin: .2em 0;
+    vertical-align: middle;
+    margin-left: .4em;
+    margin-right: 22px;
+}
+.ui-spinner-button {
+    width: 16px;
+    height: 50%;
+    font-size: .5em;
+    padding: 0;
+    margin: 0;
+    text-align: center;
+    position: absolute;
+    cursor: default;
+    display: block;
+    overflow: hidden;
+    right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+    border-top: none;
+    border-bottom: none;
+    border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+    position: absolute;
+    margin-top: -8px;
+    top: 50%;
+    left: 0;
+}
+.ui-spinner-up {
+    top: 0;
+}
+.ui-spinner-down {
+    bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+    /* need to fix icons sprite */
+    background-position: -65px -16px;
+}
+.ui-tabs {
+    position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+    padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+    margin: 0;
+    padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+    list-style: none;
+    float: left;
+    position: relative;
+    top: 0;
+    margin: 1px .2em 0 0;
+    border-bottom-width: 0;
+    padding: 0;
+    white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+    float: left;
+    padding: .5em 1em;
+    text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+    margin-bottom: -1px;
+    padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+    cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+    cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+    display: block;
+    border-width: 0;
+    padding: 1em 1.4em;
+    background: none;
+}
+.ui-tooltip {
+    padding: 8px;
+    position: absolute;
+    z-index: 9999;
+    max-width: 300px;
+    -webkit-box-shadow: 0 0 5px #aaa;
+    box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+    border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+    font-family: Verdana,Arial,sans-serif;
+    font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+    font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+    font-family: Verdana,Arial,sans-serif;
+    font-size: 1em;
+}
+.ui-widget-content {
+    border: 1px solid #aaaaaa;
+    background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
+    color: #222222;
+}
+.ui-widget-content a {
+    color: #222222;
+}
+.ui-widget-header {
+    border: 1px solid #aaaaaa;
+    background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
+    color: #222222;
+    font-weight: bold;
+}
+.ui-widget-header a {
+    color: #222222;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+    border: 1px solid #d3d3d3;
+    background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
+    font-weight: normal;
+    color: #555555;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+    color: #555555;
+    text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+    border: 1px solid #999999;
+    background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
+    font-weight: normal;
+    color: #212121;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+    color: #212121;
+    text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+    border: 1px solid #aaaaaa;
+    background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+    font-weight: normal;
+    color: #212121;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+    color: #212121;
+    text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+    border: 1px solid #fcefa1;
+    background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
+    color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+    color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+    border: 1px solid #cd0a0a;
+    background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
+    color: #cd0a0a;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+    color: #cd0a0a;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+    color: #cd0a0a;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+    font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+    opacity: .7;
+    filter:Alpha(Opacity=70); /* support: IE8 */
+    font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+    opacity: .35;
+    filter:Alpha(Opacity=35); /* support: IE8 */
+    background-image: none;
+}
+.ui-state-disabled .ui-icon {
+    filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+    width: 16px;
+    height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+    background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-widget-header .ui-icon {
+    background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-state-default .ui-icon {
+    background-image: url("images/ui-icons_888888_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+    background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-active .ui-icon {
+    background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+    background-image: url("images/ui-icons_2e83ff_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+    background-image: url("images/ui-icons_cd0a0a_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+    border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+    border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+    border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+    border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+    background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+    opacity: .3;
+    filter: Alpha(Opacity=30); /* support: IE8 */
+}
+.ui-widget-shadow {
+    margin: -8px 0 0 -8px;
+    padding: 8px;
+    background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+    opacity: .3;
+    filter: Alpha(Opacity=30); /* support: IE8 */
+    border-radius: 8px;
+}
index 27c6b47..45f5efc 100644 (file)
@@ -82,6 +82,10 @@ span.version {
     font-size:8pt;
     color:#888888;
 }
+input[type=checkbox] {
+  min-width:5px !important;
+  margin-left:0 !important;
+}
 input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
     min-width:260px;
     padding:6px;
@@ -378,71 +382,87 @@ div.container-resource, div.container-slice {
 div#slice-view {
     margin:0;
 }
-div.list-group-item {
-    border:0;
-    -moz-border-radius: 0;
-    border-radius: 0;
-    background-color:white;
-    font-weight:bold;
-    padding-left:0;
+
+div.sl-filter-facilities {
+    padding:0 5px;
 }
-a.list-group-item {
-    -moz-border-radius: 0;
-    border-radius: 0;
-    border:0;
-    background-color:white;
-    padding:3px 2px 3px 10px;
-    border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+    margin-bottom:15px;
+    
+}
+img.sl-image {
+    margin:0 5px 5px 0;
+    padding:0;
+    vertical-align:middle;
+}
+a.sl-facility {
+    color:gray;
+    text-decoration:none;
 }
-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;
+a.sl-facility:hover {
+    color:#342961;
+}
+a.sl-facility.active {
     color:black;
-    background-color:#F5F5F5;
-    border-left:2pt blue solid;
+    text-decoration:none;
 }
-
-a.list-group-item:hover {
-    -moz-border-radius: 0;
-    border-radius: 0;
-    border-left:2pt blue solid;
+a.sl-facility::before {
+    content: " ";
 }
-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.sl-facilities {
+    border-bottom:#CCCCCC 1px solid;
+    padding-bottom:15px;
+    margin-bottom:15px;
+}
+div.sl-facilities:last-child {
+    border:0;
+}
+a.sl-testbed {
+    color:gray;
+    text-decoration:none;
+    margin-left:25px;
+    margin-bottom:5px;
+}
+a.sl-testbed:hover {
+    color:#342961;
+}
+a.sl-testbed.active {
+    color:black;
+}
+div.sl-filter-resources {
+    margin:0 0 10px 0;
+    text-align:center;
 }
-
 span.sl-resources {
     font-size:9pt;
     color:gray;
 }
-a.sl-resources, a.sl-resources:hover {
+a.sl-resources {
     font-size:9pt;
     border:0;
-    padding:2px 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-    width:105px;
-    margin-left:4px;
-    margin-bottom:8px;
+    padding:2px 8px;
+    margin:0 5px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
     text-align: center;
 }
 a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
     border:0;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
+    padding:2px 8px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+    background-color:#E7A6E7;
+    color:#000000;
 }
 a.sl-resources:first-child {
-    margin-left:12px;
 }
 button.btn-apply {
     font-size:13px;
     padding:2px 8px;
+    margin:0 5px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+    text-align: center;
 }
 div#slice-info {
     margin-top:25px;
index 190924e..4627124 100644 (file)
@@ -13,7 +13,7 @@ body {
 a, a:active, a:focus {
     outline: 0;
     text-decoration:none;
-    color:#760073;
+    color:#FF4400;
 }
 a:hover {
     color:#0D0049;
@@ -82,6 +82,10 @@ span.version {
     font-size:8pt;
     color:#888888;
 }
+input[type=checkbox] {
+  min-width:5px !important;
+  margin-left:0 !important;
+}
 input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
     min-width:260px;
     padding:6px;
@@ -174,14 +178,14 @@ button.btn-danger:active {
 }
 button.btn-onelab, input.btn-onelab {
     border:0;
-    border-bottom:3px solid #760073;
-    background-color:#302562;
+    border-bottom:3px solid #FFA315;
+    background-color:#FFA315;
     color:white;
 }
 button.btn-onelab:hover, input.btn-onelab:hover {
     border:0;
-    border-bottom:3px solid #760073;
-    background-color:#302562;
+    border-bottom:3px solid #FF7E00;
+    background-color:#FF7E00;
     color:white;
 }
 button.btn-onelab:active, input.btn-onelab:active {
@@ -378,43 +382,53 @@ div.container-resource, div.container-slice {
 div#slice-view {
     margin:0;
 }
-div.list-group-item {
-    border:0;
-    -moz-border-radius: 0;
-    border-radius: 0;
-    background-color:white;
-    font-weight:bold;
-    padding-left:0;
+
+/* FACILITY/TESTBED filters */
+div.sl-filter-facilities {
+    padding:0 5px;
 }
-a.list-group-item {
-    -moz-border-radius: 0;
-    border-radius: 0;
-    border:0;
-    background-color:white;
-    padding:3px 2px 3px 10px;
-    border-left:2pt white solid;
+div.sl-filter-facilities h4 {
+    margin-bottom:15px;
+    
+}
+img.sl-image {
+    margin:0 5px 5px 0;
+    padding:0;
+    vertical-align:middle;
+}
+a.sl-facility {
+    color:gray;
+    text-decoration:none;
+}
+a.sl-facility:hover {
+    color:#342961;
 }
-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;
+a.sl-facility.active {
     color:black;
-    background-color:#F5F5F5;
-    border-left:2pt blue solid;
+    text-decoration:none;
 }
-
-a.list-group-item:hover {
-    -moz-border-radius: 0;
-    border-radius: 0;
-    border-left:2pt blue solid;
+a.sl-facility::before {
+    content: " ";
 }
-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.sl-facilities {
+    border-bottom:#CCCCCC 1px solid;
+    padding-bottom:15px;
+    margin-bottom:15px;
+}
+div.sl-facilities:last-child {
+    border:0;
+}
+a.sl-testbed {
+    color:gray;
+    text-decoration:none;
+    margin-left:25px;
+    margin-bottom:5px;
+}
+a.sl-testbed:hover {
+    color:#342961;
+}
+a.sl-testbed.active {
+    color:black;
 }
 
 span.sl-resources {
@@ -576,7 +590,7 @@ div.navigation li a {
     color:#0C0047;
 }
 div.navigation li a:hover, div.navigation li a.current {
-    color:#760073;
+    color:#FF4400;
     text-decoration:none;
 }
 
@@ -715,7 +729,7 @@ div.home {
     line-height:1.2em;
     letter-spacing:0.3pt;
     min-height:500px;
-    //background-image: url('../img/bg-experiment.png');
+    background-image: url('../img/bg-smartfire.png');
     background-repeat:no-repeat;
     background-size:cover;
     background-position:center top;
@@ -798,7 +812,6 @@ div.registration-form {
 div.slogan {
     text-align:center;
     color:white;
-    padding-top:60px;
     text-shadow: 1px 1px #013540;
 }
 
diff --git a/portal/static/icons/iotlab.png b/portal/static/icons/iotlab.png
new file mode 100644 (file)
index 0000000..56a8e56
Binary files /dev/null and b/portal/static/icons/iotlab.png differ
diff --git a/portal/static/icons/mobile.png b/portal/static/icons/mobile.png
new file mode 100644 (file)
index 0000000..81ee438
Binary files /dev/null and b/portal/static/icons/mobile.png differ
diff --git a/portal/static/icons/planetlab.png b/portal/static/icons/planetlab.png
new file mode 100644 (file)
index 0000000..a74082a
Binary files /dev/null and b/portal/static/icons/planetlab.png differ
diff --git a/portal/static/icons/wireless.png b/portal/static/icons/wireless.png
new file mode 100644 (file)
index 0000000..4db0aa3
Binary files /dev/null and b/portal/static/icons/wireless.png differ
diff --git a/portal/static/img/bg-smartfire.png b/portal/static/img/bg-smartfire.png
new file mode 100644 (file)
index 0000000..f5340fc
Binary files /dev/null and b/portal/static/img/bg-smartfire.png differ
index 2b2cfa3..e8d5121 100644 (file)
@@ -36,11 +36,13 @@ $(document).ready(function() {
 
     /* TODO: factorize into functions */
     $('button#deleteslices').click(function() {
+        var flag = false;
         $('input:checkbox.slice').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
                 $.post("/delete/slice/",{'filters':{'slice_hrn':this.id}}, function(data) {
                     if(data.success){
+                        localStorage.clear();
                         $('tr[id="'+record_id+'"]').fadeOut("slow");
                         $('tr[id="'+record_id+'"]').remove();
                         mysliceAlert('Success: slice deleted','success', true);
@@ -76,10 +78,34 @@ $(document).ready(function() {
         // TODO: refresh table
         //window.location="/portal/institution#slices";
     });
+    $('button#deleteprojects').click(function() {
+        var flag = false;
+        $('input:checkbox.project').each(function (index) {
+            if(this.checked){
+                var record_id = this.id;
+                console.log(record_id);
+                $.post("/delete/myslice:authority/",{'filters':{'authority_hrn':this.id}}, function(data) {
+                    if(data.success){
+                        localStorage.clear();
+                        $('tr[id="'+record_id+'"]').fadeOut("slow");
+                        $('tr[id="'+record_id+'"]').remove();
+                        mysliceAlert('Success: project deleted','success', true);
+                    }else{
+                        mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                        //alert("Rest Error for "+record_id+": "+data.error);
+                    }
+                });
+            }
+        });
+    });
 
     $('button#createslice').click(function() {
         window.location="/portal/slice_request/";
     });
+
+    $('button#createproject').click(function() {
+        window.location="/portal/project_request/";
+    });
     $('button#slicerequestbtn').click(function() {
         /*
         window.location="/portal/slice_request/";
index 1ccc1c1..548d5da 100644 (file)
@@ -1,6 +1,10 @@
 /*
  * MySlice Class
  */
+function isFunction(functionToCheck) {
+ var getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
 
 function list() {
        this.elements = [];
@@ -114,6 +118,20 @@ var myslice = {
                }
                return this.user;
        },
+       projects: {},
+       
+       projects: function() {
+               if ($.isEmptyObject(this.projects)) {
+                       //this.login(function() { return this.user; });
+            if(localStorage.getItem('projects')!='undefined'){
+                           this.projects = JSON.parse(localStorage.getItem('projects'));
+            }else{
+                return false;
+            }
+               }
+               return this.projects;
+       },
+
     loadSlices: function(slices) {
         if (typeof(slices) == "undefined"){
 
@@ -154,12 +172,46 @@ var myslice = {
         if($.isEmptyObject(user)){
             // REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
                    $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
-                           //myslice.user = new user(data[0]);
-                           localStorage.setItem('user', JSON.stringify(data[0]));
-                myslice.loadSlices(data[0].slices);
+                       if (data.length > 0) {
+                           localStorage.setItem('user', JSON.stringify(data[0]));
+                    projects = [];
+                           $.each(data[0].pi_authorities, function(idx, auth) {
+                        // PI on projects
+                        if(auth.split('.').length>2){
+                            if($.inArray(auth,projects) == -1){
+                                projects.push(auth);
+                            }
+                        }else if (auth.split('.').length>1){
+                        // PI on authorities
+                            // What are the projects under this authority?
+                            $.post("/rest/myslice:authority/",{'fields':['authority_hrn'],'filters':{'authority_hrn':'CONTAINS'+auth}}, function( data ) {
+                                       $.each(data, function(idx, project) {
+                                    console.log(project.authority_hrn);
+                                    if($.inArray(project.authority_hrn,projects) == -1){
+                                        projects.push(project.authority_hrn);
+                                    }
+                                });
+                            });
+                        }else{
+                            console.log("admin account - we don't list all from root");
+                        }
+                    });
+                    localStorage.setItem('projects', JSON.stringify(projects));
+                    myslice.loadSlices(data[0].slices);
+                    if(isFunction(fn)){
+                        fn();
+                    }
+                }
                    });
+        }else{
+            if(isFunction(fn)){
+                fn();
+            }
         }
+
        },
+
+
     getSlices: function(name) {
        
     },
diff --git a/portal/templates/_widget-no_credentials.html b/portal/templates/_widget-no_credentials.html
new file mode 100644 (file)
index 0000000..ab07ce7
--- /dev/null
@@ -0,0 +1,66 @@
+<!-- This widget is used to show a popup to users explaining why they don't have credentials delegated to the portal (accountview, homeview) -->
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+     <div class="modal-dialog">
+         <div class="modal-content">
+             <div class="modal-header">
+                 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                     <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+             </div>
+                       <div class="modal-body" style="text-align:justify;">
+                       <p>You are getting this message for any of the following reasons:</p>
+                       <ul>
+                               <li>If your account is still pending for validation</li>
+                               <li>If the server cache hasn't been cleared</li>
+                               <li>If you press the "Clear Credentials" button</li>
+                               <li>If you "Generate a new key pair"</li>
+                               <li>If a new slice is added to your account</li>
+                       </ul>
+                       <h3>Clear server cache</h3>
+            <p>
+            <button class="btn btn-default btn-primary" type="button" title="Clear server cache" name="clear_server_cache" id="clear_server_cache" style="float:left;">Clear server cache</button>
+            <div id="clear_success" style="color:green; margin-left: 160px;">&nbsp;</div>
+            <div id="clear_error" style="color:red; margin-left: 160px;">&nbsp;</div>
+            </p>
+                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
+                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
+                               then please logout and login back into to the portal.
+                       </p>
+                       <h3>Manual delegation of credentials</h3>
+                               <p>
+                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
+                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
+                                       delegated to the portal, please follow these instructions:
+                               </p>
+                               <ul>
+                                       <li>Your account must first be validated by the manager of your organization.</li>
+                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+                                               <a href="/portal/manual_delegation" target="_blank" style="text-decoration:underline;font-weight:bold;">delegate your credentials.</a></li>
+                               </ul>
+                       </p>
+                       <h3>Contact support</h3>
+                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank" style="text-decoration:underline;font-weight:bold;">contact us</a>.</p>
+             </div>
+             <div class="modal-footer">
+                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+             </div>
+         </div>
+     </div>
+</div>
+<script>
+$(document).ready(function() {
+    $('button#clear_server_cache').click(function() {
+        $('#clear_success').html('<img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Services" />');
+        $.post("/cache/clear/", function( data ) {
+            console.log(data);
+            if(data['ret']==1){
+                $('#clear_success').html('Server cache cleared')
+            }else{
+                $('#clear_error').html('error:'+data['error'])
+                $('#clear_success').html('');
+            }
+        });
+    });
+});
+</script>
+
index 175b09c..0856bd8 100644 (file)
@@ -4,7 +4,7 @@
        <li><a href="/slice/{{ slice }}#testbeds">Testbeds</a></li>
        <li class="active"><a class="link" href="/resources/{{ slice }}">Resources</a></li>
        <li><a href="/slice/{{ slice }}#users">Users</a></li>
-       <!--<li><a href="/slice/{{ slice }}#statistics">Statistics</a></li> -->
+       <li><a href="/slice/{{ slice }}#statistics">Statistics</a></li>
        <li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
        <li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li>
        <li><a href="/slice/{{ slice }}#sla">SLA</a></li>
@@ -15,7 +15,7 @@
        <li class="testbeds"><a href="#testbeds">Testbeds</a></li>
        <li><a class="link" href="/resources/{{ slice }}">Resources</a></li>
        <li class="users"><a href="#users">Users</a></li>
-<!--   <li class="statistics"><a href="#statistics">Statistics</a></li> -->
+       <li class="statistics"><a href="#statistics">Statistics</a></li>
        <li class="measurements"><a href="#measurements">Measurements</a></li>
        <li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li>
        <li class="sla"><a href="#sla" data-toggle="tab">SLA</a></li>
index 6236344..668c3d3 100644 (file)
@@ -1,51 +1,49 @@
-
-<div id="header">
-       <div class="wrapper">
-               <div class="logo">
-                       <a href="/"><img src="{{ STATIC_URL }}img/onelab-portal.png" alt="OneLab - Future Internet Testbeds" /></a>
+{% load portal_filters %}
+<div class="header">
+<div class="container">
+       <div class="row">
+               <div class="col-sm-3 col-md-3 logo">
+                       <a href="/"><img src="{{ STATIC_URL }}img/onelab-portal.png" alt="OneLab Portal - Future Internet Testbeds" /></a>
+               </div>
+               {% if username %}
+               <div class="col-sm-4 col-md-4 navigation">
+                       <ul>
+                               <li>
+                                       <a class="dropdown-toggle" data-toggle="dropdown" href="#">
+                                       EXPERIMENT <span class="caret"></span>
+                               </a>
+                                       
+                                       <div class="dropdown-menu" style="z-index:99;">
+                                                       <ul id="dropdown-slice-list">
+                                                               <li class="title"><a href="/portal/slice_request/">Request Slice</a></li>
+                                                       </ul>
+                                       </div>
+                               </li>
+                               {%if 'is_pi'  in pi %}  
+                               <li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
+                                {%endif%}
+                               <li><a href="/support/">SUPPORT</a></li>
+                       </ul>
+               </div>
+               {% else %}
+               <div class="col-sm-4 col-md-4 navigation">
                </div>
-               
-               <div id="secondary">
+               {% endif %}
+               <div class="col-sm-5 col-md-5 secondary">
                        <ul>
                                <li><a href="/news">News</a></li>
-                               <li><a href="/portal/about">About</a></li>
-                               <li><a target="_blank" href="http://www.onelab.eu">Public Website</a></li>
+                               <li><a href="/about">About</a></li>
+                               <li><a target="_blank" href="https://www.onelab.eu">Public Website</a></li>
                                <li><a target="_blank" href="http://intranet.onelab.eu">Intranet</a></li>
                        </ul>
+                       {% if username %}
+                       <div class="account">You are logged in as &nbsp;<a href="/account/">{{ username }}</a> &nbsp;&nbsp;|&nbsp;&nbsp; <a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</a></div>
+                       {% endif %}
                </div>
        </div>
-       
-       {% if username %}
-       <div id="navigation">
-               <div class="wrapper">
-               <ul>
-                       <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
-                       <li>|</li>
-                       <li id="nav-institution" class=""><a href="/portal/institution">INSTITUTION</a></li>
-                       <li class="slices">
-                               <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                                       SLICES <span class="caret"></span>
-                       </a>
-                               
-                               <div class="dropdown-menu" style="z-index:99;">
-                                               <ul id="dropdown-slice-list">
-                                                       <li><a href="/portal/slice_request/">Request Slice</a></li>
-                                               </ul>
-                               </div>
-                               </li>
-                       <li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
-                       <li id="nav-support"><a href="/portal/support/">SUPPORT</a></li>
-                       <li>|</li>
-                       <li id="nav-logout" style="margin-top: 10px;"><a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> LOGOUT</a></li>
-               </ul>
-               </div>
-       </div>
-       {% else %}
-       <div id="navigation">
-               <div class="wrapper"></div>
-       </div>
-       {% endif %}
 </div>
+</div>
+
 <script>
        $(document).ready(function() {
                $('li.slices').mouseenter(function() {
diff --git a/portal/templates/_widget-tradeoff.html b/portal/templates/_widget-tradeoff.html
new file mode 100644 (file)
index 0000000..4e75ba3
--- /dev/null
@@ -0,0 +1,39 @@
+<!-- Modal- Trade-off Message  -->
+<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+            <div class="modal-dialog">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                            <h4 class="modal-title" id="myModalLabel">
+                                                               Automatic vs. Manual delegation of credentials
+                                                       </h4>
+                    </div>
+                                       <div class="modal-body" style="text-align:justify;">
+                                       <h3>Automatic delegation of credentials</h3>
+                                               <p>Don't delete private key, ease-of-use option:</p>
+                                               <ul>
+                                                       <li>
+                                                               This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
+                                                       </li>
+                                                       <li>
+                                                               This option does not provide as high of a level of security; however, your private key will still only be used in the portal and 
+                                                               will be available to you and the OneLab admins only.
+                                                       </li>
+                                               </ul>
+                                       <h3>Manual delegation of credentials</h3>
+                                               <p>Download & Delete private key, higher security option:</p>
+                                               <ul>
+                                                       <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials 
+                                                               on your behalf, and you will have to manually
+                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
+                                                       </li>
+                                               </ul>
+                                       <h3>Contact support</h3>
+                                       <p>For more information, please  <a href="/contact/" target="_blank">contact us</a>.</p>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                    </div>
+                </div>
+            </div>
+</div>
index 2b99be1..985974f 100644 (file)
@@ -1,7 +1,22 @@
-{% extends "layout_wide.html" %}
+{% extends "layout.html" %}
+{% load portal_filters %}
 {% block content %}
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                        Account &nbsp;>&nbsp; <a href="/account">{{ person.email }}</a>
+                </div>
+       </div>
+        {%if 'no_creds' in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+    {%endif%}
+        {%if 'creds_expired' in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
 
-
+</div>
 {% if messages %}
 <ul class="messages">
     {% for message in messages %}
     {% endfor %}
 </ul>
 {% endif %}
-<div class="container">
-       <div class="row">
-               <div class="col-md-12">
-                       <ul class="nav nav-tabs nav-section">
-                               <li class="active"><a href="#profile"><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Account" /> User Profile</a></li>
-                               <li><a href="#account">Account</a></li>
-                               <li><a href="#access">Testbed Access</a></li>
-                       </ul>
-           </div>
-       </div>
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value"  name="button_value" value="" />
+
+<div class="row">
+       <div class="col-md-12">
+               <ul class="nav nav-tabs nav-section">
+                       <li class="active"><a href="#profile">User Profile</a></li>
+                       <li><a href="#account">Account</a></li>
+                       <li><a href="#access">Testbed Access</a></li>
+               </ul>
+    </div>
 </div>
-<div class="container tab-content">
+<div class="tab-content">
        <div class="tab-pane active row" id="profile">
                
                <div class="col-md-12">
 
-                       <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
                                {% csrf_token %}
                                        <table class="profile">          
                                        <tr>
@@ -37,7 +53,7 @@
                                                <td class="key">Email</td>
                                                <td class="value">
                                                                <span id="emailval" class="value" >{{ person.email }}</span>
-                                                               <button class="btn btn-default btn-xs" type="button" id="edit_email" onclick="editAlert();"  title="To change your affiliation please contact the administrator">
+                                                               <button class="btn btn-default" type="button" id="edit_email" onclick="editAlert();"  title="To change your affiliation please contact the administrator">
                                                                <span class="glyphicon glyphicon-question-sign"></span> Edit
                                                                </button>
                                                        </td>
                                                <tr class="even">
                                                        <td class="key">Generate Keys</td>
                                                        <td>
-                                                               <input type="submit" name="generate" class="btn btn-danger btn-xs" value="Generate a new Key Pair" id="generate_keypair" 
+                                                               <input type="submit" name="generate" class="btn btn-primary" value="Generate a new Key Pair" id="generate_keypair" 
                                                                           onclick="return confirm('Are you sure? If you do so, your current credentials will be overwritten.');" 
                                                                           title="It will generate a new key Pair and your current credentials will be overwritten."/>
                                                </td> 
                                                <td class="value">
                                                                <span id="keyval" class="value">******** </span>
                                                                <span class="hide_this" id="span_upload">
-                                                                       <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_upload"> Cancel </button>
+                                                                       <button type="button" class="btn btn-default" title="Cancel" id="cancel_upload"> Cancel </button>
                                                                        <div style='display:none;'>
                                                                                <input type='hidden'  name='upload'  /></div>
                                                                                <input type="file" name="pubkey" class="required" id="pubkey"/>  
                                                                                   onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
                                                                </span>
                                                                <div style='display:none;'> <input type='hidden'  name='dload'  /> </div> 
-                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                                <button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
                                                 {%if 'N/A' not in user_private_key%}
                                                <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='dl_pkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download     
                                                                </button>
                                                        <input class="btn btn-danger btn-xs" id="delete" name="delete" type="submit"  value="Delete" title="Delete your private key"
-                                                                               onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
+                                                                               onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
                                                </td>
                                                  {%else%}
                                                        <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                        <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default btn-xs disabled" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey" value="dl_pkey">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                        </button>
                                                        <input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
                                        <tr class="even" id="sfi_config_row">
                                                <td class="key">sfi_config </td>
                                                <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
-                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_sfi_config">
-                                                                       <span class="glyphicon glyphicon-download"></span> Download 
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='dl_sfi_config';">
+                                                                       <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                </td>
                         </tr>
+                                               <tr class="odd">
+                                                       {%if 'N/A' not in user_private_key%}
+                                                       <td class="key">Identity</td> 
+                                               <td>
+                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                               </button>
+                                                       </td>
+                                                       {%else%}
+                                                       <td class="key">Identity</td> 
+                                                       <td>
+                                                       <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                       </button>
+                                                       </td>
+                                                       {%endif%} 
+                                               </tr>
+
                                                <tr class="even">
                                                <td colspan="2">
-                                                       <p class="message" id="pkey_del_msg"><b> Tradeoff:</b> Ease-of-use vs Security.<br>
-                                                                       <b>Ease-of-use:</b> Automatic account delegation. Don't delete private key.<br>
-                                                                       <b>Security:</b> Manual account delegation. Download & Delete private key.
+                                                               <p class="command">
+                                                                       <a href="#" style="color:green" data-toggle="modal" data-target="#tradeoffmodal">Automatic vs. Manual delegation of credentials:</a>
+                                                                       Trade-off between ease-of-use & security</p>
                                                                </p>
                                                </td>
                                                </tr>
                </table>
        
                </div>
-       
 
        {%if 'Enabled'  in user_status %}
                <div class="col-md-12">
                <h3>Credentials <small>Delegated to Principal Account</small></h3>
-                       <table class="table">
-                                       <caption><b>Delegated User Credential</b></caption> 
-                           <tr class="odd"> 
-                               <th>Expiration Date</th>
-                                               <th>Download</th>
-                           </tr>
-                                       {% for row in my_users %}         
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
-                                                               <span class="glyphicon glyphicon-download"></span> Credential
-                                                       </button>
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate">
-                                                               <span class="glyphicon glyphicon-download"></span> Certificate
-                                                       </button>
-                             <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
-                                 <span class="glyphicon glyphicon-download"></span> PKCS p12
-                             </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                                </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Slice Credentials</b></caption>  
-                               <tr class="odd"> 
-                                               <th>Slice Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                               </tr>
-                                       {% for row in my_slices %}     
-                               <tr class="border_bottom">
-                                       <td class="odd"> {{ row.slice_name }} </td>
-                                               <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd"> 
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button> 
-                                               </td>
-                               </tr>
-                               {%endfor%}
-                               </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Authority Credentials</b></caption>
-                                       <tr class="odd"> 
-                                       <th>Authority Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                                       </tr>
-                                       {% for row in my_auths %}
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.auth_name }} </td>
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                               </table>
-                               <p></p>
-                                {%if '' not in my_users%}      
-                               <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%else%}
-                               <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%endif%}
+                   <table class="table">
+                               <caption><b>Delegated User Credential</b></caption> 
+                       <tr class="odd"> 
+                           <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_users %}         
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+                                                       <span class="glyphicon glyphicon-download"></span> Credential
+                                               </button>
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+                                                       <span class="glyphicon glyphicon-download"></span> Certificate
+                                               </button>
+                         <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+                             <span class="glyphicon glyphicon-download"></span> PKCS p12
+                         </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                        </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Slice Credentials</b></caption>  
+                       <tr class="odd"> 
+                                       <th>Slice Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_slices %}     
+                       <tr class="border_bottom">
+                               <td class="odd"> {{ row.slice_name }} </td>
+                                       <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd"> 
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button> 
+                                       </td>
+                       </tr>
+                       {%endfor%}
+                       </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Authority Credentials</b></caption>
+                               <tr class="odd"> 
+                               <th>Authority Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                               </tr>
+                               {% for row in my_auths %}
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.auth_name }} </td>
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                       </table>
+                       <p></p>
+                        {%if '' not in my_users%}      
+                       <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+                       {%else%}
+                       <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+                       {%endif%}
                </div>
        </div>
 
+
        <div class="tab-pane row" id="access">
                <div class="col-md-12">
        
                 <td class="odd"> {{ row.account_type }} </td>
                                <td class="odd"> {{ row.account_reference }} </td>
                                <td class="odd">
-                               <button class="btn btn-danger btn-xs" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
                                                <span class="glyphicon glyphicon-minus"></span>
                                        </button>
                                </td>
             <tr class="border_bottom">
                 <td class="odd"> {{ platform.platform_no_access }} </td>
                 <td class="odd">
-                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
                                                <span class="glyphicon glyphicon-plus"></span>
                                        </button>
                                </td>
        </div>
 {%endif%} 
 </div>
-</form>
 </div>
 
+</form>
 <script>
     $(document).ready(function() {
+           {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+        localStorage.clear();
+        $.post("/cache/clear/", function( data ) {
+        });
+        {% endif %}
        $('.nav-tabs a').click(function (e) {
                        e.preventDefault();
                        $(this).tab('show');
                        id = $(this).attr('href').substr(1);
-               
                });
                
         $('button#createslice').click(function() {
index cc60f7f..9c6eb1b 100644 (file)
@@ -3,7 +3,16 @@
 <html lang="en"><head>
 <title>{{theme}} portal - {{ section }}</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="shortcut icon" href="/static/img/favicon.ico">
+
+<!--Selecting favicon based on theme. Add more for other portals -->
+{% if theme == "fed4fire" %}
+    <link rel="shortcut icon" href="/static/img/fed4fire_favicon.ico">
+{% elif theme == "smartfire" %}
+    <link rel="shortcut icon" href="/static/img/smartfire_favicon.ico">
+{% else %}
+    <link rel="shortcut icon" href="/static/img/favicon.ico">
+{% endif %}
+
 {# This is where insert_str will end up #}{% media_container prelude %}
 {% include 'messages-transient-header.html' %}
 <script type="text/javascript"> {# raw js code - use {% insert prelude_js %} ... {% endinsert %} #} {% container prelude_js %}</script>
@@ -18,6 +27,7 @@
 {{ header_prelude }}
 {% block head %} {% endblock head %}
 {# let's add these ones no matter what #}
+{#NOTE: DO NOT ADD JQUERY-UI JS & CSS HERE. IT BREAKS THE RESOURCE BROWSING PAGE -- DETAILS WITH JORDAN AUGE#}
 {% insert_str prelude "js/jquery.min.js" %}
 {% insert_str prelude "js/angular/angular.min.js" %}
 {% insert_str prelude "js/jquery.html5storage.min.js" %}
@@ -48,53 +58,58 @@ XXX TODO: session
 This list of slices should go into SESSION !
 */
 $(document).ready(function() {
-    {% if username %}
-    myslice.login();
+{% if username %}
+    myslice.login(function(){
+        user = myslice.user();
 
-    user = myslice.user();
-    
-    var slices = [];
-    if($.isEmptyObject(user)){
-        $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
-            if(data.length > 0){
-                drawSlices(data[0].slices);  
-            }else{
-               $("div#home-slice-list").html(
-                                       "<div>You do not yet have a slice</div>");
-                       $("ul#dropdown-slice-list").append("<li>no slice</li>");
-                slices.push("no slice");
-            }
-       });
-    }else{
-        slices = user.slices;
-        drawSlices(slices);
-    }
+        var slices = [];
+        if($.isEmptyObject(user)){
+            $("div#home-slice-list").html(
+                       "<div>You do not yet have a slice</div>");
+            $("ul#dropdown-slice-list").append("<li>no slice</li>");
+            slices.push("no slice");
+        }else{
+            slices = user.slices;
+            drawSlices(slices);
+        }
+        {% if theme == "fed4fire" %}
+        p = myslice.projects();
+        if(p != null){
+            drawProjects(p);
+        }
+        {% endif %}
+    });
 
-    /*
-        Launch queries to get the resources and leases in Manifold Cache
-    */
-        
     function drawSlices(slices){
         var items = [];
                
         $.each( slices, function(i, val) {
             items.push( "<li><a href=\"/resources/"+val+"\">" + val + "</a></li>" );
-            /*
-            // Launch a Query for each slice to get resources and leases in Manifold Cache
-            // Now only done in Homeview to speed up the other pages
-            $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
-            });
-            */
         });
         $("div#home-slice-list").html($( "<ul/>", { html: items.join( "" ) }));
         $("ul#dropdown-slice-list").append(items.join( "" ));
     }
+    
+    {% if theme == "fed4fire" %}
+    function drawProjects(projects){
+        var items = [];
+               
+        $.each( projects, function(i, val) {
+            items.push( "<li><a href=\"/portal/project/"+val+"\">" + val + "</a></li>" );
+        });
+        $("div#home-project-list").html($( "<ul/>", { html: items.join( "" ) }));
+        $("ul#dropdown-project-list").append(items.join( "" ));
+    }
     {% endif %}
+{% endif %}
        jQuery('[title!=""]').qtip();
 });
 </script>
 </head>
 <body ng-app="ManifoldApp">
+<div class="row">
+{% widget '_widget-message.html' %}
+</div>
 {% block container %}
        {% block topmenu %}
        {% widget "_widget-topmenu.html" %}
index b0c3b6d..2c53cb6 100644 (file)
@@ -16,6 +16,7 @@
 <div class="container tab-content">
     <div class="tab-pane active row" id="about">
                <div class="col-md-12">
+                   <h3>The Fed4Fire portal</h3>
                        <p>
                                Fed4FIRE Portal is a central place to get acess to all Fed4FIRE testbeds.In order to get access to the portal,
                                an experimenter needs to  <a href="/portal/register">register</a> to the portal. The portal administrative body
index 6163459..985974f 100644 (file)
@@ -1,16 +1,18 @@
 {% extends "layout.html" %}
+{% load portal_filters %}
 {% block content %}
-
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
 <div class="row">
        <div class="col-md-12">
                 <div class="breadcrumbs">
                         Account &nbsp;>&nbsp; <a href="/account">{{ person.email }}</a>
                 </div>
        </div>
-        {%if 'no_creds'  in user_cred %}
+        {%if 'no_creds' in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
     {%endif%}
-        {%if 'creds_expired'  in user_cred %}
+        {%if 'creds_expired' in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
 
     {% endfor %}
 </ul>
 {% endif %}
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value"  name="button_value" value="" />
+
 <div class="row">
        <div class="col-md-12">
                <ul class="nav nav-tabs nav-section">
@@ -36,7 +42,6 @@
                
                <div class="col-md-12">
 
-                       <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
                                {% csrf_token %}
                                        <table class="profile">          
                                        <tr>
                                                                                   onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
                                                                </span>
                                                                <div style='display:none;'> <input type='hidden'  name='dload'  /> </div> 
-                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                                <button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
                                                 {%if 'N/A' not in user_private_key%}
                                                <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='dl_pkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download     
                                                                </button>
                                                        <input class="btn btn-danger btn-xs" id="delete" name="delete" type="submit"  value="Delete" title="Delete your private key"
-                                                                               onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
+                                                                               onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
                                                </td>
                                                  {%else%}
                                                        <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                        <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey" value="dl_pkey">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                        </button>
                                                        <input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
                                        <tr class="even" id="sfi_config_row">
                                                <td class="key">sfi_config </td>
                                                <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
-                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config">
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='dl_sfi_config';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                </td>
                                                        {%if 'N/A' not in user_private_key%}
                                                        <td class="key">Identity</td> 
                                                <td>
-                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity">
+                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                                </button>
                                                        </td>
                </table>
        
                </div>
-       
 
        {%if 'Enabled'  in user_status %}
                <div class="col-md-12">
                <h3>Credentials <small>Delegated to Principal Account</small></h3>
-                       <table class="table">
-                                       <caption><b>Delegated User Credential</b></caption> 
-                           <tr class="odd"> 
-                               <th>Expiration Date</th>
-                                               <th>Download</th>
-                           </tr>
-                                       {% for row in my_users %}         
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
-                                                               <span class="glyphicon glyphicon-download"></span> Credential
-                                                       </button>
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate">
-                                                               <span class="glyphicon glyphicon-download"></span> Certificate
-                                                       </button>
-                             <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
-                                 <span class="glyphicon glyphicon-download"></span> PKCS p12
-                             </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                                </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Slice Credentials</b></caption>  
-                               <tr class="odd"> 
-                                               <th>Slice Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                               </tr>
-                                       {% for row in my_slices %}     
-                               <tr class="border_bottom">
-                                       <td class="odd"> {{ row.slice_name }} </td>
-                                               <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd"> 
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button> 
-                                               </td>
-                               </tr>
-                               {%endfor%}
-                               </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Authority Credentials</b></caption>
-                                       <tr class="odd"> 
-                                       <th>Authority Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                                       </tr>
-                                       {% for row in my_auths %}
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.auth_name }} </td>
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                               </table>
-                               <p></p>
-                                {%if '' not in my_users%}      
-                               <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%else%}
-                               <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%endif%}
+                   <table class="table">
+                               <caption><b>Delegated User Credential</b></caption> 
+                       <tr class="odd"> 
+                           <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_users %}         
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+                                                       <span class="glyphicon glyphicon-download"></span> Credential
+                                               </button>
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+                                                       <span class="glyphicon glyphicon-download"></span> Certificate
+                                               </button>
+                         <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+                             <span class="glyphicon glyphicon-download"></span> PKCS p12
+                         </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                        </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Slice Credentials</b></caption>  
+                       <tr class="odd"> 
+                                       <th>Slice Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_slices %}     
+                       <tr class="border_bottom">
+                               <td class="odd"> {{ row.slice_name }} </td>
+                                       <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd"> 
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button> 
+                                       </td>
+                       </tr>
+                       {%endfor%}
+                       </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Authority Credentials</b></caption>
+                               <tr class="odd"> 
+                               <th>Authority Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                               </tr>
+                               {% for row in my_auths %}
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.auth_name }} </td>
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                       </table>
+                       <p></p>
+                        {%if '' not in my_users%}      
+                       <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+                       {%else%}
+                       <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+                       {%endif%}
                </div>
        </div>
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
-                    </div>
-                                       <div class="modal-body" style="text-align:justify;">
-                                       <p>You are getting this message for any of the following reasons:</p>
-                                       <ul>
-                                               <li>If your account is still pending for validation</li>
-                                               <li>If you press the "Clear Credentials" button</li>
-                                               <li>If you "Generate a new key pair"</li>
-                                               <li>If a new slice is added to your account</li>
-                                       </ul>
-                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
-                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
-                                               then please logout and login back into to the portal.
-                                       </p>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>
-                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
-                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
-                                                       delegated to the portal, please follow these instructions:
-                                               </p>
-                                               <ul>
-                                                       <li>Your account must first be validated by the manager of your organization.</li>
-                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
-                                               </ul>
-                                       </p>
-                                       <h3>Contact support</h3>
-                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
-
-
-<!-- Modal- Trade-off Message  -->
-<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">
-                                                               Automatic vs. Manual delegation of credentials
-                                                       </h4>
-                    </div>
-                                       <div class="modal-body" style="text-align:justify;">
-                                       <h3>Automatic delegation of credentials</h3>
-                                               <p>Don't delete private key, ease-of-use option:</p>
-                                               <ul>
-                                                       <li>
-                                                               This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
-                                                       </li>
-                                                       <li>
-                                                               This option does not provide as high of a level of security; however, your private key will still only be used in the portal and 
-                                                               will be available to you and the Fed4FIRE admins only.
-                                                       </li>
-                                               </ul>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>Download & Delete private key, higher security option:</p>
-                                               <ul>
-                                                       <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials 
-                                                               on your behalf, and you will have to manually
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
-                                                       </li>
-                                               </ul>
-                                       <h3>Contact support</h3>
-                                       <p>For more information, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
-
 
 
        <div class="tab-pane row" id="access">
                 <td class="odd"> {{ row.account_type }} </td>
                                <td class="odd"> {{ row.account_reference }} </td>
                                <td class="odd">
-                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
                                                <span class="glyphicon glyphicon-minus"></span>
                                        </button>
                                </td>
             <tr class="border_bottom">
                 <td class="odd"> {{ platform.platform_no_access }} </td>
                 <td class="odd">
-                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
                                                <span class="glyphicon glyphicon-plus"></span>
                                        </button>
                                </td>
        </div>
 {%endif%} 
 </div>
-</form>
 </div>
 
+</form>
 <script>
     $(document).ready(function() {
+           {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+        localStorage.clear();
+        $.post("/cache/clear/", function( data ) {
+        });
+        {% endif %}
        $('.nav-tabs a').click(function (e) {
                        e.preventDefault();
                        $(this).tab('show');
                        id = $(this).attr('href').substr(1);
-               
                });
                
         $('button#createslice').click(function() {
index 385f698..5d632b6 100644 (file)
@@ -6,47 +6,7 @@
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
-                    </div>
-                    <div class="modal-body" style="text-align:justify;">
-                                       <p>You are getting this message for any of the following reasons:</p>
-                                       <ul>
-                                               <li>If your account is still pending for validation</li>
-                                               <li>If you press the "Clear Credentials" button</li>
-                                               <li>If you "Generate a new key pair"</li>
-                                               <li>If a new slice is added to your account</li>
-                                       </ul>
-                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
-                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
-                                               then please logout and login back into to the portal.
-                                       </p>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>
-                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
-                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
-                                                       delegated to the portal, please follow these instructions:
-                                               </p>
-                                               <ul>
-                                                       <li>Your account must first be validated by the manager of your organization.</li>
-                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
-                                               </ul>
-                                       </p>
-                                       <h3>Contact support</h3>
-                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
+{% widget "_widget-no_credentials.html" %}
 <div class="container dashboard">
        <div class="row">
        {%if 'no_creds'  in user_cred %}
@@ -55,7 +15,6 @@
        {%if 'creds_expired'  in user_cred %}
        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
-               {%if 'is_pi'  in pi %}
                <div class="col-md-3">
                        <h3>
                                EXPERIMENT
                                <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a>
                        </div>
                        <div>
-                               <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
-                       </div>
-               </div>
-               <div class="col-md-3">
-                       <h3>
-                               SUPPORT
-                       </h3>
-                       <div>
-                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
-                       </div>
-                       <p></p>
-                       <div>
-                       <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
-                       </div>
-                       <div>
-                       <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
-                       </div>
-               </div>
-               
-               <div class="col-md-3">
-                       <h3>
-                               ACCOUNT
-                       </h3>
-                       <div>
-                               <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
-                       </div>
-                       <div>
-                               {% if person.last_name %}
-                                       {{person.first_name}} {{person.last_name}}<br />
-                               {% endif %}
-                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
-               </div>
-               </div>
-       </div>
-       {%else%}
-       <div class="row">
-               <div class="col-md-4">
-                       <h3>
-                               EXPERIMENT
-                       </h3>
-                       <div>
-                               <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+                               <button id="projectrequestbtn" type="button" class="btn btn-default" style="width:165px;"><span class="glyphicon glyphicon-plus"></span> Join Project</button>
                        </div>
                        <div>
-                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+                               <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
                        </div>
                        <div>
-                               <p><strong>Your slices </strong>
-                               <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
-                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
-                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
-                                       those slices will not appear here."
+                               <p><strong>Your projects </strong>
+                                       <span title="A project is a sub-authority under the responsability of your institution gathering users, who will be able to create slices for their experiments."
                                        class="glyphicon glyphicon-info-sign">
                                </span>
-                               </p>
+                               </p>
                        </div>
                        <div>   
-                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                               <div id="home-project-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
                        </div>
-                       {% if pending_slices %}
-                       <p><strong>Pending slices</strong>
-                       <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
-                               class="glyphicon glyphicon-info-sign">
-                       <ul>
-                       {% for slices in pending_slices %}
-                       <li>{{slices}}</li>
-                       {% endfor %}
-                       </ul>
-                       </span>
-                       </p>
-                       {%endif%}
-                       <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
-                       <a class="btn btn-primary" style="width: 150px;" 
-                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
-                                       title="Click here to start your experiment with jFed" 
-                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
-                    <span class="glyphicon glyphicon-cloud"></span> jFed</a>   
+
                </div>
-               <div class="col-md-4">
+               <div class="col-md-3">
                        <h3>
                                SUPPORT
                        </h3>
                        </div>
                        <p></p>
                        <div>
-                       <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
+                       <button id="statbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats" style="margin-right: 10px;"></span>Testbeds' status</button>
                        </div>
                        <div>
                        <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
                        </div>
                </div>
                
-               <div class="col-md-4">
+               <div class="col-md-3">
                        <h3>
                                ACCOUNT
                        </h3>
                </div>
                </div>
        </div>
-       {%endif%}
 
 </div>
 {% else %}
 
 <script type="text/javascript">
        $(document).ready(function() {
+           {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+        localStorage.clear();
+        $.post("/cache/clear/", function( data ) {
+        });
+        {% endif %}
                $('a.home-tab').click(function() {
                        $('ul.nav-tabs li').removeClass('active');
                        $(this).parent().addClass('active');
                $('button#slicerequestbtn').click(function() {
                        window.location="/portal/slice_request/";
                });
+               $('button#projectrequestbtn').click(function() {
+                       window.location="/portal/project_request/";
+               });
 
         myslice.loadSlices();
 });
index bd361de..90da984 100644 (file)
@@ -9,7 +9,11 @@
        <div class="row">
                <div class="col-md-12">
                         <div class="breadcrumbs">
-                                Management &nbsp;>&nbsp; Institution: <span id="authority_name"></span>
+                {% if project %}
+                               Management &nbsp;>&nbsp; Project: <span id="authority_name">{{user_details.parent_authority}}</span>
+                {% else %}
+                               Management &nbsp;>&nbsp; Institution: <span id="authority_name">{{user_details.parent_authority}}</span>
+                {% endif %}
                         </div>
                </div>
        </div>
@@ -20,6 +24,9 @@
                        <ul class="nav nav-tabs nav-section">
                                <li class="active"><a href="#about">About</a></li>
                                <li><a href="#users">Users</a></li>
+                {% if not project %}
+                               <li><a href="#projects">Projects</a></li>
+                {% endif %}
                                <li><a href="#slices">Slices</a></li>
                                <li><a href="#requests">Requests</a></li>
                        </ul>
@@ -28,6 +35,9 @@
 </div>
 <div class="container tab-content">
        <div class="tab-pane active row" id="about">
+        <div class="col-md-12 el">
+        <h2>{{user_details.parent_authority}}</h2>
+        </div>
        </div>
        
        <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
@@ -37,7 +47,9 @@
                                <table id="user-tab" class="table">
                                        <tr>
                                        <th>+/-</th>
+                            {% if not project %}
                                        <th>Email</th>
+                            {% endif %}
                                        <th>User hrn</th>
                             <!--
                                        <th>First name</th>
                                </table>
                                
                        </div>
-                       {%if 'is_pi'  in pi %}  
+                       {%if  pi %}     
                        <div>
+                {% if project %}
+                               <button id="removepi" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Remove from project</button>
+                {% else %}
+                               <button id="makepi" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-up"></span> Upgrade to PI</button>
+                               <button id="removepi" type="button" class="btn"><span class="glyphicon glyphicon-arrow-down"></span> Downgrade to  user</button>
                                <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+                {% endif %}
                        </div>
                        {% endif %}
                </div>
        </div>
 
+    {% if not project %}
+       <div class="tab-pane row" id="projects" data-authority="{{user_details.parent_authority}}">
+               <div class="col-md-12 el">
+                       <div id="project-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Projects" /></div>
+                               <div id="project-tab-loaded" style="display:none;">
+                               <table id="project-tab" class="table">
+                                       <tr>
+                                       <th>+/-</th>
+                                       <th>Project hrn</th>
+                                       </tr>
+                               </table>
+                               
+                       </div>
+                       <div>
+               {% if  pi %}
+                       <button id="createproject" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create project</button>
+                       <button id="deleteprojects" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected projects</button>
+                       {% else %}
+                       <button id="createproject" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request project</button>
+                       {% endif %}
+                       </div>
+               </div>
+       </div>
+   {% endif %}
        <div class="tab-pane row" id="slices">
                <div class="col-md-12 el">
            <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
                    </tr>
                </table>                        
            </div>
-       {% if 'is_pi'  in pi %}
         <div>
-               {% if 'is_pi'  in pi %}
+               {% if pi %}
                        <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
                        {% else %}
                        <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
                        {% endif %}
-            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
-            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
         </div>
-               {% endif %} 
           </div>
        </div>
        <div class="tab-pane row" id="requests">
@@ -92,7 +132,7 @@ $(document).ready(function() {
     {% if person %}
     {% if user_details.parent_authority %}
 
-        $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+        $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
             var list_slices = [];
             var table_slices = [];
             /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
@@ -103,7 +143,7 @@ $(document).ready(function() {
                 }else{
                     nodes_length=val.nodes.length;
                 }
-                console.log(val);
+                //console.log(val);
                 if(val.users=="undefined" || val.users==null){
                     users_length=0;
                 }else{
@@ -118,7 +158,14 @@ $(document).ready(function() {
                 
                 slice_row = "<tr id='"+val.slice_hrn+"'>";
                 slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
-                slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
+
+                // filter links to slices, only those that the user has credentials for
+                s = myslice.user.slices;
+                if(s.length > 0 && $.inArray(val.slice_hrn, myslice.user.slices)!=-1){
+                    slice_row += "<td><a href='/slice/"+val.slice_hrn+"'>" + val.slice_hrn + "</a></td>";
+                }else{
+                    slice_row += "<td>" + val.slice_hrn + "</td>";
+                }
                 slice_row += "<td>"+users_length+"</td>";
                 slice_row += "<td>"+slice_url+"</td>";
                 //slice_row += "<td>"+nodes_length+"</td>";
@@ -134,8 +181,25 @@ $(document).ready(function() {
             $("div#slice-tab-loading").css("display","none");
         });
                
-               
-        $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+        {% if project %}
+               $.post("/rest/myslice:authority/",{'fields':['pi_users'],'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
+           
+            var table_users = [];
+            $.each( data[0].pi_users, function( key, val ) {
+                //console.log(val);
+                user_row = "<tr id='"+val+"'>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val+"'></td>";
+                user_row += "<td>"+val+"</td>";
+                user_row += "</tr>";
+                table_users.push(user_row);
+            });
+            $("table#user-tab tr:last").after(table_users.join( "" ));
+            $("div#user-tab-loaded").css("display","block");
+            $("div#user-tab-loading").css("display","none");
+
+        });
+        {% else %}
+        $.post("/rest/myslice:user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
             var list_users = [];
             var table_users = [];
                    /* Available fields
@@ -160,7 +224,31 @@ $(document).ready(function() {
             $("div#user-tab-loaded").css("display","block");
             $("div#user-tab-loading").css("display","none");
         });
+               $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS{{user_details.parent_authority}}'}}, function( data ) {
+           
+            var table_projects = [];
+            $.each( data, function( key, val ) {
+                console.log(val);
+                project_row = "<tr id='"+val.authority_hrn+"'>";
+                project_row += "<td><input type='checkbox' class='project' id='"+val.authority_hrn+"'></td>";
 
+                // filter links to projects, only those that the user has credentials for
+                p = myslice.projects;
+                if(p.length > 0 && $.inArray(val.authority_hrn, p)!=-1){
+                    project_row += "<td><a href='/portal/project/"+val.authority_hrn+"'>"+val.authority_hrn+"</a></td>";
+                }else{
+                    project_row += "<td>"+val.authority_hrn+"</td>";
+                }
+                project_row += "</tr>";
+                table_projects.push(project_row);
+            });
+            $("table#project-tab tr:last").after(table_projects.join( "" ));
+            $("div#project-tab-loaded").css("display","block");
+            $("div#project-tab-loading").css("display","none");
+
+        });
+
+        {% endif %}
     {% endif %}
     {% endif %}
 
@@ -171,8 +259,13 @@ $(document).ready(function() {
                e.preventDefault();
                $(this).tab('show');
        var id = $(this).attr('href').substr(1);
+       if ((id == 'requests')){
+               $("#" + id).load('/management/' + id);
+        }
+        /*
        if ((id == 'requests') || (id == 'about'))
                $("#" + id).load('/management/' + id);
+        */
        });
        var hash = window.location.hash;
        if (hash) {
@@ -181,5 +274,79 @@ $(document).ready(function() {
                $('.nav-tabs a[href=#about]').click();
        }
 });
+
+//upgrade users to PI
+$(document).ready(function() {
+    $('button#makepi').click(function() {
+        var flag = false;
+        var pi_users = [];
+        $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
+            pi_users = data[0]["pi_users"];
+            $('input:checkbox.user').each(function (index) {
+                if(this.checked){
+                    var record_id = this.id;
+                    pi_users.push(record_id)
+                    flag = true;                
+                }
+            });
+            if(flag == true){
+                $.post("/update/myslice:authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'},'params':{'pi_users':pi_users}}, function(data) {
+                    if(data.success){
+                        mysliceAlert('Success: User rights added to: {{user_details.parent_authority}}','success', true);
+                    }else{
+                        mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                        //alert("Rest Error for "+record_id+": "+data.error);
+                    }
+                });
+            }
+        });
+    });
+});
+//downgrade to user [in projects:remove from project]
+$(document).ready(function() {
+    $('button#removepi').click(function() {
+        var flag = false;
+        var pi_users = [];
+        $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
+            pi_users = data[0]["pi_users"];
+                       // http://stackoverflow.com/questions/9792927/javascript-array-search-and-remove-string
+            $('input:checkbox.user').each(function (index) {
+                if(this.checked){
+                    var record_id = this.id;
+                                       for (var i=pi_users.length-1; i>=0; i--) {
+                                       if (pi_users[i] === record_id) {
+                                               pi_users.splice(i, 1);
+                                       }
+                                       }
+                    flag = true;                
+                }
+            });
+            if(flag == true){
+                $.post("/update/myslice:authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'},'params':{'pi_users':pi_users}}, function(data) {
+                    if(data.success){
+                        mysliceAlert('Success: User rights removed from: {{user_details.parent_authority}}','success', true);
+                        {% if project %}
+                        // remove the user from the list of pis of the project displayed
+                        $('input:checkbox.user').each(function (index) {
+                           if(this.checked){
+                               var record_id = this.id;
+                               $('tr[id="'+record_id+'"]').fadeOut("slow");
+                               $('tr[id="'+record_id+'"]').remove();
+                            }
+
+                        });
+                        {% endif %}
+                    }else{
+                        mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                        //alert("Rest Error for "+record_id+": "+data.error);
+                    }
+                });
+            }
+        });
+    });
+});
+
+
+
 </script>
 {% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_projectrequest_view.html b/portal/templates/fed4fire/fed4fire_projectrequest_view.html
new file mode 100644 (file)
index 0000000..d5885a0
--- /dev/null
@@ -0,0 +1,192 @@
+{% extends "layout.html" %}
+{% load i18n %}
+
+{% block content %}
+<script src="{{ STATIC_URL }}js/jquery-ui.js"></script>
+<script src="{{ STATIC_URL }}js/jquery-ui-combobox.js"></script>
+<link rel='stylesheet' type='text/css' href="{{ STATIC_URL }}css/jquery-ui.css">
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.ui.combobox.css">
+<br />
+<div class="row">
+    <div class="col-md-12">
+        <ul class="nav nav-tabs nav-section">
+            <li class="active"><a href="#existing">Join existing Project</a></li>
+            <li><a href="#new">Create new Project</a></li>
+            
+        </ul>
+    </div>
+</div>
+
+{% if errors %}
+<div class="row">
+    <div class="col-md-12">
+    <ul class="error">
+      {% for error in errors %}
+      <li>{{ error }}</li>
+      {% endfor %}
+    </ul>
+    </div>
+</div>
+{% endif %}
+
+<div class="container tab-content">
+    
+       <div class="tab-pane active" id="existing"> 
+        <div class="row">
+            <div class="col-md-6">
+                 <h3>Join an existing Project</h3>
+            </div>
+            <div class="col-md-6">
+                 <h3>List of projects you are part of</h3>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-md-6">
+                <form role="form" method="post" action="/portal/project_request">
+                {% csrf_token %}
+                <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div> 
+                <select id="projects" name="project_name" style="display:none;"></select> <div style="display:none;" id="projects_button"><input type="submit" id="join" name="join" value="Join" class="btn"/></div>
+                </form>
+            </div>
+            <div class="col-md-6">
+                <table class="table project-list">
+                    {% for pending in pending_projects %}
+                    <tr><td>(PENDING) {{ pending.project_name }}</td><td>{{ pending.authority_hrn }}</td><td>{{ pending.created|date:"d/m/Y" }}</td></tr>
+                    {% endfor %}
+                    {% for pending in pending_join_projects %}
+                    <tr><td>(PENDING JOIN) {{ pending.project_name }}</td><td>&nbsp;</td><td>{{ pending.created|date:"d/m/Y" }}</td></tr>
+                    {% endfor %}
+
+                </table>
+            </div>
+        </div>
+    </div>
+    
+    <div class="tab-pane" id="new"> 
+        <div class="row">
+            <div class="col-md-12">
+                 <h3>Create a new Project</h3>
+            </div>
+        </div>
+    
+        
+        <div class="row">
+            <div class="col-md-12">
+                <form role="form" method="post" action="/portal/project_request">
+                {% csrf_token %}
+                  <div class="form-group">
+                    <input type="text" name="project_name" value="" style="width:380px;" placeholder="Name" required>
+                  </div>
+                  <div class="form-group">
+                    <select id="org_name" name="authority_name" class="form-control" style="width:380px" value="{{ organization }}" required> 
+                    {% if authorities %}
+                        {% for authority in authorities %}
+                            {% if authority.name %}
+                                <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+                            {% else %}
+                                <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+                            {% endif %}
+                        {% endfor %} 
+                    {% endif %}
+                    </select>
+                  </div>
+                  
+                  
+                  <div class="form-group">
+                    <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Description" style="width:380px" title="Purpose of your project (informative)" required="required"></textarea>
+                  </div>
+                  <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
+                </form>
+        
+            </div>
+        </div>
+    </div>
+    
+</div>
+               
+<script>
+$(document).ready(function() {
+    var myprojects = JSON.parse(localStorage.getItem('projects'));
+    console.log(myprojects);
+    if (myprojects) {
+        $.each(myprojects, function (i, val){
+            console.log(val);
+            $('.project-list').append('<tr><td>'+ val +'</td></tr>');
+        });
+    } else {
+        $('.project-list').html('<tr><td>no projetcs</td></tr>');
+    }
+    
+    $('.nav-tabs a').click(function (e) {
+        e.preventDefault();
+        $(this).tab('show');
+    });
+    $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS{{ root_authority_hrn }}' }}, function( data ) {
+       
+        var projects = [];
+        project_row = "<option value=''> - </option>";
+        projects.push(project_row);
+       
+        $.each( data, function( key, val ) {
+            if(val.authority_hrn.split('.').length > 2){
+                if($.inArray(val.authority_hrn, myprojects)==-1){
+                project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
+                projects.push(project_row);
+                }
+            }
+        });
+        $("#projects").show();
+        $("#projects_button").css('margin-left', '50px');
+        $("#projects_button").css('display', 'inline-block');
+        $("#project_loading").hide();
+        $("#projects").html(projects.join( "" ));
+        $("#projects").combobox();
+    });
+/*
+       
+       $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+               var jsonData = JSON.parse(data);
+        $(this).attr("value", jsonData[0]['parent_authority']);
+    });
+       $("#authority_hrn").val("{{authority_name}}");
+       var availableTags = [
+    {% if authorities %}
+        {% for authority in authorities %}
+            {% if authority.name %}
+                {value:"{{ authority.name }}",label:"{{authority.name}}"},
+                       // to show only full name
+            {% else %}
+                {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+            {% endif %}
+        {% endfor %}    
+    {% else %}
+        {value:"",label:"No authority found !!!"}
+    {% endif %}
+    ];
+       // sorting the list
+       availableTags.sort(function(a,b){
+               var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+               if (nameA < nameB) {
+               return -1;
+               }
+               if (nameA > nameB) {
+               return 1;
+               }
+       return 0;
+       }); 
+    $( "#authority_hrn" ).autocomplete({
+      source: availableTags,
+      minLength: 0,
+      select: function( event, ui ) {console.log(jQuery(this));}
+    });
+*/
+       $("#submit_pi").click(function() {
+               localStorage.clear();
+       });
+       // auto-complete the form
+    jQuery("#org_name").combobox();
+
+});
+</script>
+{% endblock %}
+
index 29e0895..ebfb4e6 100644 (file)
 {% block content %}        
 
 <div class="row">
+       <div class="col-md-12">
        <h1><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Registration" />User sign-up</h1>
+       </div>
 </div>
 <div class="row">
-               <p></p>
-               <p><strong>Questions? <a href="/portal/contact" >Contact us.</a></strong></p>
+       <div class="col-md-12">
+               <p><strong>Questions? <a href="/contact" >Contact us.</a></strong></p>
+  </div>
 </div>
 {% if errors %}
-<ul>
-  {% for error in errors %}
-  <li>{{ error }}</li>
-  {% endfor %}
-</ul>
+<div class="row">
+       <div class="col-md-12">
+               <ul class="error">
+                 {% for error in errors %}
+                 <li>{{ error | safe }}</li>
+                 {% endfor %}
+               </ul>
+       </div>
+</div>
 {% endif %}
-<div class="row"><div class="col-sm-12">
-<form class="cmxform form-horizontal" id="registrationForm" method="post" enctype="multipart/form-data" role="form">
-{% csrf_token %}
-       <div class="form-group">
-               <label for="authority_hrn" class="control-label">Authority</label>
-               <p></p>
-               <input id="authority_hrn" name="authority_hrn" class="form-control" style="width:530px" value="{{ authority_hrn }}" placeholder="fed4fire.global" required>
-               <p class="help-block">If your organization does not deploy a Fed4FIRE authority itself, you can use the<br> default one called "fed4fire.global".
+<form action="/register" class="cmxform form-horizontal" method="post" enctype="multipart/form-data">
+<div class="row">
+       <div class="col-md-12">
+                       <p>
+                               {% csrf_token %}
+                               <label for="authority_hrn" class="control-label">Organization</label>
+                       </p>
+                       <p>
+                               <select id="org_name" name="org_name" class="form-control" style="width:590px" value="{{ organization }}" 
+                               title="Choose your organization (company/university) from the list that apears when you click in the field and start to type.
+                                Use the arrow keys to scroll through the list; type part of the name to narrow down the list. We will send an email to 
+                                the managers that we have on record for your organization, asking them to validate your sign-up request." required>
+                {% if authorities %}
+                    {% for authority in authorities %}
+                        {% if authority.name %}
+                            <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
+                        {% else %}
+                            <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
+                        {% endif %}
+                    {% endfor %}
+                {% else %}
+                    <option value:"">No authority found !!!</option>
+                {% endif %}
+                </select>
+            </p>
+                               <p class="help-block">If your organization does not deploy a Fed4FIRE authority itself, you can use the<br> default one called "fed4fire.global".
                If your organization however does provide a<br> Fed4FIRE authority itself, please make sure to select it here. If you start typing<br> your organization's
                 name, it will pop up.
                </p> 
        </div>
+</div>
 
-       <div class="row">
-       <div class="col-md-4">
-       
-           <div class="form-group">
+<div class="row">
+       <div class="col-md-6">
+        <p>
                        <label for="firstname" class="control-label">Personal information</label>
-                       <p></p>
-                       <input type="text" name="firstname" class="form-control" style="width:200px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
-           </div>
-           <div class="form-group">
-                       <input type="text" name="lastname" size="25" class="form-control" style="width:200px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
-           </div>
-               <div class="form-group">
-               <input type="email" name="email" size="25"  class="form-control" style="width:200px" value="{{ email }}" 
+               </p>
+        <p>
+                       <input type="text" name="firstname" class="form-control" style="width:350px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
+           </p>
+        <p>
+                       <input type="text" name="lastname" size="25" class="form-control" style="width:350px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
+           </p>
+        <p>
+               <input type="email" name="email" size="25"  class="form-control" style="width:350px" value="{{ email }}" 
                        title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues."
-                       placeholder="Email" required/>
-               </div>
+                       placeholder="Email" required />
+               </p>
        </div>  
 
-       <!-- LOGIN
-       TODO: Login should be suggested from user email or first/last name, and
-       checked for existence. In addition, the full HRN should be shown to the
-       user.
-    <div class="form-group">
-      <label for="login" class="col-xs-2 control-label">Login</label>
-      <div class="col-xs-4">
-         <input type="text" name="login" size="25" class="form-control" minlength="2" value="{{ login }}" placeholder="Login" required />
-      </div>
-      <div class="col-xs-6"><p class="form-hint">Enter your login</p></div>
-    </div>
-       -->
-       <div class="col-md-4">
-           <div class="form-group">
+       <div class="col-md-6">
+        <p>
              <label for="password" class="control-label">Authentication</label>
-                 <p></p>       
-             <input type="password"  id="password" name="password"   class="form-control" style="width:200px" minlength="4" value="{{ password }}" 
-                       title="Your password allows you to log in to this portal."
-                       placeholder="Password" required/>
-           </div>
-           <div class="form-group">
-                       <input type="password"  id="confirmpassword" name="confirmpassword" style="width:200px"  minlength="4" class="form-control" value="" 
-                               placeholder="Confirm password" required/>
-           </div>
-           <div class="form-group">
-               <!--<label for="question" class="control-label">Keys</label> -->
-                       <select name="question" class="form-control" style="width:200px" id="key-policy" 
-                               title="Your public/private key pair allows you to access the testbeds." required>        
+               </p>
+               <p>     
+             <input type="password"  id="password" name="password"   class="form-control" style="width:250px" minlength="4" value="{{ password }}" title="Your password allows you to log in to this portal." placeholder="Password" required />
+           </p>
+        <p>
+                       <input type="password"  id="confirmpassword" name="confirmpassword" style="width:250px"  minlength="4" class="form-control" value="" placeholder="Confirm password" required />
+           </p>
+        <p>
+                       <select name="question" class="form-control" style="width:350px" id="key-policy" 
+                               title="Your public/private key pair allows you to access the testbeds." required >        
                                <option value="generate">Generate my keys for me (recommended)</option>
                                <option value="upload">Upload my public key (advanced users only)</option>
                        </select>
-           </div>
-           <div class="form-group" style="display:none;" id="upload_key">
+           </p>
+           <div style="display:none;" id="upload_key">
                <label for="file" class="control-label">Upload public key</label>
-               <input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" required/>
+               <input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" />
                <br />
                        <div class="alert alert-danger" id="pkey_del_msg">
                                In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to 
-                               <a href="http://trac.myslice.info/wiki/InstallSfa" target="_blank">delegate your public key to the portal.</a>
+                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
                        </div>
            </div>
        </div>
+</div>
+<div class="row">
+       <div class="col-md-12">
+        <p>
+                       <input type="checkbox" name="agreement" value="agreement" required />&nbsp;&nbsp; I agree to the 
+                       <a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a> 
+               </p>
        </div>
-
-       <div class="form-group">
-               <p></p>
-               <input type="checkbox" name="agreement" value="agreement" required/> I agree to the 
-               <button class="btn btn-default btn-xs" data-toggle="modal" data-target="#myModal">terms and conditions.</button> 
+</div>
+<div class="row">
+       <div class="col-md-12">
+               <div id="register">
+                       <p>
+               <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+              </p>
+           </div>
        </div>
+</div>
+</form>
        <!-- Modal - columns selector -->
-               <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-                       <div class="modal-dialog">
-                       <div class="modal-content">
-                               <div class="modal-header">
-                                       <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                                               <h4 class="modal-title" id="myModalLabel">Terms & Conditions</h4>
-                               </div>
-                               <div class="modal-body">
-                                               <p>The exact terms and conditions for Fed4FIRE are currently under development.</p>                                             
-                               </div>
-                               <div class="modal-footer">
-                                       <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                               </div>
-                       </div>
-                       </div>
-               </div>
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+       <div class="modal-dialog">
+               <div class="modal-content">
+                       <div class="modal-header">
+                               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                                       <h4 class="modal-title" id="myModalLabel">Terms & Conditions</h4>
+                       </div>
+                       <div class="modal-body">
+                               <p align="left">
+                                       The exact terms and conditions for Fed4FIRE are currently under development.
+                               </p>
 
-    <div class="form-group" id="register">
-               <p></p> 
-       <button class="submit btn btn-primary" type="submit">Sign up</button>
-    </div>
-</form>  
+                       </div>
+                       <div class="modal-footer">
+                               <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                       </div>
+               </div>
+       </div>
 </div>
+
+    
 <script>
-jQuery(document).ready(function(){
-    //this .load is useless here
-    $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
-        $(this).attr("value", 'fed4fire.global');
-    });
+
+$(document).ready(function(){
+    /*
     var availableTags = [
     {% if authorities %}
         {% for authority in authorities %}
             {% if authority.name %}
                 {value:"{{ authority.authority_hrn }}",label:"{{authority.name}}"},
+                       // show hrn if we don't have the name
             {% else %}
                 {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
             {% endif %}
@@ -139,19 +159,46 @@ jQuery(document).ready(function(){
         {value:"",label:"No authority found !!!"}
     {% endif %}
     ];
-    jQuery( "#authority_hrn" ).autocomplete({
-      source: availableTags,
-      minLength: 0,
-      change: function (event, ui) {
-          if(!ui.item){
-              //http://api.jqueryui.com/autocomplete/#event-change -
-              // The item selected from the menu, if any. Otherwise the property is null
-              //so clear the item for force selection
-              jQuery("#authority_hrn").val("");
-          }
-      }
-      //select: function( event, ui ) {console.log(jQuery(this))}
+       // sorting the list
+    
+       availableTags.sort(function(a,b){
+               var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+               if (nameA < nameB) {
+               return -1;
+               }
+               if (nameA > nameB) {
+               return 1;
+               }
+       return 0;
+       }); 
+    */
+    
+       // auto-complete the form
+    jQuery("#org_name").combobox();
+
+    //setting the default value in the org_list
+    var temp="fed4fire.global"; 
+    $("#org_name").val(temp);
+
+    /*
+    // Must be executed in Python as Admin Query - User is not logged in
+
+    $.post("/rest/authority/",{'filters':{'authority_hrn':'CONTAINS'+temp}}, function( data ) {
+        $.each( data, function( key, val ) {
+            console.log(val);
+        });
     });
+    */
+       $('[title!=""]').qtip();
+       $("form").validate();
+       $("form").submit(function() {
+               if ($('select option:selected').val() == 'upload') {
+                       if ($('input[name=user_public_key]').val() == '') {
+                               alert('Please specify the key file to upload');
+                               return false;
+                       }
+               }
+       });
 });
 </script>
 {% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html b/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html
deleted file mode 100644 (file)
index 0ca237f..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<div class="col-md-2">
-</div>
-<div class="col-md-8">
-       <h2>How to access your slice</h2>
-       <h3>PlanetLab Europe</h3>
-       
-       <p>
-               PlanetLab Europe resources are accessible directly via SSH. Your SSH public key is deployed automatically
-               on the reserved nodes. To access your slice on a resource just type the following command:
-       </p>
-       {%if ple_resources%}
-       <p class="command">
-       {%for resource in ple_resources %}
-               $ ssh {{ple_slicename}}@{{resource}}<br>
-       {%endfor%}
-       </p>
-        <h4>Windows users</h4>
-        <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
-       {%else%}
-               <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
-               <p class="command">
-               $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
-               </p>
-                <h4>Windows users</h4>
-                <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
-       {%endif%}
-       <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
-       <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
-       <p>
-               Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes, 
-               after witch you will be able to access the resource.
-       </p>
-       
-       <h3>NITOS</h3>
-       
-       <p>
-        NITOS resources are not directly accessible. You will need to log in on a gateway server and from there access the node.
-        The NITOS server address is nitlab.inf.uth.gr, so to connect to the NITOS server:
-       </p>
-       <p class="command">
-       $ ssh {{slicename}}@nitlab.inf.uth.gr
-       </p>
-       <h4>Windows users</h4>
-       <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
-
-       <p>
-       <!-- In order to connect to NITOS server he has to upload his public key on the server. 
-       For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys. 
-       I think this is a procedure that needs to be done at the registration phase of the user, 
-       through myslice, Broker etc. but I will answer you in a couple of days for sure. -->
-       </p>
-
-       <p>
-               You will then need to prepare the resource by loading an OMF image on it:
-       </p>
-       
-       <p class="command">
-               $ omf load -i baseline_grid.ndz -t omf.nitos.node016
-       </p>
-
-       <p>
-               Turn on the node:
-       </p>
-       
-       <p class="command">
-               $ omf tell -a on -t omf.nitos.node016
-       </p>
-       <p>
-               And finally ssh on the node:
-       </p>
-       <p class="command">
-               $ ssh root@node016
-       </p>
-       <p>
-               On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
-               restart the OMF Resource Controller and finally execute the experiment:
-       </p>
-       <p class="command">
-               $ omf exec --slice slice_name your_exp.rb
-       </p>
-       <p>
-       The complete tutorial is available at the following address:
-       <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
-       </p>
-       
-       <br />
-       
-       <h2>Available Tools</h2>
-       <p><img src="{{ STATIC_URL }}img/terminal_icon.png" width="50"> <b>SSH</b></p>
-       <p>
-       Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers that connects, via a secure channel over an insecure network, a server and a client (running SSH server and SSH client programs, respectively). The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2.
-       </p>
-       <p> More Info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
-       <br>
-       <br>
-       <p><img src="{{ STATIC_URL }}img/nepi_logo.png" width="90"></p>
-       <p>NEPI, the Network Experimentation Programming Interface, is a life-cycle management tool for network experiments. The idea behind NEPI is to provide a single tool to design, deploy, and control network experiments, and gather the experiment results. Going further, NEPI was specially conceived to function with arbitrary experimentation platforms, so researchers could use a single tool to work with network simulators, emulators, or physical testbeds, or even a mixture of them. To accomplish this, NEPI provides a high-level interface to describe experiments that is independent from any experimentation platform, but is able to capture platform specific configurations. Experiment definitions can be stored in XML format to be later reproduced, and modified according to experimentation needs. Experiment execution is orchestrated by a global experiment controller, that is platform independent, and different platform-dependent testbed controllers, creating a control hierarchy that is able t adapt to platform specific requirements while providing an integrated control scheme.</p>
-       <p> More Info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
-       <br>
-       <p><img src="{{ STATIC_URL }}img/omf-logo.png" width="90"></p>
-       <p>OMF is a Testbed Control, Measurement and Management Framework.</p>
-       <p>
-       OMF was originally developed for the ORBIT wireless testbed at Winlab, Rutgers University. Since 2007, OMF has been actively extended to operate on testbeds with many different type of network and resource technologies. It is now deployed and used on different testbeds in Australia, Europe, and in the U.S. OMF is currently being extended further to support exciting new features and technologies. This website is hosting this ongoing activity. OMF development is now conducted essentially within the TEMPO project at NICTA (Australia) in strong collaboration with Winlab (Rutgers University).
-       </p>
-       <p>In addition to the main OMF software, this site also hosts OMF sub-projects addressing various related aspects of a testbed's control, measurement, and management.</p>
-       <p>More Info: <a href="http://mytestbed.net/projects/omf" target="_blank">http://mytestbed.net/projects/omf</a></p>
-</div>
-<div class="col-md-2">
-</div>
index 98097db..7bcd56d 100644 (file)
@@ -4,7 +4,7 @@
 {% block content %}
        <div class="row">
                <div class="col-md-12">
-                        <div class="breadcrumbs">
+                        <div class="breadcrumbs" style="line-height: 3;">
                                 Experiment &nbsp;>&nbsp; Request a new Slice
                         </div>
                </div>
                                title="Please enter a name for your slice"required="required">
                          </div>
                          <div class="form-group">
-                               {%if 'is_pi'  in pi %}
+                               {% if pi %}
                                <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization" 
                                title="An authority responsible for vetting your slice" required="required">
-                               {%else%}
-                           <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
+                               {% else %}
+                           <input type="hidden" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
                                title="An authority responsible for vetting your slice" required="required" readonly>
-                               {%endif%}
+                <span style="float:left;">Authority: &nbsp;</span>
+                <div id="authority_display">
+                <img src="{{ STATIC_URL }}img/loading.gif" alt="Loading authority" />
+                </div>
+                               {% endif %}
                          </div>
                          <div class="form-group">
+                Project: <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div> 
+                <select id="project" name="project" style="display:none;">
+                </select>
+              </div>
+                         <div class="form-group">
                            <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
                                title="Please provide the url of your experiment if you have one." value="{{url}}">
                          </div>
                                <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px" 
                                title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
                          </div>
-                         {%if 'is_pi'  in pi %}        
+                         {% if pi %}   
                          <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
-                         {%else%}
+                         {% else %}
                          <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
-                         {%endif%}     
+                         {% endif %}   
                        </form>
        
                </div>
@@ -66,7 +75,15 @@ jQuery(document).ready(function(){
        $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
                var jsonData = JSON.parse(data);
         $(this).attr("value", jsonData[0]['parent_authority']);
+           {% if pi %}
+        draw_projects(jsonData[0]['parent_authority']);
+        {% else %}
+        $('#authority_display').html(jsonData[0]['parent_authority']);
+        draw_projects('');
+        {% endif %}
     });
+
+       {% if pi %}
        $("#authority_hrn").val("{{authority_name}}");
        var availableTags = [
     {% if authorities %}
@@ -96,13 +113,46 @@ jQuery(document).ready(function(){
     $( "#authority_hrn" ).autocomplete({
       source: availableTags,
       minLength: 0,
-      select: function( event, ui ) {console.log(jQuery(this));}
+      select: function( event, ui ) {
+        $("#project").hide();
+        $("#project_loading").css('display', 'inline-block');
+        draw_projects(jQuery('.ui-state-focus').html());
+      },
     });
-
-       $("#submit_pi").click(function() {
-               localStorage.clear();
-       });
+    {% endif %}
 });
+
+function draw_projects(authority_hrn){
+
+    var projects = [];
+    project_row = "<option value=''> - </option>";
+    projects.push(project_row);
+
+    if(authority_hrn.length > 0){
+        // Not for root authority
+        if(authority_hrn.split('.').length > 1){
+            $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS'+authority_hrn}}, function( data ) {
+               
+                $.each( data, function( key, val ) {
+                    project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
+                    projects.push(project_row);
+                });
+                $("#project").html(projects.join( "" ));
+            });
+        }else{
+            $("#project").html(projects.join( "" ));
+        }
+    }else{
+        my_projects = JSON.parse(localStorage.getItem('projects'));
+        $.each( my_projects, function( i, val ) {
+            project_row = "<option value='"+val+"'>"+val+"</option>";
+            projects.push(project_row);
+        });
+        $("#project").html(projects.join( "" ));
+    }
+    $("#project").show();
+    $("#project_loading").hide();
+}
 </script>
 {% endblock %}
 
index ddb4518..680163e 100644 (file)
@@ -1,56 +1,52 @@
 
 <div id="header">
-       <div class="wrapper">
-               <div class="logo">
-                       <a href="/"><img src="{{ STATIC_URL }}img/f4f-logo.png" alt="Fed4Fire Portal" width="80px" />Home</a>
-               </div>
-               
-               <div id="secondary">
+    <div class="container">
+    <div class="row">
+        <div class="col-sm-4 col-md-4 logo">
+            <a href="/"><img src="{{ STATIC_URL }}img/f4f-logo.png" alt="Fed4Fire Portal" width="80px" /></a>
+        </div>
+        
+        
+           <div id="secondary" class="col-sm-8 col-md-8 secondary">
                        <ul>
+                           <li><a href="/">Home</a></li>
                                <li><a href="/portal/about">About</a></li>
                                <li><a href="http://doc.fed4fire.eu/">Documentation</a></li>
                                <li><a target="_blank" href="http://www.fed4fire.eu">Project website</a></li>
                        </ul>
                </div>
        </div>
-       
-       {% if username %}
-       <div id="navigation">
-               <div class="wrapper">
-               <ul>
-                       <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
-                       <li>|</li>
-                       <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
-                       <li class="slices">
-                               <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                                       SLICES <span class="caret"></span>
-                       </a>
-                               
-                               <div class="dropdown-menu" style="z-index:99;">
-                                               <ul id="dropdown-slice-list">
-                                                       <li><a href="/portal/slice_request/">Request Slice</a></li>
-                            <!--
-                                                       <li><a href="/slice/ple.upmc.agent3/">ple.upmc.agent3</a></li>
-                                                   <li><a href="/slice/ple.upmc.agent/">ple.upmc.agent</a></li>
-                                                   <li><a href="/slice/ple.upmc.myslicedemo/">ple.upmc.myslicedemo</a></li>
-                                                   <li><a href="/slice/ple.upmc.slicestat/">ple.upmc.slicestat</a></li>
-                                                   <li><a href="/slice/ple.upmc.agent2/">ple.upmc.agent2</a></li>
-                            -->
-                                               </ul>
-                               </div>
-                               </li>
-                       <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
-                       <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
-                       <li>|</li>
-                       <li id="nav-logout" style="margin-top: 10px;"><a id="logout" style="cursor:pointer;" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> LOGOUT</a></li>
-               </ul>
-               </div>
-       </div>
-       {% else %}
-       <div id="navigation">
-               <div class="wrapper"></div>
-       </div>
-       {% endif %}
+    </div>
+<div id="navigation">
+    <div class="container"> 
+       <div class="row">
+          {% if username %}
+        <div class="col-md-12 navigation">
+            <ul>
+                <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
+                <li>|</li>
+                <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
+                <li class="slices">
+                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">SLICES <span class="caret"></span></a>
+                    
+                    <div class="dropdown-menu" style="z-index:99;">
+                            <ul id="dropdown-slice-list">
+                                <li><a href="/portal/slice_request/">Request Slice</a></li>
+                            </ul>
+                    </div>
+                    </li>
+                <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
+                <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
+                <li>|</li>
+                <li id="nav-logout"><span class="glyphicon glyphicon-off iconlogout"></span> <a id="logout" data-username="{{ username }}" href="#">LOGOUT</a></li>
+            </ul>
+        </div>
+        {% else %}
+        <div class="col-sm-4 col-md-4 navigation">
+        </div>
+        {% endif %}
+    </div>
+    </div>
 </div>
 <script>
        $(document).ready(function() {
                                $(this).fadeOut(100);
                        }
                });
-               // var slices = localStorage.getItem('slices');
-               // if (slices.length == 0) {
-                       // $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
-                       // var items = [];
-                               // localStorage.setItem('slices', data[0].slice);
-                       // });
-               // }
-               // $.each(slices, function( key, val ) {
-                       // items.push( "<li><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
-               // });
-               // $("div#home-slice-list").html($( "<ul/>", { html: items.join( "" ) }));
        });
 </script>
index 383aa95..379547c 100644 (file)
-{% extends "layout.html" %}
+{% extends "layout_base.html" %}
 {% load portal_filters %}
 
 {% block content %}
-<div class="row">
+<!-- <div class="row">
 {% widget '_widget-news.html' %}
-</div>
-<div class="row" id="home-dashboard">
-       <ul class="nav nav-tabs">
-         <li class="active"><a class="home-tab" data-panel="user" href="#">USER</a></li>
-         <li><a class="home-tab" data-panel="manager" href="#">MANAGER</a></li>
-       </ul>
-       <div class="home-panel" id="user">
-               <table>
-                       <tr>
-                               <td>ACCOUNT</td>
-                               <td>SLICES</td>
-                               <td>SUPPORT</td>
-                       </tr>
-                       <tr>
-                               <td><a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a></td>
-                               <td><a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a></td>
-                               <td><a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a></td>
-                       </tr>
-                       <tr>
-                               {% if person %}
-                               <td class="logged-in">
-                                       <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
-                                       <div>
-                                       {% if person.last_name %}
-                                               {{person.first_name}} {{person.last_name}}<br />
-                                       {% endif %}
-                                       <span class="label">Email:</span> <a href='/portal/account/'>{{person.email}}</a>
-                               </div>
-                               {% else %}
-                               <td>
-                                       {% widget '_widget-login-user.html' %}
-                               {% endif %}
-                               </td>
-                               <td>
-                               {% if person %}
-                                       <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
-                                       <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
-                               {% else %}
-                                       <button id="signupbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-user"></span> Sign Up</button>
+</div> -->
+{% if username %}
+{% widget "_widget-no_credentials.html" %}
+<div class="container dashboard">
+       {%if 'no_creds'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+    {%endif%}
+       {%if 'creds_expired'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
+
+       <div class="row">
+               {% if pi %}
+               <div class="col-md-3">
+                       <h3>
+                               EXPERIMENT
+                       </h3>
+                       <div>
+                               <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
+                       </div>
+                       <div>
+                               <p><strong>Your slices </strong>
+                                       <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                                       However, on the OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere, 
+                                       such as on the PlanetLab Europe portal, those slices will not appear here."
+                                       class="glyphicon glyphicon-info-sign">
+                               </span>
+
+                               </p>
+                       </div>
+                       <div>   
+                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                       </div>
+               </div>
+               <div class="col-md-3">
+                       <h3>MANAGEMENT</h3>
+                       <div>
+                               <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
+                       </div>
+               </div>
+               <div class="col-md-3">
+                       <h3>
+                               SUPPORT
+                       </h3>
+                       <div>
+                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+                       </div>
+               </div>
+               
+               <div class="col-md-3">
+                       <h3>
+                               ACCOUNT
+                       </h3>
+                       <div>
+                               <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
+                       </div>
+                       <div>
+                               {% if person.last_name %}
+                                       {{person.first_name}} {{person.last_name}}<br />
                                {% endif %}
-                               </td>
-                               <td class="support">
-                                       <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
-                               </td>
-                       </tr>
-               </table>
+                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+               </div>
+               </div>
        </div>
-       <div class="home-panel" id="manager">
-               <table>
-                       <tr>
-                               <td>INSTITUTION</td>
-                               <td>SLICES</td>
-                               <td>REQUESTS</td>
-                       </tr>
-                       <tr>
-                               <td><a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a></td>
-                               <td><a href="/portal/institution#slices"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a></td>
-                               <td><a href="/portal/validate"><img src="{{ STATIC_URL }}img/icon_testbed_color.png" alt="" /></a></td>
-                       </tr>
-                       <tr>
-                               {% if person %}
-                               <td class="logged-in">
-                                       <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
-                               {% else %}
-                               <td>
-                                       {% widget '_widget-login-manager.html' %}
+       {%else%}
+       <div class="row">
+               <div class="col-md-4">
+                       <h3>
+                               EXPERIMENT
+                       </h3>
+                       <div>
+                               <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+                       </div>
+                       <div>
+                               <p><strong>Your slices </strong>
+                               <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                                       However, on the OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere, 
+                                       such as on the PlanetLab Europe portal, those slices will not appear here."
+                                       class="glyphicon glyphicon-info-sign">
+                               </span>
+                               </p>
+                       </div>
+                       <div>   
+                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                       </div>
+                       {% if pending_slices %}
+                       <p><strong>Pending slices</strong>
+                       <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
+                               class="glyphicon glyphicon-info-sign">
+                       <ul>
+                       {% for slices in pending_slices %}
+                       <li>{{slices}}</li>
+                       {% endfor %}
+                       </ul>
+                       </span>
+                       </p>
+                       {%endif%}       
+               </div>
+               <div class="col-md-4">
+                       <h3>
+                               SUPPORT
+                       </h3>
+                       <div>
+                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+                       </div>
+               </div>
+               
+               <div class="col-md-4">
+                       <h3>
+                               ACCOUNT
+                       </h3>
+                       <div>
+                               <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
+                       </div>
+                       <div>
+                               {% if person.last_name %}
+                                       {{person.first_name}} {{person.last_name}}<br />
                                {% endif %}
-                               </td>
-                               <td>
-                                       {% if person %}
-                                   <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
-                                       {% endif %}
-                               </td>
-                               <td class="support">
-                                       {% if person %}
-                                   <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
-                                       {% endif %}
-                               </td>
-                       </tr>
-               </table>
+                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+               </div>
+               </div>
        </div>
+       {%endif%}
+
 </div>
+{% else %}
+<div class="container-fluid home">
+       <div class="">
+               <div class="col-sm-2"></div>
+               <div class="col-sm-4 slogan">
+                       <h2>
+                               Your Easy Access to Computer Networking Testbeds:
+                       </h2>
+                       <h3>
+                               A wide variety of world class testbeds available through your one account
+                       </h3>
+               </div>
+               <div class="col-sm-5 col-sm-offset-1">
+                       <div class="row">
+                               {% widget '_widget-login-user.html' %}
+                       </div>
+               </div>
+               <div class="col-sm-1"></div>
+       </div>
+</div>
+{% endif %}
+
+
 <script type="text/javascript">
        $(document).ready(function() {
                $('a.home-tab').click(function() {
                        $('div#'+$(this).data('panel')).show();
                });
                $('button#validaterequestbtn').click(function() {
-                       window.location="/portal/validate/";
+                       window.location="/portal/institution#requests";
                });
                $('button#ticketbtn').click(function() {
                        window.location="/portal/contact/";
                $('button#slicerequestbtn').click(function() {
                        window.location="/portal/slice_request/";
                });
-/*-------
-List of slices has been moved in 
-portal/templates/base.html
-This should go into session
---------*/
+
+        myslice.loadSlices();
+        
 });
 </script>
+
 {% endblock %}
index c627e5b..30fad6c 100644 (file)
-{% extends "layout.html" %}
+{% extends "layout_wide.html" %}
 
 {% block head %} 
 <script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
 {% endblock head %}
 
 {% block content %}
-<div class="row">
-       <div class="col-md-12">
-               <ul class="nav nav-tabs nav-section">
-                       <li class="active"><a href="#info"><img src="{{ STATIC_URL }}icons/authority-xs.png" alt="Institution" /> Institution {{user_details.parent_authority}}</a></li>
-                       <li><a href="#users">Users</a></li>
-                       <li><a href="#slices">Slices</a></li>
-               </ul>
-    </div>
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Management &nbsp;>&nbsp; Institution: <span id="authority_name">{{user_details.parent_authority}}</span>
+                        </div>
+               </div>
+       </div>
 </div>
-<div class="tab-content">
-       <div class="tab-pane active row" id="info">
-               <div class="col-md-12">
-                       <div id="authority-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Authority" /></div>
-                   <div id="authority-tab-loaded" style="display:none;">
-                       <div id="authority-data"></div>
-                   </div>
-          </div>
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                       <ul class="nav nav-tabs nav-section">
+                               <li class="active"><a href="#about">About</a></li>
+                               <li><a href="#users">Users</a></li>
+                               <li><a href="#slices">Slices</a></li>
+                               <li><a href="#requests">Requests</a></li>
+                       </ul>
+           </div>
        </div>
-
+</div>
+<div class="container tab-content">
+       <div class="tab-pane active row" id="about">
+        <div class="col-md-12 el">
+        <h2>{{user_details.parent_authority}}</h2>
+        </div>
+       </div>
+       
        <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
-               <div class="col-md-12">
+               <div class="col-md-12 el">
                        <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
                                <div id="user-tab-loaded" style="display:none;">
-                               <table id="user-tab">
+                               <table id="user-tab" class="table">
                                        <tr>
                                        <th>+/-</th>
-                                       <th>email</th>
-                                       <th>user_hrn</th>
-                                       <th>first name</th>
-                                       <th>last name</th>
-                                       <th>enabled</th>
+                                       <th>Email</th>
+                                       <th>User hrn</th>
+                            <!--
+                                       <th>First name</th>
+                                       <th>Last name</th>
+                                       <th>Enabled</th>
+                            -->
                                        </tr>
                                </table>
-                               {%if 'is_pi'  in pi %}  
-                               <div>
-                                       <button id="deleteusers" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Users</button>
-                               </div>
-                               {%endif%}
+                               
+                       </div>
+                       {%if  pi %}     
+                       <div>
+                               <button id="makepi" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-up"></span> Upgrade to PI</button>
+                               <button id="removepi" type="button" class="btn"><span class="glyphicon glyphicon-arrow-down"></span> Downgrade to  user</button>
+                               <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
                        </div>
+                       {% endif %}
                </div>
        </div>
-       
+
        <div class="tab-pane row" id="slices">
+               <div class="col-md-12 el">
            <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
            <div id="slice-tab-loaded" style="display:none;">
-               {%if 'is_pi'  in pi %}
-               <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> create slice</button>
-               {%else%}
-               <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> request slice</button>
-               {%endif%}
-               <table id="slice-tab">
+               <table id="slice-tab" class="table">
                    <tr>
                        <th>+/-</th>
-                       <th>slice_hrn</th>
-                       <th>users</th>
-                       <th>url</th>
+                       <th>Slice hrn</th>
+                       <th>Users</th>
+                       <th>Url</th>
                        <!-- <th>nodes</th> -->
-                       <th>expiration</th>
+                       <th>Creation</th>
                    </tr>
-               </table>
-               <br>
-                       {%if 'is_pi'  in pi %}
-               <div>
-                   <button id="renewslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
-                   <button id="deleteslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
-               </div>
-                       {%endif%} 
+               </table>                        
            </div>
+       {% if pi %}
+        <div>
+               {% if  pi %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+                       {% else %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                       {% endif %}
+            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+        </div>
+               {% endif %} 
+          </div>
+       </div>
+       <div class="tab-pane row" id="requests">
        </div>
 </div>
 <script>
 $(document).ready(function() {
     {% if person %}
     {% if user_details.parent_authority %}
-        
-        $.post("/rest/authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
-            var authority_data = [];
-            var onelab_data = [];
-                       /* 'city','enabled','legal','longitude','onelab_membership','address','parent_authority','slice','user','country',
-            'tech','abbreviated_name','url','postcode','description','scientific','authority_hrn','latitude','name'    */
-            $.each( data, function( key, val ) {
-                authority_row = "<img src='{{ STATIC_URL }}img/institutions/{{user_details.parent_authority}}.gif' alt='' /><br>";
-                authority_row += "<br>";
-                authority_row += "<b>authority:</b> "+val.authority_hrn+"<br>";
-                authority_data.push(authority_row);
-            });
-            $("div#authority-data").html(authority_data.join( "" ));
-            $("div#onelab-data").html(onelab_data.join( "" ));
-            $("div#authority-tab-loaded").css("display","block");
-            $("div#authority-tab-loading").css("display","none");
-         });
 
-        $.post("/rest/slice/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+        $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
             var list_slices = [];
             var table_slices = [];
             /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
@@ -108,16 +108,17 @@ $(document).ready(function() {
                 }else{
                     nodes_length=val.nodes.length;
                 }
+                //console.log(val);
                 if(val.users=="undefined" || val.users==null){
                     users_length=0;
                 }else{
                     users_length=val.users.length;
                 }
 
-                if(val.slice_url=="undefined" || val.slice_url==null){
+                if(val.url=="undefined" || val.url==null){
                     slice_url="";
                 }else{
-                    slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_url+"</a>";
+                    slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
                 }
                 
                 slice_row = "<tr id='"+val.slice_hrn+"'>";
@@ -126,7 +127,7 @@ $(document).ready(function() {
                 slice_row += "<td>"+users_length+"</td>";
                 slice_row += "<td>"+slice_url+"</td>";
                 //slice_row += "<td>"+nodes_length+"</td>";
-                slice_row += "<td>"+val.slice_expires+"</td>";
+                slice_row += "<td>"+val.slice_date_created+"</td>";
                 slice_row += "</tr>";
                 table_slices.push(slice_row);
                 
@@ -137,34 +138,78 @@ $(document).ready(function() {
             $("div#slice-tab-loaded").css("display","block");
             $("div#slice-tab-loading").css("display","none");
         });
+               
+        {% if project %}
+        // XXX LOIC CACHE PB IF PREFIXED !
+               $.post("/rest/authority/",{'fields':['pi_users'],'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
+           
+            var table_users = [];
+            $.each( data[0].pi_users, function( key, val ) {
+                console.log(val);
+                user_row = "<tr id='"+val+"'>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val+"'></td>";
+                user_row += "<td></td>";
+                user_row += "<td>"+val+"</td>";
+                user_row += "</tr>";
+                table_users.push(user_row);
+            });
+            $("table#user-tab tr:last").after(table_users.join( "" ));
+            $("div#user-tab-loaded").css("display","block");
+            $("div#user-tab-loading").css("display","none");
 
-               $.post("/rest/user/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-             var list_users = [];
-             var table_users = [];
-                        /* Available fields
-                        user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
-                        user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
-                        */
-             $.each( data, function( key, val ) {
-                 list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
-                 user_row = "<tr id='"+val.user_hrn+"'>";
-                 user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
-                 user_row += "<td>"+val.user_email+"</td>";
-                 user_row += "<td>"+val.user_hrn+"</td>";
-                 user_row += "<td>"+val.user_first_name+"</td>";
-                 user_row += "<td>"+val.user_last_name+"</td>";
-                                user_row += "<td>"+val.user_enabled+"</td>";
-                 user_row += "</tr>";
-                 table_users.push(user_row);
-             });
-             $("table#user-tab tr:last").after(table_users.join( "" ));
-             $("div#user-tab-loaded").css("display","block");
-             $("div#user-tab-loading").css("display","none");
-          });
+        });
+        {% else %}
+        $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+            var list_users = [];
+            var table_users = [];
+                   /* Available fields
+                   user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
+                   user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
+                   */
+            $.each( data, function( key, val ) {
+                list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
+                user_row = "<tr id='"+val.user_hrn+"'>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
+                user_row += "<td>"+val.user_email+"</td>";
+                user_row += "<td>"+val.user_hrn+"</td>";
+                /*
+                user_row += "<td>"+val.user_first_name+"</td>";
+                user_row += "<td>"+val.user_last_name+"</td>";
+                           user_row += "<td>"+val.user_enabled+"</td>";
+                */
+                user_row += "</tr>";
+                table_users.push(user_row);
+            });
+            $("table#user-tab tr:last").after(table_users.join( "" ));
+            $("div#user-tab-loaded").css("display","block");
+            $("div#user-tab-loading").css("display","none");
+        });
+
+        {% endif %}
+    {% endif %}
+    {% endif %}
 
-   {% endif %}
-   {% endif %}
+}); // End document.ready
 
-}); // end document.ready
+$(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+               e.preventDefault();
+               $(this).tab('show');
+       var id = $(this).attr('href').substr(1);
+       if ((id == 'requests')){
+               $("#" + id).load('/management/' + id);
+        }
+        /*
+       if ((id == 'requests') || (id == 'about'))
+               $("#" + id).load('/management/' + id);
+        */
+       });
+       var hash = window.location.hash;
+       if (hash) {
+               $('.nav-tabs a[href='+hash+']').click();
+       } else {
+               $('.nav-tabs a[href=#about]').click();
+       }
+});
 </script>
 {% endblock %}
index dad0e6e..db4ace2 100644 (file)
                 <b>{{request.first_name}} {{request.last_name}}</b> &lt;<a href="mailto:{{request.email}}">{{request.email}}</a>&gt;
             {% elif request.type == 'slice' %}
             <b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+            {% elif request.type == 'project' %}
+            <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
+            {% elif request.type == 'join' %}
+            <b>{{request.user_hrn}}</b> --  to join {{ request.authority_hrn }}
             {% else %}
             <b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{request.address_country}}
             {% endif %}
                {% else %}
                    {% if request.type == 'slice' %}
                Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+                  {% elif request.type == 'project' %}
+            <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
+                  {% elif request.type == 'join' %}
+            <b>{{request.user_hrn}}</b> --  to join {{ request.authority_hrn }}
                    {% else %} {# authority #}
                Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
                    {% endif %}
                        {% else %}
                            {% if request.type == 'slice' %}
                        Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+                           {% elif request.type == 'project' %}
+                    <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
                            {% else %} {# authority #}
                        Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
                            {% endif %}
index 7f2e98e..3b47997 100644 (file)
                                                        </button>       
                                        </td>
                                </tr>
+                                       {% if not  pi %}
+                                       <tr class="odd">
+                                       <td class="key">Upgrade to PI</td>
+                                       <td>
+                                               <input type="submit" name="makepi" class="btn btn-primary btn-xs" value="Upgrade to PI" id="makepi" 
+                                               onclick="return confirm('Are you sure? If you do so, the user will be updated to a PI');" 
+                                               title="It will make the user PI of his instution"/>
+                                       </td>
+                                       </tr>
+                                       {% else %}
+                                       <tr class="odd">
+                                       <td class="key">Downgrade to user</td>
+                                       <td>
+                                               <input type="submit" name="removepi" class="btn btn-danger btn-xs" value="Downgrade to user" id="makepi" 
+                                               onclick="return confirm('Are you sure? If you do so, the PI will be downgraded to a user');" 
+                                               title="It will downgrade the PI to a user of his instution"/>
+                                       </td>
+                                       </tr>
+                                       {% endif %}
+
                                </table>
                </div>
        </div>
index 13da125..985974f 100644 (file)
@@ -1,16 +1,18 @@
 {% extends "layout.html" %}
+{% load portal_filters %}
 {% block content %}
-
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
 <div class="row">
        <div class="col-md-12">
                 <div class="breadcrumbs">
                         Account &nbsp;>&nbsp; <a href="/account">{{ person.email }}</a>
                 </div>
        </div>
-        {%if 'no_creds'  in user_cred %}
+        {%if 'no_creds' in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
     {%endif%}
-        {%if 'creds_expired'  in user_cred %}
+        {%if 'creds_expired' in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
 
     {% endfor %}
 </ul>
 {% endif %}
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value"  name="button_value" value="" />
+
 <div class="row">
        <div class="col-md-12">
                <ul class="nav nav-tabs nav-section">
@@ -36,7 +42,6 @@
                
                <div class="col-md-12">
 
-                       <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
                                {% csrf_token %}
                                        <table class="profile">          
                                        <tr>
                                                                                   onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
                                                                </span>
                                                                <div style='display:none;'> <input type='hidden'  name='dload'  /> </div> 
-                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                                <button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
                                                 {%if 'N/A' not in user_private_key%}
                                                <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='dl_pkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download     
                                                                </button>
                                                        <input class="btn btn-danger btn-xs" id="delete" name="delete" type="submit"  value="Delete" title="Delete your private key"
-                                                                               onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
+                                                                               onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
                                                </td>
                                                  {%else%}
                                                        <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                        <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey" value="dl_pkey">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                        </button>
                                                        <input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
                                        <tr class="even" id="sfi_config_row">
                                                <td class="key">sfi_config </td>
                                                <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
-                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_sfi_config">
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='dl_sfi_config';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                </td>
                         </tr>
+                                               <tr class="odd">
+                                                       {%if 'N/A' not in user_private_key%}
+                                                       <td class="key">Identity</td> 
+                                               <td>
+                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                               </button>
+                                                       </td>
+                                                       {%else%}
+                                                       <td class="key">Identity</td> 
+                                                       <td>
+                                                       <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                       </button>
+                                                       </td>
+                                                       {%endif%} 
+                                               </tr>
 
                                                <tr class="even">
                                                <td colspan="2">
                </table>
        
                </div>
-       
 
        {%if 'Enabled'  in user_status %}
                <div class="col-md-12">
                <h3>Credentials <small>Delegated to Principal Account</small></h3>
-                       <table class="table">
-                                       <caption><b>Delegated User Credential</b></caption> 
-                           <tr class="odd"> 
-                               <th>Expiration Date</th>
-                                               <th>Download</th>
-                           </tr>
-                                       {% for row in my_users %}         
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
-                                                               <span class="glyphicon glyphicon-download"></span> Credential
-                                                       </button>
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate">
-                                                               <span class="glyphicon glyphicon-download"></span> Certificate
-                                                       </button>
-                             <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
-                                 <span class="glyphicon glyphicon-download"></span> PKCS p12
-                             </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                                </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Slice Credentials</b></caption>  
-                               <tr class="odd"> 
-                                               <th>Slice Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                               </tr>
-                                       {% for row in my_slices %}     
-                               <tr class="border_bottom">
-                                       <td class="odd"> {{ row.slice_name }} </td>
-                                               <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd"> 
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button> 
-                                               </td>
-                               </tr>
-                               {%endfor%}
-                               </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Authority Credentials</b></caption>
-                                       <tr class="odd"> 
-                                       <th>Authority Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                                       </tr>
-                                       {% for row in my_auths %}
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.auth_name }} </td>
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                               </table>
-                               <p></p>
-                                {%if '' not in my_users%}      
-                               <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%else%}
-                               <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%endif%}
+                   <table class="table">
+                               <caption><b>Delegated User Credential</b></caption> 
+                       <tr class="odd"> 
+                           <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_users %}         
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+                                                       <span class="glyphicon glyphicon-download"></span> Credential
+                                               </button>
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+                                                       <span class="glyphicon glyphicon-download"></span> Certificate
+                                               </button>
+                         <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+                             <span class="glyphicon glyphicon-download"></span> PKCS p12
+                         </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                        </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Slice Credentials</b></caption>  
+                       <tr class="odd"> 
+                                       <th>Slice Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_slices %}     
+                       <tr class="border_bottom">
+                               <td class="odd"> {{ row.slice_name }} </td>
+                                       <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd"> 
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button> 
+                                       </td>
+                       </tr>
+                       {%endfor%}
+                       </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Authority Credentials</b></caption>
+                               <tr class="odd"> 
+                               <th>Authority Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                               </tr>
+                               {% for row in my_auths %}
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.auth_name }} </td>
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                       </table>
+                       <p></p>
+                        {%if '' not in my_users%}      
+                       <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+                       {%else%}
+                       <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+                       {%endif%}
                </div>
        </div>
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
-                    </div>
-                                       <div class="modal-body" style="text-align:justify;">
-                                       <p>You are getting this message for any of the following reasons:</p>
-                                       <ul>
-                                               <li>If your account is still pending for validation</li>
-                                               <li>If you press the "Clear Credentials" button</li>
-                                               <li>If you "Generate a new key pair"</li>
-                                               <li>If a new slice is added to your account</li>
-                                       </ul>
-                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
-                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
-                                               then please logout and login back into to the portal.
-                                       </p>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>
-                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
-                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
-                                                       delegated to the portal, please follow these instructions:
-                                               </p>
-                                               <ul>
-                                                       <li>Your account must first be validated by the manager of your organization.</li>
-                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
-                                               </ul>
-                                       </p>
-                                       <h3>Contact support</h3>
-                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
-
-
-<!-- Modal- Trade-off Message  -->
-<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">
-                                                               Automatic vs. Manual delegation of credentials
-                                                       </h4>
-                    </div>
-                                       <div class="modal-body" style="text-align:justify;">
-                                       <h3>Automatic delegation of credentials</h3>
-                                               <p>Don't delete private key, ease-of-use option:</p>
-                                               <ul>
-                                                       <li>
-                                                               This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
-                                                       </li>
-                                                       <li>
-                                                               This option does not provide as high of a level of security; however, your private key will still only be used in the portal and 
-                                                               will be available to you and the OneLab admins only.
-                                                       </li>
-                                               </ul>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>Download & Delete private key, higher security option:</p>
-                                               <ul>
-                                                       <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials 
-                                                               on your behalf, and you will have to manually
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
-                                                       </li>
-                                               </ul>
-                                       <h3>Contact support</h3>
-                                       <p>For more information, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
-
 
 
        <div class="tab-pane row" id="access">
                 <td class="odd"> {{ row.account_type }} </td>
                                <td class="odd"> {{ row.account_reference }} </td>
                                <td class="odd">
-                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
                                                <span class="glyphicon glyphicon-minus"></span>
                                        </button>
                                </td>
             <tr class="border_bottom">
                 <td class="odd"> {{ platform.platform_no_access }} </td>
                 <td class="odd">
-                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
                                                <span class="glyphicon glyphicon-plus"></span>
                                        </button>
                                </td>
        </div>
 {%endif%} 
 </div>
-</form>
 </div>
 
+</form>
 <script>
     $(document).ready(function() {
+           {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+        localStorage.clear();
+        $.post("/cache/clear/", function( data ) {
+        });
+        {% endif %}
        $('.nav-tabs a').click(function (e) {
                        e.preventDefault();
                        $(this).tab('show');
                        id = $(this).attr('href').substr(1);
-               
                });
                
         $('button#createslice').click(function() {
index 4e8b22c..bacc2b2 100644 (file)
@@ -6,57 +6,17 @@
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
-                    </div>
-                    <div class="modal-body" style="text-align:justify;">
-                                       <p>You are getting this message for any of the following reasons:</p>
-                                       <ul>
-                                               <li>If your account is still pending for validation</li>
-                                               <li>If you press the "Clear Credentials" button</li>
-                                               <li>If you "Generate a new key pair"</li>
-                                               <li>If a new slice is added to your account</li>
-                                       </ul>
-                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
-                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
-                                               then please logout and login back into to the portal.
-                                       </p>
-                                       <h3>Manual delegation of credentials</h3>
-                                               <p>
-                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
-                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
-                                                       delegated to the portal, please follow these instructions:
-                                               </p>
-                                               <ul>
-                                                       <li>Your account must first be validated by the manager of your organization.</li>
-                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
-                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
-                                               </ul>
-                                       </p>
-                                       <h3>Contact support</h3>
-                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
+{% widget "_widget-no_credentials.html" %}
 <div class="container dashboard">
-          {%if 'no_creds'  in user_cred %}
-      <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
-  {%endif%}
-        {%if 'creds_expired'  in user_cred %}
-    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+       {%if 'no_creds'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+    {%endif%}
+       {%if 'creds_expired'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
 
        <div class="row">
-               {%if 'is_pi'  in pi %}
+               {% if pi %}
                <div class="col-md-3">
                        <h3>
                                EXPERIMENT
diff --git a/portal/templates/onelab/onelab_institution.html b/portal/templates/onelab/onelab_institution.html
deleted file mode 100644 (file)
index 4dcaf1b..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-{% extends "layout_wide.html" %}
-
-{% block head %} 
-<script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
-{% endblock head %}
-
-{% block content %}
-<div class="container">
-       <div class="row">
-               <div class="col-md-12">
-                        <div class="breadcrumbs">
-                                Management &nbsp;>&nbsp; Institution: <span id="authority_name"></span>
-                        </div>
-               </div>
-       </div>
-</div>
-<div class="container">
-       <div class="row">
-               <div class="col-md-12">
-                       <ul class="nav nav-tabs nav-section">
-                               <li class="active"><a href="#about">About</a></li>
-                               <li><a href="#users">Users</a></li>
-                               <li><a href="#slices">Slices</a></li>
-                               <li><a href="#requests">Requests</a></li>
-                       </ul>
-           </div>
-       </div>
-</div>
-<div class="container tab-content">
-       <div class="tab-pane active row" id="about">
-       </div>
-       
-       <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
-               <div class="col-md-12 el">
-                       <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
-                               <div id="user-tab-loaded" style="display:none;">
-                               <table id="user-tab" class="table">
-                                       <tr>
-                                       <th>+/-</th>
-                                       <th>Email</th>
-                                       <th>User hrn</th>
-                            <!--
-                                       <th>First name</th>
-                                       <th>Last name</th>
-                                       <th>Enabled</th>
-                            -->
-                                       </tr>
-                               </table>
-                               
-                       </div>
-                       {%if 'is_pi'  in pi %}  
-                       <div>
-                               <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
-                       </div>
-                       {% endif %}
-               </div>
-       </div>
-
-       <div class="tab-pane row" id="slices">
-               <div class="col-md-12 el">
-           <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
-           <div id="slice-tab-loaded" style="display:none;">
-               <table id="slice-tab" class="table">
-                   <tr>
-                       <th>+/-</th>
-                       <th>Slice hrn</th>
-                       <th>Users</th>
-                       <th>Url</th>
-                       <!-- <th>nodes</th> -->
-                       <th>Creation</th>
-                   </tr>
-               </table>                        
-           </div>
-       {% if 'is_pi'  in pi %}
-        <div>
-               {% if 'is_pi'  in pi %}
-                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
-                       {% else %}
-                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
-                       {% endif %}
-            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
-            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
-        </div>
-               {% endif %} 
-          </div>
-       </div>
-       <div class="tab-pane row" id="requests">
-       </div>
-</div>
-<script>
-$(document).ready(function() {
-    {% if person %}
-    {% if user_details.parent_authority %}
-
-        $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-            var list_slices = [];
-            var table_slices = [];
-            /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
-            $.each( data, function( key, val ) {
-                list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
-                if(val.nodes=="undefined" || val.nodes==null){
-                    nodes_length=0;
-                }else{
-                    nodes_length=val.nodes.length;
-                }
-                if(val.users=="undefined" || val.users==null){
-                    users_length=0;
-                }else{
-                    users_length=val.users.length;
-                }
-
-                if(val.url=="undefined" || val.url==null){
-                    slice_url="";
-                }else{
-                    slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
-                }
-                
-                slice_row = "<tr id='"+val.slice_hrn+"'>";
-                slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
-                slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
-                slice_row += "<td>"+users_length+"</td>";
-                slice_row += "<td>"+slice_url+"</td>";
-                //slice_row += "<td>"+nodes_length+"</td>";
-                slice_row += "<td>"+val.slice_date_created+"</td>";
-                slice_row += "</tr>";
-                table_slices.push(slice_row);
-                
-            });
-           
-            /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
-            $("table#slice-tab tr:last").after(table_slices.join( "" ));
-            $("div#slice-tab-loaded").css("display","block");
-            $("div#slice-tab-loading").css("display","none");
-        });
-               
-               
-        $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-            var list_users = [];
-            var table_users = [];
-                   /* Available fields
-                   user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
-                   user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
-                   */
-            $.each( data, function( key, val ) {
-                list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
-                user_row = "<tr id='"+val.user_hrn+"'>";
-                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
-                user_row += "<td>"+val.user_email+"</td>";
-                user_row += "<td>"+val.user_hrn+"</td>";
-                /*
-                user_row += "<td>"+val.user_first_name+"</td>";
-                user_row += "<td>"+val.user_last_name+"</td>";
-                           user_row += "<td>"+val.user_enabled+"</td>";
-                */
-                user_row += "</tr>";
-                table_users.push(user_row);
-            });
-            $("table#user-tab tr:last").after(table_users.join( "" ));
-            $("div#user-tab-loaded").css("display","block");
-            $("div#user-tab-loading").css("display","none");
-        });
-
-    {% endif %}
-    {% endif %}
-
-}); // End document.ready
-
-$(document).ready(function() {
-       $('.nav-tabs a').click(function (e) {
-               e.preventDefault();
-               $(this).tab('show');
-       var id = $(this).attr('href').substr(1);
-       if ((id == 'requests') || (id == 'about'))
-               $("#" + id).load('/management/' + id);
-       });
-       var hash = window.location.hash;
-       if (hash) {
-               $('.nav-tabs a[href='+hash+']').click();
-       } else {
-               $('.nav-tabs a[href=#about]').click();
-       }
-});
-</script>
-{% endblock %}
index 703b4af..b764570 100644 (file)
@@ -7,11 +7,6 @@
        <h1><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Registration" />User sign-up</h1>
        </div>
 </div>
-<div class="row">
-       <div class="col-md-12">
-               <p><strong>Questions? <a href="/contact" >Contact us.</a></strong></p>
-  </div>
-</div>
 {% if errors %}
 <div class="row">
        <div class="col-md-12">
@@ -25,8 +20,8 @@
 {% endif %}
                                <form action="/register" class="cmxform form-horizontal" method="post" enctype="multipart/form-data">
 <div class="row">
-       <div class="col-md-12">
-                       <div class="form-group">
+       <div class="col-md-6">
+           <div>
                                {% csrf_token %}
                                <label for="authority_hrn" class="control-label">Organization</label>
                                <p></p>
                 </div>
                                <p></p>
                                <p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
-                       </div>
+               </div>
        </div>
+       <div class="col-md-6">
+        <h4>
+            Questions? <a href="/contact" >Contact us.</a>
+       </h4>
+  </div>
 </div>
 
 <div class="row">
        <div class="col-md-6">
-       
-           <div class="form-group">
+          <p>
                        <label for="firstname" class="control-label">Personal information</label>
-                       <p></p>
+          </p>
+          <p>
                        <input type="text" name="firstname" class="form-control" style="width:350px" minlength="2" value="{{ first_name }}" placeholder="First name" required />
-           </div>
-           <div class="form-group">
+           </p>
+           <p>
                        <input type="text" name="lastname" size="25" class="form-control" style="width:350px" minlength="2" value="{{ last_name }}" placeholder="Last name" required />
-           </div>
-               <div class="form-group">
-               <input type="email" name="email" size="25"  class="form-control" style="width:350px" value="{{ email }}" 
-                       title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues."
-                       placeholder="Email" required />
-               </div>
+           </p>
+               <p>
+               <input type="email" name="email" size="25"  class="form-control" style="width:350px" value="{{ email }}" title="Your e-mail address will be your identifier for logging in. We contact you to verify your account and then, occasionally, for important issues." placeholder="Email" required />
+               </p>
        </div>  
 
        <div class="col-md-6">
-           <div class="form-group">
+           <p>
              <label for="password" class="control-label">Authentication</label>
-                 <p></p>       
+               </p>    
+               <p>
              <input type="password"  id="password" name="password"   class="form-control" style="width:250px" minlength="4" value="{{ password }}" 
                        title="Your password allows you to log in to this portal."
                        placeholder="Password" required />
-           </div>
-           <div class="form-group">
+           </p>
+           <p>
                        <input type="password"  id="confirmpassword" name="confirmpassword" style="width:250px"  minlength="4" class="form-control" value="" 
                                placeholder="Confirm password" required />
-           </div>
-           <div class="form-group">
+           </p>
+           <p>
                        <select name="question" class="form-control" style="width:350px" id="key-policy" 
                                title="Your public/private key pair allows you to access the testbeds." required >        
                                <option value="generate">Generate my keys for me (recommended)</option>
                                <option value="upload">Upload my public key (advanced users only)</option>
                        </select>
-           </div>
-           <div class="form-group" style="display:none;" id="upload_key">
+           </p>
+           <div style="display:none;" id="upload_key">
                <label for="file" class="control-label">Upload public key</label>
                <input type="file" name="user_public_key" class="form-control" style="width:200px" id="user_public_key" />
                <br />
 </div>
 <div class="row">
        <div class="col-md-12">
-               <div class="form-group">
-                       <p></p>
+               <p>
                        <input type="checkbox" name="agreement" value="agreement" required />&nbsp;&nbsp; I agree to the 
                        <a href="#" data-toggle="modal" data-target="#myModal">terms and conditions.</a> 
-               </div>
+               </p>
        </div>
 </div>
 <div class="row">
        <div class="col-md-10">
-               <div class="form-group" id="register">
+               <div id="register">
+                   <p>
                        <span class="glyphicon glyphicon-info-sign"></span> &nbsp;
                If you are a <b>PlanetLab Europe</b> user, please fill in this form using the same email address that you
                 currently use for your PlanetLab Europe account.
                Your existing credentials will be used to validate your OneLab account.
                Please be sure to specify a different password for your new OneLab account.
+               </p>
            </div>
        </div>
 </div>
 <div class="row">
        <div class="col-md-12">
-               <div class="form-group" id="register">
-                       <p></p> 
+               <div id="register">
+                       <p>
                <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+               </p>
                </form>
            </div>
        </div>
index 211f35d..3394e59 100644 (file)
                                title="Please enter a name for your slice"required="required">
                          </div>
                          <div class="form-group">
-                               {%if 'is_pi'  in pi %}
+                               {% if pi %}
                                <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization" 
                                title="An authority responsible for vetting your slice" required="required">
-                               {%else%}
+                               {% else %}
                            <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
                                title="An authority responsible for vetting your slice" required="required" readonly>
-                               {%endif%}
+                               {% endif %}
                          </div>
                          <div class="form-group">
                            <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
                                <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px" 
                                title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
                          </div>
-                         {%if 'is_pi'  in pi %}        
+                         {% if pi %}   
                          <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
-                         {%else%}
+                         {% else %}
                          <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
-                         {%endif%}     
+                         {% endif %}   
                        </form>
        
                </div>
index 10fbbe1..668c3d3 100644 (file)
@@ -44,9 +44,6 @@
 </div>
 </div>
 
-<div class="row">
-{% widget '_widget-message.html' %}
-</div>
 <script>
        $(document).ready(function() {
                $('li.slices').mouseenter(function() {
diff --git a/portal/templates/project-request-ack-view.html b/portal/templates/project-request-ack-view.html
new file mode 100644 (file)
index 0000000..9b70c5f
--- /dev/null
@@ -0,0 +1,9 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+<h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Slice" />Request received</h1>
+
+We will process your request and get back to you as soon as possible.
+{% endblock %}
+
diff --git a/portal/templates/project-request-done-view.html b/portal/templates/project-request-done-view.html
new file mode 100644 (file)
index 0000000..d962afd
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+  <h1>Success</h1>
+
+Your request to join/create project was successful.
+<script>
+$(document).ready(function() {
+    localStorage.clear();
+});
+</script>
+{% endblock %}
+
index 4d09858..6c04487 100644 (file)
@@ -57,7 +57,6 @@
                 </select>
                 </div>
                                <p></p>
-                               <p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
                        </div>
        </div>
 </div>
index 78502cf..a4485af 100644 (file)
@@ -1,13 +1,10 @@
 {% extends "layout_wide.html" %}
 
-{% block head %} 
-<!-- <script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script> -->
-{% endblock head %}
-
 {% block content %}
 <div class="container">
        <div class="row">
                <div class="col-md-12">
+                   <br />
                        <ul class="nav nav-tabs nav-section-mod">
                                <li class="active"><a href="#appservices"> Application Services </a></li>
                                <li><a href="#fedservices"> Federation Services </a></li>
index 0d0a03b..9ab6807 100644 (file)
@@ -5,6 +5,10 @@
   <h1>Slice created</h1>
 
 As a manager of your institution, your slice has directly been created directly.
-
+<script>
+$(document).ready(function() {
+    localStorage.clear();
+});
+</script>
 {% endblock %}
 
diff --git a/portal/templates/slice-request-view.html b/portal/templates/slice-request-view.html
deleted file mode 100644 (file)
index 830c7ee..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "layout.html" %}
-{% load i18n %}
-
-{% block head %}
-{{ wizard.form.media }}
-<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/registration.css" />
-{% endblock %}
-
-{% block content %}
-
-
-
-<div class="onelab-title well-lg">
-  <h2>Request a Slice</h2>
-</div>
-
-<div class='well'>
-  <form id="commentForm" class="form-horizontal" action="" method="post" role="form">{% csrf_token %}
-  <fieldset>
-    {% for field in form %}
-    <div class="form-group">
-      <label for="{{ field.html_name }}" class="col-xs-2 control-label">{{ field.label }}</label>
-      <div class="col-xs-4"> {{ field.errors }} {{ field }} </div>
-      <div class="col-xs-6"> <p class="form-hint">{{ field.help_text }}</p> </div>
-    </div>
-    {% endfor %}
-    <button class="submit btn btn-default" type="submit"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
-  </fieldset>
-  </form>
-</div>
-
-{% endblock %}
index ff1fc3e..3fefedf 100644 (file)
@@ -54,8 +54,6 @@ $(document).ready(function() {
                        <ul class="nav nav-tabs">
                          <li class="active"><a href="#resourcelist" role="tab" data-toggle="tab">Table</a></li>
                          <li> <a href="#resourcemap" role="tab" data-toggle="tab">Map</a></li>
-              <li> <a href="#openflowcontroller" role="tab" data-toggle="tab">OpenFlow Controller</a></li>
-              <li> <a href="#resourceflowspace" role="tab" data-toggle="tab">Flowspace</a></li>
                          <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
                        </ul>
                        </div>
@@ -92,24 +90,6 @@ $(document).ready(function() {
                                <div class="tab-pane" id="resourcemap">
                        {{map_resources}}
                                </div>
-                <div class="tab-pane" id="openflowcontroller">
-                    <p>{{vms_list}}</p>
-                    <p>{{vm_form}}</p>
-
-                    <p>{{below_table}}</p>
-                </div>
-
-                <div class="tab-pane" id="resourceflowspace">
-                    <p>{{welcome}}</p>
-                    <p>{{flowspaces}}</p>
-                    <p>{{flowspaces_form}}</p>
-                    <p>{{oflowspaces_form}}</p>
-                    <p>{{topology}}</p>
-                    <p>{{resources}}</p>
-
-                    <p>{{below_table}}</p>
-                </div>
-
                                <div class="tab-pane" id="resourcescheduler">
                        {{scheduler}}
                                </div>
index ce97efa..e10c88f 100644 (file)
@@ -16,7 +16,6 @@
        {%endfor%}
        </p>
        <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
-       <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
        <p>
                Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes, 
                after witch you will be able to access the resource.
@@ -74,7 +73,7 @@
                the following command:
        </p>
        <p class="command">
-               ssh {{iot_login}}@fit3-dev.inrialpes.fr
+               ssh {{iot_login}}@grenoble.iot-lab.info
        </p>
        {% endif %}
        {% if nitos_resources or nitos_paris_resources %}
        {% if nitos_resources %}        
        <h4>NITLab</h4>
        <p class="command">
-       $ ssh {{slicename}}@nitlab.inf.uth.gr
-       </p>
+           $ ssh {{slicename}}@nitlab.inf.uth.gr #nodes 001-040<br>
+        $ ssh {{slicename}}@nitlab2.inf.uth.gr #nodes 041-049<br>
+        $ ssh {{slicename}}@nitlab3.inf.uth.gr #nodes > 049
+    </p>
        
-       <p>For each of the reserved nodes, follo the steps given below:</p>
+       <p>Loading an OMF-compatible image on your resource:</p>
        <p class="command">
        {%for resource in nitos_resources %}
                <b>Resource</b><br>
-       $ omf load -i baseline_grid.ndz -t {{resource}}  #loading OMF image on the node<br>
-               $ omf tell -a on -t {{resource}}  #turn on the node <br>
-               $ ssh root@{{resource}}  #ssh to the node<br><br>
+        $ omf6 stat -t {{resource}} #check the status of the node<br>
+        $ omf6 tell -a on -t {{resource}}  #turn on/off the node <br>
+       $ omf6 load -i baseline.ndz -t {{resource}}  #for orbit-like node (002-009) use "baseline_orbit.ndz"<br>
+               $ ssh root@{{resource}}  #ssh to the node<br>
        {%endfor%}
        </p>
+    <p><b>NOTE:</b> Nodes 002-009 are orbit-like nodes. For these nodes use "baseline_orbit.ndz". All these images come with OMF5.4 resource controller. To do OMF6 experiments use "baseline_omf6_1_1.ndz" and  "baseline_orbit_omf6_1_1.ndz" for grid nodes and orbit nodes respectively. </p>
        {% endif %}
 
        {% if nitos_paris_resources %}
        {%endif%}
 
        <p>
-               On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
+               On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml (OMF5.4 only) according to your slice settings and then
                restart the OMF Resource Controller and finally execute the experiment:
        </p>
        <p class="command">
                $ omf exec --slice {{slicename}} your_exp.rb
        </p>
        <p>
-       The complete tutorial is available at the following address:
+       The complete tutorial on NITOS nodes:
        <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
        </p>
-       <p>To learn more about OMF6, please click <a href="http://omf.mytestbed.net/projects/omf6/wiki/Wiki" target="_blank">here.</a></p>
+    <p>OMF based experiments' tutorials are available <a href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/omf-tutorials-scenarios" target="_blank">here.</a></p> 
+       <p>To learn more about OMF, please click <a href="http://omf.mytestbed.net/projects/omf/wiki/OMF_Main_Page" target="_blank">here.</a></p>
 
        {% endif %}
        
index 199444a..985974f 100644 (file)
@@ -1,15 +1,20 @@
 {% extends "layout.html" %}
+{% load portal_filters %}
 {% block content %}
-
+{% widget "_widget-no_credentials.html" %}
+{% widget "_widget-tradeoff.html" %}
 <div class="row">
        <div class="col-md-12">
                 <div class="breadcrumbs">
                         Account &nbsp;>&nbsp; <a href="/account">{{ person.email }}</a>
                 </div>
        </div>
-        {%if 'no_creds'  in user_cred %}
+        {%if 'no_creds' in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
-{%endif%}
+    {%endif%}
+        {%if 'creds_expired' in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
 
 </div>
 {% if messages %}
     {% endfor %}
 </ul>
 {% endif %}
+
+<form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
+<input type="hidden" id="button_value"  name="button_value" value="" />
+
 <div class="row">
        <div class="col-md-12">
                <ul class="nav nav-tabs nav-section">
@@ -33,7 +42,6 @@
                
                <div class="col-md-12">
 
-                       <form id="editForm" method="post" action="account_process" enctype="multipart/form-data">
                                {% csrf_token %}
                                        <table class="profile">          
                                        <tr>
                                                                                   onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
                                                                </span>
                                                                <div style='display:none;'> <input type='hidden'  name='dload'  /> </div> 
-                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_file">
+                                                               <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                                </button>
                                                                <button class="btn btn-default btn-xs" id="upload_file" type="button" title="Upload a public key">
                                                 {%if 'N/A' not in user_private_key%}
                                                <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey" value="dl_pkey" onclick="javascript:document.getElementById('button_value').value='dl_pkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download     
                                                                </button>
                                                        <input class="btn btn-danger btn-xs" id="delete" name="delete" type="submit"  value="Delete" title="Delete your private key"
-                                                                               onclick="return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
+                                                                               onclick="javascript:document.getElementById('button_value').value='delete'; return confirm('Are you sure? If you do so, you have to delegate your credentials manually.');"/> 
                                                </td>
                                                  {%else%}
                                                        <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                        <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey" value="dl_pkey">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                        </button>
                                                        <input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
                                                        </td>
                                                 {%endif%}              
                                                </tr>
+                                       <tr class="even" id="sfi_config_row">
+                                               <td class="key">sfi_config </td>
+                                               <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config" value="dl_sfi_config" onclick="javascript:document.getElementById('button_value').value='dl_sfi_config';">
+                                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                                               </button>
+                                               </td>
+                        </tr>
+                                               <tr class="odd">
+                                                       {%if 'N/A' not in user_private_key%}
+                                                       <td class="key">Identity</td> 
+                                               <td>
+                                                               <button type="submit" name="dl_identity" class="btn btn-default btn-xs" title="You will require it to use jfed" id="dl_identity" onclick="javascript:document.getElementById('button_value').value='dl_identity';">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                               </button>
+                                                       </td>
+                                                       {%else%}
+                                                       <td class="key">Identity</td> 
+                                                       <td>
+                                                       <button type="submit" name="dl_identity" class="btn btn-default btn-xs disabled" title="You will require it to use jfed" id="dl_identity">
+                                                               <span class="glyphicon glyphicon-download"></span> Download 
+                                                       </button>
+                                                       </td>
+                                                       {%endif%} 
+                                               </tr>
+
                                                <tr class="even">
                                                <td colspan="2">
-                                                       <p class="message" id="pkey_del_msg"><b> Tradeoff:</b> Ease-of-use vs Security.<br>
-                                                                       <b>Ease-of-use:</b> Automatic account delegation. Don't delete private key.<br>
-                                                                       <b>Security:</b> Manual account delegation. Download & Delete private key.
+                                                               <p class="command">
+                                                                       <a href="#" style="color:green" data-toggle="modal" data-target="#tradeoffmodal">Automatic vs. Manual delegation of credentials:</a>
+                                                                       Trade-off between ease-of-use & security</p>
                                                                </p>
                                                </td>
                                                </tr>
                </table>
        
                </div>
-       
 
        {%if 'Enabled'  in user_status %}
                <div class="col-md-12">
                <h3>Credentials <small>Delegated to Principal Account</small></h3>
-                       <table class="table">
-                                       <caption><b>Delegated User Credential</b></caption> 
-                           <tr class="odd"> 
-                               <th>Expiration Date</th>
-                                               <th>Download</th>
-                           </tr>
-                                       {% for row in my_users %}         
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential">
-                                                               <span class="glyphicon glyphicon-download"></span> Credential
-                                                       </button>
-                                                       <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate">
-                                                               <span class="glyphicon glyphicon-download"></span> Certificate
-                                                       </button>
-                             <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12">
-                                 <span class="glyphicon glyphicon-download"></span> PKCS p12
-                             </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                                </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Slice Credentials</b></caption>  
-                               <tr class="odd"> 
-                                               <th>Slice Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                               </tr>
-                                       {% for row in my_slices %}     
-                               <tr class="border_bottom">
-                                       <td class="odd"> {{ row.slice_name }} </td>
-                                               <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd"> 
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button> 
-                                               </td>
-                               </tr>
-                               {%endfor%}
-                               </table>
-                               <p></p>
-                               <table class="mytable table table-bordered table-hover">
-                                       <caption><b>Delegated Authority Credentials</b></caption>
-                                       <tr class="odd"> 
-                                       <th>Authority Name</th> 
-                                       <th>Expiration Date</th>
-                                               <th>Download</th>
-                                       </tr>
-                                       {% for row in my_auths %}
-                                       <tr class="border_bottom">
-                                       <td class="odd"> {{ row.auth_name }} </td>
-                                       <td class="odd"> {{ row.cred_exp }} </td>
-                                               <td class="odd">
-                                                       <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials">
-                                                               <span class="glyphicon glyphicon-download"></span> Download
-                                                       </button>
-                                               </td>
-                                       </tr>
-                                       {%endfor%}
-                               </table>
-                               <p></p>
-                                {%if '' not in my_users%}      
-                               <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%else%}
-                               <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
-                               {%endif%}
+                   <table class="table">
+                               <caption><b>Delegated User Credential</b></caption> 
+                       <tr class="odd"> 
+                           <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_users %}         
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cred" type="submit" title="Download User Credential" onclick="javascript:document.getElementById('button_value').value='dl_user_cred';">
+                                                       <span class="glyphicon glyphicon-download"></span> Credential
+                                               </button>
+                                               <button class="btn btn-default btn-xs" name= "dl_user_cert" type="submit" title="Download User Certificate" onclick="javascript:document.getElementById('button_value').value='dl_user_cert';">
+                                                       <span class="glyphicon glyphicon-download"></span> Certificate
+                                               </button>
+                         <button class="btn btn-default btn-xs" name= "dl_user_p12" type="submit" title="Download User PKCS12" onclick="javascript:document.getElementById('button_value').value='dl_user_p12';">
+                             <span class="glyphicon glyphicon-download"></span> PKCS p12
+                         </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                        </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Slice Credentials</b></caption>  
+                       <tr class="odd"> 
+                                       <th>Slice Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                       </tr>
+                               {% for row in my_slices %}     
+                       <tr class="border_bottom">
+                               <td class="odd"> {{ row.slice_name }} </td>
+                                       <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd"> 
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.slice_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button> 
+                                       </td>
+                       </tr>
+                       {%endfor%}
+                       </table>
+                       <p></p>
+                       <table class="mytable table table-bordered table-hover">
+                               <caption><b>Delegated Authority Credentials</b></caption>
+                               <tr class="odd"> 
+                               <th>Authority Name</th> 
+                               <th>Expiration Date</th>
+                                       <th>Download</th>
+                               </tr>
+                               {% for row in my_auths %}
+                               <tr class="border_bottom">
+                               <td class="odd"> {{ row.auth_name }} </td>
+                               <td class="odd"> {{ row.cred_exp }} </td>
+                                       <td class="odd">
+                                               <button class="btn btn-default btn-xs" name= "dl_{{row.auth_name}}" type="submit" title="Download Authority Credentials" onclick="javascript:document.getElementById('button_value').value='dl_{{row.auth_name}}';">
+                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                               </button>
+                                       </td>
+                               </tr>
+                               {%endfor%}
+                       </table>
+                       <p></p>
+                        {%if '' not in my_users%}      
+                       <p><button class="btn btn-danger btn-lg btn-block"   name= "clear_cred" type="submit" title="Clear All Credentials" onclick="javascript:document.getElementById('button_value').value='clear_cred';">Clear Credentials</button></p>
+                       {%else%}
+                       <p><button class="btn btn-danger btn-lg btn-block disabled"   name= "clear_cred" type="submit" title="Clear All Credentials">Clear Credentials</button></p>
+                       {%endif%}
                </div>
        </div>
-<!-- Modal- No credentials -->
-<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-                <div class="modal-content">
-                    <div class="modal-header">
-                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
-                    </div>
-                    <div class="modal-body">
-                                       <p>You may get this message for several reasons.</p>
-                                       <h3>Account Delegation: Automatic</h3>
-                                       <ul>
-                                               <li>If your account is not yet validated</li>
-                                               <li>If you press the "Clear Credentials" button</li>
-                                               <li>If you "Generate a new key pair"</li>
-                                               <li>If a new slice is added to your account</li>
-                                       </ul>
-                                       <p>In all the above mentioned cases, it is sufficient to refresh the page or go back to home page. The portal will regenrate your credentials.
-                                        In some cases it may take more time than usual. If nothing works, then please logout and login again to the portal.</p>
-                                       <h3>Account Delegation: Manual</h3>
-                                               <p>First of all your account needs to be validated by the manager of your organization.</p>
-                                               <p>As you have uploaded your own public key, the portal can no longer generate your credentials automatically.</p>
-                                               <p>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
-                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
-                                       </p>
-                                       <h5>Contact support</h5>
-                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
-                    </div>
-                    <div class="modal-footer">
-                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    </div>
-                </div>
-            </div>
-</div>
 
 
        <div class="tab-pane row" id="access">
                 <td class="odd"> {{ row.account_type }} </td>
                                <td class="odd"> {{ row.account_reference }} </td>
                                <td class="odd">
-                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
                                                <span class="glyphicon glyphicon-minus"></span>
                                        </button>
                                </td>
             <tr class="border_bottom">
                 <td class="odd"> {{ platform.platform_no_access }} </td>
                 <td class="odd">
-                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform">
+                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
                                                <span class="glyphicon glyphicon-plus"></span>
                                        </button>
                                </td>
        </div>
 {%endif%} 
 </div>
-</form>
 </div>
 
+</form>
 <script>
     $(document).ready(function() {
+           {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
+        localStorage.clear();
+        $.post("/cache/clear/", function( data ) {
+        });
+        {% endif %}
        $('.nav-tabs a').click(function (e) {
                        e.preventDefault();
                        $(this).tab('show');
                        id = $(this).attr('href').substr(1);
-               
                });
                
         $('button#createslice').click(function() {
diff --git a/portal/templates/smartfire/smartfire_activate_user.html b/portal/templates/smartfire/smartfire_activate_user.html
new file mode 100644 (file)
index 0000000..48e0142
--- /dev/null
@@ -0,0 +1,29 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>We have received a user signup request for your email address at {{current_site}}</p>
+<p>You have the following user details:</p>
+
+Organization: {{organization}}<br>
+First name: {{first_name}}<br>
+Last name: {{last_name}}<br>
+Email: {{email}}<br>
+
+<p></p>
+<p>
+You may now <a href="http://{{current_site}}">log</a> in to the portal using your email address and the password that you provided, but your access will be limited. To gain full access, two steps are required:
+</p>
+
+<ul style="list-style-type:decimal;">
+<li>
+You must confirm that you have indeed made this request by clicking on the following link: <br>
+       <a href={{validation_link}}>{{validation_link}}</a> 
+       <ul><li>If you did not make this request, we apologise. You may disregard this email or you may advise us the error by replying to this email.</li></ul>
+</li>
+<li>
+A manager from your organization must also validate your request. Upon confirmation of your signup request, we will send an email to the managers at your organization with a validation request.
+</li>
+</ul>
+<p>
+We look forward to welcoming you to SmartFIRE. You will find answers to frequently asked questions <a href="http://{{current_site}}/support/">here</a>. 
+Please don't hesitate to <a href="http://{{current_site}}/contact/">contact us</a> with any additional questions that you might have.
+</p>
diff --git a/portal/templates/smartfire/smartfire_activate_user.txt b/portal/templates/smartfire/smartfire_activate_user.txt
new file mode 100644 (file)
index 0000000..ac84bc3
--- /dev/null
@@ -0,0 +1,24 @@
+We have received a user signup request for your email address at {{current_site}}
+
+You have the following user details:
+
+Organization: {{organization}}
+First name: {{first_name}}
+Last name: {{last_name}}
+Email: {{email}}
+
+You may now log in to the portal using your email address and the password that you provided, but your access will be limited. To gain full access, two steps are required:
+
+       1. You must confirm that you have indeed made this request by clicking on the following link:
+
+               {{validation_link}}
+
+               If you did not make this request, we apologise. You may disregard this email or you may advise us the error by replying to this email.
+
+       2. A manager from your organization must also validate your request. Upon confirmation of your signup request, we will send an email to the managers at your organization with a validation request.
+
+We look forward to welcoming you to SmartFIRE portal. 
+Please don't hesitate to contact us at support@onelab.eu with any additional questions that you might have.
+
+
+
diff --git a/portal/templates/smartfire/smartfire_authority_request_denied.html b/portal/templates/smartfire/smartfire_authority_request_denied.html
new file mode 100644 (file)
index 0000000..e4da271
--- /dev/null
@@ -0,0 +1,20 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested an addition of the following authority in the SmartFIRE portal ({{portal_url}}):</p> 
+<p></p>
+<b>Name of organization:</b> {{site_name}}<br>
+<b>Short name:</b> {{short_name}}<br>
+<b>Url:</b> {{url}}<br>
+<b>City:</b> {{city}}<br>
+<b>Country:</b> {{country}}<br>
+<p></p>
+</p>After verifying your request, we regret to inform you that, we are unable to validate your request.</p>
+<p>For any queries, contact us by replying to this email.</p>
+<br>
+<p>We wish you all the best.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
+
diff --git a/portal/templates/smartfire/smartfire_authority_request_denied.txt b/portal/templates/smartfire/smartfire_authority_request_denied.txt
new file mode 100644 (file)
index 0000000..44d522b
--- /dev/null
@@ -0,0 +1,18 @@
+Dear SmartFIRE user,
+
+You have recently requested an addition of the following authority in the SmartFIRE portal ({{portal_url}}): 
+
+Name of organization: {{site_name}}
+Short name: {{short_name}}
+Url: {{url}}
+City: {{city}}
+Country: {{country}}
+
+
+After verifying your request, we regret to inform you that, we are unable to validate your request.
+For any queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The SmartFIRE team
diff --git a/portal/templates/smartfire/smartfire_authority_request_email.html b/portal/templates/smartfire/smartfire_authority_request_email.html
new file mode 100644 (file)
index 0000000..72af5a7
--- /dev/null
@@ -0,0 +1,22 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>NEW AUTHORITY REQUEST</h1>
+<br>
+<p>This email is only for SmartFIRE admins</p>
+<br>
+<h2>{{site_name}}</h2>             
+<b>Authority hrn    :</b> {{authority_hrn}}<br>         
+<b>Abreviated name  :</b> {{site_abbreviated_name}}<br>
+<b>URL              :</b> {{site_url}}<br>              
+<b>City             :</b> {{address_city}}<br>          
+<b>Country          :</b> {{address_country}}<br>  
+
+<br><br>
+
+<h2>PI for this Authority</h2>     
+<b>First Name   :</b> {{first_name}}<br>
+<b>Last Name    :</b> {{last_name}}<br>
+<b>Authority hrn:</b> {{authority_hrn}}<br>
+<b>Public key   :</b> {{public_key}}<br>
+<b>Email        :</b> {{email}}<br>
+<b>User Hrn     :</b> {{user_hrn}}<br>
diff --git a/portal/templates/smartfire/smartfire_authority_request_email.txt b/portal/templates/smartfire/smartfire_authority_request_email.txt
new file mode 100644 (file)
index 0000000..93daae0
--- /dev/null
@@ -0,0 +1,22 @@
+This email is only for SmartFIRE admins.
+
+NEW AUTHORITY REQUEST
+
+Site             : {{site_name}}             
+
+Authority hrn    : {{authority_hrn}}         
+Abreviated name  : {{site_abbreviated_name}} 
+URL              : {{site_url}}              
+
+
+City             : {{address_city}}          
+Country          : {{address_country}}  
+
+
+PI for this Authority     
+First Name   : {{first_name}}
+Last Name    : {{last_name}}
+Authority hrn: {{authority_hrn}}
+Public key   : {{public_key}}
+Email        : {{email}}
+User Hrn     : {{user_hrn}}
diff --git a/portal/templates/smartfire/smartfire_authority_request_email_subject.txt b/portal/templates/smartfire/smartfire_authority_request_email_subject.txt
new file mode 100644 (file)
index 0000000..1366a27
--- /dev/null
@@ -0,0 +1 @@
+SmartFIRE new Authority request submitted
diff --git a/portal/templates/smartfire/smartfire_contact_support_email.html b/portal/templates/smartfire/smartfire_contact_support_email.html
new file mode 100644 (file)
index 0000000..edd8534
--- /dev/null
@@ -0,0 +1,10 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>User details</h1>
+<br>
+<b>Email        :</b> {{email}}
+
+<h1>Query details</h1>
+
+<b>Subject             :</b> {{subject}}
+<b>Query               :</b> {{description}}
diff --git a/portal/templates/smartfire/smartfire_contact_support_email.txt b/portal/templates/smartfire/smartfire_contact_support_email.txt
new file mode 100644 (file)
index 0000000..536d1b2
--- /dev/null
@@ -0,0 +1,9 @@
+User details: 
+
+email           : {{email}}
+
+Query Details:
+
+Subject         : {{subject}}
+Description     : {{description}}
+
diff --git a/portal/templates/smartfire/smartfire_contact_support_email_subject.txt b/portal/templates/smartfire/smartfire_contact_support_email_subject.txt
new file mode 100644 (file)
index 0000000..7d15d8d
--- /dev/null
@@ -0,0 +1 @@
+SmartFIRE support: user ticket
diff --git a/portal/templates/smartfire/smartfire_email_activation.html b/portal/templates/smartfire/smartfire_email_activation.html
new file mode 100644 (file)
index 0000000..124f32a
--- /dev/null
@@ -0,0 +1,25 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+<div class="row">
+       <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" />User sign-up</h1>
+</div>
+<div class="row">
+       {% if activation_status == 'success' %}
+               <h3>Signup request confirmed.</h3>
+               <p>You are currently able to log in to the portal using your email address and the password that you have provided; however, your access is still limited.</p> 
+               <p>You will have full access as soon as your account is validated by a manager at your organization. We have sent an email to your organisation's managers with a validation request.</p>
+    {% elif activation_status == 'validated' %}
+               <h3>Account validated.</h3>
+               <p>We have identified you as a valid PLE user. Your SmartFIRE account has automatically been approved.</p>
+        <p>You have a full access to SmartFIRE testbeds.</p>
+       {%else%}
+               <h3>Signup confirmation failed.</h3>
+               <p>You have probably arrived at this page by clicking a confirmation link in an email that we have sent to you. 
+               We have been unable to match the link that you have clicked to a signup request in our database.</p>
+               <p>Please <a href="/portal/contact/">contact support</a> so that we may help you complete the signup process.</p>
+       {%endif%}
+ </div>
+
+{% endblock %}
diff --git a/portal/templates/smartfire/smartfire_email_default_recipients.txt b/portal/templates/smartfire/smartfire_email_default_recipients.txt
new file mode 100644 (file)
index 0000000..df7e93a
--- /dev/null
@@ -0,0 +1 @@
+SmartFIRE Support <support@onelab.eu>
diff --git a/portal/templates/smartfire/smartfire_email_default_sender.txt b/portal/templates/smartfire/smartfire_email_default_sender.txt
new file mode 100644 (file)
index 0000000..df7e93a
--- /dev/null
@@ -0,0 +1 @@
+SmartFIRE Support <support@onelab.eu>
index 8236fc5..89fdf64 100644 (file)
@@ -6,9 +6,17 @@
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
+{% widget "_widget-no_credentials.html" %}
 <div class="container dashboard">
+       {%if 'no_creds'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+    {%endif%}
+       {%if 'creds_expired'  in user_cred %}
+        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
+
        <div class="row">
-               {%if 'is_pi'  in pi %}
+               {% if pi %}
                <div class="col-md-3">
                        <h3>
                                EXPERIMENT
@@ -22,9 +30,7 @@
                        <div>
                                <p><strong>Your slices </strong>
                                        <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
-                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
-                                       However, on the OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere, 
-                                       such as on the PlanetLab Europe portal, those slices will not appear here."
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'." 
                                        class="glyphicon glyphicon-info-sign">
                                </span>
 
@@ -88,9 +94,7 @@
                        <div>
                                <p><strong>Your slices </strong>
                                <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
-                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
-                                       However, on the OneLab portal, you will only see slices that you have created through OneLab. If you have created slices elsewhere, 
-                                       such as on the PlanetLab Europe portal, those slices will not appear here."
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'."
                                        class="glyphicon glyphicon-info-sign">
                                </span>
                                </p>
                        <div>   
                                <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
                        </div>
+                       {% if pending_slices %}
+                       <p><strong>Pending slices</strong>
+                       <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
+                               class="glyphicon glyphicon-info-sign">
+                       <ul>
+                       {% for slices in pending_slices %}
+                       <li>{{slices}}</li>
+                       {% endfor %}
+                       </ul>
+                       </span>
+                       </p>
+                       {%endif%}       
                </div>
                <div class="col-md-4">
                        <h3>
                <div class="col-sm-2"></div>
                <div class="col-sm-4 slogan">
                        <h2>
-                               SmartFIRE
+                               Your Easy Access to Computer Networking Testbeds:
                        </h2>
                        <h3>
-                               EU-South Korea Cooperation<br>
-                               On Future Internet Infrastructure
+                               A wide variety of world class testbeds available through your one account
                        </h3>
                </div>
                <div class="col-sm-5 col-sm-offset-1">
                $('button#slicerequestbtn').click(function() {
                        window.location="/portal/slice_request/";
                });
-/*-------
-List of slices has been moved in 
-portal/templates/base.html
-This should go into session
---------*/
+
+        myslice.loadSlices();
+        
 });
 </script>
-{# widget "_widget-monitor.html" #}
-{# widget "_widget-stats-top-slices.html" #}
 
 {% endblock %}
diff --git a/portal/templates/smartfire/smartfire_slice_request_denied.html b/portal/templates/smartfire/smartfire_slice_request_denied.html
new file mode 100644 (file)
index 0000000..6c7d595
--- /dev/null
@@ -0,0 +1,17 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested the following slice on the SmartFIRE portal({{portal_url}}):</p> 
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{url}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<br>
+<p>We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. 
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on SmartFIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
diff --git a/portal/templates/smartfire/smartfire_slice_request_denied.txt b/portal/templates/smartfire/smartfire_slice_request_denied.txt
new file mode 100644 (file)
index 0000000..e4b4990
--- /dev/null
@@ -0,0 +1,14 @@
+Dear SmartFIRE user,
+
+You have recently requested the following slice on the SmartFIRE portal({{portal_url}}):
+
+Slice name   : {{slice_name}}
+URL          : {{url}}
+Purpose      : {{purpose}}
+We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on SmartFIRE.
+
+Yours sincerely,
+The SmartFIRE team
diff --git a/portal/templates/smartfire/smartfire_slice_request_email_subject.txt b/portal/templates/smartfire/smartfire_slice_request_email_subject.txt
new file mode 100644 (file)
index 0000000..e3988df
--- /dev/null
@@ -0,0 +1 @@
+Slice request submitted 
diff --git a/portal/templates/smartfire/smartfire_slice_request_validated.html b/portal/templates/smartfire/smartfire_slice_request_validated.html
new file mode 100644 (file)
index 0000000..2c96a1d
--- /dev/null
@@ -0,0 +1,21 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear SmartFIRE user,</p>
+<p></p>
+<p>You have recently requested a slice in the SmartFIRE portal.</p>
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{number_of_nodes}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<p></p>
+<p>
+       We are pleased to inform you that a manager from your institution has validated your slice request on the SmartFIRE portal. 
+       You can now add resources to you slice and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the SmartFIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
+
+
diff --git a/portal/templates/smartfire/smartfire_slice_request_validated.txt b/portal/templates/smartfire/smartfire_slice_request_validated.txt
new file mode 100644 (file)
index 0000000..571a3e4
--- /dev/null
@@ -0,0 +1,16 @@
+Dear SmartFIRE user,
+
+You have recently requested a slice in the SmartFIRE portal.
+
+Slice name      : {{slice_name}}
+URL             : {{number_of_nodes}}
+Purpose         : {{purpose}}
+
+
+We are pleased to inform you that a manager from your institution has validated your slice request on the SmartFIRE portal. You can now add resources to you slice and start experimenting.
+
+We wish you a fruitful user experience with the SmartFIRE portal.
+
+Yours sincerely,
+The SmartFIRE team
+
diff --git a/portal/templates/smartfire/smartfire_user_request_denied.html b/portal/templates/smartfire/smartfire_user_request_denied.html
new file mode 100644 (file)
index 0000000..64678e3
--- /dev/null
@@ -0,0 +1,11 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>You have recently registered as a user to SmartFIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.</p>
+<p></p>
+<p>We wish you all the best.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
+
diff --git a/portal/templates/smartfire/smartfire_user_request_denied.txt b/portal/templates/smartfire/smartfire_user_request_denied.txt
new file mode 100644 (file)
index 0000000..29edc21
--- /dev/null
@@ -0,0 +1,8 @@
+Dear {{first_name}} {{last_name}},
+
+You have recently registered as a user to SmartFIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The SmartFIRE team
diff --git a/portal/templates/smartfire/smartfire_user_request_email.html b/portal/templates/smartfire/smartfire_user_request_email.html
new file mode 100644 (file)
index 0000000..ae8952c
--- /dev/null
@@ -0,0 +1,16 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<h1>NEW USER REQUEST</h1>
+<br>
+<b>First name   :</b> {{first_name}}<br>
+<b>Last name    :</b> {{last_name}}<br>
+<b>Organization :</b> {{organization}}<br>
+<b>Authority hrn:</b> {{authority_hrn}}<br>
+<b>Public key   :</b> {{public_key}}<br>
+<b>Email        :</b> {{email}}<br>
+<b>User hrn     :</b> {{user_hrn}}<br>
+<b>Portal url  :</b> {{ current_site }}<br>
+<p></p>
+<p>You can validate the user <a href="http://{{current_site}}/portal/validate">here</a>.<p>
+<br>
+<p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
diff --git a/portal/templates/smartfire/smartfire_user_request_email.txt b/portal/templates/smartfire/smartfire_user_request_email.txt
new file mode 100644 (file)
index 0000000..17ce184
--- /dev/null
@@ -0,0 +1,14 @@
+NEW USER REQUEST
+
+First name   : {{first_name}}
+Last name    : {{last_name}} 
+Organization :{{organization}}
+Authority hrn: {{authority_hrn}}
+Public key   : {{public_key}}
+Email        : {{email}}
+User hrn     : {{user_hrn}}
+Portal url   : {{ current_site }}
+
+Please note that the validation request will only become visible once the user has confirmed his/her email address.
+
+
diff --git a/portal/templates/smartfire/smartfire_user_request_email_subject.txt b/portal/templates/smartfire/smartfire_user_request_email_subject.txt
new file mode 100644 (file)
index 0000000..a373b60
--- /dev/null
@@ -0,0 +1 @@
+User request submitted
diff --git a/portal/templates/smartfire/smartfire_user_request_validated.html b/portal/templates/smartfire/smartfire_user_request_validated.html
new file mode 100644 (file)
index 0000000..7997a18
--- /dev/null
@@ -0,0 +1,14 @@
+<img src="http://eukorea-fire.eu/wp-content/uploads/2014/02/SmartFIRE_logo.png">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>It is my pleasure to welcome you as a fully signed-up user of the SmartFIRE experimental facility. SmartFIRE provides you with access to world class computer networking testbeds. Our aim at SmartFIRE is to promote the use of these testbeds for pre-commercial research and development by industry, for scientific research, and for university level laboratory exercises.</p>
+<p></p>
+</p>
+Your entry point for access to the testbeds is the SmartFIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or individual nodes on the testbed with your SmartFIRE public/private key pair, or you may use an experiment control tool such as as OMF. The SmartFIRE  operations team is standing by at support@onelab.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the SmartFIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The SmartFIRE team</p>
diff --git a/portal/templates/smartfire/smartfire_user_request_validated.txt b/portal/templates/smartfire/smartfire_user_request_validated.txt
new file mode 100644 (file)
index 0000000..b546b19
--- /dev/null
@@ -0,0 +1,10 @@
+Dear {{first_name}} {{last_name}},
+
+It is our pleasure to welcome you as a fully signed-up user of the SmartFIRE experimental facility. SmartFIRE provides you with access to world class computer networking testbeds.. Our aim at SmartFIRE is to promote the use of these testbeds for pre-commercial research and development by industry, for scientific research, and for university level laboratory exercises.
+
+Your entry point for access to the testbeds is the SmartFIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or to individual nodes on the testbed with your SmartFIRE public/private key pair, or you may use an experiment control tool such as as  OMF. The SmartFIRE operations team is standing by at support@onelab.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+
+We wish you a fruitful user experience with the SmartFIRE portal.
+
+Yours sincerely,
+The SmartFIRE team
index 7529c61..eaa5c2a 100644 (file)
        <div class="login-submit">
                <input type="submit" class="btn btn-onelab" value="Sign In" />
                <span class="lost-password">&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a href="/portal/pass_reset/">Can't access your account?</a></span>
-       </div>
-       <div class="login-signup">
-               <!-- You don't have yet an account? 
-               
-               <a href="/register">Sign Up!</a> -->
+       <p></p>
+       <p style="color:white;">Don't have an account? <a href="/register">Sign Up!</a></p>
        </div>
        </form>
 </div>
index 738075f..de34e32 100644 (file)
@@ -19,7 +19,7 @@
                                                        </ul>
                                        </div>
                                </li>
-                               {%if 'is_pi'  in pi %}  
+                               {%if pi %}      
                                <li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
                                 {%endif%}
                                <li><a href="/support/">SUPPORT</a></li>
diff --git a/portal/templates/user_register_email.txt b/portal/templates/user_register_email.txt
deleted file mode 100644 (file)
index dc34c21..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Your have registered for an account in {{site}}.
-
-Your activation key is :{{activation_key}}; it will expire in {{expiration_days}} days.
-
diff --git a/portal/templates/user_register_email_subject.txt b/portal/templates/user_register_email_subject.txt
deleted file mode 100644 (file)
index 6ec4cc2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Onelab New User request submitted
index 42a8dcb..905858c 100644 (file)
@@ -37,6 +37,7 @@ from portal.dashboardview           import DashboardView
 from portal.accountview             import AccountView, account_process
 from portal.contactview             import ContactView
 from portal.slicerequestview        import SliceRequestView
+from portal.projectrequestview      import ProjectRequestView
 from portal.registrationview        import RegistrationView
 from portal.joinview                import JoinView
 from portal.sliceviewold            import SliceView
@@ -79,6 +80,7 @@ urlpatterns = patterns('',
     #url(r'^my_account/?$', MyAccountView.as_view(), name='my_account'),
     url(r'^account/?$', AccountView.as_view(), name='account'),
     url(r'^institution/?$', InstitutionView.as_view(), name='institution'),
+    url(r'^project/(?P<authority_hrn>[\w\.]+)/?$', InstitutionView.as_view(), name='project'),
     url(r'^about/?$', AboutView.as_view(), name='about'),
     url(r'^users/?$', UsersView.as_view(), name='user_list'),
     url(r'^user/(?P<email>[\w\s.@\-]+)/?$', UserView.as_view(), name='user'),
@@ -98,6 +100,8 @@ urlpatterns = patterns('',
     #url(r'^pass_reset/?$', PassResetView.as_view(), name='pass_rest'),
     # Slice request
     url(r'^slice_request/?$', SliceRequestView.as_view(), name='slice_request'),
+    # Project request
+    url(r'^project_request/?$', ProjectRequestView.as_view(), name='project_request'),
     url(r'^terms/?$', TermsView.as_view(), name='terms'),
     url(r'^manual_delegation/?$', ManualDelegationView.as_view(), name='manual_delegation'),
     # Validate pending requests
index b26ba0f..b87a250 100644 (file)
@@ -151,7 +151,7 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
 
             # ** Where am I a PI **
             # For this we need to ask SFA (of all authorities) = PI function
-            pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+            pi_authorities_query = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
             pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
             pi_authorities = set()
             try:
index a856596..96b901f 100644 (file)
@@ -74,6 +74,7 @@ class ObjectRequest(object):
     def setKey(self):
         # What about key formed of multiple fields???
         query = Query.get('local:object').filter_by('table', '==', self.type).select('key')
+        print query
         results = execute_query(self.request, query)
         print "key of object = %s" % results
         if results :
@@ -114,6 +115,8 @@ class ObjectRequest(object):
                     query.filter_by(k, '<=', f[2:])
                 elif (f[:1] == "<") :
                     query.filter_by(k, '<', f[1:])
+                elif (f[:8] == "CONTAINS") :
+                    query.filter_by(k, 'CONTAINS', f[8:])
                 else :
                     query.filter_by(k, '==', f)
         return query
diff --git a/rest/cache.py b/rest/cache.py
new file mode 100644 (file)
index 0000000..3943946
--- /dev/null
@@ -0,0 +1,22 @@
+from django.http                import HttpResponse
+from portal.actions             import clear_user_creds
+
+from manifoldapi.manifoldapi    import execute_query
+from manifold.core.query        import Query
+
+import json
+
+def dispatch(request, action):
+    
+    if (action == 'clear') :
+        query = Query.update('myslice:user').filter_by('user_hrn', '==', '$user_hrn').set({'user_email':str(request.user)})
+        try:
+            res = execute_query(request, query)
+        except Exception, e:
+            ret = { "ret" : -1, "error" : "error clearing cache: %s" % e }
+            return HttpResponse(json.dumps(ret), content_type="application/json")
+    
+        ret = { "ret" : 1 }
+    else:
+        ret = { "ret" : 0, "error" : "action not supported" }
+    return HttpResponse(json.dumps(ret), content_type="application/json")
index e385baf..676d108 100755 (executable)
@@ -3,10 +3,16 @@ from django.conf.urls import patterns, url, include
 from sla import slicetabsla
 
 urlpatterns = patterns('',
-       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
-       url(r'^testbeds/', slicetabsla.Testbeds.as_view(), name="testbeds"),
-       url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
-       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
-       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
-       url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
-)
\ No newline at end of file
+       url(r'^api-auth/',
+            include('rest_framework.urls', namespace='rest_framework')),
+       url(r'^testbeds/',
+            slicetabsla.Testbeds.as_view(), name="testbeds"),
+       url(r'^(?P<slicename>[^/]+)/?$',
+            slicetabsla.SLAView.as_view(), name="agreements_summary"),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$',
+            slicetabsla.agreement_details, name='agreement_details'),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$',
+            slicetabsla.agreement_term_violations, name='agreement_term_violations'),
+       url(r'^agreements/simplecreate/?$',
+            slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
+)