Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into fibre
authorLoic Baron <loic.baron@lip6.fr>
Wed, 23 Jul 2014 16:13:01 +0000 (13:13 -0300)
committerLoic Baron <loic.baron@lip6.fr>
Wed, 23 Jul 2014 16:13:01 +0000 (13:13 -0300)
Conflicts:
portal/registrationview.py
portal/slicerequestview.py
ui/topmenu.py

88 files changed:
apache/myslice.wsgi [new symlink]
apache/sp-fibre/default [new file with mode: 0644]
apache/sp-fibre/myslice-django [new file with mode: 0644]
apache/sp-fibre/shibboleth-myslice [new file with mode: 0644]
apache/unfold.conf
apache/unfold.wsgi
auth/manifoldbackend-130314.py [new file with mode: 0644]
auth/manifoldbackend.py
auth/manifoldbackend.py.original [new file with mode: 0644]
manifoldapi/manifoldproxy.py
manifoldapi/static/js/manifold.js
myslice/configengine.py
myslice/settings.py
myslice/urls.py
old.unfold.sqlite3-110314 [new file with mode: 0644]
plugins/scheduler2/templates/scheduler.html
portal/actions-100314.py [new file with mode: 0644]
portal/actions.py
portal/homeview.py
portal/registrationview.py
portal/slicerequestview.py
portal/sliceresourceview.py
portal/static/css/fibre.css [new file with mode: 0644]
portal/static/css/onelab_edelberto.css [new file with mode: 0644]
portal/static/img/fibre-logo.gif [new file with mode: 0644]
portal/static/img/fibre/br.png [new file with mode: 0644]
portal/static/img/fibre/cafe.jpg [new file with mode: 0644]
portal/static/img/fibre/eu.png [new file with mode: 0644]
portal/static/img/fibre/icon_authority_color.png [new file with mode: 0644]
portal/static/img/fibre/icon_slices.png [new file with mode: 0644]
portal/static/img/fibre/icon_support.png [new file with mode: 0644]
portal/static/img/fibre/icon_testbed_color.png [new file with mode: 0644]
portal/static/img/fibre/icon_user_color.png [new file with mode: 0644]
portal/static/img/fibre/icones.zip [new file with mode: 0644]
portal/static/img/icon_authority_color.png~HEAD [new file with mode: 0644]
portal/static/img/icon_slices.png~HEAD [new file with mode: 0644]
portal/static/img/icon_support.png~HEAD [new file with mode: 0644]
portal/static/img/icon_testbed_color.png~HEAD [new file with mode: 0644]
portal/static/img/icon_user_color.png~HEAD [new file with mode: 0644]
portal/static/img/optical_fibre.jpg [new file with mode: 0644]
portal/static/img/original-backup/authority-icon.png [new file with mode: 0644]
portal/static/img/original-backup/experiments.png [new file with mode: 0644]
portal/static/img/original-backup/f4f-logo.png [new file with mode: 0644]
portal/static/img/original-backup/marker1.png [new file with mode: 0644]
portal/static/img/original-backup/marker2.png [new file with mode: 0644]
portal/static/img/original-backup/ques_icon.png [new file with mode: 0644]
portal/static/img/original-backup/resource-icon.png [new file with mode: 0644]
portal/static/img/original-backup/slice-icon.png [new file with mode: 0644]
portal/static/img/original-backup/testbeds.png [new file with mode: 0644]
portal/static/img/original-backup/user-icon.png [new file with mode: 0644]
portal/static/img/original-backup/user.png [new file with mode: 0644]
portal/static/js/jquery.qtip.min.js
portal/templates/_widget-topmenu.html
portal/templates/base.html
portal/templates/fibre/fibre__widget-login-fed-manager.html [new file with mode: 0644]
portal/templates/fibre/fibre__widget-login-manager.html [new file with mode: 0644]
portal/templates/fibre/fibre__widget-topmenu.html [new file with mode: 0644]
portal/templates/fibre/fibre_about.html [new file with mode: 0644]
portal/templates/fibre/fibre_account-view.html [new file with mode: 0644]
portal/templates/fibre/fibre_base.html [new file with mode: 0644]
portal/templates/fibre/fibre_contact.html [new file with mode: 0644]
portal/templates/fibre/fibre_home-view.html [new file with mode: 0644]
portal/templates/fibre/fibre_institution.html [new file with mode: 0644]
portal/templates/fibre/fibre_management-tab-about.html [new file with mode: 0644]
portal/templates/fibre/fibre_management-tab-requests.html [new file with mode: 0644]
portal/templates/fibre/fibre_news.html [new file with mode: 0644]
portal/templates/fibre/fibre_registration_view.html [new file with mode: 0644]
portal/templates/fibre/fibre_slice-tab-users-view.html [new file with mode: 0644]
portal/templates/fibre/fibre_slice-user-view.html [new file with mode: 0644]
portal/templates/fibre/fibre_slice-view.html [new file with mode: 0644]
portal/templates/fibre/fibre_slicerequest_view.html [new file with mode: 0644]
portal/templates/fibre/fibre_supportview.html [new file with mode: 0644]
portal/templates/fibre/fibre_termsview.html [new file with mode: 0644]
portal/templates/fibre/fibre_user_request_email.html [new file with mode: 0644]
portal/templates/fibre/fibre_user_request_email.txt [new file with mode: 0644]
portal/templates/fibre/fibre_widget-login-user.html [new file with mode: 0644]
portal/templates/fibre/fibre_widget-news.html [new file with mode: 0644]
portal/templates/fibre/fibre_widget-slice-sections.html [new file with mode: 0644]
portal/templates/onelab/onelab_base.html
portal/templates/registration_view.html
portal/templates/slice-resource-view.html
portal/templates/slice-tab-users-view.html
portal/templates/user_register.html
ui/templates/base2.html [new file with mode: 0644]
unfold.sqlite3-110314 [new file with mode: 0644]
unfold.sqlite3-130314 [new file with mode: 0644]
unfold.sqlite3-140314 [new file with mode: 0644]
unfold.sqlite3.old-120314 [new file with mode: 0644]

diff --git a/apache/myslice.wsgi b/apache/myslice.wsgi
new file mode 120000 (symlink)
index 0000000..69ee492
--- /dev/null
@@ -0,0 +1 @@
+unfold.wsgi
\ No newline at end of file
diff --git a/apache/sp-fibre/default b/apache/sp-fibre/default
new file mode 100644 (file)
index 0000000..ec902c6
--- /dev/null
@@ -0,0 +1,24 @@
+NameVirtualHost *:80
+<VirtualHost *:80>
+        ServerName     200.130.15.182
+        ServerSignature Off
+        # Redirecionamento para SSL
+        #RewriteEngine on
+        #RewriteCond %{HTTPS} !=on
+        #RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [R,L]
+        DocumentRoot /var/www/
+        <Directory /var/www/>
+                Options Indexes FollowSymLinks MultiViews
+                AllowOverride None
+                Order allow,deny
+                allow from all
+        </Directory>
+        ErrorLog /var/log/apache2/error.log
+        # Possible values include: debug, info, notice, warn, error, crit,
+        # alert, emerg.
+        LogLevel info
+        CustomLog /var/log/apache2/sp-access-80.log combined
+</VirtualHost>
diff --git a/apache/sp-fibre/myslice-django b/apache/sp-fibre/myslice-django
new file mode 100644 (file)
index 0000000..bafed8f
--- /dev/null
@@ -0,0 +1,56 @@
+NameVirtualHost *:443
+<IfModule mod_ssl.c>
+<VirtualHost *:443>
+    ServerAdmin support-myslice@myslice.info
+    ServerName portal.fibre.br
+
+    DocumentRoot /var/www/myslice
+    WSGIScriptAlias / /var/www/myslice/apache/unfold.wsgi 
+
+    <Directory /var/www/myslice>
+        Options Indexes FollowSymLinks MultiViews
+        AllowOverride All
+        Order allow,deny
+        allow from all
+    </Directory>
+
+    Alias /static/ /var/www/myslice/static/
+    <Directory /var/www/myslice/static>
+        Order deny,allow
+        Allow from all
+    </Directory>
+
+    #Alias /certificates/ /var/certificates-f4f/
+    ErrorLog ${APACHE_LOG_DIR}/error.log
+
+    LogLevel warn
+
+    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
+
+    # SSL
+    SSLEngine on
+    SSLProtocol all -SSLv2
+    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
+    SSLCertificateKeyFile   /etc/ssl/private/fibre.key
+    SSLCertificateFile      /etc/ssl/certs/fibre.crt
+    SSLOptions +StdEnvVars +ExportCertData
+    SSLCACertificatePath /etc/sfa/trusted_roots
+    SSLVerifyClient optional_no_ca
+    #SSLVerifyClient require
+    SSLVerifyDepth 5
+    ServerSignature On
+
+    <FilesMatch "\.(cgi|shtml|phtml|php)$">
+        SSLOptions +StdEnvVars
+    </FilesMatch>
+    <Directory /usr/lib/cgi-bin>
+        SSLOptions +StdEnvVars
+    </Directory>
+
+    BrowserMatch "MSIE [2-6]" \
+        nokeepalive ssl-unclean-shutdown \
+        downgrade-1.0 force-response-1.0
+    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+</VirtualHost>
+</IfModule>
diff --git a/apache/sp-fibre/shibboleth-myslice b/apache/sp-fibre/shibboleth-myslice
new file mode 100644 (file)
index 0000000..fc39e54
--- /dev/null
@@ -0,0 +1,61 @@
+<VirtualHost 200.130.15.182:443>
+        ServerName     200.130.15.182
+        ServerSignature Off
+
+        SSLEngine               on
+        #SSLCertificateFile      /etc/unfold/trusted_roots
+        SSLCertificateFile      /etc/ssl/certs/fibre.crt
+        SSLCertificateKeyFile   /etc/ssl/private/fibre.key
+
+        #ShibURLScheme https
+
+        DocumentRoot /var/www/
+        <Directory /var/www/>
+                Options -Indexes FollowSymLinks -MultiViews
+                AllowOverride None
+                Order deny,allow
+                Allow from all
+        </Directory>
+
+#        WSGIScriptAlias / /usr/share/unfold/apache/myslice.wsgi
+#        <Directory /usr/share/unfold/apache>
+#        <Files myslice.wsgi>
+#        Order deny,allow
+#        Allow from all
+#        </Files>
+#        </Directory>
+#        Alias /static/ /usr/share/unfold/static/
+#        <Directory /usr/share/unfold/static>
+#        Order deny,allow
+#        Allow from all
+#        </Directory>
+
+
+#<Location myslice/secure>
+#      AuthType Shibboleth
+#      ShibRequestSetting requireSession true
+#        ShibRequestSetting applicationId default
+#      Require valid-user
+#</Location>
+
+<Location /Shibboleth.sso>
+  SetHandler shib
+</Location>
+<Location /shibboleth-sp2>
+  SetHandler shib
+</Location>
+
+
+#         <Location /moodle/auth/shibboleth>
+#                 AuthType shibboleth
+#                 ShibRequireSession On
+#                 require valid-user
+#         </Location>
+
+        # Possible values include: debug, info, notice, warn, error, crit,
+        # alert, emerg.
+        ErrorLog /var/log/apache2/error.log
+        LogLevel info
+        CustomLog /var/log/apache2/sp-access-443.log combined
+
+</VirtualHost>
index 357db7e..fed763e 100644 (file)
@@ -1,19 +1,19 @@
 # see also unfold-ssl.conf
 
 <VirtualHost *:80>
-       WSGIDaemonProcess unfold processes=2 threads=25
-       WSGIProcessGroup  unfold
-       CustomLog ${APACHE_LOG_DIR}/unfold-access.log common
-       ErrorLog ${APACHE_LOG_DIR}/unfold-error.log
-        WSGIScriptAlias / /usr/share/unfold/apache/unfold.wsgi
-        <Directory /usr/share/unfold/apache/>
-        <Files unfold.wsgi>
+       WSGIDaemonProcess myslice processes=2 threads=25
+       WSGIProcessGroup  myslice
+       CustomLog ${APACHE_LOG_DIR}/myslice-access.log common
+       ErrorLog ${APACHE_LOG_DIR}/myslice-error.log
+        WSGIScriptAlias / /var/www/myslice/apache/myslice.wsgi
+        <Directory /var/www/myslice/myslice/apache/>
+        <Files myslice.wsgi>
         Order deny,allow
         Allow from all
         </Files>
         </Directory>
-        Alias /static/ /usr/share/unfold/static/
-        <Directory /usr/share/unfold/static>
+        Alias /static/ /var/www/myslice/myslice/static/
+        <Directory /var/www/myslicee/myslice/static>
         Order deny,allow
         Allow from all
         </Directory>
index 4af2e9f..34ffb36 100644 (file)
@@ -1,12 +1,14 @@
 import os
 import sys
 
-path = '/var/myslice-f4f'
+#site.addsitedir('/var/www/myslice')
+
+path = '/var/www/myslice'
 if path not in sys.path:
-    sys.path.append(path)
+    sys.path = [path] + sys.path
+print sys.path
 
 os.environ['DJANGO_SETTINGS_MODULE'] = 'myslice.settings'
 
 import django.core.handlers.wsgi
 application = django.core.handlers.wsgi.WSGIHandler()
-
diff --git a/auth/manifoldbackend-130314.py b/auth/manifoldbackend-130314.py
new file mode 100644 (file)
index 0000000..ee80113
--- /dev/null
@@ -0,0 +1,228 @@
+import time
+
+# import ldap for LDAP authentication - Edelberto
+import ldap
+
+from django.contrib.auth.models import User
+
+from manifoldapi.manifoldapi    import ManifoldAPI, ManifoldException, ManifoldResult
+from manifold.core.query        import Query
+
+# Name my backend 'ManifoldBackend'
+class ManifoldBackend:
+
+
+    # Create an authentication method
+    # This is called by the standard Django login procedure
+    def authenticate(self, token=None):
+    
+        # LDAP local/global var
+        checkldap = None
+
+        if not token:
+            return None
+
+        try:
+            #usernameldap is from LDAP user form. If it is filled - See portal/homeview.py too
+            usernameldap = token['usernameldap']
+            username = token['username']
+            password = token['password']
+            request = token['request']
+
+            # if data are not from LDAP form then normal (local) login
+            if not usernameldap:
+                auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
+                api = ManifoldAPI(auth)
+                sessions_result = api.forward(Query.create('local:session').to_dict())
+                print "result"
+                sessions = sessions_result.ok_value()
+                print "ok"
+                if not sessions:
+                    print "GetSession failed", sessions_result.error()
+                    return
+                print "first", sessions
+                session = sessions[0]
+
+                # Change to session authentication
+                api.auth = {'AuthMethod': 'session', 'session': session['session']}
+                self.api = api
+
+                # Get account details
+                # the new API would expect Get('local:user') instead
+                persons_result = api.forward(Query.get('local:user').to_dict())
+                persons = persons_result.ok_value()
+                if not persons:
+                    print "GetPersons failed",persons_result.error()
+                    return
+                person = persons[0]
+                print "PERSON=", person
+
+                request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+            ################################
+            # Edelberto LDAP authentication
+            # if data are from LDAP form, so
+            else:
+            # XXX UGLY
+            # Needing to create an specific entries at settings.py (or myslice.ini) for these vars
+            ##################################################
+            # Edelberto - UFF - esilva@ic.uff.br
+            # v1 - ldap authentication module
+            # Note: focus on LDAP FIBRE-BR for DN
+            #       if uses other DN, configuration are needed
+            ###################################################
+            #Searching an LDAP Directory
+
+                try:
+                    #uid = "debora@uff.br"
+
+                    # Receiving an email address, how can we split and mount it in DN format?
+                    #mail = "debora@uff.br"
+                    mail = usernameldap
+                    login = mail.split('@')[0]
+                    org = mail.split('@')[1]
+                    o = org.split('.')[0]
+                    dc = org.split('.')[1]
+                    '''
+                    print mail
+                    print login
+                    print org
+                    print o
+                    print dc
+                    '''
+
+                    # DN format to authenticate - IMPORTANT!
+                    #FIBRE-BR format
+                    uid = "uid="+mail+",ou=people,o="+o+",dc="+dc
+                    #uid = "uid=debora@uff.br,ou=people,o=uff,dc=br"
+                    # User password from LDAP form
+                    #userPassword = "fibre"
+                    userPassword = password
+
+                    # testing with:
+                    # wrong password for test
+                    #    userPassword = "fibre2"
+                    
+                    # Parameters to connect on LDAP
+                    ldap.set_option(ldap.OPT_REFERRALS, 0)
+                    # LDAP Server Address
+                    l = ldap.open("127.0.0.1")
+                    # LDAP version
+                    l.protocol_version = ldap.VERSION3
+
+                    #l.simple_bind(uid, userPassword)
+                    # l.bind_s is necessary to do the authentication with a normal LDAP user
+                    l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
+                    #print l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
+
+                    # DN base - Our root dc (dc=br)
+                    baseDN="dc="+dc
+                    searchScope = ldap.SCOPE_SUBTREE
+                    retrieveAttributes = None
+                    # User only can see its credentials. He search only his attributes
+                    searchFilter = "uid="+mail
+
+                    # Getting all attributes
+                    try:
+                        ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)
+                        result_set = []
+                        # while exist attributes, save them in a list!
+                        while 1:
+                        #   print l.result(ldap_result_id, 0)
+                            result_type, result_data = l.result(ldap_result_id, 0)
+                            if (result_data == []):
+                            #print ("User %s don't allowed to bind in LDAP", uid)
+                                break
+                            else:
+                                ## Appendng to a list
+                                if result_type == ldap.RES_SEARCH_ENTRY:
+                                    result_set.append(result_data)
+                                    #    print result_set
+                    except ldap.LDAPError, e:
+                        print e
+
+                    # Matching if the user is really who his say
+                    #checkldap = None
+                    if l.compare_s(uid, 'uid', mail):
+                        # DEBUG
+                        checkldap = True
+                        print "match"
+
+                # Now, based on default Manifold Auth
+                        auth = {'AuthMethod': 'password', 'Username': usernameldap, 'AuthString': password}
+                        api = ManifoldAPI(auth)
+                        sessions_result = api.forward(Query.create('local:session').to_dict())
+                        print "result"
+                        sessions = sessions_result.ok_value()
+                        print "ok"
+                        if not sessions:
+                            print "GetSession failed", sessions_result.error()
+                            return
+                        print "first", sessions
+                        session = sessions[0]
+
+                        # Change to session authentication
+                        api.auth = {'AuthMethod': 'session', 'session': session['session']}
+                        self.api = api
+
+                        # Get account details
+                        # the new API would expect Get('local:user') instead
+                        persons_result = api.forward(Query.get('local:user').to_dict())
+                        persons = persons_result.ok_value()
+                        if not persons:
+                            print "GetPersons failed",persons_result.error()
+                            return
+                        person = persons[0]
+                        print "PERSON=", person
+
+                        request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+
+                    else:
+                        print "no match. User doesnt allowed"
+                        checkldap = False
+
+                except ldap.LDAPError, e:
+                    print "E: LDAP Search user", e                      
+        # end of LDAP
+       
+        # Follow the same of Manifold 
+        except ManifoldException, e:
+            print "ManifoldBackend.authenticate caught ManifoldException, returning corresponding ManifoldResult"
+            return e.manifold_result
+        except Exception, e:
+            print "E: manifoldbackend", e
+            import traceback
+            traceback.print_exc()
+            return None
+    
+        if not usernameldap:
+            try:
+                # Check if the user exists in Django's local database
+               user = User.objects.get(username=username)
+            except User.DoesNotExist:
+                # Create a user in Django's local database
+                user = User.objects.create_user(username, usernamep, 'passworddoesntmatter')
+                user.first_name = "DUMMY_FIRST_NAME" #person['first_name']
+                user.last_name = "DUMMY LAST NAME" # person['last_name']
+                user.email = person['email']
+            return user
+        else:
+            if checkldap:
+                try:
+                    # Check if the user exists in Django's local database
+                    user = User.objects.get(username=usernameldap)
+                except User.DoesNotExist:
+                    # Create a user in Django's local database
+                    user = User.objects.create_user(username, usernameldap, 'passworddoesntmatter')
+                    user.first_name = "DUMMY_FIRST_NAME" #person['first_name']
+                    user.last_name = "DUMMY LAST NAME" # person['last_name']
+                    user.email = person['email']
+                return user
+
+    # Required for your backend to work properly - unchanged in most scenarios
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+
index afb8782..0522653 100644 (file)
@@ -1,5 +1,8 @@
 import time
 
+# import ldap for LDAP authentication - Edelberto
+import ldap
+
 from django.contrib.auth.models import User
 
 from manifoldapi.manifoldapi    import ManifoldAPI, ManifoldException, ManifoldResult
@@ -8,44 +11,188 @@ from manifold.core.query        import Query
 # Name my backend 'ManifoldBackend'
 class ManifoldBackend:
 
+
     # Create an authentication method
     # This is called by the standard Django login procedure
     def authenticate(self, token=None):
+    
+        # LDAP local/global var
+        checkldap = None
+
         if not token:
             return None
 
         try:
+            print "ManifoldBackend authenticate()"
+            # Mandatory fields in token
             username = token['username']
-            password = token['password']
             request = token['request']
 
-            auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
-            api = ManifoldAPI(auth)
-            sessions_result = api.forward(Query.create('local:session').to_dict())
-            print "result"
-            sessions = sessions_result.ok_value()
-            print "ok"
-            if not sessions:
-                print "GetSession failed", sessions_result.error()
-                return
-            print "first", sessions
-            session = sessions[0]
-
-            # Change to session authentication
-            api.auth = {'AuthMethod': 'session', 'session': session['session']}
-            self.api = api
-
-            # Get account details
-            # the new API would expect Get('local:user') instead
-            persons_result = api.forward(Query.get('local:user').to_dict())
-            persons = persons_result.ok_value()
-            if not persons:
-                print "GetPersons failed",persons_result.error()
-                return
-            person = persons[0]
-            print "PERSON=", person
-
-            request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+            # usernameldap is optional - from LDAP user form. 
+            # If it is filled - See portal/homeview.py too
+            if 'usernameldap' in token:
+                usernameldap = token['usernameldap']
+            else:
+                usernameldap = None
+            password = token['password']
+            # if data are not from LDAP form then normal (local) login
+            if not usernameldap:
+                print "not userldap ManifoldBackend authenticate()"
+                auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
+                api = ManifoldAPI(auth)
+                sessions_result = api.forward(Query.create('local:session').to_dict())
+                print "result"
+                sessions = sessions_result.ok_value()
+                print "ok"
+                if not sessions:
+                    print "GetSession failed", sessions_result.error()
+                    return
+                print "first", sessions
+                session = sessions[0]
+
+                # Change to session authentication
+                api.auth = {'AuthMethod': 'session', 'session': session['session']}
+                self.api = api
+
+                # Get account details
+                # the new API would expect Get('local:user') instead
+                persons_result = api.forward(Query.get('local:user').to_dict())
+                persons = persons_result.ok_value()
+                if not persons:
+                    print "GetPersons failed",persons_result.error()
+                    return
+                person = persons[0]
+                print "PERSON=", person
+
+                request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+            ################################
+            # Edelberto LDAP authentication
+            # if data are from LDAP form, so
+            else:
+                print "userldap ManifoldBackend authenticate()"
+            # XXX UGLY
+            # Needing to create an specific entries at settings.py (or myslice.ini) for these vars
+            ##################################################
+            # Edelberto - UFF - esilva@ic.uff.br
+            # v1 - ldap authentication module
+            # Note: focus on LDAP FIBRE-BR for DN
+            #       if uses other DN, configuration are needed
+            ###################################################
+            #Searching an LDAP Directory
+
+                try:
+                    #uid = "debora@uff.br"
+
+                    # Receiving an email address, how can we split and mount it in DN format?
+                    #mail = "debora@uff.br"
+                    mail = usernameldap
+                    login = mail.split('@')[0]
+                    org = mail.split('@')[1]
+                    o = org.split('.')[0]
+                    dc = org.split('.')[1]
+                    '''
+                    print mail
+                    print login
+                    print org
+                    print o
+                    print dc
+                    '''
+
+                    # DN format to authenticate - IMPORTANT!
+                    #FIBRE-BR format
+                    uid = "uid="+mail+",ou=people,o="+o+",dc="+dc
+                    #uid = "uid=debora@uff.br,ou=people,o=uff,dc=br"
+                    # User password from LDAP form
+                    #userPassword = "fibre"
+                    userPassword = password
+
+                    # testing with:
+                    # wrong password for test
+                    #    userPassword = "fibre2"
+                    
+                    # Parameters to connect on LDAP
+                    ldap.set_option(ldap.OPT_REFERRALS, 0)
+                    # LDAP Server Address
+                    l = ldap.open("127.0.0.1")
+                    # LDAP version
+                    l.protocol_version = ldap.VERSION3
+
+                    #l.simple_bind(uid, userPassword)
+                    # l.bind_s is necessary to do the authentication with a normal LDAP user
+                    l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
+                    #print l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
+
+                    # DN base - Our root dc (dc=br)
+                    baseDN="dc="+dc
+                    searchScope = ldap.SCOPE_SUBTREE
+                    retrieveAttributes = None
+                    # User only can see its credentials. He search only his attributes
+                    searchFilter = "uid="+mail
+
+                    # Getting all attributes
+                    try:
+                        ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)
+                        result_set = []
+                        # while exist attributes, save them in a list!
+                        while 1:
+                        #   print l.result(ldap_result_id, 0)
+                            result_type, result_data = l.result(ldap_result_id, 0)
+                            if (result_data == []):
+                            #print ("User %s don't allowed to bind in LDAP", uid)
+                                break
+                            else:
+                                ## Appendng to a list
+                                if result_type == ldap.RES_SEARCH_ENTRY:
+                                    result_set.append(result_data)
+                                    #    print result_set
+                    except ldap.LDAPError, e:
+                        print e
+
+                    # Matching if the user is really who his say
+                    #checkldap = None
+                    if l.compare_s(uid, 'uid', mail):
+                        # DEBUG
+                        checkldap = True
+                        print "match"
+
+                # Now, based on default Manifold Auth
+                        auth = {'AuthMethod': 'password', 'Username': usernameldap, 'AuthString': password}
+                        api = ManifoldAPI(auth)
+                        sessions_result = api.forward(Query.create('local:session').to_dict())
+                        print "result"
+                        sessions = sessions_result.ok_value()
+                        print "ok"
+                        if not sessions:
+                            print "GetSession failed", sessions_result.error()
+                            return
+                        print "first", sessions
+                        session = sessions[0]
+
+                        # Change to session authentication
+                        api.auth = {'AuthMethod': 'session', 'session': session['session']}
+                        self.api = api
+
+                        # Get account details
+                        # the new API would expect Get('local:user') instead
+                        persons_result = api.forward(Query.get('local:user').to_dict())
+                        persons = persons_result.ok_value()
+                        if not persons:
+                            print "GetPersons failed",persons_result.error()
+                            return
+                        person = persons[0]
+                        print "PERSON=", person
+
+                        request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+
+                    else:
+                        print "no match. User doesnt allowed"
+                        checkldap = False
+
+                except ldap.LDAPError, e:
+                    print "E: LDAP Search user", e                      
+        # end of LDAP
+       
+        # Follow the same of Manifold 
         except ManifoldException, e:
             print "ManifoldBackend.authenticate caught ManifoldException, returning corresponding ManifoldResult"
             return e.manifold_result
@@ -54,14 +201,24 @@ class ManifoldBackend:
             import traceback
             traceback.print_exc()
             return None
-
-        try:
-            # Check if the user exists in Django's local database
-            user = User.objects.get(username=username)
-        except User.DoesNotExist:
-            # Create a user in Django's local database
-            user = User.objects.create_user(username, username, 'passworddoesntmatter')
-            user.email = person['email']
+    
+        if not usernameldap:
+            try:
+                # Check if the user exists in Django's local database
+               user = User.objects.get(username=username)
+            except User.DoesNotExist:
+                # Create a user in Django's local database
+                user = User.objects.create_user(username, usernamep, 'passworddoesntmatter')
+                user.email = person['email']
+        else:
+            if checkldap:
+                try:
+                    # Check if the user exists in Django's local database
+                    user = User.objects.get(username=usernameldap)
+                except User.DoesNotExist:
+                    # Create a user in Django's local database
+                    user = User.objects.create_user(username, usernameldap, 'passworddoesntmatter')
+                    user.email = person['email']
 
         if 'firstname' in person:
             user.first_name = person['firstname']
@@ -69,7 +226,6 @@ class ManifoldBackend:
             user.last_name = person['lastname']
 
         return user
-
     # Required for your backend to work properly - unchanged in most scenarios
     def get_user(self, user_id):
         try:
diff --git a/auth/manifoldbackend.py.original b/auth/manifoldbackend.py.original
new file mode 100644 (file)
index 0000000..eb87ab8
--- /dev/null
@@ -0,0 +1,76 @@
+import time
+
+from django.contrib.auth.models import User
+
+from manifoldapi.manifoldapi    import ManifoldAPI, ManifoldException, ManifoldResult
+from manifold.core.query        import Query
+
+# Name my backend 'ManifoldBackend'
+class ManifoldBackend:
+
+    # Create an authentication method
+    # This is called by the standard Django login procedure
+    def authenticate(self, token=None):
+        if not token:
+            return None
+
+        try:
+            username = token['username']
+            password = token['password']
+            request = token['request']
+
+            auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
+            api = ManifoldAPI(auth)
+            sessions_result = api.forward(Query.create('local:session').to_dict())
+            print "result"
+            sessions = sessions_result.ok_value()
+            print "ok"
+            if not sessions:
+                print "GetSession failed", sessions_result.error()
+                return
+            print "first", sessions
+            session = sessions[0]
+
+            # Change to session authentication
+            api.auth = {'AuthMethod': 'session', 'session': session['session']}
+            self.api = api
+
+            # Get account details
+            # the new API would expect Get('local:user') instead
+            persons_result = api.forward(Query.get('local:user').to_dict())
+            persons = persons_result.ok_value()
+            if not persons:
+                print "GetPersons failed",persons_result.error()
+                return
+            person = persons[0]
+            print "PERSON=", person
+
+            request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+        except ManifoldException, e:
+            print "ManifoldBackend.authenticate caught ManifoldException, returning corresponding ManifoldResult"
+            return e.manifold_result
+        except Exception, e:
+            print "E: manifoldbackend", e
+            import traceback
+            traceback.print_exc()
+            return None
+
+        try:
+            # Check if the user exists in Django's local database
+            user = User.objects.get(username=username)
+        except User.DoesNotExist:
+            # Create a user in Django's local database
+            user = User.objects.create_user(username, username, 'passworddoesntmatter')
+            user.first_name = "DUMMY_FIRST_NAME" #person['first_name']
+            user.last_name = "DUMMY LAST NAME" # person['last_name']
+            user.email = person['email']
+        return user
+
+    # Required for your backend to work properly - unchanged in most scenarios
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+
index 99959ae..76f6165 100644 (file)
@@ -55,6 +55,7 @@ with the query passed using POST"""
             admin_user, admin_password = ConfigEngine().manifold_admin_user_password()
             manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
         else:
+            print manifold_query
             print request.session['manifold']
             manifold_api_session_auth = request.session['manifold']['auth']
 
index 7dfcb4d..fe76629 100644 (file)
@@ -320,12 +320,13 @@ function QueryStore() {
         var self = this;
         var query_ext = this.find_analyzed_query_ext(query_uuid);
         var record_key = manifold.metadata.get_key(query_ext.query.object);
+
         $.each(records, function(i, record) {
-            var key = manifold.metadata.get_key(query_ext.query.object);
+            //var key = manifold.metadata.get_key(query_ext.query.object);
             // ["start_time", "resource", "end_time"]
             // ["urn"]
-            
             var record_key_value = manifold.record_get_value(record, record_key);
+            
             query_ext.records.put(record_key_value, record);
 
             if (!(query_ext.state.get(record_key_value)))
index 5ce5260..1a46e6d 100644 (file)
@@ -33,7 +33,7 @@ class ConfigEngine(object):
 
     default_manifold_admin_user     = 'admin'
     default_manifold_admin_password = 'demo'
-    default_myslice_theme           = 'onelab'
+    default_myslice_theme           = 'fibre'
 
 
     def __init__ (self):
@@ -48,7 +48,9 @@ class ConfigEngine(object):
 
         parser.add_section('googlemap')
         parser.set ('googlemap','api_key', None)
+        print os.path.join(ROOT,'myslice/myslice.ini')
         parser.read (os.path.join(ROOT,'myslice/myslice.ini'))
+        print parser
         self.config_parser=parser
 
     def __getattr__(self, section):
index 235a18c..89565dd 100644 (file)
@@ -42,9 +42,9 @@ except:
 # when deployed from a package
 # this code is run by collectstatic too, so we cannot
 # assume we have ./static present already
-HTTPROOT="/var/myslice-f4f"
+HTTPROOT="/var/www/myslice"
 # the place to store local data, like e.g. the sqlite db
-DATAROOT="/var/unfold"
+DATAROOT="/var/www/myslice"
 # if not there, then we assume it's from a devel tree
 if not os.path.isdir (os.path.join(HTTPROOT,"static")):
     HTTPROOT=ROOT
@@ -199,6 +199,7 @@ ROOT_URLCONF = 'myslice.urls'
 
 # Python dotted path to the WSGI application used by Django's runserver.
 WSGI_APPLICATION = 'unfold.wsgi.application'
+#WSGI_APPLICATION = 'myslice.wsgi.application'
 
 TEMPLATE_DIRS = [ ]
 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
@@ -290,8 +291,10 @@ CSRF_FAILURE_VIEW = 'manifoldapi.manifoldproxy.csrf_failure'
 # put stuff under static/
 # IA_MEDIA_PREFIX = '/code/'
 
+SESSION_ENGINE = 'django.contrib.sessions.backends.file'
+
 ####SLA#####
 
 SLA_MANAGER_URL = "http://157.193.215.125:4000/sla-service"
 SLA_MANAGER_USER = "normal_user"
-SLA_MANAGER_PASSWORD = "password"
\ No newline at end of file
+SLA_MANAGER_PASSWORD = "password"
index dacebde..07db378 100644 (file)
@@ -17,6 +17,8 @@ import portal.dashboardview
 import portal.homeview
 import portal.newsview
 
+import plugins.cafe.edelberto
+
 from portal.registrationview        import RegistrationView
 from portal.termsview               import TermsView
 
@@ -117,3 +119,10 @@ for aux in auxiliaries:
         urls.append ( url ( r'^%s/'%aux, include ('%s.urls'%aux )))
 
 urlpatterns = patterns(*urls)
+
+# Shibboleth - Edelberto
+urlpatterns += patterns('',
+   url(r'^cafe/', plugins.cafe.edelberto.EdelbertoView.as_view()),
+   #url(r'^cafe/', 'plugins.cafe.edelberto.index'),
+)
+
diff --git a/old.unfold.sqlite3-110314 b/old.unfold.sqlite3-110314
new file mode 100644 (file)
index 0000000..7c680de
Binary files /dev/null and b/old.unfold.sqlite3-110314 differ
index e07637a..0cb9698 100755 (executable)
             //alert("1");\r
         </script>\r
     </div>\r
+</div>\r
diff --git a/portal/actions-100314.py b/portal/actions-100314.py
new file mode 100644 (file)
index 0000000..62f95bc
--- /dev/null
@@ -0,0 +1,602 @@
+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
+import json
+
+from django.contrib.auth.models import User
+from django.template.loader     import render_to_string
+from django.core.mail           import EmailMultiAlternatives
+
+from theme                      import ThemeView
+
+theme = ThemeView()
+
+# Thierry: moving this right into the code so 
+# most people can use myslice without having to install sfa
+# XXX tmp sfa dependency, should be moved to SFA gateway
+#from sfa.util.xrn                import Xrn 
+
+
+# Get the list of authorities
+
+def authority_get_pis(request, authority_hrn):
+    query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
+    results = execute_admin_query(request, query)
+    # NOTE: temporarily commented. Because results is giving empty list. 
+    # Needs more debugging
+    #if not results:
+    #    raise Exception, "Authority not found: %s" % authority_hrn
+    #result, = results
+    #return result['pi_users']
+    return results
+
+def authority_get_pi_emails(request, authority_hrn):
+    pi_users = authority_get_pis(request,authority_hrn)
+    if any(d['pi_users'] == None for d in pi_users):
+        theme.template_name = 'email_default_recipients.txt' 
+        default_email = render_to_string(theme.template, request)
+        default_email = default_email.replace('\n', '')
+        return default_email
+    else:
+        pi_user_hrns = [ hrn for x in pi_users for hrn in x['pi_users'] ]
+        query = Query.get('user').filter_by('user_hrn', 'included', pi_user_hrns).select('user_email')
+        results = execute_admin_query(request, query)
+        return [result['user_email'] for result in results]
+
+def is_pi(wsgi_request, user_hrn, authority_hrn):
+    # XXX could be done in a single query !
+
+    # select pi_authorities from user where user_hrn == "ple.upmc.jordan_auge"
+    query = Query.get('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
+    
+# SFA get record
+
+def sfa_get_user(request, user_hrn, pub):
+    query_sfa_user = Query.get('user').filter_by('user_hrn', '==', user_hrn)
+    result_sfa_user = execute_query(request, query_sfa_user)
+    return result_sfa_user                        
+
+def sfa_update_user(request, user_hrn, user_params):
+    # user_params: keys [public_key] 
+    if 'email' in user_params:
+        user_params['user_email'] = user_params['email']
+    query = Query.update('user').filter_by('user_hrn', '==', user_hrn).set(user_params).select('user_hrn')
+    results = execute_query(request,query)
+    return results
+
+def sfa_add_authority(request, authority_params):
+    query = Query.create('authority').set(authority_params).select('authority_hrn')
+    results = execute_query(request, query)
+    print "sfa_add_auth results=",results
+    if not results:
+        raise Exception, "Could not create %s. Already exists ?" % authority_params['hrn']
+    return results
+
+def sfa_add_user_to_slice(request, user_hrn, slice_params):
+# UPDATE myslice:slice SET researcher=['ple.upmc.jordan_auge','ple.inria.thierry_parmentelat','ple.upmc.loic_baron','ple.upmc.ciro_scognamiglio','ple.upmc.mohammed-yasin_rahman','ple.upmc.azerty'] where slice_hrn=='ple.upmc.myslicedemo'
+    query_current_users = Query.get('slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
+    results_current_users = execute_query(request, query_current_users)
+    slice_params['researcher'] = slice_params['researcher'] | results_current_users
+    query = Query.update('slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
+    results = execute_query(request, query)
+# Also possible but not supported yet
+# UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
+    if not results:
+        raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
+    return results
+
+# Propose hrn
+
+def manifold_add_user(wsgi_request, request):
+    """Add a Manifold user corresponding to a user request.
+
+    Args:
+        wsgi_request: a WSGIRequest instance
+        request (dict): a dictionary containing the user request built from the
+            form.
+
+    Returns:
+        The user_id of the inserted user.
+
+    Raises:
+        ?
+    
+    """
+    USER_CONFIG = '{"firstname": "%(first_name)s", "lastname": "%(last_name)s", "authority": "%(authority_hrn)s"}'
+
+    user_params = {
+        'email'     : request['email'],
+        'password'  : request['password'],
+        'config'    : USER_CONFIG % request,
+        'status'    : 1,
+    }
+
+    query = Query.create('local:user').set(user_params).select('email')
+    results = execute_admin_query(request, query)
+    if not results:
+        raise Exception, "Failed creating manifold user: %s" % user_params['email']
+    result = results[0]
+    return result['email']
+
+def manifold_update_user(request, email, user_params):
+    # user_params: password, config e.g., 
+    query = Query.update('local:user').filter_by('email', '==', email).set(user_params).select('email')
+    results = execute_admin_query(request,query)
+    # NOTE: results remains empty and goes to Exception. However, it updates the manifold DB.
+    # That's why I commented the exception part. -- Yasin 
+    #if not results:
+    #    raise Exception, "Failed updating manifold user: %s" % user_params['email']
+    #result, = results
+    return results
+
+def manifold_add_account(request, account_params):
+    query = Query.create('local:account').set(account_params).select(['user', 'platform'])
+    results = execute_admin_query(request,query)
+    if not results:
+        raise Exception, "Failed creating manifold account on platform %s for user: %s" % (account_params['platform'], account_params['user'])
+    result, = results
+    return result['user_id']
+
+def manifold_update_account(request,user_id,account_params):
+    # account_params: config
+    query = Query.update('local:account').filter_by('platform', '==', 'myslice').filter_by('user_id', '==', user_id).set(account_params).select('user_id')
+    results = execute_admin_query(request,query)
+    return results
+
+#explicitly mention the platform_id
+def manifold_delete_account(request, platform_id, user_id, account_params):
+    query = Query.delete('local:account').filter_by('platform_id', '==', platform_id).filter_by('user_id', '==', user_id).set(account_params).select('user_id')
+    results = execute_admin_query(request,query)
+    return results
+
+
+#not tested
+def manifold_add_platform(request, platform_params):
+    query = Query.create('local:platform').set(platform_params).select(['user', 'platform'])
+    results = execute_admin_query(request,query)
+    if not results:
+        raise Exception, "Failed creating manifold platform %s for user: %s" % (platform_params['platform'], platform_params['user'])
+    result, = results
+    return result['platform_id']
+
+
+def make_request_user(user):
+    request = {}
+    request['type']          = 'user'
+    request['id']            = user.id
+    request['timestamp']     = user.created # XXX in DB ?
+    request['authority_hrn'] = user.authority_hrn
+    request['first_name']    = user.first_name
+    request['last_name']     = user.last_name
+    request['email']         = user.email
+    request['login']         = user.login
+    request['user_hrn']      = user.user_hrn
+    request['public_key']    = user.public_key
+    request['private_key']   = user.private_key
+    return request
+
+def make_request_slice(slice):
+    request = {}
+    request['type'] = 'slice'
+    request['id'] = slice.id
+    request['user_hrn'] = slice.user_hrn
+    request['timestamp'] = slice.created
+    request['authority_hrn'] = slice.authority_hrn
+    request['slice_name'] = slice.slice_name
+    request['number_of_nodes'] = slice.number_of_nodes
+    request['type_of_nodes'] = slice.type_of_nodes
+    request['purpose'] = slice.purpose
+    return request
+
+def make_request_authority(authority):
+    request = {}
+    request['type']                  = 'authority'
+    request['id']                    = authority.id
+    request['site_name']             = authority.site_name
+    request['site_latitude']         = authority.site_latitude
+    request['site_longitude']        = authority.site_longitude
+    request['site_url']              = authority.site_url
+    request['site_authority']        = authority.site_authority
+    request['site_abbreviated_name'] = authority.site_abbreviated_name
+    request['address_line1']         = authority.address_line1
+    request['address_line2']         = authority.address_line2
+    request['address_line3']         = authority.address_line3
+    request['address_city']          = authority.address_city
+    request['address_postalcode']    = authority.address_postalcode
+    request['address_state']         = authority.address_state
+    request['address_country']       = authority.address_country
+    request['authority_hrn']         = authority.authority_hrn
+    request['timestamp']             = authority.created
+    return request
+
+def make_requests(pending_users, pending_slices, pending_authorities):
+    requests = []
+    for user in pending_users:
+        requests.append(make_request_user(user))
+    for slice in pending_slices:
+        requests.append(make_request_slice(slice))
+    for authority in pending_authorities:
+        requests.append(make_request_authority(authority))
+    return requests   
+
+def get_request_by_id(ids):
+    sorted_ids = { 'user': [], 'slice': [], 'authority': [] }
+    for type__id in ids:
+        type, id = type__id.split('__')
+        sorted_ids[type].append(id)
+        
+    if not ids:
+        pending_users  = PendingUser.objects.all()
+        pending_slices = PendingSlice.objects.all()
+        pending_authorities = PendingAuthority.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()
+
+    return make_requests(pending_users, pending_slices, pending_authorities)
+
+def get_requests(authority_hrns=None):
+    print "get_request_by_authority auth_hrns = ", authority_hrns
+    if not authority_hrns:
+        pending_users  = PendingUser.objects.all()
+        pending_slices = PendingSlice.objects.all()
+        pending_authorities = PendingAuthority.objects.all()
+    else:
+        pending_users  = PendingUser.objects.filter(authority_hrn__in=authority_hrns).all()
+        pending_slices = PendingSlice.objects.filter(authority_hrn__in=authority_hrns).all()
+        pending_authorities = PendingAuthority.objects.filter(authority_hrn__in=authority_hrns).all()
+
+    return make_requests(pending_users, pending_slices, pending_authorities)
+
+# XXX Is it in sync with the form fields ?
+
+def portal_validate_request(wsgi_request, request_ids):
+    status = {}
+
+    if not isinstance(request_ids, list):
+        request_ids = [request_ids]
+
+    requests = get_request_by_id(request_ids)
+    for request in requests:
+        # type, id, timestamp, details, allowed -- MISSING: authority_hrn
+        # CAREFUL about details
+        # user  : first name, last name, email, password, keypair
+        # slice : number of nodes, type of nodes, purpose
+        
+        request_status = {}
+
+        if request['type'] == 'user':
+
+            try:
+                create_user(wsgi_request, request)
+                request_status['SFA user'] = {'status': True }
+
+            except Exception, e:
+                 request_status['SFA user'] = {'status': False, 'description': str(e)}
+                       
+#            user_params = {'status':2}
+#            manifold_update_user(request, request['email'], user_params)
+
+            # MANIFOLD user should be added beforehand, during registration
+            #try:
+            #    manifold_user_params = { key: request[key] for key in MANIFOLD_USER_KEYS }
+            #    # XXX # manifold_add_user(manifold_user_params)
+            #    request_status['MySlice user'] = {'status': True }
+            #except Exception, e:
+            #    request_status['MySlice user'] = {'status': False, 'description': str(e)}
+
+            # XXX
+            #manifold_account_params = { key: request[key] for key in MANIFOLD_ACCOUNT_KEYS }
+            #manifold_add_account(manifold_account_params)
+            #request_status['MySlice testbed accounts'] = {'status': False }
+
+        elif request['type'] == 'slice':
+            try:
+                create_slice(wsgi_request, request)
+                request_status['SFA slice'] = {'status': True }
+
+            except Exception, e:
+                request_status['SFA slice'] = {'status': False, 'description': str(e)}
+
+        elif request['type'] == 'authority':
+            try:
+                #hrn = "%s.%s" % (request['authority_hrn'], request['site_authority'])
+                hrn = request['site_authority']
+                # XXX tmp sfa dependency
+                from sfa.util.xrn import Xrn 
+                urn = Xrn(hrn, request['type']).get_urn()
+
+                sfa_authority_params = {
+                    'hrn'        : hrn,
+                    'urn'        : urn,
+                    'type'       : request['type'],
+                    #'pi'        : None,
+                    'enabled'    : True
+                }
+                print "ADD Authority"
+                sfa_add_authority(wsgi_request, sfa_authority_params)
+                request_status['SFA authority'] = {'status': True }
+
+            except Exception, e:
+                request_status['SFA authority'] = {'status': False, 'description': str(e)}
+
+        # XXX Remove from Pendings in database
+
+        status['%s__%s' % (request['type'], request['id'])] = request_status
+
+    return status
+
+
+def validate_action(request, **kwargs):
+    ids = filter(None, kwargs['id'].split('/'))
+    status = portal_validate_request(request, ids)
+    json_answer = json.dumps(status)
+    return HttpResponse (json_answer, mimetype="application/json")
+
+# Django and ajax
+# http://djangosnippets.org/snippets/942/
+
+
+
+#-------------------------------------------------------------------------------
+# REQUESTS - Slices
+#-------------------------------------------------------------------------------
+
+def create_slice(wsgi_request, request):
+    """
+    Arguments:
+        wsgi_request (~ WSGIRequest) : 
+        request (dict) : the slice request in our own dict format
+
+    Raises:
+        Exception
+    """
+    hrn = "%s.%s" % (request['authority_hrn'], request['slice_name'])
+    # XXX tmp sfa dependency
+    from sfa.util.xrn import Xrn 
+    urn = Xrn(hrn, request['type']).get_urn()
+    
+    # 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()
+
+    # XXX We should create a slice with Manifold terminology
+    slice_params = {
+        'slice_hrn'        : hrn, 
+        'slice_urn'        : urn,
+        'slice_type'       : request['type'],
+        'users'            : user_hrns,
+        'slice_enabled'    : True
+    }
+    # ignored in request: id, timestamp,  number_of_nodes, type_of_nodes, purpose
+
+    query = Query.create('slice').set(slice_params).select('slice_hrn')
+    results = execute_query(wsgi_request, query)
+    if not results:
+        raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
+    return results
+
+def create_pending_slice(wsgi_request, request, email):
+    """
+    """
+
+    # Insert an entry in the PendingSlice table
+    s = PendingSlice(
+        slice_name      = request['slice_name'],
+        user_hrn        = request['user_hrn'],
+        authority_hrn   = request['authority_hrn'],
+        number_of_nodes = request['number_of_nodes'],
+        purpose         = request['purpose'],
+    )
+    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])
+        print msg
+        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
+#-------------------------------------------------------------------------------
+
+def manifold_add_reference_user_accounts(wsgi_request, request):
+    """When a new user is created, add reference accounts to the reference platform.
+    """
+    # XXX XXX XXX The rest of this function has to be checked XXX XXX XXX
+
+    # Retrieve user information
+    user_query  = Query().get('local:user')             \
+        .select('user_id', 'config', 'email', 'status') \
+        .filter_by('email', '==', request['email'])
+    user_details = execute_admin_query(wsgi_request, user_query)
+
+    # USER MAIN ACCOUNT != reference
+    #print 'USER MAIN ACCOUNT != reference'
+    list_accounts_query = Query().get('local:account')              \
+        .select('user_id', 'platform_id', 'auth_type', 'config')    \
+        .filter_by('user_id', '==', user_details[0]['user_id'])     \
+        .filter_by('auth_type', '!=', 'reference')
+    list_accounts = execute_admin_query(wsgi_request, list_accounts_query)
+
+    # XXX main_platform is being erased several times ???
+    for account in list_accounts:
+        main_platform_query = Query().get('local:platform')         \
+            .select('platform_id', 'platform')                      \
+            .filter_by('platform_id', '==', account['platform_id'])
+        main_platform = execute_admin_query(wsgi_request, main_platform_query)
+
+    # Add reference accounts on SFA enabled platforms
+    platforms_query = Query().get('local:platform') \
+        .filter_by('disabled', '==', '0')           \
+        .filter_by('gateway_type', '==', 'sfa')     \
+        .select('platform_id', 'gateway_type')
+    platforms = execute_admin_query(wsgi_request, platforms_query)
+    for platform in platforms:
+        #print "add reference to platform ",platform
+        manifold_account_params = {
+            'user_id'       : user_details[0]['user_id'],
+            'platform_id'   : platform['platform_id'],
+            'auth_type'     : 'reference',
+            'config'        : '{"reference_platform": "' + main_platform[0]['platform'] + '"}',
+        }
+        manifold_add_account(wsgi_request, manifold_account_params)
+
+def sfa_create_user(wsgi_request, request):
+    """
+    Arguments:
+        wsgi_request (~ WSGIRequest) : 
+        request (dict) : the user request in our own dict format
+
+    Raises:
+        Exception
+    """
+    from sfa.util.xrn import Xrn 
+
+    auth_pi = request.get('pi', None)
+    auth_pi = list([auth_pi]) if auth_pi else list()
+
+    # We create a user request with Manifold terminology
+    sfa_user_params = {
+        'user_hrn'          : request['user_hrn'],
+        'user_email'        : request['email'],
+        'user_urn'          : Xrn(request['user_hrn'], request['type']).get_urn(),
+        'user_type'         : request['type'],
+        'keys'              : request['public_key'],
+        'user_first_name'   : request['first_name'],
+        'user_last_name'    : request['last_name'],
+        'pi_authorities'    : auth_pi,
+        'user_enabled'      : True
+    }
+
+    query = Query.create('user').set(sfa_user_params).select('user_hrn')
+    results = execute_query(wsgi_request, query)
+    if not results:
+        raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
+    return results
+
+#def ldap_create_user
+
+def create_user(wsgi_request, request):
+    
+    # XXX This has to be stored centrally
+    USER_STATUS_ENABLED = 2
+
+    # NOTE : if we were to create a user directly (just like we create slices,
+    # we would have to perform the steps in create_pending_user too
+
+    # Add the user to the SFA registry
+    sfa_create_user(wsgi_request, request)
+
+    # Update Manifold user status
+    manifold_update_user(wsgi_request, request['email'], {'status': USER_STATUS_ENABLED})
+
+    # Add reference accounts for platforms
+    manifold_add_reference_user_accounts(wsgi_request, request)
+
+def create_pending_user(wsgi_request, request, user_detail):
+    """
+    """
+
+    # Insert an entry in the PendingUser table
+    b = PendingUser(
+        first_name    = request['first_name'],
+        last_name     = request['last_name'],
+        authority_hrn = request['authority_hrn'],
+        email         = request['email'],
+        password      = request['password'],
+        public_key    = request['public_key'],
+        private_key   = request['private_key'],
+        user_hrn      = request['user_hrn'],
+        pi            = '',                         # XXX Why not None ?
+    )
+    b.save()
+
+    # saves the user to django auth_user table [needed for password reset]
+    user = User.objects.create_user(request['email'], request['email'], request['password'])
+
+    # Creating a manifold user
+    user_id = manifold_add_user(wsgi_request, request)
+
+    # Creating a Manifold account on the MySlice platform
+    # Note the JSON representation of public and private keys already includes quotes
+    account_config = {
+        'user_hrn'          : request['user_hrn'],
+        'user_public_key'   : request['public_key'],
+    }
+    if request['private_key']:
+        account_config['user_private_key'] = request['private_key']
+
+    user_id = user_detail['user_id'] + 1 # the user_id for the newly created user in local:user
+
+    # XXX TODO: Require a myslice platform
+    # ALERT: this will disapear with ROUTERV2 of Manifold
+    # We have to consider the case where several registries can be used
+    # Removed hardcoded platform = 5
+    # This platform == 'myslice' is a TMP FIX !!
+    try:
+        reg_platform_query = Query().get('local:platform') \
+            .filter_by('platform', '==', 'myslice')           \
+            .select('platform_id')
+        reg_platform = execute_admin_query(wsgi_request, reg_platform_query)
+
+        registry_platform_id = reg_platform[0]['platform_id']
+        account_params = {
+            'platform_id'   : reg_platform_id, # XXX ALERT !!
+            'user_id'       : user_id, 
+            'auth_type'     : request['auth_type'], 
+            'config'        : json.dumps(account_config),
+        }
+        manifold_add_account(wsgi_request, account_params)
+    except Exception, e:
+        print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
+
+    try:
+        # Send an email: the recipients are the PI of the authority
+        # If No PI is defined for this Authority, send to a default email (different for each theme)
+        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+        
+        theme.template_name = 'user_request_email.html'
+        html_content = render_to_string(theme.template, request)
+    
+        theme.template_name = 'user_request_email.txt'
+        text_content = render_to_string(theme.template, request)
+    
+        theme.template_name = 'user_request_email_subject.txt'
+        subject = render_to_string(theme.template, request)
+        subject = subject.replace('\n', '')
+    
+        theme.template_name = 'email_default_sender.txt'
+        sender =  render_to_string(theme.template, request)
+        sender = sender.replace('\n', '')
+    
+        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"
index 3479c02..da537cb 100644 (file)
@@ -507,6 +507,138 @@ def sfa_create_user(wsgi_request, request):
         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
     return results
 
+def ldap_create_user(wsgi_request, request, user_detail):
+    """
+    Populating LDAP withuser data - Edelberto 10/03/2014
+    """
+    # import needed modules
+    import ldap
+    import ldap.modlist as modlist
+
+    # Open a connection
+    # XXX We need to create this in settings
+    # ldap.open is deprecated!
+    #l = ldap.open("127.0.0.1")
+    l = ldap.initialize('ldap://127.0.0.1:389')
+
+    # you should  set this to ldap.VERSION2 if you're using a v2 directory
+    l.protocol_version = ldap.VERSION3
+
+    # Bind/authenticate with a user with apropriate rights to add objects
+    # XXX Now we set the force rootd but after we need to set this in settings file for could change the dn and password of root
+    l.simple_bind_s("cn=Manager,dc=br","fibre")
+
+    # The dn of our new entry/object
+    #dn="uid=addtest@uff.br,ou=people,o=uff,dc=br"
+
+    # we need to create the dn entry
+    # Receiving an email address, how can we split and mount it in DN format?
+    #mail = "debora@uff.br"
+    mail = request['email']
+    login = mail.split('@')[0]
+    org = mail.split('@')[1]
+    o = org.split('.')[-2]
+    dc = org.split('.')[-1]
+
+    # DN format to authenticate - IMPORTANT!
+    #FIBRE-BR format
+    dn = "uid="+mail+",ou=people,o="+o+",dc="+dc
+
+    # DEBUG
+    print "dn:"+dn
+    print request['password']
+
+    # Creating a unique uidNumber - Necessary for experiments
+    # Was defined to began in 100000
+    unique = int(user_detail['user_id']) + 100000
+    #unique = int(unique)
+    print unique
+
+    # A dict to help build the "body" of the object
+    attrs = {}
+    attrs['objectclass'] = ['person','inetOrgPerson','posixAccount','eduPerson','brPerson','schacPersonalCharacteristics','fibre', 'ldapPublicKey']
+    # XXX Converting all unicodes to string
+    attrs['uid'] = mail.encode('utf-8')
+    attrs['cn'] = request['first_name'].encode('latin1')
+    attrs['sn'] = request['last_name'].encode('latin1')
+    # XXX we need to set a unique uidNumber. How?
+    attrs['uidNumber'] = str(unique)
+    attrs['gidNumber'] = '500'
+    attrs['homeDirectory'] = "/home/"+org+"/"+mail
+    attrs['homeDirectory'] = attrs['homeDirectory'].encode('utf-8')
+    attrs['mail'] = mail.encode('utf-8')
+    attrs['eppn'] = mail.encode('utf8')
+    attrs['userPassword'] = request['password'].encode('utf-8')
+    attrs['sshPublicKey'] = request['public_key'].encode('utf-8')
+    # XXX We really set TRUE for those attributes? 
+    #attrs['userEnable'] = 'TRUE'
+    # set FALSE and change after when the user is validated
+    attrs['userEnable'] = 'FALSE'
+    attrs['omfAdmin'] = 'TRUE'
+
+    # Convert our dict to nice syntax for the add-function using modlist-module
+    ldif = modlist.addModlist(attrs)
+
+    # DEBUG
+    print attrs['userPassword']
+    print attrs['cn']
+    print attrs['sn']
+    print attrs['homeDirectory']
+    #print ldif
+
+    # Do the actual synchronous add-operation to the ldapserver
+    l.add_s(dn,ldif)
+
+    # Its nice to the server to disconnect and free resources when done
+    l.unbind_s()
+
+    return ldif
+
+def ldap_modify_user(wsgi_request, request):
+    #Modify entries in an LDAP Directory
+
+    #Synchrounous modify
+    # import needed modules
+    import ldap
+    import ldap.modlist as modlist
+
+    # Open a connection
+    l = ldap.initialize("ldap://localhost:389/")
+
+    # Bind/authenticate with a user with apropriate rights to add objects
+    l.simple_bind_s("cn=Manager,dc=br","fibre")
+
+    # we need to create the dn entry
+    # Receiving an email address, how can we split and mount it in DN format?
+    #mail = "debora@uff.br"
+    mail = request['email']
+    login = mail.split('@')[0]
+    org = mail.split('@')[1]
+    o = org.split('.')[-2]
+    dc = org.split('.')[-1]
+
+    # DN format to authenticate - IMPORTANT!
+    #FIBRE-BR format
+    dn = "uid="+mail+",ou=people,o="+o+",dc="+dc
+
+    # The dn of our existing entry/object
+    #dn="uid=mario@uff.br,ou=people,o=uff,dc=br"
+
+    # Some place-holders for old and new values
+    old = {'userEnable':'FALSE'}
+    new = {'userEnable':'TRUE'}
+
+    # Convert place-holders for modify-operation using modlist-module
+    ldif = modlist.modifyModlist(old,new)
+
+    # Do the actual modification
+    l.modify_s(dn,ldif)
+
+    # Its nice to the server to disconnect and free resources when done
+    l.unbind_s()
+
+    return ldif
+
 def create_user(wsgi_request, request):
     
     # XXX This has to be stored centrally
@@ -514,16 +646,34 @@ def create_user(wsgi_request, request):
 
     # NOTE : if we were to create a user directly (just like we create slices,
     # we would have to perform the steps in create_pending_user too
-
+    
+    # Edelberto - I put this more below
     # Add the user to the SFA registry
-    sfa_create_user(wsgi_request, request)
+    #sfa_create_user(wsgi_request, request)
 
     # Update Manifold user status
     manifold_update_user(wsgi_request, request['email'], {'status': USER_STATUS_ENABLED})
 
     # Add reference accounts for platforms
     manifold_add_reference_user_accounts(wsgi_request, request)
+    
+# Add the user to the SFA registry
+    sfa_create_user(wsgi_request, request)
 
+    '''   
+    # LDAP update user userEnabled = True
+    try:
+        mail = request['email']
+        login = mail.split('@')[0]
+        org = mail.split('@')[1]
+        o = org.split('.')[-2]
+        dc = org.split('.')[-1]
+        # To know if user is a LDAP user - Need to has a 'dc' identifier
+        if dc == 'br' or 'eu':
+            ldap_modify_user(wsgi_request, request)
+    except Exception, e:
+        "LDAP create user failed"
+    '''
 def create_pending_user(wsgi_request, request, user_detail):
     """
     """
@@ -589,7 +739,6 @@ def create_pending_user(wsgi_request, request, user_detail):
             .filter_by('platform', '==', 'myslice')           \
             .select('platform_id')
         reg_platform = execute_admin_query(wsgi_request, reg_platform_query)
-
         reg_platform_id = reg_platform[0]['platform_id']
         account_params = {
             'platform_id'   : reg_platform_id, # XXX ALERT !!
@@ -599,7 +748,11 @@ def create_pending_user(wsgi_request, request, user_detail):
         }
         manifold_add_account(wsgi_request, account_params)
     except Exception, e:
-        print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
+       print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
+
+    # Add user to LDAP userEnabled = False
+    # Not more here. Create before directly to the registrationview.py
+    # After we change userEnable = TRUE when validate the user
 
     try:
         # Send an email: the recipients are the PI of the authority
index 4576431..c4a99ca 100644 (file)
@@ -34,9 +34,16 @@ class HomeView (FreeAccessView, ThemeView):
         
         username = request.POST.get('username')
         password = request.POST.get('password')
+       
+        # LDAP form - If FIBRE, then get the possibilite to authenticate using usernameldap
+        #if self.theme == 'fibre':
+        usernameldap = request.POST.get('usernameldap')
+        token = {'usernameldap': usernameldap, 'username': username ,'password': password, 'request': request}    
+        #else:
         
-        # pass request within the token, so manifold session key can be attached to the request session.
-        token = {'username': username, 'password': password, 'request': request}    
+        # Follow original code
+        ## pass request within the token, so manifold session key can be attached to the request session.
+        #token = {'username': username, 'password': password, 'request': request}    
 
         # our authenticate function returns either
         # . a ManifoldResult - when something has gone wrong, like e.g. backend is unreachable
@@ -104,13 +111,14 @@ class HomeView (FreeAccessView, ThemeView):
             # XXX Something like an invalid session seems to make the execute fail sometimes, and thus gives an error on the main page
             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')
+            if platform_details:
+                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"
index 4e3b040..199c173 100644 (file)
@@ -17,7 +17,9 @@ from manifoldapi.manifoldapi    import execute_admin_query
 from manifold.core.query        import Query
 
 from portal.models              import PendingUser
-from portal.actions             import create_pending_user
+#from portal.actions             import create_pending_user
+# Edelberto - LDAP
+from portal.actions             import create_pending_user, ldap_create_user
 
 from myslice.theme import ThemeView
 
@@ -38,7 +40,7 @@ class RegistrationView (FreeAccessView, ThemeView):
         """
         errors = []
 
-        authorities_query = Query.get('authority').select('name', 'authority_hrn')
+        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)
@@ -57,6 +59,9 @@ class RegistrationView (FreeAccessView, ThemeView):
             current_site = Site.objects.get_current()
             current_site = current_site.domain
 
+            #authorities_query = Query.get('authority').select('name', 'authority_hrn')
+            #authorities = execute_admin_query(wsgi_request, authorities_query)
+    
             for authority in authorities:
                 if authority['name'] == wsgi_request.POST.get('org_name', ''):
                     authority_hrn = authority['authority_hrn']     
@@ -149,8 +154,25 @@ class RegistrationView (FreeAccessView, ThemeView):
                 user_request['public_key']  = file_content
                 
             if not errors:
+                '''
+                try:
+                    # verify if is a  LDAP 
+                    mail = user_detail['email']
+                    login = mail.split('@')[0]
+                    org = mail.split('@')[1]
+                    o = org.split('.')[-2]
+                    dc = org.split('.')[-1]
+                    # To know if user is a LDAP user - Need to has a 'dc' identifier
+                    if dc == 'br' or 'eu':
+                        # LDAP insert directly - but with userEnable = FALSE
+                        ldap_create_user(wsgi_request, user_request, user_detail)
+                   
+                except Exception, e:
+                    print "LDAP: problem em access the LDAP with this credentail" 
+                '''
                 create_pending_user(wsgi_request, user_request, user_detail)
                 self.template_name = 'user_register_complete.html'
+            
                 return render(wsgi_request, self.template, {'theme': self.theme}) 
 
         else:
index 222a28e..bd711d5 100644 (file)
@@ -170,7 +170,7 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             'exp_url': exp_url,
             'pi': pi,
             'authority_name': authority_name,        
-            'authority_hrn': user_authority,        
+            'authority_hrn': user_authority,
             'cc_myself': True,
             'authorities': authorities,
             'theme': self.theme,
index 2d603b4..9db52c0 100644 (file)
@@ -22,6 +22,12 @@ from plugins.googlemap                  import GoogleMap
 from plugins.filter_status              import FilterStatusPlugin
 from plugins.testbeds                   import TestbedsPlugin
 from plugins.scheduler2                 import Scheduler2
+
+# Bristol plugin
+from plugins.univbrisfoam       import UnivbrisFoam
+from plugins.univbrisfv         import UnivbrisFv
+from plugins.univbrisfvf        import UnivbrisFvf
+
 from plugins.columns_editor             import ColumnsEditor
 from plugins.sladialog                  import SlaDialog
 from plugins.lists.simplelist           import SimpleList
@@ -42,6 +48,11 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         metadata = page.get_metadata()
         page.expose_js_metadata()
 
+        # Bristol
+        univbrisfoam_query=Query().get('ofelia-bristol-of:resource').select('urn')
+        page.enqueue_query(univbrisfoam_query)
+
+
         resource_md = metadata.details_by_object('resource')
         resource_fields = [column['name'] for column in resource_md['column']]
 
@@ -234,6 +245,50 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             query           = main_query,
             username            = request.user,
         )
+
+        # Bristol plugin
+        univbrisfoamlist = UnivbrisFoam(
+            page  = page,
+            title = 'univbris_foam_ports_selection',
+            domid = 'univbris_foam_ports_selection',
+            query = univbrisfoam_query,
+            query_all = univbrisfoam_query,
+            checkboxes = False,
+            datatables_options = {
+                'iDisplayLength': 10,
+                'bLengthChange' : True,
+                'bAutoWidth'    : True,
+                },
+        )
+
+        #plugin which manages the different flowspaces that the user creates, and also sends flowspaces to manifold
+        univbrisfvlist = UnivbrisFv(
+                page  = page,
+                title = 'univbris_flowspace_selection',
+                domid = 'univbris_flowspace_selection',
+                query = None,
+                query_all = None,
+                datatables_options = {
+                    'iDisplayLength': 5,
+                    'bLengthChange' : True,
+                    'bAutoWidth'    : True,
+                    },
+            )
+
+        #plugin which allows the definition of a single flowspace
+        univbrisfvform = UnivbrisFvf(
+                page  = page,
+                title = 'univbris_flowspace_form',
+                domid = 'univbris_flowspace_form',
+                query = None,
+                query_all = None,
+                datatables_options = {
+                    'iDisplayLength': 3,
+                    'bLengthChange' : True,
+                    'bAutoWidth'    : True,
+                    },
+            )
+
             
 
         # --------------------------------------------------------------------------
@@ -284,6 +339,13 @@ class SliceResourceView (LoginRequiredView, ThemeView):
 
         template_env['map_resources'] = map_resources.render(self.request)
         template_env['scheduler'] = resources_as_scheduler2.render(self.request)
+
+        # Bristol plugin
+        template_env['resources'] = univbrisfoamlist.render(self.request)
+        template_env['flowspaces']= univbrisfvlist.render(self.request)
+        template_env['flowspaces_form']= univbrisfvform.render(self.request)
+
+
 #        template_env['pending_resources'] = pending_resources.render(self.request)
         template_env['sla_dialog'] = '' # sla_dialog.render(self.request)
         template_env["theme"] = self.theme
diff --git a/portal/static/css/fibre.css b/portal/static/css/fibre.css
new file mode 100644 (file)
index 0000000..639b040
--- /dev/null
@@ -0,0 +1,696 @@
+@import url("../fonts/opensans_bold_macroman/stylesheet.css");
+
+html { height: 100% }
+
+body {
+    background-color:white;
+    color:black;
+    margin:0;
+    padding:0;
+    height: 100%;
+}
+a, a:active, a:focus {
+    outline: 0;
+    text-decoration:none;
+}
+
+h1 {
+    border-bottom:1px solid #DDDDDD;
+    padding:0 0 0 0;
+    margin:15px 0 15px 0;
+    font-size:14pt;
+}
+h1 img {
+    vertical-align:middle;
+    margin-bottom:4px;
+    margin-right:10px;
+}
+h2 {
+    font-size:14pt;
+    color:#333333;
+}
+h3 {
+    font-size:13pt;
+    color:#201E62;
+}
+input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
+    min-width:260px;
+    padding:6px;
+    border:1pt solid #22606D;
+    vertical-align:bottom;
+    border-radius:0;
+}
+
+textarea {
+    padding:6px;
+    border:1pt solid #22606D !important;
+    border-radius:0 !important;
+}
+
+span.label {
+    font-size:11pt;
+    color:gray;
+    font-weight:normal;
+    padding:0;
+}
+div.el {
+    padding-bottom:15px;
+}
+div.breadcrumbs {
+    margin:15px 0;
+    color:gray;
+    font-size:10pt;
+}
+/* buttons */
+button.btn, input.btn {
+    padding:6px 10px;
+    border-radius:5px;
+    font-size:10pt;
+    font-weight:normal;
+}
+button.btn span.glyphicon {
+    margin-right:6px;
+}
+button.btn-default {
+    border-bottom:3px solid #cccccc;
+}
+button.btn-default:hover {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:3px solid #ADADAD;
+}
+button.btn-default:active {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:1px solid #ADADAD;
+    margin-top:2px;
+    box-shadow:none;
+}
+button.btn-primary {
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:hover {
+    box-shadow:none;
+    background-color:#428bca;
+    border:1px solid #357ebd;
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:active {
+    box-shadow:none;
+    border-bottom:1px solid #3071A9;
+    margin-top:2px;
+}
+button.btn-danger {
+    border-bottom:3px solid #A13F3A;
+}
+button.btn-danger:hover {
+    box-shadow:none;
+    background-color:#d9534f;
+    border:1px solid #d43f3a;
+    border-bottom:3px solid #A13F3A;
+}
+button.btn-danger:active {
+    border:1px solid #d43f3a;
+    box-shadow:none;
+    margin-top:2px;
+}
+button.btn-onelab, input.btn-onelab {
+    border:0;
+    border-bottom:3px solid #760073;
+    background-color:#302562;
+    color:white;
+}
+button.btn-onelab:hover, input.btn-onelab:hover {
+    border:0;
+    border-bottom:3px solid #760073;
+    background-color:#302562;
+    color:white;
+}
+button.btn-onelab:active, input.btn-onelab:active {
+    box-shadow:none;
+    border-bottom:1px solid #760073;
+    margin-top:2px;
+}
+
+.container-resource button {
+    padding:2px 4px;
+    border-radius:3px;
+    font-size:9pt;
+    font-weight:normal;
+}
+.container-resource select,.container-resource option, .container-resource input {
+    padding:2px 4px;
+    font-size:9pt;
+}
+.badge {
+    font-size:9pt;
+    margin-left:4px;
+}
+/***** Notifications *****/
+.warning {
+    border: 1px solid red;
+    margin: 20px 60px;
+    padding: 10px 20px;
+    color: red;
+    background-color: #f2dbdb;
+    text-align: center;
+}
+
+/* HOME DASHBOARD */
+div#home-dashboard {
+    color:black;
+    margin:0 auto 25px auto;
+}
+div#home-dashboard table {
+    margin:25px;
+    width:100%;
+}
+div#home-dashboard table td {
+    text-align:center;
+    padding:15px 0;
+    width:33%;
+}
+div#home-dashboard table tr:first-child td {
+    font-size:12pt;
+    font-weight:bold;
+    color:#270A5A;
+}
+div#home-dashboard table tr:last-child td {
+    vertical-align:top;
+    padding:25px 0;
+}
+div#home-dashboard table tr:last-child td.logged-in {
+    border-right:1px solid #DDDDDD;
+    padding:25px;
+}
+div#home-dashboard table tr:last-child td.support {
+    border-left:1px solid #DDDDDD;
+    padding:25px;
+}
+div#home-dashboard table tr:last-child td:first-child {
+}
+div#home-dashboard table tr:last-child td:last-child {
+    border-right:0;
+}
+div#home-dashboard table tr:last-child td.logged-in div {
+    text-align:left;
+    padding:25px 0;
+}
+div#home-dashboard table tr:last-child td.support div {
+    text-align:left;
+    padding:25px 0;
+}
+div#home-dashboard div.login-widget {
+    padding:20px;
+}
+div#home-dashboard table td.support {
+}
+div#home-dashboard table td.support a {
+}
+div#home-dashboard table td.support a:hover {
+    text-decoration:none;
+}
+
+div#home-dashboard div#manager {
+    display:none;
+}
+
+div#home-dashboard div#home-slice-list {
+    margin:25px 0;
+    padding:0 25px;
+    text-align:left;
+}
+div#home-dashboard div#home-slice-list ul {
+    list-style: none;
+    padding:0;
+    margin:0;
+}
+div#home-dashboard div#home-slice-list li {
+    
+}
+
+/**/
+
+/**/
+/* WELL */
+div.well {
+}
+/**/
+/* TABLE */
+table.table {
+    margin:0;
+}
+table.table thead {
+    padding:0;
+}
+table.table tbody {
+    padding:0;
+}
+table.table tr {
+    padding:0;
+}
+table.table td {
+    padding:0;
+}
+/* INSTITUTION */
+div#institution {
+    color:black;
+}
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+
+
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+
+
+
+/* TICKET REQUEST */
+div#ticket-request {
+    color:black;
+}
+.form-hint {
+    font-size:11pt;
+    font-style:italic;
+    color:gray;
+}
+div#ticket-request p {
+    margin:20px 0;
+}
+
+ul.nav-tabs {
+    margin:0 0 15px 0;
+}
+ul.nav-tabs ul {}
+ul.nav-tabs li {}
+
+ul.nav-section li a {
+    color:black;
+    border-bottom:0;
+}
+ul.nav-section li:first-child {
+    padding:0;
+}
+ul.nav-section li:first-child a {
+}
+ul.nav-section li:first-child.active a {
+}
+
+ul.nav-resources {
+    margin:15px 0;
+}
+ul.nav-resources a {
+    padding: 4px 10px 5px 10px;
+}
+
+/* SLICE VIEW */
+div.container-resource, div.container-slice {
+    padding-right:15px;
+    padding-left:15px;
+}
+.table th {
+    border-top:0 !important;
+}
+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;
+}
+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;
+}
+a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus {
+    -moz-border-radius: 0;
+    border-radius: 0;
+    font-weight: bold;
+    color:black;
+    background-color:#F5F5F5;
+    border-left:2pt blue solid;
+}
+
+a.list-group-item:hover {
+    -moz-border-radius: 0;
+    border-radius: 0;
+    border-left:2pt blue solid;
+}
+a.list-group-item p.list-group-item-text {
+    -moz-border-radius: 0;
+    border-radius: 0;
+    font-size:9pt;
+    font-style:italic;
+    font-weight: normal;
+    color: black !important;
+}
+
+span.sl-resources {
+    font-size:9pt;
+    color:gray;
+}
+a.sl-resources, a.sl-resources:hover {
+    font-size:9pt;
+    border:0;
+    padding:2px 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+}
+a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
+    border:0;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+}
+
+div#slice-info {
+    margin-top:25px;
+}
+div#slice-info table {
+    width:100%;
+    margin:0 auto;
+}
+div#slice-info table td:first-child {
+    text-align:right;
+    font-weight:bold;
+    padding-right:15px;
+}
+div#slice-info td {
+    padding:5px;
+}
+
+/* SLICE VIEW sections */
+.slice-sections, .slice-pending {
+    margin:0;
+    padding:0;
+}
+.slice-sections ul, .slice-pending ul {
+    margin:0;
+    padding:0;
+}
+.slice-pending ul {
+    width:400px;
+    margin:0 auto 15px auto;
+}
+.slice-sections li {
+    text-align:left;
+    margin:0;
+    padding:0;
+}
+.slice-pending li {
+    padding-right:15px;
+}
+.slice-sections li a, .slice-pending li a {
+    font-size:14px;
+    color:black;
+    padding:0;
+}
+.slice-sections li.active a, .slice-pending li.active a  {
+    color:#201E62;
+    background-color:#EFEFEF;
+    text-decoration:underline;
+    padding:0;
+}
+.slice-sections ul.nav-pills li a:hover, .slice-pending ul.nav-pills li a:hover {
+    text-decoration:underline;
+    background-color:#EFEFEF;
+    color:black;
+}
+.slice-sections ul.nav-pills li.active, .slice-pending ul.nav-pills li.active {
+
+}
+.slice-sections li:first-child, .slice-sections li:first-child a {
+    color:#201E62;
+    font-weight:bold;
+}
+.slice-experiment {
+    text-align:right;
+    padding:0;
+}
+.slice-experiment button {
+    margin:3px 0 0 0;
+    background-color:#CC4125;
+    color:white;
+}
+
+.slice-pending {
+}
+.slice-pending button {
+    font-size:9pt;
+    margin:-2px 0 0 0;
+    padding:3px 5px;
+}
+.slice-pending button.apply {
+}
+.slice-pending button.clear {
+}
+tr.active, tr.active td {
+    background-color:#FFFFCC !important;
+}
+div.dataTables_filter label{
+    float:left;
+    width:400px;
+}
+
+/* HEADER */
+
+
+.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;
+  background-color:white;
+  margin-bottom: 35px;
+}
+
+div.navigation {
+    
+}
+div.navigation ul {
+    margin:26px 0 0 0;
+    padding:0;
+    display: inline-block;
+    list-style-type: none;
+    white-space: nowrap;
+}
+
+div.navigation li {
+    color:#0C0047;
+    font-family:open_sansbold, sans-serif;
+    font-size:9pt;
+    font-weight:normal;
+    line-height:0.8em;
+    letter-spacing:0.4pt;
+    list-style:none;
+    float:left;
+    padding:0 15px;
+    margin:0;
+    text-transform:uppercase;
+}
+div.navigation li:hover {
+}
+div.navigation li a {
+    color:#0C0047;
+}
+div.navigation li a:hover, div.navigation li a.current {
+    color:#760073;
+    text-decoration:none;
+}
+
+div.navigation li:last-child {
+    margin-right:0;
+}
+
+
+div.navigation .dropdown-menu {
+    color:black;
+    -moz-box-shadow:    1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    -webkit-box-shadow: 1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    box-shadow:         1px 1px 0px 0 rgba(58, 48, 100,0.8);
+    border-radius:2px;
+    padding:0 5px 5px 5px;
+    margin-top:5px;
+    margin-left:20px;
+}
+div.navigation .dropdown-menu ul {
+    margin:0;
+    padding:15px 5px 5px 5px;
+    display:list-item;
+}
+div.navigation .dropdown-menu li {
+    margin:0 10px 0 0;
+    padding:0 0 8px 0;
+    display:list-item;
+    float:none;
+    text-transform: none;
+}
+
+div.navigation .dropdown-menu a {
+    font-family:Helvetica,sans-serif;
+    font-size:10pt;
+    color:black;
+}
+div.navigation .dropdown-menu li.title {
+    margin-bottom:10px;
+}
+div.navigation .dropdown-menu li.title a {
+    font-family:open_sansbold, sans-serif;
+}
+
+
+div.navigation .dropdown-menu li:first-child {
+    border-bottom:1px solid white;
+    padding-bottom:5px;
+     
+}
+
+div.secondary {
+    text-align:right;
+}
+
+div.secondary ul {
+   margin:6px 0 0 0;
+   padding:0;
+}
+
+div.secondary li {
+    font-size:9pt;
+    display:inline;
+    list-style:none;
+    margin:0px;
+    padding:0;
+    margin-right:15px;
+    color:#747474;
+    letter-spacing:0.4px;
+}
+div.secondary li:last-child {
+    margin-right:0;
+}
+div.secondary li a {
+    color:#747474;
+}
+div.secondary li a:hover {
+    text-decoration:none;
+}
+div.secondary .button {    
+    width:300px;
+    margin-top:15px;
+}
+div.secondary .account {
+    margin-top:10px;
+    padding:0;
+    font-size:9pt;
+    color:gray;
+    text-align:right;
+}
+div.secondary .account span {
+    font-size:8pt;
+}
+div.secondary .account a {
+    color:black;
+}
+div.home {
+    font-size:11pt;
+    line-height:1.2em;
+    letter-spacing:0.3pt;
+    min-height:500px;
+    background-image: url('../img/optical_fibre.jpg');
+    background-repeat:no-repeat;
+    background-size:cover;
+    background-position:center top;
+    background-color:#013ADF;
+    padding:100px 0;
+}
+div.home h2 {
+    color:white;
+    line-height:1.2em;
+    font-size:18pt;
+}
+div.home h3 {
+    color:white;
+    line-height:1.4em;
+}
+div.dashboard {
+    text-align:center;
+}
+div.dashboard div {
+    margin:25px 0;
+}
+div.dashboard ul {
+    text-align:left;
+    margin-left:24px;
+    list-style:none;
+}
+div.registration-form {
+    padding-top:150px;
+    text-align:center;
+}
+
+.login-form input {
+    width:320px;
+}
+.login-form input[type=submit] {
+    width:108px;
+}
+
+.login-submit {
+    vertical-align:middle;
+    padding:0;
+}
+.lost-password {
+    font-size:10pt;
+    color:black;
+    text-align:right;
+    padding:0px;
+}
+.lost-password a {
+    color:white;
+    text-shadow:0.5px 0.5px black;
+}
+.login-signup {
+    font-size:12pt;
+    color:white;
+    text-shadow:0.5px 0.5px black;
+    margin-top:45px;
+    padding:5px 0 0 4px;
+    
+}
+.login-signup a {
+    color:white;
+    text-shadow:0.5px 0.5px black;
+    padding-bottom:2px;
+    border-bottom:2pt solid white;
+}
+.login-signup a:hover {
+    text-decoration:none;
+}
+.login-signup button {
+    padding:8px;
+    border:0;
+    border-bottom:2px solid #540086;
+    background-color:#302562;
+    color:white;
+    width:100px;
+    border-radius:5px;
+    font-size:12pt;
+}
+div.slogan {
+    text-align:center;
+    color:white;
+    padding-top:60px;
+    text-shadow: 1px 1px #013540;
+}
diff --git a/portal/static/css/onelab_edelberto.css b/portal/static/css/onelab_edelberto.css
new file mode 100644 (file)
index 0000000..797d79c
--- /dev/null
@@ -0,0 +1,457 @@
+/* @override unfold/static/css/plugin.css */
+
+/*-------------------------------- MARKO'S STYLES -----*/
+
+/* GENERAL */
+
+a, a:visited {
+    color: rgb(13, 187, 255) !important;
+    text-decoration: none !important;
+}
+
+a:hover {
+    color: blue !important;
+    text-decoration: none !important;
+}
+
+.container {
+    /*padding: 0 !important;*/
+    padding-top: 60px !important;
+    color: #fff;
+/*    background: url(http://new.fit-equipex.fr/images/background.jpg) no-repeat; */
+    background-color: rgb(237, 241, 243);
+    margin: 0;
+    width: 100%;
+    max-width: 100%;
+    min-height: 100%;
+    height: 100%;
+}
+
+.container h1, .container h2 {
+    color: #fff !important;
+}
+
+.navbar-brand {
+    padding: 5px !important;
+}
+
+.nav {
+    padding-top: 30px !important;
+    padding-left: 20px !important;
+}
+
+.navbar-default {
+    background-color: #fff !important;
+}
+
+p.login-status {
+    color: blue !important;
+}
+
+div.plugin-outline-complete, 
+div.plugin-outline-body {
+    border: 0px solid;
+    border-radius: 0;
+    border-color: #ccc;
+    -webkit-transition: padding 200ms ease-out;
+    -moz-transition: padding 200ms ease-out;
+    -o-transition: padding 200ms ease-out;
+    transition: padding 0.2s ease-out;
+    padding: 20px;
+    margin: 0;
+}
+/*
+div.plugin-outline-complete:hover, 
+div.plugin-outline-body:hover {
+    padding: 80px 80px 120px 80px; 
+}
+*/
+a.plugin-tooltip { 
+    font-size: 130%;
+    font-style: normal;
+    font-weight: bold;
+    padding: 5px;
+    color: #333;
+    font-family: Ubuntu, Arial, sans-serif;
+    text-transform: uppercase;
+}
+
+a.plugin-tooltip:hover { 
+    color: #fff; 
+    text-decoration: none;
+}
+
+
+
+/* LIST VIEW */
+div.well-lg {
+    background-color: rgba(168, 32, 202, 0.5) !important;
+}
+div.onelab-title {
+    background-color: #3A5FCD !important;
+    /*background-color: rgba(168, 32, 202, 0.5) !important;*/
+}
+div.well {
+    /*background-color: rgba(0, 0, 0, 0.5) !important;*/
+    background-color: #fff !important;
+    color: rgb(37, 37, 37) !important;
+}
+h2.well.well-lg {
+    border-radius:0;
+    border: 0;
+    font-family: Ubuntu, arial, sans-serif;
+    /* text-transform: ; */
+    font-weight: normal;
+    font-size: 40px;
+    /* color: #30196d; */
+    color: white;
+    margin-bottom: 0px;
+    margin-top: 0;
+    padding: 40px;
+    opacity: 1;
+    text-align: center;
+    background-color: #30196d;
+}
+
+#complete-resources {
+/*    background-color: #92f79e !important; */
+    background-color: #B8B2FF !important;
+}
+
+#complete-filters {
+/*    background-color: #4af25d; */
+    background-color: #add7ff;
+}
+
+#complete-users {
+/*    background-color: #ff7394 !important; */
+    background-color: #add7ff !important;
+}
+/*
+#complete-measurements {
+    background-color: !important;
+}
+*/
+#complete-pending {
+/*    background-color: #add7ff !important; */
+    background-color: #B8B2FF !important;
+
+}
+
+#complete-customize-resources {
+    background-color: #efdfdf;
+}
+
+#complete-msgs-pre {
+    background-color: #ccc;
+}
+
+#complete-resources, 
+#complete-filters, 
+#complete-users, 
+#complete-measurements,
+#complete-pending,
+#complete-customize-resources,
+#complete-msgs-pre {
+    opacity: 1;
+    text-align: center;
+    color: #333;
+}
+
+#complete-resources:hover, 
+#complete-filters:hover, 
+#complete-users:hover, 
+#complete-measurements:hover,
+#complete-pending:hover,
+#complete-customize-resources:hover,
+#complete-msgs-pre:hover {
+    opacity: 1;
+}
+
+.nav.nav-tabs {
+    font-family: Ubuntu, Arial, sans-serif;
+    border: 0 !important;
+    border-bottom: 3px solid #fff !important;
+    margin-bottom: 40px;
+}
+
+.nav.nav-tabs li.active a {
+    color: #572bc9;
+    border-left: 0px solid #572bc9;
+    border-top: 0px solid #572bc9;
+    border-right: 0px solid #572bc9;
+}
+
+.nav.nav-tabs li a {
+    color: #333;
+    border: 0 !important;
+    margin-right: 5px;
+}
+
+.nav.nav-tabs li a:hover {
+    color: #333;
+    background: #572bc9;
+    color: #fff;
+    border: 0 !important;
+}
+
+
+
+/* if window enlarged wider than background picture */
+body {
+    background: rgb(237, 241, 243) !important;
+    /*background: black !important;*/
+}
+
+/* TOPMENU.CSS */
+
+/* Thierry : turning this off
+body {
+    *//* background: #30196d !important; *//*
+    background: black !important;
+    padding-top: 60px;
+    padding-bottom: 0px;
+}
+Thierry */
+
+/* Thierry : turning this off
+div.topmenu { 
+    padding-top: 0px;
+    font-family: Ubuntu, Arial, sans-serif;
+    font-weight: bold;
+    background: #fff;
+    -webkit-box-shadow: 0px 10px 10px rgba(50, 50, 50, 0.44);
+    -moz-box-shadow:    0px 10px 10px rgba(50, 50, 50, 0.44);
+    box-shadow:         0px 10px 10px rgba(50, 50, 50, 0.44);
+}
+Thierry */
+
+/* Thierry : turning this off
+.navbar-nav li a,
+.navbar-nav li.other a {
+    padding-top: 25px;
+    padding-bottom: 20px;
+}
+Thierry */
+
+.navbar-nav li a:hover {
+    color: #572bc9 !important;
+}
+
+.navbar-nav li.active a {
+    background: #eee !important;
+}
+
+/* Thierry : turning this off
+ul.logged-in { 
+    padding-top: 25px; 
+}
+Thierry */
+button.logged-in { 
+    font-size: 1em;
+    font-weight: bold; 
+    margin-left: 5px;
+    margin-top: -5px;
+    background: #572bc9;
+    border: 2px solid #572bc9;
+    color: #eee;
+    padding: 5px 15px;
+    border-radius:5px;
+}
+
+button.logged-in:hover { 
+    /* background: #4af25d; */
+    background: #ff7394;
+    border: 2px solid #ff7394;
+    color: #333;
+}
+li.username {
+    margin-bottom: 10px;
+    font-size: 0.8em;
+    text-transform: none;
+    font-weight: normal; 
+    color: #999;
+}
+
+
+/* BOOTSTRAP */
+
+
+ul.pagination li a {
+    /* background: ; */
+    color: #572bc9;
+    font-family: Ubuntu, Arial, sans-serif;
+}
+
+ul.pagination li.active a {
+    background: #572bc9;
+    border: 1px solid #572bc9;
+}
+
+.btn.btn-default {
+    background: #572bc9;
+    color: #ccc;
+    font-family: Ubuntu, Arial, sans-serif;
+    font-weight: bold;
+    border: 0px;
+}
+
+.btn.btn-default:hover {
+    /* background: #4af25d; */
+    background: #ff7394;
+    color: #333;
+    font-family: Ubuntu, Arial, sans-serif;
+    font-weight: bold;
+    border: 0px;
+}
+
+input {
+    border-radius: 3px;
+    border: none;
+    border: 1px solid #ccc;
+}
+
+
+div.dataTables_length label, 
+div.dataTables_filter label,
+div.dataTables_info {
+    font-family: Ubuntu, Arial, sans-serif !important;
+}
+
+
+
+
+/* QUERYTABLE */
+
+div.QueryTable table.dataTable th {
+    font: bold 12px/22px Ubuntu, Arial, sans-serif;
+    color: #333 !important;
+    border-right: 0px solid #333 !important;
+    border-bottom: 0px solid #C1DAD7 !important;
+    border-top: 0px solid #C1DAD7 !important;
+    letter-spacing: 1px;
+    text-transform: uppercase;
+    text-align: left;
+    padding: 8px 12px 4px 20px;
+    vertical-align:middle;
+    background: url('../img/tablesort-header.png') no-repeat !important; 
+}
+
+div.QueryTable table.dataTable td, div.QueryTable table.dataTable textarea, div.QueryTable table.dataTable input [type="text"] {
+    font: normal 12px Ubuntu, Arial, Helvetica, sans-serif;
+    border-right: 0px solid #fff !important;
+    border-bottom: 1px solid #fff !important;
+}
+
+div.QueryTable table.dataTable thead { 
+    background: url('../img/tablesort-header.png') repeat-x !important;
+    background-color: #caebea;
+}
+
+div.QueryTable table.dataTable tfoot { 
+    background: url('../img/tablesort-header.png') repeat-x !important;
+    /* background-color: # !important; */
+}
+
+
+/* QUERY EDITOR */
+
+table.query-editor {
+    margin: 40px auto !important;
+    clear: both;
+    /* width: 80%;*/
+    width: 100% !important;
+    font-family: Ubuntu;
+}
+
+.query-editor-spacer,
+.plugin.QueryUpdater,
+/* Thierry : turning this off
+.plugin.Tabs 
+Thierry */
+{
+    margin-top: 60px !important;
+}
+
+table.query-editor td {
+    padding: 5px 5px !important;
+    font: normal 12px Ubuntu, Arial, sans-serif !important;
+}
+
+
+
+/* DASHBOARD */
+
+#ms-dashboard-profile,
+#ms-dashboard-testbeds,
+#ms-dashboard-slices {
+    -webkit-transition: all 50ms ease-out;
+    -moz-transition: all 50ms ease-out;
+    -o-transition: all 50ms ease-out;
+    transition: all 0.05s ease-out;
+    padding-top: 140px;
+    padding-bottom: 60px;
+    margin-top: 60px;
+    color: #fff;
+    font-family: Ubuntu, Arial, sans-serif;
+    text-align: center;
+       
+}
+
+#ms-dashboard-profile:hover,
+#ms-dashboard-testbeds:hover,
+#ms-dashboard-slices:hover {
+    margin-top: 65px;
+}
+
+#ms-dashboard-profile {
+    background: url("../img/icon_users_color.png") top center no-repeat;
+}
+
+#ms-dashboard-testbeds {
+    background: url("../img/icon_testbed_color.png") top center no-repeat;
+}
+
+#ms-dashboard-slices {
+    background: url("../img/icon_slices_color.png") top center no-repeat;
+}
+
+.ms-dashboard-content ul {
+    list-style-type: none !important;
+    padding-left: 0;
+    text-align: center !important;
+}
+
+.ms-dashboard-content {
+    padding: 0 !important;
+}
+
+.ms-dashboard-content a {
+    color: #ff7394 !important;
+/* color: #ff0099 !important; */
+}
+
+.ms-dashboard-content a:hover {
+    color: white !important;
+}
+.ms-dashboard-caption h2 {
+    font-family: Ubuntu, Arial, sans-serif;
+    border-bottom: 0 !important;
+    text-transform: uppercase;
+}
+
+#ms-dashboard-profile>div.ms-dashboard-caption {
+    background: no-repeat url(#) !important;
+    padding-left: 0 !important;
+}   
+
+#ms-dashboard-testbeds>div.ms-dashboard-caption {
+    background: no-repeat url(#) !important;
+    padding-left: 0 !important;
+}   
+
+#ms-dashboard-slices>div.ms-dashboard-caption {
+    background: no-repeat url(#) !important;
+    padding-left: 0 !important;
+}   
+
diff --git a/portal/static/img/fibre-logo.gif b/portal/static/img/fibre-logo.gif
new file mode 100644 (file)
index 0000000..e215771
Binary files /dev/null and b/portal/static/img/fibre-logo.gif differ
diff --git a/portal/static/img/fibre/br.png b/portal/static/img/fibre/br.png
new file mode 100644 (file)
index 0000000..4225053
Binary files /dev/null and b/portal/static/img/fibre/br.png differ
diff --git a/portal/static/img/fibre/cafe.jpg b/portal/static/img/fibre/cafe.jpg
new file mode 100644 (file)
index 0000000..c73e6f1
Binary files /dev/null and b/portal/static/img/fibre/cafe.jpg differ
diff --git a/portal/static/img/fibre/eu.png b/portal/static/img/fibre/eu.png
new file mode 100644 (file)
index 0000000..03f1d0f
Binary files /dev/null and b/portal/static/img/fibre/eu.png differ
diff --git a/portal/static/img/fibre/icon_authority_color.png b/portal/static/img/fibre/icon_authority_color.png
new file mode 100644 (file)
index 0000000..342a1dd
Binary files /dev/null and b/portal/static/img/fibre/icon_authority_color.png differ
diff --git a/portal/static/img/fibre/icon_slices.png b/portal/static/img/fibre/icon_slices.png
new file mode 100644 (file)
index 0000000..9527461
Binary files /dev/null and b/portal/static/img/fibre/icon_slices.png differ
diff --git a/portal/static/img/fibre/icon_support.png b/portal/static/img/fibre/icon_support.png
new file mode 100644 (file)
index 0000000..54bce1b
Binary files /dev/null and b/portal/static/img/fibre/icon_support.png differ
diff --git a/portal/static/img/fibre/icon_testbed_color.png b/portal/static/img/fibre/icon_testbed_color.png
new file mode 100644 (file)
index 0000000..f3c55e4
Binary files /dev/null and b/portal/static/img/fibre/icon_testbed_color.png differ
diff --git a/portal/static/img/fibre/icon_user_color.png b/portal/static/img/fibre/icon_user_color.png
new file mode 100644 (file)
index 0000000..e88d559
Binary files /dev/null and b/portal/static/img/fibre/icon_user_color.png differ
diff --git a/portal/static/img/fibre/icones.zip b/portal/static/img/fibre/icones.zip
new file mode 100644 (file)
index 0000000..bab607b
Binary files /dev/null and b/portal/static/img/fibre/icones.zip differ
diff --git a/portal/static/img/icon_authority_color.png~HEAD b/portal/static/img/icon_authority_color.png~HEAD
new file mode 100644 (file)
index 0000000..342a1dd
Binary files /dev/null and b/portal/static/img/icon_authority_color.png~HEAD differ
diff --git a/portal/static/img/icon_slices.png~HEAD b/portal/static/img/icon_slices.png~HEAD
new file mode 100644 (file)
index 0000000..9527461
Binary files /dev/null and b/portal/static/img/icon_slices.png~HEAD differ
diff --git a/portal/static/img/icon_support.png~HEAD b/portal/static/img/icon_support.png~HEAD
new file mode 100644 (file)
index 0000000..54bce1b
Binary files /dev/null and b/portal/static/img/icon_support.png~HEAD differ
diff --git a/portal/static/img/icon_testbed_color.png~HEAD b/portal/static/img/icon_testbed_color.png~HEAD
new file mode 100644 (file)
index 0000000..f3c55e4
Binary files /dev/null and b/portal/static/img/icon_testbed_color.png~HEAD differ
diff --git a/portal/static/img/icon_user_color.png~HEAD b/portal/static/img/icon_user_color.png~HEAD
new file mode 100644 (file)
index 0000000..e88d559
Binary files /dev/null and b/portal/static/img/icon_user_color.png~HEAD differ
diff --git a/portal/static/img/optical_fibre.jpg b/portal/static/img/optical_fibre.jpg
new file mode 100644 (file)
index 0000000..a62eb25
Binary files /dev/null and b/portal/static/img/optical_fibre.jpg differ
diff --git a/portal/static/img/original-backup/authority-icon.png b/portal/static/img/original-backup/authority-icon.png
new file mode 100644 (file)
index 0000000..bde603a
Binary files /dev/null and b/portal/static/img/original-backup/authority-icon.png differ
diff --git a/portal/static/img/original-backup/experiments.png b/portal/static/img/original-backup/experiments.png
new file mode 100644 (file)
index 0000000..cd97086
Binary files /dev/null and b/portal/static/img/original-backup/experiments.png differ
diff --git a/portal/static/img/original-backup/f4f-logo.png b/portal/static/img/original-backup/f4f-logo.png
new file mode 100644 (file)
index 0000000..8a72315
Binary files /dev/null and b/portal/static/img/original-backup/f4f-logo.png differ
diff --git a/portal/static/img/original-backup/marker1.png b/portal/static/img/original-backup/marker1.png
new file mode 100644 (file)
index 0000000..5f29aea
Binary files /dev/null and b/portal/static/img/original-backup/marker1.png differ
diff --git a/portal/static/img/original-backup/marker2.png b/portal/static/img/original-backup/marker2.png
new file mode 100644 (file)
index 0000000..9dce718
Binary files /dev/null and b/portal/static/img/original-backup/marker2.png differ
diff --git a/portal/static/img/original-backup/ques_icon.png b/portal/static/img/original-backup/ques_icon.png
new file mode 100644 (file)
index 0000000..4113c12
Binary files /dev/null and b/portal/static/img/original-backup/ques_icon.png differ
diff --git a/portal/static/img/original-backup/resource-icon.png b/portal/static/img/original-backup/resource-icon.png
new file mode 100644 (file)
index 0000000..919bdbe
Binary files /dev/null and b/portal/static/img/original-backup/resource-icon.png differ
diff --git a/portal/static/img/original-backup/slice-icon.png b/portal/static/img/original-backup/slice-icon.png
new file mode 100644 (file)
index 0000000..9e8747b
Binary files /dev/null and b/portal/static/img/original-backup/slice-icon.png differ
diff --git a/portal/static/img/original-backup/testbeds.png b/portal/static/img/original-backup/testbeds.png
new file mode 100644 (file)
index 0000000..ed9aa0e
Binary files /dev/null and b/portal/static/img/original-backup/testbeds.png differ
diff --git a/portal/static/img/original-backup/user-icon.png b/portal/static/img/original-backup/user-icon.png
new file mode 100644 (file)
index 0000000..88f6bf8
Binary files /dev/null and b/portal/static/img/original-backup/user-icon.png differ
diff --git a/portal/static/img/original-backup/user.png b/portal/static/img/original-backup/user.png
new file mode 100644 (file)
index 0000000..fa72bdd
Binary files /dev/null and b/portal/static/img/original-backup/user.png differ
index 3ae7bbe..dc74d29 100644 (file)
@@ -1,4 +1,4 @@
 /* qTip2 v2.2.0 tips modal viewport svg imagemap ie6 | qtip2.com | Licensed MIT, GPL | Thu Nov 21 2013 20:34:59 */
 (function(t,e,i){(function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):jQuery&&!jQuery.fn.qtip&&t(jQuery)})(function(s){"use strict";function o(t,e,i,o){this.id=i,this.target=t,this.tooltip=E,this.elements={target:t},this._id=X+"-"+i,this.timers={img:{}},this.options=e,this.plugins={},this.cache={event:{},target:s(),disabled:k,attr:o,onTooltip:k,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=k}function n(t){return t===E||"object"!==s.type(t)}function r(t){return!(s.isFunction(t)||t&&t.attr||t.length||"object"===s.type(t)&&(t.jquery||t.then))}function a(t){var e,i,o,a;return n(t)?k:(n(t.metadata)&&(t.metadata={type:t.metadata}),"content"in t&&(e=t.content,n(e)||e.jquery||e.done?e=t.content={text:i=r(e)?k:e}:i=e.text,"ajax"in e&&(o=e.ajax,a=o&&o.once!==k,delete e.ajax,e.text=function(t,e){var n=i||s(this).attr(e.options.content.attr)||"Loading...",r=s.ajax(s.extend({},o,{context:e})).then(o.success,E,o.error).then(function(t){return t&&a&&e.set("content.text",t),t},function(t,i,s){e.destroyed||0===t.status||e.set("content.text",i+": "+s)});return a?n:(e.set("content.text",n),r)}),"title"in e&&(n(e.title)||(e.button=e.title.button,e.title=e.title.text),r(e.title||k)&&(e.title=k))),"position"in t&&n(t.position)&&(t.position={my:t.position,at:t.position}),"show"in t&&n(t.show)&&(t.show=t.show.jquery?{target:t.show}:t.show===W?{ready:W}:{event:t.show}),"hide"in t&&n(t.hide)&&(t.hide=t.hide.jquery?{target:t.hide}:{event:t.hide}),"style"in t&&n(t.style)&&(t.style={classes:t.style}),s.each(R,function(){this.sanitize&&this.sanitize(t)}),t)}function h(t,e){for(var i,s=0,o=t,n=e.split(".");o=o[n[s++]];)n.length>s&&(i=o);return[i||t,n.pop()]}function l(t,e){var i,s,o;for(i in this.checks)for(s in this.checks[i])(o=RegExp(s,"i").exec(t))&&(e.push(o),("builtin"===i||this.plugins[i])&&this.checks[i][s].apply(this.plugins[i]||this,e))}function c(t){return G.concat("").join(t?"-"+t+" ":" ")}function d(i){return i&&{type:i.type,pageX:i.pageX,pageY:i.pageY,target:i.target,relatedTarget:i.relatedTarget,scrollX:i.scrollX||t.pageXOffset||e.body.scrollLeft||e.documentElement.scrollLeft,scrollY:i.scrollY||t.pageYOffset||e.body.scrollTop||e.documentElement.scrollTop}||{}}function p(t,e){return e>0?setTimeout(s.proxy(t,this),e):(t.call(this),i)}function u(t){return this.tooltip.hasClass(ee)?k:(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=p.call(this,function(){this.toggle(W,t)},this.options.show.delay),i)}function f(t){if(this.tooltip.hasClass(ee))return k;var e=s(t.relatedTarget),i=e.closest(U)[0]===this.tooltip[0],o=e[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==e[0]&&"mouse"===this.options.position.target&&i||this.options.hide.fixed&&/mouse(out|leave|move)/.test(t.type)&&(i||o))try{t.preventDefault(),t.stopImmediatePropagation()}catch(n){}else this.timers.hide=p.call(this,function(){this.toggle(k,t)},this.options.hide.delay,this)}function g(t){return this.tooltip.hasClass(ee)||!this.options.hide.inactive?k:(clearTimeout(this.timers.inactive),this.timers.inactive=p.call(this,function(){this.hide(t)},this.options.hide.inactive),i)}function m(t){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(t)}function v(t,i,o){s(e.body).delegate(t,(i.split?i:i.join(he+" "))+he,function(){var t=T.api[s.attr(this,H)];t&&!t.disabled&&o.apply(t,arguments)})}function y(t,i,n){var r,h,l,c,d,p=s(e.body),u=t[0]===e?p:t,f=t.metadata?t.metadata(n.metadata):E,g="html5"===n.metadata.type&&f?f[n.metadata.name]:E,m=t.data(n.metadata.name||"qtipopts");try{m="string"==typeof m?s.parseJSON(m):m}catch(v){}if(c=s.extend(W,{},T.defaults,n,"object"==typeof m?a(m):E,a(g||f)),h=c.position,c.id=i,"boolean"==typeof c.content.text){if(l=t.attr(c.content.attr),c.content.attr===k||!l)return k;c.content.text=l}if(h.container.length||(h.container=p),h.target===k&&(h.target=u),c.show.target===k&&(c.show.target=u),c.show.solo===W&&(c.show.solo=h.container.closest("body")),c.hide.target===k&&(c.hide.target=u),c.position.viewport===W&&(c.position.viewport=h.container),h.container=h.container.eq(0),h.at=new z(h.at,W),h.my=new z(h.my),t.data(X))if(c.overwrite)t.qtip("destroy",!0);else if(c.overwrite===k)return k;return t.attr(Y,i),c.suppress&&(d=t.attr("title"))&&t.removeAttr("title").attr(se,d).attr("title",""),r=new o(t,c,i,!!l),t.data(X,r),t.one("remove.qtip-"+i+" removeqtip.qtip-"+i,function(){var t;(t=s(this).data(X))&&t.destroy(!0)}),r}function b(t){return t.charAt(0).toUpperCase()+t.slice(1)}function w(t,e){var s,o,n=e.charAt(0).toUpperCase()+e.slice(1),r=(e+" "+be.join(n+" ")+n).split(" "),a=0;if(ye[e])return t.css(ye[e]);for(;s=r[a++];)if((o=t.css(s))!==i)return ye[e]=s,o}function _(t,e){return Math.ceil(parseFloat(w(t,e)))}function x(t,e){this._ns="tip",this.options=e,this.offset=e.offset,this.size=[e.width,e.height],this.init(this.qtip=t)}function q(t,e){this.options=e,this._ns="-modal",this.init(this.qtip=t)}function C(t){this._ns="ie6",this.init(this.qtip=t)}var T,j,z,M,I,W=!0,k=!1,E=null,S="x",L="y",A="width",B="height",D="top",F="left",O="bottom",P="right",N="center",$="flipinvert",V="shift",R={},X="qtip",Y="data-hasqtip",H="data-qtip-id",G=["ui-widget","ui-tooltip"],U="."+X,Q="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),J=X+"-fixed",K=X+"-default",Z=X+"-focus",te=X+"-hover",ee=X+"-disabled",ie="_replacedByqTip",se="oldtitle",oe={ie:function(){for(var t=3,i=e.createElement("div");(i.innerHTML="<!--[if gt IE "+ ++t+"]><i></i><![endif]-->")&&i.getElementsByTagName("i")[0];);return t>4?t:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||k};j=o.prototype,j._when=function(t){return s.when.apply(s,t)},j.render=function(t){if(this.rendered||this.destroyed)return this;var e,i=this,o=this.options,n=this.cache,r=this.elements,a=o.content.text,h=o.content.title,l=o.content.button,c=o.position,d=("."+this._id+" ",[]);return s.attr(this.target[0],"aria-describedby",this._id),this.tooltip=r.tooltip=e=s("<div/>",{id:this._id,"class":[X,K,o.style.classes,X+"-pos-"+o.position.my.abbrev()].join(" "),width:o.style.width||"",height:o.style.height||"",tracking:"mouse"===c.target&&c.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":k,"aria-describedby":this._id+"-content","aria-hidden":W}).toggleClass(ee,this.disabled).attr(H,this.id).data(X,this).appendTo(c.container).append(r.content=s("<div />",{"class":X+"-content",id:this._id+"-content","aria-atomic":W})),this.rendered=-1,this.positioning=W,h&&(this._createTitle(),s.isFunction(h)||d.push(this._updateTitle(h,k))),l&&this._createButton(),s.isFunction(a)||d.push(this._updateContent(a,k)),this.rendered=W,this._setWidget(),s.each(R,function(t){var e;"render"===this.initialize&&(e=this(i))&&(i.plugins[t]=e)}),this._unassignEvents(),this._assignEvents(),this._when(d).then(function(){i._trigger("render"),i.positioning=k,i.hiddenDuringWait||!o.show.ready&&!t||i.toggle(W,n.event,k),i.hiddenDuringWait=k}),T.api[this.id]=this,this},j.destroy=function(t){function e(){if(!this.destroyed){this.destroyed=W;var t=this.target,e=t.attr(se);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),s.each(this.plugins,function(){this.destroy&&this.destroy()}),clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this._unassignEvents(),t.removeData(X).removeAttr(H).removeAttr(Y).removeAttr("aria-describedby"),this.options.suppress&&e&&t.attr("title",e).removeAttr(se),this._unbind(t),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=E,delete T.api[this.id]}}return this.destroyed?this.target:(t===W&&"hide"!==this.triggering||!this.rendered?e.call(this):(this.tooltip.one("tooltiphidden",s.proxy(e,this)),!this.triggering&&this.hide()),this.target)},M=j.checks={builtin:{"^id$":function(t,e,i,o){var n=i===W?T.nextid:i,r=X+"-"+n;n!==k&&n.length>0&&!s("#"+r).length?(this._id=r,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):t[e]=o},"^prerender":function(t,e,i){i&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(t,e,i){this._updateContent(i)},"^content.attr$":function(t,e,i,s){this.options.content.text===this.target.attr(s)&&this._updateContent(this.target.attr(i))},"^content.title$":function(t,e,s){return s?(s&&!this.elements.title&&this._createTitle(),this._updateTitle(s),i):this._removeTitle()},"^content.button$":function(t,e,i){this._updateButton(i)},"^content.title.(text|button)$":function(t,e,i){this.set("content."+e,i)},"^position.(my|at)$":function(t,e,i){"string"==typeof i&&(t[e]=new z(i,"at"===e))},"^position.container$":function(t,e,i){this.rendered&&this.tooltip.appendTo(i)},"^show.ready$":function(t,e,i){i&&(!this.rendered&&this.render(W)||this.toggle(W))},"^style.classes$":function(t,e,i,s){this.rendered&&this.tooltip.removeClass(s).addClass(i)},"^style.(width|height)":function(t,e,i){this.rendered&&this.tooltip.css(e,i)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(t,e,i){this.rendered&&this.tooltip.toggleClass(K,!!i)},"^events.(render|show|move|hide|focus|blur)$":function(t,e,i){this.rendered&&this.tooltip[(s.isFunction(i)?"":"un")+"bind"]("tooltip"+e,i)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var t=this.options.position;this.tooltip.attr("tracking","mouse"===t.target&&t.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},j.get=function(t){if(this.destroyed)return this;var e=h(this.options,t.toLowerCase()),i=e[0][e[1]];return i.precedance?i.string():i};var ne=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,re=/^prerender|show\.ready/i;j.set=function(t,e){if(this.destroyed)return this;var o,n=this.rendered,r=k,c=this.options;return this.checks,"string"==typeof t?(o=t,t={},t[o]=e):t=s.extend({},t),s.each(t,function(e,o){if(n&&re.test(e))return delete t[e],i;var a,l=h(c,e.toLowerCase());a=l[0][l[1]],l[0][l[1]]=o&&o.nodeType?s(o):o,r=ne.test(e)||r,t[e]=[l[0],l[1],o,a]}),a(c),this.positioning=W,s.each(t,s.proxy(l,this)),this.positioning=k,this.rendered&&this.tooltip[0].offsetWidth>0&&r&&this.reposition("mouse"===c.position.target?E:this.cache.event),this},j._update=function(t,e){var i=this,o=this.cache;return this.rendered&&t?(s.isFunction(t)&&(t=t.call(this.elements.target,o.event,this)||""),s.isFunction(t.then)?(o.waiting=W,t.then(function(t){return o.waiting=k,i._update(t,e)},E,function(t){return i._update(t,e)})):t===k||!t&&""!==t?k:(t.jquery&&t.length>0?e.empty().append(t.css({display:"block",visibility:"visible"})):e.html(t),this._waitForContent(e).then(function(t){t.images&&t.images.length&&i.rendered&&i.tooltip[0].offsetWidth>0&&i.reposition(o.event,!t.length)}))):k},j._waitForContent=function(t){var e=this.cache;return e.waiting=W,(s.fn.imagesLoaded?t.imagesLoaded():s.Deferred().resolve([])).done(function(){e.waiting=k}).promise()},j._updateContent=function(t,e){this._update(t,this.elements.content,e)},j._updateTitle=function(t,e){this._update(t,this.elements.title,e)===k&&this._removeTitle(k)},j._createTitle=function(){var t=this.elements,e=this._id+"-title";t.titlebar&&this._removeTitle(),t.titlebar=s("<div />",{"class":X+"-titlebar "+(this.options.style.widget?c("header"):"")}).append(t.title=s("<div />",{id:e,"class":X+"-title","aria-atomic":W})).insertBefore(t.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(t){s(this).toggleClass("ui-state-active ui-state-focus","down"===t.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(t){s(this).toggleClass("ui-state-hover","mouseover"===t.type)}),this.options.content.button&&this._createButton()},j._removeTitle=function(t){var e=this.elements;e.title&&(e.titlebar.remove(),e.titlebar=e.title=e.button=E,t!==k&&this.reposition())},j.reposition=function(i,o){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=W;var n,r,a=this.cache,h=this.tooltip,l=this.options.position,c=l.target,d=l.my,p=l.at,u=l.viewport,f=l.container,g=l.adjust,m=g.method.split(" "),v=h.outerWidth(k),y=h.outerHeight(k),b=0,w=0,_=h.css("position"),x={left:0,top:0},q=h[0].offsetWidth>0,C=i&&"scroll"===i.type,T=s(t),j=f[0].ownerDocument,z=this.mouse;if(s.isArray(c)&&2===c.length)p={x:F,y:D},x={left:c[0],top:c[1]};else if("mouse"===c)p={x:F,y:D},!z||!z.pageX||!g.mouse&&i&&i.pageX?i&&i.pageX||((!g.mouse||this.options.show.distance)&&a.origin&&a.origin.pageX?i=a.origin:(!i||i&&("resize"===i.type||"scroll"===i.type))&&(i=a.event)):i=z,"static"!==_&&(x=f.offset()),j.body.offsetWidth!==(t.innerWidth||j.documentElement.clientWidth)&&(r=s(e.body).offset()),x={left:i.pageX-x.left+(r&&r.left||0),top:i.pageY-x.top+(r&&r.top||0)},g.mouse&&C&&z&&(x.left-=(z.scrollX||0)-T.scrollLeft(),x.top-=(z.scrollY||0)-T.scrollTop());else{if("event"===c?i&&i.target&&"scroll"!==i.type&&"resize"!==i.type?a.target=s(i.target):i.target||(a.target=this.elements.target):"event"!==c&&(a.target=s(c.jquery?c:this.elements.target)),c=a.target,c=s(c).eq(0),0===c.length)return this;c[0]===e||c[0]===t?(b=oe.iOS?t.innerWidth:c.width(),w=oe.iOS?t.innerHeight:c.height(),c[0]===t&&(x={top:(u||c).scrollTop(),left:(u||c).scrollLeft()})):R.imagemap&&c.is("area")?n=R.imagemap(this,c,p,R.viewport?m:k):R.svg&&c&&c[0].ownerSVGElement?n=R.svg(this,c,p,R.viewport?m:k):(b=c.outerWidth(k),w=c.outerHeight(k),x=c.offset()),n&&(b=n.width,w=n.height,r=n.offset,x=n.position),x=this.reposition.offset(c,x,f),(oe.iOS>3.1&&4.1>oe.iOS||oe.iOS>=4.3&&4.33>oe.iOS||!oe.iOS&&"fixed"===_)&&(x.left-=T.scrollLeft(),x.top-=T.scrollTop()),(!n||n&&n.adjustable!==k)&&(x.left+=p.x===P?b:p.x===N?b/2:0,x.top+=p.y===O?w:p.y===N?w/2:0)}return x.left+=g.x+(d.x===P?-v:d.x===N?-v/2:0),x.top+=g.y+(d.y===O?-y:d.y===N?-y/2:0),R.viewport?(x.adjusted=R.viewport(this,x,l,b,w,v,y),r&&x.adjusted.left&&(x.left+=r.left),r&&x.adjusted.top&&(x.top+=r.top)):x.adjusted={left:0,top:0},this._trigger("move",[x,u.elem||u],i)?(delete x.adjusted,o===k||!q||isNaN(x.left)||isNaN(x.top)||"mouse"===c||!s.isFunction(l.effect)?h.css(x):s.isFunction(l.effect)&&(l.effect.call(h,this,s.extend({},x)),h.queue(function(t){s(this).css({opacity:"",height:""}),oe.ie&&this.style.removeAttribute("filter"),t()})),this.positioning=k,this):this},j.reposition.offset=function(t,i,o){function n(t,e){i.left+=e*t.scrollLeft(),i.top+=e*t.scrollTop()}if(!o[0])return i;var r,a,h,l,c=s(t[0].ownerDocument),d=!!oe.ie&&"CSS1Compat"!==e.compatMode,p=o[0];do"static"!==(a=s.css(p,"position"))&&("fixed"===a?(h=p.getBoundingClientRect(),n(c,-1)):(h=s(p).position(),h.left+=parseFloat(s.css(p,"borderLeftWidth"))||0,h.top+=parseFloat(s.css(p,"borderTopWidth"))||0),i.left-=h.left+(parseFloat(s.css(p,"marginLeft"))||0),i.top-=h.top+(parseFloat(s.css(p,"marginTop"))||0),r||"hidden"===(l=s.css(p,"overflow"))||"visible"===l||(r=s(p)));while(p=p.offsetParent);return r&&(r[0]!==c[0]||d)&&n(r,1),i};var ae=(z=j.reposition.Corner=function(t,e){t=(""+t).replace(/([A-Z])/," $1").replace(/middle/gi,N).toLowerCase(),this.x=(t.match(/left|right/i)||t.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(t.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!e;var i=t.charAt(0);this.precedance="t"===i||"b"===i?L:S}).prototype;ae.invert=function(t,e){this[t]=this[t]===F?P:this[t]===P?F:e||this[t]},ae.string=function(){var t=this.x,e=this.y;return t===e?t:this.precedance===L||this.forceY&&"center"!==e?e+" "+t:t+" "+e},ae.abbrev=function(){var t=this.string().split(" ");return t[0].charAt(0)+(t[1]&&t[1].charAt(0)||"")},ae.clone=function(){return new z(this.string(),this.forceY)},j.toggle=function(t,i){var o=this.cache,n=this.options,r=this.tooltip;if(i){if(/over|enter/.test(i.type)&&/out|leave/.test(o.event.type)&&n.show.target.add(i.target).length===n.show.target.length&&r.has(i.relatedTarget).length)return this;o.event=d(i)}if(this.waiting&&!t&&(this.hiddenDuringWait=W),!this.rendered)return t?this.render(1):this;if(this.destroyed||this.disabled)return this;var a,h,l,c=t?"show":"hide",p=this.options[c],u=(this.options[t?"hide":"show"],this.options.position),f=this.options.content,g=this.tooltip.css("width"),m=this.tooltip.is(":visible"),v=t||1===p.target.length,y=!i||2>p.target.length||o.target[0]===i.target;return(typeof t).search("boolean|number")&&(t=!m),a=!r.is(":animated")&&m===t&&y,h=a?E:!!this._trigger(c,[90]),this.destroyed?this:(h!==k&&t&&this.focus(i),!h||a?this:(s.attr(r[0],"aria-hidden",!t),t?(o.origin=d(this.mouse),s.isFunction(f.text)&&this._updateContent(f.text,k),s.isFunction(f.title)&&this._updateTitle(f.title,k),!I&&"mouse"===u.target&&u.adjust.mouse&&(s(e).bind("mousemove."+X,this._storeMouse),I=W),g||r.css("width",r.outerWidth(k)),this.reposition(i,arguments[2]),g||r.css("width",""),p.solo&&("string"==typeof p.solo?s(p.solo):s(U,p.solo)).not(r).not(p.target).qtip("hide",s.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete o.origin,I&&!s(U+'[tracking="true"]:visible',p.solo).not(r).length&&(s(e).unbind("mousemove."+X),I=k),this.blur(i)),l=s.proxy(function(){t?(oe.ie&&r[0].style.removeAttribute("filter"),r.css("overflow",""),"string"==typeof p.autofocus&&s(this.options.show.autofocus,r).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):r.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(t?"visible":"hidden")},this),p.effect===k||v===k?(r[c](),l()):s.isFunction(p.effect)?(r.stop(1,1),p.effect.call(r,this),r.queue("fx",function(t){l(),t()})):r.fadeTo(90,t?1:0,l),t&&p.target.trigger("qtip-"+this.id+"-inactive"),this))},j.show=function(t){return this.toggle(W,t)},j.hide=function(t){return this.toggle(k,t)},j.focus=function(t){if(!this.rendered||this.destroyed)return this;var e=s(U),i=this.tooltip,o=parseInt(i[0].style.zIndex,10),n=T.zindex+e.length;return i.hasClass(Z)||this._trigger("focus",[n],t)&&(o!==n&&(e.each(function(){this.style.zIndex>o&&(this.style.zIndex=this.style.zIndex-1)}),e.filter("."+Z).qtip("blur",t)),i.addClass(Z)[0].style.zIndex=n),this},j.blur=function(t){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass(Z),this._trigger("blur",[this.tooltip.css("zIndex")],t),this)},j.disable=function(t){return this.destroyed?this:("toggle"===t?t=!(this.rendered?this.tooltip.hasClass(ee):this.disabled):"boolean"!=typeof t&&(t=W),this.rendered&&this.tooltip.toggleClass(ee,t).attr("aria-disabled",t),this.disabled=!!t,this)},j.enable=function(){return this.disable(k)},j._createButton=function(){var t=this,e=this.elements,i=e.tooltip,o=this.options.content.button,n="string"==typeof o,r=n?o:"Close tooltip";e.button&&e.button.remove(),e.button=o.jquery?o:s("<a />",{"class":"qtip-close "+(this.options.style.widget?"":X+"-icon"),title:r,"aria-label":r}).prepend(s("<span />",{"class":"ui-icon ui-icon-close",html:"&times;"})),e.button.appendTo(e.titlebar||i).attr("role","button").click(function(e){return i.hasClass(ee)||t.hide(e),k})},j._updateButton=function(t){if(!this.rendered)return k;var e=this.elements.button;t?this._createButton():e.remove()},j._setWidget=function(){var t=this.options.style.widget,e=this.elements,i=e.tooltip,s=i.hasClass(ee);i.removeClass(ee),ee=t?"ui-state-disabled":"qtip-disabled",i.toggleClass(ee,s),i.toggleClass("ui-helper-reset "+c(),t).toggleClass(K,this.options.style.def&&!t),e.content&&e.content.toggleClass(c("content"),t),e.titlebar&&e.titlebar.toggleClass(c("header"),t),e.button&&e.button.toggleClass(X+"-icon",!t)},j._storeMouse=function(t){(this.mouse=d(t)).type="mousemove"},j._bind=function(t,e,i,o,n){var r="."+this._id+(o?"-"+o:"");e.length&&s(t).bind((e.split?e:e.join(r+" "))+r,s.proxy(i,n||this))},j._unbind=function(t,e){s(t).unbind("."+this._id+(e?"-"+e:""))};var he="."+X;s(function(){v(U,["mouseenter","mouseleave"],function(t){var e="mouseenter"===t.type,i=s(t.currentTarget),o=s(t.relatedTarget||t.target),n=this.options;e?(this.focus(t),i.hasClass(J)&&!i.hasClass(ee)&&clearTimeout(this.timers.hide)):"mouse"===n.position.target&&n.hide.event&&n.show.target&&!o.closest(n.show.target[0]).length&&this.hide(t),i.toggleClass(te,e)}),v("["+H+"]",Q,g)}),j._trigger=function(t,e,i){var o=s.Event("tooltip"+t);return o.originalEvent=i&&s.extend({},i)||this.cache.event||E,this.triggering=t,this.tooltip.trigger(o,[this].concat(e||[])),this.triggering=k,!o.isDefaultPrevented()},j._bindEvents=function(t,e,o,n,r,a){if(n.add(o).length===n.length){var h=[];e=s.map(e,function(e){var o=s.inArray(e,t);return o>-1?(h.push(t.splice(o,1)[0]),i):e}),h.length&&this._bind(o,h,function(t){var e=this.rendered?this.tooltip[0].offsetWidth>0:!1;(e?a:r).call(this,t)})}this._bind(o,t,r),this._bind(n,e,a)},j._assignInitialEvents=function(t){function e(t){return this.disabled||this.destroyed?k:(this.cache.event=d(t),this.cache.target=t?s(t.target):[i],clearTimeout(this.timers.show),this.timers.show=p.call(this,function(){this.render("object"==typeof t||o.show.ready)},o.show.delay),i)}var o=this.options,n=o.show.target,r=o.hide.target,a=o.show.event?s.trim(""+o.show.event).split(" "):[],h=o.hide.event?s.trim(""+o.hide.event).split(" "):[];/mouse(over|enter)/i.test(o.show.event)&&!/mouse(out|leave)/i.test(o.hide.event)&&h.push("mouseleave"),this._bind(n,"mousemove",function(t){this._storeMouse(t),this.cache.onTarget=W}),this._bindEvents(a,h,n,r,e,function(){clearTimeout(this.timers.show)}),(o.show.ready||o.prerender)&&e.call(this,t)},j._assignEvents=function(){var i=this,o=this.options,n=o.position,r=this.tooltip,a=o.show.target,h=o.hide.target,l=n.container,c=n.viewport,d=s(e),p=(s(e.body),s(t)),v=o.show.event?s.trim(""+o.show.event).split(" "):[],y=o.hide.event?s.trim(""+o.hide.event).split(" "):[];s.each(o.events,function(t,e){i._bind(r,"toggle"===t?["tooltipshow","tooltiphide"]:["tooltip"+t],e,null,r)}),/mouse(out|leave)/i.test(o.hide.event)&&"window"===o.hide.leave&&this._bind(d,["mouseout","blur"],function(t){/select|option/.test(t.target.nodeName)||t.relatedTarget||this.hide(t)}),o.hide.fixed?h=h.add(r.addClass(J)):/mouse(over|enter)/i.test(o.show.event)&&this._bind(h,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+o.hide.event).indexOf("unfocus")>-1&&this._bind(l.closest("html"),["mousedown","touchstart"],function(t){var e=s(t.target),i=this.rendered&&!this.tooltip.hasClass(ee)&&this.tooltip[0].offsetWidth>0,o=e.parents(U).filter(this.tooltip[0]).length>0;e[0]===this.target[0]||e[0]===this.tooltip[0]||o||this.target.has(e[0]).length||!i||this.hide(t)}),"number"==typeof o.hide.inactive&&(this._bind(a,"qtip-"+this.id+"-inactive",g),this._bind(h.add(r),T.inactiveEvents,g,"-inactive")),this._bindEvents(v,y,a,h,u,f),this._bind(a.add(r),"mousemove",function(t){if("number"==typeof o.hide.distance){var e=this.cache.origin||{},i=this.options.hide.distance,s=Math.abs;(s(t.pageX-e.pageX)>=i||s(t.pageY-e.pageY)>=i)&&this.hide(t)}this._storeMouse(t)}),"mouse"===n.target&&n.adjust.mouse&&(o.hide.event&&this._bind(a,["mouseenter","mouseleave"],function(t){this.cache.onTarget="mouseenter"===t.type}),this._bind(d,"mousemove",function(t){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(ee)&&this.tooltip[0].offsetWidth>0&&this.reposition(t)})),(n.adjust.resize||c.length)&&this._bind(s.event.special.resize?c:p,"resize",m),n.adjust.scroll&&this._bind(p.add(n.container),"scroll",m)},j._unassignEvents=function(){var i=[this.options.show.target[0],this.options.hide.target[0],this.rendered&&this.tooltip[0],this.options.position.container[0],this.options.position.viewport[0],this.options.position.container.closest("html")[0],t,e];this._unbind(s([]).pushStack(s.grep(i,function(t){return"object"==typeof t})))},T=s.fn.qtip=function(t,e,o){var n=(""+t).toLowerCase(),r=E,h=s.makeArray(arguments).slice(1),l=h[h.length-1],c=this[0]?s.data(this[0],X):E;return!arguments.length&&c||"api"===n?c:"string"==typeof t?(this.each(function(){var t=s.data(this,X);if(!t)return W;if(l&&l.timeStamp&&(t.cache.event=l),!e||"option"!==n&&"options"!==n)t[n]&&t[n].apply(t,h);else{if(o===i&&!s.isPlainObject(e))return r=t.get(e),k;t.set(e,o)}}),r!==E?r:this):"object"!=typeof t&&arguments.length?i:(c=a(s.extend(W,{},t)),this.each(function(t){var e,o;return o=s.isArray(c.id)?c.id[t]:c.id,o=!o||o===k||1>o.length||T.api[o]?T.nextid++:o,e=y(s(this),o,c),e===k?W:(T.api[o]=e,s.each(R,function(){"initialize"===this.initialize&&this(e)}),e._assignInitialEvents(l),i)}))},s.qtip=o,T.api={},s.each({attr:function(t,e){if(this.length){var i=this[0],o="title",n=s.data(i,"qtip");if(t===o&&n&&"object"==typeof n&&n.options.suppress)return 2>arguments.length?s.attr(i,se):(n&&n.options.content.attr===o&&n.cache.attr&&n.set("content.text",e),this.attr(se,e))}return s.fn["attr"+ie].apply(this,arguments)},clone:function(t){var e=(s([]),s.fn["clone"+ie].apply(this,arguments));return t||e.filter("["+se+"]").attr("title",function(){return s.attr(this,se)}).removeAttr(se),e}},function(t,e){if(!e||s.fn[t+ie])return W;var i=s.fn[t+ie]=s.fn[t];s.fn[t]=function(){return e.apply(this,arguments)||i.apply(this,arguments)}}),s.ui||(s["cleanData"+ie]=s.cleanData,s.cleanData=function(t){for(var e,i=0;(e=s(t[i])).length;i++)if(e.attr(Y))try{e.triggerHandler("removeqtip")}catch(o){}s["cleanData"+ie].apply(this,arguments)}),T.version="2.2.0",T.nextid=0,T.inactiveEvents=Q,T.zindex=15e3,T.defaults={prerender:k,id:k,overwrite:W,suppress:W,content:{text:W,attr:"title",title:k,button:k},position:{my:"top left",at:"bottom right",target:k,container:k,viewport:k,adjust:{x:0,y:0,mouse:W,scroll:W,resize:W,method:"flipinvert flipinvert"},effect:function(t,e){s(this).animate(e,{duration:200,queue:k})}},show:{target:k,event:"mouseenter",effect:W,delay:90,solo:k,ready:k,autofocus:k},hide:{target:k,event:"mouseleave",effect:W,delay:0,fixed:k,inactive:k,leave:"window",distance:k},style:{classes:"",widget:k,width:k,height:k,def:W},events:{render:E,move:E,show:E,hide:E,toggle:E,visible:E,hidden:E,focus:E,blur:E}};var le,ce="margin",de="border",pe="color",ue="background-color",fe="transparent",ge=" !important",me=!!e.createElement("canvas").getContext,ve=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,ye={},be=["Webkit","O","Moz","ms"];if(me)var we=t.devicePixelRatio||1,_e=function(){var t=e.createElement("canvas").getContext("2d");return t.backingStorePixelRatio||t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||1}(),xe=we/_e;else var qe=function(t,e,i){return"<qtipvml:"+t+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(e||"")+' style="behavior: url(#default#VML); '+(i||"")+'" />'};s.extend(x.prototype,{init:function(t){var e,i;i=this.element=t.elements.tip=s("<div />",{"class":X+"-tip"}).prependTo(t.tooltip),me?(e=s("<canvas />").appendTo(this.element)[0].getContext("2d"),e.lineJoin="miter",e.miterLimit=1e5,e.save()):(e=qe("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(e+e),t._bind(s("*",i).add(i),["click","mousedown"],function(t){t.stopPropagation()},this._ns)),t._bind(t.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(t){var e=this.qtip.elements.titlebar;return e&&(t.y===D||t.y===N&&this.element.position().top+this.size[1]/2+this.options.offset<e.outerHeight(W))},_parseCorner:function(t){var e=this.qtip.options.position.my;return t===k||e===k?t=k:t===W?t=new z(e.string()):t.string||(t=new z(t),t.fixed=W),t},_parseWidth:function(t,e,i){var s=this.qtip.elements,o=de+b(e)+"Width";return(i?_(i,o):_(s.content,o)||_(this._useTitle(t)&&s.titlebar||s.content,o)||_(s.tooltip,o))||0},_parseRadius:function(t){var e=this.qtip.elements,i=de+b(t.y)+b(t.x)+"Radius";return 9>oe.ie?0:_(this._useTitle(t)&&e.titlebar||e.content,i)||_(e.tooltip,i)||0},_invalidColour:function(t,e,i){var s=t.css(e);return!s||i&&s===t.css(i)||ve.test(s)?k:s},_parseColours:function(t){var e=this.qtip.elements,i=this.element.css("cssText",""),o=de+b(t[t.precedance])+b(pe),n=this._useTitle(t)&&e.titlebar||e.content,r=this._invalidColour,a=[];return a[0]=r(i,ue)||r(n,ue)||r(e.content,ue)||r(e.tooltip,ue)||i.css(ue),a[1]=r(i,o,pe)||r(n,o,pe)||r(e.content,o,pe)||r(e.tooltip,o,pe)||e.tooltip.css(o),s("*",i).add(i).css("cssText",ue+":"+fe+ge+";"+de+":0"+ge+";"),a},_calculateSize:function(t){var e,i,s,o=t.precedance===L,n=this.options.width,r=this.options.height,a="c"===t.abbrev(),h=(o?n:r)*(a?.5:1),l=Math.pow,c=Math.round,d=Math.sqrt(l(h,2)+l(r,2)),p=[this.border/h*d,this.border/r*d];return p[2]=Math.sqrt(l(p[0],2)-l(this.border,2)),p[3]=Math.sqrt(l(p[1],2)-l(this.border,2)),e=d+p[2]+p[3]+(a?0:p[0]),i=e/d,s=[c(i*n),c(i*r)],o?s:s.reverse()},_calculateTip:function(t,e,i){i=i||1,e=e||this.size;var s=e[0]*i,o=e[1]*i,n=Math.ceil(s/2),r=Math.ceil(o/2),a={br:[0,0,s,o,s,0],bl:[0,0,s,0,0,o],tr:[0,o,s,0,s,o],tl:[0,0,0,o,s,o],tc:[0,o,n,0,s,o],bc:[0,0,s,0,n,o],rc:[0,0,s,r,0,o],lc:[s,0,s,o,0,r]};return a.lt=a.br,a.rt=a.bl,a.lb=a.tr,a.rb=a.tl,a[t.abbrev()]},_drawCoords:function(t,e){t.beginPath(),t.moveTo(e[0],e[1]),t.lineTo(e[2],e[3]),t.lineTo(e[4],e[5]),t.closePath()},create:function(){var t=this.corner=(me||oe.ie)&&this._parseCorner(this.options.corner);return(this.enabled=!!this.corner&&"c"!==this.corner.abbrev())&&(this.qtip.cache.corner=t.clone(),this.update()),this.element.toggle(this.enabled),this.corner},update:function(e,i){if(!this.enabled)return this;var o,n,r,a,h,l,c,d,p=this.qtip.elements,u=this.element,f=u.children(),g=this.options,m=this.size,v=g.mimic,y=Math.round;e||(e=this.qtip.cache.corner||this.corner),v===k?v=e:(v=new z(v),v.precedance=e.precedance,"inherit"===v.x?v.x=e.x:"inherit"===v.y?v.y=e.y:v.x===v.y&&(v[e.precedance]=e[e.precedance])),n=v.precedance,e.precedance===S?this._swapDimensions():this._resetDimensions(),o=this.color=this._parseColours(e),o[1]!==fe?(d=this.border=this._parseWidth(e,e[e.precedance]),g.border&&1>d&&!ve.test(o[1])&&(o[0]=o[1]),this.border=d=g.border!==W?g.border:d):this.border=d=0,c=this.size=this._calculateSize(e),u.css({width:c[0],height:c[1],lineHeight:c[1]+"px"}),l=e.precedance===L?[y(v.x===F?d:v.x===P?c[0]-m[0]-d:(c[0]-m[0])/2),y(v.y===D?c[1]-m[1]:0)]:[y(v.x===F?c[0]-m[0]:0),y(v.y===D?d:v.y===O?c[1]-m[1]-d:(c[1]-m[1])/2)],me?(r=f[0].getContext("2d"),r.restore(),r.save(),r.clearRect(0,0,6e3,6e3),a=this._calculateTip(v,m,xe),h=this._calculateTip(v,this.size,xe),f.attr(A,c[0]*xe).attr(B,c[1]*xe),f.css(A,c[0]).css(B,c[1]),this._drawCoords(r,h),r.fillStyle=o[1],r.fill(),r.translate(l[0]*xe,l[1]*xe),this._drawCoords(r,a),r.fillStyle=o[0],r.fill()):(a=this._calculateTip(v),a="m"+a[0]+","+a[1]+" l"+a[2]+","+a[3]+" "+a[4]+","+a[5]+" xe",l[2]=d&&/^(r|b)/i.test(e.string())?8===oe.ie?2:1:0,f.css({coordsize:c[0]+d+" "+(c[1]+d),antialias:""+(v.string().indexOf(N)>-1),left:l[0]-l[2]*Number(n===S),top:l[1]-l[2]*Number(n===L),width:c[0]+d,height:c[1]+d}).each(function(t){var e=s(this);e[e.prop?"prop":"attr"]({coordsize:c[0]+d+" "+(c[1]+d),path:a,fillcolor:o[0],filled:!!t,stroked:!t}).toggle(!(!d&&!t)),!t&&e.html(qe("stroke",'weight="'+2*d+'px" color="'+o[1]+'" miterlimit="1000" joinstyle="miter"'))})),t.opera&&setTimeout(function(){p.tip.css({display:"inline-block",visibility:"visible"})},1),i!==k&&this.calculate(e,c)},calculate:function(t,e){if(!this.enabled)return k;var i,o,n=this,r=this.qtip.elements,a=this.element,h=this.options.offset,l=(r.tooltip.hasClass("ui-widget"),{});return t=t||this.corner,i=t.precedance,e=e||this._calculateSize(t),o=[t.x,t.y],i===S&&o.reverse(),s.each(o,function(s,o){var a,c,d;o===N?(a=i===L?F:D,l[a]="50%",l[ce+"-"+a]=-Math.round(e[i===L?0:1]/2)+h):(a=n._parseWidth(t,o,r.tooltip),c=n._parseWidth(t,o,r.content),d=n._parseRadius(t),l[o]=Math.max(-n.border,s?c:h+(d>a?d:-a)))
 }),l[t[i]]-=e[i===S?0:1],a.css({margin:"",top:"",bottom:"",left:"",right:""}).css(l),l},reposition:function(t,e,s){function o(t,e,i,s,o){t===V&&l.precedance===e&&c[s]&&l[i]!==N?l.precedance=l.precedance===S?L:S:t!==V&&c[s]&&(l[e]=l[e]===N?c[s]>0?s:o:l[e]===s?o:s)}function n(t,e,o){l[t]===N?g[ce+"-"+e]=f[t]=r[ce+"-"+e]-c[e]:(a=r[o]!==i?[c[e],-r[e]]:[-c[e],r[e]],(f[t]=Math.max(a[0],a[1]))>a[0]&&(s[e]-=c[e],f[e]=k),g[r[o]!==i?o:e]=f[t])}if(this.enabled){var r,a,h=e.cache,l=this.corner.clone(),c=s.adjusted,d=e.options.position.adjust.method.split(" "),p=d[0],u=d[1]||d[0],f={left:k,top:k,x:0,y:0},g={};this.corner.fixed!==W&&(o(p,S,L,F,P),o(u,L,S,D,O),l.string()===h.corner.string()||h.cornerTop===c.top&&h.cornerLeft===c.left||this.update(l,k)),r=this.calculate(l),r.right!==i&&(r.left=-r.right),r.bottom!==i&&(r.top=-r.bottom),r.user=this.offset,(f.left=p===V&&!!c.left)&&n(S,F,P),(f.top=u===V&&!!c.top)&&n(L,D,O),this.element.css(g).toggle(!(f.x&&f.y||l.x===N&&f.y||l.y===N&&f.x)),s.left-=r.left.charAt?r.user:p!==V||f.top||!f.left&&!f.top?r.left+this.border:0,s.top-=r.top.charAt?r.user:u!==V||f.left||!f.left&&!f.top?r.top+this.border:0,h.cornerLeft=c.left,h.cornerTop=c.top,h.corner=l.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),le=R.tip=function(t){return new x(t,t.options.style.tip)},le.initialize="render",le.sanitize=function(t){if(t.style&&"tip"in t.style){var e=t.style.tip;"object"!=typeof e&&(e=t.style.tip={corner:e}),/string|boolean/i.test(typeof e.corner)||(e.corner=W)}},M.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(t){this.size=[t.width,t.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},s.extend(W,T.defaults,{style:{tip:{corner:W,mimic:k,width:6,height:6,border:W,offset:0}}});var Ce,Te,je="qtip-modal",ze="."+je;Te=function(){function t(t){if(s.expr[":"].focusable)return s.expr[":"].focusable;var e,i,o,n=!isNaN(s.attr(t,"tabindex")),r=t.nodeName&&t.nodeName.toLowerCase();return"area"===r?(e=t.parentNode,i=e.name,t.href&&i&&"map"===e.nodeName.toLowerCase()?(o=s("img[usemap=#"+i+"]")[0],!!o&&o.is(":visible")):!1):/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||n:n}function i(t){1>c.length&&t.length?t.not("body").blur():c.first().focus()}function o(t){if(h.is(":visible")){var e,o=s(t.target),a=n.tooltip,l=o.closest(U);e=1>l.length?k:parseInt(l[0].style.zIndex,10)>parseInt(a[0].style.zIndex,10),e||o.closest(U)[0]===a[0]||i(o),r=t.target===c[c.length-1]}}var n,r,a,h,l=this,c={};s.extend(l,{init:function(){return h=l.elem=s("<div />",{id:"qtip-overlay",html:"<div></div>",mousedown:function(){return k}}).hide(),s(e.body).bind("focusin"+ze,o),s(e).bind("keydown"+ze,function(t){n&&n.options.show.modal.escape&&27===t.keyCode&&n.hide(t)}),h.bind("click"+ze,function(t){n&&n.options.show.modal.blur&&n.hide(t)}),l},update:function(e){n=e,c=e.options.show.modal.stealfocus!==k?e.tooltip.find("*").filter(function(){return t(this)}):[]},toggle:function(t,o,r){var c=(s(e.body),t.tooltip),d=t.options.show.modal,p=d.effect,u=o?"show":"hide",f=h.is(":visible"),g=s(ze).filter(":visible:not(:animated)").not(c);return l.update(t),o&&d.stealfocus!==k&&i(s(":focus")),h.toggleClass("blurs",d.blur),o&&h.appendTo(e.body),h.is(":animated")&&f===o&&a!==k||!o&&g.length?l:(h.stop(W,k),s.isFunction(p)?p.call(h,o):p===k?h[u]():h.fadeTo(parseInt(r,10)||90,o?1:0,function(){o||h.hide()}),o||h.queue(function(t){h.css({left:"",top:""}),s(ze).length||h.detach(),t()}),a=o,n.destroyed&&(n=E),l)}}),l.init()},Te=new Te,s.extend(q.prototype,{init:function(t){var e=t.tooltip;return this.options.on?(t.elements.overlay=Te.elem,e.addClass(je).css("z-index",T.modal_zindex+s(ze).length),t._bind(e,["tooltipshow","tooltiphide"],function(t,i,o){var n=t.originalEvent;if(t.target===e[0])if(n&&"tooltiphide"===t.type&&/mouse(leave|enter)/.test(n.type)&&s(n.relatedTarget).closest(Te.elem[0]).length)try{t.preventDefault()}catch(r){}else(!n||n&&"tooltipsolo"!==n.type)&&this.toggle(t,"tooltipshow"===t.type,o)},this._ns,this),t._bind(e,"tooltipfocus",function(t,i){if(!t.isDefaultPrevented()&&t.target===e[0]){var o=s(ze),n=T.modal_zindex+o.length,r=parseInt(e[0].style.zIndex,10);Te.elem[0].style.zIndex=n-1,o.each(function(){this.style.zIndex>r&&(this.style.zIndex-=1)}),o.filter("."+Z).qtip("blur",t.originalEvent),e.addClass(Z)[0].style.zIndex=n,Te.update(i);try{t.preventDefault()}catch(a){}}},this._ns,this),t._bind(e,"tooltiphide",function(t){t.target===e[0]&&s(ze).filter(":visible").not(e).last().qtip("focus",t)},this._ns,this),i):this},toggle:function(t,e,s){return t&&t.isDefaultPrevented()?this:(Te.toggle(this.qtip,!!e,s),i)},destroy:function(){this.qtip.tooltip.removeClass(je),this.qtip._unbind(this.qtip.tooltip,this._ns),Te.toggle(this.qtip,k),delete this.qtip.elements.overlay}}),Ce=R.modal=function(t){return new q(t,t.options.show.modal)},Ce.sanitize=function(t){t.show&&("object"!=typeof t.show.modal?t.show.modal={on:!!t.show.modal}:t.show.modal.on===i&&(t.show.modal.on=W))},T.modal_zindex=T.zindex-200,Ce.initialize="render",M.modal={"^show.modal.(on|blur)$":function(){this.destroy(),this.init(),this.qtip.elems.overlay.toggle(this.qtip.tooltip[0].offsetWidth>0)}},s.extend(W,T.defaults,{show:{modal:{on:k,effect:W,blur:W,stealfocus:W,escape:W}}}),R.viewport=function(i,s,o,n,r,a,h){function l(t,e,i,o,n,r,a,h,l){var c=s[n],p=_[t],b=x[t],w=i===V,q=p===n?l:p===r?-l:-l/2,C=b===n?h:b===r?-h:-h/2,T=v[n]+y[n]-(f?0:u[n]),j=T-c,z=c+l-(a===A?g:m)-T,M=q-(_.precedance===t||p===_[e]?C:0)-(b===N?h/2:0);return w?(M=(p===n?1:-1)*q,s[n]+=j>0?j:z>0?-z:0,s[n]=Math.max(-u[n]+y[n],c-M,Math.min(Math.max(-u[n]+y[n]+(a===A?g:m),c+M),s[n],"center"===p?c-q:1e9))):(o*=i===$?2:0,j>0&&(p!==n||z>0)?(s[n]-=M+o,d.invert(t,n)):z>0&&(p!==r||j>0)&&(s[n]-=(p===N?-M:M)+o,d.invert(t,r)),v>s[n]&&-s[n]>z&&(s[n]=c,d=_.clone())),s[n]-c}var c,d,p,u,f,g,m,v,y,b=o.target,w=i.elements.tooltip,_=o.my,x=o.at,q=o.adjust,C=q.method.split(" "),T=C[0],j=C[1]||C[0],z=o.viewport,M=o.container,I=i.cache,W={left:0,top:0};return z.jquery&&b[0]!==t&&b[0]!==e.body&&"none"!==q.method?(u=M.offset()||W,f="static"===M.css("position"),c="fixed"===w.css("position"),g=z[0]===t?z.width():z.outerWidth(k),m=z[0]===t?z.height():z.outerHeight(k),v={left:c?0:z.scrollLeft(),top:c?0:z.scrollTop()},y=z.offset()||W,("shift"!==T||"shift"!==j)&&(d=_.clone()),W={left:"none"!==T?l(S,L,T,q.x,F,P,A,n,a):0,top:"none"!==j?l(L,S,j,q.y,D,O,B,r,h):0},d&&I.lastClass!==(p=X+"-pos-"+d.abbrev())&&w.removeClass(i.cache.lastClass).addClass(i.cache.lastClass=p),W):W},R.polys={polygon:function(t,e){var i,s,o,n={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10},adjustable:k},r=0,a=[],h=1,l=1,c=0,d=0;for(r=t.length;r--;)i=[parseInt(t[--r],10),parseInt(t[r+1],10)],i[0]>n.position.right&&(n.position.right=i[0]),i[0]<n.position.left&&(n.position.left=i[0]),i[1]>n.position.bottom&&(n.position.bottom=i[1]),i[1]<n.position.top&&(n.position.top=i[1]),a.push(i);if(s=n.width=Math.abs(n.position.right-n.position.left),o=n.height=Math.abs(n.position.bottom-n.position.top),"c"===e.abbrev())n.position={left:n.position.left+n.width/2,top:n.position.top+n.height/2};else{for(;s>0&&o>0&&h>0&&l>0;)for(s=Math.floor(s/2),o=Math.floor(o/2),e.x===F?h=s:e.x===P?h=n.width-s:h+=Math.floor(s/2),e.y===D?l=o:e.y===O?l=n.height-o:l+=Math.floor(o/2),r=a.length;r--&&!(2>a.length);)c=a[r][0]-n.position.left,d=a[r][1]-n.position.top,(e.x===F&&c>=h||e.x===P&&h>=c||e.x===N&&(h>c||c>n.width-h)||e.y===D&&d>=l||e.y===O&&l>=d||e.y===N&&(l>d||d>n.height-l))&&a.splice(r,1);n.position={left:a[0][0],top:a[0][1]}}return n},rect:function(t,e,i,s){return{width:Math.abs(i-t),height:Math.abs(s-e),position:{left:Math.min(t,i),top:Math.min(e,s)}}},_angles:{tc:1.5,tr:7/4,tl:5/4,bc:.5,br:.25,bl:.75,rc:2,lc:1,c:0},ellipse:function(t,e,i,s,o){var n=R.polys._angles[o.abbrev()],r=0===n?0:i*Math.cos(n*Math.PI),a=s*Math.sin(n*Math.PI);return{width:2*i-Math.abs(r),height:2*s-Math.abs(a),position:{left:t+r,top:e+a},adjustable:k}},circle:function(t,e,i,s){return R.polys.ellipse(t,e,i,i,s)}},R.svg=function(t,i,o){for(var n,r,a,h,l,c,d,p,u,f,g,m=s(e),v=i[0],y=s(v.ownerSVGElement),b=1,w=1,_=!0;!v.getBBox;)v=v.parentNode;if(!v.getBBox||!v.parentNode)return k;n=y.attr("width")||y.width()||parseInt(y.css("width"),10),r=y.attr("height")||y.height()||parseInt(y.css("height"),10);var x=(parseInt(i.css("stroke-width"),10)||0)/2;switch(x&&(b+=x/n,w+=x/r),v.nodeName){case"ellipse":case"circle":f=R.polys.ellipse(v.cx.baseVal.value,v.cy.baseVal.value,(v.rx||v.r).baseVal.value+x,(v.ry||v.r).baseVal.value+x,o);break;case"line":case"polygon":case"polyline":for(u=v.points||[{x:v.x1.baseVal.value,y:v.y1.baseVal.value},{x:v.x2.baseVal.value,y:v.y2.baseVal.value}],f=[],p=-1,c=u.numberOfItems||u.length;c>++p;)d=u.getItem?u.getItem(p):u[p],f.push.apply(f,[d.x,d.y]);f=R.polys.polygon(f,o);break;default:f=v.getBoundingClientRect(),f={width:f.width,height:f.height,position:{left:f.left,top:f.top}},_=!1}return g=f.position,y=y[0],_&&(y.createSVGPoint&&(a=v.getScreenCTM(),u=y.createSVGPoint(),u.x=g.left,u.y=g.top,h=u.matrixTransform(a),g.left=h.x,g.top=h.y),y.viewBox&&(l=y.viewBox.baseVal)&&l.width&&l.height&&(b*=n/l.width,w*=r/l.height)),g.left+=m.scrollLeft(),g.top+=m.scrollTop(),f},R.imagemap=function(t,e,i){e.jquery||(e=s(e));var o,n,r,a,h,l=e.attr("shape").toLowerCase().replace("poly","polygon"),c=s('img[usemap="#'+e.parent("map").attr("name")+'"]'),d=s.trim(e.attr("coords")),p=d.replace(/,$/,"").split(",");if(!c.length)return k;if("polygon"===l)a=R.polys.polygon(p,i);else{if(!R.polys[l])return k;for(r=-1,h=p.length,n=[];h>++r;)n.push(parseInt(p[r],10));a=R.polys[l].apply(this,n.concat(i))}return o=c.offset(),o.left+=Math.ceil((c.outerWidth(k)-c.width())/2),o.top+=Math.ceil((c.outerHeight(k)-c.height())/2),a.position.left+=o.left,a.position.top+=o.top,a};var Me,Ie='<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';"  style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';s.extend(C.prototype,{_scroll:function(){var e=this.qtip.elements.overlay;e&&(e[0].style.top=s(t).scrollTop()+"px")},init:function(i){var o=i.tooltip;1>s("select, object").length&&(this.bgiframe=i.elements.bgiframe=s(Ie).appendTo(o),i._bind(o,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=s("<div/>",{id:X+"-rcontainer"}).appendTo(e.body),i.elements.overlay&&i.elements.overlay.addClass("qtipmodal-ie6fix")&&(i._bind(t,["scroll","resize"],this._scroll,this._ns,this),i._bind(o,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var t,e,i=this.qtip.tooltip,s={height:i.outerHeight(k),width:i.outerWidth(k)},o=this.qtip.plugins.tip,n=this.qtip.elements.tip;e=parseInt(i.css("borderLeftWidth"),10)||0,e={left:-e,top:-e},o&&n&&(t="x"===o.corner.precedance?[A,F]:[B,D],e[t[1]]-=n[t[0]]()),this.bgiframe.css(e).css(s)},redraw:function(){if(1>this.qtip.rendered||this.drawing)return this;var t,e,i,s,o=this.qtip.tooltip,n=this.qtip.options.style,r=this.qtip.options.position.container;return this.qtip.drawing=1,n.height&&o.css(B,n.height),n.width?o.css(A,n.width):(o.css(A,"").appendTo(this.redrawContainer),e=o.width(),1>e%2&&(e+=1),i=o.css("maxWidth")||"",s=o.css("minWidth")||"",t=(i+s).indexOf("%")>-1?r.width()/100:0,i=(i.indexOf("%")>-1?t:1)*parseInt(i,10)||e,s=(s.indexOf("%")>-1?t:1)*parseInt(s,10)||0,e=i+s?Math.min(Math.max(e,s),i):e,o.css(A,Math.round(e)).appendTo(r)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([t,this.qtip.tooltip],this._ns)}}),Me=R.ie6=function(t){return 6===oe.ie?new C(t):k},Me.initialize="render",M.ie6={"^content|style$":function(){this.redraw()}}})})(window,document);
-//@ sourceMappingURL=http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.map
\ No newline at end of file
+//@ sourceMappingURL=https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.map
index 6236344..01a0c91 100644 (file)
@@ -2,15 +2,13 @@
 <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>
+                       <a href="/"><img src="{{ STATIC_URL }}img/fibre-logo.gif" alt="FIBRE - Future Internet Testbeds Experimentation Between Brazil and Europe" width="150px" height="75px" /></a>
                </div>
                
                <div id="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 target="_blank" href="http://intranet.onelab.eu">Intranet</a></li>
+                               <li><a target="_blank" href="http://www.fibre-ict.eu/">Public Website</a></li>
                        </ul>
                </div>
        </div>
index 237cfa6..b282727 100644 (file)
@@ -86,7 +86,7 @@ $(document).ready(function() {
 <body ng-app="ManifoldApp">
 {% block container %}
        {% block topmenu %}
-       {% widget "_widget-topmenu.html" %}
+       {% widget "__widget-topmenu.html" %}
        {% endblock topmenu %}
        {% include 'messages-transient.html' %}
        {% block base_content %}
diff --git a/portal/templates/fibre/fibre__widget-login-fed-manager.html b/portal/templates/fibre/fibre__widget-login-fed-manager.html
new file mode 100644 (file)
index 0000000..638ff81
--- /dev/null
@@ -0,0 +1,35 @@
+<div class="well login-widget" style="background:none;border:none;width:400px;">
+       {% if state %}
+       <span class="help-block">{{ state }}</span>
+       {% endif %}
+       <form action="/login/" method="post" role="form">
+         {% csrf_token %}
+         {% if next %}
+         <input type="hidden" name="next" value="{{ next }}" />
+         {% endif %}
+       <div class="form-group" style="color:white;">
+       <label for="fed"></label>
+       <input type="radio" name="base" value="br" checked>
+               <img src="{{ STATIC_URL }}img/fibre/br.png" alt="Brazil" height="32" width="40" />
+       <input type="radio" name="base" value="eu">
+               <img src="{{ STATIC_URL }}img/fibre/eu.png" alt="Europe Union" height="32" width="32" />
+       <input type="radio" name="base" value="local">&nbsp;Local User
+       </div>
+
+       <div class="form-group">
+       <label for="username">Email address / Username</label>
+       <input type="email" class="form-control" name="username" placeholder="Enter Email / username">
+       </div>
+       <div class="form-group">
+       <label for="password">Password</label>
+       <input type="password" class="form-control" name="password" placeholder="Password">
+       </div>
+       <div class="login-submit">
+               <input class="btn btn-default" type="submit" 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">
+               Don't have an account? <a href="/portal/register">Sign up now</a>
+       </div>
+       </form>
+</div>
diff --git a/portal/templates/fibre/fibre__widget-login-manager.html b/portal/templates/fibre/fibre__widget-login-manager.html
new file mode 100644 (file)
index 0000000..7c5f170
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="well">
+       {% if state %}
+       <span class="help-block">{{ state }}</span>
+       {% endif %}
+       <form action="/login/" method="post" role="form">
+         {% csrf_token %}
+         {% if next %}
+         <input type="hidden" name="next" value="{{ next }}" />
+         {% endif %}
+       <div class="form-group">
+       <label for="username">Email address / Username</label>
+       <input type="email" class="form-control" name="username" placeholder="Enter Email / username">
+       </div>
+       <div class="form-group">
+       <label for="password">Password</label>
+       <input type="password" class="form-control" name="password" placeholder="Password">
+       </div>
+       <div class="login-submit">
+               <input class="btn btn-default" type="submit" 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">
+               <a href="/portal/register">Try</a>, <a href="/portal/register">Sign Up</a> or <a href="/portal/join">Join</a>
+       </div>
+       </form>
+</div>
diff --git a/portal/templates/fibre/fibre__widget-topmenu.html b/portal/templates/fibre/fibre__widget-topmenu.html
new file mode 100644 (file)
index 0000000..2a73376
--- /dev/null
@@ -0,0 +1,70 @@
+{% 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/fibre-logo.gif" alt="FIBRE - Future Internet Testbeds Experimentation Between Brazil and Europe" width="150px" height="75px" /></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="/portal/institution">MANAGEMENT</a></li>
+                                {%endif%}
+                               <li><a href="/portal/support/">SUPPORT</a></li>
+                       </ul>
+               </div>
+               {% else %}
+               <div class="col-sm-4 col-md-4 navigation">
+               </div>
+               {% endif %}
+               <div class="col-sm-5 col-md-5 secondary">
+                       <ul>
+                               <li><a href="/portal/about">About</a></li>
+                               <li><a target="_blank" href="http://www.fibre-ict.eu/">Public Website</a></li>
+                       </ul>
+                       {% if username %}
+                       <div class="account">You are logged in as &nbsp;<a href="/portal/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>
+</div>
+</div>
+
+<div class="row">
+{% widget '_widget-message.html' %}
+</div>
+<script>
+       $(document).ready(function() {
+               $('li.slices').mouseenter(function() {
+                       $('div#menu-slice-list').fadeIn(100);
+               });
+               $('div#menu-slice-list').mouseleave(function(e) {
+                       if (!$('li.slices').is(":hover")) {
+                               $(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>
diff --git a/portal/templates/fibre/fibre_about.html b/portal/templates/fibre/fibre_about.html
new file mode 100644 (file)
index 0000000..5b7eb96
--- /dev/null
@@ -0,0 +1,104 @@
+{% extends "layout.html" %}
+
+{% block content %}
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                </div>
+       </div>
+</div>
+<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="#components">Underlying technologies</a></li>
+        </ul>
+    </div>
+</div>
+
+
+<div class="tab-content">
+    <div class="tab-pane active row" id="about">
+               <div class="col-md-12">
+                       <p>
+                               OneLab Portal is a central place to get acess to all OneLab testbeds.In order to get access to the portal,
+                               an experimenter needs to  <a href="/portal/register">register</a> to the portal. The portal administrative body
+                               is responsible to accept or reject newly registered users.   
+                       </p>
+                       <p>
+                               To learn more about OneLab visit:  <a href="http://onelab.eu/" target="_blank">http://onelab.eu/</a>                    
+                       </p>
+                       <p>
+                               If you have any questions regarding using the portal visit: <a href="/portal/support">OneLab support</a>
+                       </p>
+                       <p>
+                               OneLab portal is a community effot. To get more information about OneLab portal team visit: 
+                               <a href="http://myslice.info/community" target="_blank">http://myslice.info/community</a>
+                       </p>
+               </div>
+       </div>
+       <div class="tab-pane row" id="components">
+               <div class="col-md-12">
+                       <h3>A ready-made and easily customisable user interface for your testbed.</h3>
+                               <p>
+                                       MySlice is an ambitious project aiming to support researchers throughout the lifecycle of experiments that can run on a variety 
+                                       of testbeds spanning different administrative domains and networking technologies. Its basic principle is to bring together 
+                                       available resources with useful information (characteristics, performance, network measurements).
+                               </p>
+                               <p>
+                                       MySlice inititiave started in Janury 2011 by offering annotation services for the first ederated experimental resources. Today, 
+                                       MySlice has taken a big step toward becoming a tand-alone web framework, which will present all available resources from testbeds 
+                                       across the world, interconnected through the Slice-based Facility Architecture (SFA) and annotated by the TopHat measurement system.
+                               </p>
+                               <p>
+                                       Our framework is built with standard programming tools (python and javascript for the front-end and python for the back-end) 
+                                       and has a modular structure based on the concept of plugins for implementing different core functionalities (query editing, 
+                                       data display, and resource allocation).
+                               </p>
+                               <p>
+                                       The goal is to enable developers with expertise on different testbed technologies and different experimental 
+                                       practices to work in parallel for optimizing the tools presented to the users allowing them for a wide range of choices 
+                                       according to their own requirements. Opening in this way the development of web-based user tools for experimentation and 
+                                       sharing effort and information can increase significantly the chances for the achievement of our challenging objective.
+                               </p>
+               </div>
+               <div class="col-md-12">
+                       <h3>Portal Components</h3>
+                               <h5>Myslice (Web Frontend)</h5>
+                                       <p>
+                                               A full-fledged and modular web portal for a testbed federation allowing user to register, 
+                                               request slices and browse and book resources, with a strong emphasis on measurements.
+                                       </p>
+                                       <p> More Info: <a href="http://myslice.info/" target="_blank">http://myslice.info/</a></p>
+                                       <p> Code: <a href="http://git.onelab.eu/?p=myslice.git;a=summary" target="_blank">Git Repository</a> (read only)</p> 
+                                       <p> 
+                                               If you need write access to the git repository you need first to send your public key to <a href="mailto:support@myslice.info">support@myslice.info</a>.
+                                       </p>
+
+
+                               <h5>Manifold (Portal backend)</h5>
+                                       <p>
+                                               Manifold is the backend that is running behind the portal. It is a component allowing the integration of distributed 
+                                               and heterogeneous data sources, such as measurement platforms or data repositories.
+                                       </p>
+                                       <p> Documentation: <a href="http://trac.myslice.info/" target="_blank">http://trac.myslice.info/</a></p>
+                                       <p> Code: <a href="https://git.top-hat.info/?p=tophat.git;a=shortlog;h=refs/heads/devel" target="_blank">Git Repository</a> (read only)</p>     
+
+                               <h5>OneLab Registry</h5>
+                                       <p>It's a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper (Registry Only mode).</p>
+                                       <p> More Info: <a href="http://svn.planet-lab.org/wiki/SfaDeveloperRegistryTutorial#RunninginRegistry-Onlymode" target="_blank">SFA Registry</a></p>
+       </div>
+   </div>
+</div>
+
+<script>
+$(document).ready(function() {
+    $('.nav-tabs a').click(function (e) {
+        e.preventDefault();
+        $(this).tab('show');
+    });
+});
+</script>
+
+
+{% endblock %}
diff --git a/portal/templates/fibre/fibre_account-view.html b/portal/templates/fibre/fibre_account-view.html
new file mode 100644 (file)
index 0000000..9941e97
--- /dev/null
@@ -0,0 +1,332 @@
+{% extends "layout.html" %}
+{% block content %}
+
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                        Account &nbsp;>&nbsp; {{ person.email }}
+                </div>
+       </div>
+</div>
+{% if messages %}
+<ul class="messages">
+    {% for message in messages %}
+    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
+    {% endfor %}
+</ul>
+{% endif %}
+<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="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>
+                                               <td colspan="2">
+                                                               <div><h3>Platform: Myslice</h3></div>
+                                               </td>
+                                       </tr>
+                                       <tr>
+                                               <td class="key">Email</td>
+                                               <td class="value">
+                                                               <span id="emailval" class="value" >{{ person.email }}</span>
+                                                               <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>
+                                       <tr class="odd">
+                                                       <td class="key">Password</td>
+                                                       <td class="value"> 
+                                                               <button class="btn btn-default btn-xs" type="button" title="Password" name="edit_pass" id="edit_pass">
+                                                                       <span class="glyphicon glyphicon-edit"></span> Edit
+                                                               </button>
+                                                               <span id="passval"class="value">******** </span>
+                                                               <span class="hide_this" id="span_pass">
+                                                               <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_pass_change"> Cancel </button>
+                                                               <div style='display:none;' id="pass_form">
+                                                               <input type='hidden'  value='' /></div>
+                                                               <table id="edit_password">
+                                                                       <tr>
+                                                                                       <td>Enter password: </td>
+                                                                                       <td class="field"> <input type="password" name="password" id="password" /> </td>
+                                                                               </tr>
+                                                                               <tr>
+                                                                                       <td>Confirm password: </td>
+                                                                                       <td class="field"> 
+                                                                                               <input type="password" name="confirmpassword" id="confirmpassword" /> 
+                                                                                               <input type="submit" class="btn btn-default btn-xs" name="submit_pass" value="Save"/> 
+                                                                                       </td>
+                                                                       </tr>
+                                                               </table>
+                                                               </span> 
+                                                       </td>
+                                       </tr>
+                                       <tr class="even">
+                                                       <td class="key">Full Name</td>
+                                                       <td class="value">
+                                                               <span id="nameval" class="value" >{{ fullname }} </span>
+                                                               <span class="hide_this" id="span_name">
+                                                               <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_name_change"> Cancel </button> 
+                                                               <div style='display:none;'><input type='hidden'  name='nameform'  /></div>
+                                                               <input id="fname" type="text" name="fname" class="required"  maxlength="200" value="{{firstname}}" />
+                                                               <input id="lname" type="text" name="lname" class="required"  maxlength="200" value="{{lastname}}" />
+                                                               <input type="submit" class="btn btn-default btn-xs" name="submit_name" value="Save"/>
+                                                               </span>
+                                                               <button class="btn btn-default btn-xs" type="button"title="Full Name" id="edit_name">
+                                                                       <span class="glyphicon glyphicon-edit"></span> Edit
+                                                               </button>
+                                                       </td>
+                                       </tr>
+                                       <tr class="odd">
+                                                       <td class="key">Authority</td>
+                                                       <td class="value">
+                                                               <span id="affval" class="value">{{ authority }}</span>
+                                                                <button class="btn btn-default btn-xs" type="button" id="edit_auth" onclick="editAlert()"  title="To change your authority please contact the administrator">
+                                                               <span class="glyphicon glyphicon-question-sign"></span> Edit
+                                                                </button>
+                                                       </td>
+                                               </tr>
+                                               {%if 'Enabled'  in user_status %}
+                                               <tr class="even">
+                                                       <td class="key">Generate Keys</td>
+                                                       <td>
+                                                               <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> 
+                                       </tr>
+                                       <tr class="odd">
+                                               <td class="key">Public Key</td>
+                                               <td class="value">
+                                                               <span id="keyval" class="value">******** </span>
+                                                               <span class="hide_this" id="span_upload">
+                                                                       <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"/>  
+                                                                               <input class="btn btn-default btn-xs" name="upload_key" id="upload_key"  type="submit" title="Upload your public key" value="Upload"
+                                                                                  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">
+                                                                       <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">
+                                                                       <span class="glyphicon glyphicon-upload"></span> Upload
+                                                               </button>       
+                                               </td>
+                                       </tr>
+                                       <tr class="even" id="pkey_row">
+                                                {%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">
+                                                                       <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.');"/> 
+                                               </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">
+                                                               <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">
+                                               <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>
+                                               </td>
+                                               </tr>
+                                               {%endif%}
+                                       </table>
+                       
+               </div>
+       </div>
+
+       <div class="tab-pane row" id="account">
+               <div class="col-md-12">
+       
+               <h3>Principal Account <small>Account used for delegating credentials</small></h3>
+               <table class="table"> 
+                       <tr class="odd"> 
+                       <th>Platform</th> 
+                       <th>Account Type</th>
+                               <th>Account Delegation</th>
+                       <th>User hrn</th>
+                               <th>User Status</th>
+                       <!--<th>Pub Key</th> -->
+               </tr>   
+                       {% for row in principal_acc %}         
+                       <tr class="border_bottom">
+                       <td class="odd"> {{ row.platform_name }} </td>
+                       <td class="odd"> {{ row.account_type }} </td>
+                               <td class="odd"> {{ row.delegation_type }} </td>
+                               <td class="odd"> {{ row.usr_hrn }}  </td>
+                               <td class="odd"> {{ row.user_status }}  </td>
+               <!--    <td class="even"> {{ row.usr_pubkey }} </td> -->
+               </tr> 
+                       {%endfor%}               
+               </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%}
+               </div>
+       </div>
+
+       <div class="tab-pane row" id="access">
+               <div class="col-md-12">
+       
+               <h3>Testbed Access <small>Reference Accounts in the following testbeds</small></h3>
+        <table class="mytable table table-bordered table-hover"> 
+            <tr class="odd"> 
+                <th>Platform</th> 
+                <th>Account Type</th>
+                               <th>Reference to</th>
+                               <th>Remove Account</th>
+            </tr>   
+            {% for row in ref_acc %}         
+            <tr class="border_bottom">
+                <td class="odd"> {{ row.platform_name }} </td>
+                <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">
+                                               <span class="glyphicon glyphicon-minus"></span>
+                                       </button>
+                               </td>
+            </tr> 
+            {%endfor%}               
+        </table>               
+               
+               
+               <h3>Add reference account to the following testbeds</h3>
+        <table class="mytable table table-bordered table-hover"> 
+            <tr class="odd"> 
+                <th>Platforms</th> 
+                <th>Add Account</th>
+            </tr>   
+            {% for platform in platform_list %}         
+            <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">
+                                               <span class="glyphicon glyphicon-plus"></span>
+                                       </button>
+                               </td>
+            </tr> 
+            {%endfor%}               
+        </table>
+       </div>
+{%endif%} 
+</div>
+</form>
+</div>
+
+<script>
+    $(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+                       e.preventDefault();
+                       $(this).tab('show');
+                       id = $(this).attr('href').substr(1);
+               
+               });
+               
+        $('button#createslice').click(function() {
+            window.location="/portal/slice_request/";
+        });
+    });
+</script>
+
+{% endblock %}
diff --git a/portal/templates/fibre/fibre_base.html b/portal/templates/fibre/fibre_base.html
new file mode 100644 (file)
index 0000000..2d9d53e
--- /dev/null
@@ -0,0 +1,49 @@
+{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
+<html lang="en"><head>
+<title>OneLab - {{ section }}</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<link rel="shortcut icon" href="/static/img/myslice-icon.png">
+{# 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>
+<script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
+<script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
+<script src="{{ STATIC_URL }}js/myslice.js"></script>
+<script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
+<style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
+{{ header_prelude }}
+{% block head %} {% endblock head %}
+{# let's add these ones no matter what #}
+{% insert_str prelude "js/jquery.min.js" %}
+{% insert_str prelude "js/angular/angular.min.js" %}
+{% insert_str prelude "js/jquery.html5storage.min.js" %}
+{% insert_str prelude "js/messages-runtime.js" %}
+{% insert_str prelude "js/class.js" %}
+{% insert_str prelude "js/plugin-helper.js" %}
+{% insert_str prelude "js/mustache.js" %}
+{% insert_str prelude "js/hashtable.js" %}
+{% insert_str prelude "js/plugin.js" %}
+{% insert_str prelude "js/manifold.js" %}
+{% insert_str prelude "css/manifold.css" %}
+{% insert_str prelude "css/plugin.css" %}
+{% insert_str prelude "js/bootstrap.js" %}
+{% insert_str prelude "css/bootstrap.css" %}
+{% insert_str prelude "js/bootstrap-datepicker.js" %}
+{% insert_str prelude "css/datepicker.css" %}
+{% insert_str prelude "js/bootstrap-slider.js" %}
+{% insert_str prelude "css/slider.css" %}
+{% insert_str prelude "css/topmenu.css" %}
+{% insert_str prelude "js/logout.js" %}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/{{ theme }}.css">
+</head>
+<body ng-app="ManifoldApp">
+{% block container %}
+       {% block topmenu %}
+       {% include theme|add:"_widget-topmenu.html" %}
+       {% endblock topmenu %}
+       {% include 'messages-transient.html' %}
+       {% block base_content %}
+       {% endblock %}
+{% endblock container %}
+</body>
+</html>
diff --git a/portal/templates/fibre/fibre_contact.html b/portal/templates/fibre/fibre_contact.html
new file mode 100644 (file)
index 0000000..21608da
--- /dev/null
@@ -0,0 +1,40 @@
+{% extends "layout.html" %}
+
+{% block head %}
+{{ wizard.form.media }}
+{% endblock %}
+
+{% block content %}
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                        Support &nbsp;>&nbsp; Contact
+                </div>
+       </div>
+</div>
+<div class="row">
+       <div class="col-md-12">
+       <p>Please check our <a href="/portal/support/">FAQ</a> section. Most of the basic problems are explained there.</p>
+       <p>
+       If you haven't find your answes in the FAQ, please contact us by filling the form below.<br />
+       You can also <a href="mailto:support@myslice.info">e-mail</a> us directly.
+       </p>
+       </div>
+</div>
+
+<div class="row">
+       <div class="col-md-4">
+               <form role="form" method="post">
+               {% csrf_token %}
+               {% for field in form %}
+           <div class="form-group">
+               <label for="{{ field.html_name }}" class="control-label">{{ field.label }}</label>
+               {{ field.errors }} {{ field }}
+           </div>
+           {% endfor %}
+               <button type="submit" class="btn btn-onelab">Create ticket</button>
+               </form>
+       </div>
+</div>
+{% endblock %}
+
diff --git a/portal/templates/fibre/fibre_home-view.html b/portal/templates/fibre/fibre_home-view.html
new file mode 100644 (file)
index 0000000..e8ec0ad
--- /dev/null
@@ -0,0 +1,184 @@
+{% extends "layout_base.html" %}
+{% load portal_filters %}
+
+{% block content %}
+<!-- <div class="row">
+{% widget '_widget-news.html' %}
+</div> -->
+{% if username %}
+<div class="container dashboard">
+       <div class="row">
+               {%if 'is_pi'  in 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> 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'."
+                                       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 %}
+                       <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>
+                       </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>
+               </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 %}
+                       <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-1"></div>
+               <div class="col-sm-5 slogan">
+                       <h2>
+                               FIBRE: Future Internet testbeds experimentation between Brazil and Europe
+                       </h2>
+                       <h3>
+                               Access variety of testbeds through your account
+                       </h3>
+               </div>
+               <div class="col-sm-5 col-sm-offset-1">
+                       <div class="row">
+                           {% include 'fibre__widget-login-fed-manager.html' %}
+                               <a href="/cafe" style="margin-left:80px;"><img src="{{ STATIC_URL }}img/fibre/cafe.jpg" alt="CAFe authentication" /></a>
+                       </div>
+               </div>
+               <div class="col-sm-1"></div>
+       </div>
+</div>
+{% endif %}
+
+
+<script type="text/javascript">
+       $(document).ready(function() {
+               $('a.home-tab').click(function() {
+                       $('ul.nav-tabs li').removeClass('active');
+                       $(this).parent().addClass('active');
+                       $('div.home-panel').hide();
+                       $('div#'+$(this).data('panel')).show();
+               });
+               $('button#validaterequestbtn').click(function() {
+                       window.location="/portal/institution#requests";
+               });
+               $('button#ticketbtn').click(function() {
+                       window.location="/portal/contact/";
+               });
+               $('button#signupbtn').click(function() {
+                       window.location="/portal/register/";
+               });
+               $('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
+--------*/
+});
+</script>
+{% endblock %}
diff --git a/portal/templates/fibre/fibre_institution.html b/portal/templates/fibre/fibre_institution.html
new file mode 100644 (file)
index 0000000..09b9071
--- /dev/null
@@ -0,0 +1,226 @@
+{% 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 class="col-md-6">
+               <div>
+                       <img src="{{ STATIC_URL|add:'img/institutions/'|add:authority.authority_hrn|add:'.gif'|file_exists }}" alt="{{authority.name}}">
+               </div>
+               <br />
+               <h3><a href="{{authority.url}}">{{authority.name}}</a></h3>
+               <p>
+                       {{authority.address}} <br />
+                       {{authority.postcode}} {{authority.city}} <br />
+                       {{authority.country}}
+               </p>
+               <br />
+               <h4>Onelab membership</h4> 
+               <p>
+                       {{ authority.onelab_membership }}
+               </p>
+        </div>
+        <div class="col-md-6">
+               <h4>Legal Contact:</h4>
+               <p>
+               {% for c in authority_contacts.legal %}
+                        {{ c }} <br />
+               {% endfor %}
+               </p>
+               <br />
+               <h4>Scientific Contact:</h4>
+               <p>
+               {% for c in authority_contacts.scientific %}
+                       {{ c }} <br />
+               {% endfor %}
+               </p>
+               <br />
+               <h4>Technical Contact:</h4>
+               <p>
+               {% for c in authority_contacts.technical %}
+                       {{ c }} <br />
+               {% endfor %}
+               </p>
+        </div>
+        <script>
+        $(document).ready(function() {
+            $('#authority_name').text("{{ authority.name|default:authority.authority_hrn }}");
+        });
+        </script>
+       </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>Expiration</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/",{'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;
+                }
+                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){
+                    slice_url="";
+                }else{
+                    slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_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_expires+"</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/",{'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 %}
diff --git a/portal/templates/fibre/fibre_management-tab-about.html b/portal/templates/fibre/fibre_management-tab-about.html
new file mode 100644 (file)
index 0000000..30fd067
--- /dev/null
@@ -0,0 +1,45 @@
+{% load portal_filters %}
+<div class="col-md-6">
+       <div>
+               <img src="{{ STATIC_URL|add:'img/institutions/'|add:authority.authority_hrn|add:'.gif'|file_exists }}" alt="{{authority.name}}">
+       </div>
+       <br />
+       <h3><a href="{{authority.url}}">{{authority.name}}</a></h3>
+       <p>
+               {{authority.address}} <br />
+               {{authority.postcode}} {{authority.city}} <br />
+               {{authority.country}}
+       </p>
+       <br />
+       <h4>Onelab membership</h4> 
+       <p>
+               {{ authority.onelab_membership }}
+       </p>
+</div>
+<div class="col-md-6">
+       <h4>Legal Contact:</h4>
+       <p>
+       {% for c in authority_contacts.legal %}
+                {{ c }} <br />
+       {% endfor %}
+       </p>
+       <br />
+       <h4>Scientific Contact:</h4>
+       <p>
+       {% for c in authority_contacts.scientific %}
+               {{ c }} <br />
+       {% endfor %}
+       </p>
+       <br />
+       <h4>Technical Contact:</h4>
+       <p>
+       {% for c in authority_contacts.technical %}
+               {{ c }} <br />
+       {% endfor %}
+       </p>
+</div>
+<script>
+$(document).ready(function() {
+    $('#authority_name').text("{{ authority.name|default:authority.authority_hrn }}");
+});
+</script>
diff --git a/portal/templates/fibre/fibre_management-tab-requests.html b/portal/templates/fibre/fibre_management-tab-requests.html
new file mode 100644 (file)
index 0000000..488e63e
--- /dev/null
@@ -0,0 +1,226 @@
+<script type="text/javascript">
+       $(document).ready(function() {
+               $("li#nav-request").addClass("active");
+       });
+       function on_click_event() {
+               var ids = []; 
+               $('.portal__validate__checkbox').each(function(i, el) {
+                       if ($(el).prop('checked')) {
+                               // portal__validate__checkbox__slice__2
+                               var id_array = $(el).attr('id').split('__');
+                               // push(slice__2)
+                               ids.push(id_array[3] + '__' + id_array[4]);
+                       }
+               });
+               if (ids.length > 0) {
+                       var id_str = ids.join('/');
+                       // XXX spinner
+                       $.getJSON('/portal/validate_action/' + id_str,
+                               function(status) {
+                                       $.each(status, function(request_type__id, request_status) {
+                                               // request_status: NAME -> dict (status, description)
+                                               var status_str = '';
+                                               $.each(request_status, function(name, result) {
+                                                       if (status_str != '')
+                                                               status_str += ' -- ';
+
+                                                       if (result.status) {
+                                                               status_str += '<font color="green">OK</font>';
+                                                               $('#portal__validate__checkbox__' + request_type__id).hide();
+                                                       } else {
+                                                               status_str += '<font color="red">ERROR: ' + result.description + '</font>';
+                                                       }
+                                               });
+                                               $('#portal__status__' + request_type__id).html(status_str);
+
+
+                                       });
+                               }
+                       );
+               }
+       }
+</script>
+
+<div class="col-md-12">
+       <h2>Authorities</h2>
+</div>
+{% if my_authorities %}
+       
+       {% for authority, requests in my_authorities.items %}
+       
+       <div class="col-md-12">
+               <h2>{{authority}}</h2>
+       </div>
+       
+    <table class="table">
+      <th>
+        <td>Type</td>
+        <td>Id</td>
+        <td>Details</td>
+        <td>Timestamp</td>
+        <td>Status</td>
+      </th>
+    {% for request in requests %}
+
+         <tr>
+               <td>
+               {% if request.allowed == 'allowed' %}
+               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+               {% else %}
+                       {% if request.allowed == 'expired' %}
+                               expired
+                       {% else %} {# denied #}
+                               denied
+                       {% endif %}
+               {% endif %}
+               </td>
+               <td>{{ request.type }}</td>
+               <td>{{ request.id }}</td>
+               <td>
+        {% if request.type == 'user' %}
+        Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+        {% 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}}
+            {% else %} {# authority #}
+        Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+            {% endif %}
+        {% endif %}
+               </td>
+               <td>{{ request.timestamp }}</td>
+               
+               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+
+    <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+         </tr>
+
+    {% endfor %}
+       </table>
+       {% endfor %}
+
+{% else %}
+       <div class="col-md-12">
+               <i>There is no pending request waiting for validation.</i>
+       </div>
+{% endif %}
+<div>nnllknjkn<br /><br /></div>
+<div class="col-md-12">
+       <h2>Sub-Authorities</h2>
+</div>
+{% if sub_authorities %}
+       
+       {% for authority, requests in sub_authorities.items %}
+       <div class="col-md-12">
+               <h2>{{authority}}</h2>
+       </div>
+       
+       <table class="table">
+             <th>
+               <td>Type</td>
+               <td>Id</td>
+               <td>Details</td>
+               <td>Timestamp</td>
+               <td>Status</td>
+             </th>
+           {% for request in requests %}
+                 <tr>
+                       <td>
+                       {% if request.allowed == 'allowed' %}
+                       <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+                       {% else %}
+                               {% if request.allowed == 'expired' %}
+                                       expired
+                               {% else %} {# denied #}
+                                       denied
+                               {% endif %}
+                       {% endif %}
+                       </td>
+                       <td>{{ request.type }}</td>
+                       <td>{{ request.id }}</td>
+                       <td>
+               {% if request.type == 'user' %}
+               Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+               {% 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}}
+                   {% else %} {# authority #}
+               Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+                   {% endif %}
+               {% endif %}
+                       </td>
+                       <td>{{ request.timestamp }}</td>
+                       
+                       <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+       
+           <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+                 </tr>
+           {% endfor %}
+       </table>
+       {% endfor %}
+{% else %}
+<div class="col-md-12">
+       <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+
+<div class="col-md-12">
+       <h2>Authorities with delegation</h2>
+</div>
+
+{% if delegation_authorities %}
+       
+       {% for authority, requests in delegation_authorities.items %}
+       <div class="col-md-12">
+               <h3>{{authority}}</h3>
+       </div>
+       <table class="table">
+                     <th>
+                       <td>Type</td>
+                       <td>Id</td>
+                       <td>Details</td>
+                       <td>Timestamp</td>
+                       <td>Status</td>
+                     </th>
+                   {% for request in requests %}
+                         <tr>
+                               <td>
+                               {% if request.allowed == 'allowed' %}
+                               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+                               {% else %}
+                                       {% if request.allowed == 'expired' %}
+                                               expired
+                                       {% else %} {# denied #}
+                                               denied
+                                       {% endif %}
+                               {% endif %}
+                               </td>
+                               <td>{{ request.type }}</td>
+                               <td>{{ request.id }}</td>
+                               <td>
+                       {% if request.type == 'user' %}
+                       Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+                       {% 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}}
+                           {% else %} {# authority #}
+                       Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+                           {% endif %}
+                      {% endif %}
+                               </td>
+                               <td>{{ request.timestamp }}</td>
+                               
+                               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+               
+                   <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+                         </tr>
+                   {% endfor %}
+       </table>
+               {% endfor %}
+{% else %}
+<div class="col-md-12">
+       <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+<div class="col-md-12">
+       <button class="btn btn-onelab" type="button" id="portal__validate" onclick="on_click_event();"><span class="glyphicon glyphicon-ok"></span> Validate</button>
+</div>
diff --git a/portal/templates/fibre/fibre_news.html b/portal/templates/fibre/fibre_news.html
new file mode 100644 (file)
index 0000000..69b417d
--- /dev/null
@@ -0,0 +1,21 @@
+{% extends "layout_wide.html" %}
+
+{% block content %}
+<div class="container">
+    <div class="row">
+        <div class="col-md-12">
+               <h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="News" />News</h1>
+               <br />
+        </div>
+    </div>
+       <div class="row">
+        <div class="col-md-12">
+               <b>15 July 2014</b> - The <b>OneLab</b> Portal opens with the <b>PlanetLab Europe</b>, <b>IOTLab</b> and <b>NITOS</b> testbeds!
+               <p>
+                       Existing PlanetLab users will be able to open an account with their existing PLE credentials.
+               </p>
+               </div>
+       </div>
+</div>
+{% endblock %}
diff --git a/portal/templates/fibre/fibre_registration_view.html b/portal/templates/fibre/fibre_registration_view.html
new file mode 100644 (file)
index 0000000..474a1b8
--- /dev/null
@@ -0,0 +1,213 @@
+{% extends "layout.html" %}
+
+{% 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">
+       <div class="col-md-12">
+               <p><strong>Questions? <a href="/portal/contact" >Contact us.</a></strong></p>
+  </div>
+</div>
+{% if errors %}
+<ul>
+  {% for error in errors %}
+  <li>{{ error }}</li>
+  {% endfor %}
+</ul>
+{% 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">
+                               {% csrf_token %}
+                               <label for="authority_hrn" class="control-label">Organization</label>
+                               <p></p>
+                               <input id="authority_hrn" 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. If it is not in the list, 
+                               please request its addition by clicking the link below. 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 />
+                               <p></p>
+                               <p>Organization not listed? <a href="/portal/join">Request its addition now.</a></p>
+                       </div>
+       </div>
+</div>
+
+<div class="row">
+       <div class="col-md-6">
+       
+           <div class="form-group">
+                       <label for="firstname" class="control-label">Personal information</label>
+                       <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">
+                       <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>
+       </div>  
+
+       <div class="col-md-6">
+           <div class="form-group">
+             <label for="password" class="control-label">Authentication</label>
+                 <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">
+                       <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">
+                       <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">
+               <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 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>
+                       </div>
+           </div>
+       </div>
+</div>
+<div class="row">
+       <div class="col-md-12">
+               <div class="form-group">
+                       <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>
+       </div>
+</div>
+<div class="row">
+       <div class="col-md-12">
+               <div class="form-group" id="register">
+                       <p></p> 
+               <input class="submit btn btn-onelab" type="submit" value="Sign up" />
+
+           </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 align="left">
+                                       Fibre: Future Internet testbeds experimentation between Brazil and Europe
+                                       <br/>
+                                               <a href="/portal/terms" target="_blank">[Printable format]</a>
+                                               </p>
+                                       <h1 align="left">1 Context</h1>
+                                       <p align="left">
+                    The main goal of the FIBRE project is the design, implementation and validation of a shared Future Internet research facility, supporting the joint experimentation of European and Brazilian researchers. In order to achieve this goal the project will carry out four main activities:
+                    </p>
+                                       <p align="left">
+                    The development and operation of a new experimental facility in Brazil, including the setup of equipment to support experimentation with various technologies (fixed layer 2 and layer 3, wireless, optical) as well as the design and implementation of a control framework to automate the use and operation of the testbed.
+                    </p>
+                                       <p align="left">
+                    The development and operation of a Future Internet facility in Europe based on enhancements and the federation of two existing infrastructures: OFELIA and OneLab. Two OFELIA islands (i2CAT and University of Bristol (UNIVBRIS)) and the UTH's NITOS testbed will be enhanced by i) adding more physical resources (servers, OpenFlow-enabled switches and access points) to be able to cope with a bigger number ofusers and different use cases, ii) improving its respective control frameworks (based on the OFELIA control framework and OMF) and iii) adding more manpower to operate the facilities.
+                    </p>
+                                       <p align="left">
+                    The federation of the Brazilian and European experimental facilities, both at the physical connectivity and control framework level, to support the provisioning of slices using resources from both testbeds.
+                    </p>
+<h2>PROCEDURE OVERVIEW</h2>
+<p>If your institution is willing to join the FIBRE Consortium, you are kindly requested to follow the steps below:<br></p>
+<p>1. <a mce_href="http://www.fibre-ict.eu/images/stories/docs/fibre_mou_v0.3.doc" href="http://www.fibre-ict.eu/images/stories/docs/fibre_mou_v0.3.doc">Download the MoU model</a>  to understand the framework of collaboration between your institution and FIBRE project. The content of the MoU shall be discussed in case-by-case basis between the two parties.&nbsp;<span style="line-height: 1.3em;" mce_style="line-height: 1.3em;">&nbsp;</span></p>
+<p>2. Contact the Project office at <a href="mailto:info@fibre.org.br">info@fibre.org.br</a> to schedule a call to clarify all your questions concerning the duties, responsibilities and advantages of joining the FIBRE project.</p>
+<p>3. If your institution understand and agree on the commitment stated in the MoU, please submit the application by editing the <a href="http://www.fibre-ict.eu/images/fibre_mou_v0.2_ff.doc" mce_href="http://www.fibre-ict.eu/images/fibre_mou_v0.2_ff.doc" style="style" mce_style="style">MoU template</a> and sending it to 
+ <a href="mailto:info@fibre.org.br">info@fibre.org.br</a></p>
+<p>4. Application Approval: the FIBRE General Assembly will decide based on the application and information gathered during the call. The approval process will normally take around one month.</p><p>5. By mutual agreement of both parties, MoU will be prepared and signed.</p>
+<p><span style="line-height: 1.3em;" mce_style="line-height: 1.3em;">6. Testbed usage / island installation: FIBRE will provide instructions and support to help your institution to carry out the activities described in the MoU.</span></p>
+<p><br></p>
+<p><span style="line-height: 1.3em;" mce_style="line-height: 1.3em;"><a mce_href="http://webconf2.rnp.br/p27egdf20y7/" href="http://webconf2.rnp.br/p27egdf20y7/">Watch the webconference meeting about the MoU details</a><br> (Held on 5/July 2013, in Portuguese)<br></span></p>
+<p><br></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(){
+    var availableTags = [
+    {% if authorities %}
+        {% for authority in authorities %}
+            {% if authority.name %}
+                {value:"{{ authority.name }}",label:"{{authority.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;
+       }); 
+       // auto-complete the form
+    $( "#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))}
+    });
+       // for hover texts
+       $('[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/fibre/fibre_slice-tab-users-view.html b/portal/templates/fibre/fibre_slice-tab-users-view.html
new file mode 100644 (file)
index 0000000..46f4c58
--- /dev/null
@@ -0,0 +1,130 @@
+<script type="text/javascript" src="{{STATIC_URL}}/js/jquery-ui.js"></script>
+<script type="text/javascript" src="{{STATIC_URL}}/js/jquery.qtip.min.js"></script>
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.qtip.min.css">
+<link rel="stylesheet" href="{{ STATIC_URL }}css/jquery-ui.css">
+<script>
+    function get_users_in_slice(authority_hrn){
+        $("table#user-tab").html("<tr><th>+/-</th><th>Email</th><th>User hrn</th></tr>");
+       var slice_users = [];
+       $.post("/rest/user/",{'filters':{'parent_authority': authority_hrn}}, 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>";
+                       // checking the box for the users that belong to the selected slice
+                       var flag_checkbox = 0;
+                       for(var data in val.slices) {
+                               var element = val.slices[data];
+                               if (element == "{{slice}}"){
+                                       //console.log("the slice is: "+ element);       
+                                       flag_checkbox = 1;
+                                       slice_users.push (val.user_hrn)
+                                       user_row += "<td><input type='checkbox' checked='True' class='user'></td>";
+                               }
+                       }
+                       if(flag_checkbox != 1){
+                       user_row += "<td><input type='checkbox' class='user'></td>";
+                       }
+               user_row += "<td>"+val.user_email+"</td>";
+               user_row += "<td>"+val.user_hrn+"</td>";
+                       //user_row += "<td>"+val.user_enabled+"</td>";
+               user_row += "</tr>";
+               table_users.push(user_row);
+            
+               });
+               $("table#user-tab tr:first").after(table_users.join( "" ));
+               $("div#user-tab-loaded").css("display","block");
+               $("div#user-tab-loading").css("display","none");
+            $("input:checkbox.user").click(function() {
+                user_hrn = $(this).closest('tr').find('td:eq(2)').html();
+                if(this.checked){
+                    var record_id = this.id;
+                    slice_users.push (user_hrn);
+                }else{
+                    console.log(slice_users);
+                }
+            });
+       }); // post rest/user
+    }
+
+    $(document).ready(function() {
+            // TODO: Add a filter based on the list of authorities
+               $.post("/rest/authority/",{'fields':['authority_hrn']}, function( data ) {
+                var list_authorities = [];
+                $.each( data, function( key, val ) {
+                    auth_hrn = val.authority_hrn;
+                    // Keep only the sub authorities, remove root auth
+                    //if(auth_hrn.indexOf(".") > -1){
+                        list_authorities.push(auth_hrn);
+                                               list_authorities.sort();
+                        if(auth_hrn=="{{user_details.parent_authority}}"){
+                                                       $('#auth_list').val(auth_hrn);
+                                               }
+                    //}
+                });
+                               $( "#auth_list" ).autocomplete({
+                               source: list_authorities,
+                               minLength: 0,
+                               select: function (event, ui) {
+                                               get_users_in_slice(ui.item.value);
+                               }
+                               //select: function( event, ui ) {console.log(jQuery(this))}
+                       });
+            }); // post rest/authority
+
+            get_users_in_slice("{{user_details.parent_authority}}");
+
+               $('button#addusers').click(function() {
+                $.post("/update/slice/",{'filters':{'slice_hrn':'{{slice}}'},'params':{'users':slice_users}}, function(data) {
+                       if(data.success){
+                       // TODO: highlight row after success
+                       //$('tr[id="'+record_id+'"]').highlight();
+                       mysliceAlert('Success: slice updated','success', true);
+                       }else{
+                       mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                       }
+                }); // post update slice
+            
+               // TODO: refresh table
+               //window.location="/portal/institution#slices";
+
+            }); // button#addusers click
+       $('[title!=""]').qtip();
+    }); // document ready
+</script>
+
+       <div class="col-md-2">
+               <div id="select-platform" class="list-group">
+               </div>
+                       
+               <ul class="list-group">
+                 <li class="list-group-item">Authority</li>
+                 <li class="list-group-item" style="padding-left:5px;">
+                       <input type="text" id="auth_list"  style ="min-width:190px;" 
+                       title="The default value is  the authority that you belong to and the selected users belong to this slice.
+                                  You can view users of other authorities (organizations) 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."/>
+          </li>
+               </ul>
+       
+       </div>
+       <div class="col-md-10">
+               <div class="row">
+               </div>
+               <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Useres" /></div>
+               <div id="user-tab-loaded" style="display:none;">
+               <table id="user-tab" class="table">
+               </table>
+
+                <!-- XXX TODO: for the moment only PIs have access to Update but users that have slice credentials should also have access to that -->
+
+                               {% if 'is_pi'  in pi %}
+                               <button id="addusers" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Update users</button>
+                               {%endif%}
+               </div>
+
diff --git a/portal/templates/fibre/fibre_slice-user-view.html b/portal/templates/fibre/fibre_slice-user-view.html
new file mode 100644 (file)
index 0000000..0a239f1
--- /dev/null
@@ -0,0 +1,73 @@
+
+<div class="col-md-2">
+       <div id="select-platform" class="list-group">
+       </div>
+               
+       <ul class="list-group">
+         <li class="list-group-item">Authority:<b> {{user_details.parent_authority}}</b>
+               <!--<select id="auth_list">
+                       <option value="ple.upmc">UPMC</option>
+                       <option value="ple.inria">INRIA</option>
+                       <option value="ple.nitos">NITOS</option>
+                       <option value="ple.iminds">iMinds</option>
+               </select> -->
+         </li>
+         <li class="list-group-item">Filter: slice</li>
+         
+       </ul>
+
+</div>
+<div class="col-md-10">
+       <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Useres" /></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>Enabled</th>
+               </tr>
+               </table>
+       </div>
+</div>
+<script>
+    $(document).ready(function() {
+                       //console.log("the value you selected: " + selectedValue);
+               $.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>";
+                                       // checking the box for the users that belong to the selected slice
+                                       var flag_checkbox = 0;
+                                       for(var data in val.slices) {
+                                       var element = val.slices[data];
+                                               if (element == "{{slice}}"){
+                                                       //console.log("the slice is: "+ element);       
+                                                       flag_checkbox = 1;
+                                                       user_row += "<td><input type='checkbox' checked='True'></td>";
+                                               }
+                                       }
+                                       if(flag_checkbox != 1){
+                               user_row += "<td><input type='checkbox'></td>";
+                                       }
+                       user_row += "<td>"+val.user_email+"</td>";
+                       user_row += "<td>"+val.user_hrn+"</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");
+               });
+       //      });
+    });
+</script>
+
diff --git a/portal/templates/fibre/fibre_slice-view.html b/portal/templates/fibre/fibre_slice-view.html
new file mode 100644 (file)
index 0000000..8057609
--- /dev/null
@@ -0,0 +1,20 @@
+{% extends "layout_wide.html" %}
+
+{% block head %}
+
+{% endblock %}
+
+{% block content %}
+
+{% include theme|add:"_widget-slice-sections.html" %}
+         
+<div class="container-fluid tab-content container-slice">
+  <div class="tab-pane active row" id="info">...</div>
+  <div class="tab-pane row" id="testbeds">...</div>
+  <div class="tab-pane row" id="resources">...</div>
+  <div class="tab-pane row" id="users">...</div>
+  <!-- <div class="tab-pane row" id="statistics">...</div> -->
+  <!-- <div class="tab-pane row" id="measurements">...</div> -->
+  <div class="tab-pane row" id="experiment">...</div>
+</div>         
+{% endblock %}
diff --git a/portal/templates/fibre/fibre_slicerequest_view.html b/portal/templates/fibre/fibre_slicerequest_view.html
new file mode 100644 (file)
index 0000000..ef78346
--- /dev/null
@@ -0,0 +1,108 @@
+{% extends "layout.html" %}
+{% load i18n %}
+
+{% block content %}
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Experiment &nbsp;>&nbsp; Request a new Slice
+                        </div>
+               </div>
+       </div>
+
+       {% if errors %}
+       <div class="row">
+               <div class="col-md-12">
+               <ul>
+                 {% for error in errors %}
+                 <li>{{ error }}</li>
+                 {% endfor %}
+               </ul>
+               </div>
+       </div>
+       {% endif %}
+       
+       <div class="row">
+               <div class="col-md-8 el">
+                       <form role="form" method="post">
+                       {% csrf_token %}
+                         <div class="form-group" style="display:none">
+                           <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
+                         </div>
+                         <div class="form-group">
+                           <input type="text" class="form-control" name="slice_name" id="slice_name" style="width:300px" placeholder="Slice name" value="{{slice_name}}" 
+                               title="Please enter a name for your slice"required="required">
+                         </div>
+                         <div class="form-group">
+                               {%if 'is_pi'  in 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;" 
+                               title="An authority responsible for vetting your slice" required="required" readonly>
+                               {%endif%}
+                         </div>
+                         <div class="form-group">
+                           <input type="text" class="form-control" name="exp_url" id="exp_url" style="width:300px" placeholder="Experiment URL (if one exists)"
+                               title="Please provide the url of your experiment if you have one." value="{{exp_url}}">
+                         </div>
+                         <div class="form-group">
+                               <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>
+                         <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request Slice</button>
+                       </form>
+       
+               </div>
+       </div>
+               
+<script>
+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']);
+    });*/
+    console.log("test");
+    test = "{{authority.name}}";
+    if(test){
+        console.log("true");
+           $("#authority_hrn").val("{{authority_name}}");
+    }else{
+        console.log("false");
+           $("#authority_hrn").val("{{authority_hrn}}");
+    }
+
+       var availableTags = [
+    {% if authorities %}
+        {% for authority in authorities %}
+            {% if authority.name %}
+                {value:"{{ authority.name }}",label:"{{authority.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));}
+    });
+});
+</script>
+{% endblock %}
+
diff --git a/portal/templates/fibre/fibre_supportview.html b/portal/templates/fibre/fibre_supportview.html
new file mode 100644 (file)
index 0000000..e33127c
--- /dev/null
@@ -0,0 +1,143 @@
+{% extends "layout_wide.html" %}
+
+{% block content %}
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Support
+                        </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="#support">Tickets</a></li>
+                               <li><a href="#faq">FAQ</a></li>
+                               <li><a href="#contact">Contact</a></li>
+                       </ul>
+           </div>
+       </div>
+</div>
+
+<div class="container tab-content">
+       <div class="tab-pane active row" id="support">
+               <div class="col-md-12">
+                       <h2>Report a Bug</h2>
+                       <p>If you have found a bug or having difficulties accesing some features or found some anomalies, please report it using our ticketing system.</p>
+                       <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Ticket</button>
+<!--                   <h3>Unresolved Tickets</h3>
+                       <table class="mytable table table-bordered table-hover">
+                       <tr>
+                           <th>Ticket No</th>
+                                       <th>Reported By</th>
+                                       <th>Description</th>
+                           <th>Status</th>
+                       </tr>
+                       <tr>
+                           <td>1</td>
+                                       <td>yasin.upmc@gmail.com</td>
+                                       <td> Slice_request page is not working </td>
+                                       <td> Unresolved</td>
+                       </tr>
+                               <tr>
+                                       <td>2</td>
+                                       <td>azerty@lip6.fr</td>
+                                       <td>Unable to Register</td>
+                                       <td>Unresolved</td>
+                               </tr> 
+               
+                   </table> -->
+               </div>
+         </div>
+       <div class="tab-pane row" id="faq">
+               <div class="col-md-12">
+                       <h2>Frequently Asked Questions (FAQs)<h2>
+
+                       <h3>Users</h3>
+                       <ul>
+                       <li><h4>Who is a user?</h4></li>
+                       <p>A user is an experimenter who registers to the OneLab portal and able to use all the facilites that the portal has to offer. However, a user does not
+                       have the right to do any admin operation such as managing slices, users and resources.</p>
+                       
+                       
+                       <li><h4>How do I register?</h4></li>
+                       <p>In order to register you must go to the <a href="/portal/register">Registration</a> page. You have to choose your corresponding institution (authority). After registration you have to wait until the PI validates your account. However upon registration, you will be able login to the portal with a limited access. Do not try to re-register with the same email address.</p>
+                       
+                       <li><h4>Why can't I register with my email?</h4></li>
+                       <p>If you have already registered then you won't be able to register again with the same email address. However, if you have never registered and still you are not able to use your email then please 
+                       <a href="/portal/contact">Contact Support</a> and mention the error message that you are getting while trying to register.</p>
+                       
+                       <li><h4>In registration, in "My keys" option, what should i choose?</h4></li>
+                       <p>There are two choices.</p> 
+                               <p class="text-justify"><b>1. Generate Key Pairs:</b> This option is for users who have no knowledge about SFA and MySlice i.e., new users. We offer convenience to the new users in order to avoid addtional efforts to delegate keys manually. If you choose this option, the portal will automatically handle your credentials and you would be able use the portal as soon as the PI validates your account. However, you can delete your private key from the portal if you are concerned about privacy issues. In that case once your current credentials expire, you have to delegate your credentials manually using <a href="http://trac.myslice.info/wiki/InstallSfa" target="_blank">SFA</a>. As this needs advance knowledge about SFA and Myslice, we highly recommend to the new users to keep both private and public keys in the portal in order to keep the process automatic. </p>
+                               <p class="text-justify"><b>2. Upload My Public Key:</b> This option is for users who have experience with MySlice and SFA. If you choose this option, once the PI validates your account, you have to delegate your credentials manually using <a href="http://trac.myslice.info/wiki/InstallSfa" target="_blank">SFA</a>. You have to repeat the same process everytime your credentials expire. Normally, credentials expire every one month. You can see the expiration date in your Account page. </p>
+                       
+                       <li><h4>Who is responsible for validating my account?</h4></li>
+                       <p>When you register, you choose an authority fromt he list of authorities. For each authority there is a Principal Investigator (PI). PI of your authority will verify your identity and if he finds that you are from his institution, he will validate your account otherwise he will reject your account.</p>
+                       
+                       <li><h4>How long I have to wait for validation?</h4></li>
+                       <p>It depends on the PI of your authority. In general, it should not take more than a week. If you are waiting more than usual, please <a href="/portal/contact">Contact Support</a> and explain your problem.</p>
+                       <li><h4>I just registered. Why can't I see any slices and resources?</h4></li>
+                       <p>Once you register, you can login to your account with limited access. It means that you can view your account details, modify your name and password. You can also view other pages. However, you will not be able to see any slices as well as resources before your account validation. But you can <a href="/portal/slice_request/">Request Slice</a> before being validated. Therefore, the PI will validate your account as well as your requested slice. Once validated, you will be able to see your slice and if you click on your slice, you will be able to see resources in that slice and you can reserve nodes and start your experiment.</p>
+                       
+                       <li><h4>How can I get access to a slice?</h4></li>
+                       <p>If you are a completely new user, you have to <a href="/portal/slice_request/">Request Slice</a>. It is upto the PI of your authority to accept/reject your slice request. </br>On the other hand, if you are a new user to the portal but you already have an account in OneLab SFA registry and you have access to slices, you will be able to see all your slices once your account is validated by the PI.</p> 
+                       
+                       <li><h4>I forgot my password, how to recover it?</h4></li>
+                       <p>If you have an account in the portal but you forgot the password, you can always <a href="/portal/pass_reset/">Reset your password</a>.</p></ul>
+                       
+                       <h3>Managers</h3>
+                       <ul>
+                       <li><h4>Who is a manager?</h4></li>
+                       <p>A manager is the Principal Investigator (PI) of the institution. Each PI has authority over his own institution. A PI can add, delete, validate users/ 
+                       slices that belong to his institution.</p>
+                       
+                       <li><h4>What is pending users/slices?</h4></li>
+                       <p>In <a href="/portal/validate">Requests</a> page you will be able to see all the users that registered under your authority and the slices that users of your authority has requested. Therefore, pending users/slices are those users and slices that are yet to be validated. You can validate/reject these requests based on the policy of your institution.</p>
+                       
+                       <li><h4>How can I manage the users/slices that belong to my institution?</h4></li>
+                       <p>In <a href="/portal/institution">Instution</a> page, under "Users" tab, you will be able to see all the users that belong to your authority. You can delete the users that you don't want anymore. Under "Slices" tab, you will be able to see all the slices that belong to your authority. You can renew/delete the slices based on your requirements. As a PI you can also <a href="/portal/slice_request/">Create Slice</a>. Just fill the form of request slice and the slice will be automatically validated if it is requested by a PI. </p>
+                       
+                       </ul>
+               </div>
+         </div>
+
+       <div class="tab-pane row" id="contact">
+               <div class="col-md-12">
+                       <h2>Contact Us</h2>
+               
+                       <h3>Mailing List</h3>
+                       <p>You can subscribe to our mailing list by sending a request to: <b>support</b> AT <b>myslice</b> DOT <b>info</b></p>
+                       <p>Also you can adress any issues in the same email address.</p>
+                       
+                       <h3>Mailing Address</h3>
+                       <address>
+                       UPMC - LIP6<br> 
+                       Boîte courrier 16 <br>
+                       Couloir 26-00, Etage 01, Bureau 102<br>
+                       4 place Jussieu<br>
+                       75252 PARIS CEDEX 05<br>
+                       France<br> 
+                       </address>
+               </div>
+         </div>
+</div>
+
+<script>
+$(document).ready(function() {
+    $('button#ticketbtn').click(function() {
+        window.location="/portal/contact/";
+    });
+       $('.nav-tabs a').click(function (e) {
+               e.preventDefault();
+               $(this).tab('show');
+       });
+});
+</script>
+
+
+{% endblock %}
+
diff --git a/portal/templates/fibre/fibre_termsview.html b/portal/templates/fibre/fibre_termsview.html
new file mode 100644 (file)
index 0000000..a82e2b1
--- /dev/null
@@ -0,0 +1,56 @@
+{% extends "layout.html" %}
+
+{% block content %}
+<div class="row">
+       <div class="col-md-12">
+       <h1> Terms and conditions</h1>
+       <p align="left">
+    <a name="_Ref238698453"></a>
+    <a name="_Ref238699060"></a>
+    <a name="_Ref249598367"></a>
+    <a name="_Ref254443731"></a>
+    <a name="_Ref254443916"></a>
+    TERMS AND CONDITIONS
+    <br/>
+    Fibre: Future Internet testbeds experimentation between Brazil and Europe
+    <br/>
+</p>
+<h2 align="left">Context</h2>
+                                       <p align="left">
+                    The main goal of the FIBRE project is the design, implementation and validation of a shared Future Internet research facility, supporting the joint experimentation of European and Brazilian researchers. In order to achieve this goal the project will carry out four main activities:
+                    </p>
+                                       <p align="left">
+                    The development and operation of a new experimental facility in Brazil, including the setup of equipment to support experimentation with various technologies (fixed layer 2 and layer 3, wireless, optical) as well as the design and implementation of a control framework to automate the use and operation of the testbed.
+                    </p>
+                                       <p align="left">
+                    The development and operation of a Future Internet facility in Europe based on enhancements and the federation of two existing infrastructures: OFELIA and OneLab. Two OFELIA islands (i2CAT and University of Bristol (UNIVBRIS)) and the UTH's NITOS testbed will be enhanced by i) adding more physical resources (servers, OpenFlow-enabled switches and access points) to be able to cope with a bigger number ofusers and different use cases, ii) improving its respective control frameworks (based on the OFELIA control framework and OMF) and iii) adding more manpower to operate the facilities.
+                    </p>
+                                       <p align="left">
+                    The federation of the Brazilian and European experimental facilities, both at the physical connectivity and control framework level, to support the provisioning of slices using resources from both testbeds.
+                    </p>
+<h2>PROCEDURE OVERVIEW</h2>
+<p>If your institution is willing to join the FIBRE Consortium, you are kindly requested to follow the steps below:<br></p>
+<p>1. <a mce_href="http://www.fibre-ict.eu/images/stories/docs/fibre_mou_v0.3.doc" href="http://www.fibre-ict.eu/images/stories/docs/fibre_mou_v0.3.doc">Download the MoU model</a>  to understand the framework of collaboration between your institution and FIBRE project. The content of the MoU shall be discussed in case-by-case basis between the two parties.&nbsp;<span style="line-height: 1.3em;" mce_style="line-height: 1.3em;">&nbsp;</span></p>
+<p>2. Contact the Project office at <a href="mailto:info@fibre.org.br">info@fibre.org.br</a> to schedule a call to clarify all your questions concerning the duties, responsibilities and advantages of joining the FIBRE project.</p>
+<p>3. If your institution understand and agree on the commitment stated in the MoU, please submit the application by editing the <a href="http://www.fibre-ict.eu/images/fibre_mou_v0.2_ff.doc" mce_href="http://www.fibre-ict.eu/images/fibre_mou_v0.2_ff.doc" style="style" mce_style="style">MoU template</a> and sending it to 
+ <a href="mailto:info@fibre.org.br">info@fibre.org.br</a></p>
+<p>4. Application Approval: the FIBRE General Assembly will decide based on the application and information gathered during the call. The approval process will normally take around one month.</p><p>5. By mutual agreement of both parties, MoU will be prepared and signed.</p>
+<p><span style="line-height: 1.3em;" mce_style="line-height: 1.3em;">6. Testbed usage / island installation: FIBRE will provide instructions and support to help your institution to carry out the activities described in the MoU.</span></p>
+<p><br></p>
+<p><span style="line-height: 1.3em;" mce_style="line-height: 1.3em;"><a mce_href="http://webconf2.rnp.br/p27egdf20y7/" href="http://webconf2.rnp.br/p27egdf20y7/">Watch the webconference meeting about the MoU details</a><br> (Held on 5/July 2013, in Portuguese)<br></span></p>
+<p><br></p>
+<div>
+    <div>
+        <div id="_com_1">
+        </div>
+    </div>
+</div> 
+</div>
+</div>
+<div class="row">
+       <div class="col-md-12">
+
+</div>
+</div>
+{% endblock %}
+
diff --git a/portal/templates/fibre/fibre_user_request_email.html b/portal/templates/fibre/fibre_user_request_email.html
new file mode 100644 (file)
index 0000000..fa0e896
--- /dev/null
@@ -0,0 +1,18 @@
+<img src="https://onelab.eu/templates/onelab2/images/logo.png">
+<br>
+<h1>NEW USER REQUEST</h1>
+<br>
+<p>You are receiving this request because we have you listed as a manager at an organization that uses OneLab.</p> 
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact support@onelab.eu.</p>
+<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>
+<p>Please note that the validation request will only become visible to you on the OneLab portal once the user has confirmed his/her email address.</p>
diff --git a/portal/templates/fibre/fibre_user_request_email.txt b/portal/templates/fibre/fibre_user_request_email.txt
new file mode 100644 (file)
index 0000000..b782e71
--- /dev/null
@@ -0,0 +1,19 @@
+NEW USER REQUEST
+
+You are receiving this request because we have you listed as a manager at an organization that uses OneLab. 
+If you believe that you have received this message in error, or if you have any questions, kindly contact support@onelab.eu.
+
+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 }}
+
+You can validate the user here: http://{{current_site}}/portal/validate
+
+Please note that the validation request will only become visible to you on the OneLab portal once the user has confirmed his/her email address.
+
+
diff --git a/portal/templates/fibre/fibre_widget-login-user.html b/portal/templates/fibre/fibre_widget-login-user.html
new file mode 100644 (file)
index 0000000..d7342f8
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="login-form">
+       {% if state %}
+       <span class="help-block">{{ state }}</span>
+       {% endif %}
+       <form action="/login/" method="post" role="form">
+         {% csrf_token %}
+         {% if next %}
+         <input type="hidden" name="next" value="{{ next }}" />
+         {% endif %}
+       <div class="form-group">
+       <input type="email" name="username" placeholder="Enter Email / Username">
+       </div>
+       <div class="form-group">
+       <input type="password" name="password" placeholder="Password">
+       </div>
+       <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="/portal/register">Sign Up!</a>
+       </div>
+       </form>
+</div>
diff --git a/portal/templates/fibre/fibre_widget-news.html b/portal/templates/fibre/fibre_widget-news.html
new file mode 100644 (file)
index 0000000..83cec76
--- /dev/null
@@ -0,0 +1,5 @@
+<div class="alert alert-info alert-dismissable">
+<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
+<span class="glyphicon glyphicon-globe"></span>
+The <b>OneLab</b> Portal opens with the <b>PlanetLab Europe</b>, <b>IOTLab</b> and <b>NITOS</b> testbeds!
+</div>
\ No newline at end of file
diff --git a/portal/templates/fibre/fibre_widget-slice-sections.html b/portal/templates/fibre/fibre_widget-slice-sections.html
new file mode 100644 (file)
index 0000000..01c8d82
--- /dev/null
@@ -0,0 +1,55 @@
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Experiment &nbsp;>&nbsp; {{ slice }}
+                        </div>
+               </div>
+       </div>
+</div>
+<div class="container-fluid container-slice">
+<div class="row">
+               <div class="col-md-12">
+{% if section == "resources" %}
+<ul class="nav nav-tabs nav-section">
+       <li><a href="/slice/{{ slice }}#info">Information</a></li>
+       <!-- <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 }}#experiment">Statistics</a></li> -->
+       <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
+       <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
+</ul>
+{% else %}
+<ul class="nav nav-tabs nav-section">
+       <li class="active"><a href="#info">Information</a></li>
+       <!-- <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="#experiment">Statistics</a></li> -->
+       <!-- <li class="measurements"><a href="#experiment">Measurements</a></li> -->
+       <li class="experiment"><a href="#experiment">Tools</a></li>
+</ul>
+
+<script>
+$(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+               if ($(this).hasClass('link')) return;
+               e.preventDefault();
+               $(this).tab('show');
+       var id = $(this).attr('href').substr(1);        
+       $("#" + id).load('/' + id + '/{{ slice }}/');
+       });
+       
+       var hash = window.location.hash;
+       if (hash) {
+               $('.nav-tabs a[href='+hash+']').click();
+       } else {
+               $('div#info').load('/info/{{ slice }}/');
+       }
+});
+</script>
+{% endif %}
+</div>
+</div>
+</div>
\ No newline at end of file
index fdab352..2d9d53e 100644 (file)
@@ -39,7 +39,7 @@
 <body ng-app="ManifoldApp">
 {% block container %}
        {% block topmenu %}
-       {% include theme|add:"__widget-topmenu.html" %}
+       {% include theme|add:"_widget-topmenu.html" %}
        {% endblock topmenu %}
        {% include 'messages-transient.html' %}
        {% block base_content %}
index ab6776c..ee6c0d4 100644 (file)
@@ -494,15 +494,17 @@ jQuery(document).ready(function(){
         {% 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}}"},
+            {% else %}
+                {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
             {% endif %}
         {% endfor %}    
     {% else %}
         {value:"",label:"No authority found !!!"}
     {% endif %}
     ];
+
+    console.log(availableTags);
+
        // sorting the list
        availableTags.sort(function(a,b){
                var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
index a8a9ac9..6b7fa4c 100644 (file)
@@ -68,6 +68,7 @@ $(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="#resourceflowspace" role="tab" data-toggle="tab">Flowspace</a></li>
                          <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
                        </ul>
                        </div>
@@ -105,7 +106,12 @@ $(document).ready(function() {
                        {{map_resources}}
                                </div>
                                <div class="tab-pane" id="resourcescheduler">
-                       {{scheduler}}
+                    {{scheduler}}
+                               </div>
+                               <div class="tab-pane" id="resourceflowspace">
+                        {{resources}}
+                        {{flowspaces}}
+                        {{flowspaces_form}}
                                </div>
        
                                <!--
index 1aaea71..c73e665 100644 (file)
@@ -4,7 +4,6 @@
 <link rel="stylesheet" href="{{ STATIC_URL }}css/jquery-ui.css">
 <script>
     function get_users_in_slice(authority_hrn){
-        console.log(authority_hrn);
         $("table#user-tab").html("<tr><th>+/-</th><th>Email</th><th>User hrn</th></tr>");
        var slice_users = [];
        $.post("/rest/user/",{'filters':{'parent_authority': authority_hrn}}, function( data ) {
                 $.each( data, function( key, val ) {
                     auth_hrn = val.authority_hrn;
                     // Keep only the sub authorities, remove root auth
-                    if(auth_hrn.indexOf(".") > -1){
+                    //if(auth_hrn.indexOf(".") > -1){
                         list_authorities.push(auth_hrn);
                                                list_authorities.sort();
                         if(auth_hrn=="{{user_details.parent_authority}}"){
                                                        $('#auth_list').val(auth_hrn);
                                                }
-                    }
+                    //}
                 });
                                $( "#auth_list" ).autocomplete({
                                source: list_authorities,
index a1295c1..bb2836f 100644 (file)
@@ -8,7 +8,7 @@
 {% block content %}
 
 <div class="row">
-       <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" /> OneLab Experimenter Registration</h1>
+       <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" /> FIBRE Experimenter Registration</h1>
 </div>
 <div class="row">
 
diff --git a/ui/templates/base2.html b/ui/templates/base2.html
new file mode 100644 (file)
index 0000000..499ed88
--- /dev/null
@@ -0,0 +1,38 @@
+{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
+<html lang="en"><head>
+<title>FIBRE - {{ section }}</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<link rel="shortcut icon" href="/static/img/myslice-icon.png">
+{# 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>
+<script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
+<script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
+<script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
+<style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
+{{ header_prelude }}
+{% block head %} {% endblock head %}
+{# let's add these ones no matter what #}
+{% insert_str prelude "js/jquery.min.js" %}
+{% insert_str prelude "js/jquery.html5storage.min.js" %}
+{% insert_str prelude "js/messages-runtime.js" %}
+{% insert_str prelude "js/class.js" %}
+{% insert_str prelude "js/plugin-helper.js" %}
+{% insert_str prelude "js/mustache.js" %}
+{% insert_str prelude "js/plugin.js" %}
+{% insert_str prelude "js/manifold.js" %}
+{% insert_str prelude "css/manifold.css" %}
+{% insert_str prelude "css/plugin.css" %}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/{{ theme }}.css">
+</head>
+<body>
+{% block container %}
+       {% block topmenu %}
+       {% include theme|add:"__widget-topmenu.html" %}
+       {% endblock topmenu %}
+       {% include 'messages-transient.html' %}
+       {% block base_content %}
+       {% endblock %}
+{% endblock container %}
+</body>
+</html>
diff --git a/unfold.sqlite3-110314 b/unfold.sqlite3-110314
new file mode 100644 (file)
index 0000000..b3018f1
Binary files /dev/null and b/unfold.sqlite3-110314 differ
diff --git a/unfold.sqlite3-130314 b/unfold.sqlite3-130314
new file mode 100644 (file)
index 0000000..0ccc69e
Binary files /dev/null and b/unfold.sqlite3-130314 differ
diff --git a/unfold.sqlite3-140314 b/unfold.sqlite3-140314
new file mode 100644 (file)
index 0000000..4e36199
Binary files /dev/null and b/unfold.sqlite3-140314 differ
diff --git a/unfold.sqlite3.old-120314 b/unfold.sqlite3.old-120314
new file mode 100644 (file)
index 0000000..815d818
Binary files /dev/null and b/unfold.sqlite3.old-120314 differ