Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorLoic Baron <loic.baron@lip6.fr>
Mon, 29 Dec 2014 09:53:03 +0000 (10:53 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Mon, 29 Dec 2014 09:53:03 +0000 (10:53 +0100)
Conflicts:
rest/credentials.py

183 files changed:
README
forge/__init__.py [new file with mode: 0644]
forge/forms.py [new file with mode: 0644]
forge/models.py [new file with mode: 0644]
forge/script/Auth.py [new file with mode: 0644]
forge/script/PlcApi/Auth.py [new file with mode: 0644]
forge/script/PlcApi/cleanKeys.py [new file with mode: 0755]
forge/script/PlcApi/deleteSlice.py [new file with mode: 0755]
forge/script/PlcApi/getLXCSites.py [new file with mode: 0755]
forge/script/PlcApi/getNodes.py [new file with mode: 0755]
forge/script/PlcApi/getSites.py [new file with mode: 0755]
forge/script/PlcApi/getSitesNNodes.py [new file with mode: 0755]
forge/script/PlcApi/getSlices.py [new file with mode: 0755]
forge/script/PlcApi/showKeys.py [new file with mode: 0755]
forge/script/PlcApi/testRequest.py [new file with mode: 0755]
forge/script/Test [new file with mode: 0644]
forge/script/__init__.py [new file with mode: 0644]
forge/script/classDefinition.py [new file with mode: 0644]
forge/script/configService/fedora-updates-testing.repo [new file with mode: 0644]
forge/script/configService/fedora-updates.repo [new file with mode: 0644]
forge/script/configService/fedora.repo [new file with mode: 0644]
forge/script/configService/httpd.conf [new file with mode: 0644]
forge/script/configService/id_rsa.pub [new file with mode: 0644]
forge/script/configService/index.html [new file with mode: 0644]
forge/script/configService/sshd_config [new file with mode: 0644]
forge/script/exceptionDefinition.py [new file with mode: 0644]
forge/script/openvswitch.py [new file with mode: 0755]
forge/script/request.py [new file with mode: 0755]
forge/script/scp.py [new file with mode: 0644]
forge/script/serviceScript.py [new file with mode: 0644]
forge/script/xmlFile/Conf.xml [new file with mode: 0644]
forge/script/xmlFile/Link.xml [new file with mode: 0644]
forge/script/xmlFile/MiMConf.xml [new file with mode: 0644]
forge/script/xmlFile/MiMLink.xml [new file with mode: 0644]
forge/script/xmlFile/TP1Conf.xml [new file with mode: 0644]
forge/script/xmlFile/TP1Link.xml [new file with mode: 0644]
forge/script/xmlFile/TestConf.xml [new file with mode: 0644]
forge/script/xmlFile/TestLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/AResT1v62_fr.pdf [new file with mode: 0644]
forge/script/xmlFileRaw/AResT5v62_fr.pdf [new file with mode: 0644]
forge/script/xmlFileRaw/MiMConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/MiMLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1Conf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1Link.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1NoServConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1NoServLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1PrivConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP1PrivLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5Conf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfForge.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoAustralia.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoLink.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5ConfNoX.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5Link.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TP5LinkNo.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TestConf.xml [new file with mode: 0644]
forge/script/xmlFileRaw/TestLink.xml [new file with mode: 0644]
forge/tasks.py [new file with mode: 0644]
forge/templates/create-course.html [new file with mode: 0644]
forge/templates/createCourse.html [new file with mode: 0644]
forge/templates/createLab.html [new file with mode: 0644]
forge/templates/labDetails.html [new file with mode: 0644]
forge/templates/list.html [new file with mode: 0644]
forge/templates/listCourse.html [new file with mode: 0644]
forge/templates/mainView.html [new file with mode: 0644]
forge/tests.py [new file with mode: 0644]
forge/views.py [new file with mode: 0644]
manifoldapi/manifoldproxy.py
manifoldapi/static/js/manifold.js
myslice/configengine.py
myslice/settings.py
myslice/urls.py
plugins/columns_editor/__init__.py
plugins/querytable/__init__.py
plugins/querytable/static/js/querytable.js
plugins/queryupdater/static/js/queryupdater.js
plugins/sladialog/templates/sladialog.html
portal/account.py [new file with mode: 0644]
portal/accountview.py
portal/actions.py
portal/homeview.py
portal/platform.py [new file with mode: 0644]
portal/registrationview.py
portal/reputationview.py [new file with mode: 0644]
portal/servicedirectory.py
portal/sliceresourceview.py
portal/slicetabexperiment.py
portal/static/css/account_view.css
portal/static/css/onelab.css
portal/static/img/bg-experiment.jpg [new file with mode: 0644]
portal/static/img/fed4fire_favicon.ico [new file with mode: 0644]
portal/static/img/myslice_favicon.ico [new file with mode: 0644]
portal/static/img/onelab_favicon.ico [new file with mode: 0644]
portal/static/img/putty-logo.png [new file with mode: 0644]
portal/static/img/testbeds/omf.nitos.png [new file with mode: 0644]
portal/static/img/testbeds/paris.fit-nitos.fr.png [new file with mode: 0644]
portal/static/img/testbeds/planetlab.png
portal/static/js/myslice.js
portal/static/reputation_static/css/delete.gif [new file with mode: 0644]
portal/static/reputation_static/css/images/star-off.png [new file with mode: 0644]
portal/static/reputation_static/css/images/star-on.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-icons_222222_256x240.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-icons_454545_256x240.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-icons_888888_256x240.png [new file with mode: 0644]
portal/static/reputation_static/css/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
portal/static/reputation_static/css/jquery-ui-1.9.2.custom.min.css [new file with mode: 0644]
portal/static/reputation_static/css/jquery.rating.css [new file with mode: 0644]
portal/static/reputation_static/css/main.css [new file with mode: 0644]
portal/static/reputation_static/img/star-off.png [new file with mode: 0644]
portal/static/reputation_static/img/star-on.png [new file with mode: 0644]
portal/static/reputation_static/img/star.gif [new file with mode: 0644]
portal/static/reputation_static/js/jquery-1.9.0.min.js [new file with mode: 0644]
portal/static/reputation_static/js/jquery.raty.min.js [new file with mode: 0644]
portal/static/reputation_static/js/ui/jquery-ui-1.9.2.custom.min.js [new file with mode: 0644]
portal/templates/account-view.html
portal/templates/base.html
portal/templates/fed4fire/fed4fire_about.html
portal/templates/fed4fire/fed4fire_account-view.html
portal/templates/fed4fire/fed4fire_base.html [deleted file]
portal/templates/fed4fire/fed4fire_contact_support_email_subject.txt
portal/templates/fed4fire/fed4fire_email_activation.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_email_default_recipients.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_email_default_sender.txt
portal/templates/fed4fire/fed4fire_footer.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_institution.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_management-tab-about.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_management-tab-requests.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice-resource-view.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice-tab-experiment.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice-view.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_email.html
portal/templates/fed4fire/fed4fire_slice_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice_request_validated.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slicerequest_view.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_supportview.html
portal/templates/fed4fire/fed4fire_user_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_email.html
portal/templates/fed4fire/fed4fire_user_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_user_request_validated.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_widget-slice-sections.html
portal/templates/fed4fire/fed4fire_widget-topmenu.html
portal/templates/onelab/onelab_account-view.html
portal/templates/onelab/onelab_base.html [deleted file]
portal/templates/onelab/onelab_home-view.html
portal/templates/onelab/onelab_slice-view.html
portal/templates/onelab/onelab_widget-slice-sections.html
portal/templates/reputation.html [new file with mode: 0644]
portal/templates/servicedirectory.html
portal/templates/slice-tab-experiment.html
portal/urls.py
portal/usersview.py
rest/credentials.py
rest/sfa_api.py [new file with mode: 0644]
sla/slaclient/restclient.py
sla/slaclient/service/fed4fire/fed4fireservice.py
sla/slaclient/service/fed4fire/jsonparser.py
sla/slaclient/templates/fed4fire/django/agreement.xml
sla/slaclient/templates/fed4fire/fed4fire.py
sla/slaclient/wsag_model.py
sla/slaclient/xmlconverter.py
sla/slicetabsla.py
sla/static/images/sort_asc.png [new file with mode: 0644]
sla/static/images/sort_both.png [new file with mode: 0644]
sla/static/images/sort_desc.png [new file with mode: 0644]
sla/templates/slice-tab-sla.html
sla/urls.py
ui/topmenu.py
unfold/page.py

diff --git a/README b/README
index b1f201d..0eda79a 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 This file documents the contents of this module
 change
-Last update 4 sept. 2013
+Last update 18 DEC. 2014
 
 See the devel/ subdir for more devel-oriented doc.
 
@@ -14,6 +14,10 @@ $ apt-get install python-django-south
 $ apt-get install python-pip or sudo easy_install pip==1.4.1
 $ pip install requests
 $ pip install djangorestframework
+$ pip install django-celery
+$ pip install geopy
+$ pip install paramiko
+
 * git clone git://git.onelab.eu/myslice.git
 -- or --
 * git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
diff --git a/forge/__init__.py b/forge/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forge/forms.py b/forge/forms.py
new file mode 100644 (file)
index 0000000..402b3c3
--- /dev/null
@@ -0,0 +1,17 @@
+# -*- coding:utf-8 -*-
+
+from django import forms
+from models import Lab, Course
+from django.db import models
+
+class LabForm(forms.ModelForm):
+       title = forms.CharField(label= "Title")
+       subject = forms.FileField(label="Subject of the lab")
+       class Meta:
+               model = Lab
+
+class courseForm(forms.Form):
+       lab = forms.ModelChoiceField(queryset= Lab.objects.all(), empty_label="Select a Lab")
+       nbEnv = forms.IntegerField(min_value=0, label="Number of environment")
+       subnet = forms.CharField(initial='10.1.0.0/16')
+
diff --git a/forge/models.py b/forge/models.py
new file mode 100644 (file)
index 0000000..e0b3ace
--- /dev/null
@@ -0,0 +1,118 @@
+# -*- coding:utf-8 -*-
+
+from django.db import models
+
+# Used for automatically delete file
+from django.dispatch import receiver
+import os
+
+# Class to describe a service set on a host
+class Service(models.Model):
+       serviceName = models.CharField(max_length=50)
+       servicePort = models.CharField(max_length=10)
+       host = models.ForeignKey('Host')
+
+       def __unicode__(self):
+               if self.servicePort != u'':
+                       return u"%s on %s" % (self.serviceName, self.servicePort)
+               else:
+                       return u"%s" % self.serviceName
+
+# Class to describe an interface available on a host
+class Interface(models.Model):
+       ip = models.CharField(max_length=16)
+       name = models.CharField(max_length=40)
+       host = models.ForeignKey('Host')
+
+       def __unicode__(self):
+               return u"%s -> %s" % (self.name, self.ip)
+
+# Class to describe a host
+class Host(models.Model):
+       TYPE_CHOICES = (
+               ('PUB', 'Public'),
+               ('PRIV', 'Private'),
+               ('COM', 'Common'),
+       )
+       hostname = models.CharField(max_length=100)
+       hostType = models.CharField(max_length=20, choices=TYPE_CHOICES, default='PRIV')
+       pleSlice = models.ForeignKey('Slice')
+       latitude = models.FloatField()
+       longitude = models.FloatField()
+
+       def __unicode__(self):
+               return u"%s %s" % (self.hostname, self.hostType)
+
+# Class to describe a slice (sliceName and reference to environment)
+class Slice(models.Model):
+       sliceName = models.CharField(max_length=50)
+       environment = models.ForeignKey('Environment')
+
+       def __unicode__(self):
+               return u"%s" % self.sliceName
+
+# Class to describe a student environment (sshKey and reference to a course)
+class Environment(models.Model):
+       sshKey = models.FileField(upload_to='ict_education/keys')
+       course = models.ForeignKey('Course')
+       confFile = models.FileField(upload_to='ict_education/xmlFiles')
+       linkFile = models.FileField(upload_to='ict_education/xmlFiles')
+       ready = models.BooleanField(default=False)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Environment)
+def environment_delete_ssh_key(sender, instance, **kwargs):
+       if instance.sshKey:
+               if os.path.isfile(instance.sshKey.path):
+                       os.remove(instance.sshKey.path)
+       if instance.confFile:
+               if os.path.isfile(instance.confFile.path):
+                       os.remove(instance.confFile.path)
+       if instance.linkFile:
+               if os.path.isfile(instance.linkFile.path):
+                       os.remove(instance.linkFile.path)
+
+# Class to describe a course (ie a set of environment) (reference to lab, mainKey used by the teacher to access all node)
+class Course(models.Model):
+       lab = models.ForeignKey('Lab')
+       mainKey = models.FileField(upload_to='ict_education/keys', null = True)
+       ready = models.BooleanField(default=False)
+       sliceName = models.CharField(max_length=50)
+       
+       def __unicode__(self):
+               return u"%s %s" % (self.lab, self.sliceName)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Course)
+def course_delete_main_ssh_key(sender, instance, **kwargs):
+       if instance.mainKey:
+               if os.path.isfile(instance.mainKey.path):
+                       os.remove(instance.mainKey.path)
+
+# Class to describe a lab
+class Lab(models.Model):
+       title = models.CharField(max_length=100)
+       author = models.CharField(max_length=40)
+       subject = models.FileField(upload_to='ict_education/Labs/subjects')
+       configurationFile = models.FileField(upload_to='ict_education/Labs/xmlFiles')
+       linkFile = models.FileField(upload_to='ict_education/Labs/xmlFiles')
+
+       def __unicode__(self):
+               return u"%s %s" % (self.title, self.author)
+
+# function used to automatically delete the stored file when deleting the model from the database
+@receiver(models.signals.post_delete, sender = Lab)
+def lab_delete_files(sender, instance, **kwargs):
+       # Remove the subject
+       if instance.subject:
+               if os.path.isfile(instance.subject.path):
+                       os.remove(instance.subject.path)
+       # Remove the configuration file
+       if instance.configurationFile:
+               if os.path.isfile(instance.configurationFile.path):
+                       os.remove(instance.configurationFile.path)
+       # Remove the link file
+       if instance.linkFile:
+               if os.path.isfile(instance.linkFile.path):
+                       os.remove(instance.linkFile.path)
+
diff --git a/forge/script/Auth.py b/forge/script/Auth.py
new file mode 100644 (file)
index 0000000..f588f31
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import xmlrpclib
+
+auth={'AuthMethod': 'password', 'Username': 'pierre.vigreux@lip6.fr', 'AuthString': '1245780'}
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+def printRes(results):
+       for result in results:
+               print result
diff --git a/forge/script/PlcApi/Auth.py b/forge/script/PlcApi/Auth.py
new file mode 100644 (file)
index 0000000..f588f31
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import xmlrpclib
+
+auth={'AuthMethod': 'password', 'Username': 'pierre.vigreux@lip6.fr', 'AuthString': '1245780'}
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+def printRes(results):
+       for result in results:
+               print result
diff --git a/forge/script/PlcApi/cleanKeys.py b/forge/script/PlcApi/cleanKeys.py
new file mode 100755 (executable)
index 0000000..e524303
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# Update with latest key
+
+from Auth import *
+
+keyId = plc_api.GetKeys(auth, {'person_id': 249241}, ['key_id'])
+for key in keyId:
+       if key['key_id'] != 117822:
+               plc_api.DeleteKey(auth, key['key_id'])
+               print "Deleting a key id ->",key['key_id']
+
diff --git a/forge/script/PlcApi/deleteSlice.py b/forge/script/PlcApi/deleteSlice.py
new file mode 100755 (executable)
index 0000000..b54665a
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+
+plc_host='www.planet-lab.eu'
+slice_pref='upmc_'
+
+api_url='https://%s:443/PLCAPI/'%plc_host
+plc_api=xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+slice_name = slice_pref+raw_input('Give the name of the slice : ')
+
+try:
+       returnCode = plc_api.DeleteSlice(Auth.auth, slice_name)
+except Exception, why:
+       print "An error occured while trying to delete the slice "+slice_name
+       print why
+       sys.exit(2)
+if returnCode != 1:
+       print "An error occured while trying to delete the slice "+slice_name
diff --git a/forge/script/PlcApi/getLXCSites.py b/forge/script/PlcApi/getLXCSites.py
new file mode 100755 (executable)
index 0000000..d02b79c
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+from Auth import *
+
+nodesLxc = plc_api.GetNodeTags(auth, {'value': 'lxc', 'tagname':'pldistro'}, ['node_id', 'hostname'])
+
+site_ids = []
+for node in nodesLxc:
+       site_ids.append(plc_api.GetNodes(auth, node['node_id'], ['site_id'])[0]['site_id'])
+
+sites = plc_api.GetSites(auth, site_ids, ['site_id', 'name', 'abbreviated_name'])
+for site in sites:
+       print site
diff --git a/forge/script/PlcApi/getNodes.py b/forge/script/PlcApi/getNodes.py
new file mode 100755 (executable)
index 0000000..1f6977d
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+import xmlrpclib
+import getpass
+import Auth
+
+plc_host='www.planet-lab.eu'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+nodeId = int(raw_input("Give me the node id: "))
+
+nodes = plc_api.GetNodes(Auth.auth, [nodeId], ['boot_state', 'site_id', 'hostname'])
+
+for node in nodes:
+       print node
diff --git a/forge/script/PlcApi/getSites.py b/forge/script/PlcApi/getSites.py
new file mode 100755 (executable)
index 0000000..43fc4be
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+import xmlrpclib
+import getpass
+import Auth
+
+plc_host='www.planet-lab.eu'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+siteId = raw_input("Give me the id of the site : ")
+try:
+       siteId = int(siteId)
+except Exception, why:
+       pass
+print type(siteId)
+sites = plc_api.GetSites(Auth.auth, [siteId], ['site_id', 'name', 'max_slices', 'slice_ids', 'node_ids', 'ext_consortium_id', 'login_base'])
+
+i = j = 0
+for site in sites:
+       if i <= 5:
+               print site
+               i+=1
+       else:
+               j+=1
+
+print "i = ",i," j = ",j
diff --git a/forge/script/PlcApi/getSitesNNodes.py b/forge/script/PlcApi/getSitesNNodes.py
new file mode 100755 (executable)
index 0000000..1409979
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+import xmlrpclib
+import Auth
+
+plc_host='www.planet-lab.eu'
+slice_name='upmc_tp'
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+N = input("Number of environment wanted :")
+M = input("Number of node wanted by environment :")
+sites = plc_api.GetSites(Auth.auth, ['*'], ['site_id', 'name', 'max_slices', 'slice_ids', 'node_ids'])
+sitesSelected = []
+
+i =  0
+for site in sites:
+       if i < N:
+               j = 0
+               nodesSite = plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'boot_state'])
+               for node in nodesSite:
+                       #print node
+                       if node['boot_state'] == 'boot' and node['run_level'] == 'boot':
+                               j+=1
+               if j >= M:
+                       i += 1
+                       sitesSelected.append(site)
+
+for site in sitesSelected:
+       print site['name'], site['site_id']
+
+if len(sitesSelected) < N:
+       print "\tWe just manage to find ",len(sitesSelected),"environment"
diff --git a/forge/script/PlcApi/getSlices.py b/forge/script/PlcApi/getSlices.py
new file mode 100755 (executable)
index 0000000..d456949
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+
+slice_pref='upmc_'
+
+plc_host='www.planet-lab.eu'
+api_url="https://%s:443/PLCAPI/"%plc_host
+
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+sliceName = slice_pref+raw_input("Give me the name of the slice : ")
+
+sliceWanted = None
+slices = plc_api.GetSlices(Auth.auth, sliceName, ['creator_person_id', 'name', 'max_nodes', 'node_ids', 'person_ids', 'slice_id'])
+
+if len(slices) > 0:
+       for slice_i in slices:
+               print slice_i['name']
+       sliceWanted = slices[0]
+
+if sliceWanted == None:
+       print "The slice "+sliceName+" doesn't exist"
+       sys.exit(2)
+persons = plc_api.GetPersons(Auth.auth, sliceWanted['person_ids'], ['first_name', 'email'])
+nodes = plc_api.GetNodes(Auth.auth, sliceWanted['node_ids'], ['hostname', 'site_id', 'node_id'])
+
+tags = plc_api.GetSliceTags(Auth.auth, {'slice_id': sliceWanted['slice_id']}, ['description', 'tagname', 'value', 'slice_tag_id'])
+
+creator = plc_api.GetPersons(Auth.auth, sliceWanted['creator_person_id'], ['first_name', 'email'])
+
+
+for person in persons:
+       print person
+
+if creator not in persons:
+       print "\tCreator"
+       print "\t\t"+str(creator)
+else:
+       print "\tCreator is in user list"
+
+print sliceWanted
+for node in nodes:
+       print "\t"+str(node)
+       pass
+print "Tag list"
+for tag in tags:
+       #print "\t"+str(tag)
+       pass
diff --git a/forge/script/PlcApi/showKeys.py b/forge/script/PlcApi/showKeys.py
new file mode 100755 (executable)
index 0000000..0c74e6f
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+from Auth import *
+
+keyId = plc_api.GetKeys(auth, {'person_id': 249241}, ['key_id', 'key'])
+for key in keyId:
+               print "A new key:"
+               print "Key value ->", key['key']
+               print "Key id ->",key['key_id']
+
diff --git a/forge/script/PlcApi/testRequest.py b/forge/script/PlcApi/testRequest.py
new file mode 100755 (executable)
index 0000000..584450b
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+import xmlrpclib
+import Auth
+
+plc_host='www.planet-lab.eu'
+slice_pref='upmc_'
+
+slice_name=slice_pref+raw_input('Give me the name of the slice : ')
+
+api_url="https://%s:443/PLCAPI/"%plc_host
+plc_api= xmlrpclib.ServerProxy(api_url, allow_none=True)
+
+# The slice's node ids
+node_ids = plc_api.GetSlices(Auth.auth, slice_name,['node_ids'])[0]['node_ids']
+
+# Get Hostname for these nodes
+slice_nodes = plc_api.GetNodes(Auth.auth, node_ids, ['hostname', 'run_level'])
+
+for node in slice_nodes:
+       print node
diff --git a/forge/script/Test b/forge/script/Test
new file mode 100644 (file)
index 0000000..a833dc5
--- /dev/null
@@ -0,0 +1,11 @@
+Slice name : upmc_testForge
+       Env 1
+               distance : 0    hostname : planetlab2.upc.es    longitude : 2.11273     latitude : 41.3897      type : private  id : 931
+               distance : 0    hostname : aguila1.lsi.upc.edu  longitude : 2.11273     latitude : 41.3897      type : common   id : 15840
+               distance : 1198 hostname : aladdin.planetlab.extranet.uni-passau.de     longitude : 13.47       latitude : 48.58        type : common   id : 14809
+               distance : 19310        hostname : planetlab-n2.wand.net.nz     longitude : 175.318     latitude : -37.7892     type : common   id : 14617
+       Env 2
+               distance : 0    hostname : planetlab1.upc.es    longitude : 2.11273     latitude : 41.3897      type : private  id : 930
+               distance : 0    hostname : aguila1.lsi.upc.edu  longitude : 2.11273     latitude : 41.3897      type : common   id : 15840
+               distance : 1198 hostname : aladdin.planetlab.extranet.uni-passau.de     longitude : 13.47       latitude : 48.58        type : common   id : 14809
+               distance : 19310        hostname : planetlab-n2.wand.net.nz     longitude : 175.318     latitude : -37.7892     type : common   id : 14617
diff --git a/forge/script/__init__.py b/forge/script/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forge/script/classDefinition.py b/forge/script/classDefinition.py
new file mode 100644 (file)
index 0000000..77e8fc9
--- /dev/null
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+from serviceScript import *
+
+class String:
+       def __init__(self):
+               self.value = None
+       
+       def __str__(self):
+               if self.value == None:
+                       return "None"
+               else:
+                       return self.value
+
+class Device:
+       def __init__(self):
+               self.id_dev = None
+               self.ip = None
+       
+       def __str__(self):
+               if self.id_dev == None:
+                       return "It's a new Device"
+               else:
+                       return "Device "+self.id_dev+" --> "+self.ip
+
+class Host:
+       def __init__(self):
+               self.id_host = None
+               self.url = String()
+               self.ssh = None
+               self.devices = []
+               self.services = None
+               self.routes = []
+               self.hostType = String()
+       
+       def __str__(self):
+               if len(self.devices) == 0:
+                       return "It's a new Host"
+               else:
+                       return "Host "+str(self.id_host)+" on "+str(self.url)+" has "+str(len(self.devices))+" device(s)"
+
+class Slice:
+       def __str__(self):
+               if len(self.hosts) == 0:
+                       return "It's a new Slice"
+               else:
+                       return "Slice "+str(self.slice_name)+" contain "+str(len(self.hosts))+" host(s)"
+
+       def __init__(self):
+               self.slice_name = String()
+               self.hosts = []
+
+class HostLink:
+       def __init__(self):
+               self.slice_name = None
+               self.id_host = None
+               self.url = None
+               self.ssh = None
+               self.bridge_name = None
+
+       def __str__(self):
+               return str(self.slice_name)+"@"+str(self.url)+"->"+str(self.bridge_name)
+
+class Link:
+       def __init__(self):
+               self.host1 = None
+               self.host2 = None
+
+       def __str__(self):
+               return " "+str(self.host1)+" <===> "+str(self.host2)
+
+class Route:
+       def __init__(self, slice_name, host_url, ssh, host_id):
+               self.slice_name = slice_name
+               self.host_url = host_url
+               self.host_ssh = ssh
+               self.host_id = host_id
+               self.subnet = None
+               self.gateway = None
+               self.device = None
+       
+       def __str__(self):
+               if self.slice_name == None:
+                       return "Empty route"
+               else:
+                       return " On "+str(self.slice_name)+"@"+str(self.host_url)+" add "+self.subnet+" gw "+self.gateway+" dev "+self.device 
+       
+       def setRoute(self):
+               execute("sudo -S sh -c  \"echo \\\"add "+self.subnet+" gw "+self.gateway+" "+self.device+"\\\" > /vsys/vroute.in\"", self.host_ssh, display = True)
+
+class Service:
+       def __init__(self, slice_name, url, ssh):
+               self.slice_name = slice_name
+               self.host_url = url
+               self.host_ssh = ssh
+               self.services = []
+       
+       def __str__(self):
+               if len(self.services) == 0:
+                       retour = ''
+               else:
+                       retour = " On "+str(self.slice_name)+"@"+str(self.host_url)+" set:"
+                       for service, port in self.services:
+                               if port != '':
+                                       retour += "\n\t"+service+" on port "+port
+                               else:
+                                       retour += "\n\t"+service
+               return retour
+
+       def setService(self):
+               print "\tOn "+str(self.slice_name)+"@"+str(self.host_url)+" now setting :"
+               for i in range(len(self.services)):
+                       if self.services[i][0] == "x11":
+                               setXRedirect(self.host_ssh)
+                       elif self.services[i][0] == "httpd":
+                               if port != '':
+                                       self.services[i][1] = setHttpd(self.host_ssh, port, self.host_url)
+                               else:
+                                       print "Error you didn't specified the port used by httpd"
+                       elif self.services[i][0] == "wireshark":
+                               setWireshark(self.host_ssh)
+                       elif self.services[i][0] == "firefox":
+                               setFirefox(self.host_ssh)
+                       elif self.services[i][0] == "php" or self.services[i][0] == 'PHP':
+                               setPHP(self.host_ssh)
+                       else:
+                               print "The service "+service+" is not available"
+
+       def removeService(self):
+               for service, port in self.services:
+                       if service == "x11":
+                               removeXRedirect(self.host_ssh)
+                       elif service == "httpd":
+                               removeHttpd(self.host_ssh)
+                       elif service == "wireshark":
+                               removeWireshark(self.host_ssh)
+                       elif service == "firefox":
+                               removeFirefox(self.host_ssh)
+                       elif service == "php" or service == 'PHP':
+                               removePHP(self.host_ssh)
+
diff --git a/forge/script/configService/fedora-updates-testing.repo b/forge/script/configService/fedora-updates-testing.repo
new file mode 100644 (file)
index 0000000..0d4d68b
--- /dev/null
@@ -0,0 +1,29 @@
+[updates-testing]
+name=Fedora $releasever - $basearch - Test Updates
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/
+#baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/$basearch/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-testing-debuginfo]
+name=Fedora $releasever - $basearch - Test Updates Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/$basearch/debug/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-debug-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-testing-source]
+name=Fedora $releasever - Test Updates Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/SRPMS/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/testing/$releasever/SRPMS/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-testing-source-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/fedora-updates.repo b/forge/script/configService/fedora-updates.repo
new file mode 100644 (file)
index 0000000..d23e871
--- /dev/null
@@ -0,0 +1,29 @@
+[updates]
+name=Fedora $releasever - $basearch - Updates
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/$basearch/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch
+enabled=1
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-debuginfo]
+name=Fedora $releasever - $basearch - Updates - Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/$basearch/debug/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-debug-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[updates-source]
+name=Fedora $releasever - Updates Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/SRPMS/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/updates/$releasever/SRPMS/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=updates-released-source-f$releasever&arch=$basearch
+enabled=0
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/fedora.repo b/forge/script/configService/fedora.repo
new file mode 100644 (file)
index 0000000..c7dda3d
--- /dev/null
@@ -0,0 +1,31 @@
+[fedora]
+name=Fedora $releasever - $basearch
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/releases/$releasever/Everything/$basearch/os/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch
+enabled=1
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[fedora-debuginfo]
+name=Fedora $releasever - $basearch - Debug
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/debug/
+baseurl=http://ftp-stud.hs-esslingen.de/pub/Mirrors/archive.fedoraproject.org/fedora/linux/releases/$releasever/Everything/$basearch/debug/
+#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-debug-$releasever&arch=$basearch
+enabled=0
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
+
+[fedora-source]
+name=Fedora $releasever - Source
+failovermethod=priority
+#baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/source/SRPMS/
+mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-source-$releasever&arch=$basearch
+enabled=0
+metadata_expire=7d
+gpgcheck=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$basearch
diff --git a/forge/script/configService/httpd.conf b/forge/script/configService/httpd.conf
new file mode 100644 (file)
index 0000000..96c8357
--- /dev/null
@@ -0,0 +1,994 @@
+#
+# This is the main Apache server configuration file.  It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.2/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do.  They're here only as hints or reminders.  If you are unsure
+# consult the online docs. You have been warned.  
+#
+# The configuration directives are grouped into three basic sections:
+#  1. Directives that control the operation of the Apache server process as a
+#     whole (the 'global environment').
+#  2. Directives that define the parameters of the 'main' or 'default' server,
+#     which responds to requests that aren't handled by a virtual host.
+#     These directives also provide default values for the settings
+#     of all virtual hosts.
+#  3. Settings for virtual hosts, which allow Web requests to be sent to
+#     different IP addresses or hostnames and have them handled by the
+#     same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/etc/httpd" will be interpreted by the
+# server as "/etc/httpd/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# Don't give away too much information about all the subcomponents
+# we are running.  Comment out this line if you don't mind remote sites
+# finding out what major optional modules you are running
+ServerTokens OS
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE!  If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+# Do NOT add a slash at the end of the directory path.
+#
+ServerRoot "/etc/httpd"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+PidFile run/httpd.pid
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 120
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive Off
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+##
+## Server-Pool Size Regulation (MPM specific)
+## 
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# ServerLimit: maximum value for MaxClients for the lifetime of the server
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule prefork.c>
+StartServers       8
+MinSpareServers    5
+MaxSpareServers   20
+ServerLimit      256
+MaxClients       256
+MaxRequestsPerChild  4000
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule worker.c>
+StartServers         2
+MaxClients         150
+MinSpareThreads     25
+MaxSpareThreads     75 
+ThreadsPerChild     25
+MaxRequestsPerChild  0
+</IfModule>
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, in addition to the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to 
+# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
+#
+#Listen 12.34.56.78:80
+Listen *:80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_alias_module modules/mod_authn_alias.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_default_module modules/mod_authn_default.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_default_module modules/mod_authz_default.so
+LoadModule ldap_module modules/mod_ldap.so
+LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule env_module modules/mod_env.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule usertrack_module modules/mod_usertrack.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule info_module modules/mod_info.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule speling_module modules/mod_speling.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule disk_cache_module modules/mod_disk_cache.so
+LoadModule cgi_module modules/mod_cgi.so
+
+#
+# The following modules are not loaded by default:
+#
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule asis_module modules/mod_asis.so
+
+#
+# Load config files from the config directory "/etc/httpd/conf.d".
+#
+Include conf.d/*.conf
+
+#
+# ExtendedStatus controls whether Apache will generate "full" status
+# information (ExtendedStatus On) or just basic information (ExtendedStatus
+# Off) when the "server-status" handler is called. The default is Off.
+#
+#ExtendedStatus On
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.  
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+#  . On SCO (ODT 3) use "User nouser" and "Group nogroup".
+#  . On HPUX you may not be able to use shared memory as nobody, and the
+#    suggested workaround is to create a user www and use that user.
+#  NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
+#  when the value of (unsigned)Group is above 60000; 
+#  don't use Group #-1 on these systems!
+#
+User apache
+Group apache
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed.  This address appears on some server-generated pages, such
+# as error documents.  e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If this is not set to valid DNS name for your host, server-generated
+# redirections will not work.  See also the UseCanonicalName directive.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address anyway, and this will make 
+# redirections work in a sensible way.
+#
+#ServerName www.example.com:80
+
+#
+# UseCanonicalName: Determines how Apache constructs self-referencing 
+# URLs and the SERVER_NAME and SERVER_PORT variables.
+# When set "Off", Apache will use the Hostname and Port supplied
+# by the client.  When set "On", Apache will use the value of the
+# ServerName directive.
+#
+UseCanonicalName Off
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/var/www/html"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+# First, we configure the "default" to be a very restrictive set of 
+# features.  
+#
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+<Directory "/var/www/html">
+
+#
+# Possible values for the Options directive are "None", "All",
+# or any combination of:
+#   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+# The Options directive is both complicated and important.  Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#options
+# for more information.
+#
+    Options Indexes FollowSymLinks
+
+#
+# AllowOverride controls what directives may be placed in .htaccess files.
+# It can be "All", "None", or any combination of the keywords:
+#   Options FileInfo AuthConfig Limit
+#
+    AllowOverride None
+
+#
+# Controls who can get stuff from this server.
+#
+    Order allow,deny
+    Allow from all
+
+</Directory>
+
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid.  This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+# See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden
+#
+<IfModule mod_userdir.c>
+    #
+    # UserDir is disabled by default since it can confirm the presence
+    # of a username on the system (depending on home directory
+    # permissions).
+    #
+    UserDir disabled
+
+    #
+    # To enable requests to /~user/ to serve the user's public_html
+    # directory, remove the "UserDir disabled" line above, and uncomment
+    # the following line instead:
+    # 
+    #UserDir public_html
+
+</IfModule>
+
+#
+# Control access to UserDir directories.  The following is an example
+# for a site where these directories are restricted to read-only.
+#
+#<Directory /home/*/public_html>
+#    AllowOverride FileInfo AuthConfig Limit
+#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+#    <Limit GET POST OPTIONS>
+#        Order allow,deny
+#        Allow from all
+#    </Limit>
+#    <LimitExcept GET POST OPTIONS>
+#        Order deny,allow
+#        Deny from all
+#    </LimitExcept>
+#</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+# The index.html.var file (a type-map) is used to deliver content-
+# negotiated documents.  The MultiViews Option can be used for the 
+# same purpose, but it is much slower.
+#
+DirectoryIndex index.html index.html.var
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives.  See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+TypesConfig /etc/mime.types
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type.  The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+<IfModule mod_mime_magic.c>
+#   MIMEMagicFile /usr/share/magic.mime
+    MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# EnableMMAP: Control whether memory-mapping is used to deliver
+# files (assuming that the underlying OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted 
+# filesystems.  On some systems, turning it off (regardless of
+# filesystem) can improve performance; for details, please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablemmap
+#
+#EnableMMAP off
+
+#
+# EnableSendfile: Control whether the sendfile kernel support is 
+# used to deliver files (assuming that the OS supports it). 
+# The default is on; turn this off if you serve from NFS-mounted 
+# filesystems.  Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
+#
+#EnableSendfile off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog logs/error_log
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# "combinedio" includes actual counts of actual bytes received (%I) and sent (%O); this
+# requires the mod_logio module to be loaded.
+#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here.  Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+#CustomLog logs/access_log common
+
+#
+# If you would like to have separate agent and referer logfiles, uncomment
+# the following directives.
+#
+#CustomLog logs/referer_log referer
+#CustomLog logs/agent_log agent
+
+#
+# For a single logfile with access, agent, and referer information
+# (Combined Logfile Format), use the following directive:
+#
+CustomLog logs/access_log combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is 
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL.  So "/icons" isn't aliased in this
+# example, only "/icons/".  If the fakename is slash-terminated, then the 
+# realname must also be slash terminated, and if the fakename omits the 
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings.  If you
+# do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/var/www/icons/"
+
+<Directory "/var/www/icons">
+    Options Indexes MultiViews FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+#
+# WebDAV module configuration section.
+# 
+<IfModule mod_dav_fs.c>
+    # Location of the WebDAV lock database.
+    DAVLockDB /var/lib/dav/lockdb
+</IfModule>
+
+#
+# ScriptAlias: This controls which directories contain server scripts.
+# ScriptAliases are essentially the same as Aliases, except that
+# documents in the realname directory are treated as applications and
+# run by the server when requested rather than as documents sent to the client.
+# The same rules about trailing "/" apply to ScriptAlias directives as to
+# Alias.
+#
+ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/var/www/cgi-bin">
+    AllowOverride None
+    Options None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Example:
+# Redirect permanent /foo http://www.example.com/bar
+
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions.  These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif core
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes.  These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes. 
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing.  Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of 
+# a document. You can then use content negotiation to give a browser a 
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will 
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as 
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases 
+# the two character 'Language' abbreviation is not identical to 
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portugese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default.  To use the 
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-tar .tgz
+
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have nothing
+# to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+
+#
+#   MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl    .crl
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+#  to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections.  We use 
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+#   Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /var/www/error/include/ files and
+# copying them to /your/include/path/, even on a per-VirtualHost basis.
+#
+
+Alias /error/ "/var/www/error/"
+
+<IfModule mod_negotiation.c>
+<IfModule mod_include.c>
+    <Directory "/var/www/error">
+        AllowOverride None
+        Options IncludesNoExec
+        AddOutputFilter Includes html
+        AddHandler type-map var
+        Order allow,deny
+        Allow from all
+        LanguagePriority en es de fr
+        ForceLanguagePriority Prefer Fallback
+    </Directory>
+
+#    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+#    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+#    ErrorDocument 410 /error/HTTP_GONE.html.var
+#    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+#    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+#    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+#    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+#    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+#    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+#    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+#    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+#    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+#    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+</IfModule>
+</IfModule>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash.  This fixes a 
+# problem with Microsoft WebFolders which does not appropriately handle 
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-status>
+#    SetHandler server-status
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Location>
+
+#
+# Allow remote server configuration reports, with the URL of
+#  http://servername/server-info (requires that mod_info.c be loaded).
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-info>
+#    SetHandler server-info
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Location>
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+#ProxyRequests On
+#
+#<Proxy *>
+#    Order deny,allow
+#    Deny from all
+#    Allow from .example.com
+#</Proxy>
+
+#
+# Enable/disable the handling of HTTP/1.1 "Via:" headers.
+# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+# Set to one of: Off | On | Full | Block
+#
+#ProxyVia On
+
+#
+# To enable a cache of proxied content, uncomment the following lines.
+# See http://httpd.apache.org/docs/2.2/mod/mod_cache.html for more details.
+#
+#<IfModule mod_disk_cache.c>
+#   CacheEnable disk /
+#   CacheRoot "/var/cache/mod_proxy"
+#</IfModule>
+#
+
+#</IfModule>
+# End of proxy directives.
+
+### Section 3: Virtual Hosts
+#
+# VirtualHost: If you want to maintain multiple domains/hostnames on your
+# machine you can setup VirtualHost containers for them. Most configurations
+# use only name-based virtual hosts so the server doesn't need to worry about
+# IP addresses. This is indicated by the asterisks in the directives below.
+#
+# Please see the documentation at 
+# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
+# for further details before you try to setup virtual hosts.
+#
+# You may use the command line option '-S' to verify your virtual host
+# configuration.
+
+#
+# Use name-based virtual hosting.
+#
+#NameVirtualHost *:80
+#
+# NOTE: NameVirtualHost cannot be used without a port specifier 
+# (e.g. :80) if mod_ssl is being used, due to the nature of the
+# SSL protocol.
+#
+
+#
+# VirtualHost example:
+# Almost any Apache directive may go into a VirtualHost container.
+# The first VirtualHost section is used for requests without a known
+# server name.
+#
+#<VirtualHost *:80>
+#    ServerAdmin webmaster@dummy-host.example.com
+#    DocumentRoot /www/docs/dummy-host.example.com
+#    ServerName dummy-host.example.com
+#    ErrorLog logs/dummy-host.example.com-error_log
+#    CustomLog logs/dummy-host.example.com-access_log common
+#</VirtualHost>
diff --git a/forge/script/configService/id_rsa.pub b/forge/script/configService/id_rsa.pub
new file mode 100644 (file)
index 0000000..ca5f7e5
--- /dev/null
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDg67pRFT/QYg3sZB1QIHO83Mme1Vl8m3yV48JDiHki2c12IuMbhUunDqq/BoXmHEEUcRLuvVhslzl3/oaeY1udO6m+JP4Xvb3RBw0vtzxlKxlCUoz48Pshb2Zx9bCup2g8VUMeWzYQwggjqxQ4Jiom7T+czQWdnPqi8If0x/OGOeSKimP7NhHqiHrGoNLG2k6fwFApTK4PTSyvegx13tDwcwF14C6OGA84kVmOyU/6xH/sa3Lsj08/1J00fcIn7KI/3LG62n6riuPAu4Dki9UV7TaM5dvN1VcTzcaU0X/mtOrOQnlJ5vyOGgPCxGhnYvirnQLBeh7NwrIb/sasfWUJ belgarion@debian
diff --git a/forge/script/configService/index.html b/forge/script/configService/index.html
new file mode 100644 (file)
index 0000000..1c70d95
--- /dev/null
@@ -0,0 +1,4 @@
+<html><body><h1>It works!</h1>
+<p>This is the default web page for this server.</p>
+<p>The web server software is running but no content has been added, yet.</p>
+</body></html>
diff --git a/forge/script/configService/sshd_config b/forge/script/configService/sshd_config
new file mode 100644 (file)
index 0000000..9924c65
--- /dev/null
@@ -0,0 +1,14 @@
+Protocol 2
+SyslogFacility AUTHPRIV
+
+PubkeyAuthentication yes
+AuthorizedKeysFile .ssh/id_rsa.pub
+
+PasswordAuthentication yes
+
+ChallengeResponseAuthentication no
+UsePAM yes
+
+X11Forwarding yes
+
+# The listening port is added by the function from service.py
diff --git a/forge/script/exceptionDefinition.py b/forge/script/exceptionDefinition.py
new file mode 100644 (file)
index 0000000..a430b6d
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+class FailToConnect(Exception):
+       def __init__(self, nodeId, nodeUrl):
+               self.nodeId = nodeId
+               self.nodeUrl = nodeUrl
+       def __str__(self):
+               return repr(self.siteId)
+       def getNodeId(self):
+               return self.nodeId
+       def getNodeUrl(self):
+               return self.nodeUrl
+
+class SSHConnectError(Exception):
+       def __init__(self, host, sliceName):
+               self.why = "Can't connect to the node "+str(sliceName)+"@"+str(host)
+       
+       def __str__(self):
+        return repr(self.why)
+
+class NodeConstraintError(Exception):
+       def __init__(self, constraint, envList):
+               self.why = "Can't find node with constraint : "+str(constraint)
+               self.envList = envList
+
+       def getEnvList(self):
+               return self.envList
diff --git a/forge/script/openvswitch.py b/forge/script/openvswitch.py
new file mode 100755 (executable)
index 0000000..dfe24c6
--- /dev/null
@@ -0,0 +1,397 @@
+#!/usr/bin/env python
+
+import sys
+import argparse
+
+import logging
+import paramiko
+import signal
+import os
+import time
+
+# Import the class used (Slice, Host, Device, Link, HostLink)
+from classDefinition import *
+
+from exceptionDefinition import SSHConnectError
+
+class TransformXml:
+       
+       def __init__(self, confFile = 'Conf.xml', linkFile = 'Link.xml', prefix = '', port = 22, keyFile = '~/.ssh/id_rsa'):
+               self.__currentNodeConf__ = None
+               self.__currentNodeLink__ = None
+               self.__currentNodeRoute__= None
+               self.__currentNodeService__ = None
+               self.__sliceList__ = []
+               self.__linkList__ = []
+               
+               self.readXml(prefix+confFile, prefix+linkFile)
+               self.sshPort = port
+               self.sshKey = keyFile
+               self.xmlToSliceObject()
+               self.xmlToLinkObject()
+       
+       def readXml(self, confPath, linkPath):
+               from xml.dom.minidom import parse
+               if not(os.path.isfile(confPath) and os.path.isfile(linkPath)):
+                       print "Error file "+confPath+" or "+linkPath+" does not exist"
+                       sys.exit(2)
+               self.conf = parse(confPath)
+               self.link = parse(linkPath)
+       
+       def getRootElementConf(self):
+               if self.__currentNodeConf__ == None:
+                       self.__currentNodeConf__ = self.conf.documentElement
+               return self.__currentNodeConf__
+       
+       def getRootElementLink(self):
+               if self.__currentNodeLink__ == None:
+                       self.__currentNodeLink__ = self.link.documentElement
+               return self.__currentNodeLink__
+       
+       def xmlToServiceObject(self, rootService, host, slice_name):
+               i = 0
+               newService = Service(slice_name, host.url, host.ssh)
+               for service_i in rootService.getElementsByTagName("service"):
+                       try:
+                                service = self.getText(service_i)
+                       except:
+                               print "The tag service is missig"
+                       servicePart = service.partition(':')
+                       newService.services.append([servicePart[0], servicePart[2]])
+               host.services = newService
+
+       def setServices(self):
+               print "Now setting the service"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               host_i.services.setService()
+                       
+       def xmlToRouteObject(self, rootRoute, host, sliceName):
+               for route_i in rootRoute.getElementsByTagName("route"):
+                       newRoute = Route(sliceName, host.url, host.ssh, host.id_host)
+                       try:
+                               newRoute.subnet = self.getText(route_i.getElementsByTagName("subnet")[0])
+                               newRoute.gateway = self.getText(route_i.getElementsByTagName("gateway")[0])
+                               devId = self.getText(route_i.getElementsByTagName("device")[0])
+                       except:
+                               print "The tag subnet / gateway or device is missing"
+                               sys.exit(2)
+                       newRoute.device = self.getTapId(newRoute, devId, host)
+                       host.routes.append(newRoute)
+
+       def setRoutes(self):
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               for route_i in host_i.routes:
+                                       route_i.setRoute()
+
+       def xmlToSliceObject(self):
+               i = j = k = 0
+               for slice_i in self.getRootElementConf().getElementsByTagName("slice"):
+                       i += 1
+                       newSlice = Slice()
+                       try:
+                               newSlice.slice_name.value = self.getText(slice_i.getElementsByTagName("slice_name")[0])
+                       except :
+                               print "The tag slice_name is missing"
+                               sys.exit(2)
+                       for host_i in slice_i.getElementsByTagName("host"):
+                               j+=1
+                               newHost = Host()
+                               try:
+                                       newHost.hostType.value = self.getText(host_i.getElementsByTagName("type")[0])
+                                       newHost.id_host = self.getText(host_i.getElementsByTagName("id")[0])
+                                       newHost.url.value = self.getText(host_i.getElementsByTagName("url")[0])
+                               except Exception, why:
+                                       print "Tag id or url is missing"
+                                       print "Slice",newSlice.slice_name," Host ",newHost.url," Interface ",str(k)
+                                       print "Why -> ", why
+                                       sys.exit(2)
+                               newHost.ssh = self.sshCheck(newHost.url.value, newSlice.slice_name.value)
+                               for interface_i in host_i.getElementsByTagName("interface"):
+                                       k+=1
+                                       newDevice = Device()
+                                       try:
+                                               newDevice.id_dev = self.getText(interface_i.getElementsByTagName("bridge_name")[0])
+                                               newDevice.ip = self.getText(interface_i.getElementsByTagName("ip")[0])
+                                       except:
+                                               print "Tag bridge_name or ip is missing"
+                                               #sys.exit(2)
+                                       newHost.devices.append(newDevice)
+                               try:
+                                       serviceRoot = host_i.getElementsByTagName("services")[0]
+                                       self.xmlToServiceObject(serviceRoot, newHost, newSlice.slice_name)
+                               except:
+                                       newHost.services = Service("","","")
+                               try:
+                                       routeRoot = host_i.getElementsByTagName("routes")[0]
+                                       self.xmlToRouteObject(routeRoot, newHost, newSlice.slice_name)
+                               except:
+                                       print "No additionnal route for host "+str(newSlice.slice_name)+"@"+str(newHost.url)
+                               newSlice.hosts.append(newHost)
+                       self.__sliceList__.append(newSlice)
+
+       def setSliceConf(self):
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               if len(host_i.devices) > 0:
+                                       print "\tOn "+str(slice_i.slice_name)+"@"+str(host_i.url)
+                                       self.execute("sudo -S sliver-ovs start_db", host_i.ssh, display = True)
+                                       self.execute("sudo -S sliver-ovs start_switch", host_i.ssh, display = True)
+                                       for interface_i in host_i.devices:
+                                               returnCode = -1
+                                               i = 0
+                                               while returnCode != 0:
+                                                       returnCode = self.execute("sudo -S sliver-ovs create_bridge "+interface_i.id_dev+" "+interface_i.ip,host_i.ssh)
+       
+                                                       if returnCode != 0:
+                                                               i += 1
+                                                               self.execute("sudo -S sliver-ovs del_bridge "+interface_i.id_dev, host_i.ssh)
+                                                               if i > 10:
+                                                                       print "I have make ",i," iteration"
+                                                               time.sleep(60)
+                                                       else:
+                                                               print "I make",i,"iteration before successfully create the interface"
+       
+       def xmlToLinkObject(self):
+               for link_i in self.getRootElementLink().getElementsByTagName("link"):
+                       newLink = Link()
+                       newHost1 = HostLink()
+                       newHost2 = HostLink()
+                       try:
+                               host1 = link_i.getElementsByTagName("host1")[0]
+                               host2 = link_i.getElementsByTagName("host2")[0]
+                       except:
+                               print "Tag host1/host2 is missing"
+                               sys.exit(2)
+                       try:
+                               newHost1.slice_name = self.getText(host1.getElementsByTagName("slice")[0])
+                               newHost1.id_host = self.getText(host1.getElementsByTagName("id")[0])
+                               newHost1.bridge_name = self.getText(host1.getElementsByTagName("bridge_name")[0])
+                       except:
+                               print "Tag slice, id or bridge_name is missing for host1"
+                               sys.exit(2)
+                       try:
+                               newHost2.slice_name = self.getText(host2.getElementsByTagName("slice")[0])
+                               newHost2.id_host = self.getText(host2.getElementsByTagName("id")[0])
+                               newHost2.bridge_name = self.getText(host2.getElementsByTagName("bridge_name")[0])
+                       except:
+                               print "Tag slice, id or bridge_name is missing for host2"
+
+                       newHost1.ssh, newHost1.url = self.getSSHAccessUrl(newHost1.slice_name, newHost1.id_host )
+                       newHost2.ssh, newHost2.url = self.getSSHAccessUrl(newHost2.slice_name, newHost2.id_host )
+                       newLink.host1 = newHost1
+                       newLink.host2 = newHost2
+                       self.__linkList__.append(newLink)
+
+       def setLinks(self):
+               import subprocess
+               print "Creating Links"
+               for link_i in self.__linkList__:
+                       host1 = link_i.host1
+                       host2 = link_i.host2
+                       link_name_host1 = host1.slice_name+"@"+str(host1.url)+"@"+host1.bridge_name
+                       link_name_host2 = host2.slice_name+"@"+str(host2.url)+"@"+host2.bridge_name
+                       link_name = link_name_host1+"---"+link_name_host2
+                       print "\tOn "+str(host1.slice_name)+"@"+str(host1.url)
+                       self.execute("sudo -S sliver-ovs create_port "+host1.bridge_name+" "+link_name, host1.ssh)
+                       print "\tOn "+str(host2.slice_name)+"@"+str(host2.url)
+                       self.execute("sudo -S sliver-ovs create_port "+host2.bridge_name+" "+link_name, host2.ssh)
+                       proc = subprocess.Popen(["host "+str(host1.url)+" | sed -n 's/^.*has address *//p'"], stdout=subprocess.PIPE, shell=True)
+                       (out, err) = proc.communicate()
+                       ip1 = out.replace('\n','')
+                       proc = subprocess.Popen(["host "+str(host2.url)+" | sed -n 's/^.*has address *//p'"], stdout=subprocess.PIPE, shell=True)
+                       (out, err) = proc.communicate()
+                       ip2 = out.replace('\n','')
+                       portUDP1 = self.execute("sudo -S sliver-ovs get_local_endpoint "+link_name, host1.ssh, retour=True).replace('\n','')
+                       portUDP2 = self.execute("sudo -S sliver-ovs get_local_endpoint "+link_name, host2.ssh, retour=True).replace('\n','')
+                       print "\tPort UDP1 = "+str(portUDP1)+" Port UDP2 = "+str(portUDP2)
+                       self.execute("sudo -S sliver-ovs set_remote_endpoint "+link_name+" "+ip2+" "+portUDP2, host1.ssh)
+                       self.execute("sudo -S sliver-ovs set_remote_endpoint "+link_name+" "+ip1+" "+portUDP1, host2.ssh)
+
+       def getSSHAccessUrl(self, slice_name, id_host):
+               host_search = self.getHost(slice_name, id_host)
+               return host_search.ssh, host_search.url
+
+       def getHost(self, slice_name, host_id):
+               i = j = 0
+               slice_search = self.__sliceList__[i]
+               try:
+                       while slice_search.slice_name.value != slice_name:
+                               i+=1
+                               slice_search = self.__sliceList__[i]
+                       host_search = slice_search.hosts[j]
+                       while host_search.id_host != host_id:
+                               j+=1
+                               host_search = slice_search.hosts[j]
+               except IndexError:
+                       print "The host in slice ->",slice_name,"and host id ->",host_id,"doesn't exist"
+                       print "\tAn IndexError occured"
+                       sys.exit(2)
+               return host_search
+
+       def getUrl(self, slice_name, id_host):
+               host_search = self.getHost(slice_name, id_host)
+               return host_search.url
+
+       def getTapId(self, route, idDev, host):
+               idUser = self.execute("id -u", route.host_ssh, retour = True).replace('\n','')
+               i = 0
+               dev_searched = host.devices[i]
+               try:
+                       while dev_searched.id_dev != idDev:
+                               i += 1
+                               dev_searched = host_searched.devices[i]
+               except IndexError:
+                       print "Error while setting the route"
+                       print "For slice ->",host_searched.slice_name," id host ->",host_searched.id_host," the following device does not exist ->",idDev
+                       sys.exit(2)
+               return "tap"+idUser+"-"+str(i)
+
+       #TODO change the function for online mode
+       def sshCheck(self, host, slice_name):
+               ssh = paramiko.SSHClient()
+               ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+               try:
+                       ssh.connect(host, username=slice_name, port=self.sshPort, key_filename=self.sshKey)
+                       pass
+               # This error is raised if the ssh key has not already been installed on the node
+               except paramiko.PasswordRequiredException, why:
+                       print "Password required exception"
+                       print "Error: ", why
+                       raise SSHConnectError(host, slice_name)
+               except paramiko.SSHException:
+                       print "An SSH exception occured"
+                       raise SSHConnectError(host, slice_name)
+               except Exception, why:
+                       print "An error occured for host "+str(host)+" on slice "+str(slice_name)
+                       print why
+                       raise SSHConnectError(host, slice_name)
+               return ssh
+
+       def timeout(signum, frame):
+               raise TimeOutException, "Command ran for too long"
+
+       def getText(self, node):
+               return node.childNodes[0].nodeValue
+       
+       def execute(self, command, ssh, display=False, retour=False):
+               print "# "+command
+               stdin, stdout, stderr = ssh.exec_command(command)
+               stdin.close()
+               while not stdout.channel.exit_status_ready():
+                       time.sleep(2)
+               err = stderr.read()
+               if err != None:
+                       splitted = err.splitlines()
+                       if len(splitted) > 0:
+                               print "\tError in execution"
+                               for line in splitted:
+                                       print "\t>",line
+               if display:
+                       for line in stdout.read().splitlines() :
+                               print " > " + line
+               elif retour:
+                       return stdout.read()
+               return stdout.channel.recv_exit_status()
+       
+       def clearConf(self):
+               print "Removing the topology configuration"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               self.sshCheck(host_i.url.value, slice_i.slice_name.value)
+                               print "\tOn "+str(slice_i.slice_name)+"@"+str(host_i.url)+" clearing the conf :"
+                               sshHost = host_i.ssh
+                               for device_i in host_i.devices:
+                                       self.execute("sudo -S sliver-ovs del_bridge "+device_i.id_dev, sshHost, display=True)
+                               self.execute("sudo -S sliver-ovs stop_switch", sshHost, display=True)
+                               self.execute("sudo -S sliver-ovs stop_db", sshHost, display=True)
+                               host_i.services.removeService()
+                               
+       def printSlice(self):
+               print "List of slice/host/interface"
+               for slice_i in self.__sliceList__:
+                       print slice_i
+                       for host_i in slice_i.hosts:
+                               print "\t"+str(host_i)
+                               for dev_i in host_i.devices:
+                                       print "\t\t"+str(dev_i)
+       
+       def printLink(self):
+               print "\nList of link"
+               for link_i in self.__linkList__:
+                       print link_i
+       
+       def printRoute(self):
+               print "\nList of additionnal route"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               for route_i in host_i.routes:
+                                       print route_i
+       
+       def printService(self):
+               print "\nList of deployed service"
+               for slice_i in self.__sliceList__:
+                       for host_i in slice_i.hosts:
+                               serviceStr = str(host_i.services)
+                               if serviceStr != '':
+                                       print host_i.services
+       
+       def getSliceList(self):
+               return self.__sliceList__
+
+       @classmethod
+       def helpOption(self):
+               print "You can use the following options:"
+               print "\t setTopology : to create the topology"
+               print "\t clearTopology : to clear the topology"
+               print "\t printTopology : to print the topology"
+               print "Optionnal:"
+               print "\t $2 : configuration xml file"
+               print "\t $3 : link xml file"
+               print "\t $2 : prefix to find the xml file"
+               print "\t If not given default are Conf.xml, Link.xml"
+
+def keyFile(x):
+       print x
+       if not os.path.exists(x) and x!=os.path.expanduser('~/.ssh/id_rsa'):
+               raise argparse.ArgumentError("{0} does not exist".format(x))
+       return x
+
+if __name__ == "__main__":
+       parser = argparse.ArgumentParser()
+       #parser = argparse.ArgumentParser("This script allow you to deploy a configured topology on planetlab node, the topology has to be descript in xml file\nYou have to use one of the action option (-c -s -p)\nYou have to specify the input file that need to be used")
+       parser.add_argument("action", help="The action you want to perform choices are print, set or clear the topology", choices = ['print','set','clear'], default='print', nargs='?')
+       parser.add_argument("-k", "--key", help="The location of the ssh private key file (default value is ~/.ssh/id_rsa)", default=os.path.expanduser('~/.ssh/id_rsa'), type=keyFile)
+       parser.add_argument('-p', '--port', help='The port used for the ssh connection (default is 22)', default=22, type = int)
+
+       groupInput = parser.add_mutually_exclusive_group()
+       groupInput.add_argument("-f", "--file", help="The xml file that will be used, Link xml file then Configuration xml file", type=str, default='', nargs=2)
+       groupInput.add_argument("-d", "--directory", help="The directory used to find the xml file the script will look at prefix+Conf.xml and prefix+Link.xml", type=str, default='./', dest='prefix')
+
+       try:
+               args = parser.parse_args()
+       except Exception, why:
+               print "An error occured while parsing the argument"
+               parser.print_help()
+               print why
+               sys.exit(2)
+
+       if args.file != '':
+               x = TransformXml(confFile = args.file[0], linkFile = args.file[1], port = args.port, keyFile = args.key)
+       else:
+               x = TransformXml(prefix = args.prefix, port = args.port, keyFile = args.key )
+
+       if args.action == "set" :
+               x.setSliceConf()
+               x.setLinks()
+               x.setRoutes()
+               x.setServices()
+       elif args.action == "clear" :
+               x.clearConf()
+       elif args.action == "print" :
+               x.printSlice()
+               x.printLink()
+               x.printRoute()
+               x.printService()
+               
diff --git a/forge/script/request.py b/forge/script/request.py
new file mode 100755 (executable)
index 0000000..6056e96
--- /dev/null
@@ -0,0 +1,759 @@
+#!/usr/bin/python
+
+import xmlrpclib
+import Auth
+import sys
+import paramiko
+import subprocess
+import time
+import geopy
+import geopy.distance
+import argparse
+import os
+import socket
+import urllib2
+import csv
+from openvswitch import TransformXml
+from exceptionDefinition import FailToConnect, NodeConstraintError
+from scp import SCPClient
+
+
+yumOpt =  "sudo -S yum -y --nogpgcheck "
+
+class TransformRawXml:
+       def __init__(self, confFile = "", linkFile = "", subnet = "", prefix = "", sliceName = "", nbEnv = 1, mainKeyPriv = None, mainKeyPub = None, sliceUrl = 'http://onelab.eu', sliceDescription = 'Slice used for educationnal purpose', country = False):
+               # Definition of the api used for the actions on planetlab
+               plc_host='www.planet-lab.eu'
+               api_url='https://%s:443/PLCAPI/'%plc_host
+               self.plc_api=xmlrpclib.ServerProxy(api_url, allow_none=True)
+               # Prefix used for the slice name
+               slice_pref='upmc_'
+
+               self.sliceUrl = sliceUrl
+               self.sliceDescription = sliceDescription
+
+               myOpsPLC = urllib2.urlopen('http://monitor.planet-lab.org/monitor/query?hostname=on&tg_format=plain&object=nodes&nodehistory_hostname=&observed_status=on&rpmvalue=')
+               self.myOpsPLCCsv = list(csv.reader(myOpsPLC))
+               myOpsPLE = urllib2.urlopen('http://monitor.planet-lab.eu/monitor/query?hostname=on&tg_format=plain&object=nodes&nodehistory_hostname=&observed_status=on&rpmvalue=')
+               self.myOpsPLECsv = list(csv.reader(myOpsPLE))
+
+               self.subnet = subnet
+               if prefix != "":
+                       self.xmlFileConf = prefix+'Conf.xml'
+                       self.xmlFileLink = prefix+'Link.xml'
+               else:
+                       self.xmlFileConf = confFile
+                       self.xmlFileLink = linkFile
+               if 'upmc_' not in sliceName:
+                       self.slice_name = slice_pref+sliceName
+               else:
+                       self.slice_name = sliceName
+
+               self.nbEnv = int(nbEnv)
+               
+               self.country = country
+
+               # Attribute for ssh key
+               self.mainKeyPriv = mainKeyPriv
+               self.mainKeyPub = mainKeyPub
+               self.envKeyPriv = []
+               self.envKeyPub = []
+
+               # Attribute that will contain the list of environment
+               self.envList = []
+
+               self.envConfFile = []
+               self.envLinkFile = []
+               
+       # Delete the slice
+       def deleteSlice(self):
+               errorCode = self.plc_api.DeleteSlice(Auth.auth, self.slice_name)
+               if errorCode != 1:
+                       print "An error occured unable to delete the slice"
+                       print errorCode
+                       print self.slice_name
+
+       # Add 15 days to the expiration date
+       def renewSlice(self, day = 15):
+               print self.slice_name
+               expiration = self.plc_api.GetSlices(Auth.auth, self.slice_name, ['expires'])[0]['expires']
+               print expiration
+               newExpiration = expiration + (3600*24*day)
+               self.plc_api.UpdateSlice(Auth.auth, self.slice_name, {'expires': newExpiration})
+               expiration = self.plc_api.GetSlices(Auth.auth, self.slice_name, ['expires'])[0]['expires']
+               print expiration
+
+       # Generate a ssh key pair
+       def generateKeyPair(self,pref = "", bit = 1024):
+               key = paramiko.RSAKey.generate(bit)
+               # Save the private key file
+               keyFilePriv = pref+"id_rsa.priv"
+               key.write_private_key_file(keyFilePriv)
+               # Save the public key file
+               keyFilePub = pref+"id_rsa.pub"
+               openedFile = open(keyFilePub, 'w')
+               openedFile.write("%s %s \n" % (key.get_name(), key.get_base64()))
+               return keyFilePriv, keyFilePub
+
+       # press any key to continue function
+       def anykey(self, prompt="Press enter to continue...", failChars=""):
+               char = raw_input(prompt)
+               return (char not in failChars)
+
+       def checkSSH(self, node):
+               countFailSSH = 9
+               ssh = paramiko.SSHClient()
+               ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+               connected = False
+               error = None
+               i = 0
+               while(connected == False):
+                       print "\n"+self.mainKeyPriv+" -> "+self.slice_name+"@"+node['hostname']
+                       try:
+                               ssh.connect(node['hostname'], username = self.slice_name, key_filename = self.mainKeyPriv)
+                               connected = True
+                       except paramiko.PasswordRequiredException, why:
+                               print "Password required exception"
+                               print "Error: ", why
+
+                       except paramiko.SSHException, why:
+                               print "An SSH exception occured"
+                               print "Error: ", why
+
+                       except socket.error, why:
+                               print "A soccket error occured"
+                               print why
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               print 'FailingNode node_id -> '+str(failingNode['node_id'])
+                               raise FailToConnect(failingNode['node_id'], failingNode['hostname'])
+
+                       except Exception, why:
+                               print "An error occured for host "+str(node['hostname'])+" on slice "+str(self.slice_name)
+                               print type(why)
+                               print why
+                               sys.exit(2)
+                               if str(why)!=error:
+                                       print why
+                                       error=str(why)
+
+                       if i > countFailSSH and connected==False:
+                               print error
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               raise Exception(failingNode['hostname'])
+                       try:
+                               if connected == False:
+                                       print "Now waiting 5 minutes for an update of the node"
+                                       time.sleep(300)
+                       except KeyboardInterrupt, why:
+                               print "You interrupt the wait"
+                       i += 1
+               print "I make",i,"iteration before getting connection"
+               copied = False
+               i=0
+               while(copied == False):
+                       try:
+                               SCPClient(ssh.get_transport()).put('configService/fedora.repo')
+                               SCPClient(ssh.get_transport()).put('configService/fedora-updates.repo')
+                               SCPClient(ssh.get_transport()).put('configService/fedora-updates-testing.repo')
+                               self.execute("sudo -S mv *.repo /etc/yum.repos.d/", ssh)
+                               self.execute("sudo -S chown root:root /etc/yum.repos.d/*.repo", ssh)
+                               copied = True
+                       except Exception, why:
+                               print "An error occured while configuring yum"
+                               print "Error: ",why
+                               if i > 4 and copied == False:
+                                       failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                                       raise Exception(failingNode['hostname'])
+                       if copied == False:
+                               time.sleep(60)
+                       i+=1
+
+               return ssh
+
+
+       # Install an alternate ssh server
+       def installSSH(self, userKeyFile, node):
+               ssh = self.checkSSH(node)
+               returnCode = -1
+               i = 0
+               while(returnCode != 0):
+                       if i > 3:
+                               failingNode = self.plc_api.GetNodes(Auth.auth, node['id'])[0]
+                               raise Exception(failingNode['hostname'])
+                       returnCode = self.execute(yumOpt+"install openssh-server", ssh, display= True)
+                       print "Return Code is ->", returnCode
+                       time.sleep(5)
+                       i += 1
+               self.execute("mkdir .ssh", ssh, display= True)
+               if node['type'] == 'private':
+                       SCPClient(ssh.get_transport()).put(userKeyFile, ".ssh/id_rsa.pub")
+                       SCPClient(ssh.get_transport()).put("configService/sshd_config", "./")
+               elif node['type'] == 'public':
+                       SCPClient(ssh.get_transport()).put(userKeyFile, ".ssh/id_rsa.pub.tmp")
+                       SCPClient(ssh.get_transport()).put("configService/sshd_config", "./")
+                       self.execute("cat .ssh/id_rsa.pub.tmp >> .ssh/id_rsa.pub", ssh)
+               self.execute("sudo -S mv ./sshd_config /etc/ssh/", ssh)
+               self.execute("sudo -S sh -c \"echo \\\"Port 2222\\\" >> /etc/ssh/sshd_config\"", ssh)
+               port = 2222
+               returnCode = -1
+               while (returnCode != 0):
+                       time.sleep(2)
+                       returnCode = self.execute("sudo -S service sshd restart", ssh, display = True)
+                       if returnCode != 0:
+                               self.execute("sudo -S sed -i -e \"s/Port "+str(port)+"/Port "+str(port+1)+"/g\" /etc/ssh/sshd_config", ssh)
+                               port +=1
+               return port
+
+       # Execute a command on a remote machine
+       def execute(self, command, ssh, display= False, retour= False):
+               print "# "+command
+               stdin, stdout, stderr = ssh.exec_command(command)
+               stdin.close()
+               while not stdout.channel.exit_status_ready():
+                       time.sleep(2)
+       
+               err = stderr.read()
+               if err != None:
+                       splitted = err.splitlines()
+                       if len(splitted) > 0:
+                               print "Error in execution"
+                               for line in splitted:
+                                       print "> "+line
+               if display:
+                       for line in stdout.read().splitlines():
+                               print "> "+line
+               elif retour:
+                       return stdout.read()
+               return stdout.channel.recv_exit_status()
+
+       # Create the xml file corresponding to each environment
+       def createXmlFile(self, hostList, idEnv):
+               from xml.dom.minidom import parse
+               conf = parse(self.xmlFileConf)
+               link = parse(self.xmlFileLink)
+               sliceNames = link.getElementsByTagName('slice')
+               for value in sliceNames:
+                       value.firstChild.nodeValue = self.slice_name
+               sliceNames = conf.getElementsByTagName('slice_name')
+               for value in sliceNames:
+                       value.firstChild.nodeValue = self.slice_name
+               urlList = conf.getElementsByTagName('url')
+               if len(hostList) < len(urlList):
+                       print "hostlist -> "+str(len(hostList))
+                       print "urllist -> "+str(len(urlList))
+                       for host in hostList:
+                               print host
+               for i in range(len(urlList)):
+                       urlList[i].firstChild.nodeValue = hostList[i]
+               subnetIP, subnetMask = self.subnet.split('/')
+               subnetMask = int(subnetMask)
+               subnetIP = subnetIP.split('.')
+               ipList = conf.getElementsByTagName('ip')
+               for ipWithMask in ipList:
+                       ip, mask = str(ipWithMask.firstChild.nodeValue).split('/')
+                       ip = ip.split('.')
+                       mask = int(mask)
+                       newIP = ''
+                       if subnetMask > mask:
+                               sys.exit(2)
+                               # TODO define SubnetException
+                               pass
+                               #raise SubnetException()
+                       else:
+                               subnetRange = subnetMask/8
+                               for i in range(len(ip)):
+                                       if i < subnetRange:
+                                               newIP+=subnetIP[i]
+                                       else:
+                                               if ip[i] == 'N':
+                                                       newIP+=str(idEnv)
+                                               else:
+                                                       newIP+=ip[i]
+                                       if i < 3:
+                                               newIP+='.'
+                               newIP+='/'+str(mask)
+                       ipWithMask.firstChild.nodeValue = newIP
+               confFileName = 'requ'+str(idEnv)+'Conf.xml'
+               confFile = open(confFileName, 'w')
+               conf.writexml(confFile)
+               confFile.close()
+               self.envConfFile.append(confFileName)
+               linkFileName = 'requ'+str(idEnv)+'Link.xml'
+               linkFile = open(linkFileName, 'w')
+               link.writexml(linkFile)
+               linkFile.close()
+               self.envLinkFile.append(linkFileName)
+
+       def getNodeAvailable(self, site, nodeUsed = []):
+               nodes = self.plc_api.GetNodes(Auth.auth, site['node_ids'])
+               if site['peer_id'] == 1:
+                       myOpsCsv = self.myOpsPLCCsv
+               else:
+                       myOpsCsv = self.myOpsPLECsv
+               for node in nodes:
+                       for row in myOpsCsv:
+                               if node['hostname'] == row[0]:
+                                       node['myOpsStatus'] = row[1]
+                                       break
+               nodeAvailable = []
+               for node in nodes:
+                       if (node['myOpsStatus'] == 'BOOT' and node['boot_state'] == 'boot' and node['run_level'] == 'boot' and node['node_id'] not in nodeUsed):
+                               nodeAvailable.append(node)
+               return nodeAvailable
+
+       def getEnvironmentWithCountryConstraint(self, countryListPrivate, contryListCommon, sites, siteBanned):
+               print "Now looking for the environment using the country constraint"
+               sitesTmp = []
+               for site in sites:
+                       if len(site['address_ids']) == 1:
+                               sitesTmp.append(site)
+               sites = sitesTmp
+               sitesEnv = sitesCommon = []
+       
+               # Getting the private allowed address
+               try:
+                       privateAddrAuth = structToArray(self.plc_api.GetAddresses(Auth.auth, {'country': countryListPrivate}, ['address_id']), 'address_id')
+               except Exception, why:
+                       print why
+                       sys.exit(2)
+
+               privateAddresses = []
+               i = 0
+               for site in sites:
+                       if site['address_ids'][0] in privateAddrAuth and i < self.nbEnv:
+                               privateAddresses.append(site['address_ids'][0])
+                               i += 1
+               # Getting the private Node
+               print "Getting the private node matching with the requirement"
+               i = 0
+               for site in sites:
+                       if len(site['address_ids']) == 1 and site['address_ids'][0] in privateAddrAuth:
+                               nodeEnv = []
+                               if i < self.nbEnv:
+                                       j = 0
+                                       nodeSite = self.plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'node_id', 'boot_state', 'hostname'])
+                                       for node in nodeSite:
+                                               if i < self.nbEnv:
+                                                       if node['boot_state'] == 'boot':
+                                                               j+=1
+                                                               nodeEnv.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname']})
+                                                       if j>=nbNodeByEnv:
+                                                               i += 1
+                                                               nodeStructList.append(nodeEnv)
+                                                               sitesEnv.append(site)
+                                                               nodeIdList = structToArray(nodeEnv, 'id')
+                                                               nodeEnv = []
+                                                               j = 0
+       
+               print nodeIdList
+               print "List of site for environment :"
+               if len(nodeStructList) < self.nbEnv:
+                       print "Error we are not able to find enough environment"
+                       sys.exit(2)
+               for site in sitesEnv:
+                       print "\t"+str(site)
+       
+               # Getting the addresse wanted for common node
+               commonAddresses = []
+               for country in countryListCommon:
+                       address = self.plc_api.GetAddresses(Auth.auth, {'country': country}, ['address_id'])[0]['address_id']
+                       if address not in privateAddresses:
+                               commonAddresses.append(address)
+
+               # Getting the common node
+               commonNodes = []
+               for site in sites:
+                       if site['address_ids'][0] in commonAddresses:
+                               nodeSite = self.plc_api.GetNodes(Auth.auth, site['node_ids'], ['hostname', 'run_level', 'node_id', 'boot_state'])
+                               for node in nodeSite:
+                                       if node['boot_state'] == 'boot' and node['node_id'] not in nodeIdList:
+                                               commonNodes.append({'type': 'common','id': node['node_id'], 'hostname': node['hostname']})
+                                               nodeIdList.append(node['node_id'])
+                                               break
+       
+               for env in nodeStructList:
+                       for node in commonNodes:
+                               env.append(node)
+
+
+               print "Address list :"
+               #for addresse in commonAddresses:
+               #       print "\t"+str(addresse)
+               print privateAddresses
+               print commonAddresses
+
+               return nodeStructList
+
+       def getEnvironmentWithDistanceConstraint(self, constraintList, sitesList, siteBanned, nodeBanned):
+               print "Now looking for the environment using the distance constraint"
+               envList = []
+               nbPrivate = nbCommon = 0
+               nbInitPrivate = nbInitCommon = 0
+               # Counting the number of private and common node
+               # Also counting the number of node located at the same point
+               for node in constraintList:
+                       if node['type'] == 'private':
+                               nbPrivate += 1
+                               if node['max'] == 0 and node['min'] == 0:
+                                       nbInitPrivate += 1
+                       elif node['type'] == 'common' or node['type'] == 'public':
+                               nbCommon += 1
+                               if node['max'] == 0 and node['min'] == 0:
+                                       nbInitCommon += 1
+       
+               print "Common "+str(nbCommon)+" "+str(nbInitCommon), " Private "+str(nbPrivate)+" "+str(nbInitPrivate)
+               nbReservedEnvironment = 0
+               siteUsed = []
+               nodePrivate = []
+               nodeShared = []
+               while nbReservedEnvironment < self.nbEnv:
+                       tmpListEnv = []
+                       maxNode = []
+                       for site in sitesList:
+                               if site['site_id'] not in siteUsed and site['site_id'] not in siteBanned:
+                                       try:
+                                               nodeAvailable = self.getNodeAvailable(site, nodeBanned)
+                                               if len(nodeAvailable) > len(maxNode):
+                                                       maxNode = nodeAvailable
+                                                       siteInit = site
+                                       except Exception, why:
+                                               print 'Couldn\'t get the node available'
+                                               print site['name']
+                                               print why
+                                               sys.exit(2)
+                       siteUsed.append(siteInit['site_id'])
+                       newEnv = []
+                       print "Site used -> "+str(siteUsed)
+                       print siteInit['name']
+                       for i in range(len(maxNode)-nbInitCommon):
+                               node = maxNode[i]
+                               if nbReservedEnvironment < self.nbEnv:
+                                       newEnv.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname'], 'distance': 0, 'latitude': siteInit['latitude'], 'longitude': siteInit['longitude']})
+                                       nodePrivate.append(node['node_id'])
+                                       if len(newEnv) == nbInitPrivate:
+                                               tmpListEnv.append(newEnv)
+                                               newEnv = []
+                                               nbReservedEnvironment += 1
+                               else:
+                                       break
+                       commonNode = []
+                       for i in range(nbInitPrivate,len(constraintList)):
+                               nodeAdded = False
+                               print constraintList[i]
+                               if constraintList[i]['type'] in ['common', 'public']:
+                                       for site in sitesList:
+                                               if site['site_id'] not in siteBanned:
+                                                       initPoint = geopy.Point(siteInit['latitude'], siteInit['longitude'])
+                                                       distPoint = geopy.Point(site['latitude'], site['longitude'])
+                                                       distance = geopy.distance.distance(initPoint, distPoint).km
+                                                       if distance >= constraintList[i]['min'] and distance <= constraintList[i]['max']:
+                                                               nodeAvailable = self.getNodeAvailable(site, nodePrivate+nodeBanned)
+                                                               if len(nodeAvailable) > 0:
+                                                                       print distance
+                                                                       print site['name']
+                                                                       siteUsed.append(site['site_id'])
+                                                                       node = nodeAvailable[0]
+                                                                       nodeShared.append(node['node_id'])
+                                                                       commonNode.append({'type': constraintList[i]['type'], 'id': node['node_id'], 'hostname': node['hostname'], 'distance': int(distance), 'latitude': site['latitude'], 'longitude': site['longitude']})
+                                                                       nodeAdded = True
+                                                                       break
+                                       if not(nodeAdded) and constraintList[i]['type'] in ['common', 'public']:
+                                               print 'Error no node added for constraint -> '+str(constraintList[i])
+                                               raise NodeConstraintError(constraintList[i], envList)
+                               elif constraintList[i]['type'] == 'private':
+                                       nodeToAdd = []
+                                       for env in tmpListEnv:
+                                               if len(nodeToAdd) == 0:
+                                                       for site in sitesList:
+                                                               if site['site_id'] not in siteBanned:
+                                                                       initPoint = geopy.Point(siteInit['latitude'], siteInit['longitude'])
+                                                                       distPoint = geopy.Point(site['latitude'], site['longitude'])
+                                                                       distance = geopy.distance.distance(initPoint, distPoint).km
+                                                                       if distance >= constraintList[i]['min'] and distance <= constraintList[i]['max']:
+                                                                               nodeAvailable = self.getNodeAvailable(site, nodePrivate+nodeShared+nodeBanned)
+                                                                               if len(nodeAvailable) > 0:
+                                                                                       nodeToAdd = nodeAvailable
+                                               node = nodeToAdd.pop(0)
+                                               env.append({'type': 'private', 'id': node['node_id'], 'hostname': node['hostname'], 'distance': int(distance), 'latitude': site['latitude'], 'longitude': site['longitude']})
+
+                       for env in tmpListEnv:
+                               for node in commonNode:
+                                       env.append(node)
+                                       
+                       envList.extend(tmpListEnv)
+       
+               return envList
+
+       # Reading the raw xml file to get information
+       # Return an array of array of struct containing the information concerning each environment requested
+       def readRawXml(self, siteBanned, nodeBanned):
+               print "Banned Site ->",siteBanned
+               print "Node banned ->",nodeBanned
+               from xml.dom.minidom import parse
+               conf = parse(self.xmlFileConf)
+               nbNodeByEnv = nbCommonNode = 0
+               nodeStructList = []
+               nodeIdList = []
+               countryListCommon = []
+               countryListPrivate = []
+               constraintList = []
+               for host_i in conf.getElementsByTagName('host'):
+                       hostType = ""
+                       try:
+                               hostType = host_i.getElementsByTagName('type')[0].firstChild.nodeValue
+                       except Exception, why:
+                               print why
+                       if hostType == 'private' or hostType == "":
+                               nbNodeByEnv += 1
+                       elif hostType == 'common' or hostType == 'public':
+                               nbCommonNode += 1
+                       else:
+                               print "Error the host type "+hostType+" doesn't exist"
+                               sys.exit(2)
+                       if self.country:
+                               try:
+                                       hostCountry = host_i.getElementsByTagName('country')[0].firstChild.nodeValue
+                                       if hostType == 'common':
+                                               countryListCommon.append(hostCountry)
+                                       elif hostType == 'private':
+                                               countryListPrivate.append(hostCountry)
+                               except Exception, why:
+                                       print "An error occured"
+                                       print why
+                                       sys.exit(2)
+                       else:
+                               try:
+                                       distance = host_i.getElementsByTagName('distances')[0]
+                                       distMin = int(distance.getElementsByTagName('min')[0].firstChild.nodeValue)
+                                       distMax = int(distance.getElementsByTagName('max')[0].firstChild.nodeValue)
+                                       constraintList.append({'type': hostType, 'min': distMin, 'max': distMax})
+                               except Exception, why:
+                                       print "An error occured"
+                                       print why
+                                       sys.exit(2)
+
+
+               print "Getting all the site available"
+               sites = self.plc_api.GetSites(Auth.auth, ['*'])
+       
+               if self.country:
+                       nodeStructList = self.getEnvironmentWithCountryConstraint(countryListPrivate, contryListCommon, sites, siteBanned, nodeBanned)
+               else:
+                       try:
+                               nodeStructList = self.getEnvironmentWithDistanceConstraint(constraintList, sites, siteBanned, nodeBanned)
+                       except NodeConstraintError as error:
+                               self.nbEnv = len(error.getEnvList())
+                               nodeStructList = error.getEnvList()
+       
+
+               # Creating a file containing all the information about the slice created
+               origStdout = sys.stdout
+               sys.stdout = open('Test', 'w')
+               i = 0
+               print "Slice name : "+self.slice_name
+               for env in nodeStructList:
+                       i+=1
+                       print "\tEnv %i"%i
+                       for node in env:
+                               strNode = '\t'
+                               for key in node.keys():
+                                       strNode += "\t"+str(key)+" : "+str(node[key])
+                               print strNode
+               sys.stdout.close()
+               sys.stdout = origStdout
+       
+               return(nodeStructList)
+
+       def structToArray(self, requestAnswer, key):
+               #return  [i[key] for i in requestAnswer]
+               array = []
+               for i in requestAnswer:
+                       array.append(i[key])
+               return array
+
+       def addSliceTag(self, sliceId, tagName, tagValue):
+               try:
+                       returnCode = self.plc_api.AddSliceTag(Auth.auth, sliceId, tagName, tagValue)
+                       if returnCode == 0:
+                               print "An error Occured while adding the tag %s -> %s"% tagName, tagValue
+               except xmlrpclib.Fault as fault:
+                       if fault.faultCode != 102:
+                               print "An error occured"
+                               print fault
+                               sys.exit(2)
+
+       def getSlice(self):
+               try:
+                       sliceId = self.plc_api.GetSlices(Auth.auth, self.slice_name)[0]['slice_id']
+               except xmlrpclib.Fault, why:
+                       print "An error while getting the slice already existing"
+                       print why
+                       sys.exit(2)
+               return sliceId
+       
+       def createSlice(self):
+               sliceId = 0
+               print "Creating a new slice called : "+self.slice_name
+               try:
+                       sliceId = self.plc_api.AddSlice(Auth.auth, {'description': self.sliceDescription, 'name':self.slice_name, 'url': self.sliceUrl})
+               except xmlrpclib.Fault, why:
+                       print "An error occured while creating the slice "+self.slice_name
+                       print why
+               except Exception, why:
+                       print "An error occured while createing the slice "+self.slice_name
+                       print type(why)
+                       print why
+               return sliceId
+       
+       def setSlice(self):
+               sliceId = self.createSlice()
+               if (sliceId == 0):
+                       print 'Slice exist'
+                       sliceId = self.getSlice()
+               print "Adding user to the slice"
+               returnCode = self.plc_api.AddPersonToSlice(Auth.auth, Auth.auth['Username'], sliceId)
+               
+               if type(self.nbEnv) != int:
+                       print "You must enter a number"
+                       sys.exit(2)
+
+               print "Generating and adding the main ssh key"
+               print os.getcwd()
+               if self.mainKeyPriv == None:
+                       self.mainKeyPriv, self.mainKeyPub = self.generateKeyPair(pref = "./key/"+self.slice_name+"main", bit = 1024)
+               f = open(self.mainKeyPub)
+               keyString = f.read()
+               try:
+                       keyId = self.plc_api.AddPersonKey(Auth.auth, Auth.auth['Username'], {'key_type': 'ssh', 'key': keyString})
+                       if returnCode == 0:
+                               print "An error occured while adding the key to the user"
+                               sys.exit(2)
+               except xmlrpclib.Fault as fault:
+                       print fault
+                       sys.exit(2)
+
+               success = False
+               #TODO Ban failing site, waiting for fix
+               #FU Berlin || Reykjavik University || FOKUS || University of Goettingen
+               siteBanned = [7341, 7336, 443, 7059]
+               # TODO banned new lip6 node + FUNDP Site + DSCHINI
+               nodeBanned = [15953, 15954, 15955, 15956, 14810]
+               while success == False:
+                       nodeList = self.readRawXml(siteBanned[:], nodeBanned)
+               
+                       print "Adding node to the slice"
+                       i = 0
+                       for env in nodeList:
+                               for node in env:
+                                       failToAdd = True
+                                       j = 0
+                                       while failToAdd:
+                                               try:
+                                                       if node['type'] == 'private' or ((node['type'] == 'common' or node['type'] == 'public') and i == 0):
+                                                               returnCode = self.plc_api.AddSliceToNodes(Auth.auth, sliceId, [node['id']])
+                                                       if returnCode != 1:
+                                                               print "An error occured while adding a node to the slice"
+                                                               time.sleep(30)
+                                                       else:
+                                                               failToAdd = False
+                                               except xmlrpclib.Fault as fault:
+                                                       print fault
+                                                       time.sleep(30)
+                                               if j > 2 and failToAdd:
+                                                       raise FailToConnect(node['id'], node['hostname'])
+                                               j+=1
+                               i = 1
+       
+
+
+                       i=0
+                       # Set additional ssh server using generated key file and port 2222
+                       try:
+                               for envList in nodeList:
+                                       envKeyPriv, envKeyPub = self.generateKeyPair(pref = "./key/"+self.slice_name+"group"+str(i+1), bit = 1024)
+                                       self.envKeyPriv.append(envKeyPriv)
+                                       self.envKeyPub.append(envKeyPub)
+                                       for node in envList:
+                                               print node['hostname']
+                                               if node['type'] != 'common':
+                                                       self.installSSH(self.envKeyPub[i], node)
+                                                       pass
+                                               else:
+                                                       self.checkSSH(node)
+                                                       pass
+                                       i+=1
+                               success = True
+                       except FailToConnect as error:
+                               print "Not able to get the ssh connection for node", error.getNodeUrl()
+                               print 'Error node id -> '+str(error.getNodeId())
+                               print 'Before adding failing node -> '+str(nodeBanned)
+                               nodeBanned.append(error.getNodeId())
+                               print 'After adding failing node -> '+str(nodeBanned)
+                       except Exception, why:
+                               print "Not able to get the ssh connection", why
+
+
+
+               print "Adding requested tag to the slice"
+               # Adding the tag needed :
+               #       - TAG -> VALUE : DEF
+               #       - vsys -> vif_up 
+               #       - vsys -> vif_down 
+               #       - vsys -> fd_tuntap : Allow to create tun/tap interface
+               #       - vsys -> vroute : Allow to define new route
+               #       - vsys_vnet -> SUBNET : Define the subnet allowed for tun/tap device
+
+               self.addSliceTag(sliceId, 'vsys', 'vif_up')
+               self.addSliceTag(sliceId, 'vsys', 'vif_down')
+               self.addSliceTag(sliceId, 'vsys', 'fd_tuntap')
+               self.addSliceTag(sliceId, 'vsys', 'vroute')
+               self.addSliceTag(sliceId, 'vsys_vnet', self.subnet)
+
+               # Configuring the node using the openvswitch.py script
+               # Command used to execute the script
+               i = 0
+               for env in nodeList:
+                       i+=1
+                       print "Env ",i
+                       hostnameList = self.structToArray(env, 'hostname')
+                       self.createXmlFile(hostnameList, i)
+                       try:
+                               x = None
+                               x = TransformXml(prefix = 'requ'+str(i), keyFile = self.mainKeyPriv)
+                               x.setSliceConf()
+                               x.setLinks()
+                               x.setRoutes()
+                               x.setServices()
+                               self.envList.append(x.getSliceList())
+                       except Exception, why:
+                               print "An error occured while configuring the environment number "+str(i-1)
+                               print Exception
+                               print ''
+                               print why
+                               sys.exit(2)
+
+       
+if __name__ == "__main__":
+       parser = argparse.ArgumentParser()
+       parser.add_argument("-s", "--subnet", help="The subnet reserved for the slice, it must include at least all the ip address used by the tp. The syntax is SUBNET/PREFIX (e.g 10.1.0.0/16 which is the default value)", default='10.1.0.0/16')
+       parser.add_argument("-n", "--name", help="Name of the slice", default='tp')
+       parser.add_argument("-nb", "--number", help="Number of the environment you want", type=int, default=1)
+       groupInput = parser.add_mutually_exclusive_group()
+       groupInput.add_argument('-f', '--file', help="The xml file that will be used, Link xml file then Configuration xml file", type=str, default='', nargs=2)
+       groupInput.add_argument("-p", "--prefix", help="A prefix used to find the xml file, the script will look at prefix+Conf.xml and prefix+Link.xml", type=str, dest='prefix')
+
+       try:
+               args = parser.parse_args()
+       except Exception, why:
+               print "An error occured while parsing the argument"
+               parser.print_help()
+               print why
+               sys.exit(2)
+       
+       if args.file != '':
+               x = TransformRawXml(confFile = args.file[0], linkFile = args.file[1], subnet = args.subnet, sliceName = args.name, nbEnv = args.number)
+               x.setSlice()
+       else:
+               x = TransformRawXml(prefix = args.prefix, subnet = args.subnet, sliceName = args.name, nbEnv = args.number)
+               x.setSlice()
+
diff --git a/forge/script/scp.py b/forge/script/scp.py
new file mode 100644 (file)
index 0000000..02c7cc1
--- /dev/null
@@ -0,0 +1,395 @@
+# scp.py
+# Copyright (C) 2008 James Bardin <jbardin@bu.edu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+"""
+Utilities for sending files over ssh using the scp1 protocol.
+"""
+
+import os
+from socket import timeout as SocketTimeout
+
+class SCPClient(object):
+    """
+    An scp1 implementation, compatible with openssh scp.
+    Raises SCPException for all transport related errors. Local filesystem
+    and OS errors pass through. 
+
+    Main public methods are .put and .get 
+    The get method is controlled by the remote scp instance, and behaves 
+    accordingly. This means that symlinks are resolved, and the transfer is
+    halted after too many levels of symlinks are detected.
+    The put method uses os.walk for recursion, and sends files accordingly.
+    Since scp doesn't support symlinks, we send file symlinks as the file
+    (matching scp behaviour), but we make no attempt at symlinked directories.
+
+    Convenience methods:
+        put_r:  put with recursion
+        put_p:  put preserving times
+        put_rp: put with recursion, preserving times
+        get_r:  get with recursion
+        get_p:  get preserving times
+        get_rp: get with recursion, preserving times
+    """
+    def __init__(self, transport, buff_size = 16384, socket_timeout = 5.0,
+                 callback = None):
+        """
+        Create an scp1 client.
+
+        @param transport: an existing paramiko L{Transport}
+        @type transport: L{Transport}
+        @param buff_size: size of the scp send buffer.
+        @type buff_size: int
+        @param socket_timeout: channel socket timeout in seconds
+        @type socket_timeout: float
+        @param callback: callback function for transfer status
+        @type callback: func
+        """
+        self.transport = transport
+        self.buff_size = buff_size
+        self.socket_timeout = socket_timeout
+        self.channel = None
+        self.preserve_times = False
+        self.callback = callback
+        self._recv_dir = ''
+        self._utime = None
+        self._dirtimes = {}
+
+    def put(self, files, remote_path = '.', 
+            recursive = False, preserve_times = False):
+        """
+        Transfer files to remote host.
+
+        @param files: A single path, or a list of paths to be transfered.
+            recursive must be True to transfer directories.
+        @type files: string OR list of strings
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: str
+        @param recursive: transfer files and directories recursively
+        @type recursive: bool
+        @param preserve_times: preserve mtime and atime of transfered files
+            and directories.
+        @type preserve_times: bool
+        """
+        self.preserve_times = preserve_times
+        self.channel = self.transport.open_session()
+        self.channel.settimeout(self.socket_timeout)
+        scp_command = ('scp -t %s\n', 'scp -r -t %s\n')[recursive]
+        self.channel.exec_command(scp_command % remote_path)
+        self._recv_confirm()
+       
+        if not isinstance(files, (list, tuple)):
+            files = [files]
+        
+        if recursive:
+            self._send_recursive(files)
+        else:
+            self._send_files(files)
+        
+        if self.channel:
+            self.channel.close()
+    
+    def put_r(self, files, remote_path = '.'):
+        """
+        Convenience function for a recursive put
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, recursive = True)
+
+    def put_p(self, files, remote_path = '.'):
+        """
+        Convenience function to put preserving times.
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, preserve_times = True)
+   
+    def put_rp(self, files, remote_path = '.'):
+        """
+        Convenience function for a recursive put, preserving times.
+
+        @param files: A single path, or a list of paths to be transfered.
+        @type files: str, list
+        @param remote_path: path in which to receive the files on the remote
+            host. defaults to '.'
+        @type remote_path: bool
+        """
+        self.put(files, remote_path, recursive = True, preserve_times = True)
+
+    def get(self, remote_path, local_path = '',
+            recursive = False, preserve_times = False):
+        """
+        Transfer files from remote host to localhost
+
+        @param remote_path: path to retreive from remote host. since this is
+            evaluated by scp on the remote host, shell wildcards and 
+            environment variables may be used.
+        @type remote_path: str
+        @param local_path: path in which to receive files locally
+        @type local_path: str
+        @param recursive: transfer files and directories recursively
+        @type recursive: bool
+        @param preserve_times: preserve mtime and atime of transfered files
+            and directories.
+        @type preserve_times: bool
+        """
+        self._recv_dir = local_path or os.getcwd() 
+        rcsv = ('', ' -r')[recursive]
+        prsv = ('', ' -p')[preserve_times]
+        self.channel = self.transport.open_session()
+        self.channel.settimeout(self.socket_timeout)
+        self.channel.exec_command('scp%s%s -f %s' % (rcsv, prsv, remote_path))
+        self._recv_all()
+        
+        if self.channel:
+            self.channel.close()
+
+    def get_r(self, remote_path, local_path = '.'):
+        """
+        Convenience function for a recursive get
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, recursive = True)
+
+    def get_p(self, remote_path, local_path = '.'):
+        """
+        Convenience function for get, preserving times.
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, preserve_times = True)
+
+    def get_rp(self, remote_path, local_path = '.'):
+        """
+        Convenience function for a recursive get, preserving times.
+
+        @param remote_path: path to retrieve from server
+        @type remote_path: str
+        @param local_path: path in which to recieve files. default cwd
+        @type local_path: str
+        """
+        self.get(remote_path, local_path, recursive = True, preserve_times = True)
+
+    def _read_stats(self, name):
+        """return just the file stats needed for scp"""
+        stats = os.stat(name)
+        mode = oct(stats.st_mode)[-4:]
+        size = stats.st_size
+        atime = int(stats.st_atime)
+        mtime = int(stats.st_mtime)
+        return (mode, size, mtime, atime)
+
+    def _send_files(self, files): 
+        for name in files:
+            basename = os.path.basename(name)
+            (mode, size, mtime, atime) = self._read_stats(name)
+            if self.preserve_times:
+                self._send_time(mtime, atime)
+            file_hdl = file(name, 'rb')
+            self.channel.sendall('C%s %d %s\n' % (mode, size, basename))
+            self._recv_confirm()
+            file_pos = 0
+            buff_size = self.buff_size
+            chan = self.channel
+            while file_pos < size:
+                chan.sendall(file_hdl.read(buff_size))
+                file_pos = file_hdl.tell()
+                if self.callback:
+                    self.callback(file_pos, size)
+            chan.sendall('\x00')
+            file_hdl.close()
+
+    def _send_recursive(self, files):
+        for base in files:
+            lastdir = base
+            for root, dirs, fls in os.walk(base):
+                # pop back out to the next dir in the walk
+                while lastdir != os.path.commonprefix([lastdir, root]):
+                    self._send_popd()
+                    lastdir = os.path.split(lastdir)[0]
+                self._send_pushd(root)
+                lastdir = root
+                self._send_files([os.path.join(root, f) for f in fls])
+        
+    def _send_pushd(self, directory):
+        (mode, size, mtime, atime) = self._read_stats(directory)
+        basename = os.path.basename(directory)
+        if self.preserve_times:
+            self._send_time(mtime, atime)
+        self.channel.sendall('D%s 0 %s\n' % (mode, basename))
+        self._recv_confirm()
+
+    def _send_popd(self):
+        self.channel.sendall('E\n')
+        self._recv_confirm()
+
+    def _send_time(self, mtime, atime):
+        self.channel.sendall('T%d 0 %d 0\n' % (mtime, atime))
+        self._recv_confirm()
+
+    def _recv_confirm(self):
+        # read scp response
+        msg = ''
+        try:
+            msg = self.channel.recv(512)
+        except SocketTimeout:
+            raise SCPException('Timout waiting for scp response')
+        if msg and msg[0] == '\x00':
+            return
+        elif msg and msg[0] == '\x01':
+            raise SCPException(msg[1:])
+        elif self.channel.recv_stderr_ready():
+            msg = self.channel.recv_stderr(512)
+            raise SCPException(msg)
+        elif not msg:
+            raise SCPException('No response from server')
+        else:
+            raise SCPException('Invalid response from server: ' + msg)
+    
+    def _recv_all(self):
+        # loop over scp commands, and recive as necessary
+        command = {'C': self._recv_file,
+                   'T': self._set_time,
+                   'D': self._recv_pushd,
+                   'E': self._recv_popd}
+        while not self.channel.closed:
+            # wait for command as long as we're open
+            self.channel.sendall('\x00')
+            msg = self.channel.recv(1024)
+            if not msg: # chan closed while recving
+                break
+            code = msg[0]
+            try:
+                command[code](msg[1:])
+            except KeyError:
+                raise SCPException(repr(msg))
+        # directory times can't be set until we're done writing files
+        self._set_dirtimes()
+    
+    def _set_time(self, cmd):
+        try:
+            times = cmd.split()
+            mtime = int(times[0])
+            atime = int(times[2]) or mtime
+        except:
+            self.channel.send('\x01')
+            raise SCPException('Bad time format')
+        # save for later
+        self._utime = (mtime, atime)
+
+    def _recv_file(self, cmd):
+        chan = self.channel
+        parts = cmd.split()
+        try:
+            mode = int(parts[0], 8)
+            size = int(parts[1])
+            path = os.path.join(self._recv_dir, parts[2])
+        except:
+            chan.send('\x01')
+            chan.close()
+            raise SCPException('Bad file format')
+        
+        try:
+            file_hdl = file(path, 'wb')
+        except IOError, e:
+            chan.send('\x01'+e.message)
+            chan.close()
+            raise
+
+        buff_size = self.buff_size
+        pos = 0
+        chan.send('\x00')
+        try:
+            while pos < size:
+                # we have to make sure we don't read the final byte
+                if size - pos <= buff_size:
+                    buff_size = size - pos
+                file_hdl.write(chan.recv(buff_size))
+                pos = file_hdl.tell()
+                if self.callback:
+                    self.callback(pos, size)
+            
+            msg = chan.recv(512)
+            if msg and msg[0] != '\x00':
+                raise SCPException(msg[1:])
+        except SocketTimeout:
+            chan.close()
+            raise SCPException('Error receiving, socket.timeout')
+
+        file_hdl.truncate()
+        try:
+            os.utime(path, self._utime)
+            self._utime = None
+            os.chmod(path, mode)
+            # should we notify the other end?
+        finally:
+            file_hdl.close()
+        # '\x00' confirmation sent in _recv_all
+
+    def _recv_pushd(self, cmd):
+        parts = cmd.split()
+        try:
+            mode = int(parts[0], 8)
+            path = os.path.join(self._recv_dir, parts[2])
+        except:
+            self.channel.send('\x01')
+            raise SCPException('Bad directory format')
+        try:
+            if not os.path.exists(path):
+                os.mkdir(path, mode)
+            elif os.path.isdir(path):
+                os.chmod(path, mode)
+            else:
+                raise SCPException('%s: Not a directory' % path)
+            self._dirtimes[path] = (self._utime)
+            self._utime = None
+            self._recv_dir = path
+        except (OSError, SCPException), e:
+            self.channel.send('\x01'+e.message)
+            raise
+
+    def _recv_popd(self, *cmd):
+        self._recv_dir = os.path.split(self._recv_dir)[0]
+        
+    def _set_dirtimes(self):
+        try:
+            for d in self._dirtimes:
+                os.utime(d, self._dirtimes[d])
+        finally:
+            self._dirtimes = {}
+
+
+class SCPException(Exception):
+    """SCP exception class"""
+    pass
diff --git a/forge/script/serviceScript.py b/forge/script/serviceScript.py
new file mode 100644 (file)
index 0000000..ad1afb1
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import paramiko
+from scp import SCPClient
+import time
+
+yumOpt = "sudo -S yum -y --nogpgcheck "
+
+# Functions used for the php module (you need to install an http server)
+def setPHP(ssh):
+       execute(yumOpt+" install php", ssh)
+       execute("sudo -S /sbin/service httpd restart", ssh)
+
+def removePHP(ssh):
+       execute(yumOpt+" remove php", ssh)
+
+# Functions used for the X redirection using ssh
+def setXRedirect(ssh):
+       # Installing X11 system and an alternate ssh server
+       execute(yumOpt+" install xorg-x11-xauth", ssh)
+       #time.sleep(10)
+
+def removeXRedirect(ssh):
+       # Remove X11 system and the alternate ssh server
+       execute(yumOpt+" remove xorg-x11-xauth", ssh)
+
+
+# Functions used for an http server
+def setHttpd(ssh, port, hostUrl):
+       port = int(port)
+       execute(yumOpt+" install -y httpd", ssh)
+       SCPClient(ssh.get_transport()).put("./configService/httpd.conf", "~")
+       SCPClient(ssh.get_transport()).put("./configService/index.html", "~")
+       execute("sudo -S mv ~/index.html /var/www/html/", ssh)
+       execute("sudo -S echo \"<html>You are on "+str(hostUrl)+"</html>\" >> /var/www/html/index.html", ssh)
+       execute("sudo -S dd if=/dev/zero of=/var/www/html/file1Mo bs=1M count=1", ssh)
+       execute("sudo -S chmod a+r /var/www/html/file1Mo", ssh)
+       execute("sudo -S mv ~/httpd.conf /etc/httpd/conf/", ssh, display = True)
+       execute("sudo -S chown root:root /etc/httpd/conf/httpd.conf", ssh, display = True)
+       execute("sudo -S sed -i -e \"s/Listen \\*:80/Listen \\*:"+str(port)+"/g\" /etc/httpd/conf/httpd.conf", ssh)
+       returnCode = -1
+       while(returnCode != 0):
+               time.sleep(2)
+               returnCode = execute("sudo -S /sbin/service httpd restart", ssh, display = True)
+               print returnCode
+               if returnCode != 0:
+                       execute("sudo -S sed -i -e \"s/Listen \\*:"+str(port)+"/Listen \\*:"+str(port+1)+"/g\" /etc/httpd/conf/httpd.conf", ssh)
+                       port += 1
+       return port
+
+def removeHttpd(ssh):
+       #Remove the httpd service
+       execute(yumOpt+" remove httpd", ssh)
+       execute("sudo -S rm -rf /etc/httpd/*", ssh)
+
+
+# Functions used for wireshark traffic analyzer (you have to install X redirection)
+def setWireshark(ssh):
+       # Install wireshark
+       execute(yumOpt+" install wireshark wireshark-gnome", ssh)
+       execute(yumOpt+" install wireshark xorg-x11-fonts-Type1", ssh)
+       
+def removeWireshark(ssh):
+       # Remove wireshark
+       execute(yumOpt+" remove wireshark wireshark-gnome", ssh)
+       execute(yumOpt+" remove wireshark xorg-x11-fonts-Type1", ssh)
+
+# Functions used for the browser firefox (you have to install X redirection)
+def setFirefox(ssh):
+       # Install firefox
+       execute(yumOpt+" install firefox", ssh)
+       execute("sudo -S sh -c \"dbus-uuidgen > /var/lib/dbus/machine-id\"", ssh)
+
+def removeFirefox(ssh):
+       # Remove firefox
+       execute(yumOpt+" remove firefox", ssh)
+
+
+# Function used to execute a command on a remote host using ssh
+def execute(command, ssh, display=False, retour=False):
+       print "# "+command
+       stdin, stdout, stderr = ssh.exec_command(command)
+       stdin.close()
+       # Wait for the end of the command
+       while not stdout.channel.exit_status_ready():
+               time.sleep(2)
+       err = stderr.read()
+       if err != None:
+               splitted = err.splitlines()
+               if len(splitted) > 0:
+                       print "\tError in execution"
+                       for line in splitted:
+                               print "\t > " + line    
+       if display:
+               for line in stdout.read().splitlines():
+                       print " > " + line
+       elif retour:
+               return stdout.read()
+       return stdout.channel.recv_exit_status()
diff --git a/forge/script/xmlFile/Conf.xml b/forge/script/xmlFile/Conf.xml
new file mode 100644 (file)
index 0000000..2708049
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>Host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>Host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/Link.xml b/forge/script/xmlFile/Link.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/MiMConf.xml b/forge/script/xmlFile/MiMConf.xml
new file mode 100644 (file)
index 0000000..f24df2d
--- /dev/null
@@ -0,0 +1,47 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>a
+                       <routes>
+                               <route>
+                                       <subnet>10.1.2.0/24</subnet>
+                                       <gateway>10.1.1.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.2.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>3</id>
+                       <url>ple4.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.2.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.1.0/24</subnet>
+                                       <gateway>10.1.2.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/MiMLink.xml b/forge/script/xmlFile/MiMLink.xml
new file mode 100644 (file)
index 0000000..f0abbe8
--- /dev/null
@@ -0,0 +1,26 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/TP1Conf.xml b/forge/script/xmlFile/TP1Conf.xml
new file mode 100644 (file)
index 0000000..bde8e11
--- /dev/null
@@ -0,0 +1,29 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11:2222</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/TP1Link.xml b/forge/script/xmlFile/TP1Link.xml
new file mode 100644 (file)
index 0000000..721c980
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFile/TestConf.xml b/forge/script/xmlFile/TestConf.xml
new file mode 100644 (file)
index 0000000..341e288
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple4.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.3.3/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple3.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.3.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFile/TestLink.xml b/forge/script/xmlFile/TestLink.xml
new file mode 100644 (file)
index 0000000..3833556
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/AResT1v62_fr.pdf b/forge/script/xmlFileRaw/AResT1v62_fr.pdf
new file mode 100644 (file)
index 0000000..9929df8
Binary files /dev/null and b/forge/script/xmlFileRaw/AResT1v62_fr.pdf differ
diff --git a/forge/script/xmlFileRaw/AResT5v62_fr.pdf b/forge/script/xmlFileRaw/AResT5v62_fr.pdf
new file mode 100644 (file)
index 0000000..e910d8c
Binary files /dev/null and b/forge/script/xmlFileRaw/AResT5v62_fr.pdf differ
diff --git a/forge/script/xmlFileRaw/MiMConf.xml b/forge/script/xmlFileRaw/MiMConf.xml
new file mode 100644 (file)
index 0000000..8c5f867
--- /dev/null
@@ -0,0 +1,47 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.2.0/24</subnet>
+                                       <gateway>10.1.1.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.1/24</ip>
+                       </interface>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.2.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.2.2/24</ip>
+                       </interface>
+                       <routes>
+                               <route>
+                                       <subnet>10.1.1.0/24</subnet>
+                                       <gateway>10.1.2.1</gateway>
+                                       <device>tap1</device>
+                               </route>
+                       </routes>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/MiMLink.xml b/forge/script/xmlFileRaw/MiMLink.xml
new file mode 100644 (file)
index 0000000..1c2050a
--- /dev/null
@@ -0,0 +1,26 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1Conf.xml b/forge/script/xmlFileRaw/TP1Conf.xml
new file mode 100644 (file)
index 0000000..ef64312
--- /dev/null
@@ -0,0 +1,41 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8085</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1Link.xml b/forge/script/xmlFileRaw/TP1Link.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1NoServConf.xml b/forge/script/xmlFileRaw/TP1NoServConf.xml
new file mode 100644 (file)
index 0000000..101a67c
--- /dev/null
@@ -0,0 +1,37 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1NoServLink.xml b/forge/script/xmlFileRaw/TP1NoServLink.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP1PrivConf.xml b/forge/script/xmlFileRaw/TP1PrivConf.xml
new file mode 100644 (file)
index 0000000..eb5316d
--- /dev/null
@@ -0,0 +1,41 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.8.100/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8085</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP1PrivLink.xml b/forge/script/xmlFileRaw/TP1PrivLink.xml
new file mode 100644 (file)
index 0000000..f1d6512
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP5Conf.xml b/forge/script/xmlFileRaw/TP5Conf.xml
new file mode 100644 (file)
index 0000000..ec9ef01
--- /dev/null
@@ -0,0 +1,75 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfForge.xml b/forge/script/xmlFileRaw/TP5ConfForge.xml
new file mode 100644 (file)
index 0000000..36799a0
--- /dev/null
@@ -0,0 +1,58 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <services>
+                               <service>httpd:8080</service>
+                               <service>php</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml b/forge/script/xmlFileRaw/TP5ConfNoAustralia.xml
new file mode 100644 (file)
index 0000000..d926886
--- /dev/null
@@ -0,0 +1,75 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                               <service>x11</service>
+                               <service>firefox</service>
+                               <service>wireshark</service>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>1500</min>
+                               <max>90000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoLink.xml b/forge/script/xmlFileRaw/TP5ConfNoLink.xml
new file mode 100644 (file)
index 0000000..7e866e1
--- /dev/null
@@ -0,0 +1,64 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5ConfNoX.xml b/forge/script/xmlFileRaw/TP5ConfNoX.xml
new file mode 100644 (file)
index 0000000..49d32f8
--- /dev/null
@@ -0,0 +1,72 @@
+<conf>
+       <slice>
+               <slice_name>SliceName</slice_name>
+               <host>
+                       <type>private</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>1</id>
+                       <url>host1</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.N/24</ip>
+                       </interface>
+                       <services>
+                       </services>
+               </host>
+               <host>
+                       <type>public</type>
+                       <country>France</country>
+                       <distances>
+                               <min>0</min>
+                               <max>0</max>
+                       </distances>
+                       <id>2</id>
+                       <url>host2</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.102/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Italy</country>
+                       <distances>
+                               <min>1000</min>
+                               <max>1500</max>
+                       </distances>
+                       <id>3</id>
+                       <url>host3</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.100/24</ip>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+                       </interface>
+               </host>
+               <host>
+                       <type>common</type>
+                       <country>Spain</country>
+                       <distances>
+                               <min>10000</min>
+                               <max>30000</max>
+                       </distances>
+                       <id>4</id>
+                       <url>host4</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.1.101/24</ip>
+                       </interface>
+                       <services>
+                               <service>httpd:8080</service>
+                       </services>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TP5Link.xml b/forge/script/xmlFileRaw/TP5Link.xml
new file mode 100644 (file)
index 0000000..d907590
--- /dev/null
@@ -0,0 +1,50 @@
+<links>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>3</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>4</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+       <link>
+               <host1>
+                       <slice>SliceName</slice>
+                       <id>1</id>
+                       <bridge_name>tap1</bridge_name>
+               </host1>
+               <host2>
+                       <slice>SliceName</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/script/xmlFileRaw/TP5LinkNo.xml b/forge/script/xmlFileRaw/TP5LinkNo.xml
new file mode 100644 (file)
index 0000000..dbadb95
--- /dev/null
@@ -0,0 +1,2 @@
+<links>
+</links>
diff --git a/forge/script/xmlFileRaw/TestConf.xml b/forge/script/xmlFileRaw/TestConf.xml
new file mode 100644 (file)
index 0000000..a8e43f3
--- /dev/null
@@ -0,0 +1,21 @@
+<conf>
+       <slice>
+               <slice_name>upmc_tp</slice_name>
+               <host>
+                       <id>1</id>
+                       <url>ple2.ipv6.lip6.fr</url>
+                       <interface>
+                               <bridge_name>tap2</bridge_name>
+                               <ip>10.1.3.1/24</ip>
+                       </interface>
+               </host>
+               <host>
+                       <id>2</id>
+                       <url>ple1.cesnet.cz</url>
+                       <interface>
+                               <bridge_name>tap1</bridge_name>
+                               <ip>10.1.3.2/24</ip>
+                       </interface>
+               </host>
+       </slice>
+</conf>
diff --git a/forge/script/xmlFileRaw/TestLink.xml b/forge/script/xmlFileRaw/TestLink.xml
new file mode 100644 (file)
index 0000000..3833556
--- /dev/null
@@ -0,0 +1,14 @@
+<links>
+       <link>
+               <host1>
+                       <slice>upmc_tp</slice>
+                       <id>1</id>
+                       <bridge_name>tap2</bridge_name>
+               </host1>
+               <host2>
+                       <slice>upmc_tp</slice>
+                       <id>2</id>
+                       <bridge_name>tap1</bridge_name>
+               </host2>
+       </link>
+</links>
diff --git a/forge/tasks.py b/forge/tasks.py
new file mode 100644 (file)
index 0000000..cf3b996
--- /dev/null
@@ -0,0 +1,145 @@
+# -*- coding:utf-8 -*-
+from django.core.files import File
+from celery import task, current_task
+from djcelery.models import TaskState
+from xmlrpclib import Fault
+
+from forge.models import *
+
+import forge.script.Auth as Auth
+import time
+
+# Import class used to create the environment
+from forge.script.request import TransformRawXml
+from forge.script.openvswitch import TransformXml
+
+# Import the settings
+from django.conf import settings
+
+@task()
+def taskInstallEnvironment(env):
+       env.ready = False
+       env.save()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       try:
+               xml = TransformXml(confFile = curDir+env.confFile.url, linkFile = curDir+env.linkFile.url, keyFile = curDir+env.course.mainKey.url)
+               xml.clearConf()
+               xml.setSliceConf()
+               xml.setLinks()
+               xml.setRoutes()
+               xml.setServices()
+       except Exception, why:
+               print why
+       os.chdir(curDir)
+       env.ready = True
+       env.save()
+
+@task()
+def taskDeleteCourse(course):
+       environments = course.environment_set.all()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       for env in environments:
+               try:
+                       xml = TransformXml(confFile = curDir+env.confFile.url, linkFile = curDir+env.linkFile.url, keyFile = curDir+env.course.mainKey.url)
+                       xml.clearConf()
+               except Exception, why:
+                       print why
+       try:
+               rawXml = TransformRawXml(sliceName=course.sliceName)
+               rawXml.deleteSlice()
+       except Fault, why:
+               print "I got an xmlrpc Fault"
+               print why
+       os.chdir(curDir)
+       course.delete()
+
+@task()
+def taskRenewSlice(course):
+       rawXml = TransformRawXml(sliceName=course.sliceName)
+       rawXml.renewSlice()
+
+@task()
+def taskCreateCourse(form):
+       newCourse = Course()
+       newCourse.lab = Lab.objects.get(id=form.cleaned_data['lab'].id)
+       newCourse.ready = False
+       newCourse.sliceName = form.cleaned_data['sliceName']
+       newCourse.save()
+       #TODO Change directory location
+       curDir = os.getcwd()
+       os.chdir('./ict_education/script/')
+       if form.cleaned_data['keyLocation'] == '':
+               keyLocation = None
+       else:
+               keyLocation = form.cleaned_data['keyLocation']
+       if form.cleaned_data['url'] == '':
+               sliceUrl = 'http://onelab.eu'
+       else:
+               sliceUrl = form.cleaned_data['url']
+       if form.cleaned_data['description'] == '':
+               sliceDescription = 'Slice used for educational purpose'
+       else:
+               sliceDescription = form.cleaned_data['url']
+       try:
+               rawXml = TransformRawXml(confFile = settings.MEDIA_ROOT+newCourse.lab.configurationFile.name, linkFile = settings.MEDIA_ROOT+newCourse.lab.linkFile.name, subnet = form.cleaned_data['subnet'], sliceName = form.cleaned_data['sliceName'], nbEnv = form.cleaned_data['nbEnv'], sliceUrl = sliceUrl, sliceDescription = sliceDescription, mainKeyPriv = keyLocation)
+               rawXml.setSlice()
+               newCourse.mainKey.save(rawXml.mainKeyPriv.split('/')[-1], File(open(rawXml.mainKeyPriv)))
+               newCourse.save()
+               i = 0
+               for environment in rawXml.envList:
+                       newEnv = Environment()
+                       newEnv.ready = False
+                       newEnv.course = newCourse
+                       newEnv.sshKey.save(rawXml.envKeyPriv[i].split('/')[-1], File(open(rawXml.envKeyPriv[i])))
+                       newEnv.confFile.save(rawXml.envConfFile[i].split('/')[-1], File(open(rawXml.envConfFile[i])))
+                       newEnv.linkFile.save(rawXml.envLinkFile[i].split('/')[-1], File(open(rawXml.envLinkFile[i])))
+                       newEnv.save()
+                       i += 1
+                       for plSlice in environment:
+                               newSlice = Slice()
+                               newSlice.sliceName = plSlice.slice_name
+                               newSlice.environment = newEnv
+                               newSlice.save()
+                               for host in plSlice.hosts:
+                                       newHost = Host()
+                                       nodeSelected = ''
+                                       for env in rawXml.nodeList:
+                                               for node in env:
+                                                       if node['hostname'] == host.url:
+                                                               nodeselected = node
+                                                               break
+                                               if nodeSelected != '':
+                                                       break
+                                       newHost.hostname = host.url
+                                       newHost.pleSlice = newSlice
+                                       newHost.latitude = nodeSelected['latitude']
+                                       newHost.longitude = nodeSelected['longitude']
+                                       newHost.save()
+                                       for serviceName, port in host.services.services:
+                                               newService = Service()
+                                               newService.serviceName = serviceName
+                                               newService.servicePort = str(port)
+                                               newService.host = newHost
+                                               newService.save()
+                                       for device in host.devices:
+                                               newInterface = Interface()
+                                               newInterface.ip = device.ip
+                                               newInterface.name = device.id_dev
+                                               newInterface.host = newHost
+                                               newInterface.save()
+                       newEnv.ready = True
+                       newEnv.save()
+               os.chdir(curDir)
+               newCourse.ready = True
+               newCourse.save()
+       except Exception, why:
+               print "An error occured deleting the environment"
+               print why
+               rawXml = TransformRawXml(sliceName=newCourse.sliceName)
+               rawXml.deleteSlice()
+               raise Exception('Global Fault')
+       return 0
diff --git a/forge/templates/create-course.html b/forge/templates/create-course.html
new file mode 100644 (file)
index 0000000..5b06bfb
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="col-md-2">
+</div>
+<div class="col-md-8">
+       <form action="." method="post" enctype="multipart/form-data">
+               {{ form.as_p }}
+               <p><input type="submit" value="Create Class" /></p>
+       </form>
+</div>
+<div class="col-md-2">
+</div>
diff --git a/forge/templates/createCourse.html b/forge/templates/createCourse.html
new file mode 100644 (file)
index 0000000..26b5b1d
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>Create a new Class</title>
+       </head>
+       <body>
+               <form action="{% url "ict_education.views.createCourse" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       {{ form.as_p }}
+                       <p><input type="submit" value="Create Class" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/createLab.html b/forge/templates/createLab.html
new file mode 100644 (file)
index 0000000..2a0b67d
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>Create a new Lab</title>
+       </head>
+       <body>
+       <!-- List of existing labs -->
+       {% if labs %}
+               <ul>
+               {% for lab in labs %}
+                       <li>{{ lab }} 
+                               <a href="/ict_education/lab-details/{{ lab.id }}">Lab details</a>
+                               <a href="/ict_education/delete-lab/{{ lab.id }}">Delete Lab</a>
+                       </li>
+               {% endfor %}
+               </ul>
+       {% else %}
+               <p>No lab</p>
+       {% endif %}
+
+               <!-- Upload form. Note enctype attribute! -->
+               <form action="{% url "ict_education.views.createLab" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       {{ form.as_p }}
+                       <p><input type="submit" value="Add Lab" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/labDetails.html b/forge/templates/labDetails.html
new file mode 100644 (file)
index 0000000..0ab10cc
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>Details of lab {{ lab.title }}</title>
+       </head>
+       <body>
+               <h1>{{ lab.title }}</h1>
+               <h2>{{ lab.author }}</h2>
+               <p><a href="{{ lab.subject.url }}">Subject</a></p>
+               <p><a href="{{ lab.configurationFile.url }}">Configuration File</a><p>
+               <p><a href="{{ lab.linkFile.url }}">{{ lab.linkFile.name }}</a></p>
+       </body>
+</html>
diff --git a/forge/templates/list.html b/forge/templates/list.html
new file mode 100644 (file)
index 0000000..42c2579
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>Minimal Django File Upload Example</title>
+       </head>
+       <body>
+       <!-- List of uploaded documents -->
+       {% if documents %}
+               <ul>
+               {% for document in documents %}
+                       <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
+               {% endfor %}
+               </ul>
+       {% else %}
+               <p>No documents.</p>
+       {% endif %}
+
+               <!-- Upload form. Note enctype attribute! -->
+               <form action="{% url "ict_education.views.list" %}" method="post" enctype="multipart/form-data">
+                       {% csrf_token %}
+                       <p>{{ form.non_field_errors }}</p>
+                       <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
+                       <p>
+                               {{ form.docfile.errors }}
+                               {{ form.docfile }}
+                       </p>
+                       <p><input type="submit" value="Upload" /></p>
+               </form>
+       </body>
+</html>
diff --git a/forge/templates/listCourse.html b/forge/templates/listCourse.html
new file mode 100644 (file)
index 0000000..0c51059
--- /dev/null
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>List of all your class</title>
+       </head>
+       <body>
+               {% if courses %}
+                       <ul>
+                       {% for course, environments in courses %}
+                               
+                               {% if course.ready %}
+                                       <ul>
+                                       <li><a href=" {{ course.mainKey.url }}">Main SSH Key</a></li>
+                                       {# <li>{{ course.id }}</li> #}
+                                       <li><a href=" {{ course.lab.subject.url }}">Subject</a></li>
+                                       <li><a href="/ict_education/delete-course/{{ course.id }}">Delete Course</a></li>
+                                       <li><a href="/ict_education/renew-slice/{{ course.id }}">Renew-Slice</a></li>
+                                       <ul>
+                                       {% for environment, slices  in environments %}
+                                               {% if environment.ready %}
+                                                       <li>Environment <a href="/ict_education/install-env/{{ environment.id }}">Re-install environment</a></li>
+                                                       <li><a href=" {{ environment.sshKey.url }}">SSH Key</a></li>
+                                                       <ul>
+                                                       {% for pleSlice, hosts in slices %}
+                                                               <li>{{ pleSlice.sliceName }}</li>
+                                                               <ul>
+                                                               {% for host, services, interfaces in hosts %}
+                                                                       <li>Hostname : {{ host.hostname }} Type : {{ host.hostType }}</li>
+                                                                       <ul>
+                                                                       {% if services %}
+                                                                               <li>Service List :</li>
+                                                                               <ul>
+                                                                               {% for service in services %}
+                                                                                       {% if service.servicePort == '' %}
+                                                                                               <li>{{ service.serviceName }}</li>
+                                                                                       {% else %}
+                                                                                               <li>{{ service.serviceName }} on {{ service.servicePort }}</li>
+                                                                                       {% endif %}
+                                                                               {% endfor %}
+                                                                               </ul>
+                                                                       {% endif %}
+                                                                       {% if interfaces %}
+                                                                               <li>Interface List :</li>
+                                                                               <ul>
+                                                                               {% for interface in interfaces %}
+                                                                                       <li>{{ interface.name }} : {{ interface.ip }}</li>
+                                                                               {% endfor %}
+                                                                               </ul>
+                                                                       {% endif %}
+                                                                       </ul>
+                                                               {% endfor %}
+                                                               </ul>
+                                                       {% endfor %}
+                                                       </ul>
+                                               {% else %}
+                                                       <ul>Now installing this environment</ul>
+                                                       <li>Environment <a href="/ict_education/install-env/{{ environment.id }}">Re-install environment</a></li>
+                                               {% endif %}
+                                       {% endfor %}
+                                       </ul>
+                               {% else %}
+                                       <li>Course not ready</li>
+                                       <li>{{ course.ready }}</li>
+                               {% endif %}
+                               </ul>
+                       {% endfor %}
+                       </ul>
+               {% else %}
+                       <p>You have not created a class yet</p>
+               {% endif %}
+       </body>
+</html>
diff --git a/forge/templates/mainView.html b/forge/templates/mainView.html
new file mode 100644 (file)
index 0000000..6f5ae31
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8"/>
+               <title>ICT Education</title>
+       </head>
+       <body>
+       <!-- List of available action -->
+               <p><a href="create-lab">Create a new lab</a></p>
+               <p><a href="create-class">Create a new course</a></p>
+               <p><a href="list-course">List of your course</a></p>
+
+       </body>
+</html
diff --git a/forge/tests.py b/forge/tests.py
new file mode 100644 (file)
index 0000000..501deb7
--- /dev/null
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.assertEqual(1 + 1, 2)
diff --git a/forge/views.py b/forge/views.py
new file mode 100644 (file)
index 0000000..6e5cc84
--- /dev/null
@@ -0,0 +1,132 @@
+# -*- coding:utf-8 -*-
+# Create your views here.
+
+# Several import from the django facilities
+from django.template import RequestContext
+from django.shortcuts import render, get_object_or_404, render_to_response, redirect
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.core.files import File
+
+# Import of the forms and models
+from forge.models import *
+from forge.forms import *
+
+# Import of the task and TaskState (used to link task in the database)
+from forge.tasks import *
+from djcelery.models import TaskState
+
+# Import the settings
+from django.conf import settings
+
+import os
+
+# Import class used to create the environment
+from forge.script.request import TransformRawXml
+
+from myslice.theme import ThemeView
+from unfold.loginrequired import FreeAccessView
+
+class CreateCourseViev (FreeAccessView, ThemeView):
+       template_name = 'create-course.html'
+
+       def get (self, request, slicename, state=None):
+               username = self.request.user
+               split_slicename = slicename.split('.')
+               ple_slicename = split_slicename[0] + '8' + split_slicename[1] + '_' + split_slicename[2]
+               if not Course.objects.get(sliceName = ple_slicename).exists():
+                       if request.method == 'POST':
+                               form = courseForm(request.POST)
+                               if form.is_valid():
+                                       result = taskCreateCourse.delay(form)
+                       else:
+                               labs = Lab.objects.all()
+                               form = courseForm()
+               return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'form': form }, context_instance=RequestContext(request))
+
+def mainView(request):
+       return render(request, 'mainView.html', locals())
+
+
+def createLab(request):
+       if request.method == 'POST':
+               form = LabForm(request.POST, request.FILES)
+               if form.is_valid():
+                       newLab = Lab(
+                               title = form['title'].value(),
+                               author = form['author'].value(),
+                               subject = request.FILES['subject'],
+                               configurationFile = request.FILES['configurationFile'],
+                               linkFile = request.FILES['linkFile'],
+                       )
+                       newLab.save()
+       else:
+               form = LabForm()
+       labs = Lab.objects.all()
+       return render_to_response('createLab.html', {'labs': labs, 'form':form}, context_instance=RequestContext(request))
+
+def labDetails(request, id):
+       try:
+               lab = Lab.objects.get(id=id)
+       except Lab.DoesNotExist:
+               raise Http404
+       return render(request, 'labDetails.html', locals())
+
+def deleteLab(request, id):
+       try:
+               lab = Lab.objects.get(id=id)
+       except Lab.DoesNotExist:
+               raise Http404
+       lab.delete()
+       return redirect('forge.views.createLab')
+
+def createCourse(request):
+       if request.method == 'POST':
+               form = courseForm(request.POST)
+               if form.is_valid():
+                       result = taskCreateCourse.delay(form)
+       else:
+               labs = Lab.objects.all()
+               form = courseForm()
+       return render(request, 'createCourse.html', locals())
+
+def installEnvironment(request, id):
+       task = taskInstallEnvironment.delay(Environment.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def renewSlice(request, id):
+       task = taskRenewSlice.delay(Course.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def deleteCourse(request, id):
+       task = taskDeleteCourse.delay(Course.objects.get(id=id))
+       return redirect('forge.views.listCourse')
+
+def listCourse(request):
+       courses = Course.objects.all()
+       environments = Environment.objects.all()
+       slices = Slice.objects.all()
+       hosts = Host.objects.all()
+       services = Service.objects.all()
+       renderCourses = []
+       for course in courses:
+               renderEnvironment = []
+               if course.ready:
+                       for environment in course.environment_set.all():
+                               renderSlice = []
+                               for pleSlice in environment.slice_set.all():
+                                       renderHost = []
+                                       for host in pleSlice.host_set.all():
+                                               renderService = []
+                                               for service in host.service_set.all():
+                                                       renderService.append(service)
+                                               renderInterface = []
+                                               for interface in host.interface_set.all():
+                                                       renderInterface.append(interface)
+                                               renderHost.append([host, renderService, renderInterface])
+                                       renderSlice.append([pleSlice, renderHost])
+                               renderEnvironment.append([environment, renderSlice])
+               renderCourses.append([course, renderEnvironment])
+
+       
+       return render(request, 'listCourse.html', {'courses': renderCourses})
index 9897b50..9385bfa 100644 (file)
@@ -59,6 +59,7 @@ with the query passed using POST"""
             manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
         else:
             if 'manifold' in request.session:
+                print '===> manifoldproxy.proxy: before auth', manifold_query
                 manifold_api_session_auth = request.session['manifold']['auth']
             else:
                 json_answer=json.dumps({'code':0,'value':[]})
index ca111de..b25647b 100644 (file)
@@ -243,6 +243,7 @@ function QueryStore() {
         // XXX query.change_action() should become deprecated
         update_query = query.clone();
         update_query.action = 'update';
+        update_query.fields = [];
         update_query.analyzed_query.action = 'update';
         update_query.params = {};
         update_query_ext = new QueryExt(update_query);
@@ -1091,7 +1092,11 @@ var manifold = {
             // Has it a domain query, and has it completed ?
             $.each(records, function(i, record) {
                 var key = manifold.metadata.get_key(query.object);
-                var record_key = manifold.record_get_value(record, key);
+                if ( typeof record === "string" ){
+                    var record_key = record;
+                }else{
+                    var record_key = manifold.record_get_value(record, key);
+                }
                 manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_SET, STATE_SET_IN);
             });
 
@@ -1363,8 +1368,9 @@ case TYPE_LIST_OF_VALUES:
                 case TYPE_LIST_OF_VALUES: // XXX Until fixed
                 case TYPE_LIST_OF_RECORDS:
                     var key, new_state, cur_query_uuid;
-
-                    cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+                    if($.inArray(field,Object.keys(query.analyzed_query.subqueries)) > -1){
+                        cur_query_uuid = query.analyzed_query.subqueries[field].query_uuid;
+                    }
 
                     // example: slice.resource
                     //  - update_query_orig.params.resource = resources in slice before update
@@ -1449,6 +1455,8 @@ case TYPE_LIST_OF_VALUES:
         var query_ext = manifold.query_store.find_query_ext(query.query_uuid);
         query_ext.query_state = QUERY_STATE_DONE;
 
+        var tmp_query = manifold.query_store.find_analyzed_query(query.query_uuid);
+        manifold.publish_result_rec(tmp_query, records);
 
         // Send DONE message to plugins
         query.iter_subqueries(function(sq, data, parent_query) {
@@ -1884,6 +1892,7 @@ case TYPE_LIST_OF_VALUES:
                 break;
 
             case RUN_UPDATE:
+                query_ext.main_query_ext.update_query_ext.query.fields = [];
                 manifold.run_query(query_ext.main_query_ext.update_query_ext.query);
                 break;
 
index 5ce5260..680ddbc 100644 (file)
@@ -35,6 +35,10 @@ class ConfigEngine(object):
     default_manifold_admin_password = 'demo'
     default_myslice_theme           = 'onelab'
 
+    #iotlab dev url
+    default_iotlab_url = "https://devgrenoble.senslab.info/rest/admin/users"
+    default_iotlab_admin_user = "auge"
+    default_iotlab_admin_password= "k,mfg1+Q"
 
     def __init__ (self):
         parser = RawConfigParser ()
index 235a18c..bd1474b 100644 (file)
@@ -2,6 +2,9 @@
 
 import os.path
 
+import djcelery
+djcelery.setup_loader()
+
 ### detect if we're in a build environment
 try:
     import manifold
@@ -233,6 +236,9 @@ INSTALLED_APPS = [
     'south', 
     # Uncomment the next line to enable the admin:
      'django.contrib.admin',
+       # FORGE Plugin app
+       'djcelery',
+       'forge',
     # Uncomment the next line to enable admin documentation:
     # 'django.contrib.admindocs',
     'portal',
@@ -242,6 +248,8 @@ INSTALLED_APPS = [
 # this app won't load in a build environment
 if not building: INSTALLED_APPS.append ('rest')
 
+BROKER_URL = "amqp://myslice:myslice@localhost:5672/myslice"
+
 for aux in auxiliaries:
     if os.path.isdir(os.path.join(ROOT,aux)): 
         print "Using devel auxiliary",aux
@@ -278,7 +286,8 @@ LOGGING = {
     }
 }
 
-AUTHENTICATION_BACKENDS = ( 'auth.manifoldbackend.ManifoldBackend','django.contrib.auth.backends.ModelBackend' )
+AUTHENTICATION_BACKENDS = ('auth.manifoldbackend.ManifoldBackend',
+                           'django.contrib.auth.backends.ModelBackend')
 
 ### the view to redirect malformed (i.e. with a wrong CSRF) incoming requests
 # without this setting django will return a 403 forbidden error, which is fine
@@ -292,6 +301,7 @@ CSRF_FAILURE_VIEW = 'manifoldapi.manifoldproxy.csrf_failure'
 
 ####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_URL = "http://157.193.215.125:4001/sla-collector/sla"
+#SLA_MANAGER_URL = "http://172.24.76.28:8000/sla"
+SLA_MANAGER_USER = "portal"
+SLA_MANAGER_PASSWORD = "password"
index 91511b7..5f4c7d4 100644 (file)
@@ -44,6 +44,8 @@ import portal.slicetabmeasurements
 import portal.managementtababout
 import portal.managementtabrequests
 
+import forge.views
+
 #### high level choices
 # main entry point (set to the / URL)
 # beware that if this view is broken you end up in an endless cycle...
@@ -82,6 +84,7 @@ urls = [
     #
     # RESTful interface
     (r'^rest/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
+    (r'^sfa/(?P<method>[^/]+)/?$', 'rest.sfa_api.dispatch'),
     (r'^table/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
     (r'^datatable/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.get.dispatch'),
     (r'^update/(?P<object_type>[^/]+)/(?P<object_name>[^/]+)?/?$', 'rest.update.dispatch'),
@@ -106,6 +109,7 @@ urls = [
     (r'^testbeds/(?P<slicename>[^/]+)/?$', portal.slicetabtestbeds.SliceTabTestbeds.as_view()),
     (r'^measurements/(?P<slicename>[^/]+)/?$', portal.slicetabmeasurements.SliceTabMeasurements.as_view()),
     (r'^experiment/(?P<slicename>[^/]+)/?$', portal.slicetabexperiment.ExperimentView.as_view()),
+    (r'^studentslabs/(?P<slicename>[^/]+)/?$', forge.views.CreateCourseViev.as_view()),
     
     url(r'^about/?$', AboutView.as_view(), name='about'),
     
index 3cc48a9..a58d412 100644 (file)
@@ -33,12 +33,16 @@ class ColumnsEditor(Plugin):
 
     def template_env(self, request):
         fields = []
+        if self.default_fields is not None:
+            default_fields = self.default_fields
+        else:
+            default_fields = self.query.fields
         #hidden_columns = self.hidden_columns
         metadata = self.page.get_metadata()
         md_fields = metadata.details_by_object('resource')
 
         # XXX use django templating system here
-        for md_field in md_fields['column']:
+        for md_field in sorted(md_fields['column']):
             if md_field['type'] == 'string':
                 if 'allowed_values' in md_field:
                     allowed_values = md_field['allowed_values'].split(',')
@@ -82,7 +86,7 @@ class ColumnsEditor(Plugin):
                 'resource_type': 'N/A',
                 'filter_input':  filter_input,
                 'header':        None,
-                'checked':       md_field['name'] in self.query.get_select()
+                'checked':       md_field['name'] in default_fields
             })
         #return { 'fields': fields, 'hidden_columns': hidden_columns }
         #return { 'fields': fields , 'query_uuid': self.query_uuid, 'query_all_uuid': self.query_all_uuid }
index 995e935..fe486d5 100644 (file)
@@ -33,12 +33,6 @@ Current implementation makes the following assumptions
   as we use 'aoColumnDefs' instead.
 """
 
-    MAP = {
-        'facility_name' :   'Facility',
-        'testbed_name'  :   'Testbed',
-        'hostname'      :   'Resource name',
-        'type'          :   'Type',
-    }
 
     def __init__ (self, query=None, query_all=None, 
                   checkboxes=False, columns=None, 
@@ -56,10 +50,19 @@ Current implementation makes the following assumptions
             _columns = columns
             _hidden_columns = []
         elif self.query:
-            _columns = [field for field in self.query.fields if not field == 'urn']
+            print "self.query.fields = ", self.query_all.fields
+            # Columns displayed by default
+            if self.default_fields is not None:
+                _columns = [field for field in self.default_fields if not field == 'urn']
+            else:
+                _columns = [field for field in self.query.fields if not field == 'urn']
             if query_all:
                 # We need a list because sets are not JSON-serializable
-                _hidden_columns = list(self.query_all.fields - self.query.fields)
+                if self.default_fields is not None:
+                    print self.query_all.fields
+                    _hidden_columns = list(self.query_all.fields - set(self.default_fields))
+                else:
+                    _hidden_columns = list(self.query_all.fields - self.query.fields)
                 _hidden_columns.append('urn')
             else:
                 _hidden_columns = []
@@ -68,9 +71,10 @@ Current implementation makes the following assumptions
             _hidden_columns = []
 
         print "_columns=", _columns
-        self.columns = { self.MAP.get(c, c) : c for c in _columns }
-        self.hidden_columns = { self.MAP.get(c, c) : c for c in _hidden_columns }
+        self.columns = { self.mapping.get(c, c) : c for c in _columns }
+        self.hidden_columns = { self.mapping.get(c, c) : c for c in _hidden_columns }
         print "self.columns", self.columns
+        print "self.hidden_columns", self.hidden_columns
 
         self.init_key=init_key
         self.datatables_options=datatables_options
index 3c1aab2..ab20810 100644 (file)
@@ -10,14 +10,6 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
 
 (function($){
 
-    
-    var QUERYTABLE_MAP = {
-        'Facility': 'facility_name',
-        'Testbed': 'testbed_name',
-        'Resource name': 'hostname',
-        'Type': 'type',
-    };
-
     var debug=false;
 //    debug=true
 
@@ -166,23 +158,35 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
             
             // resource info
             var sTable = this.table;
+            var oSettings = this.table.fnSettings();
+            var cols = oSettings.aoColumns;
+            var self = this;
             $('table.dataTable').delegate('a.resource-info','click',function() {
                 var aPos = sTable.fnGetPosition( this.parentNode );
                 var aData = sTable.fnGetData( aPos[0] );
                 //console.log(aData);
-                
-                var network_hrn = aData[18];
+
+                var index = {}
+                // XXX Loic @ Hardcoded !!! Maybe a loop over all fields would be better 
+                index['network_hrn'] = self.getColIndex('network_hrn',cols);
+                var network_hrn = aData[index['network_hrn']];
+
+                index['hostname'] = self.getColIndex('hostname',cols);
+                index['urn'] = self.getColIndex('urn',cols);
+                index['type'] = self.getColIndex('type',cols);
+                index['status'] = self.getColIndex('boot_state',cols);
+                index['testbed'] = self.getColIndex('testbed_name',cols);
+                index['facility'] = self.getColIndex('facility_name',cols);
                 var resourceData = {
-                    'hostname' : strip(aData[2]),
-                    'urn' : aData[6],
-                    'type' : aData[3],
-                    'status' : aData[10],
-                    'testbed' : aData[4],
-                    'facility' : aData[5],
+                    'hostname' : strip(aData[index['hostname']]),
+                    'urn' : aData[index['urn']],
+                    'type' : aData[index['type']],
+                    'status' : aData[index['status']],
+                    'testbed' : aData[index['testbed']],
+                    'facility' : aData[index['facility']],
                 };
                 
-                
-                console.log(network_hrn);
+                /*
                 //Greece: 37.6687092,22.2282404
                 if (network_hrn == 'omf.nitos') {
                     var logo = 'nitos';
@@ -192,6 +196,8 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
                     };
                     var coordinates = resourceLocation['latitude']+','+resourceLocation['longitude'];
                 } else if (network_hrn == 'iotlab') {
+                */
+                if (network_hrn == 'iotlab') {
                     var logo = network_hrn;
                     var s = resourceData['hostname'].split(".");
                     var n = s[0].split("-");
index f3ba672..f1d6b32 100644 (file)
 
         /***************************** GUI EVENTS *****************************/
 
-        /************************** GUI MANIPULATION **************************/
+        do_checksla: function(e) {
+            var username = e.data.options.username;
+            var urn = data.value;
+            var arraySelectedResources = data.selected_resources;
+
+            var accepted_sla = [];
+            var count = 0;
+            var self = e.data;
+            // var testbedsWithSLA = ["iminds", "fuseco", "netmode"];
+            var testbedsWithSLA;
+            
+            var sliverPattern = /IDN\+(.+)\+(node|channel)\+/;
+            var list = [];
+
+            var promt = $('#sla-table-body');
+            
+            $.get("/sla/testbeds/", function(data) {
+                testbedsWithSLA = data;
+
+                console.log("Testbeds with SLA: " + testbedsWithSLA);
+
+                $(arraySelectedResources).each(function () {
+                    var sliverMatch = sliverPattern.exec(this);
+                    var sliverId = sliverMatch[1];
+                    for (var i = 0; i < testbedsWithSLA.length; i++) {
+                        if(this.indexOf(testbedsWithSLA[i].toLowerCase()) >= 0){ // If it has SLA
+                            if (list.indexOf(sliverId) == -1) { // If it is not in the list
+                                list.push(sliverId);
+                            }
+                        }
+                    }
+                });
+
+                if (list.length > 0) {
+                    for (var i = 0; i < list.length; i++) {
+                        var element = $('<tr>');
+                        element.append(
+                            $('<td>').append(list[i]),
+                            $('<td>').append('99% of Uptime for 99% of resources'),
+                            $('<td align="center">').append('<input type="checkbox" name="slaaccept" value="' + list[i] + '"/> <br />')
+                        );
+                        promt.append(element);
+                    }
+
+                    $('#sla_dialog').show();
+                    $('#slamodal').modal('show');
+                } else {
+                    //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+                }
+            
+            });
+                    
+            $("#submit_sla").unbind().click(function(){
+                console.log("With username: " + username);
+
+                var notChecked = $("input[name='slaaccept']:not(:checked)");
+                
+                if (notChecked.length > 0) {
+                    for (var i = 0; i < notChecked.length; i++) {
+                         console.log("SLA not accepted: " + notChecked[i].value);
+                    }    
+
+                    alert("All SLAs have to be accepted to continue with the reservation");
+
+                } else {
+                    // $(list).each(function () {
+                    //     var date = new Date();
+                    //     date.setYear(date.getFullYear() + 1);
+
+                    //     $.post("/sla/agreements/simplecreate", 
+                    //         { "template_id": this.toString(),
+                    //           "user": username,
+                    //           "expiration_time": date.toISOString()
+                    //         });
+
+                        
+                    // });
+
+                    $.ajax({
+                        url: "/sla/agreements/simplecreate", 
+                        data: { testbeds: list,
+                          user: username,
+                          resources: arraySelectedResources,
+                          slice: main_query.filters.slice()[0][2]
+                        },
+                        type: "post",
+                        traditional: true
+                    });
+
+                    console.log(main_query.filters.slice()[0][2]);
+                      
+                    $('#slamodal').modal('hide');
+                    $('#sla-table-body').empty();
+                    //manifold.raise_event(self.options.query_uuid, RUN_UPDATE);
+                }
+            });
+
+               $("#cancel_sla").unbind().click(function(){
+                $('#slamodal').modal('hide');
+                $('#sla-table-body').empty();
+            }); 
+        },
+               /************************** GUI MANIPULATION **************************/
 
         populate_table: function()
         {
index ce27c2e..cb50c29 100644 (file)
@@ -1,18 +1,27 @@
 <div id={{ domid }}>
-<div class="modal fade" id="slamodal-wilab2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
+<div class="modal fade" id="slamodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
                data-backdrop="static" data-keyboard="false">
   <div class="modal-dialog">
     <div class="modal-content">
       <div class="modal-header">
-        <h4 class="modal-title" id="myModalLabel">Provider iMinds offers the following SLA</h4>
+        <h4 class="modal-title" id="myModalLabel">Selected testbed(s) provide the following SLAs</h4>
       </div>
       <div class="modal-body"  id="modal-body">
-        <!-- <p>SLA description</p>
-        <p>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the WiLab2 resources during the sliver lifetime</p> -->
+        <table class="table" id="sla-modal-table">
+          <thead>
+          <tr>
+            <th>Testbed</th>
+            <th>SLA Description</th>
+            <th>Accept</th>
+          </tr>
+          </thead>
+          <tbody id="sla-table-body">
+          </tbody>
+        </table>
       </div>
       <div class="modal-footer">
-        <button type="button" id="dismiss_sla_wilab2" class="btn btn-default" data-dismiss="modal">Dismiss</button>
-        <button type="button" id="accept_sla_wilab2" class="btn btn-primary">Accept</button>
+        <button type="button" id="cancel_sla" class="btn btn-default" data-dismiss="modal">Cancel</button>
+        <button type="button" id="submit_sla" class="btn btn-primary">Submit</button>
       </div>
     </div>
   </div>
diff --git a/portal/account.py b/portal/account.py
new file mode 100644 (file)
index 0000000..7d08e1c
--- /dev/null
@@ -0,0 +1,45 @@
+from manifold.core.query                import Query
+from manifoldapi.manifoldapi            import execute_query
+
+from datetime import datetime
+import time
+import dateutil.parser
+import calendar
+
+import json, os, re, itertools
+
+class Account:
+    def __init__ (self, platform_id, user_id):
+        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id', '==', platform_id).filter_by('user_id', '==', user_id)
+        account_details = execute_query(self.request, account_query)
+        self.user_id     = account_details['user_id']
+        self.platform_id = account_details['platform_id']
+        self.auth_type   = account_details['auth_type']
+        self.config      = account_details['config']
+        account_config = json.loads(account_details['config'])
+
+        self.usr_hrn = account_config.get('user_hrn',None)
+        self.pub_key = account_config.get('user_public_key',None)
+        self.reference = account_config.get ('reference_platform',None)
+
+        self.user_cred = account_config.get('delegated_user_credential',None)
+        self.user_cred_expiration = get_expiration(self.user_cred)
+        
+        slice_creds = account_config.get('delegated_slice_credentials',None)
+        for slice_name, slice_cred in slice_creds.iteritems():
+            self.slice_cred_expiration = get_expiration(self.slice_cred)
+
+        self.auth_cred = account_config.get('delegated_authority_credentials',None)
+        self.auth_cred_expiration = get_expiration(self.auth_cred)
+
+def get_expiration (credential, format = 'UTC'):
+    exp_date = re.search('<expires>(.*)</expires>', credential)
+    if exp_date:
+        exp_date = exp_date.group(1)
+        if format == 'timestamp':
+            exp_date = calendar.timegm(dateutil.parser.parse(exp_date).utctimetuple())
+    else:
+        exp_date = None
+    return exp_date
+
index 5048383..4d25c61 100644 (file)
@@ -14,10 +14,12 @@ from django.http                        import HttpResponse, HttpResponseRedirec
 from django.contrib                     import messages
 from django.contrib.auth.decorators     import login_required
 
+from myslice.configengine           import ConfigEngine
 from myslice.theme import ThemeView
 
+from portal.account                     import Account, get_expiration
 #
-import json, os, re, itertools
+import json, os, re, itertools, time
 from OpenSSL import crypto
 from Crypto.PublicKey import RSA
 
@@ -37,6 +39,10 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/my_account.edit_profile.js","js/jquery-ui.js" ] )
         page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css" ] )
 
+        # Execute a Query to delegate credentials if necessary
+        sfa_user_query  = Query().get('myslice:user').select('user_hrn').filter_by('user_hrn','==','$user_hrn')
+        sfa_user_result = execute_query(self.request, sfa_user_query)
+
         user_query  = Query().get('local:user').select('config','email','status')
         user_details = execute_query(self.request, user_query)
         
@@ -210,7 +216,11 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         if acc_user_cred == {} or acc_user_cred == 'N/A':
             user_cred = 'no_creds'
         else:
-            user_cred = 'has_creds'
+            exp_date = get_expiration(acc_user_cred, 'timestamp')
+            if exp_date < time.time():
+                user_cred = 'creds_expired'
+            else:
+                user_cred = 'has_creds'
 
         context = super(AccountView, self).get_context_data(**kwargs)
         context['principal_acc'] = principal_acc_list
@@ -243,6 +253,20 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         context.update(prelude_env)
         return context
 
+@login_required
+def get_myslice_platform(request):
+    platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled','config').filter_by('platform','==','myslice')
+    platform_details = execute_query(request, platform_query)
+    for platform_detail in platform_details:
+        return platform_detail
+
+@login_required
+def get_myslice_account(request):
+    platform_myslice = get_myslice_platform(request)
+    account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id','==',platform_myslice['platform_id'])
+    account_details = execute_query(request, account_query)
+    for account_detail in account_details:
+        return account_detail
 
 @login_required
 #my_acc form value processing
@@ -256,10 +280,19 @@ def account_process(request):
     platform_query  = Query().get('local:platform').select('platform_id','platform')
     platform_details = execute_query(request, platform_query)
     
-    # getting the user_id from the session
-    for user_detail in user_details:
-            user_id = user_detail['user_id']
-            user_email = user_detail['email']
+    # getting the user_id from the session                                            
+    for user_detail in user_details:                                                  
+        user_id = user_detail['user_id']                                              
+        user_email = user_detail['email']                                             
+        try:
+            if user_email == request.user.email:                                          
+                authorize_query = True                                                    
+            else:                                                                         
+                print "SECURITY: %s tried to update %s" % (user_email, request.user.email)
+                messages.error(request, 'You are not authorized to modify another user.') 
+                return HttpResponseRedirect("/portal/account/")                               
+        except Exception,e:
+            print "Exception = %s" % e
 
     for account_detail in account_details:
         for platform_detail in platform_details:
@@ -380,7 +413,7 @@ def account_process(request):
                         # updating sfa
                         public_key = public_key.replace('"', '');
                         user_pub_key = {'keys': public_key}
-                        #sfa_update_user(request, user_hrn, user_pub_key)
+
                         sfa_update_user(request, user_hrn, user_pub_key)
                         result_sfa_user = sfa_get_user(request, user_hrn, public_key)
                         try:
@@ -395,6 +428,7 @@ def account_process(request):
                                 raise Exception,"Keys are not matching"
                         except Exception,e:
                             messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
+                            print "Exception in accountview ", e
                         return HttpResponseRedirect("/portal/account/")
         else:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
@@ -515,6 +549,40 @@ def account_process(request):
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
+    # Download sfi_config
+    elif 'dl_sfi_config' in request.POST:
+        platform_detail = get_myslice_platform(request)
+        platform_config = json.loads(platform_detail['config'])
+        account_detail = get_myslice_account(request)
+        account_config = json.loads(account_detail['config'])
+
+        user_hrn = account_config.get('user_hrn','N/A')
+        t_user_hrn = user_hrn.split('.')
+        authority_hrn = t_user_hrn[0] + '.' + t_user_hrn[1]
+        import socket
+        hostname = socket.gethostbyaddr(socket.gethostname())[0]
+        registry = platform_config.get('registry','N/A')
+        admin_user = platform_config.get('user','N/A')
+        if 'localhost' in registry:
+            port = registry.split(':')[-1:][0]
+            registry = "http://" + hostname +':'+ port
+        manifold_host = ConfigEngine().manifold_url()
+        if 'localhost' in manifold_host:
+            manifold_host = manifold_host.replace('localhost',hostname)
+        sfi_config  = '[sfi]\n'
+        sfi_config += 'auth = '+ authority_hrn +'\n'
+        sfi_config += 'user = '+ user_hrn +'\n'
+        sfi_config += 'registry = '+ registry +'\n'
+        sfi_config += 'sm = http://sfa3.planet-lab.eu:12346/\n\n'
+        sfi_config += '[myslice]\n'
+        sfi_config += 'backend = '+ manifold_host +'\n'
+        sfi_config += 'delegate  = '+ admin_user +'\n'
+        sfi_config += 'platform  = myslice\n'
+        sfi_config += 'username  = '+ user_email +'\n'
+        response = HttpResponse(sfi_config, content_type='text/plain')
+        response['Content-Disposition'] = 'attachment; filename="sfi_config"'
+        return response
+
     #clear all creds
     elif 'clear_cred' in request.POST:
         try:
index 6fde021..31e4bcb 100644 (file)
@@ -11,6 +11,8 @@ from django.template.loader     import render_to_string
 from django.core.mail           import EmailMultiAlternatives, send_mail
 
 from myslice.theme              import ThemeView
+from myslice.configengine       import ConfigEngine
+
 
 theme = ThemeView()
 
@@ -25,6 +27,8 @@ import activity.slice
 # Get the list of authorities
 
 def authority_get_pis(request, authority_hrn):
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
     results = execute_admin_query(request, query)
     print "authority_get_pis = %s" % results
@@ -49,7 +53,9 @@ def authority_get_pi_emails(request, authority_hrn):
         return ['support@onelab.eu']
     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')
+
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+        query = Query.get('myslice: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]
 
@@ -95,8 +101,10 @@ def clear_user_creds(request, user_email):
 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')
+    # seauthorities from user where user_hrn == "ple.upmc.jordan_auge"
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
     results = execute_admin_query(wsgi_request, query)
     if not results:
         # XXX Warning ?
@@ -108,19 +116,25 @@ def is_pi(wsgi_request, user_hrn, authority_hrn):
 # 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)
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_sfa_user = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn)
+    result_sfa_user = execute_admin_query(request, query_sfa_user)
     return result_sfa_user                        
 
 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)
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.update('myslice:user').filter_by('user_hrn', '==', user_hrn).set(user_params).select('user_hrn')
+    results = execute_admin_query(request,query)
     return results
 
 def sfa_add_authority(request, authority_params):
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.create('authority').set(authority_params).select('authority_hrn')
     results = execute_query(request, query)
     print "sfa_add_auth results=",results
@@ -130,10 +144,14 @@ def sfa_add_authority(request, authority_params):
 
 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'])
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_current_users = Query.get('myslice: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')
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.update('myslice: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'
@@ -590,7 +608,8 @@ def create_slice(wsgi_request, request):
     user_hrn = request.get('user_hrn', None)
     user_hrns = list([user_hrn]) if user_hrn else list()
     
-    user_query  = Query().get('user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    user_query  = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
     user_details_sfa = execute_admin_query(wsgi_request, user_query)
     if not user_details_sfa:
         raise Exception, "User %s doesn't exist, validate user before validating slice" % user_hrn
@@ -612,6 +631,7 @@ def create_slice(wsgi_request, request):
     }
     # ignored in request: id, timestamp,  number_of_nodes, type_of_nodes, purpose
 
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.create('myslice:slice').set(slice_params).select('slice_hrn')
     results = execute_query(wsgi_request, query)
     if not results:
@@ -619,7 +639,7 @@ def create_slice(wsgi_request, request):
     else:
         clear_user_creds(wsgi_request,user_email)
         # log user activity
-        #activity.slice.validate(request, "Slice validation", { "slice" : hrn })
+        activity.slice.validate(request, { "slice" : hrn })
         try:
             theme.template_name = 'slice_request_validated.txt'
             text_content = render_to_string(theme.template, request)
@@ -752,7 +772,8 @@ def sfa_create_user(wsgi_request, request, namespace = None, as_admin = False):
     if namespace is not None:
         query = Query.create('%s:user' % namespace).set(sfa_user_params).select('user_hrn')
     else:
-        query = Query.create('user').set(sfa_user_params).select('user_hrn')
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+        query = Query.create('myslice:user').set(sfa_user_params).select('user_hrn')
 
     if as_admin:
         results = execute_admin_query(wsgi_request, query)
@@ -789,9 +810,9 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
     import time
     from requests.auth import HTTPBasicAuth
     
-    URL_REST = 'https://devgrenoble.senslab.info/rest/admin/users'
-    LOGIN_ADMIN = "auge"
-    PASSWORD_ADMIN = "k,mfg1+Q"
+    URL_REST = ConfigEngine.default_iotlab_url
+    LOGIN_ADMIN = ConfigEngine.default_iotlab_admin_user
+    PASSWORD_ADMIN = ConfigEngine.default_iotlab_admin_password
 
     auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
     headers = {'content-type': 'application/json'}
@@ -802,7 +823,7 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
 
     iotlab_user_params = {
         "type"          : "SA",
-        "login"         : request['email'],
+        #"login"         : request['email'], #auto generated by iotlab
         "password"      : password,
         "firstName"     : request['first_name'],
         "lastName"      : request['last_name'],
index f1ac37c..3e9514f 100644 (file)
@@ -17,9 +17,10 @@ from ui.topmenu                         import topmenu_items, the_user
 from myslice.configengine               import ConfigEngine
 
 from myslice.theme                      import ThemeView
+from portal.account                     import Account, get_expiration
 from portal.models                      import PendingSlice
 
-import json
+import json, time
 import activity.user
 
 class HomeView (FreeAccessView, ThemeView):
@@ -97,8 +98,12 @@ class HomeView (FreeAccessView, ThemeView):
                     if acc_user_cred == {} or acc_user_cred == 'N/A':
                         user_cred = 'no_creds'
                     else:
-                        user_cred = 'has_creds'
-                    
+                        exp_date = get_expiration(acc_user_cred, 'timestamp')
+                        if exp_date < time.time():
+                            user_cred = 'creds_expired'
+                        else:
+                            user_cred = 'has_creds'
+
                     # list the pending slices of this user
                     pending_slices = []
                     for slices in PendingSlice.objects.filter(type_of_nodes__iexact=self.request.user).all():
@@ -160,7 +165,11 @@ class HomeView (FreeAccessView, ThemeView):
             if acc_user_cred == {} or acc_user_cred == 'N/A':
                 user_cred = 'no_creds'
             else:
-                user_cred = 'has_creds'
+                exp_date = get_expiration(acc_user_cred, 'timestamp')
+                if exp_date < time.time():
+                    user_cred = 'creds_expired'
+                else:
+                    user_cred = 'has_creds'
 
             # list the pending slices of this user
             pending_slices = []
diff --git a/portal/platform.py b/portal/platform.py
new file mode 100644 (file)
index 0000000..f224056
--- /dev/null
@@ -0,0 +1,21 @@
+from manifold.core.query                import Query
+from manifoldapi.manifoldapi            import execute_query
+
+class Platform:
+    def __init__ (self, id = None, name = None):
+        if id is not None:
+            platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled').filter_by('platform_id', '==', platform_id)
+        if name is not None:
+            platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled').filter_by('platform', '==', platform)
+        self.id       = platform_query['platform_id']
+        self.name     = platform_query['platform']
+        self.type     = platform_query['gateway_type']
+        self.disabled = platform_query['disabled']
+
+#class Platforms:
+#    def __init__ (self):
+#        platforms_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+#        platforms_details = execute_query(self.request, platform_query)
+#        for platform_detail in platforms_details:
+#            Platform(id = platform_detail['platform_id'])
index e55e30f..353f534 100644 (file)
@@ -41,6 +41,7 @@ class RegistrationView (FreeAccessView, ThemeView):
         """
         errors = []
         authority_hrn = None
+        # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
         authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
         if authorities is not None:
@@ -52,6 +53,7 @@ class RegistrationView (FreeAccessView, ThemeView):
         page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/jquery.qtip.min.js","js/jquery-ui.js" ] )
         page.add_css_files ( [ "css/onelab.css", "css/registration.css", "css/jquery.qtip.min.css" ] )
         page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
+        page.expose_js_metadata()
         print "############ BREAKPOINT 2 #################"
         if method == 'POST':
             reg_form = {}
@@ -116,7 +118,9 @@ class RegistrationView (FreeAccessView, ThemeView):
             # Does the user exist in sfa? [query is very slow!!]
             #user_query  = Query().get('user').select('user_hrn','user_email')
             # XXX Test based on the user_hrn is quick
-            user_query  = Query().get('user').select('user_hrn','user_email').filter_by('user_hrn','==',user_request['user_hrn'])
+
+            # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+            user_query  = Query().get('myslice:user').select('user_hrn','user_email').filter_by('user_hrn','==',user_request['user_hrn'])
             user_details_sfa = execute_admin_query(wsgi_request, user_query)
 
             for user in user_details_sfa:
@@ -191,7 +195,7 @@ class RegistrationView (FreeAccessView, ThemeView):
             print "############ BREAKPOINT B #################"
 
         template_env = {
-          'topmenu_items': topmenu_items_live('Register', page),
+          #'topmenu_items': topmenu_items_live('Register', page),
           'errors': errors,
           'authorities': authorities,
           'theme': self.theme
diff --git a/portal/reputationview.py b/portal/reputationview.py
new file mode 100644 (file)
index 0000000..40f8506
--- /dev/null
@@ -0,0 +1,300 @@
+from django.contrib.auth        import authenticate, login, logout\r
+from django.template            import RequestContext\r
+from django.shortcuts           import render, render_to_response\r
+\r
+from manifoldapi.manifoldresult import ManifoldResult\r
+from ui.topmenu                 import topmenu_items, the_user\r
+from myslice.configengine       import ConfigEngine\r
+from manifold.core.query        import Query\r
+from unfold.page                import Page\r
+from manifoldapi.manifoldapi    import execute_admin_query, execute_query\r
+from unfold.loginrequired       import LoginRequiredAutoLogoutView\r
+\r
+from myslice.theme import ThemeView\r
+import json\r
+import hashlib\r
+import datetime\r
+import urllib2\r
+import ast\r
+from django.views.decorators.csrf import csrf_exempt\r
+from django.http                  import *\r
+\r
+def response_mimetype(request):\r
+        \r
+    if "application/json" in request.META['HTTP_ACCEPT']:\r
+        return "application/json"\r
+    else:\r
+        return "text/plain"\r
+    \r
+\r
+def json_to_rest(url, data ):\r
+        \r
+    req = urllib2.Request(url)\r
+    req.add_header('Content-Type', 'application/json')\r
+    response = urllib2.urlopen(req, json.dumps(data))\r
+    \r
+    if data == "a":\r
+        mylist = ast.literal_eval(response.read())\r
+    else:\r
+        mylist = response.read().translate(None, '"[]').split(",")\r
+        \r
+    return (mylist)\r
+\r
+\r
+def unix_to_timestamp(timest):\r
+    try:\r
+        return datetime.datetime.fromtimestamp(int(timest)).strftime('%Y-%m-%d %H:%M:%S')\r
+    except:\r
+        return timest\r
+\r
+def timestamp_to_unix(timest):\r
+    try:\r
+        pass\r
+    except:\r
+        pass\r
+    \r
+    \r
+def slice_to_exp(slices_users):\r
+    experiments = {}\r
+    testbeds = {}\r
+    \r
+    \r
+    for slice in slices_users:\r
+        nodes={}\r
+        leases = slice['lease']\r
+        if leases is not None:\r
+            for lease in leases:\r
+                resource = lease['resource']\r
+                start_t = lease['start_time']\r
+                end_t = lease['end_time']\r
+                #node = lease['resource']\r
+                \r
+                testbed_start = resource.index('IDN+')+4\r
+                testbed_end = resource.index('+node+')\r
+                \r
+                testbed = resource[testbed_start:testbed_end]\r
+                node = resource[testbed_end+6:]\r
+                \r
+                if testbed in testbeds:\r
+                    if node not in testbeds[testbed]:\r
+                        testbeds[testbed].append(node)\r
+                else:\r
+                    testbeds[testbed] = [node]\r
+                \r
+                #group nodes in consecutive timeslots\r
+                if not node in nodes:       \r
+                    nodes[node]={str(start_t):{'start_t':start_t, 'nodes':node, 'end_t':end_t}}\r
+                else:\r
+                    if not str(start_t) in nodes[node]:\r
+                        f=0\r
+                        for n in nodes[node]:\r
+                            if n[str(end_t)] == start_t:\r
+                                n[str(end_t)] == end_t\r
+                                f=1\r
+                        if f==0:\r
+                            nodes[node][str(start_t)]={'start_t':start_t, 'nodes':node, 'end_t':end_t}\r
+                        \r
+        #group grouped nodes in experiments\r
+        for n in nodes:\r
+            for exp in nodes[n]:\r
+                key = str(exp) + str(nodes[n][exp]['end_t'])\r
+                \r
+                if key not in experiments:\r
+                    experiments[key]={'slice_hrn':slice['slice_hrn'], \\r
+                                      'start':nodes[n][exp]['start_t'], 'end':nodes[n][exp]['end_t'], 'nodes':[nodes[n][exp]['nodes']]}   \r
+                elif nodes[n][exp]['end_t'] == experiments[key]['end']:\r
+                    experiments[key]['nodes'].append(nodes[n][exp]['nodes'])\r
+                    \r
+    return (experiments,testbeds)\r
+   \r
+class ReputationView (LoginRequiredAutoLogoutView, ThemeView):\r
+    template_name = 'reputation.html'\r
+        \r
+    # expose this so we can mention the backend URL on the welcome page\r
+    def default_env (self):\r
+        return { \r
+                 'MANIFOLD_URL':ConfigEngine().manifold_url(),\r
+                 }\r
+\r
+    def post (self,request):\r
+        env = self.default_env()\r
+        env['theme'] = self.theme\r
+                \r
+        return render_to_response(self.template, env, context_instance=RequestContext(request))\r
+\r
+\r
+    \r
+    \r
+    def get (self, request, state=None):\r
+        env = self.default_env()\r
+                \r
+        #####    *** Reputation Plugin-specific START       ***     ############\r
+        #The following 'if' is a dirty way for bypassing the JS AJAX cross-domain prevention policy...not pretty\r
+        if request.GET.has_key(u'slicedata[user_eval][overall]'):\r
+            dict_to_send = {}\r
+            dict_to_send['eid'] = str(request.GET[u'slicedata[id]'])\r
+            dict_to_send['slice_hrn'] = str(request.GET[u'slicedata[slice_hrn]'])\r
+            dict_to_send['user_hrn'] = str(request.GET[u'slicedata[user_hrn]'])\r
+            dict_to_send['start_tunix'] = str(request.GET[u'slicedata[start_tunix]'])\r
+            dict_to_send['end_tunix'] = str(request.GET[u'slicedata[end_tunix]'])\r
+            dict_to_send['start_t'] = str(request.GET[u'slicedata[start_t]'])\r
+            dict_to_send['end_t'] = str(request.GET[u'slicedata[end_t]'])\r
+            dict_to_send['testbeds'] = ast.literal_eval(str(request.GET[u'testbeds']))\r
+            dict_to_send['user_eval'] = {}\r
+            dict_to_send['user_eval']['reuse'] = str(request.GET[u'slicedata[user_eval][reuse]'])\r
+            dict_to_send['user_eval']['availability'] = str(request.GET[u'slicedata[user_eval][availability]'])\r
+            dict_to_send['user_eval']['pay'] = str(request.GET[u'slicedata[user_eval][pay]'])\r
+            dict_to_send['user_eval']['support'] = str(request.GET[u'slicedata[user_eval][support]'])\r
+            dict_to_send['user_eval']['overall'] = str(request.GET[u'slicedata[user_eval][overall]'])\r
+            dict_to_send['user_eval']['link_quality'] = str(request.GET[u'slicedata[user_eval][link_quality]'])\r
+            dict_to_send['user_eval']['problems'] = str(request.GET[u'slicedata[user_eval][problems]'])\r
+            dict_to_send['user_eval']['quality'] = str(request.GET[u'slicedata[user_eval][quality]'])\r
+            \r
+            slicedata_received = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/json', dict_to_send )\r
+                        \r
+            return HttpResponse(json.dumps(slicedata_received), content_type = response_mimetype(self.request))\r
+\r
+                \r
+        slices_users = []\r
+        \r
+        #get slices\r
+        userslice_query = Query().get('slice').select('slice_urn', 'slice_hrn', 'users', 'resource', 'lease')\r
+        slice_details = execute_query(self.request, userslice_query)\r
+        \r
+        #get local users\r
+        local_user_query  = Query().get('local:user').select('email','status','config')\r
+        local_user_details = execute_admin_query(self.request, local_user_query)\r
+        \r
+        #get users - create dict[email]=hrn\r
+        user_query  = Query().get('user').select('user_hrn','user_urn','user_email')\r
+        user_details = execute_admin_query(self.request, user_query)\r
+        users_hrn = {}\r
+        for item in user_details:\r
+            users_hrn[item['user_email']] = item['user_hrn']\r
+        \r
+        #get currenct username (email)\r
+        if request.user.is_authenticated():\r
+            cur_username = request.user.username  \r
+        \r
+        #get a list of all the slices for the logged in user\r
+        testbeds = []\r
+\r
+        for slice in slice_details:\r
+            \r
+            if users_hrn[cur_username] in slice['users']:\r
+                slices_users.append({'slice_hrn':slice['slice_hrn'], 'user':cur_username, 'user_hrn':users_hrn[cur_username] \\r
+                                     , 'resource':slice['resource'], 'lease':slice['lease'] })  \r
+                \r
+                             \r
+        env['slices_users'] = slices_users  ### For logging\r
+       \r
+        #####create slicelist for template & JSON\r
+        experiments,testbeds =  slice_to_exp(slices_users)\r
+    \r
+        all_exp = []\r
+        iddata = []\r
+                          \r
+        for exp in experiments:\r
+            experiment = {}\r
+            experiment['slice_hrn'] = experiments[exp]['slice_hrn']\r
+            experiment['user_hrn'] = users_hrn[cur_username]\r
+            experiment['start_tunix'] = experiments[exp]['start']\r
+            experiment['end_tunix'] = experiments[exp]['end']\r
+            experiment['start_t'] = unix_to_timestamp(experiments[exp]['start'])\r
+            experiment['end_t'] = unix_to_timestamp(experiments[exp]['end'])\r
+            experiment['testbeds'] = {}\r
+            for exp_node in experiments[exp]['nodes']:\r
+                list_testbeds = [ key for key,val in testbeds.items()]\r
+                for tkey in list_testbeds:\r
+                    if exp_node in testbeds[tkey]:\r
+                        if tkey in experiment['testbeds']:\r
+                            if exp_node not in experiment['testbeds'][tkey]:\r
+                                experiment['testbeds'][tkey].append(exp_node)\r
+                        else:\r
+                            experiment['testbeds'][tkey] = [exp_node]\r
+            tempid = hashlib.sha1(str(experiment)).hexdigest()                    \r
+            experiment['id'] = tempid\r
+            \r
+            iddata.append(tempid)\r
+            all_exp.append(experiment)\r
+        \r
+        \r
+        ###### Check which experiments have not been rated yet. Pop from all_exp any experiment that has already been rated\r
+        unrated_exp = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/qid', iddata)    \r
+        \r
+        for item in all_exp:\r
+            if item['id'] in unrated_exp:\r
+                pass\r
+            else:\r
+                all_exp.pop(all_exp.index(item))\r
+\r
+\r
+\r
+        ###### Get Reputation values from Reputation DB\r
+        reps = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/showrep', "a")\r
+        #env['logging_test'] = reps    \r
+        \r
+        #create a services list and a dict containing the services for each testbed\r
+        serv_per_tb = {}\r
+        services = []\r
+        for item in reps:\r
+            serv_per_tb[item['testbed']]=[]\r
+            for serv in item['services']:\r
+                if serv.keys()[0] not in services:\r
+                    services.append(serv.keys()[0])\r
+                    serv_per_tb[item['testbed']].append(serv.keys()[0])        \r
+        \r
+        #in json, sevices are in the form: 'services':[{'serv1':x}, {'serv2':y}], so we transform it to 'services':[x,y] based on\r
+        # the services dict above. If for a specific service there is no applicable value, we put N/A            \r
+        for testbed in reps:\r
+            d = list(testbed['services'])\r
+            del testbed['services']\r
+            testbed['services'] = []\r
+            for s in services:\r
+                set_v = 0\r
+                for i in d:\r
+                    try:\r
+                        testbed['services'].append(i[s])\r
+                        set_v=1\r
+                    except:\r
+                        pass\r
+                if set_v == 0 :\r
+                    testbed['services'].append('N/A')\r
+                \r
+        ###### Pass variables to template\r
+        env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
+        env['serv_per_tb'] = json.dumps(serv_per_tb, ensure_ascii=False)\r
+        env['reputation'] = reps\r
+        env['rep_serv'] = services\r
+        env['slicelist'] = all_exp\r
+        env['json_data'] = json.dumps(all_exp, ensure_ascii=False)\r
+        \r
+        ######    *** Reputation Plugin-specific END       ***     ############\r
+        \r
+        \r
+        if request.user.is_authenticated(): \r
+            env['person'] = self.request.user\r
+        else: \r
+            env['person'] = None\r
+    \r
+        env['theme'] = self.theme\r
+        #env['user_list']= user_list\r
+\r
+        env['username']=the_user(request)\r
+        env['topmenu_items'] = topmenu_items(None, request)\r
+        if state: env['state'] = state\r
+        elif not env['username']: env['state'] = None\r
+        # use one or two columns for the layout - not logged in users will see the login prompt\r
+        env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"        \r
+        \r
+        return render_to_response(self.template, env, context_instance=RequestContext(request))\r
+    \r
+\r
+\r
+    \r
+\r
+                    \r
+                    \r
+                    \r
+                    \r
+            
\ No newline at end of file
index c645538..ad4967d 100644 (file)
@@ -18,7 +18,7 @@ import json
 
 class ServiceDirectoryView (LoginRequiredAutoLogoutView, ThemeView):
     template_name = 'servicedirectory.html'
-    server_url = "http://157.193.215.125:4001/"
+    server_url = "http://157.193.215.125:4001/service-directory/"
         
     # expose this so we can mention the backend URL on the welcome page
     def default_env (self):
index 75ede2a..3f0c3b4 100644 (file)
@@ -59,41 +59,70 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         user_md = metadata.details_by_object('user')
         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
 
+        query_resource_all = Query.get('resource').select(resource_fields)
+        page.enqueue_query(query_resource_all)
+
+        # leases query
+        #lease_md = metadata.details_by_object('lease')
+        #lease_fields = [column['name'] for column in lease_md['column']]
+
+        #query_lease_all = Query.get('lease').select(lease_fields)
+        #page.enqueue_query(query_lease_all)
+
+        slice_md = metadata.details_by_object('slice')
+        slice_fields = [column['name'] for column in slice_md['column']]
+        print "SLICE RES VIEW fields = %s" % slice_fields
         # TODO The query to run is embedded in the URL
         # Example: select slice_hrn, resource.urn, lease.resource, lease.start_time, lease.end_time from slice where slice_hrn == "ple.upmc.myslicedemo"
         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
-        main_query.select(
-                # SLICE
-                'slice_hrn',
-                # - The record key is needed otherwise the storage of records
-                #   bugs !
-                'slice_urn',
-                # RESOURCES
-                'resource',
-                'lease',
-                'resource.urn',
-                'resource.hostname', 'resource.type',
-                # - The facility_name and testbed_name are required for the
-                #   testbeds plugin to properly work.
-                'resource.facility_name', 
-                'resource.testbed_name',
-                # LEASES
-                'lease.resource',
-                'lease.start_time',
-                'lease.end_time',
-                # - The lease_id is important for NITOS identify already existing
-                #   leases
-                'lease.lease_id', 
-
-                # FLOWSPACE
-                #'flowspace',               
-                # VMS
-                #'vms',
-
-
-                #'user.user_hrn',
-                #'application.measurement_point.counter'
-        )
+        main_query.select(slice_fields)
+
+        # Columns shown by default in Query_table plugin
+        page.expose_js_var("QUERYTABLE_MAP","{'Resource name': 'hostname', 'Type': 'type', 'Facility': 'facility_name','Testbed': 'testbed_name', 'Status':'boot_state'}")
+       
+        # Columns checked by default in Columns_selector plugin
+        query_default_fields = ['hostname', 'type', 'facility_name', 'testbed_name', 'boot_state']
+
+        QUERYTABLE_MAP = { 
+            'hostname'      :   'Resource name',
+            'type'          :   'Type',
+            'facility_name' :   'Facility',
+            'testbed_name'  :   'Testbed',
+            'boot_state'    :   'Status',
+        }
+
+
+        #        # SLICE
+        #        'slice_hrn',
+        #        # - The record key is needed otherwise the storage of records
+        #        #   bugs !
+        #        'slice_urn',
+        #        # RESOURCES
+        #        'resource',
+        #        'lease',
+        #        'resource.urn',
+        #        'resource.hostname', 'resource.type',
+        #        # - The facility_name and testbed_name are required for the
+        #        #   testbeds plugin to properly work.
+        #        'resource.facility_name',
+        #        'resource.testbed_name',
+        #        # LEASES
+        #        'lease.resource',
+        #        'lease.start_time',
+        #        'lease.end_time',
+        #        # - The lease_id is important for NITOS identify already existing
+        #        #   leases
+        #        'lease.lease_id',
+
+        #        # FLOWSPACE
+        #        #'flowspace',
+        #        # VMS
+        #        #'vms',
+
+
+        #        #'user.user_hrn',
+        #        #'application.measurement_point.counter'
+        #)
         # for internal use in the querytable plugin;
         # needs to be a unique column present for each returned record
         main_query_init_key = 'urn'
@@ -104,28 +133,20 @@ class SliceResourceView (LoginRequiredView, ThemeView):
         #sq_flowspace   = aq.subquery('flowspace')
         #sq_vms         = aq.subquery('vms')
 
-        query_resource_all = Query.get('resource').select(resource_fields)
-        page.enqueue_query(query_resource_all)
-
-        # leases query
-        #lease_md = metadata.details_by_object('lease')
-        #lease_fields = [column['name'] for column in lease_md['column']]
-
-        #query_lease_all = Query.get('lease').select(lease_fields)
-        #page.enqueue_query(query_lease_all)
-
         # --------------------------------------------------------------------------
         # ALL RESOURCES LIST
         # resources as a list using datatable plugin
  
-        list_resources = QueryTable(
-            page       = page,
-            domid      = 'resources-list',
-            title      = 'List view',
-            query      = sq_resource,
-            query_all  = query_resource_all,
-            init_key   = "urn",
-            checkboxes = True,
+        list_resources     = QueryTable(
+            page           = page,
+            domid          = 'resources-list',
+            title          = 'List view',
+            query          = sq_resource,
+            query_all      = query_resource_all,
+            mapping        = QUERYTABLE_MAP,
+            default_fields = query_default_fields,
+            init_key       = "urn",
+            checkboxes     = True,
             datatables_options = {
                 'iDisplayLength': 25,
                 'bLengthChange' : True,
@@ -176,6 +197,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             page  = page,
             query = sq_resource, 
             query_all = query_resource_all,
+            default_fields = query_default_fields,
             title = "Select Columns",
             domid = 'select-columns',
         )
index 023c206..254b676 100644 (file)
@@ -15,6 +15,9 @@ from ui.topmenu import topmenu_items, the_user
 from myslice.configengine import ConfigEngine
 
 from myslice.theme import ThemeView
+from myslice.configengine import ConfigEngine
+
+import urllib2,json
 
 class ExperimentView (FreeAccessView, ThemeView):
     template_name = 'slice-tab-experiment.html'
@@ -29,20 +32,70 @@ class ExperimentView (FreeAccessView, ThemeView):
         query_current_resources = Query.get('slice').select('resource').filter_by('slice_hrn','==',slicename)
         current_resources = execute_query(request, query_current_resources)
 
-        formatted_resource_list=[]
+        ple_resource_list=[]
+        nitos_resource_list=[]
+        nitos_paris_resource_list=[]
+        iotlab_resource_list=[]
         try:
             for resources in current_resources:
                 list_res = resources['resource']
+                #print "list_b4"
+                #print list_res
                 for res in list_res:
                     split_list = res.split('+') # split the resource urn
-                    if [s for s in split_list if 'ple' in s]: # search only ple resources
+                    #print "list_after"
+                    #print split_list
+                    if [s for s in split_list if 'ple' in s]: # find ple resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        ple_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:paris.fit-nitos.fr' in s]: # find nitos_paris resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        nitos_paris_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'iotlab' in s]: # find iotlab resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        iotlab_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:nitos.indoor' in s]: # find nitos_indoor resources
                         res_hrn = split_list[-1] # last element is resource hrn
-                        formatted_resource_list.append(res_hrn)
+                        nitos_resource_list.append(res_hrn)
+                    if [s for s in split_list if 'omf:nitos.outdoor' in s]: # find nitos_outdoor resources
+                        res_hrn = split_list[-1] # last element is resource hrn
+                        nitos_resource_list.append(res_hrn)
+
+
         except Exception,e:
-            print "Exception in slicetabexperiment.py in ple resource search %s" % e
+            print "Exception in slicetabexperiment.py in OneLab resource search %s" % e
         
-        print "list of ple resource hrns"
-        print formatted_resource_list
+        #print "list of ple res hrns"
+        #print ple_resource_list
+        #print "list of nit_paris res hrns"
+        #print nitos_paris_resource_list
+        #print "list of iotLab res hrns"
+        #print iotlab_resource_list
+        #print "list of nitos res hrns"
+        #print nitos_resource_list
+
+        #get all  iotlab users
+        try:
+            userData = "Basic " + (ConfigEngine.default_iotlab_admin_user + ":" + ConfigEngine.default_iotlab_admin_password).encode("base64").rstrip()
+            req = urllib2.Request(ConfigEngine.default_iotlab_url)
+            req.add_header('Accept', 'application/json')
+            req.add_header("Content-type", "application/x-www-form-urlencoded")
+            req.add_header('Authorization', userData)
+            # make the request and print the results
+            res = urllib2.urlopen(req)
+            all_users = json.load(res) 
+        except URLError as e:
+            print "There is a problem in getting iotlab users %s" % e.reason
+       
+        #print all_users 
 
-        return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'ple_resources':formatted_resource_list }, context_instance=RequestContext(request))
+        #getting the login from email
+        #initial value  no-account == contact_admin
+        iot_login = 'contact_admin'
+        username = str(username)
+        for user in all_users:
+            if user['email'] == username:
+                iot_login = user['login']
+            
+        return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'ple_resources':ple_resource_list, 'nitos_resources': nitos_resource_list, 'nitos_paris_resources':nitos_paris_resource_list, 'iotlab_resources':iotlab_resource_list, 'iot_login':iot_login }, context_instance=RequestContext(request))
 
index cfdf432..bcb2950 100644 (file)
@@ -56,14 +56,14 @@ table.profile tr td.value {
 }
 
 table.profile button { 
-  width: 80px;
+  width: 100px;
   vertical-align: middle;
   float: right;
   margin-right: 15px;
 }
 
 #delete {
-  width: 80px;
+  width: 100px;
   vertical-align: middle;
   float: right;
   margin-right: 15px;
@@ -71,7 +71,7 @@ table.profile button {
 }
 
 #upload_key {
-  width: 80px;
+  width: 100px;
   vertical-align: middle;
   float: right; 
   margin-right: 15px;
@@ -123,7 +123,7 @@ table.profile form{
 
 #generate_keypair {
   position:relative;
-  width: 175px;
+  width: 215px;
   float: right;
   margin-right: 15px;
 
@@ -143,7 +143,7 @@ table.profile form{
 }
 
 .wide_button {
-  width: 175px;
+  width: 215px;
 }
 
 .api_cell {
index 0b238d9..27c6b47 100644 (file)
@@ -715,7 +715,7 @@ div.home {
     line-height:1.2em;
     letter-spacing:0.3pt;
     min-height:500px;
-    background-image: url('../img/bg-experiment.png');
+    background-image: url('../img/bg-experiment.jpg');
     background-repeat:no-repeat;
     background-size:cover;
     background-position:center top;
diff --git a/portal/static/img/bg-experiment.jpg b/portal/static/img/bg-experiment.jpg
new file mode 100644 (file)
index 0000000..1fc35c1
Binary files /dev/null and b/portal/static/img/bg-experiment.jpg differ
diff --git a/portal/static/img/fed4fire_favicon.ico b/portal/static/img/fed4fire_favicon.ico
new file mode 100644 (file)
index 0000000..c2d91a0
Binary files /dev/null and b/portal/static/img/fed4fire_favicon.ico differ
diff --git a/portal/static/img/myslice_favicon.ico b/portal/static/img/myslice_favicon.ico
new file mode 100644 (file)
index 0000000..08b8cd4
Binary files /dev/null and b/portal/static/img/myslice_favicon.ico differ
diff --git a/portal/static/img/onelab_favicon.ico b/portal/static/img/onelab_favicon.ico
new file mode 100644 (file)
index 0000000..a2754aa
Binary files /dev/null and b/portal/static/img/onelab_favicon.ico differ
diff --git a/portal/static/img/putty-logo.png b/portal/static/img/putty-logo.png
new file mode 100644 (file)
index 0000000..cf0fec4
Binary files /dev/null and b/portal/static/img/putty-logo.png differ
diff --git a/portal/static/img/testbeds/omf.nitos.png b/portal/static/img/testbeds/omf.nitos.png
new file mode 100644 (file)
index 0000000..311fbbb
Binary files /dev/null and b/portal/static/img/testbeds/omf.nitos.png differ
diff --git a/portal/static/img/testbeds/paris.fit-nitos.fr.png b/portal/static/img/testbeds/paris.fit-nitos.fr.png
new file mode 100644 (file)
index 0000000..e21fc4b
Binary files /dev/null and b/portal/static/img/testbeds/paris.fit-nitos.fr.png differ
index bb0a197..8a39d47 100644 (file)
Binary files a/portal/static/img/testbeds/planetlab.png and b/portal/static/img/testbeds/planetlab.png differ
index d9593af..34a3516 100644 (file)
@@ -114,17 +114,44 @@ var myslice = {
                }
                return this.user;
        },
+    loadSlices: function(slices) {
+        if (typeof(slices) == "undefined"){
 
+            if(myslice.user != null && typeof(myslice.user.slices) != "undefined" && myslice.user.slices.length>0){
+                slices = myslice.user.slices
+            }
+        }
+        // myslice.user is in LocalStorage
+        if(typeof(slices) != "undefined"){
+            /*
+                Launch queries to get the resources and leases in Manifold Cache
+            */
+            $.post("/rest/resource/", function( data ) {
+            });
+            $.post("/rest/lease/", function( data ) {
+            });
+
+            $.each( slices, function(i, val) {
+                /*
+                Launch a Query for each slice to get resources and leases in Manifold Cache
+                */
+                $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
+                });
+            });
+        }
+
+    },
        login: function(fn) {
         user = localStorage.getItem('user');
         if($.isEmptyObject(user)){
-                   $.post("/rest/user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
+            // REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+                   $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'}}, function( data ) {
                            //myslice.user = new user(data[0]);
                            localStorage.setItem('user', JSON.stringify(data[0]));
+                myslice.loadSlices(data[0].slices);
                    });
         }
        },
-
     getSlices: function(name) {
        
     },
diff --git a/portal/static/reputation_static/css/delete.gif b/portal/static/reputation_static/css/delete.gif
new file mode 100644 (file)
index 0000000..43c6ca8
Binary files /dev/null and b/portal/static/reputation_static/css/delete.gif differ
diff --git a/portal/static/reputation_static/css/images/star-off.png b/portal/static/reputation_static/css/images/star-off.png
new file mode 100644 (file)
index 0000000..956fa7c
Binary files /dev/null and b/portal/static/reputation_static/css/images/star-off.png differ
diff --git a/portal/static/reputation_static/css/images/star-on.png b/portal/static/reputation_static/css/images/star-on.png
new file mode 100644 (file)
index 0000000..975fe7f
Binary files /dev/null and b/portal/static/reputation_static/css/images/star-on.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_flat_0_aaaaaa_40x100.png b/portal/static/reputation_static/css/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..5b5dab2
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_flat_75_ffffff_40x100.png b/portal/static/reputation_static/css/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644 (file)
index 0000000..ac8b229
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_glass_55_fbf9ee_1x400.png b/portal/static/reputation_static/css/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..ad3d634
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_glass_65_ffffff_1x400.png b/portal/static/reputation_static/css/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..42ccba2
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_glass_75_dadada_1x400.png b/portal/static/reputation_static/css/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..5a46b47
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_glass_75_e6e6e6_1x400.png b/portal/static/reputation_static/css/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_glass_95_fef1ec_1x400.png b/portal/static/reputation_static/css/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/portal/static/reputation_static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/portal/static/reputation_static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..7c9fa6c
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/portal/static/reputation_static/css/images/ui-icons_222222_256x240.png b/portal/static/reputation_static/css/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..b273ff1
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-icons_222222_256x240.png differ
diff --git a/portal/static/reputation_static/css/images/ui-icons_2e83ff_256x240.png b/portal/static/reputation_static/css/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..09d1cdc
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-icons_2e83ff_256x240.png differ
diff --git a/portal/static/reputation_static/css/images/ui-icons_454545_256x240.png b/portal/static/reputation_static/css/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..59bd45b
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-icons_454545_256x240.png differ
diff --git a/portal/static/reputation_static/css/images/ui-icons_888888_256x240.png b/portal/static/reputation_static/css/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..6d02426
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-icons_888888_256x240.png differ
diff --git a/portal/static/reputation_static/css/images/ui-icons_cd0a0a_256x240.png b/portal/static/reputation_static/css/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..2ab019b
Binary files /dev/null and b/portal/static/reputation_static/css/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/portal/static/reputation_static/css/jquery-ui-1.9.2.custom.min.css b/portal/static/reputation_static/css/jquery-ui-1.9.2.custom.min.css
new file mode 100644 (file)
index 0000000..5708cbc
--- /dev/null
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.9.2 - 2013-01-17
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.button.css, jquery.ui.dialog.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;zoom:1}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;zoom:1}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}* html .ui-tooltip{background-image:none}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
\ No newline at end of file
diff --git a/portal/static/reputation_static/css/jquery.rating.css b/portal/static/reputation_static/css/jquery.rating.css
new file mode 100644 (file)
index 0000000..50cf2e2
--- /dev/null
@@ -0,0 +1,12 @@
+/* jQuery.Rating Plugin CSS - http://www.fyneworks.com/jquery/star-rating/ */\r
+div.rating-cancel,div.star-rating{float:left;width:17px;height:15px;text-indent:-999em;cursor:pointer;display:block;background:transparent;overflow:hidden}\r
+div.rating-cancel,div.rating-cancel a{background:url(delete.gif) no-repeat 0 -16px}\r
+div.star-rating,div.star-rating a{background:url(star.gif) no-repeat 0 0px}\r
+div.rating-cancel a,div.star-rating a{display:block;width:16px;height:100%;background-position:0 0px;border:0}\r
+div.star-rating-on a{background-position:0 -16px!important}\r
+div.star-rating-hover a{background-position:0 -32px}\r
+/* Read Only CSS */\r
+div.star-rating-readonly a{cursor:default !important}\r
+/* Partial Star CSS */\r
+div.star-rating{background:transparent!important;overflow:hidden!important}\r
+/* END jQuery.Rating Plugin CSS */
\ No newline at end of file
diff --git a/portal/static/reputation_static/css/main.css b/portal/static/reputation_static/css/main.css
new file mode 100644 (file)
index 0000000..2f9dcbf
--- /dev/null
@@ -0,0 +1,196 @@
+/*\r
+*\r
+*/\r
+\r
+\r
+\r
+*{ margin: 0; padding: 0; }\r
+\r
+:focus,:active { outline: 0; }\r
+body {\r
+       font-family:"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;\r
+       font-size:12px;\r
+       color: #111; \r
+       background: #f7f7f7;\r
+}\r
+.registration_form {\r
+       margin:0 auto;\r
+       width:500px;\r
+       padding:14px;\r
+}\r
+label {\r
+       width: 10em;\r
+       float: left;\r
+       margin-right: 0.5em;\r
+       display: block\r
+}\r
+.submit {\r
+       float:right;\r
+}\r
+fieldset {\r
+       background:#EBF4FB none repeat scroll 0 0;\r
+       border:2px solid #B7DDF2;\r
+       width: 500px;\r
+}\r
+legend {\r
+       color: #fff;\r
+       background: #80D3E2;\r
+       border: 1px solid #781351;\r
+       padding: 2px 6px\r
+}\r
+.elements {\r
+       padding:10px;\r
+}\r
+p {\r
+       color:#666666;\r
+       font-size:13px;\r
+       margin-bottom:20px;\r
+       padding-bottom:10px;\r
+}\r
+a{\r
+    color:#0099FF;\r
+font-weight:bold;\r
+}\r
+\r
+/* Box Style */\r
+ .success, .warning, .errormsgbox, .validation {\r
+       border: 1px solid;\r
+       margin: 0 auto;\r
+       padding:10px 5px 10px 60px;\r
+       background-repeat: no-repeat;\r
+       background-position: 10px center;\r
+     font-weight:bold;\r
+     width:450px;\r
+     \r
+}\r
+.success {\r
+   \r
+       color: #4F8A10;\r
+       background-color: #DFF2BF;\r
+       background-image:url('../images/success.png');\r
+}\r
+.warning {\r
+\r
+       color: #9F6000;\r
+       background-color: #FEEFB3;\r
+       background-image: url('../images/warning.png');\r
+}\r
+.errormsgbox {\r
\r
+       color: #D8000C;\r
+       background-color: #FFBABA;\r
+       background-image: url('../images/error.png');\r
+       \r
+}\r
+.validation {\r
\r
+       color: #D63301;\r
+       background-color: #FFCCBA;\r
+       background-image: url('../images/error.png');\r
+}\r
+\r
+a { text-decoration: none; color: #000; }\r
+       a:hover { color: #000; }\r
+.x { clear: both; }\r
+\r
+p { line-height: 22px; margin: 0 0 22px; color:#666; }\r
+img { border: 0; }\r
+\r
+h1 { font-size: 24px; font-weight: normal; margin-bottom: 15px;}\r
+h2 { font-size: 14px; font-weight: normal; margin-bottom: 2px; color: #333; }\r
+h3 { font-size: 14px; font-weight: bolder; margin-bottom: 10px; color: #333; }\r
+h4 { font-size: 18px; font-weight: normal; float: left; margin: 3px 0 10px; width: 460px; }\r
+\r
+#wrapper { margin: 0 auto; width: 980px; background: url(../images/bg.jpg) no-repeat; }\r
+\r
+#logo { padding: 20px 12px 10px; }\r
+       #logo h1 { font: bold 24px Arial; text-shadow: 1px 1px 1px #fff; letter-spacing: 4px; }\r
+               #logo h1 a { color: #333; }\r
+               #logo h1 a span { color: #000; }\r
+#content { background: #fff; width: 980px; }\r
+       \r
+.menu { list-style:none; margin: 14px 25px 0 10px; width: 600px; float: left; }\r
+       .menu li { float: left; margin: 0 4px 0 0; }\r
+       .menu li a { display: block; font-size: 14px; padding: 14px 24px; border: 1px solid #fff; }\r
+       .menu a:hover, .menu li.current a { border: 1px solid #ddd; }\r
+\r
+               .menu li ul { display: block; background: #fff; margin: -1px 0 0; position: absolute; display: none; z-index: 2; border: 1px solid #ddd; }\r
+               .menu li ul li { float: none; display: inline; margin: 0; padding: 0; }\r
+               .menu li ul li a { width: auto; margin: 4px; white-space: nowrap; }\r
+\r
+#search { float: right; width: 275px; margin: 23px 18px; display: inline; }\r
+       #search .text { width: 227px; height: 16px; border: 1px solid #ddd; padding: 5px; float: left; color: #888; }\r
+       #search .submit { float: right; border: 0; background: #000 url(../images/search.gif) no-repeat center 8px; width: 32px; height: 28px; padding-top: 1px; }\r
+\r
+#pitch { margin-bottom: 30px; }\r
+       #pitch .infoline { margin-top: -70px; padding: 25px 0 25px 25px; background: #000; font-size: 18px; width: 955px; height: 18px; opacity:0.70; filter:alpha(opacity=70); color: #fff; }\r
+\r
+       .pitch-gallery { overflow: hidden; width: 980px; position: relative; }\r
+               .pitch-gallery-holder { width: 3920px; position: relative; top: 0; left: 0; }\r
+               .pitch-gallery-div { float: left; }\r
+               \r
+#left { width: 600px; float: left; margin-left: 25px; display: inline; }\r
+       #left img { float: left; margin: 5px 20px 2px 0; padding: 3px; border: 1px solid #ccc; }\r
+       #left form { padding-left: 45px; }\r
+       #left label { float: left; display: block; clear: both; padding: 3px 0; color: #666; font-weight: normal; width: 150px; }\r
+               #left .lcurrent { font-weight: bold; }\r
+       #left label img { vertical-align: middle; }\r
+       #left input.text, textarea, select { float: left; margin: 0 5px 10px 0; padding: 2px; width: 250px; border: 1px solid #ccc; }\r
+       #left textarea { height: 200px; }\r
+       #left select { width: 366px; }\r
+       #left input.radio {  }\r
+               #left input:focus { border-color:#aaa; }\r
+               #left textarea:focus { border-color: #aaa; }    \r
+       .error { font-size: 10px; color: #666; margin: 0 0 10px 150px; display: none; }\r
+       #left .submit { border: 0; background: #000; color: #fff; padding: 5px; float: left; margin-left: 150px; }\r
+       \r
+ul { color: #666; margin: 0 0 10px 10px; line-height: 18px; }\r
+ol { color: #666; margin: 5px 0 5px 30px; line-height: 18px; }\r
+       \r
+       #contact-back { margin: 12px 40px 0 0; float: right; }\r
+\r
+.post { position: relative; margin-bottom: 20px; height: 127px; }\r
+.post-options { position: relative; margin: -37px 0 40px 0; font-size: 10px; color: #666; }\r
+\r
+#right { width: 260px; float: right; border-left: 1px solid #ccc; padding-left: 36px; margin-right: 25px; display: inline; }\r
+       \r
+#feature { margin-left: 25px; padding-bottom: 10px; }\r
+       .small-post { float: left; width: 260px; margin-right: 75px; }\r
+               .small-post img { border: 1px solid #ccc; padding: 3px; margin-bottom: 10px; }\r
+       .last { margin-right: 0; }\r
+       #feature ul { margin-top: -11px; }\r
+       \r
+#footer { color: #666; font-size: 11px; margin: 20px 0 20px 10px; }\r
+\r
+.post-info { font-size: 11px; color: #999; }\r
+.read-more { background: url(../images/link.gif) no-repeat center left; padding-left: 13px; font-size: 10px; }\r
+.break { border-top: 1px solid #ccc; margin: 30px 0; display: block; }\r
+       .no-border { border: 0; }\r
+.space { margin-bottom: 20px; }\r
+\r
+.ui-widget-header {\r
+       background: transparent !important;\r
+       border: none !important;\r
+       border-bottom: 1px solid #AAA !important;\r
+       border-radius: 0px !important;\r
+}\r
+\r
+\r
+#tabs{\r
+       margin-top: 30px !important;\r
+       min-height: 700px;\r
+}\r
+\r
+\r
+#temp_log{\r
+       display: block;\r
+       width:700px;\r
+       height:500px;\r
+       overflow: auto;\r
+       background-color:grey;\r
+       color:white !important;\r
+       padding: 10px 10px 10px 10px;\r
+       margin-left:auto;\r
+       margin-right:auto;\r
+       \r
+}\r
diff --git a/portal/static/reputation_static/img/star-off.png b/portal/static/reputation_static/img/star-off.png
new file mode 100644 (file)
index 0000000..956fa7c
Binary files /dev/null and b/portal/static/reputation_static/img/star-off.png differ
diff --git a/portal/static/reputation_static/img/star-on.png b/portal/static/reputation_static/img/star-on.png
new file mode 100644 (file)
index 0000000..975fe7f
Binary files /dev/null and b/portal/static/reputation_static/img/star-on.png differ
diff --git a/portal/static/reputation_static/img/star.gif b/portal/static/reputation_static/img/star.gif
new file mode 100644 (file)
index 0000000..d0948a7
Binary files /dev/null and b/portal/static/reputation_static/img/star.gif differ
diff --git a/portal/static/reputation_static/js/jquery-1.9.0.min.js b/portal/static/reputation_static/js/jquery-1.9.0.min.js
new file mode 100644 (file)
index 0000000..50d1b22
--- /dev/null
@@ -0,0 +1,4 @@
+/*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(cn[0].contentWindow||cn[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=A(e,t),cn.detach()),bn[e]=n),n}function A(e,t){var n=st(t.createElement(e)).appendTo(t.body),r=st.css(n[0],"display");return n.remove(),r}function j(e,t,n,r){var i;if(st.isArray(t))st.each(t,function(t,i){n||kn.test(e)?r(e,i):j(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==st.type(t))r(e,t);else for(i in t)j(e+"["+i+"]",t[i],n,r)}function D(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(lt)||[];if(st.isFunction(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function L(e,n,r,i){function o(u){var l;return a[u]=!0,st.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||s||a[c]?s?!(l=c):t:(n.dataTypes.unshift(c),o(c),!1)}),l}var a={},s=e===$n;return o(n.dataTypes[0])||!a["*"]&&o("*")}function H(e,n){var r,i,o=st.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((o[r]?e:i||(i={}))[r]=n[r]);return i&&st.extend(!0,e,i),e}function M(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(o in c)o in r&&(n[c[o]]=r[o]);for(;"*"===l[0];)l.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("Content-Type"));if(i)for(o in u)if(u[o]&&u[o].test(i)){l.unshift(o);break}if(l[0]in r)a=l[0];else{for(o in r){if(!l[0]||e.converters[o+" "+l[0]]){a=o;break}s||(s=o)}a=a||s}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function q(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=u[++s];)if("*"!==i){if("*"!==l&&l!==i){if(n=a[l+" "+i]||a["* "+i],!n)for(r in a)if(o=r.split(" "),o[1]===i&&(n=a[l+" "+o[0]]||a["* "+o[0]])){n===!0?n=a[r]:a[r]!==!0&&(i=o[0],u.splice(s--,0,i));break}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(c){return{state:"parsererror",error:n?c:"No conversion from "+l+" to "+i}}}l=i}return{state:"success",data:t}}function _(){try{return new e.XMLHttpRequest}catch(t){}}function F(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function O(){return setTimeout(function(){Qn=t}),Qn=st.now()}function B(e,t){st.each(t,function(t,n){for(var r=(rr[t]||[]).concat(rr["*"]),i=0,o=r.length;o>i;i++)if(r[i].call(e,t,n))return})}function P(e,t,n){var r,i,o=0,a=nr.length,s=st.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Qn||O(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:st.extend({},t),opts:st.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Qn||O(),duration:n.duration,tweens:[],createTween:function(t,n){var r=st.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(R(c,l.opts.specialEasing);a>o;o++)if(r=nr[o].call(l,e,c,l.opts))return r;return B(l,c),st.isFunction(l.opts.start)&&l.opts.start.call(e,l),st.fx.timer(st.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function R(e,t){var n,r,i,o,a;for(n in e)if(r=st.camelCase(n),i=t[r],o=e[n],st.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=st.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function W(e,t,n){var r,i,o,a,s,u,l,c,f,p=this,d=e.style,h={},g=[],m=e.nodeType&&w(e);n.queue||(c=st._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,f=c.empty.fire,c.empty.fire=function(){c.unqueued||f()}),c.unqueued++,p.always(function(){p.always(function(){c.unqueued--,st.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===st.css(e,"display")&&"none"===st.css(e,"float")&&(st.support.inlineBlockNeedsLayout&&"inline"!==S(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",st.support.shrinkWrapBlocks||p.done(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(r in t)if(o=t[r],Zn.exec(o)){if(delete t[r],u=u||"toggle"===o,o===(m?"hide":"show"))continue;g.push(r)}if(a=g.length){s=st._data(e,"fxshow")||st._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?st(e).show():p.done(function(){st(e).hide()}),p.done(function(){var t;st._removeData(e,"fxshow");for(t in h)st.style(e,t,h[t])});for(r=0;a>r;r++)i=g[r],l=p.createTween(i,m?s[i]:0),h[i]=s[i]||st.style(e,i),i in s||(s[i]=l.start,m&&(l.end=l.start,l.start="width"===i||"height"===i?1:0))}}function $(e,t,n,r,i){return new $.prototype.init(e,t,n,r,i)}function I(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=wn[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function z(e){return st.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}var X,U,V=e.document,Y=e.location,J=e.jQuery,G=e.$,Q={},K=[],Z="1.9.0",et=K.concat,tt=K.push,nt=K.slice,rt=K.indexOf,it=Q.toString,ot=Q.hasOwnProperty,at=Z.trim,st=function(e,t){return new st.fn.init(e,t,X)},ut=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,lt=/\S+/g,ct=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,ft=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,pt=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,dt=/^[\],:{}\s]*$/,ht=/(?:^|:|,)(?:\s*\[)+/g,gt=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,mt=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,yt=/^-ms-/,vt=/-([\da-z])/gi,bt=function(e,t){return t.toUpperCase()},xt=function(){V.addEventListener?(V.removeEventListener("DOMContentLoaded",xt,!1),st.ready()):"complete"===V.readyState&&(V.detachEvent("onreadystatechange",xt),st.ready())};st.fn=st.prototype={jquery:Z,constructor:st,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:ft.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof st?n[0]:n,st.merge(this,st.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:V,!0)),pt.test(i[1])&&st.isPlainObject(n))for(i in n)st.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=V.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=V,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):st.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),st.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return nt.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=st.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return st.each(this,e,t)},ready:function(e){return st.ready.promise().done(e),this},slice:function(){return this.pushStack(nt.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(st.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:tt,sort:[].sort,splice:[].splice},st.fn.init.prototype=st.fn,st.extend=st.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||st.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(e=arguments[u]))for(n in e)r=s[n],i=e[n],s!==i&&(c&&i&&(st.isPlainObject(i)||(o=st.isArray(i)))?(o?(o=!1,a=r&&st.isArray(r)?r:[]):a=r&&st.isPlainObject(r)?r:{},s[n]=st.extend(c,a,i)):i!==t&&(s[n]=i));return s},st.extend({noConflict:function(t){return e.$===st&&(e.$=G),t&&e.jQuery===st&&(e.jQuery=J),st},isReady:!1,readyWait:1,holdReady:function(e){e?st.readyWait++:st.ready(!0)},ready:function(e){if(e===!0?!--st.readyWait:!st.isReady){if(!V.body)return setTimeout(st.ready);st.isReady=!0,e!==!0&&--st.readyWait>0||(U.resolveWith(V,[st]),st.fn.trigger&&st(V).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===st.type(e)},isArray:Array.isArray||function(e){return"array"===st.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?Q[it.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==st.type(e)||e.nodeType||st.isWindow(e))return!1;try{if(e.constructor&&!ot.call(e,"constructor")&&!ot.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||ot.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||V;var r=pt.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=st.buildFragment([e],t,i),i&&st(i).remove(),st.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=st.trim(n),n&&dt.test(n.replace(gt,"@").replace(mt,"]").replace(ht,"")))?Function("return "+n)():(st.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||st.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&st.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(yt,"ms-").replace(vt,bt)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,r){var i,o=0,a=e.length,s=n(e);if(r){if(s)for(;a>o&&(i=t.apply(e[o],r),i!==!1);o++);else for(o in e)if(i=t.apply(e[o],r),i===!1)break}else if(s)for(;a>o&&(i=t.call(e[o],o,e[o]),i!==!1);o++);else for(o in e)if(i=t.call(e[o],o,e[o]),i===!1)break;return e},trim:at&&!at.call("\ufeff\u00a0")?function(e){return null==e?"":at.call(e)}:function(e){return null==e?"":(e+"").replace(ct,"")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?st.merge(r,"string"==typeof e?[e]:e):tt.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(rt)return rt.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else for(;n[o]!==t;)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,r){var i,o=0,a=e.length,s=n(e),u=[];if(s)for(;a>o;o++)i=t(e[o],o,r),null!=i&&(u[u.length]=i);else for(o in e)i=t(e[o],o,r),null!=i&&(u[u.length]=i);return et.apply([],u)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(r=e[n],n=e,e=r),st.isFunction(e)?(i=nt.call(arguments,2),o=function(){return e.apply(n||this,i.concat(nt.call(arguments)))},o.guid=e.guid=e.guid||st.guid++,o):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===st.type(r)){o=!0;for(u in r)st.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,st.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(st(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),st.ready.promise=function(t){if(!U)if(U=st.Deferred(),"complete"===V.readyState)setTimeout(st.ready);else if(V.addEventListener)V.addEventListener("DOMContentLoaded",xt,!1),e.addEventListener("load",st.ready,!1);else{V.attachEvent("onreadystatechange",xt),e.attachEvent("onload",st.ready);var n=!1;try{n=null==e.frameElement&&V.documentElement}catch(r){}n&&n.doScroll&&function i(){if(!st.isReady){try{n.doScroll("left")}catch(e){return setTimeout(i,50)}st.ready()}}()}return U.promise(t)},st.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){Q["[object "+t+"]"]=t.toLowerCase()}),X=st(V);var Tt={};st.Callbacks=function(e){e="string"==typeof e?Tt[e]||r(e):st.extend({},e);var n,i,o,a,s,u,l=[],c=!e.once&&[],f=function(t){for(n=e.memory&&t,i=!0,u=a||0,a=0,s=l.length,o=!0;l&&s>u;u++)if(l[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}o=!1,l&&(c?c.length&&f(c.shift()):n?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function r(t){st.each(t,function(t,n){var i=st.type(n);"function"===i?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==i&&r(n)})})(arguments),o?s=l.length:n&&(a=t,f(n))}return this},remove:function(){return l&&st.each(arguments,function(e,t){for(var n;(n=st.inArray(t,l,n))>-1;)l.splice(n,1),o&&(s>=n&&s--,u>=n&&u--)}),this},has:function(e){return st.inArray(e,l)>-1},empty:function(){return l=[],this},disable:function(){return l=c=n=t,this},disabled:function(){return!l},lock:function(){return c=t,n||p.disable(),this},locked:function(){return!c},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!c||(o?c.push(t):f(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},st.extend({Deferred:function(e){var t=[["resolve","done",st.Callbacks("once memory"),"resolved"],["reject","fail",st.Callbacks("once memory"),"rejected"],["notify","progress",st.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return st.Deferred(function(n){st.each(t,function(t,o){var a=o[0],s=st.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&st.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?st.extend(e,r):r}},i={};return r.pipe=r.then,st.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=nt.call(arguments),a=o.length,s=1!==a||e&&st.isFunction(e.promise)?a:0,u=1===s?e:st.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?nt.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=Array(a),n=Array(a),r=Array(a);a>i;i++)o[i]&&st.isFunction(o[i].promise)?o[i].promise().done(l(i,r,o)).fail(u.reject).progress(l(i,n,t)):--s;return s||u.resolveWith(r,o),u.promise()}}),st.support=function(){var n,r,i,o,a,s,u,l,c,f,p=V.createElement("div");if(p.setAttribute("className","t"),p.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",r=p.getElementsByTagName("*"),i=p.getElementsByTagName("a")[0],!r||!i||!r.length)return{};o=V.createElement("select"),a=o.appendChild(V.createElement("option")),s=p.getElementsByTagName("input")[0],i.style.cssText="top:1px;float:left;opacity:.5",n={getSetAttribute:"t"!==p.className,leadingWhitespace:3===p.firstChild.nodeType,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(i.getAttribute("style")),hrefNormalized:"/a"===i.getAttribute("href"),opacity:/^0.5/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:!!s.value,optSelected:a.selected,enctype:!!V.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==V.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===V.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},s.checked=!0,n.noCloneChecked=s.cloneNode(!0).checked,o.disabled=!0,n.optDisabled=!a.disabled;try{delete p.test}catch(d){n.deleteExpando=!1}s=V.createElement("input"),s.setAttribute("value",""),n.input=""===s.getAttribute("value"),s.value="t",s.setAttribute("type","radio"),n.radioValue="t"===s.value,s.setAttribute("checked","t"),s.setAttribute("name","t"),u=V.createDocumentFragment(),u.appendChild(s),n.appendChecked=s.checked,n.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,p.attachEvent&&(p.attachEvent("onclick",function(){n.noCloneEvent=!1}),p.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})p.setAttribute(l="on"+f,"t"),n[f+"Bubbles"]=l in e||p.attributes[l].expando===!1;return p.style.backgroundClip="content-box",p.cloneNode(!0).style.backgroundClip="",n.clearCloneStyle="content-box"===p.style.backgroundClip,st(function(){var r,i,o,a="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",s=V.getElementsByTagName("body")[0];s&&(r=V.createElement("div"),r.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",s.appendChild(r).appendChild(p),p.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=p.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",c=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",n.reliableHiddenOffsets=c&&0===o[0].offsetHeight,p.innerHTML="",p.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",n.boxSizing=4===p.offsetWidth,n.doesNotIncludeMarginInBodyOffset=1!==s.offsetTop,e.getComputedStyle&&(n.pixelPosition="1%"!==(e.getComputedStyle(p,null)||{}).top,n.boxSizingReliable="4px"===(e.getComputedStyle(p,null)||{width:"4px"}).width,i=p.appendChild(V.createElement("div")),i.style.cssText=p.style.cssText=a,i.style.marginRight=i.style.width="0",p.style.width="1px",n.reliableMarginRight=!parseFloat((e.getComputedStyle(i,null)||{}).marginRight)),p.style.zoom!==t&&(p.innerHTML="",p.style.cssText=a+"width:1px;padding:1px;display:inline;zoom:1",n.inlineBlockNeedsLayout=3===p.offsetWidth,p.style.display="block",p.innerHTML="<div></div>",p.firstChild.style.width="5px",n.shrinkWrapBlocks=3!==p.offsetWidth,s.style.zoom=1),s.removeChild(r),r=p=o=i=null)}),r=o=u=a=i=s=null,n}();var wt=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,Nt=/([A-Z])/g;st.extend({cache:{},expando:"jQuery"+(Z+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?st.cache[e[st.expando]]:e[st.expando],!!e&&!s(e)},data:function(e,t,n){return i(e,t,n,!1)},removeData:function(e,t){return o(e,t,!1)},_data:function(e,t,n){return i(e,t,n,!0)},_removeData:function(e,t){return o(e,t,!0)},acceptData:function(e){var t=e.nodeName&&st.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),st.fn.extend({data:function(e,n){var r,i,o=this[0],s=0,u=null;if(e===t){if(this.length&&(u=st.data(o),1===o.nodeType&&!st._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>s;s++)i=r[s].name,i.indexOf("data-")||(i=st.camelCase(i.substring(5)),a(o,i,u[i]));st._data(o,"parsedAttrs",!0)}return u}return"object"==typeof e?this.each(function(){st.data(this,e)}):st.access(this,function(n){return n===t?o?a(o,e,st.data(o,e)):null:(this.each(function(){st.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){st.removeData(this,e)})}}),st.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=st._data(e,n),r&&(!i||st.isArray(r)?i=st._data(e,n,st.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=st.queue(e,t),r=n.length,i=n.shift(),o=st._queueHooks(e,t),a=function(){st.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return st._data(e,n)||st._data(e,n,{empty:st.Callbacks("once memory").add(function(){st._removeData(e,t+"queue"),st._removeData(e,n)})})}}),st.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?st.queue(this[0],e):n===t?this:this.each(function(){var t=st.queue(this,e,n);st._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&st.dequeue(this,e)})},dequeue:function(e){return this.each(function(){st.dequeue(this,e)})},delay:function(e,t){return e=st.fx?st.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=st.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};for("string"!=typeof e&&(n=e,e=t),e=e||"fx";s--;)r=st._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var Ct,kt,Et=/[\t\r\n]/g,St=/\r/g,At=/^(?:input|select|textarea|button|object)$/i,jt=/^(?:a|area)$/i,Dt=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,Lt=/^(?:checked|selected)$/i,Ht=st.support.getSetAttribute,Mt=st.support.input;st.fn.extend({attr:function(e,t){return st.access(this,st.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){st.removeAttr(this,e)})},prop:function(e,t){return st.access(this,st.prop,e,t,arguments.length>1)},removeProp:function(e){return e=st.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(st.isFunction(e))return this.each(function(t){st(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(lt)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Et," "):" ")){for(o=0;i=t[o++];)0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=st.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(st.isFunction(e))return this.each(function(t){st(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(lt)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Et," "):"")){for(o=0;i=t[o++];)for(;r.indexOf(" "+i+" ")>=0;)r=r.replace(" "+i+" "," ");n.className=e?st.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return st.isFunction(e)?this.each(function(n){st(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n)for(var i,o=0,a=st(this),s=t,u=e.match(lt)||[];i=u[o++];)s=r?s:!a.hasClass(i),a[s?"addClass":"removeClass"](i);else("undefined"===n||"boolean"===n)&&(this.className&&st._data(this,"__className__",this.className),this.className=this.className||e===!1?"":st._data(this,"__className__")||"")})},hasClass:function(e){for(var t=" "+e+" ",n=0,r=this.length;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(Et," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=st.isFunction(e),this.each(function(r){var o,a=st(this);1===this.nodeType&&(o=i?e.call(this,r,a.val()):e,null==o?o="":"number"==typeof o?o+="":st.isArray(o)&&(o=st.map(o,function(e){return null==e?"":e+""})),n=st.valHooks[this.type]||st.valHooks[this.nodeName.toLowerCase()],n&&"set"in n&&n.set(this,o,"value")!==t||(this.value=o))});if(o)return n=st.valHooks[o.type]||st.valHooks[o.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(o,"value"))!==t?r:(r=o.value,"string"==typeof r?r.replace(St,""):null==r?"":r)}}}),st.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(st.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&st.nodeName(n.parentNode,"optgroup"))){if(t=st(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=st.makeArray(t);return st(e).find("option").each(function(){this.selected=st.inArray(st(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return e.getAttribute===t?st.prop(e,n,r):(a=1!==s||!st.isXMLDoc(e),a&&(n=n.toLowerCase(),o=st.attrHooks[n]||(Dt.test(n)?kt:Ct)),r===t?o&&a&&"get"in o&&null!==(i=o.get(e,n))?i:(e.getAttribute!==t&&(i=e.getAttribute(n)),null==i?t:i):null!==r?o&&a&&"set"in o&&(i=o.set(e,r,n))!==t?i:(e.setAttribute(n,r+""),r):(st.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(lt);if(o&&1===e.nodeType)for(;n=o[i++];)r=st.propFix[n]||n,Dt.test(n)?!Ht&&Lt.test(n)?e[st.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:st.attr(e,n,""),e.removeAttribute(Ht?n:r)},attrHooks:{type:{set:function(e,t){if(!st.support.radioValue&&"radio"===t&&st.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!st.isXMLDoc(e),a&&(n=st.propFix[n]||n,o=st.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):At.test(e.nodeName)||jt.test(e.nodeName)&&e.href?0:t}}}}),kt={get:function(e,n){var r=st.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?Mt&&Ht?null!=i:Lt.test(n)?e[st.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?st.removeAttr(e,n):Mt&&Ht||!Lt.test(n)?e.setAttribute(!Ht&&st.propFix[n]||n,n):e[st.camelCase("default-"+n)]=e[n]=!0,n}},Mt&&Ht||(st.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return st.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t
+},set:function(e,n,r){return st.nodeName(e,"input")?(e.defaultValue=n,t):Ct&&Ct.set(e,n,r)}}),Ht||(Ct=st.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},st.attrHooks.contenteditable={get:Ct.get,set:function(e,t,n){Ct.set(e,""===t?!1:t,n)}},st.each(["width","height"],function(e,n){st.attrHooks[n]=st.extend(st.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),st.support.hrefNormalized||(st.each(["href","src","width","height"],function(e,n){st.attrHooks[n]=st.extend(st.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),st.each(["href","src"],function(e,t){st.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),st.support.style||(st.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),st.support.optSelected||(st.propHooks.selected=st.extend(st.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),st.support.enctype||(st.propFix.enctype="encoding"),st.support.checkOn||st.each(["radio","checkbox"],function(){st.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),st.each(["radio","checkbox"],function(){st.valHooks[this]=st.extend(st.valHooks[this],{set:function(e,n){return st.isArray(n)?e.checked=st.inArray(st(e).val(),n)>=0:t}})});var qt=/^(?:input|select|textarea)$/i,_t=/^key/,Ft=/^(?:mouse|contextmenu)|click/,Ot=/^(?:focusinfocus|focusoutblur)$/,Bt=/^([^.]*)(?:\.(.+)|)$/;st.event={global:{},add:function(e,n,r,i,o){var a,s,u,l,c,f,p,d,h,g,m,y=3!==e.nodeType&&8!==e.nodeType&&st._data(e);if(y){for(r.handler&&(a=r,r=a.handler,o=a.selector),r.guid||(r.guid=st.guid++),(l=y.events)||(l=y.events={}),(s=y.handle)||(s=y.handle=function(e){return st===t||e&&st.event.triggered===e.type?t:st.event.dispatch.apply(s.elem,arguments)},s.elem=e),n=(n||"").match(lt)||[""],c=n.length;c--;)u=Bt.exec(n[c])||[],h=m=u[1],g=(u[2]||"").split(".").sort(),p=st.event.special[h]||{},h=(o?p.delegateType:p.bindType)||h,p=st.event.special[h]||{},f=st.extend({type:h,origType:m,data:i,handler:r,guid:r.guid,selector:o,needsContext:o&&st.expr.match.needsContext.test(o),namespace:g.join(".")},a),(d=l[h])||(d=l[h]=[],d.delegateCount=0,p.setup&&p.setup.call(e,i,g,s)!==!1||(e.addEventListener?e.addEventListener(h,s,!1):e.attachEvent&&e.attachEvent("on"+h,s))),p.add&&(p.add.call(e,f),f.handler.guid||(f.handler.guid=r.guid)),o?d.splice(d.delegateCount++,0,f):d.push(f),st.event.global[h]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,m=st.hasData(e)&&st._data(e);if(m&&(u=m.events)){for(t=(t||"").match(lt)||[""],l=t.length;l--;)if(s=Bt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){for(f=st.event.special[d]||{},d=(r?f.delegateType:f.bindType)||d,p=u[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||st.removeEvent(e,d,m.handle),delete u[d])}else for(d in u)st.event.remove(e,d+t[l],n,r,!0);st.isEmptyObject(u)&&(delete m.handle,st._removeData(e,"events"))}},trigger:function(n,r,i,o){var a,s,u,l,c,f,p,d=[i||V],h=n.type||n,g=n.namespace?n.namespace.split("."):[];if(s=u=i=i||V,3!==i.nodeType&&8!==i.nodeType&&!Ot.test(h+st.event.triggered)&&(h.indexOf(".")>=0&&(g=h.split("."),h=g.shift(),g.sort()),c=0>h.indexOf(":")&&"on"+h,n=n[st.expando]?n:new st.Event(h,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=g.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:st.makeArray(r,[n]),p=st.event.special[h]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!st.isWindow(i)){for(l=p.delegateType||h,Ot.test(l+h)||(s=s.parentNode);s;s=s.parentNode)d.push(s),u=s;u===(i.ownerDocument||V)&&d.push(u.defaultView||u.parentWindow||e)}for(a=0;(s=d[a++])&&!n.isPropagationStopped();)n.type=a>1?l:p.bindType||h,f=(st._data(s,"events")||{})[n.type]&&st._data(s,"handle"),f&&f.apply(s,r),f=c&&s[c],f&&st.acceptData(s)&&f.apply&&f.apply(s,r)===!1&&n.preventDefault();if(n.type=h,!(o||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===h&&st.nodeName(i,"a")||!st.acceptData(i)||!c||!i[h]||st.isWindow(i))){u=i[c],u&&(i[c]=null),st.event.triggered=h;try{i[h]()}catch(m){}st.event.triggered=t,u&&(i[c]=u)}return n.result}},dispatch:function(e){e=st.event.fix(e);var n,r,i,o,a,s=[],u=nt.call(arguments),l=(st._data(this,"events")||{})[e.type]||[],c=st.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){for(s=st.event.handlers.call(this,e,l),n=0;(o=s[n++])&&!e.isPropagationStopped();)for(e.currentTarget=o.elem,r=0;(a=o.handlers[r++])&&!e.isImmediatePropagationStopped();)(!e.namespace_re||e.namespace_re.test(a.namespace))&&(e.handleObj=a,e.data=a.data,i=((st.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u),i!==t&&(e.result=i)===!1&&(e.preventDefault(),e.stopPropagation()));return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(l.disabled!==!0||"click"!==e.type){for(i=[],r=0;u>r;r++)a=n[r],o=a.selector+" ",i[o]===t&&(i[o]=a.needsContext?st(o,this).index(l)>=0:st.find(o,this,null,[l]).length),i[o]&&i.push(a);i.length&&s.push({elem:l,handlers:i})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[st.expando])return e;var t,n,r=e,i=st.event.fixHooks[e.type]||{},o=i.props?this.props.concat(i.props):this.props;for(e=new st.Event(r),t=o.length;t--;)n=o[t],e[n]=r[n];return e.target||(e.target=r.srcElement||V),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,i.filter?i.filter(e,r):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,a=n.button,s=n.fromElement;return null==e.pageX&&null!=n.clientX&&(r=e.target.ownerDocument||V,i=r.documentElement,o=r.body,e.pageX=n.clientX+(i&&i.scrollLeft||o&&o.scrollLeft||0)-(i&&i.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(i&&i.scrollTop||o&&o.scrollTop||0)-(i&&i.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&s&&(e.relatedTarget=s===e.target?n.toElement:s),e.which||a===t||(e.which=1&a?1:2&a?3:4&a?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return st.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==V.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===V.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=st.extend(new st.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?st.event.trigger(i,null,t):st.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},st.removeEvent=V.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,n,r){var i="on"+n;e.detachEvent&&(e[i]===t&&(e[i]=null),e.detachEvent(i,r))},st.Event=function(e,n){return this instanceof st.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?u:l):this.type=e,n&&st.extend(this,n),this.timeStamp=e&&e.timeStamp||st.now(),this[st.expando]=!0,t):new st.Event(e,n)},st.Event.prototype={isDefaultPrevented:l,isPropagationStopped:l,isImmediatePropagationStopped:l,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=u,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=u,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u,this.stopPropagation()}},st.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){st.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!st.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),st.support.submitBubbles||(st.event.special.submit={setup:function(){return st.nodeName(this,"form")?!1:(st.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=st.nodeName(n,"input")||st.nodeName(n,"button")?n.form:t;r&&!st._data(r,"submitBubbles")&&(st.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),st._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&st.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return st.nodeName(this,"form")?!1:(st.event.remove(this,"._submit"),t)}}),st.support.changeBubbles||(st.event.special.change={setup:function(){return qt.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(st.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),st.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),st.event.simulate("change",this,e,!0)})),!1):(st.event.add(this,"beforeactivate._change",function(e){var t=e.target;qt.test(t.nodeName)&&!st._data(t,"changeBubbles")&&(st.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||st.event.simulate("change",this.parentNode,e,!0)}),st._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return st.event.remove(this,"._change"),!qt.test(this.nodeName)}}),st.support.focusinBubbles||st.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){st.event.simulate(t,e.target,st.event.fix(e),!0)};st.event.special[t]={setup:function(){0===n++&&V.addEventListener(e,r,!0)},teardown:function(){0===--n&&V.removeEventListener(e,r,!0)}}}),st.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(s in e)this.on(s,n,r,e[s],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=l;else if(!i)return this;return 1===o&&(a=i,i=function(e){return st().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=st.guid++)),this.each(function(){st.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,st(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=l),this.each(function(){st.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){st.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?st.event.trigger(e,n,r,!0):t},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),st.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){st.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)},_t.test(t)&&(st.event.fixHooks[t]=st.event.keyHooks),Ft.test(t)&&(st.event.fixHooks[t]=st.event.mouseHooks)}),function(e,t){function n(e){return ht.test(e+"")}function r(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>C.cacheLength&&delete e[t.shift()],e[n]=r}}function i(e){return e[P]=!0,e}function o(e){var t=L.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function a(e,t,n,r){var i,o,a,s,u,l,c,d,h,g;if((t?t.ownerDocument||t:R)!==L&&D(t),t=t||L,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!M&&!r){if(i=gt.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&O(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Q.apply(n,K.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&W.getByClassName&&t.getElementsByClassName)return Q.apply(n,K.call(t.getElementsByClassName(a),0)),n}if(W.qsa&&!q.test(e)){if(c=!0,d=P,h=t,g=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(l=f(e),(c=t.getAttribute("id"))?d=c.replace(vt,"\\$&"):t.setAttribute("id",d),d="[id='"+d+"'] ",u=l.length;u--;)l[u]=d+p(l[u]);h=dt.test(e)&&t.parentNode||t,g=l.join(",")}if(g)try{return Q.apply(n,K.call(h.querySelectorAll(g),0)),n}catch(m){}finally{c||t.removeAttribute("id")}}}return x(e.replace(at,"$1"),t,n,r)}function s(e,t){for(var n=e&&t&&e.nextSibling;n;n=n.nextSibling)if(n===t)return-1;return e?1:-1}function u(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function c(e){return i(function(t){return t=+t,i(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function f(e,t){var n,r,i,o,s,u,l,c=X[e+" "];if(c)return t?0:c.slice(0);for(s=e,u=[],l=C.preFilter;s;){(!n||(r=ut.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(i=[])),n=!1,(r=lt.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(at," ")}),s=s.slice(n.length));for(o in C.filter)!(r=pt[o].exec(s))||l[o]&&!(r=l[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?a.error(e):X(e,u).slice(0)}function p(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function d(e,t,n){var r=t.dir,i=n&&"parentNode"===t.dir,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=$+" "+o;if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i)if(l=t[P]||(t[P]={}),(u=l[r])&&u[0]===c){if((s=u[1])===!0||s===N)return s===!0}else if(u=l[r]=[c],u[1]=e(t,n,a)||N,u[1]===!0)return!0}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function m(e,t,n,r,o,a){return r&&!r[P]&&(r=m(r)),o&&!o[P]&&(o=m(o,a)),i(function(i,a,s,u){var l,c,f,p=[],d=[],h=a.length,m=i||b(t||"*",s.nodeType?[s]:s,[]),y=!e||!i&&t?m:g(m,p,e,s,u),v=n?o||(i?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r)for(l=g(v,d),r(l,[],s,u),c=l.length;c--;)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f));if(i){if(o||e){if(o){for(l=[],c=v.length;c--;)(f=v[c])&&l.push(y[c]=f);o(null,v=[],l,u)}for(c=v.length;c--;)(f=v[c])&&(l=o?Z.call(i,f):p[c])>-1&&(i[l]=!(a[l]=f))}}else v=g(v===a?v.splice(h,v.length):v),o?o(null,a,v,u):Q.apply(a,v)})}function y(e){for(var t,n,r,i=e.length,o=C.relative[e[0].type],a=o||C.relative[" "],s=o?1:0,u=d(function(e){return e===t},a,!0),l=d(function(e){return Z.call(t,e)>-1},a,!0),c=[function(e,n,r){return!o&&(r||n!==j)||((t=n).nodeType?u(e,n,r):l(e,n,r))}];i>s;s++)if(n=C.relative[e[s].type])c=[d(h(c),n)];else{if(n=C.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;i>r&&!C.relative[e[r].type];r++);return m(s>1&&h(c),s>1&&p(e.slice(0,s-1)).replace(at,"$1"),n,r>s&&y(e.slice(s,r)),i>r&&y(e=e.slice(r)),i>r&&p(e))}c.push(n)}return h(c)}function v(e,t){var n=0,r=t.length>0,o=e.length>0,s=function(i,s,u,l,c){var f,p,d,h=[],m=0,y="0",v=i&&[],b=null!=c,x=j,T=i||o&&C.find.TAG("*",c&&s.parentNode||s),w=$+=null==x?1:Math.E;for(b&&(j=s!==L&&s,N=n);null!=(f=T[y]);y++){if(o&&f){for(p=0;d=e[p];p++)if(d(f,s,u)){l.push(f);break}b&&($=w,N=++n)}r&&((f=!d&&f)&&m--,i&&v.push(f))}if(m+=y,r&&y!==m){for(p=0;d=t[p];p++)d(v,h,s,u);if(i){if(m>0)for(;y--;)v[y]||h[y]||(h[y]=G.call(l));h=g(h)}Q.apply(l,h),b&&!i&&h.length>0&&m+t.length>1&&a.uniqueSort(l)}return b&&($=w,j=x),v};return r?i(s):s}function b(e,t,n){for(var r=0,i=t.length;i>r;r++)a(e,t[r],n);return n}function x(e,t,n,r){var i,o,a,s,u,l=f(e);if(!r&&1===l.length){if(o=l[0]=l[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&9===t.nodeType&&!M&&C.relative[o[1].type]){if(t=C.find.ID(a.matches[0].replace(xt,Tt),t)[0],!t)return n;e=e.slice(o.shift().value.length)}for(i=pt.needsContext.test(e)?-1:o.length-1;i>=0&&(a=o[i],!C.relative[s=a.type]);i--)if((u=C.find[s])&&(r=u(a.matches[0].replace(xt,Tt),dt.test(o[0].type)&&t.parentNode||t))){if(o.splice(i,1),e=r.length&&p(o),!e)return Q.apply(n,K.call(r,0)),n;break}}return S(e,l)(r,t,M,n,dt.test(e)),n}function T(){}var w,N,C,k,E,S,A,j,D,L,H,M,q,_,F,O,B,P="sizzle"+-new Date,R=e.document,W={},$=0,I=0,z=r(),X=r(),U=r(),V=typeof t,Y=1<<31,J=[],G=J.pop,Q=J.push,K=J.slice,Z=J.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},et="[\\x20\\t\\r\\n\\f]",tt="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",nt=tt.replace("w","w#"),rt="([*^$|!~]?=)",it="\\["+et+"*("+tt+")"+et+"*(?:"+rt+et+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+nt+")|)|)"+et+"*\\]",ot=":("+tt+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+it.replace(3,8)+")*)|.*)\\)|)",at=RegExp("^"+et+"+|((?:^|[^\\\\])(?:\\\\.)*)"+et+"+$","g"),ut=RegExp("^"+et+"*,"+et+"*"),lt=RegExp("^"+et+"*([\\x20\\t\\r\\n\\f>+~])"+et+"*"),ct=RegExp(ot),ft=RegExp("^"+nt+"$"),pt={ID:RegExp("^#("+tt+")"),CLASS:RegExp("^\\.("+tt+")"),NAME:RegExp("^\\[name=['\"]?("+tt+")['\"]?\\]"),TAG:RegExp("^("+tt.replace("w","w*")+")"),ATTR:RegExp("^"+it),PSEUDO:RegExp("^"+ot),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+et+"*(even|odd|(([+-]|)(\\d*)n|)"+et+"*(?:([+-]|)"+et+"*(\\d+)|))"+et+"*\\)|)","i"),needsContext:RegExp("^"+et+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+et+"*((?:-\\d)?\\d*)"+et+"*\\)|)(?=[^-]|$)","i")},dt=/[\x20\t\r\n\f]*[+~]/,ht=/\{\s*\[native code\]\s*\}/,gt=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,mt=/^(?:input|select|textarea|button)$/i,yt=/^h\d$/i,vt=/'|\\/g,bt=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,xt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,Tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{K.call(H.childNodes,0)[0].nodeType}catch(wt){K=function(e){for(var t,n=[];t=this[e];e++)n.push(t);return n}}E=a.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},D=a.setDocument=function(e){var r=e?e.ownerDocument||e:R;return r!==L&&9===r.nodeType&&r.documentElement?(L=r,H=r.documentElement,M=E(r),W.tagNameNoComments=o(function(e){return e.appendChild(r.createComment("")),!e.getElementsByTagName("*").length}),W.attributes=o(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),W.getByClassName=o(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),W.getByName=o(function(e){e.id=P+0,e.innerHTML="<a name='"+P+"'></a><div name='"+P+"'></div>",H.insertBefore(e,H.firstChild);var t=r.getElementsByName&&r.getElementsByName(P).length===2+r.getElementsByName(P+0).length;return W.getIdNotName=!r.getElementById(P),H.removeChild(e),t}),C.attrHandle=o(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==V&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},W.getIdNotName?(C.find.ID=function(e,t){if(typeof t.getElementById!==V&&!M){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},C.filter.ID=function(e){var t=e.replace(xt,Tt);return function(e){return e.getAttribute("id")===t}}):(C.find.ID=function(e,n){if(typeof n.getElementById!==V&&!M){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==V&&r.getAttributeNode("id").value===e?[r]:t:[]}},C.filter.ID=function(e){var t=e.replace(xt,Tt);return function(e){var n=typeof e.getAttributeNode!==V&&e.getAttributeNode("id");return n&&n.value===t}}),C.find.TAG=W.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==V?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i];i++)1===n.nodeType&&r.push(n);return r}return o},C.find.NAME=W.getByName&&function(e,n){return typeof n.getElementsByName!==V?n.getElementsByName(name):t},C.find.CLASS=W.getByClassName&&function(e,n){return typeof n.getElementsByClassName===V||M?t:n.getElementsByClassName(e)},_=[],q=[":focus"],(W.qsa=n(r.querySelectorAll))&&(o(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||q.push("\\["+et+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||q.push(":checked")}),o(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&q.push("[*^$]="+et+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),q.push(",.*:")})),(W.matchesSelector=n(F=H.matchesSelector||H.mozMatchesSelector||H.webkitMatchesSelector||H.oMatchesSelector||H.msMatchesSelector))&&o(function(e){W.disconnectedMatch=F.call(e,"div"),F.call(e,"[s!='']:x"),_.push("!=",ot)}),q=RegExp(q.join("|")),_=RegExp(_.join("|")),O=n(H.contains)||H.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},B=H.compareDocumentPosition?function(e,t){var n;return e===t?(A=!0,0):(n=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&n||e.parentNode&&11===e.parentNode.nodeType?e===r||O(R,e)?-1:t===r||O(R,t)?1:0:4&n?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var n,i=0,o=e.parentNode,a=t.parentNode,u=[e],l=[t];if(e===t)return A=!0,0;if(e.sourceIndex&&t.sourceIndex)return(~t.sourceIndex||Y)-(O(R,e)&&~e.sourceIndex||Y);if(!o||!a)return e===r?-1:t===r?1:o?-1:a?1:0;if(o===a)return s(e,t);for(n=e;n=n.parentNode;)u.unshift(n);for(n=t;n=n.parentNode;)l.unshift(n);for(;u[i]===l[i];)i++;return i?s(u[i],l[i]):u[i]===R?-1:l[i]===R?1:0},A=!1,[0,0].sort(B),W.detectDuplicates=A,L):L},a.matches=function(e,t){return a(e,null,null,t)},a.matchesSelector=function(e,t){if((e.ownerDocument||e)!==L&&D(e),t=t.replace(bt,"='$1']"),!(!W.matchesSelector||M||_&&_.test(t)||q.test(t)))try{var n=F.call(e,t);if(n||W.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return a(t,L,null,[e]).length>0},a.contains=function(e,t){return(e.ownerDocument||e)!==L&&D(e),O(e,t)},a.attr=function(e,t){var n;return(e.ownerDocument||e)!==L&&D(e),M||(t=t.toLowerCase()),(n=C.attrHandle[t])?n(e):M||W.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},a.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},a.uniqueSort=function(e){var t,n=[],r=1,i=0;if(A=!W.detectDuplicates,e.sort(B),A){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));for(;i--;)e.splice(n[i],1)}return e},k=a.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=k(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=k(t);return n},C=a.selectors={cacheLength:50,createPseudo:i,match:pt,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xt,Tt),e[3]=(e[4]||e[5]||"").replace(xt,Tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||a.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&a.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return pt.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&ct.test(n)&&(t=f(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(xt,Tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=z[e+" "];return t||(t=RegExp("(^|"+et+")"+e+"("+et+"|$)"))&&z(e,function(e){return t.test(e.className||typeof e.getAttribute!==V&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=a.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.substr(i.length-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){for(;g;){for(f=t;f=f[g];)if(s?f.nodeName.toLowerCase()===y:1===f.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(c=m[P]||(m[P]={}),l=c[e]||[],d=l[0]===$&&l[1],p=l[0]===$&&l[2],f=d&&m.childNodes[d];f=++d&&f&&f[g]||(p=d=0)||h.pop();)if(1===f.nodeType&&++p&&f===t){c[e]=[$,d,p];break}}else if(v&&(l=(t[P]||(t[P]={}))[e])&&l[0]===$)p=l[1];else for(;(f=++d&&f&&f[g]||(p=d=0)||h.pop())&&((s?f.nodeName.toLowerCase()!==y:1!==f.nodeType)||!++p||(v&&((f[P]||(f[P]={}))[e]=[$,p]),f!==t)););return p-=i,p===r||0===p%r&&p/r>=0}}},PSEUDO:function(e,t){var n,r=C.pseudos[e]||C.setFilters[e.toLowerCase()]||a.error("unsupported pseudo: "+e);return r[P]?r(t):r.length>1?(n=[e,e,"",t],C.setFilters.hasOwnProperty(e.toLowerCase())?i(function(e,n){for(var i,o=r(e,t),a=o.length;a--;)i=Z.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:i(function(e){var t=[],n=[],r=S(e.replace(at,"$1"));return r[P]?i(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:i(function(e){return function(t){return a(e,t).length>0}}),contains:i(function(e){return function(t){return(t.textContent||t.innerText||k(t)).indexOf(e)>-1}}),lang:i(function(e){return ft.test(e||"")||a.error("unsupported lang: "+e),e=e.replace(xt,Tt).toLowerCase(),function(t){var n;do if(n=M?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===H},focus:function(e){return e===L.activeElement&&(!L.hasFocus||L.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!C.pseudos.empty(e)},header:function(e){return yt.test(e.nodeName)},input:function(e){return mt.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[0>n?n+t:n]}),even:c(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:c(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:c(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:c(function(e,t,n){for(var r=0>n?n+t:n;t>++r;)e.push(r);return e})}};for(w in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})C.pseudos[w]=u(w);for(w in{submit:!0,reset:!0})C.pseudos[w]=l(w);S=a.compile=function(e,t){var n,r=[],i=[],o=U[e+" "];if(!o){for(t||(t=f(e)),n=t.length;n--;)o=y(t[n]),o[P]?r.push(o):i.push(o);o=U(e,v(i,r))}return o},C.pseudos.nth=C.pseudos.eq,C.filters=T.prototype=C.pseudos,C.setFilters=new T,D(),a.attr=st.attr,st.find=a,st.expr=a.selectors,st.expr[":"]=st.expr.pseudos,st.unique=a.uniqueSort,st.text=a.getText,st.isXMLDoc=a.isXML,st.contains=a.contains}(e);var Pt=/Until$/,Rt=/^(?:parents|prev(?:Until|All))/,Wt=/^.[^:#\[\.,]*$/,$t=st.expr.match.needsContext,It={children:!0,contents:!0,next:!0,prev:!0};st.fn.extend({find:function(e){var t,n,r;if("string"!=typeof e)return r=this,this.pushStack(st(e).filter(function(){for(t=0;r.length>t;t++)if(st.contains(r[t],this))return!0}));for(n=[],t=0;this.length>t;t++)st.find(e,this[t],n);return n=this.pushStack(st.unique(n)),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=st(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(st.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(f(this,e,!1))},filter:function(e){return this.pushStack(f(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?$t.test(e)?st(e,this.context).index(this[0])>=0:st.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=$t.test(e)||"string"!=typeof e?st(e,t||this.context):0;i>r;r++)for(n=this[r];n&&n.ownerDocument&&n!==t&&11!==n.nodeType;){if(a?a.index(n)>-1:st.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}return this.pushStack(o.length>1?st.unique(o):o)},index:function(e){return e?"string"==typeof e?st.inArray(this[0],st(e)):st.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?st(e,t):st.makeArray(e&&e.nodeType?[e]:e),r=st.merge(this.get(),n);return this.pushStack(st.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),st.fn.andSelf=st.fn.addBack,st.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return st.dir(e,"parentNode")},parentsUntil:function(e,t,n){return st.dir(e,"parentNode",n)},next:function(e){return c(e,"nextSibling")},prev:function(e){return c(e,"previousSibling")
+},nextAll:function(e){return st.dir(e,"nextSibling")},prevAll:function(e){return st.dir(e,"previousSibling")},nextUntil:function(e,t,n){return st.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return st.dir(e,"previousSibling",n)},siblings:function(e){return st.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return st.sibling(e.firstChild)},contents:function(e){return st.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:st.merge([],e.childNodes)}},function(e,t){st.fn[e]=function(n,r){var i=st.map(this,t,n);return Pt.test(e)||(r=n),r&&"string"==typeof r&&(i=st.filter(r,i)),i=this.length>1&&!It[e]?st.unique(i):i,this.length>1&&Rt.test(e)&&(i=i.reverse()),this.pushStack(i)}}),st.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?st.find.matchesSelector(t[0],e)?[t[0]]:[]:st.find.matches(e,t)},dir:function(e,n,r){for(var i=[],o=e[n];o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!st(o).is(r));)1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});var zt="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Xt=/ jQuery\d+="(?:null|\d+)"/g,Ut=RegExp("<(?:"+zt+")[\\s/>]","i"),Vt=/^\s+/,Yt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Jt=/<([\w:]+)/,Gt=/<tbody/i,Qt=/<|&#?\w+;/,Kt=/<(?:script|style|link)/i,Zt=/^(?:checkbox|radio)$/i,en=/checked\s*(?:[^=]|=\s*.checked.)/i,tn=/^$|\/(?:java|ecma)script/i,nn=/^true\/(.*)/,rn=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,on={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:st.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},an=p(V),sn=an.appendChild(V.createElement("div"));on.optgroup=on.option,on.tbody=on.tfoot=on.colgroup=on.caption=on.thead,on.th=on.td,st.fn.extend({text:function(e){return st.access(this,function(e){return e===t?st.text(this):this.empty().append((this[0]&&this[0].ownerDocument||V).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(st.isFunction(e))return this.each(function(t){st(this).wrapAll(e.call(this,t))});if(this[0]){var t=st(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return st.isFunction(e)?this.each(function(t){st(this).wrapInner(e.call(this,t))}):this.each(function(){var t=st(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=st.isFunction(e);return this.each(function(n){st(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){st.nodeName(this,"body")||st(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,r=0;null!=(n=this[r]);r++)(!e||st.filter(e,[n]).length>0)&&(t||1!==n.nodeType||st.cleanData(b(n)),n.parentNode&&(t&&st.contains(n.ownerDocument,n)&&m(b(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&st.cleanData(b(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&st.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return st.clone(this,e,t)})},html:function(e){return st.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(Xt,""):t;if(!("string"!=typeof e||Kt.test(e)||!st.support.htmlSerialize&&Ut.test(e)||!st.support.leadingWhitespace&&Vt.test(e)||on[(Jt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(Yt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(st.cleanData(b(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=st.isFunction(e);return t||"string"==typeof e||(e=st(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;(n&&1===this.nodeType||11===this.nodeType)&&(st(this).remove(),t?t.parentNode.insertBefore(e,t):n.appendChild(e))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=et.apply([],e);var i,o,a,s,u,l,c=0,f=this.length,p=this,m=f-1,y=e[0],v=st.isFunction(y);if(v||!(1>=f||"string"!=typeof y||st.support.checkClone)&&en.test(y))return this.each(function(i){var o=p.eq(i);v&&(e[0]=y.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(f&&(i=st.buildFragment(e,this[0].ownerDocument,!1,this),o=i.firstChild,1===i.childNodes.length&&(i=o),o)){for(n=n&&st.nodeName(o,"tr"),a=st.map(b(i,"script"),h),s=a.length;f>c;c++)u=i,c!==m&&(u=st.clone(u,!0,!0),s&&st.merge(a,b(u,"script"))),r.call(n&&st.nodeName(this[c],"table")?d(this[c],"tbody"):this[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,st.map(a,g),c=0;s>c;c++)u=a[c],tn.test(u.type||"")&&!st._data(u,"globalEval")&&st.contains(l,u)&&(u.src?st.ajax({url:u.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):st.globalEval((u.text||u.textContent||u.innerHTML||"").replace(rn,"")));i=o=null}return this}}),st.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){st.fn[e]=function(e){for(var n,r=0,i=[],o=st(e),a=o.length-1;a>=r;r++)n=r===a?this:this.clone(!0),st(o[r])[t](n),tt.apply(i,n.get());return this.pushStack(i)}}),st.extend({clone:function(e,t,n){var r,i,o,a,s,u=st.contains(e.ownerDocument,e);if(st.support.html5Clone||st.isXMLDoc(e)||!Ut.test("<"+e.nodeName+">")?s=e.cloneNode(!0):(sn.innerHTML=e.outerHTML,sn.removeChild(s=sn.firstChild)),!(st.support.noCloneEvent&&st.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||st.isXMLDoc(e)))for(r=b(s),i=b(e),a=0;null!=(o=i[a]);++a)r[a]&&v(o,r[a]);if(t)if(n)for(i=i||b(e),r=r||b(s),a=0;null!=(o=i[a]);a++)y(o,r[a]);else y(e,s);return r=b(s,"script"),r.length>0&&m(r,!u&&b(e,"script")),r=i=o=null,s},buildFragment:function(e,t,n,r){for(var i,o,a,s,u,l,c,f=e.length,d=p(t),h=[],g=0;f>g;g++)if(o=e[g],o||0===o)if("object"===st.type(o))st.merge(h,o.nodeType?[o]:o);else if(Qt.test(o)){for(s=s||d.appendChild(t.createElement("div")),a=(Jt.exec(o)||["",""])[1].toLowerCase(),u=on[a]||on._default,s.innerHTML=u[1]+o.replace(Yt,"<$1></$2>")+u[2],c=u[0];c--;)s=s.lastChild;if(!st.support.leadingWhitespace&&Vt.test(o)&&h.push(t.createTextNode(Vt.exec(o)[0])),!st.support.tbody)for(o="table"!==a||Gt.test(o)?"<table>"!==u[1]||Gt.test(o)?0:s:s.firstChild,c=o&&o.childNodes.length;c--;)st.nodeName(l=o.childNodes[c],"tbody")&&!l.childNodes.length&&o.removeChild(l);for(st.merge(h,s.childNodes),s.textContent="";s.firstChild;)s.removeChild(s.firstChild);s=d.lastChild}else h.push(t.createTextNode(o));for(s&&d.removeChild(s),st.support.appendChecked||st.grep(b(h,"input"),x),g=0;o=h[g++];)if((!r||-1===st.inArray(o,r))&&(i=st.contains(o.ownerDocument,o),s=b(d.appendChild(o),"script"),i&&m(s),n))for(c=0;o=s[c++];)tn.test(o.type||"")&&n.push(o);return s=null,d},cleanData:function(e,n){for(var r,i,o,a,s=0,u=st.expando,l=st.cache,c=st.support.deleteExpando,f=st.event.special;null!=(o=e[s]);s++)if((n||st.acceptData(o))&&(i=o[u],r=i&&l[i])){if(r.events)for(a in r.events)f[a]?st.event.remove(o,a):st.removeEvent(o,a,r.handle);l[i]&&(delete l[i],c?delete o[u]:o.removeAttribute!==t?o.removeAttribute(u):o[u]=null,K.push(i))}}});var un,ln,cn,fn=/alpha\([^)]*\)/i,pn=/opacity\s*=\s*([^)]*)/,dn=/^(top|right|bottom|left)$/,hn=/^(none|table(?!-c[ea]).+)/,gn=/^margin/,mn=RegExp("^("+ut+")(.*)$","i"),yn=RegExp("^("+ut+")(?!px)[a-z%]+$","i"),vn=RegExp("^([+-])=("+ut+")","i"),bn={BODY:"block"},xn={position:"absolute",visibility:"hidden",display:"block"},Tn={letterSpacing:0,fontWeight:400},wn=["Top","Right","Bottom","Left"],Nn=["Webkit","O","Moz","ms"];st.fn.extend({css:function(e,n){return st.access(this,function(e,n,r){var i,o,a={},s=0;if(st.isArray(n)){for(i=ln(e),o=n.length;o>s;s++)a[n[s]]=st.css(e,n[s],!1,i);return a}return r!==t?st.style(e,n,r):st.css(e,n)},e,n,arguments.length>1)},show:function(){return N(this,!0)},hide:function(){return N(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:w(this))?st(this).show():st(this).hide()})}}),st.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=un(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":st.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=st.camelCase(n),l=e.style;if(n=st.cssProps[u]||(st.cssProps[u]=T(l,u)),s=st.cssHooks[n]||st.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=vn.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(st.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||st.cssNumber[u]||(r+="px"),st.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=st.camelCase(n);return n=st.cssProps[u]||(st.cssProps[u]=T(e.style,u)),s=st.cssHooks[n]||st.cssHooks[u],s&&"get"in s&&(o=s.get(e,!0,r)),o===t&&(o=un(e,n,i)),"normal"===o&&n in Tn&&(o=Tn[n]),r?(a=parseFloat(o),r===!0||st.isNumeric(a)?a||0:o):o},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(ln=function(t){return e.getComputedStyle(t,null)},un=function(e,n,r){var i,o,a,s=r||ln(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||st.contains(e.ownerDocument,e)||(u=st.style(e,n)),yn.test(u)&&gn.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):V.documentElement.currentStyle&&(ln=function(e){return e.currentStyle},un=function(e,n,r){var i,o,a,s=r||ln(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),yn.test(u)&&!dn.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u}),st.each(["height","width"],function(e,n){st.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&hn.test(st.css(e,"display"))?st.swap(e,xn,function(){return E(e,n,i)}):E(e,n,i):t},set:function(e,t,r){var i=r&&ln(e);return C(e,t,r?k(e,n,r,st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,i),i):0)}}}),st.support.opacity||(st.cssHooks.opacity={get:function(e,t){return pn.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=st.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===st.trim(o.replace(fn,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=fn.test(o)?o.replace(fn,i):o+" "+i)}}),st(function(){st.support.reliableMarginRight||(st.cssHooks.marginRight={get:function(e,n){return n?st.swap(e,{display:"inline-block"},un,[e,"marginRight"]):t}}),!st.support.pixelPosition&&st.fn.position&&st.each(["top","left"],function(e,n){st.cssHooks[n]={get:function(e,r){return r?(r=un(e,n),yn.test(r)?st(e).position()[n]+"px":r):t}}})}),st.expr&&st.expr.filters&&(st.expr.filters.hidden=function(e){return 0===e.offsetWidth&&0===e.offsetHeight||!st.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||st.css(e,"display"))},st.expr.filters.visible=function(e){return!st.expr.filters.hidden(e)}),st.each({margin:"",padding:"",border:"Width"},function(e,t){st.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];4>r;r++)i[e+wn[r]+t]=o[r]||o[r-2]||o[0];return i}},gn.test(e)||(st.cssHooks[e+t].set=C)});var Cn=/%20/g,kn=/\[\]$/,En=/\r?\n/g,Sn=/^(?:submit|button|image|reset)$/i,An=/^(?:input|select|textarea|keygen)/i;st.fn.extend({serialize:function(){return st.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=st.prop(this,"elements");return e?st.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!st(this).is(":disabled")&&An.test(this.nodeName)&&!Sn.test(e)&&(this.checked||!Zt.test(e))}).map(function(e,t){var n=st(this).val();return null==n?null:st.isArray(n)?st.map(n,function(e){return{name:t.name,value:e.replace(En,"\r\n")}}):{name:t.name,value:n.replace(En,"\r\n")}}).get()}}),st.param=function(e,n){var r,i=[],o=function(e,t){t=st.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=st.ajaxSettings&&st.ajaxSettings.traditional),st.isArray(e)||e.jquery&&!st.isPlainObject(e))st.each(e,function(){o(this.name,this.value)});else for(r in e)j(r,e[r],n,o);return i.join("&").replace(Cn,"+")};var jn,Dn,Ln=st.now(),Hn=/\?/,Mn=/#.*$/,qn=/([?&])_=[^&]*/,_n=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Fn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,On=/^(?:GET|HEAD)$/,Bn=/^\/\//,Pn=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Rn=st.fn.load,Wn={},$n={},In="*/".concat("*");try{Dn=Y.href}catch(zn){Dn=V.createElement("a"),Dn.href="",Dn=Dn.href}jn=Pn.exec(Dn.toLowerCase())||[],st.fn.load=function(e,n,r){if("string"!=typeof e&&Rn)return Rn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),st.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(o="POST"),s.length>0&&st.ajax({url:e,type:o,dataType:"html",data:n}).done(function(e){a=arguments,s.html(i?st("<div>").append(st.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,a||[e.responseText,t,e])}),this},st.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){st.fn[t]=function(e){return this.on(t,e)}}),st.each(["get","post"],function(e,n){st[n]=function(e,r,i,o){return st.isFunction(r)&&(o=o||i,i=r,r=t),st.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),st.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Dn,type:"GET",isLocal:Fn.test(jn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":In,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":st.parseJSON,"text xml":st.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?H(H(e,st.ajaxSettings),t):H(st.ajaxSettings,e)},ajaxPrefilter:D(Wn),ajaxTransport:D($n),ajax:function(e,n){function r(e,n,r,s){var l,f,v,b,T,N=n;2!==x&&(x=2,u&&clearTimeout(u),i=t,a=s||"",w.readyState=e>0?4:0,r&&(b=M(p,w,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=w.getResponseHeader("Last-Modified"),T&&(st.lastModified[o]=T),T=w.getResponseHeader("etag"),T&&(st.etag[o]=T)),304===e?(l=!0,N="notmodified"):(l=q(p,b),N=l.state,f=l.data,v=l.error,l=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),w.status=e,w.statusText=(n||N)+"",l?g.resolveWith(d,[f,N,w]):g.rejectWith(d,[w,N,v]),w.statusCode(y),y=t,c&&h.trigger(l?"ajaxSuccess":"ajaxError",[w,p,l?f:v]),m.fireWith(d,[w,N]),c&&(h.trigger("ajaxComplete",[w,p]),--st.active||st.event.trigger("ajaxStop")))}"object"==typeof e&&(n=e,e=t),n=n||{};var i,o,a,s,u,l,c,f,p=st.ajaxSetup({},n),d=p.context||p,h=p.context&&(d.nodeType||d.jquery)?st(d):st.event,g=st.Deferred(),m=st.Callbacks("once memory"),y=p.statusCode||{},v={},b={},x=0,T="canceled",w={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!s)for(s={};t=_n.exec(a);)s[t[1].toLowerCase()]=t[2];t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=b[n]=b[n]||e,v[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)y[t]=[y[t],e[t]];else w.always(e[w.status]);return this},abort:function(e){var t=e||T;return i&&i.abort(t),r(0,t),this}};if(g.promise(w).complete=m.add,w.success=w.done,w.error=w.fail,p.url=((e||p.url||Dn)+"").replace(Mn,"").replace(Bn,jn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=st.trim(p.dataType||"*").toLowerCase().match(lt)||[""],null==p.crossDomain&&(l=Pn.exec(p.url.toLowerCase()),p.crossDomain=!(!l||l[1]===jn[1]&&l[2]===jn[2]&&(l[3]||("http:"===l[1]?80:443))==(jn[3]||("http:"===jn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=st.param(p.data,p.traditional)),L(Wn,p,n,w),2===x)return w;c=p.global,c&&0===st.active++&&st.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!On.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(Hn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=qn.test(o)?o.replace(qn,"$1_="+Ln++):o+(Hn.test(o)?"&":"?")+"_="+Ln++)),p.ifModified&&(st.lastModified[o]&&w.setRequestHeader("If-Modified-Since",st.lastModified[o]),st.etag[o]&&w.setRequestHeader("If-None-Match",st.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&w.setRequestHeader("Content-Type",p.contentType),w.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+In+"; q=0.01":""):p.accepts["*"]);for(f in p.headers)w.setRequestHeader(f,p.headers[f]);if(p.beforeSend&&(p.beforeSend.call(d,w,p)===!1||2===x))return w.abort();T="abort";for(f in{success:1,error:1,complete:1})w[f](p[f]);if(i=L($n,p,n,w)){w.readyState=1,c&&h.trigger("ajaxSend",[w,p]),p.async&&p.timeout>0&&(u=setTimeout(function(){w.abort("timeout")},p.timeout));try{x=1,i.send(v,r)}catch(N){if(!(2>x))throw N;r(-1,N)}}else r(-1,"No Transport");return w},getScript:function(e,n){return st.get(e,t,n,"script")},getJSON:function(e,t,n){return st.get(e,t,n,"json")}}),st.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return st.globalEval(e),e}}}),st.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),st.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=V.head||st("head")[0]||V.documentElement;return{send:function(t,i){n=V.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Xn=[],Un=/(=)\?(?=&|$)|\?\?/;st.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xn.pop()||st.expando+"_"+Ln++;return this[e]=!0,e}}),st.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Un.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Un.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=st.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Un,"$1"+o):n.jsonp!==!1&&(n.url+=(Hn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||st.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Xn.push(o)),s&&st.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Vn,Yn,Jn=0,Gn=e.ActiveXObject&&function(){var e;for(e in Vn)Vn[e](t,!0)};st.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&_()||F()}:_,Yn=st.ajaxSettings.xhr(),st.support.cors=!!Yn&&"withCredentials"in Yn,Yn=st.support.ajax=!!Yn,Yn&&st.ajaxTransport(function(n){if(!n.crossDomain||st.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,f,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=st.noop,Gn&&delete Vn[a]),i)4!==u.readyState&&u.abort();else{f={},s=u.status,p=u.responseXML,c=u.getAllResponseHeaders(),p&&p.documentElement&&(f.xml=p),"string"==typeof u.responseText&&(f.text=u.responseText);try{l=u.statusText}catch(d){l=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=f.text?200:404}}catch(h){i||o(-1,h)}f&&o(s,l,f,c)},n.async?4===u.readyState?setTimeout(r):(a=++Jn,Gn&&(Vn||(Vn={},st(e).unload(Gn)),Vn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Qn,Kn,Zn=/^(?:toggle|show|hide)$/,er=RegExp("^(?:([+-])=|)("+ut+")([a-z%]*)$","i"),tr=/queueHooks$/,nr=[W],rr={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=er.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(st.cssNumber[e]?"":"px"),"px"!==r&&s){s=st.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,st.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};st.Animation=st.extend(P,{tweener:function(e,t){st.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");for(var n,r=0,i=e.length;i>r;r++)n=e[r],rr[n]=rr[n]||[],rr[n].unshift(t)},prefilter:function(e,t){t?nr.unshift(e):nr.push(e)}}),st.Tween=$,$.prototype={constructor:$,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(st.cssNumber[n]?"":"px")},cur:function(){var e=$.propHooks[this.prop];return e&&e.get?e.get(this):$.propHooks._default.get(this)},run:function(e){var t,n=$.propHooks[this.prop];return this.pos=t=this.options.duration?st.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):$.propHooks._default.set(this),this}},$.prototype.init.prototype=$.prototype,$.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=st.css(e.elem,e.prop,"auto"),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){st.fx.step[e.prop]?st.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[st.cssProps[e.prop]]||st.cssHooks[e.prop])?st.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},$.propHooks.scrollTop=$.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},st.each(["toggle","show","hide"],function(e,t){var n=st.fn[t];st.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(I(t,!0),e,r,i)}}),st.fn.extend({fadeTo:function(e,t,n,r){return this.filter(w).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=st.isEmptyObject(e),o=st.speed(t,n,r),a=function(){var t=P(this,st.extend({},e),o);a.finish=function(){t.stop(!0)},(i||st._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=st.timers,a=st._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&tr.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&st.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=st._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=st.timers,a=r?r.length:0;for(n.finish=!0,st.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),st.each({slideDown:I("show"),slideUp:I("hide"),slideToggle:I("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){st.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),st.speed=function(e,t,n){var r=e&&"object"==typeof e?st.extend({},e):{complete:n||!n&&t||st.isFunction(e)&&e,duration:e,easing:n&&t||t&&!st.isFunction(t)&&t};return r.duration=st.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in st.fx.speeds?st.fx.speeds[r.duration]:st.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){st.isFunction(r.old)&&r.old.call(this),r.queue&&st.dequeue(this,r.queue)},r},st.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},st.timers=[],st.fx=$.prototype.init,st.fx.tick=function(){var e,n=st.timers,r=0;for(Qn=st.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||st.fx.stop(),Qn=t},st.fx.timer=function(e){e()&&st.timers.push(e)&&st.fx.start()},st.fx.interval=13,st.fx.start=function(){Kn||(Kn=setInterval(st.fx.tick,st.fx.interval))},st.fx.stop=function(){clearInterval(Kn),Kn=null},st.fx.speeds={slow:600,fast:200,_default:400},st.fx.step={},st.expr&&st.expr.filters&&(st.expr.filters.animated=function(e){return st.grep(st.timers,function(t){return e===t.elem}).length}),st.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){st.offset.setOffset(this,e,t)});var n,r,i={top:0,left:0},o=this[0],a=o&&o.ownerDocument;if(a)return n=a.documentElement,st.contains(n,o)?(o.getBoundingClientRect!==t&&(i=o.getBoundingClientRect()),r=z(a),{top:i.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:i.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):i},st.offset={setOffset:function(e,t,n){var r=st.css(e,"position");"static"===r&&(e.style.position="relative");var i,o,a=st(e),s=a.offset(),u=st.css(e,"top"),l=st.css(e,"left"),c=("absolute"===r||"fixed"===r)&&st.inArray("auto",[u,l])>-1,f={},p={};c?(p=a.position(),i=p.top,o=p.left):(i=parseFloat(u)||0,o=parseFloat(l)||0),st.isFunction(t)&&(t=t.call(e,n,s)),null!=t.top&&(f.top=t.top-s.top+i),null!=t.left&&(f.left=t.left-s.left+o),"using"in t?t.using.call(e,f):a.css(f)}},st.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===st.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),st.nodeName(e[0],"html")||(n=e.offset()),n.top+=st.css(e[0],"borderTopWidth",!0),n.left+=st.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-st.css(r,"marginTop",!0),left:t.left-n.left-st.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||V.documentElement;e&&!st.nodeName(e,"html")&&"static"===st.css(e,"position");)e=e.offsetParent;return e||V.documentElement})}}),st.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);st.fn[e]=function(i){return st.access(this,function(e,i,o){var a=z(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?st(a).scrollLeft():o,r?o:st(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}}),st.each({Height:"height",Width:"width"},function(e,n){st.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){st.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return st.access(this,function(n,r,i){var o;return st.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?st.css(n,r,s):st.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=st,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return st})})(window);
+//@ sourceMappingURL=jquery.min.map
\ No newline at end of file
diff --git a/portal/static/reputation_static/js/jquery.raty.min.js b/portal/static/reputation_static/js/jquery.raty.min.js
new file mode 100644 (file)
index 0000000..bc73d7e
--- /dev/null
@@ -0,0 +1,12 @@
+/*!
+ * jQuery Raty - A Star Rating Plugin
+ *
+ * Licensed under The MIT License
+ *
+ * @version        2.4.5
+ * @author         Washington Botelho
+ * @documentation  wbotelhos.com/raty
+ * 
+ */
+
+;(function(b){var a={init:function(c){return this.each(function(){var d=this,h=b(d).empty();d.opt=b.extend(true,{},b.fn.raty.defaults,c);h.data("settings",d.opt);d.opt.number=a.between(d.opt.number,0,20);if(d.opt.path.substring(d.opt.path.length-1,d.opt.path.length)!="/"){d.opt.path+="/";}if(typeof d.opt.score=="function"){d.opt.score=d.opt.score.call(d);}if(d.opt.score){d.opt.score=a.between(d.opt.score,0,d.opt.number);}for(var e=1;e<=d.opt.number;e++){b("<img />",{src:d.opt.path+((!d.opt.score||d.opt.score<e)?d.opt.starOff:d.opt.starOn),alt:e,title:(e<=d.opt.hints.length&&d.opt.hints[e-1]!==null)?d.opt.hints[e-1]:e}).appendTo(d);if(d.opt.space){h.append((e<d.opt.number)?"&#160;":"");}}d.stars=h.children('img:not(".raty-cancel")');d.score=b("<input />",{type:"hidden",name:d.opt.scoreName}).appendTo(d);if(d.opt.score&&d.opt.score>0){d.score.val(d.opt.score);a.roundStar.call(d,d.opt.score);}if(d.opt.iconRange){a.fill.call(d,d.opt.score);}a.setTarget.call(d,d.opt.score,d.opt.targetKeep);var g=d.opt.space?4:0,f=d.opt.width||(d.opt.number*d.opt.size+d.opt.number*g);if(d.opt.cancel){d.cancel=b("<img />",{src:d.opt.path+d.opt.cancelOff,alt:"x",title:d.opt.cancelHint,"class":"raty-cancel"});if(d.opt.cancelPlace=="left"){h.prepend("&#160;").prepend(d.cancel);}else{h.append("&#160;").append(d.cancel);}f+=(d.opt.size+g);}if(d.opt.readOnly){a.fixHint.call(d);if(d.cancel){d.cancel.hide();}}else{h.css("cursor","pointer");a.bindAction.call(d);}h.css("width",f);});},between:function(e,d,c){return Math.min(Math.max(parseFloat(e),d),c);},bindAction:function(){var c=this,e=b(c);e.mouseleave(function(){var f=c.score.val()||undefined;a.initialize.call(c,f);a.setTarget.call(c,f,c.opt.targetKeep);if(c.opt.mouseover){c.opt.mouseover.call(c,f);}});var d=c.opt.half?"mousemove":"mouseover";if(c.opt.cancel){c.cancel.mouseenter(function(){b(this).attr("src",c.opt.path+c.opt.cancelOn);c.stars.attr("src",c.opt.path+c.opt.starOff);a.setTarget.call(c,null,true);if(c.opt.mouseover){c.opt.mouseover.call(c,null);}}).mouseleave(function(){b(this).attr("src",c.opt.path+c.opt.cancelOff);if(c.opt.mouseover){c.opt.mouseover.call(c,c.score.val()||null);}}).click(function(f){c.score.removeAttr("value");if(c.opt.click){c.opt.click.call(c,null,f);}});}c.stars.bind(d,function(g){var h=parseInt(this.alt,10);if(c.opt.half){var f=parseFloat((g.pageX-b(this).offset().left)/c.opt.size),i=(f>0.5)?1:0.5;h=parseFloat(this.alt)-1+i;a.fill.call(c,h);if(c.opt.precision){h=h-i+f;}a.showHalf.call(c,h);}else{a.fill.call(c,h);}e.data("score",h);a.setTarget.call(c,h,true);if(c.opt.mouseover){c.opt.mouseover.call(c,h,g);}}).click(function(f){c.score.val((c.opt.half||c.opt.precision)?e.data("score"):this.alt);if(c.opt.click){c.opt.click.call(c,c.score.val(),f);}});},cancel:function(c){return b(this).each(function(){var d=this,e=b(d);if(e.data("readonly")===true){return this;}if(c){a.click.call(d,null);}else{a.score.call(d,null);}d.score.removeAttr("value");});},click:function(c){return b(this).each(function(){if(b(this).data("readonly")===true){return this;}a.initialize.call(this,c);if(this.opt.click){this.opt.click.call(this,c);}else{a.error.call(this,'you must add the "click: function(score, evt) { }" callback.');}a.setTarget.call(this,c,true);});},error:function(c){b(this).html(c);b.error(c);},fill:function(k){var c=this,h=c.stars.length,g=0,d,j,f;for(var e=1;e<=h;e++){d=c.stars.eq(e-1);if(c.opt.iconRange&&c.opt.iconRange.length>g){j=c.opt.iconRange[g];if(c.opt.single){f=(e==k)?(j.on||c.opt.starOn):(j.off||c.opt.starOff);}else{f=(e<=k)?(j.on||c.opt.starOn):(j.off||c.opt.starOff);}if(e<=j.range){d.attr("src",c.opt.path+f);}if(e==j.range){g++;}}else{if(c.opt.single){f=(e==k)?c.opt.starOn:c.opt.starOff;}else{f=(e<=k)?c.opt.starOn:c.opt.starOff;}d.attr("src",c.opt.path+f);}}},fixHint:function(){var c=b(this),e=parseInt(this.score.val(),10),d=this.opt.noRatedMsg;if(!isNaN(e)&&e>0){d=(e<=this.opt.hints.length&&this.opt.hints[e-1]!==null)?this.opt.hints[e-1]:e;}c.data("readonly",true).css("cursor","default").attr("title",d);this.score.attr("readonly","readonly");this.stars.attr("title",d);},getScore:function(){var d=[],c;b(this).each(function(){c=this.score.val();d.push(c?parseFloat(c):undefined);});return(d.length>1)?d:d[0];},readOnly:function(c){return this.each(function(){var d=b(this);if(d.data("readonly")===c){return this;}if(this.cancel){if(c){this.cancel.hide();}else{this.cancel.show();}}if(c){d.unbind();d.children("img").unbind();a.fixHint.call(this);}else{a.bindAction.call(this);a.unfixHint.call(this);}d.data("readonly",c);});},reload:function(){return a.set.call(this,{});},roundStar:function(e){var d=(e-Math.floor(e)).toFixed(2);if(d>this.opt.round.down){var c=this.opt.starOn;if(d<this.opt.round.up&&this.opt.halfShow){c=this.opt.starHalf;}else{if(d<this.opt.round.full){c=this.opt.starOff;}}this.stars.eq(Math.ceil(e)-1).attr("src",this.opt.path+c);}},score:function(){return arguments.length?a.setScore.apply(this,arguments):a.getScore.call(this);},set:function(c){this.each(function(){var d=b(this),f=d.data("settings"),e=d.clone().removeAttr("style").insertBefore(d);d.remove();e.raty(b.extend(f,c));});return b(this.selector);},setScore:function(c){return b(this).each(function(){if(b(this).data("readonly")===true){return this;}a.initialize.call(this,c);a.setTarget.call(this,c,true);});},setTarget:function(e,d){if(this.opt.target){var c=b(this.opt.target);if(c.length==0){a.error.call(this,"target selector invalid or missing!");}var f=e;if(!d||f===undefined){f=this.opt.targetText;}else{if(this.opt.targetType=="hint"){f=(f===null&&this.opt.cancel)?this.opt.cancelHint:this.opt.hints[Math.ceil(f-1)];}else{f=this.opt.precision?parseFloat(f).toFixed(1):parseInt(f,10);}}if(this.opt.targetFormat.indexOf("{score}")<0){a.error.call(this,'template "{score}" missing!');}if(e!==null){f=this.opt.targetFormat.toString().replace("{score}",f);}if(c.is(":input")){c.val(f);}else{c.html(f);}}},showHalf:function(d){var c=(d-Math.floor(d)).toFixed(1);if(c>0&&c<0.6){this.stars.eq(Math.ceil(d)-1).attr("src",this.opt.path+this.opt.starHalf);}},initialize:function(c){c=!c?0:a.between(c,0,this.opt.number);a.fill.call(this,c);if(c>0){if(this.opt.halfShow){a.roundStar.call(this,c);}this.score.val(c);}},unfixHint:function(){for(var c=0;c<this.opt.number;c++){this.stars.eq(c).attr("title",(c<this.opt.hints.length&&this.opt.hints[c]!==null)?this.opt.hints[c]:c);}b(this).data("readonly",false).css("cursor","pointer").removeAttr("title");this.score.attr("readonly","readonly");}};b.fn.raty=function(c){if(a[c]){return a[c].apply(this,Array.prototype.slice.call(arguments,1));}else{if(typeof c==="object"||!c){return a.init.apply(this,arguments);}else{b.error("Method "+c+" does not exist!");}}};b.fn.raty.defaults={cancel:false,cancelHint:"cancel this rating!",cancelOff:"cancel-off.png",cancelOn:"cancel-on.png",cancelPlace:"left",click:undefined,half:false,halfShow:true,hints:["bad","poor","regular","good","gorgeous"],iconRange:undefined,mouseover:undefined,noRatedMsg:"not rated yet",number:5,path:"",precision:false,round:{down:0.25,full:0.6,up:0.76},readOnly:false,score:undefined,scoreName:"score",single:false,size:16,space:true,starHalf:"star-half.png",starOff:"star-off.png",starOn:"star-on.png",target:undefined,targetFormat:"{score}",targetKeep:false,targetText:"",targetType:"hint",width:undefined};})(jQuery);
diff --git a/portal/static/reputation_static/js/ui/jquery-ui-1.9.2.custom.min.js b/portal/static/reputation_static/js/ui/jquery-ui-1.9.2.custom.min.js
new file mode 100644 (file)
index 0000000..d8e985b
--- /dev/null
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.9.2 - 2013-01-17
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.button.js, jquery.ui.dialog.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-drop.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-slide.js
+* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
+
+(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},contains:e.contains,hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e<t+n},isOver:function(t,n,r,i,s,o){return e.ui.isOverAxis(t,r,s)&&e.ui.isOverAxis(n,i,o)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&(e.effects.effect[u]||e.uiBackCompat!==!1&&e.effects[u])?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}}),e.uiBackCompat!==!1&&(e.Widget.prototype._getCreateOptions=function(){return e.metadata&&e.metadata.get(this.element[0])[this.widgetName]})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(e){n=!1}),e.widget("ui.mouse",{version:"1.9.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return!e.ui.ie||document.documentMode>=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,d,v,m,g=e(t.of),y=e.position.getWithinInfo(t.within),b=e.position.getScrollInfo(y),w=g[0],E=(t.collision||"flip").split(" "),S={};return w.nodeType===9?(l=g.width(),d=g.height(),v={top:0,left:0}):e.isWindow(w)?(l=g.width(),d=g.height(),v={top:g.scrollTop(),left:g.scrollLeft()}):w.preventDefault?(t.at="left top",l=d=0,v={top:w.pageY,left:w.pageX}):(l=g.outerWidth(),d=g.outerHeight(),v=g.offset()),m=e.extend({},v),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),S[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),E.length===1&&(E[1]=E[0]),t.at[0]==="right"?m.left+=l:t.at[0]==="center"&&(m.left+=l/2),t.at[1]==="bottom"?m.top+=d:t.at[1]==="center"&&(m.top+=d/2),n=h(S.at,l,d),m.left+=n[0],m.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),w=p(this,"marginLeft"),x=p(this,"marginTop"),T=f+w+p(this,"marginRight")+b.width,N=c+x+p(this,"marginBottom")+b.height,C=e.extend({},m),k=h(S.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:w,marginTop:x},e.each(["left","top"],function(r,i){e.ui.position[E[r]]&&e.ui.position[E[r]][i](C,{targetWidth:l,targetHeight:d,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:y,elem:a})}),e.fn.bgiframe&&a.bgiframe(),t.using&&(u=function(e){var n=v.left-C.left,s=n+l-f,o=v.top-C.top,u=o+d-c,h={target:{element:g,left:v.left,top:v.top,width:l,height:d},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),d<c&&i(o+u)<d&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.left<u[0]&&(s=u[0]+this.offset.click.left),t.pageY-this.offset.click.top<u[1]&&(o=u[1]+this.offset.click.top),t.pageX-this.offset.click.left>u[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.top<u[1]||f-this.offset.click.top>u[3]?f-this.offset.click.top<u[1]?f+n.grid[1]:f-n.grid[1]:f:f;var l=n.grid[0]?this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX;s=u?l-this.offset.click.left<u[0]||l-this.offset.click.left>u[2]?l-this.offset.click.left<u[0]?l+n.grid[0]:l-n.grid[0]:l:l}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(e){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("draggable"),i=this,s=function(t){var n=this.offset.click.top,r=this.offset.click.left,i=this.positionAbs.top,s=this.positionAbs.left,o=t.height,u=t.width,a=t.top,f=t.left;return e.ui.isOver(i+n,s+r,a,f,o,u)};e.each(r.sortables,function(s){var o=!1,u=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!=u&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(u.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,n){var r=e("body"),i=e(this).data("draggable").options;r.css("cursor")&&(i._cursor=r.css("cursor")),r.css("cursor",i.cursor)},stop:function(t,n){var r=e(this).data("draggable").options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(t,n){var r=e(this).data("draggable");r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"&&(r.overflowOffset=r.scrollParent.offset())},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=!1;if(r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"){if(!i.axis||i.axis!="x")r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY<i.scrollSensitivity?r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop+i.scrollSpeed:t.pageY-r.overflowOffset.top<i.scrollSensitivity&&(r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop-i.scrollSpeed);if(!i.axis||i.axis!="y")r.overflowOffset.left+r.scrollParent[0].offsetWidth-t.pageX<i.scrollSensitivity?r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft+i.scrollSpeed:t.pageX-r.overflowOffset.left<i.scrollSensitivity&&(r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft-i.scrollSpeed)}else{if(!i.axis||i.axis!="x")t.pageY-e(document).scrollTop()<i.scrollSensitivity?s=e(document).scrollTop(e(document).scrollTop()-i.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<i.scrollSensitivity&&(s=e(document).scrollTop(e(document).scrollTop()+i.scrollSpeed));if(!i.axis||i.axis!="y")t.pageX-e(document).scrollLeft()<i.scrollSensitivity?s=e(document).scrollLeft(e(document).scrollLeft()-i.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<i.scrollSensitivity&&(s=e(document).scrollLeft(e(document).scrollLeft()+i.scrollSpeed))}s!==!1&&e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(r,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,n){var r=e(this).data("draggable"),i=r.options;r.snapElements=[],e(i.snap.constructor!=String?i.snap.items||":data(draggable)":i.snap).each(function(){var t=e(this),n=t.offset();this!=r.element[0]&&r.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:n.top,left:n.left})})},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=i.snapTolerance,o=n.offset.left,u=o+r.helperProportions.width,a=n.offset.top,f=a+r.helperProportions.height;for(var l=r.snapElements.length-1;l>=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s<o&&o<h+s&&p-s<a&&a<d+s||c-s<o&&o<h+s&&p-s<f&&f<d+s||c-s<u&&u<h+s&&p-s<a&&a<d+s||c-s<u&&u<h+s&&p-s<f&&f<d+s)){r.snapElements[l].snapping&&r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=!1;continue}if(i.snapMode!="inner"){var v=Math.abs(p-f)<=s,m=Math.abs(d-a)<=s,g=Math.abs(c-u)<=s,y=Math.abs(h-o)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p-r.helperProportions.height,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c-r.helperProportions.width}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h}).left-r.margins.left)}var b=v||m||g||y;if(i.snapMode!="outer"){var v=Math.abs(p-a)<=s,m=Math.abs(d-f)<=s,g=Math.abs(c-o)<=s,y=Math.abs(h-u)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d-r.helperProportions.height,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h-r.helperProportions.width}).left-r.margins.left)}!r.snapElements[l].snapping&&(v||m||g||y||b)&&r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=v||m||g||y||b}}}),e.ui.plugin.add("draggable","stack",{start:function(t,n){var r=e(this).data("draggable").options,i=e.makeArray(e(r.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!i.length)return;var s=parseInt(i[0].style.zIndex)||0;e(i).each(function(e){this.style.zIndex=s+e}),this[0].style.zIndex=s+i.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){e.widget("ui.droppable",{version:"1.9.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var t=this.options,n=t.accept;this.isover=0,this.isout=1,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];for(var n=0;n<t.length;n++)t[n]==this&&t.splice(n,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t=="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current;if(!r||(r.currentItem||r.element)[0]==this.element[0])return!1;var i=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope==r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(t,n,r){if(!n.offset)return!1;var i=(t.positionAbs||t.position.absolute).left,s=i+t.helperProportions.width,o=(t.positionAbs||t.position.absolute).top,u=o+t.helperProportions.height,a=n.offset.left,f=a+n.proportions.width,l=n.offset.top,c=l+n.proportions.height;switch(r){case"fit":return a<=i&&s<=f&&l<=o&&u<=c;case"intersect":return a<i+t.helperProportions.width/2&&s-t.helperProportions.width/2<f&&l<o+t.helperProportions.height/2&&u-t.helperProportions.height/2<c;case"pointer":var h=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,p=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,d=e.ui.isOver(p,h,l,a,n.proportions.height,n.proportions.width);return d;case"touch":return(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c)&&(i>=a&&i<=f||s>=a&&s<=f||i<a&&s>f);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;o<r.length;o++){if(r[o].options.disabled||t&&!r[o].accept.call(r[o].element[0],t.currentItem||t.element))continue;for(var u=0;u<s.length;u++)if(s[u]==r[o].element[0]){r[o].proportions.height=0;continue e}r[o].visible=r[o].element.css("display")!="none";if(!r[o].visible)continue;i=="mousedown"&&r[o]._activate.call(r[o],n),r[o].offset=r[o].element.offset(),r[o].proportions={width:r[o].element[0].offsetWidth,height:r[o].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r=e.ui.intersect(t,this,this.options.tolerance),i=!r&&this.isover==1?"isout":r&&this.isover==0?"isover":null;if(!i)return;var s;if(this.options.greedy){var o=this.options.scope,u=this.element.parents(":data(droppable)").filter(function(){return e.data(this,"droppable").options.scope===o});u.length&&(s=e.data(u[0],"droppable"),s.greedyChild=i=="isover"?1:0)}s&&i=="isover"&&(s.isover=0,s.isout=1,s._out.call(s,n)),this[i]=1,this[i=="isout"?"isover":"isout"]=0,this[i=="isover"?"_over":"_out"].call(this,n),s&&i=="isout"&&(s.isout=0,s.isover=1,s._over.call(s,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i<r.length;i++){var s=e.trim(r[i]),o="ui-resizable-"+s,u=e('<div class="ui-resizable-handle '+o+'"></div>');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),i<u.maxWidth&&(u.maxWidth=i),o<u.maxHeight&&(u.maxHeight=o);this._vBoundaries=u},_updateCache:function(e){var t=this.options;this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e,t){var n=this.options,i=this.position,s=this.size,o=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),o=="sw"&&(e.left=i.left+(s.width-e.width),e.top=null),o=="nw"&&(e.top=i.top+(s.height-e.height),e.left=i.left+(s.width-e.width)),e},_respectSize:function(e,t){var n=this.helper,i=this._vBoundaries,s=this._aspectRatio||t.shiftKey,o=this.axis,u=r(e.width)&&i.maxWidth&&i.maxWidth<e.width,a=r(e.height)&&i.maxHeight&&i.maxHeight<e.height,f=r(e.width)&&i.minWidth&&i.minWidth>e.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r<this._proportionallyResizeElements.length;r++){var i=this._proportionallyResizeElements[r];if(!this.borderDif){var s=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],o=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];this.borderDif=e.map(s,function(e,t){var n=parseInt(e,10)||0,r=parseInt(o[t],10)||0;return n+r})}i.css({height:n.height()-this.borderDif[0]-this.borderDif[2]||0,width:n.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.right<i||a.top>u||a.bottom<s):r.tolerance=="fit"&&(f=a.left>i&&a.right<o&&a.top>s&&a.bottom<u),f?(a.selected&&(a.$element.removeClass("ui-selected"),a.selected=!1),a.unselecting&&(a.$element.removeClass("ui-unselecting"),a.unselecting=!1),a.selecting||(a.$element.addClass("ui-selecting"),a.selecting=!0,n._trigger("selecting",t,{selecting:a.element}))):(a.selecting&&((t.metaKey||t.ctrlKey)&&a.startselected?(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.$element.addClass("ui-selected"),a.selected=!0):(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.startselected&&(a.$element.addClass("ui-unselecting"),a.unselecting=!0),n._trigger("unselecting",t,{unselecting:a.element}))),a.selected&&!t.metaKey&&!t.ctrlKey&&!a.startselected&&(a.$element.removeClass("ui-selected"),a.selected=!1,a.$element.addClass("ui-unselecting"),a.unselecting=!0,n._trigger("unselecting",t,{unselecting:a.element})))}),!1},_mouseStop:function(t){var n=this;this.dragged=!1;var r=this.options;return e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?r=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(r=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?r=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(r=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var i=this.items.length-1;i>=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(t){var n=this.options.axis==="x"||e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),r=this.options.axis==="y"||e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),i=n&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o=="right"||s=="down"?2:1:s&&(s=="down"?2:1):!1},_intersectsWithSides:function(t){var n=e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),r=e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s=="right"&&r||s=="left"&&!r:i&&(i=="down"&&n||i=="up"&&!n)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!=0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]==e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n=this.items,r=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],i=this._connectWith();if(i&&this.ready)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u<c;u++){var h=e(l[u]);h.data(this.widgetName+"-item",f),n.push({item:h,instance:f,width:0,height:0,left:0,top:0})}}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var n=this.items.length-1;n>=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)<s&&(s=Math.abs(c-f),o=this.items[l],this.direction=h?"up":"down")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.top<this.containment[1]||u-this.offset.click.top>this.containment[3]?u-this.offset.click.top<this.containment[1]?u+n.grid[1]:u-n.grid[1]:u:u;var a=this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0];s=this.containment?a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2]?a-this.offset.click.left<this.containment[0]?a+n.grid[0]:a-n.grid[0]:a:a}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i==this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS)if(this._storedCSS[i]=="auto"||this._storedCSS[i]=="static")this._storedCSS[i]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!n&&r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(var i=this.containers.length-1;i>=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&(r.active===!1||r.active==null)&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.uiBackCompat!==!1&&(function(e,t){e.extend(t.options,{navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}});var n=t._create;t._create=function(){if(this.options.navigation){var t=this,r=this.element.find(this.options.header),i=r.next(),s=r.add(i).find("a").filter(this.options.navigationFilter)[0];s&&r.add(i).each(function(n){if(e.contains(this,s))return t.options.active=Math.floor(n/2),!1})}n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{heightStyle:null,autoHeight:!0,clearStyle:!1,fillSpace:!1});var n=t._create,r=t._setOption;e.extend(t,{_create:function(){this.options.heightStyle=this.options.heightStyle||this._mergeHeightStyle(),n.call(this)},_setOption:function(e){if(e==="autoHeight"||e==="clearStyle"||e==="fillSpace")this.options.heightStyle=this._mergeHeightStyle();r.apply(this,arguments)},_mergeHeightStyle:function(){var e=this.options;if(e.fillSpace)return"fill";if(e.clearStyle)return"content";if(e.autoHeight)return"auto"}})}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options.icons,{activeHeader:null,headerSelected:"ui-icon-triangle-1-s"});var n=t._createIcons;t._createIcons=function(){this.options.icons&&(this.options.icons.activeHeader=this.options.icons.activeHeader||this.options.icons.headerSelected),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){t.activate=t._activate;var n=t._findActive;t._findActive=function(e){return e===-1&&(e=!1),e&&typeof e!="number"&&(e=this.headers.index(this.headers.filter(e)),e===-1&&(e=!1)),n.call(this,e)}}(jQuery,jQuery.ui.accordion.prototype),jQuery.ui.accordion.prototype.resize=jQuery.ui.accordion.prototype.refresh,function(e,t){e.extend(t.options,{change:null,changestart:null});var n=t._trigger;t._trigger=function(e,t,r){var i=n.apply(this,arguments);return i?(e==="beforeActivate"?i=n.call(this,"changestart",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel}):e==="activate"&&(i=n.call(this,"change",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel})),i):!1}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{animate:null,animated:"slide"});var n=t._create;t._create=function(){var e=this.options;e.animate===null&&(e.animated?e.animated==="slide"?e.animate=300:e.animated==="bounceslide"?e.animate={duration:200,down:{easing:"easeOutBounce",duration:1e3}}:e.animate=e.animated:e.animate=!1),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype))})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).toggleClass("ui-state-active"),t.buttonElement.attr("aria-pressed",t.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.9.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||"&#160;",s,o,u,a,f;s=(this.uiDialog=e("<div>")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("<div>")).addClass("ui-dialog-titlebar  ui-widget-header  ui-corner-all  ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("<a href='#'></a>").addClass("ui-dialog-titlebar-close  ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("<span>")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("<span>").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("<div>")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("<div>")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("<button></button>",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||"&#160;"))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()<e.ui.dialog.overlay.maxZ)return!1})},1),e(window).bind("resize.dialog-overlay",e.ui.dialog.overlay.resize));var n=this.oldInstances.pop()||e("<div>").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t<n?e(window).height()+"px":t+"px"):e(document).height()+"px"},width:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),n=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),t<n?e(window).width()+"px":t+"px"):e(document).width()+"px"},resize:function(){var t=e([]);e.each(e.ui.dialog.overlay.instances,function(){t=t.add(this)}),t.css({width:0,height:0}).css({width:e.ui.dialog.overlay.width(),height:e.ui.dialog.overlay.height()})}}),e.extend(e.ui.dialog.overlay.prototype,{destroy:function(){e.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"<em>Loading&#8230;</em>"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1<this.anchors.length?1:-1)),n.disabled=e.map(e.grep(n.disabled,function(e){return e!==t}),function(e){return e>=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"<div></div>"},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function d(e){var n=o(),r=n._rgba=[];return e=e.toLowerCase(),h(s,function(t,i){var s,o=i.re.exec(e),a=o&&i.parse(o),f=i.space||"rgba";if(a)return s=n[f](a),n[u[f].cache]=s[u[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&t.extend(r,c.transparent),n):c[e]}function v(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var r="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),i=/^([\-+])=\s*(\d+\.?\d*)/,s=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],o=t.Color=function(e,n,r,i){return new t.Color.fn.parse(e,n,r,i)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},a={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},f=o.support={},l=t("<p>")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n<t.length;n++)t[n]!==null&&e.data(r+t[n],e[0].style[t[n]])},restore:function(e,n){var i,s;for(s=0;s<n.length;s++)n[s]!==null&&(i=e.data(r+n[s]),i===t&&(i=""),e.css(n[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);
\ No newline at end of file
index 2b8a9ca..2b99be1 100644 (file)
                                                        </td>
                                                 {%endif%}              
                                                </tr>
+                                       <tr class="even" id="sfi_config_row">
+                                               <td class="key">sfi_config </td>
+                                               <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_sfi_config">
+                                                                       <span class="glyphicon glyphicon-download"></span> Download 
+                                                               </button>
+                                               </td>
+                        </tr>
                                                <tr class="even">
                                                <td colspan="2">
                                                        <p class="message" id="pkey_del_msg"><b> Tradeoff:</b> Ease-of-use vs Security.<br>
index 0f2ecb5..9bc52dd 100644 (file)
@@ -69,11 +69,22 @@ $(document).ready(function() {
         slices = user.slices;
         drawSlices(slices);
     }
+
+    /*
+        Launch queries to get the resources and leases in Manifold Cache
+    */
+        
     function drawSlices(slices){
         var items = [];
                
         $.each( slices, function(i, val) {
             items.push( "<li><a href=\"/resources/"+val+"\">" + val + "</a></li>" );
+            /*
+            // Launch a Query for each slice to get resources and leases in Manifold Cache
+            // Now only done in Homeview to speed up the other pages
+            $.post("/rest/slice/", { 'filters': { 'slice_hrn' : val } }, function(data) {
+            });
+            */
         });
         $("div#home-slice-list").html($( "<ul/>", { html: items.join( "" ) }));
         $("ul#dropdown-slice-list").append(items.join( "" ));
index 91998cb..b0c3b6d 100644 (file)
     <div class="tab-pane active row" id="about">
                <div class="col-md-12">
                        <p>
-                               Fed4Fire Portal is a central place to get acess to all Fed4fire testbeds.In order to get access to the portal,
+                               Fed4FIRE Portal is a central place to get acess to all Fed4FIRE testbeds.In order to get access to the portal,
                                an experimenter needs to  <a href="/portal/register">register</a> to the portal. The portal administrative body
                                is responsible to accept or reject newly registered users.   
                        </p>
                        <p>
-                               To learn more about Fed4fire visit:  <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>                      
+                               To learn more about Fed4FIRE visit:  <a href="http://www.fed4fire.eu/" target="_blank">http://www.fed4fire.eu/</a>                      
                        </p>
                        <p>
                                If you have any questions regarding using the portal visit our <a href="/portal/support/">FAQ</a>
                        </p>
                        <p>
-                               Fed4fire portal is a community effot. To get more information about Fed4fire portal team visit: 
+                               Fed4FIRE portal is a community effot. To get more information about Fed4FIRE portal team visit: 
                                <a href="http://myslice.info/community" target="_blank">http://myslice.info/community</a>
                        </p>
                </div>
@@ -80,8 +80,8 @@
                                        <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>Fed4fire Registry</h5>
-                                       <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4fire registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
+                               <h5>Fed4FIRE Registry</h5>
+                                       <p><a href="https://sfa-fed4fire.pl.sophia.inria.fr" target="_blank">Fed4FIRE registry</a> is a SFA registry. SFA Registry is a specific installation mode of the SFAWrapper.</p>
                                        <p> More Info: <a href="http://svn.planet-lab.org/wiki/SfaDeveloperRegistryTutorial#RunninginRegistry-Onlymode" target="_blank">SFA Registry</a></p>
        </div>
    </div>
index ac85870..6163459 100644 (file)
@@ -1,7 +1,20 @@
-{% extends "layout_wide.html" %}
+{% extends "layout.html" %}
 {% block content %}
 
+<div class="row">
+       <div class="col-md-12">
+                <div class="breadcrumbs">
+                        Account &nbsp;>&nbsp; <a href="/account">{{ person.email }}</a>
+                </div>
+       </div>
+        {%if 'no_creds'  in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+    {%endif%}
+        {%if 'creds_expired'  in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
 
+</div>
 {% if messages %}
 <ul class="messages">
     {% for message in messages %}
     {% endfor %}
 </ul>
 {% endif %}
-<div class="container">
-       <div class="row">
-               <div class="col-md-12">
-                       <ul class="nav nav-tabs nav-section">
-                               <li class="active"><a href="#profile"><img src="{{ STATIC_URL }}icons/user-xs.png" alt="User Account" /> User Profile</a></li>
-                               <li><a href="#account">Account</a></li>
-                               <li><a href="#access">Testbed Access</a></li>
-                       </ul>
-           </div>
-       </div>
+<div class="row">
+       <div class="col-md-12">
+               <ul class="nav nav-tabs nav-section">
+                       <li class="active"><a href="#profile">User Profile</a></li>
+                       <li><a href="#account">Account</a></li>
+                       <li><a href="#access">Testbed Access</a></li>
+               </ul>
+    </div>
 </div>
-<div class="container tab-content">
+<div class="tab-content">
        <div class="tab-pane active row" id="profile">
                
                <div class="col-md-12">
                                        <table class="profile">          
                                        <tr>
                                                <td colspan="2">
-                                                               <div>Platform: Myslice</div>
+                                                               <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 btn-xs" type="button" id="edit_email" onclick="editAlert();"  title="To change your affiliation please contact the administrator">
+                                                               <button class="btn btn-default" type="button" id="edit_email" onclick="editAlert();"  title="To change your affiliation please contact the administrator">
                                                                <span class="glyphicon glyphicon-question-sign"></span> Edit
                                                                </button>
                                                        </td>
                                                <tr class="even">
                                                        <td class="key">Generate Keys</td>
                                                        <td>
-                                                               <input type="submit" name="generate" class="btn btn-danger btn-xs" value="Generate a new Key Pair" id="generate_keypair" 
+                                                               <input type="submit" name="generate" class="btn btn-primary" value="Generate a new Key Pair" id="generate_keypair" 
                                                                           onclick="return confirm('Are you sure? If you do so, your current credentials will be overwritten.');" 
                                                                           title="It will generate a new key Pair and your current credentials will be overwritten."/>
                                                </td> 
                                                <td class="value">
                                                                <span id="keyval" class="value">******** </span>
                                                                <span class="hide_this" id="span_upload">
-                                                                       <button type="button" class="btn btn-default btn-xs" title="Cancel" id="cancel_upload"> Cancel </button>
+                                                                       <button type="button" class="btn btn-default" title="Cancel" id="cancel_upload"> Cancel </button>
                                                                        <div style='display:none;'>
                                                                                <input type='hidden'  name='upload'  /></div>
                                                                                <input type="file" name="pubkey" class="required" id="pubkey"/>  
                                                 {%if 'N/A' not in user_private_key%}
                                                <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default" title="Download your privaye key" id="dl_pkey">
                                                                        <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"
                                                  {%else%}
                                                        <td class="key">Private Key </td> <!-- Hide if priv_key doesn't exist in myslice platform   -->
                                                        <td class="value">********<a href="#"></a>
-                                                       <button type="submit" name="dl_pkey" class="btn btn-default btn-xs disabled" title="Download your privaye key" id="dl_pkey">
+                                                       <button type="submit" name="dl_pkey" class="btn btn-default disabled" title="Download your privaye key" id="dl_pkey">
                                                                <span class="glyphicon glyphicon-download"></span> Download 
                                                        </button>
                                                        <input class="btn btn-danger btn-xs disabled" id="delete" name="delete" type="submit" title="Delete your private key" value="Delete" />
                                                        </td>
                                                 {%endif%}              
                                                </tr>
+                                       <tr class="even" id="sfi_config_row">
+                                               <td class="key">sfi_config </td>
+                                               <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your sfi_config" id="dl_sfi_config">
+                                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                                               </button>
+                                               </td>
+                        </tr>
                                                <tr class="odd">
                                                        {%if 'N/A' not in user_private_key%}
                                                        <td class="key">Identity</td> 
                                                        </td>
                                                        {%endif%} 
                                                </tr>
+
                                                <tr class="even">
                                                <td colspan="2">
-                                                       <p class="message" id="pkey_del_msg"><b> Tradeoff:</b> Ease-of-use vs Security.<br>
-                                                                       <b>Ease-of-use:</b> Automatic account delegation. Don't delete private key.<br>
-                                                                       <b>Security:</b> Manual account delegation. Download & Delete private key.
+                                                               <p class="command">
+                                                                       <a href="#" style="color:green" data-toggle="modal" data-target="#tradeoffmodal">Automatic vs. Manual delegation of credentials:</a>
+                                                                       Trade-off between ease-of-use & security</p>
                                                                </p>
                                                </td>
                                                </tr>
                                                        <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>
+                             <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%}
                                {%endif%}
                </div>
        </div>
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+            <div class="modal-dialog">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+                    </div>
+                                       <div class="modal-body" style="text-align:justify;">
+                                       <p>You are getting this message for any of the following reasons:</p>
+                                       <ul>
+                                               <li>If your account is still pending for validation</li>
+                                               <li>If you press the "Clear Credentials" button</li>
+                                               <li>If you "Generate a new key pair"</li>
+                                               <li>If a new slice is added to your account</li>
+                                       </ul>
+                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
+                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
+                                               then please logout and login back into to the portal.
+                                       </p>
+                                       <h3>Manual delegation of credentials</h3>
+                                               <p>
+                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
+                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
+                                                       delegated to the portal, please follow these instructions:
+                                               </p>
+                                               <ul>
+                                                       <li>Your account must first be validated by the manager of your organization.</li>
+                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
+                                               </ul>
+                                       </p>
+                                       <h3>Contact support</h3>
+                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                    </div>
+                </div>
+            </div>
+</div>
+
+
+<!-- Modal- Trade-off Message  -->
+<div class="modal fade" id="tradeoffmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+            <div class="modal-dialog">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                            <h4 class="modal-title" id="myModalLabel">
+                                                               Automatic vs. Manual delegation of credentials
+                                                       </h4>
+                    </div>
+                                       <div class="modal-body" style="text-align:justify;">
+                                       <h3>Automatic delegation of credentials</h3>
+                                               <p>Don't delete private key, ease-of-use option:</p>
+                                               <ul>
+                                                       <li>
+                                                               This means that you will keep your private key in the portal and it will automatically delegate your credentials on your behalf.
+                                                       </li>
+                                                       <li>
+                                                               This option does not provide as high of a level of security; however, your private key will still only be used in the portal and 
+                                                               will be available to you and the Fed4FIRE admins only.
+                                                       </li>
+                                               </ul>
+                                       <h3>Manual delegation of credentials</h3>
+                                               <p>Download & Delete private key, higher security option:</p>
+                                               <ul>
+                                                       <li>If you delete your private key, you will have more security but the portal will no longer be able to delegate credentials 
+                                                               on your behalf, and you will have to manually
+                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a>
+                                                       </li>
+                                               </ul>
+                                       <h3>Contact support</h3>
+                                       <p>For more information, please  <a href="/contact/" target="_blank">contact us</a>.</p>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                    </div>
+                </div>
+            </div>
+</div>
+
+
 
        <div class="tab-pane row" id="access">
                <div class="col-md-12">
                 <td class="odd"> {{ row.account_type }} </td>
                                <td class="odd"> {{ row.account_reference }} </td>
                                <td class="odd">
-                               <button class="btn btn-danger btn-xs" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
+                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform">
                                                <span class="glyphicon glyphicon-minus"></span>
                                        </button>
                                </td>
diff --git a/portal/templates/fed4fire/fed4fire_base.html b/portal/templates/fed4fire/fed4fire_base.html
deleted file mode 100644 (file)
index 7eaaf05..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-{# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
-<title>Fed4Fire Portal - {{ 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/fed4fire/fed4fire_email_activation.html b/portal/templates/fed4fire/fed4fire_email_activation.html
new file mode 100644 (file)
index 0000000..ae7627a
--- /dev/null
@@ -0,0 +1,21 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+<div class="row">
+       <h1><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="User Registration" />User sign-up</h1>
+</div>
+<div class="row">
+       {% if activation_status == 'success' %}
+               <h3>Signup request confirmed.</h3>
+               <p>You are currently able to log in to the portal using your email address and the password that you have provided; however, your access is still limited.</p> 
+               <p>You will have full access as soon as your account is validated by a manager at your organization. We have sent an email to your organisation's managers with a validation request.</p>
+       {%else%}
+               <h3>Signup confirmation failed.</h3>
+               <p>You have probably arrived at this page by clicking a confirmation link in an email that we have sent to you. 
+               We have been unable to match the link that you have clicked to a signup request in our database.</p>
+               <p>Please <a href="/portal/contact/">contact support</a> so that we may help you complete the signup process.</p>
+       {%endif%}
+ </div>
+
+{% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_email_default_recipients.txt b/portal/templates/fed4fire/fed4fire_email_default_recipients.txt
new file mode 100644 (file)
index 0000000..b2de7ee
--- /dev/null
@@ -0,0 +1 @@
+Fed4FIRE Support <contact@fed4fire.eu>
diff --git a/portal/templates/fed4fire/fed4fire_footer.html b/portal/templates/fed4fire/fed4fire_footer.html
new file mode 100644 (file)
index 0000000..d4db4be
--- /dev/null
@@ -0,0 +1 @@
+<!--No foorter added for the moment -->
index 09e4731..385f698 100644 (file)
@@ -6,8 +6,56 @@
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
+<!-- Modal- No credentials -->
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+            <div class="modal-dialog">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                            <h4 class="modal-title" id="myModalLabel">No credentials are delegated to the portal</h4>
+                    </div>
+                    <div class="modal-body" style="text-align:justify;">
+                                       <p>You are getting this message for any of the following reasons:</p>
+                                       <ul>
+                                               <li>If your account is still pending for validation</li>
+                                               <li>If you press the "Clear Credentials" button</li>
+                                               <li>If you "Generate a new key pair"</li>
+                                               <li>If a new slice is added to your account</li>
+                                       </ul>
+                                       <p>Unless your account has not yet been validated, it is sufficient to refresh the page or go back to the home page. 
+                                               The portal will then regenerate your credentials. In some cases it may take more time than usual. If nothing works, 
+                                               then please logout and login back into to the portal.
+                                       </p>
+                                       <h3>Manual delegation of credentials</h3>
+                                               <p>
+                                                       You have selected upon sign-up to upload your public key. As you have uploaded your own public key, 
+                                                       the portal can no longer generate your credentials automatically. In order to have your credentials 
+                                                       delegated to the portal, please follow these instructions:
+                                               </p>
+                                               <ul>
+                                                       <li>Your account must first be validated by the manager of your organization.</li>
+                                                       <li>In order for the portal to contact testbeds on your behalf, so as to list and reserve resources, you will need to
+                                                               <a href="/portal/manual_delegation" target="_blank">delegate your credentials to the portal.</a></li>
+                                               </ul>
+                                       </p>
+                                       <h3>Contact support</h3>
+                                       <p>If you don't have the above mentioned cases and still have this message, please  <a href="/contact/" target="_blank">contact us</a>.</p>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                    </div>
+                </div>
+            </div>
+</div>
 <div class="container dashboard">
        <div class="row">
+       {%if 'no_creds'  in user_cred %}
+       <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
+       {%endif%}
+       {%if 'creds_expired'  in user_cred %}
+       <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
+               {%if 'is_pi'  in pi %}
                <div class="col-md-3">
                        <h3>
                                EXPERIMENT
                                <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
                        </div>
                        <div>
-                               <button id="slicerequestbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
+                       </div>
+                       <div>
+                               <p><strong>Your slices </strong>
+                                       <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
+                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                                       those slices will not appear here."
+                                       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>
-                <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
-                        </div>
-                       <div>
-                                       <a class="btn btn-primary" style="width: 150px;" 
-                    href='http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp'
+                       <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
+                       <a class="btn btn-primary" style="width: 150px;" 
+                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
                                        title="Click here to start your experiment with jFed" 
-                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/r1389/webstart/experimenter/jfed-experimenter.jnlp');">
+                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
                     <span class="glyphicon glyphicon-cloud"></span> jFed</a>
-                       </div>
                </div>
                <div class="col-md-3">
                        <h3>MANAGEMENT</h3>
                                SUPPORT
                        </h3>
                        <div>
-                               <a href="http://doc.fed4fire.eu/support.html"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
                        </div>
                        <div>
-                               <button id="ticketbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
                        </div>
                        <p></p>
                        <div>
                        <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
                        </div>
+                       <div>
+                       <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
+                       </div>
                </div>
                
                <div class="col-md-3">
                                <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
                        </div>
                        <div>
-                               <button id="logoutbtn" type="button" style="width: 150px;" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
+                               <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 Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                                       those slices will not appear here."
+                                       class="glyphicon glyphicon-info-sign">
+                               </span>
+                               </p>
+                       </div>
+                       <div>   
+                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                       </div>
+                       {% if pending_slices %}
+                       <p><strong>Pending slices</strong>
+                       <span title="Slices that you have requested and are pending for validation by the contact person of your organization."
+                               class="glyphicon glyphicon-info-sign">
+                       <ul>
+                       {% for slices in pending_slices %}
+                       <li>{{slices}}</li>
+                       {% endfor %}
+                       </ul>
+                       </span>
+                       </p>
+                       {%endif%}
+                       <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
+                       <a class="btn btn-primary" style="width: 150px;" 
+                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
+                                       title="Click here to start your experiment with jFed" 
+                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
+                    <span class="glyphicon glyphicon-cloud"></span> jFed</a>   
+               </div>
+               <div class="col-md-4">
+                       <h3>
+                               SUPPORT
+                       </h3>
+                       <div>
+                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
+                       </div>
+                       <div>
+                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
+                       </div>
+                       <p></p>
+                       <div>
+                       <button id="statbtn" type="button" style="width: 150px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' status</button>
+                       </div>
+                       <div>
+                       <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
+                       </div>
+               </div>
+               
+               <div class="col-md-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">Email:</span> <a href='/portal/account/'>{{person.email}}</a>
+                       <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#'+$(this).data('panel')).show();
                });
                $('button#validaterequestbtn').click(function() {
-                       window.location="/portal/validate/";
+                       window.location="/portal/institution#requests";
                });
                $('button#ticketbtn').click(function() {
                        window.location="/portal/contact/";
                $('button#statbtn').click(function() {
                window.location="https://flsmonitor.fed4fire.eu";
                });
+                $('button#repbtn').click(function() {
+               window.location="/portal/reputation";
+                });
                $('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
---------*/
+
+        myslice.loadSlices();
 });
 </script>
+
+<!--for jfed tool-->
 <script type="text/javascript" src="{{STATIC_URL}}js/fed4fire_dtjava_orig.js"></script>
 <script>
        function launchApplication(jnlpfile) {
@@ -146,4 +289,7 @@ This should go into session
         return false;
      }
 </script>
+{# widget "_widget-monitor.html" #}
+{# widget "_widget-stats-top-slices.html" #}
+
 {% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_institution.html b/portal/templates/fed4fire/fed4fire_institution.html
new file mode 100644 (file)
index 0000000..bd361de
--- /dev/null
@@ -0,0 +1,185 @@
+{% extends "layout_wide.html" %}
+
+{% block head %} 
+<script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
+{% endblock head %}
+
+{% block content %}
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Management &nbsp;>&nbsp; Institution: <span id="authority_name"></span>
+                        </div>
+               </div>
+       </div>
+</div>
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                       <ul class="nav nav-tabs nav-section">
+                               <li class="active"><a href="#about">About</a></li>
+                               <li><a href="#users">Users</a></li>
+                               <li><a href="#slices">Slices</a></li>
+                               <li><a href="#requests">Requests</a></li>
+                       </ul>
+           </div>
+       </div>
+</div>
+<div class="container tab-content">
+       <div class="tab-pane active row" id="about">
+       </div>
+       
+       <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
+               <div class="col-md-12 el">
+                       <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                               <div id="user-tab-loaded" style="display:none;">
+                               <table id="user-tab" class="table">
+                                       <tr>
+                                       <th>+/-</th>
+                                       <th>Email</th>
+                                       <th>User hrn</th>
+                            <!--
+                                       <th>First name</th>
+                                       <th>Last name</th>
+                                       <th>Enabled</th>
+                            -->
+                                       </tr>
+                               </table>
+                               
+                       </div>
+                       {%if 'is_pi'  in pi %}  
+                       <div>
+                               <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+                       </div>
+                       {% endif %}
+               </div>
+       </div>
+
+       <div class="tab-pane row" id="slices">
+               <div class="col-md-12 el">
+           <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+           <div id="slice-tab-loaded" style="display:none;">
+               <table id="slice-tab" class="table">
+                   <tr>
+                       <th>+/-</th>
+                       <th>Slice hrn</th>
+                       <th>Users</th>
+                       <th>Url</th>
+                       <!-- <th>nodes</th> -->
+                       <th>Creation</th>
+                   </tr>
+               </table>                        
+           </div>
+       {% if 'is_pi'  in pi %}
+        <div>
+               {% if 'is_pi'  in pi %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+                       {% else %}
+                       <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                       {% endif %}
+            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+        </div>
+               {% endif %} 
+          </div>
+       </div>
+       <div class="tab-pane row" id="requests">
+       </div>
+</div>
+<script>
+$(document).ready(function() {
+    {% if person %}
+    {% if user_details.parent_authority %}
+
+        $.post("/rest/slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+            var list_slices = [];
+            var table_slices = [];
+            /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
+            $.each( data, function( key, val ) {
+                list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
+                if(val.nodes=="undefined" || val.nodes==null){
+                    nodes_length=0;
+                }else{
+                    nodes_length=val.nodes.length;
+                }
+                console.log(val);
+                if(val.users=="undefined" || val.users==null){
+                    users_length=0;
+                }else{
+                    users_length=val.users.length;
+                }
+
+                if(val.url=="undefined" || val.url==null){
+                    slice_url="";
+                }else{
+                    slice_url="<a href='"+val.url+"' target='_blank'>"+val.url+"</a>";
+                }
+                
+                slice_row = "<tr id='"+val.slice_hrn+"'>";
+                slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
+                slice_row += "<td><a href=\"/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></td>";
+                slice_row += "<td>"+users_length+"</td>";
+                slice_row += "<td>"+slice_url+"</td>";
+                //slice_row += "<td>"+nodes_length+"</td>";
+                slice_row += "<td>"+val.slice_date_created+"</td>";
+                slice_row += "</tr>";
+                table_slices.push(slice_row);
+                
+            });
+           
+            /* $("div#slice-list").html($( "<ul/>", { html: list_slices.join( "" ) })); */
+            $("table#slice-tab tr:last").after(table_slices.join( "" ));
+            $("div#slice-tab-loaded").css("display","block");
+            $("div#slice-tab-loading").css("display","none");
+        });
+               
+               
+        $.post("/rest/user/",{'fields':['user_hrn','user_email'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
+            var list_users = [];
+            var table_users = [];
+                   /* Available fields
+                   user_gid, user_enabled, slices, pi_authorities, keys, parent_authority, user_first_name,
+                   user_urn, user_last_name, user_phone, user_hrn, user_email, user_type
+                   */
+            $.each( data, function( key, val ) {
+                list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
+                user_row = "<tr id='"+val.user_hrn+"'>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"'></td>";
+                user_row += "<td>"+val.user_email+"</td>";
+                user_row += "<td>"+val.user_hrn+"</td>";
+                /*
+                user_row += "<td>"+val.user_first_name+"</td>";
+                user_row += "<td>"+val.user_last_name+"</td>";
+                           user_row += "<td>"+val.user_enabled+"</td>";
+                */
+                user_row += "</tr>";
+                table_users.push(user_row);
+            });
+            $("table#user-tab tr:last").after(table_users.join( "" ));
+            $("div#user-tab-loaded").css("display","block");
+            $("div#user-tab-loading").css("display","none");
+        });
+
+    {% endif %}
+    {% endif %}
+
+}); // End document.ready
+
+$(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+               e.preventDefault();
+               $(this).tab('show');
+       var id = $(this).attr('href').substr(1);
+       if ((id == 'requests') || (id == 'about'))
+               $("#" + id).load('/management/' + id);
+       });
+       var hash = window.location.hash;
+       if (hash) {
+               $('.nav-tabs a[href='+hash+']').click();
+       } else {
+               $('.nav-tabs a[href=#about]').click();
+       }
+});
+</script>
+{% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_management-tab-about.html b/portal/templates/fed4fire/fed4fire_management-tab-about.html
new file mode 100644 (file)
index 0000000..bc768a6
--- /dev/null
@@ -0,0 +1,71 @@
+{% 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 />
+    {% if authority.name and authority.url %}
+       <h3><a href="{{authority.url}}">{{authority.name}}</a></h3>
+    {% elif authority.name %}
+       <h3>{{authority.name}}</h3>
+    {% endif %}
+       <p>
+    {% if authority.address %}
+               {{authority.address}} <br />
+    {% endif %}
+    {% if authority.postcode %}
+               {{authority.postcode}} 
+    {% endif %}
+    {% if authority.address %}
+        {{authority.city}} <br />
+    {% endif %}
+    {% if authority.address %}
+               {{authority.country}}
+    {% endif %}
+       </p>
+       <br />
+
+    {% if authority.address %}
+       <h4>Onelab membership</h4> 
+       <p>
+               {{ authority.onelab_membership }}
+       </p>
+    {% endif %}
+</div>
+<div class="col-md-6">
+    {% if authority.legal %}
+       <h4>Legal Contact:</h4>
+       <p>
+       {% for c in authority_contacts.legal %}
+                {{ c }} <br />
+       {% endfor %}
+       </p>
+       <br />
+    {% endif %}
+    {% if authority.scientific %}
+       <h4>Scientific Contact:</h4>
+       <p>
+       {% for c in authority_contacts.scientific %}
+               {{ c }} <br />
+       {% endfor %}
+       </p>
+       <br />
+    {% endif %}
+    {% if authority.technical %}
+       <h4>Technical Contact:</h4>
+       <p>
+       {% for c in authority_contacts.technical %}
+               {{ c }} <br />
+       {% endfor %}
+       </p>
+    {% endif %}
+</div>
+<script>$(document).ready(function() {
+{% if authority.name %}
+    auth_name = "{{authority.name}}";
+{% else %}
+    auth_name = "{{authority.authority_hrn}}";
+{% endif %}
+    $('#authority_name').text(auth_name);
+});
+</script>
diff --git a/portal/templates/fed4fire/fed4fire_management-tab-requests.html b/portal/templates/fed4fire/fed4fire_management-tab-requests.html
new file mode 100644 (file)
index 0000000..e255779
--- /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>From your 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' %}
+            <b>{{request.first_name}} {{request.last_name}}</b> <a href="mailto:{{request.email}}">{{request.email}}</a>
+        {% else %}
+            {% if request.type == 'slice' %}
+            <b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+            {% else %} {# authority #}
+            <b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{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>From your 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>From your 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/fed4fire/fed4fire_slice-resource-view.html b/portal/templates/fed4fire/fed4fire_slice-resource-view.html
new file mode 100644 (file)
index 0000000..3fefedf
--- /dev/null
@@ -0,0 +1,121 @@
+{% extends "layout_wide.html" %}
+{% load portal_filters %}
+
+{% block head %}
+<!-- <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC1RUj824JAiHRVqgc2CSIg4CpKHhh84Lw&sensor=false"></script> -->
+<script src="{{ STATIC_URL }}js/onelab_slice-resource-view.js"></script>
+<script>
+       //myslice.slice = "{{ slice }}";
+
+$(document).ready(function() {
+            $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+        // find the plugin object inside the tab content referenced by the current tabs
+        $('.plugin', $($(e.target).attr('href'))).trigger('shown.bs.tab');
+        $('.plugin', $($(e.target).attr('href'))).trigger('show');
+            });
+});
+</script>
+{% endblock %}
+
+{% block content %}
+{% widget '_widget-slice-sections.html' %}
+<div class="container-fluid container-resource">
+       <div class="row">
+       <div class="col-md-2">
+               <!-- <div id="select-platform" class="list-group"></div> -->
+               {{filter_testbeds}}
+       </div>
+       <div class="col-md-10" style="height:100%;">
+               <div class="row">
+                       {% if msg %}
+                       <div class="col-md-12"><p class="alert-success">{{ msg }}</p></div>
+                       {% endif %}
+               </div>
+       
+               <div class="row">
+                       <div class="col-md-6">
+                               {{ filter_status }}
+                       </div>
+                       <div class="col-md-1">
+                               {{ apply }}
+                       </div>
+               </div>
+               <!--
+               <div class="list-group-item list-resources">
+                       <span class="list-group-item-heading" style="padding-left: 0;">Resource status:</span>
+                       <a class="list-group-item active" data-panel="resources" href="#" style='display: inline-block !important;'>All</a>
+                       <a class="list-group-item" data-panel="reserved" href="#" style='display: inline-block !important;'>Reserved</a>
+                       <a class="list-group-item" data-panel="pending" href="#" style='display: inline-block !important;'>Pending <span class="badge" id="badge-pending" data-number="0"></span></a>
+               </div>
+               -->
+
+               <div class="row">
+                       <div class="col-md-12">
+                       <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="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
+                       </ul>
+                       </div>
+               </div>
+               
+               <!-- 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">Columns selector</h4>
+                               </div>
+                               <div class="modal-body">
+                                       {{columns_editor}}
+                               </div>
+                               <div class="modal-footer">
+                                       <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                               </div>
+                       </div>
+                       </div>
+               </div>
+               
+               
+               <div class="row">
+                       <div class="col-md-12">
+                       <div class="tab-content" style="height:100%;">
+                               <div class="tab-pane active" id="resourcelist">
+                                        <!-- Button trigger modal - columns selector -->
+                                       <button class="btn btn-default btn-sm" style="float:right;" data-toggle="modal" data-target="#myModal">...</button>
+                       {{list_resources}}
+                                       <!-- <table cellpadding="0" cellspacing="0" border="0" class="table" id="objectList"></table> -->
+                               </div>
+                               <div class="tab-pane" id="resourcemap">
+                       {{map_resources}}
+                               </div>
+                               <div class="tab-pane" id="resourcescheduler">
+                       {{scheduler}}
+                               </div>
+       
+                               <!--
+                               <div id="reserved" class="tab-pane" style="height:370px;display:none;">
+                       <table width="80%">
+                           <tr><th width="50%" style="text-align:center;">resources</th><th width="50%" style="text-align:center;">leases</th></tr>
+                           <tr>
+                               <td style="text-align:center">{{list_reserved_resources}}</td>
+                               <td style="text-align:center">{{list_reserved_leases}}</td>
+                           </tr>
+                       </table>
+                               </div>
+                               <div id="pending" class="tab-pane" style="height:370px;display:none;">
+                       {{pending_resources}}
+                               </div>
+                               <div id="sla_dialog" class="tab-pane" style="height:370px;display:none;">
+                       {{sla_dialog}}
+                               </div>
+       -->
+       
+                       </div>
+               </div>
+       </div>
+       </div>
+       </div>
+</div>
+{% endblock %}
diff --git a/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html b/portal/templates/fed4fire/fed4fire_slice-tab-experiment.html
new file mode 100644 (file)
index 0000000..0ca237f
--- /dev/null
@@ -0,0 +1,111 @@
+<div class="col-md-2">
+</div>
+<div class="col-md-8">
+       <h2>How to access your slice</h2>
+       <h3>PlanetLab Europe</h3>
+       
+       <p>
+               PlanetLab Europe resources are accessible directly via SSH. Your SSH public key is deployed automatically
+               on the reserved nodes. To access your slice on a resource just type the following command:
+       </p>
+       {%if ple_resources%}
+       <p class="command">
+       {%for resource in ple_resources %}
+               $ ssh {{ple_slicename}}@{{resource}}<br>
+       {%endfor%}
+       </p>
+        <h4>Windows users</h4>
+        <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+       {%else%}
+               <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
+               <p class="command">
+               $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
+               </p>
+                <h4>Windows users</h4>
+                <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+       {%endif%}
+       <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
+       <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
+       <p>
+               Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes, 
+               after witch you will be able to access the resource.
+       </p>
+       
+       <h3>NITOS</h3>
+       
+       <p>
+        NITOS resources are not directly accessible. You will need to log in on a gateway server and from there access the node.
+        The NITOS server address is nitlab.inf.uth.gr, so to connect to the NITOS server:
+       </p>
+       <p class="command">
+       $ ssh {{slicename}}@nitlab.inf.uth.gr
+       </p>
+       <h4>Windows users</h4>
+       <p>Use <a href="http://www.putty.org/" target="_blank">SSH client.</a></p>
+
+       <p>
+       <!-- In order to connect to NITOS server he has to upload his public key on the server. 
+       For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys. 
+       I think this is a procedure that needs to be done at the registration phase of the user, 
+       through myslice, Broker etc. but I will answer you in a couple of days for sure. -->
+       </p>
+
+       <p>
+               You will then need to prepare the resource by loading an OMF image on it:
+       </p>
+       
+       <p class="command">
+               $ omf load -i baseline_grid.ndz -t omf.nitos.node016
+       </p>
+
+       <p>
+               Turn on the node:
+       </p>
+       
+       <p class="command">
+               $ omf tell -a on -t omf.nitos.node016
+       </p>
+       <p>
+               And finally ssh on the node:
+       </p>
+       <p class="command">
+               $ ssh root@node016
+       </p>
+       <p>
+               On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
+               restart the OMF Resource Controller and finally execute the experiment:
+       </p>
+       <p class="command">
+               $ omf exec --slice slice_name your_exp.rb
+       </p>
+       <p>
+       The complete tutorial is available at the following address:
+       <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
+       </p>
+       
+       <br />
+       
+       <h2>Available Tools</h2>
+       <p><img src="{{ STATIC_URL }}img/terminal_icon.png" width="50"> <b>SSH</b></p>
+       <p>
+       Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers that connects, via a secure channel over an insecure network, a server and a client (running SSH server and SSH client programs, respectively). The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2.
+       </p>
+       <p> More Info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
+       <br>
+       <br>
+       <p><img src="{{ STATIC_URL }}img/nepi_logo.png" width="90"></p>
+       <p>NEPI, the Network Experimentation Programming Interface, is a life-cycle management tool for network experiments. The idea behind NEPI is to provide a single tool to design, deploy, and control network experiments, and gather the experiment results. Going further, NEPI was specially conceived to function with arbitrary experimentation platforms, so researchers could use a single tool to work with network simulators, emulators, or physical testbeds, or even a mixture of them. To accomplish this, NEPI provides a high-level interface to describe experiments that is independent from any experimentation platform, but is able to capture platform specific configurations. Experiment definitions can be stored in XML format to be later reproduced, and modified according to experimentation needs. Experiment execution is orchestrated by a global experiment controller, that is platform independent, and different platform-dependent testbed controllers, creating a control hierarchy that is able t adapt to platform specific requirements while providing an integrated control scheme.</p>
+       <p> More Info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
+       <br>
+       <p><img src="{{ STATIC_URL }}img/omf-logo.png" width="90"></p>
+       <p>OMF is a Testbed Control, Measurement and Management Framework.</p>
+       <p>
+       OMF was originally developed for the ORBIT wireless testbed at Winlab, Rutgers University. Since 2007, OMF has been actively extended to operate on testbeds with many different type of network and resource technologies. It is now deployed and used on different testbeds in Australia, Europe, and in the U.S. OMF is currently being extended further to support exciting new features and technologies. This website is hosting this ongoing activity. OMF development is now conducted essentially within the TEMPO project at NICTA (Australia) in strong collaboration with Winlab (Rutgers University).
+       </p>
+       <p>In addition to the main OMF software, this site also hosts OMF sub-projects addressing various related aspects of a testbed's control, measurement, and management.</p>
+       <p>More Info: <a href="http://mytestbed.net/projects/omf" target="_blank">http://mytestbed.net/projects/omf</a></p>
+</div>
+<div class="col-md-2">
+</div>
diff --git a/portal/templates/fed4fire/fed4fire_slice-view.html b/portal/templates/fed4fire/fed4fire_slice-view.html
new file mode 100644 (file)
index 0000000..c2d52c3
--- /dev/null
@@ -0,0 +1,18 @@
+{% 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/fed4fire/fed4fire_slice_request_denied.html b/portal/templates/fed4fire/fed4fire_slice_request_denied.html
new file mode 100644 (file)
index 0000000..ca2b910
--- /dev/null
@@ -0,0 +1,17 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):</p> 
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{url}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<br>c
+<p>We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. 
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on Fed4FIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_denied.txt b/portal/templates/fed4fire/fed4fire_slice_request_denied.txt
new file mode 100644 (file)
index 0000000..21897b4
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested the following slice on the Fed4FIRE portal({{portal_url}}):
+
+Slice name   : {{slice_name}}
+URL          : {{url}}
+Purpose      : {{purpose}}
+We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on Fed4FIRE.
+
+Yours sincerely,
+The Fed4FIRE team
+
index 888e032..1a49a14 100644 (file)
@@ -2,10 +2,21 @@
 <br>
 <h1>NEW SLICE REQUEST</h1>
 <br>
-<b>slice name      :</b> {{slice_name}}</br>
-<b>number of nodes :</b> {{number_of_nodes}}</br>
-<b>type of nodes   :</b> {{type_of_nodes}}</br>
-<b>purpose         :</b> {{purpose}}</br>
-<b>email           :</b> {{email}}</br>
+<p>You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.</p>
+<p>A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.</p>
+<br>
+<b>Slice name      :</b> {{slice_name}}</br>
+<b>URL                            :</b> {{url}}</br>
+<b>Purpose         :</b> {{purpose}}</br>
+<b>Organization           :</b> {{organization}}</br>
+<b>Email           :</b> {{email}}</br>
 <b>Portal url     :</b> {{current_site}}</br> 
+<p></p>
+<p>You can see new slice request <a href="http://{{current_site}}/portal/validate">in the portal.</a><p>
+<p>Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.</p>
+<p>And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.</p>
+<p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
+<p></p>
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu</p>
+
 
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_email.txt b/portal/templates/fed4fire/fed4fire_slice_request_email.txt
new file mode 100644 (file)
index 0000000..5b7ccb0
--- /dev/null
@@ -0,0 +1,20 @@
+NEW SLICE REQUEST
+
+You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.
+A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.
+
+Slice name      : {{slice_name}}
+URL                    : {{url}}
+Purpose         : {{purpose}}
+Email           : {{email}}
+Organization   : {{organization}}
+Portal url             : {{current_site}}
+
+You can see new slice request in: http://{{current_site}}/portal/validate
+Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.
+And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided. 
+Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done. 
+
+If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu
+
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_validated.html b/portal/templates/fed4fire/fed4fire_slice_request_validated.html
new file mode 100644 (file)
index 0000000..fbcbea8
--- /dev/null
@@ -0,0 +1,21 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested a slice in the Fed4FIRE portal.</p>
+<br>
+<b>Slice name   :</b> {{slice_name}}<br>
+<b>URL          :</b> {{url}}<br>
+<b>Purpose      :</b> {{purpose}}<br>
+<p></p>
+<p>
+       We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal. 
+       You can now add resources to you slice and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_slice_request_validated.txt b/portal/templates/fed4fire/fed4fire_slice_request_validated.txt
new file mode 100644 (file)
index 0000000..a89be97
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested a slice in the Fed4FIRE portal.
+
+Slice name      : {{slice_name}}
+URL             : {{url}}
+Purpose         : {{purpose}}
+
+
+We are pleased to inform you that a manager from your institution has validated your slice request on the Fed4FIRE portal. You can now add resources to you slice and start experimenting.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
diff --git a/portal/templates/fed4fire/fed4fire_slicerequest_view.html b/portal/templates/fed4fire/fed4fire_slicerequest_view.html
new file mode 100644 (file)
index 0000000..211f35d
--- /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 class="error">
+                 {% 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="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
+                               title="Please provide the url of your experiment if you have one." value="{{url}}">
+                         </div>
+                         <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>
+                         {%if 'is_pi'  in pi %}        
+                         <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+                         {%else%}
+                         <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+                         {%endif%}     
+                       </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']);
+    });*/
+       $("#authority_hrn").val("{{authority_name}}");
+       var availableTags = [
+    {% if authorities %}
+        {% for authority in authorities %}
+            {% if authority.name %}
+                {value:"{{ authority.name }}",label:"{{authority.name}}"},
+                       // to show only full name
+           // {% else %}
+           //     {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+            {% endif %}
+        {% endfor %}    
+    {% else %}
+        {value:"",label:"No authority found !!!"}
+    {% endif %}
+    ];
+       // sorting the list
+       availableTags.sort(function(a,b){
+               var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
+               if (nameA < nameB) {
+               return -1;
+               }
+               if (nameA > nameB) {
+               return 1;
+               }
+       return 0;
+       }); 
+    $( "#authority_hrn" ).autocomplete({
+      source: availableTags,
+      minLength: 0,
+      select: function( event, ui ) {console.log(jQuery(this));}
+    });
+
+       $("#submit_pi").click(function() {
+               localStorage.clear();
+       });
+});
+</script>
+{% endblock %}
+
index dffad05..9f50d2c 100644 (file)
@@ -11,7 +11,7 @@
                        <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
+                       <p>A user is an experimenter who registers to the Fed4FIRE 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>
                        
                        
@@ -36,7 +36,7 @@
                        <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> 
+                       <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 Fed4FIRE 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>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_denied.html b/portal/templates/fed4fire/fed4fire_user_request_denied.html
new file mode 100644 (file)
index 0000000..56f7f4f
--- /dev/null
@@ -0,0 +1,11 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.</p>
+<p></p>
+<p>We  wish you all the best.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
diff --git a/portal/templates/fed4fire/fed4fire_user_request_denied.txt b/portal/templates/fed4fire/fed4fire_user_request_denied.txt
new file mode 100644 (file)
index 0000000..b3afba5
--- /dev/null
@@ -0,0 +1,8 @@
+Dear {{first_name}} {{last_name}},
+
+You have recently registered as a user to Fed4FIRE portal. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.
+
+We wish you all the best.
+
+Yours sincerely,
+The Fed4FIRE team
index 5c6801f..60abd27 100644 (file)
@@ -4,8 +4,13 @@
 <br>
 <b>First name   :</b> {{first_name}}<br>
 <b>Last name    :</b> {{last_name}}<br>
+<b>Organization :</b> {{organization}}<br>
 <b>Authority hrn:</b> {{authority_hrn}}<br>
 <b>Public key   :</b> {{public_key}}<br>
 <b>Email        :</b> {{email}}<br>
 <b>User hrn     :</b> {{user_hrn}}<br>
 <b>Portal url  :</b> {{ current_site }}<br>
+<p></p>
+<p>You can validate the user <a href="http://{{current_site}}/portal/validate">here</a>.<p>
+<br>
+<p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_email.txt b/portal/templates/fed4fire/fed4fire_user_request_email.txt
new file mode 100644 (file)
index 0000000..17ce184
--- /dev/null
@@ -0,0 +1,14 @@
+NEW USER REQUEST
+
+First name   : {{first_name}}
+Last name    : {{last_name}} 
+Organization :{{organization}}
+Authority hrn: {{authority_hrn}}
+Public key   : {{public_key}}
+Email        : {{email}}
+User hrn     : {{user_hrn}}
+Portal url   : {{ current_site }}
+
+Please note that the validation request will only become visible once the user has confirmed his/her email address.
+
+
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated.html b/portal/templates/fed4fire/fed4fire_user_request_validated.html
new file mode 100644 (file)
index 0000000..9048a6c
--- /dev/null
@@ -0,0 +1,14 @@
+<img src="http://www.fed4fire.eu/uploads/media/fed4fire-logo.jpg">
+<br>
+<p>Dear {{first_name}} {{last_name}},</p>
+<p></p>
+<p>It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.</p>
+<p></p>
+</p>
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. The Fed4FIRE  operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+</p>
+<p></p>
+</p>We  wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>THE Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated.txt b/portal/templates/fed4fire/fed4fire_user_request_validated.txt
new file mode 100644 (file)
index 0000000..40a1b03
--- /dev/null
@@ -0,0 +1,10 @@
+Dear {{first_name}} {{last_name}},
+
+It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.
+
+Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or to individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. TheFed4FIRE operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
index 230a14d..40761b5 100644 (file)
@@ -1,29 +1,37 @@
+<div class="container">
+       <div class="row">
+               <div class="col-md-12">
+                        <div class="breadcrumbs">
+                                Experiment &nbsp;>&nbsp; Slice: {{ 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"><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="About MySlice" /> {{ slice }}</a></li>
-<!--   <li><a href="/slice/{{ slice }}#testbeds">Testbeds</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 class="sla"><a href="/slice/{{ slice }}#sla">SLA</a></li>
-
-<!--   <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> 
-       <li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
-       <li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li> -->
-
+       <li><a href="/slice/{{ slice }}#info">Information</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"><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="About MySlice" /> {{ slice }}</a></li>
-       <!--<li class="testbeds"><a href="#testbeds">Testbeds</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" data-toggle="tab">Experiment</a></li> -->
-       <li class="sla"><a href="#sla">SLA</a></li>
-
+       <li class="active"><a href="#info">Information</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) {
@@ -33,7 +41,16 @@ $(document).ready(function() {
        var id = $(this).attr('href').substr(1);        
        $("#" + id).load('/' + id + '/{{ slice }}/');
        });
-       $('div#info').load('/info/{{ 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 66a5ce9..ddb4518 100644 (file)
@@ -20,7 +20,7 @@
                <ul>
                        <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
                        <li>|</li>
-                       <li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>
+                       <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
                        <li class="slices">
                                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                                        SLICES <span class="caret"></span>
@@ -39,7 +39,6 @@
                                                </ul>
                                </div>
                                </li>
-                       <li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
                        <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
                        <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
                        <li>|</li>
index 549ec6b..13da125 100644 (file)
@@ -9,7 +9,10 @@
        </div>
         {%if 'no_creds'  in user_cred %}
     <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
-{%endif%}
+    {%endif%}
+        {%if 'creds_expired'  in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
 
 </div>
 {% if messages %}
                                                        </td>
                                                 {%endif%}              
                                                </tr>
+                                       <tr class="even" id="sfi_config_row">
+                                               <td class="key">sfi_config </td>
+                                               <td class="value">use sfi_config file with sfi.py package (pip install sfa)<a href="#"></a>
+                                                       <button type="submit" name="dl_sfi_config" class="btn btn-default btn-xs" title="Download your privaye key" id="dl_sfi_config">
+                                                                       <span class="glyphicon glyphicon-download"></span> Download
+                                                               </button>
+                                               </td>
+                        </tr>
+
                                                <tr class="even">
                                                <td colspan="2">
                                                                <p class="command">
diff --git a/portal/templates/onelab/onelab_base.html b/portal/templates/onelab/onelab_base.html
deleted file mode 100644 (file)
index fdab352..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-{# 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>
index 944bcbe..08670c8 100644 (file)
@@ -51,6 +51,9 @@
           {%if 'no_creds'  in user_cred %}
       <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
   {%endif%}
+        {%if 'creds_expired'  in user_cred %}
+    <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
+    {%endif%}
 
        <div class="row">
                {%if 'is_pi'  in pi %}
                $('button#slicerequestbtn').click(function() {
                        window.location="/portal/slice_request/";
                });
-/*-------
-List of slices has been moved in 
-portal/templates/base.html
-This should go into session
---------*/
+
+        myslice.loadSlices();
+        
 });
 </script>
 {# widget "_widget-monitor.html" #}
index c2d52c3..c8b6b44 100644 (file)
@@ -14,5 +14,6 @@
   <!-- <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 class="tab-pane row" id="studentslabs">...</div> -->
 </div>         
 {% endblock %}
index 40761b5..e03a53c 100644 (file)
@@ -20,6 +20,7 @@
        <!-- <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>
+       <!-- <li><a href="/slice/{{ slice }}#studentslabs">Students Labs</a></li> -->
 </ul>
 {% else %}
 <ul class="nav nav-tabs nav-section">
@@ -30,6 +31,7 @@
        <!-- <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>
+       <!-- <li class="studentslabs"><a href="#studentslabs">Students Labs</a></li> -->
 </ul>
 
 <script>
@@ -53,4 +55,4 @@ $(document).ready(function() {
 {% endif %}
 </div>
 </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/portal/templates/reputation.html b/portal/templates/reputation.html
new file mode 100644 (file)
index 0000000..c000ee9
--- /dev/null
@@ -0,0 +1,436 @@
+{% extends "layout-unfold1.html" %}\r
+\r
+{% block head %}\r
+{{ wizard.form.media }}\r
+{% endblock %}\r
+\r
+{% block unfold_main %}\r
+\r
+<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/onelab.css" />\r
+\r
+<!-- Reputation Specific -->\r
+<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}reputation_static/css/main.css" />\r
+\r
+<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}reputation_static/css/jquery-ui-1.9.2.custom.min.css" />\r
+\r
+<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}reputation_static/css/jquery.rating.css" /> \r
+\r
+<script src="{{STATIC_URL}}reputation_static/js/jquery-1.9.0.min.js" type="text/javascript"></script>\r
+<script type="text/javascript" src="{{STATIC_URL}}reputation_static/js/ui/jquery-ui-1.9.2.custom.min.js"></script>\r
+<script type="text/javascript" src="{{STATIC_URL}}reputation_static/js/jquery.raty.min.js"></script>\r
+ <style>\r
+       #slicelist a {\r
+               color: rgb(96, 96, 216);\r
+               width:75% !important;\r
+       }\r
+       \r
+       .ui-accordion-header, .ui-accordion-content {\r
+               width:120% !important;\r
+       }\r
+       \r
+       ul {\r
+               list-style: none;\r
+               margin: 0;\r
+               padding: 0;\r
+       }\r
+       ul > li {\r
+               margin: 0;\r
+               padding: 0 0 8px 0;\r
+               height: 25px;\r
+       }\r
+       ol > li {\r
+               height: 60px;\r
+       }\r
+       #slicelist li:last-child {\r
+               padding: 0;\r
+       }\r
+       #slicelist {\r
+               width: 50%;\r
+       }\r
+\r
+       #scoreform {\r
+               width: 500px;\r
+       }\r
+       #submit {\r
+               text-align: center;\r
+       }\r
+       \r
+       #scoreform > ol > li > div > input:first-child {\r
+               margin: 4px 3px 0 0;\r
+       }\r
+       #scoreform > ol > li > div > input:last-child {\r
+               margin: 4px 3px 0 10px;\r
+       }\r
+</style> \r
+\r
+<div id='rep-container' align="center" style="text-align:left;margin-left:1%;"> \r
+\r
+\r
+       <div id="tabs">\r
+         <ul>\r
+           <li><a href="#tabs-1">Testbeds' Reputation</a></li>\r
+           <li><a href="#tabs-2">Evaluate your experiments</a></li>\r
+         </ul>\r
+         <div id="tabs-1">\r
+       \r
+                         \r
+               <table class="reptable table table-bordered table-hover">\r
+                   <tr class="odd">\r
+                               <th> Testbed </th>\r
+                               {% for service in rep_serv %}\r
+                                               <th id='service{{forloop.counter}}' class='{{service}}-class'>Service: {{ service}} </th>\r
+                               {%endfor%}\r
+                   </tr>\r
+                   \r
+                   \r
+                   {% for testbed_rep in reputation %}\r
+                           <tr class="border_bottom">\r
+                               <td class="odd">\r
+                                                       <span> {{ testbed_rep.testbed }} </span>         \r
+                                               </td>\r
+                                       \r
+                                       {% for tb_serv in testbed_rep.services %}\r
+                                               <td>\r
+                                                       {{tb_serv}}\r
+                                               </td>\r
+                                       {%endfor%}\r
+                                               \r
+                           </tr>\r
+                   {%endfor%}\r
+                               \r
+               </table>    \r
+           \r
+         </div>\r
+         <div id="tabs-2">\r
+               <h1>Experiment Evaluation</h1>\r
+               <p><b>List of your unrated experiments</b></p><div id="slicelist">\r
+                       \r
+                       {% for aslice in slicelist %}\r
+                       <h3>Slice <b>{{ aslice.slice_hrn }}</b></h3>\r
+                       <div style="padding-bottom:0;padding-top:0;">\r
+                           <ul><li>\r
+                                   experiment from <b>{{ aslice.start_t }}</b> to <b>{{ aslice.end_t }}</b> | <a href="#" class="rate_button" data-resid={{ aslice.id }}>Rate it</a>\r
+                                       </ul>\r
+                       </div>\r
+               \r
+               \r
+                       {%endfor%}\r
+               </div>  \r
+       \r
+         </div>\r
+       </div>\r
+\r
+</div>\r
+\r
+\r
+<div id="scoreform" style="display:none">\r
+    <ol>\r
+        <li>\r
+            <span>How was your overall experience with NETMODE Testbed?</span> \r
+            <div id="q1">\r
+            </div>\r
+        </li>\r
+       <li>\r
+            Did you experience any problems during the experiment?\r
+            <div id="q2">\r
+                <input type="radio" name="q2" value="1" />Yes\r
+                <input type="radio" name="q2" value="0" />No\r
+            </div>\r
+        </li>\r
+\r
+        <li>\r
+            How would you rate the provided user support (instructions, tutorials, email support)?\r
+            <div id="q3">\r
+            </div>\r
+        </li>\r
+        <li>\r
+            Would you use NETMODE testbed again?\r
+            <div id="q4">\r
+                <input type="radio" name="q4" value="1" />Yes\r
+                <input type="radio" name="q4" value="0" />No\r
+            </div>\r
+        </li>\r
+        <li>\r
+            Would you be willing to pay for this service?\r
+            <div id="q5">\r
+                <input type="radio" name="q5" value="1" />Yes\r
+                <input type="radio" name="q5" value="0" />No\r
+            </div>\r
+        </li>\r
+        <li>\r
+            How would you rate the Node Availability in the experiment?\r
+            <div id="q6">\r
+            </div>\r
+        </li>\r
+        <li>\r
+            How would you rate the Link Quality regarding PDR in the experiment (1:Very Low, 5:Very High )?\r
+            <div id="q7">\r
+            </div>\r
+        </li>\r
+        <li>\r
+            Rate your level of certainty regarding your answers above?\r
+            <div id="q8">\r
+            </div>\r
+        </li>\r
+\r
+    </ol>\r
+    <div id="submit">\r
+        <a href="#">Submit &raquo;</a>\r
+    </div>\r
+</div>\r
+\r
+\r
+</div>\r
+\r
+\r
+       <div id='temp_log' style="display: none;">\r
+\r
+        <table class="mytable table table-bordered table-hover">\r
+            <tr class="odd">\r
+               <th>User Email</th>\r
+                <th>User HRN</th>\r
+                               <th>Slice HRN</th>\r
+                               <th>Resources</th>\r
+                               <th>Leases</th>\r
+                               \r
+            </tr>\r
+            \r
+            {% for slice in slices_users %}\r
+            <tr class="border_bottom">\r
+                <td class="odd">\r
+                                       <a href="/portal/user/{{slice.user}}"><span class="glyphicon glyphicon-search"></span></a>      \r
+                                       {{ slice.user }} \r
+                               </td>\r
+                               <td class="odd"> {{ slice.user_hrn }} </td>\r
+                               <td class="even"> {{ slice.slice_hrn }} </td>\r
+                               <td class="even"> {{ slice.resource }} </td>\r
+                               <td class="even"> {{ slice.lease }} </td>\r
+                               \r
+            </tr>\r
+            {%endfor%}\r
+                        \r
+        </table>\r
+\r
+               <div id='logging_out'>{{ logging_test }}</div>\r
+        \r
+       </div>\r
+\r
+<!-- END of Reputation Specific -->\r
+\r
+\r
+<div class="onelab-title well-lg">\r
+  <h2>Onelab Support</h2>\r
+  <h4>If you have already registered, then please send an <a href="mailto:support@myslice.info">e-mail</a>\r
+  or <a href="http://trac.myslice.info/" >visit us</a></h4>\r
+</div>\r
+\r
+\r
+<!-- Reputation Specific -->\r
+\r
+<script type="text/javascript">\r
+\r
+serv_per_tb = jQuery.parseJSON('{{ serv_per_tb|safe }}');\r
+\r
+$(function() {\r
+       $( "#tabs" ).tabs();\r
+});\r
+\r
+var data = jQuery.parseJSON('{{ json_data|safe }}');\r
+\r
+\r
+\r
+\r
+var resid = -1;\r
+var q1 = -1;\r
+var q2 = -1;\r
+var q3 = -1;\r
+var q4 = -1;\r
+var q5 = -1;\r
+var q6 = -1;\r
+var q7 = -1;\r
+var q8 = -1;\r
+\r
+function initDialog() {\r
+       \r
+       \r
+    $("input:radio").removeAttr("checked");\r
+    $("#submit > a").click(function() {\r
+        if ($("#q2 input:checked").val()) {\r
+            q2 = $("#q2 input:checked").val();\r
+        }\r
+        if ($("#q4 input:checked").val()) {\r
+            q4 = $("#q4 input:checked").val();\r
+        }\r
+        if ($("#q5 input:checked").val()) {\r
+            q5 = $("#q5 input:checked").val();\r
+        }\r
+\r
+        $("a[data-resid='"+resid+"']").css("text-decoration", "line-through").unbind("click").removeAttr("href");\r
+\r
+        //TODO: check input if valid before submitting\r
+\r
+        sum = q1 + q2 + q3 + q4 + q5 + q6 + q7 +q8;\r
+\r
+        if (sum == -8) {\r
+            alert("Please provide at least one rating to submit");\r
+        }\r
+        else {\r
+            $("#scoreform").dialog("close");\r
+            slicedata = {};\r
+               for(var event in data){\r
+                               if ((data[event]).id == resid) {\r
+                                       slicedata = (data[event]);\r
+                               }       \r
+                       }\r
+                       \r
+\r
+                       \r
+                       slicedata["user_eval"] = {'overall':q1, 'problems':q2, 'support':q3, 'reuse':q4, 'pay':q5, 'availability':q6, 'link_quality':q7, 'quality':q8};\r
+                       testbeds_str = JSON.stringify(slicedata['testbeds'])\r
+                       delete slicedata['testbeds'];\r
+            //console.log(JSON.stringify(slicedata))\r
+                        \r
+            $.ajax({\r
+                   type: "GET",\r
+                   url: "reputation/submit_eval",\r
+                   data: {slicedata: slicedata, testbeds: testbeds_str},\r
+                   accepts: "application/json",\r
+                   success: function (data) {\r
+                       var json = $.parseJSON(data);\r
+                       console.log(json);\r
+                       },\r
+                   error: function(xhr,errmsg,err) {\r
+                       alert(" X " + errmsg + " X " + err+ ": " + xhr.responseText);\r
+                   }\r
+               });\r
+        }\r
+\r
+        return false;\r
+    });\r
+    $("#q1").raty({\r
+        number: 5,\r
+        size: 24,\r
+        starOn: 'static/reputation_static/img/star-on.png',\r
+        starOff: 'static/reputation_static/img/star-off.png',\r
+        click: function(score, evt) {\r
+            q1 = score;\r
+        }\r
+    });\r
+    $("#q3").raty({\r
+        number: 5,\r
+        size: 24,\r
+        starOn: 'static/reputation_static/img/star-on.png',\r
+        starOff: 'static/reputation_static/img/star-off.png',\r
+        click: function(score, evt) {\r
+            q3 = score;\r
+        }\r
+    });\r
+    $("#q6").raty({\r
+        number: 5,\r
+        size: 24,\r
+        starOn: 'static/reputation_static/img/star-on.png',\r
+        starOff: 'static/reputation_static/img/star-off.png',\r
+        click: function(score, evt) {\r
+            q6 = score;\r
+        }\r
+    });\r
+    $("#q7").raty({\r
+        number: 5,\r
+        size: 24,\r
+        starOn: 'static/reputation_static/img/star-on.png',\r
+        starOff: 'static/reputation_static/img/star-off.png',\r
+        click: function(score, evt) {\r
+            q7 = score;\r
+        }\r
+    });\r
+    $("#q8").raty({\r
+        number: 5,\r
+        size: 24,\r
+        starOn: 'static/reputation_static/img/star-on.png',\r
+        starOff: 'static/reputation_static/img/star-off.png',\r
+        click: function(score, evt) {\r
+            q8 = score;\r
+        }\r
+    });\r
+}\r
+$(function() {\r
+    /* \r
+        vars with answers to questions\r
+    */\r
+\r
+    $("#slicelist").accordion({\r
+        heightStyle: "content"\r
+    });\r
+\r
+    initDialog();\r
+               \r
+    clone = $("#scoreform").clone(true);\r
+\r
+    $(".rate_button").click(function() {\r
+        q1 = -1;\r
+        q2 = -1;\r
+        q3 = -1;\r
+        q4 = -1;\r
+        q5 = -1;\r
+        q6 = -1;\r
+               q7 = -1;\r
+               q8 = -1;\r
+        resid = $(this).attr("data-resid"); \r
+        \r
+        slicedata = {};\r
+       for(var event in data){\r
+                       if ((data[event]).id == resid) {\r
+                               slicedata = (data[event]);\r
+                       }       \r
+               }       \r
+\r
+               srv_arr = []            \r
+        for (var tb in slicedata["testbeds"]){ \r
+               for (var srv in serv_per_tb[tb]){ \r
+                       if (srv != 'equals') {\r
+                               //console.log(serv_per_tb[tb][srv]); \r
+                               srv_arr.push(serv_per_tb[tb][srv]) \r
+                       } \r
+               } \r
+        }     \r
+        \r
+        cq1 = "overall";\r
+        cq6 = "availability";\r
+        cq7 = "link_quality";\r
+        \r
+        q_to_remove = []\r
+        \r
+        if ($.inArray(cq1, srv_arr) == -1 ){\r
+               $("#scoreform > ol").children(':eq('+0+')').remove();\r
+        } \r
+        if ($.inArray(cq6, srv_arr) == -1 ){\r
+               $("#scoreform > ol").children(':eq('+5+')').remove();\r
+        } \r
+               if ($.inArray(cq7, srv_arr) == -1 ){\r
+               $("#scoreform > ol").children(':eq('+6+')').remove();\r
+        } \r
+        \r
+        $("#scoreform").dialog({\r
+            title: "Rate experiment",\r
+            width: 500,\r
+            modal: true,\r
+            draggable: false,\r
+            resizable: false,\r
+            hide: "fade",\r
+            close : function() {\r
+                $(this).dialog("destroy");\r
+                $("#scoreform").remove();\r
+                $("body").append(clone); \r
+                initDialog();\r
+            }\r
+        });\r
+        return false;\r
+    }); \r
+    \r
+\r
+});\r
+</script>\r
+\r
+<!-- END of Reputation Specific -->\r
+\r
+{% endblock %}
\ No newline at end of file
index 85eee75..78502cf 100644 (file)
@@ -82,24 +82,11 @@ loadedTabs = [];
             async: "false",
             url: "{{ servdirurl }}appservices/",
             success: function(data, status, jqXHR){
-                // console.log(data);
-                // $.each(data, function(i, item){
-                //     console.log(item);
-                //     var tr = $('<tr>').append(
-                //         $('<td id="name">').text(item.name),
-                //         $('<td>').text(item.provider),
-                //         $('<td>').append('<a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
-                //         $('<td>').text(item.protocol),
-                //         $('<td>').text(item.APIBasic),
-                //         $('<td>').text(item.briefDescription)
-                //     );
-                //     $("#appservices-tab > tbody:last").append(tr);
-                //     $("td#name").click(function(){
-                //         window.location.href = data.endPoint;
-                //     });
-                // });
+
                   function createToggle(name){
                       return function(){
+                        var icon = $('p#name-' + name + ' span');
+                        icon.toggleClass("glyphicon-chevron-down");
                         var el = $('p#expandable-' + name);
                         if(!el.is(':animated')){
                           $(el).toggle(300);
@@ -121,21 +108,23 @@ loadedTabs = [];
 
                     var row = $('<div class="row">').append(
                       $('<div>').addClass("col-md-3 portfolio-item").append(
-                        $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+                        $('<a href="' + item.APILink + '">').append(
+                          $('<img>').attr('src', "{{ STATIC_URL }}img/servicedirectory/" + imgsrc)
+                        )
                      ),
                       $('<div>').addClass("col-md-6 portfolio-item").append(
-                        $('<p id="name-' + item.name.replace(/ /g,'') + '">').text(item.name),
+                        $('<p id="name-' + item.name.replace(/ /g,'') + '">').append(
+                          $('<span class="glyphicon glyphicon-chevron-right">'), " " + item.name),
                         $('<p>').text(item.briefDescription),
                         $('<p>').text("Provider: " + item.provider),
                         $('<p>').append('Endpoint: <a href="' + item.endPoint + '">' + item.endPoint + "</a>"),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.fullDescription).hide(),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text("Protocol: " + item.protocol).hide(),
                         $('<p id="expandable-' + item.name.replace(/ /g,'') + '">')
-                              .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide(),
-                        $('<p id="expandable-' + item.name.replace(/ /g,'') + '">').text(item.APIBasic).hide()
+                              .append('API documentation: <a href="' + item.APILink + '">' + item.APILink + "</a>").hide()
                       )
                     );
-                    $("#appservices-tab").append(row);
+                    $('#appservices-tab').append(row);
                     $('p#name-' + item.name.replace(/ /g,'')).click(createToggle(item.name.replace(/ /g,'')));
                 });
 
@@ -173,88 +162,6 @@ loadedTabs = [];
                 console.log("ERROR: " + status);
             }
         });
-        
-  //       $.post("/rest/authority/",{'filters':{'authority_hrn':'{{user_details.parent_authority}}'}}, function( data ) {
-  //           var authority_data = [];
-  //           var onelab_data = [];
-               //      /* 'city','enabled','legal','longitude','onelab_membership','address','parent_authority','slice','user','country',
-  //           'tech','abbreviated_name','url','postcode','description','scientific','authority_hrn','latitude','name' */
-  //           $.each( data, function( key, val ) {
-  //               authority_row = "<img src='{{ STATIC_URL }}img/institutions/{{user_details.parent_authority}}.gif' alt='' /><br>";
-  //               authority_row += "<br>";
-  //               authority_row += "<b>authority:</b> "+val.authority_hrn+"<br>";
-  //               authority_data.push(authority_row);
-  //           });
-  //           $("div#authority-data").html(authority_data.join( "" ));
-  //           $("div#onelab-data").html(onelab_data.join( "" ));
-  //           $("div#authority-tab-loaded").css("display","block");
-  //           $("div#authority-tab-loading").css("display","none");
-  //        });
-
-  //       $.post("/rest/slice/",{'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
-  //           var list_slices = [];
-  //           var table_slices = [];
-  //           /* "slice_hrn", "slice_description", "slice_type", "parent_authority", "created", "nodes", "slice_url", "slice_last_updated", "users", "slice_urn", "slice_expires" */
-  //           $.each( data, function( key, val ) {
-  //               list_slices.push( "<li><a href=\"portal/slice/"+val.slice_hrn+"\">" + val.slice_hrn + "</a></li>" );
-  //               if(val.nodes=="undefined" || val.nodes==null){
-  //                   nodes_length=0;
-  //               }else{
-  //                   nodes_length=val.nodes.length;
-  //               }
-  //               if(val.users=="undefined" || val.users==null){
-  //                   users_length=0;
-  //               }else{
-  //                   users_length=val.users.length;
-  //               }
-
-  //               if(val.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 %}
 
index 9dca1d1..eb9a4ec 100644 (file)
-<div class="col-md-2">
-</div>
-<div class="col-md-8">
-       <h2>How to access your slice</h2>
+<div class="col-md-10 col-md-offset-1">
+       {% if ple_resources or iotlab_resources or nitos_resources or nitos_paris_resources%}
+               <h2>How to access your reserved resources</h2>
+       {% endif %}
+       {% if ple_resources %}
        <h3>PlanetLab Europe</h3>
        
        <p>
                PlanetLab Europe resources are accessible directly via SSH. Your SSH public key is deployed automatically
                on the reserved nodes. To access your slice on a resource just type the following command:
        </p>
-       {%if ple_resources%}
        <p class="command">
        {%for resource in ple_resources %}
+               <b>Resource</b><br>
                $ ssh {{ple_slicename}}@{{resource}}<br>
        {%endfor%}
        </p>
-       {%else%}
-               <p><b>NOTE:</b> You did not reserve any PLE resources yet. Once reserved, you will get the actual SSH command. A specimen command is given below:</p>
-               <p class="command">
-               $ ssh {{ple_slicename}}@planetlab-resource.hostname.com<br>
-               </p>
-       {%endif%}
        <p><strong>NOTE:</strong> Your original slicename <b>{{slicename}}</b> has been converted to PlanetLab specific format <b>{{ple_slicename}}</b> in order to do SSH.</p>
        <p>Please note that the first '.' is replaced by number 8 and the rest of the dot/s are replaced by underscore/s.</p>
        <p>
                Be aware that after you reserve a PlanetLab Europe resource your slice will be deployed with a delay of about 15 minutes, 
                after witch you will be able to access the resource.
        </p>
-       
+       {% endif %}
+
+       {% if iotlab_resources %}       
        <h3>FIT IoT-Lab</h3>
        <p>FIT IoT-Lab resources are accessible directly via SSH and <a href="https://devgrenoble.senslab.info/testbed/" target="_blank">web GUI.</a>
                To acess IoT-Lab resources using web GUI, use the same login and  password of OneLab portal. To acess Iot-Lab resources using SSH type
                the following command:
        </p>
        <p class="command">
-               ssh {{username}}@fit3-dev.inrialpes.fr
+               ssh {{iot_login}}@fit3-dev.inrialpes.fr
        </p>
-       
+       {% endif %}
+       {% if nitos_resources or nitos_paris_resources %}
        <h3>NITOS</h3>
        
        <p>
         NITOS resources are not directly accessible. You will need to log in on a gateway server and from there access the node.
-        The NITOS server address is nitlab.inf.uth.gr, so to connect to the NITOS server:
+        You will find the ssh commands to connect to NITOS nodes below:
        </p>
+
+       {% if nitos_resources %}        
+       <h4>NITLab</h4>
        <p class="command">
        $ ssh {{slicename}}@nitlab.inf.uth.gr
        </p>
        
-       <p>
-       <!-- In order to connect to NITOS server he has to upload his public key on the server. 
-       For now we do it this way: http://nitlab.inf.uth.gr/NITlab/index.php/your-ssh-keys. 
-       I think this is a procedure that needs to be done at the registration phase of the user, 
-       through myslice, Broker etc. but I will answer you in a couple of days for sure. -->
-       </p>
-
-       <p>
-               You will then need to prepare the resource by loading an OMF image on it:
-       </p>
-       
+       <p>For each of the reserved nodes, follo the steps given below:</p>
        <p class="command">
-               $ omf load -i baseline_grid.ndz -t omf.nitos.node016
+       {%for resource in nitos_resources %}
+               <b>Resource</b><br>
+       $ omf load -i baseline_grid.ndz -t {{resource}}  #loading OMF image on the node<br>
+               $ omf tell -a on -t {{resource}}  #turn on the node <br>
+               $ ssh root@{{resource}}  #ssh to the node<br><br>
+       {%endfor%}
        </p>
+       {% endif %}
 
-       <p>
-               Turn on the node:
-       </p>
-       
+       {% if nitos_paris_resources %}
+       <h4>FIT NITOS-Lab Paris</h4>
+        <p class="command">
+               $ ssh {{slicename}}@griffin.ipv6.lip6.fr
+        </p>
+       <p>For each of the reserved nodes, follo the steps given below:</p>
        <p class="command">
-               $ omf tell -a on -t omf.nitos.node016
-       </p>
-       <p>
-               And finally ssh on the node:
-       </p>
-       <p class="command">
-               $ ssh root@node016
+       {%for resource in nitos_paris_resources %}
+               <b>Resource</b><br>
+       $ omf load -i baseline_grid.ndz -t {{resource}}  #loading OMF image on the node<br>
+       $ omf tell -a on -t {{resource}}  #turn on the node <br>
+       $ ssh root@{{resource}}  #ssh to the node<br><br>
+       {%endfor%}
        </p>
+       {%endif%}
+
        <p>
                On the node itself you will have to modify the file /etc/omf-resctl-5.3/omf-resctl.yaml according to your slice settings and then
                restart the OMF Resource Controller and finally execute the experiment:
        </p>
        <p class="command">
-               $ omf exec --slice slice_name your_exp.rb
+               $ omf exec --slice {{slicename}} your_exp.rb
        </p>
        <p>
        The complete tutorial is available at the following address:
        <a target="_blank" href="http://nitlab.inf.uth.gr/NITlab/index.php/testbed/instructions/basic-tutorial">NITOS basic tutorial</a>
        </p>
-       
-       <br />
+       <p>To learn more about OMF6, please click <a href="http://omf.mytestbed.net/projects/omf6/wiki/Wiki" target="_blank">here.</a></p>
+
+       {% endif %}
        
        <h2>Available Tools</h2>
        <p><img src="{{ STATIC_URL }}img/terminal_icon.png" width="50"> <b>SSH</b></p>
        <p>
        Secure Shell (SSH) is a cryptographic network protocol for secure data communication, remote command-line login, remote command execution, and other secure network services between two networked computers that connects, via a secure channel over an insecure network, a server and a client (running SSH server and SSH client programs, respectively). The protocol specification distinguishes between two major versions that are referred to as SSH-1 and SSH-2.
        </p>
-       <p> More Info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
+       <p> More info: <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">http://en.wikipedia.org/wiki/Secure_Shell</a></p>
        <br>
+       <p><img src="{{ STATIC_URL }}img/putty-logo.png" width="50"> <b>PuTTY</b></p>
+       <p>
+               PuTTY is an SSH and telnet client, developed originally by Simon Tatham for the Windows platform. PuTTY is open source software that is available with source code and is developed and supported by a group of volunteers.
+       </p>
+       <p>More info: <a href="http://www.putty.org/" target="_blank">http://www.putty.org/</a></p>     
        <br>
        <p><img src="{{ STATIC_URL }}img/nepi_logo.png" width="90"></p>
        <p>NEPI, the Network Experimentation Programming Interface, is a life-cycle management tool for network experiments. The idea behind NEPI is to provide a single tool to design, deploy, and control network experiments, and gather the experiment results. Going further, NEPI was specially conceived to function with arbitrary experimentation platforms, so researchers could use a single tool to work with network simulators, emulators, or physical testbeds, or even a mixture of them. To accomplish this, NEPI provides a high-level interface to describe experiments that is independent from any experimentation platform, but is able to capture platform specific configurations. Experiment definitions can be stored in XML format to be later reproduced, and modified according to experimentation needs. Experiment execution is orchestrated by a global experiment controller, that is platform independent, and different platform-dependent testbed controllers, creating a control hierarchy that is able t adapt to platform specific requirements while providing an integrated control scheme.</p>
-       <p> More Info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
+       <p> More info: <a href="http://nepi.inria.fr" target="_blank">http://nepi.inria.fr</a></p>
        <br>
        <p><img src="{{ STATIC_URL }}img/omf-logo.png" width="90"></p>
        <p>OMF is a Testbed Control, Measurement and Management Framework.</p>
        <p>In addition to the main OMF software, this site also hosts OMF sub-projects addressing various related aspects of a testbed's control, measurement, and management.</p>
        <p>More Info: <a href="http://mytestbed.net/projects/omf" target="_blank">http://mytestbed.net/projects/omf</a></p>
 </div>
-<div class="col-md-2">
-</div>
index 8859e62..42a8dcb 100644 (file)
@@ -57,6 +57,8 @@ from portal.emailactivationview     import ActivateEmailView
 from portal.views                   import PresViewView, pres_view_static, pres_view_methods, pres_view_animation
 from portal.django_passresetview    import password_reset, password_reset_done, password_reset_confirm, password_reset_complete 
 
+from portal.reputationview      import ReputationView
+
 # DEPRECATED #named_register_forms = (
 # DEPRECATED #    ("step1", RegisterUserForm),
 # DEPRECATED #    ("step2", RegisterUserStep2Form)
@@ -128,6 +130,11 @@ urlpatterns = patterns('',
 
     url(r'^servicedirectory/?$', ServiceDirectoryView.as_view(), name='servicedirectory'),
 
+
+    url(r'^reputation/?$', ReputationView.as_view(), name='reputation'),
+    url(r'^reputation/submit_eval/?$', ReputationView.as_view(), name='reputation_submit_eval'),
+    
+    
 )
 # (r'^accounts/', include('registration.backends.default.urls')),
 
index 5b4e2ee..1314175 100644 (file)
@@ -54,10 +54,10 @@ class UsersView (LoginRequiredAutoLogoutView, ThemeView):
 
             status_list.append(user_status)
             #get authority
-            #if user['config']:
-            user_config = json.loads(user['config'])
-            user_authority = user_config.get('authority','N/A')
-            authority_list.append(user_authority)
+            if user['config'] is not None:
+                user_config = json.loads(user['config'])
+                user_authority = user_config.get('authority','N/A')
+                authority_list.append(user_authority)
     
         user_list = [{'email': t[0], 'status': t[1], 'authority':t[2]}
             for t in zip(email_list, status_list, authority_list)]
index d95679a..a8c8ba7 100644 (file)
@@ -9,8 +9,6 @@ def dispatch(request, action):
         emails = request.POST.getlist('emails[]')
         if not emails:
             emails = request.GET.getlist('emails[]')
-        #import pdb
-        #pdb.set_trace()
         if emails :
             for email in emails :
                 try :
diff --git a/rest/sfa_api.py b/rest/sfa_api.py
new file mode 100644 (file)
index 0000000..04b156b
--- /dev/null
@@ -0,0 +1,142 @@
+from sfa.trust.certificate      import Keypair, Certificate
+from sfa.client.sfaserverproxy  import SfaServerProxy
+from sfa.client.return_value    import ReturnValue
+from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+from manifold.core.query        import Query
+from manifold.models            import db
+from manifold.models.platform   import Platform
+from manifold.models.user       import User
+
+from django.shortcuts           import render_to_response
+
+from unfold.loginrequired       import LoginRequiredView
+
+from rest import ObjectRequest, error
+
+from string import join
+
+from django.http import HttpResponse
+from rest import error
+import os,json
+
+import ConfigParser 
+
+def dispatch(request, method):
+    Config = ConfigParser.ConfigParser()
+    Config.read(os.getcwd() + "/myslice/monitor.ini")
+
+    # hardcoded user to be replaced by auth
+    user_email = "loic.baron@lip6.fr"
+
+    # Get this as parameters
+    slice_hrn = "fed4fire.upmc.berlin"
+    urn = hrn_to_urn(slice_hrn, "slice")
+    #urn = hrn_to_urn("fed4fire.upmc.loic_baron", "user")
+
+    platforms = list()
+    options   = list()
+    rspec = ''
+    results = dict()
+
+    if request.method == 'POST':
+        req_items = request.POST
+    elif request.method == 'GET':
+        req_items = request.GET
+
+    for el in req_items.items():
+        if el[0].startswith('rspec'):
+            rspec += el[1]
+        if el[0].startswith('platform'):
+            platforms += req_items.getlist('platform[]')
+        elif el[0].startswith('options'):
+            options += req_items.getlist('options[]')
+
+    if len(platforms)==0:
+        platforms.append('myslice')
+    #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
+
+    from manifoldapi.manifoldapi    import execute_admin_query
+    for pf in platforms:
+        platform = get_platform_config(pf)
+        print platform
+        if 'sm' in platform and len(platform['sm']) > 0:
+            print 'sm'
+            server_url = platform['sm']
+        if 'rm' in platform and len(platform['rm']) > 0:
+            print 'rm'
+            server_url = platform['rm']
+        if 'registry' in platform and len(platform['registry']) > 0:
+            print 'registry'
+            server_url = platform['registry']
+    
+        if not Config.has_option('monitor', 'cert') :
+             return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+        cert = os.path.abspath(Config.get('monitor', 'cert'))
+        if not os.path.isfile(cert) :
+             return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
+
+        if not Config.has_option('monitor', 'pkey') :
+             return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+
+        pkey = os.path.abspath(Config.get('monitor', 'pkey'))
+        if not os.path.isfile(pkey) :
+             return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
+        server = SfaServerProxy(server_url, pkey, cert)
+
+        # Get user config from Manifold
+        user_config = get_user_config(user_email, pf)
+        if 'delegated_user_credential' in user_config:
+            user_cred = user_config['delegated_user_credential']
+        else:
+            user_cred = {}
+
+        #if 'delegated_slice_credentials' in user_config:
+        #    for slice_name, cred in user_config['delegated_slice_credentials']:
+        #        if slice_name == slice_param
+
+        if method == "GetVersion": 
+            result = server.GetVersion()
+        elif method == "ListResources":
+            api_options = {}
+            #api_options ['call_id'] = unique_call_id()
+            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+            result = server.ListResources([user_cred], api_options)
+        elif method == "Describe":
+            api_options = {}
+            #api_options ['call_id'] = unique_call_id()
+            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+            result = server.Describe([urn] ,[object_cred], api_options)
+
+        else:
+            return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported yet'}), content_type="application/json")
+
+        results[pf] = result
+
+    return HttpResponse(json.dumps(results), content_type="application/json")
+
+def get_user_account(user_email, platform_name):
+    """
+    Returns the user configuration for a given platform.
+    This function does not resolve references.
+    """
+    user = db.query(User).filter(User.email == user_email).one()
+    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+    accounts = [a for a in user.accounts if a.platform == platform]
+    if not accounts:
+        raise Exception, "this account does not exist"
+
+    if accounts[0].auth_type == 'reference':
+        pf = json.loads(accounts[0].config)['reference_platform']
+        return get_user_account(user_email, pf)
+
+    return accounts[0]
+
+def get_user_config(user_email, platform_name):
+    account = get_user_account(user_email, platform_name)
+    return json.loads(account.config) if account.config else {}
+
+def get_platform_config(platform_name):
+    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+    return json.loads(platform.config) if platform.config else {}
index c00ca2f..8091f4e 100755 (executable)
@@ -12,13 +12,13 @@ from django.conf import settings
 
 """REST client to SLA Manager.
 
-Contains a generic rest client and wrappers over this generic client 
+Contains a generic rest client and wrappers over this generic client
 for each resource.
 
 Each resource client implements business-like() functions, but
 returns a tuple (output, requests.Response)
 
-The resource clients are initialized with the rooturl and a path, which 
+The resource clients are initialized with the rooturl and a path, which
 are combined to build the resource url. The path is defaulted to the known
 resource path. So, for example, to create a agreements client:
 
@@ -32,29 +32,27 @@ c = restclient.Factory.agreements()
 
 """
 
-_PROVIDERS_PATH = "providerso"
-_AGREEMENTS_PATH = "agreementso"
-_TEMPLATES_PATH = "templateso"
-_VIOLATIONS_PATH = "violationso"
+_PROVIDERS_PATH = "providers"
+_AGREEMENTS_PATH = "agreements"
+_TEMPLATES_PATH = "templates"
+_VIOLATIONS_PATH = "violations"
 _ENFORCEMENTJOBS_PATH = "enforcements"
 
 rooturl = settings.SLA_MANAGER_URL
 
-# SLA_MANAGER_USER = "normal_user"
-# SLA_MANAGER_PASSWORD = "password"
 
 class Factory(object):
     @staticmethod
-    def agreements():
-        """Returns aREST client for Agreements
+    def agreements(path=_AGREEMENTS_PATH):
+        """Returns a REST client for Agreements
 
         :rtype : Agreements
          """
-        return Agreements(rooturl)
+        return Agreements(rooturl, path)
 
     @staticmethod
     def providers():
-        """Returns aREST client for Providers
+        """Returns a REST client for Providers
 
         :rtype : Providers
         """
@@ -62,7 +60,7 @@ class Factory(object):
 
     @staticmethod
     def violations():
-        """Returns aREST client for Violations
+        """Returns a REST client for Violations
 
         :rtype : Violations
         """
@@ -70,7 +68,7 @@ class Factory(object):
 
     @staticmethod
     def templates():
-        """Returns aREST client for Violations
+        """Returns a REST client for Violations
 
         :rtype : Violations
         """
@@ -78,12 +76,13 @@ class Factory(object):
 
     @staticmethod
     def enforcements():
-        """Returns aREST client for Enforcements jobs
+        """Returns a REST client for Enforcements jobs
 
         :rtype : Enforcements
         """
         return Enforcements(rooturl)
 
+
 class Client(object):
 
     def __init__(self, root_url):
@@ -104,22 +103,34 @@ class Client(object):
         Returns a requests.Response
 
         :rtype : request.Response
-        :param str path: remaining path from root url; 
+        :param str path: remaining path from root url;
             empty if desired path equal to rooturl.
         :param kwargs: arguments to requests.get
-        
-        Example: 
+
+        Example:
             c = Client("http://localhost:8080/service")
             c.get("/resource", headers = { "accept": "application/json" })
         """
         url = _buildpath_(self.rooturl, path)
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+        if "testbed" in kwargs:
+            url = url + "?testbed=" + kwargs["testbed"]
+
+        if "headers" not in kwargs:
+            kwargs["headers"] = {"accept": "application/xml"}
+
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+                                       settings.SLA_MANAGER_PASSWORD)
+
+        # for key, values in kwargs.iteritems():
+        #     print key, values
+
         result = requests.get(url, **kwargs)
         print "GET {} {} {}".format(
             result.url, result.status_code, result.text[0:70])
+        print result.encoding
 
         return result
-    
+
     def post(self, path, data=None, **kwargs):
         """Just a wrapper over request.post, just in case
 
@@ -140,7 +151,17 @@ class Client(object):
             )
         """
         url = _buildpath_(self.rooturl, path)
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
+
+        if "testbed" in kwargs:
+            url = url + "?testbed=" + kwargs["testbed"]
+
+        if "headers" not in kwargs:
+            kwargs["headers"] = {"accept": "application/xml",
+                                 "content-type": "application/xml"}
+
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
+                                       settings.SLA_MANAGER_PASSWORD)
+
         result = requests.post(url, data, **kwargs)
         location = result.headers["location"] \
             if "location" in result.headers else "<null>"
@@ -148,7 +169,6 @@ class Client(object):
             result.url, result.status_code, location)
         return result
 
-    
 
 class _Resource(object):
 
@@ -184,7 +204,7 @@ class _Resource(object):
 
         content_type = r.headers.get('content-type', '')
 
-        print("content-type = " + content_type)
+        #print("content-type = " + content_type)
         if content_type == 'application/json':
             result = r.json()
         elif content_type == 'application/xml':
@@ -202,18 +222,21 @@ class _Resource(object):
         resources = self._processresult(r, self.listconverter)
         return resources, r
 
-    def getbyid(self, id):
+    def getbyid(self, id, params):
         """Get resource 'id'"""
-        r = self.client.get(id)
+        r = self.client.get(id, params=params)
         resource = _Resource._processresult(r, self.converter)
         return resource, r
 
-    def get(self, params):
+    def get(self, path, params):
         """Generic query over resource: GET /resource?q1=v1&q2=v2...
 
         :param dict[str,str] params: values to pass as get parameters
         """
-        r = self.client.get("", params=params)
+        if path is None:
+            path = ""
+
+        r = self.client.get(path, params=params)
         resources = self._processresult(r, self.listconverter)
         return resources, r
 
@@ -272,27 +295,36 @@ class Agreements(object):
         """
         return self.res.get(dict(providerId=providerid))
 
-    def getstatus(self, agreementid):
+    def getstatus(self, agreementid, testbed):
         """Get guarantee status of an agreement
 
         :param str agreementid :
         :rtype : wsag_model.AgreementStatus
         """
-        path = _buildpath_(agreementid, "guaranteestatus")
-        r = self.res.client.get(path, headers={'accept': 'application/json'})
+        path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
+        r = self.res.client.get(path, headers={'accept': 'application/json'},
+                                params={'testbed': testbed})
 
         json_obj = r.json()
-        
+
         status = wsag_model.AgreementStatus.json_decode(json_obj)
 
         return status, r
-    
-    def create(self, agreement):
+
+    def getbyslice(self, slicename):
+        """Get the agreements corresponding to a slice
+
+        :rtype : list[wsag_model.Agreement]
+        """
+        return self.res.get(slicename, dict())
+
+    def create(self, agreement, testbed):
         """Create a new agreement
 
         :param str agreement: sla template in ws-agreement format.
         """
-        return self.res.create(agreement)
+        return self.res.create(agreement, params={'testbed': testbed})
+
 
 class Templates(object):
 
@@ -319,7 +351,7 @@ class Templates(object):
 
         :rtype: wsag_model.Template
         """
-        return self.res.getbyid(provider_id)
+        return self.res.getbyid(provider_id, {"testbed": provider_id})
 
     def create(self, template):
         """Create a new template
@@ -328,6 +360,7 @@ class Templates(object):
         """
         self.res.create(template)
 
+
 class Providers(object):
 
     def __init__(self, root_url, path=_PROVIDERS_PATH):
@@ -363,6 +396,7 @@ class Providers(object):
         body = provider.to_xml()
         return self.res.create(body)
 
+
 class Violations(object):
 
     def __init__(self, root_url, path=_VIOLATIONS_PATH):
@@ -389,7 +423,7 @@ class Violations(object):
         """
         return self.res.getbyid(violationid)
 
-    def getbyagreement(self, agreement_id, term=None):
+    def getbyagreement(self, agreement_id, testbed, term=None):
         """Get the violations of an agreement.
 
         :param str agreement_id:
@@ -397,8 +431,9 @@ class Violations(object):
             violations from all terms will be returned
         :rtype: list[wsag_model.Violation]
         """
-        return self.res.get(
-            {"agreementId": agreement_id, "guaranteeTerm": term})
+        return self.res.get("", params={"agreementId": agreement_id,
+                                        "guaranteeTerm": term,
+                                        "testbed": testbed})
 
 
 class Enforcements(object):
@@ -420,17 +455,20 @@ class Enforcements(object):
         """
         return self.res.getall()
 
-    def getbyagreement(self, agreement_id):
+    def getbyagreement(self, agreement_id, testbed):
         """Get the enforcement of an agreement.
 
         :param str agreement_id:
-        
+
         :rtype: list[wsag_model.Enforcement]
         """
-        return self.res.getbyid(agreement_id)    
+        return self.res.getbyid(agreement_id, params={"testbed": testbed})
 
 
 def _buildpath_(*paths):
+    if "" in paths:
+        paths = [path for path in paths if path != ""]
+
     return "/".join(paths)
 
 
@@ -440,7 +478,6 @@ def main():
     #
     global rooturl
     rooturl = "http://127.0.0.1:8080/sla-service"
-    
 
     c = Factory.templates()
     #r = c.getall()
@@ -450,12 +487,9 @@ def main():
 
     #r = c.getbyconsumer('RandomClient')
     r = c.getbyid("template02")
-    
 
     print r
 
 
 if __name__ == "__main__":
     main()
-
-
index caecf26..9883098 100755 (executable)
@@ -5,9 +5,9 @@ to sla manager.
 It is intended as backend service for a rest interface.\r
 \r
 The json input must work together with the templates to form a valid template\r
- or agreement for Xifi (be careful!)\r
+ or agreement for fed4fire (be careful!)\r
 \r
-This (very simple) service is coupled to the way xifi is interpreting\r
+This (very simple) service is coupled to the way fed4fire is interpreting\r
 ws-agreement.\r
 \r
 \r
@@ -18,10 +18,13 @@ from sla.slaclient import wsag_model
 from sla.slaclient import restclient\r
 from sla.slaclient.templates.fed4fire.django.factory import Factory as TemplateFactory\r
 import sla.slaclient.templates.fed4fire as fed4fire\r
-from time import localtime, strftime\r
+#from time import localtime, strftime\r
 import uuid\r
+import dateutil.parser\r
+\r
+\r
 class ServiceContext(object):\r
-    def __init__(self, restfactory = None, templatefactory=None):\r
+    def __init__(self, restfactory=None, templatefactory=None):\r
         """\r
         :type restfactory: restclient.Factory\r
         """\r
@@ -101,38 +104,42 @@ def createagreement(json_data, context):
 \r
     # Builds AgreementInput from json\r
     data = jsonparser.agreementinput_from_json(json_data)\r
+\r
     # Read template from manager\r
+    # client_templates.getbyid(provider_id, testbed)\r
     slatemplate, request = client_templates.getbyid(data.template_id)\r
     # Copy (overriding if necessary) from template to AgreementInput\r
     final_data = data.from_template(slatemplate)\r
+\r
     slaagreement = fed4fire.render_slaagreement(final_data)\r
 \r
     client_agreements = context.restfactory.agreements()\r
-    return client_agreements.create(slaagreement)\r
-    \r
-\r
-def createagreementsimplified(template_id, user, expiration_time):\r
-        context = ServiceContext(\r
-            restclient.Factory(),\r
-            TemplateFactory()\r
-        )\r
-        \r
-        agreement = {\r
-            "agreement_id": str(uuid.uuid4()),\r
-            "template_id": template_id,\r
-            "expiration_time": expiration_time,\r
-            "consumer": user,\r
-        }\r
-    \r
-        json_data = json.dumps(agreement)\r
-\r
-        return createagreement(json_data, context)\r
-    \r
-def main():\r
-    createagreementsimplified("iMindsServiceWiLab2", "virtualwall", "2014-04-34T23:12:12")\r
-\r
-\r
-if __name__ == "__main__":\r
-    main()\r
-      \r
-        \r
+    return client_agreements.create(slaagreement, data.template_id)\r
+\r
+\r
+def createagreementsimplified(template_id, user, expiration_time, resources):\r
+    context = ServiceContext(\r
+        restclient.Factory(),\r
+        TemplateFactory()\r
+    )\r
+\r
+    agreement = {\r
+        "agreement_id": str(uuid.uuid4()),\r
+        "template_id": template_id,\r
+        "expiration_time": expiration_time.strftime('%Y-%m-%dT%H:%M:%S%Z'),\r
+        "consumer": user,\r
+        "guarantees": [\r
+            {\r
+                "name": "uptime",\r
+                "bounds": ["0", "1"],\r
+                "scope": {\r
+                    "service_name": "",\r
+                    "scope": resources[template_id]\r
+                }\r
+            }\r
+        ]\r
+    }\r
+\r
+    json_data = json.dumps(agreement)\r
+\r
+    return createagreement(json_data, context)\r
index 3dc8fca..d4a2300 100755 (executable)
@@ -69,8 +69,6 @@ def agreementinput_from_json(json_data):
     }\r
     """\r
     d = json.loads(json_data)\r
-    if "expiration_time" in d:\r
-        d["expiration_time"] = dateutil.parser.parse(d["expiration_time"])\r
 \r
     t = AgreementInput(\r
         agreement_id=d.get("agreement_id", None),\r
@@ -111,10 +109,18 @@ def _json_parse_guarantee_terms(d):
     """\r
     result = []\r
     for term in d.get("guarantees", None) or ():\r
+        gs = AgreementInput.GuaranteeTerm.GuaranteeScope(\r
+            term["scope"].get("service_name", ""),\r
+            term["scope"].get("scope", "")\r
+            )\r
+        print "*******GS****"\r
+        print gs\r
         result.append(\r
             AgreementInput.GuaranteeTerm(\r
                 metric_name=term["name"],\r
-                bounds=tuple(term["bounds"])\r
+                bounds=tuple(term["bounds"]),\r
+                guarantee_scopes=gs\r
             )\r
         )\r
-    return result
\ No newline at end of file
+\r
+    return result\r
index 096a7e3..7cf9a66 100755 (executable)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-    {% if data.agreement_id %}AgreementId="{{data.agreement_id}}"{% endif %}>\r
+    {% if data.agreement_id %}wsag:AgreementId="{{data.agreement_id}}"{% endif %}>\r
     {% if data.agreement_name %}<wsag:Name>{{data.agreement_name}}</wsag:Name>{% endif %}\r
 \r
     <wsag:Context>\r
                 {% endfor %}</wsag:Variables>\r
             </wsag:ServiceProperties>\r
             {% for term in data.guarantee_terms %}\r
-            <wsag:GuaranteeTerm Name="{{term.name}}">\r
-                {# do not need servicescope #}\r
-                   {% for scope in term.scopes %}\r
-                <wsag:ServiceScope ServiceName="{{scope.servicename}}"/>\r
+            <wsag:GuaranteeTerm wsag:Name="{{term.name}}">\r
+                {% for gs in term.scopes %}\r
+                <wsag:ServiceScope wsag:ServiceName="{{gs.servicename}}">\r
+                    {{ gs.scope }}\r
+                </wsag:ServiceScope>\r
                 {% endfor %}\r
                 <wsag:ServiceLevelObjective>\r
                     <wsag:KPITarget>\r
index efb939c..2de5201 100755 (executable)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-\r
-"""Template system for xifi project.\r
+"""Template system for fed4fire project.\r
 \r
 The specific template system is configured with the factory module variable.\r
 \r
@@ -32,7 +32,7 @@ Usage:
     data = sla.slaclient.templates.fed4fire.TemplateInput(template_id="template-test")\r
     slatemplate_xml = sla.slaclient.templates.fed4fire.render_slatemplate(data)\r
 \r
-Notes about agreements in XiFi:\r
+Notes about agreements in fed4fire:\r
     The ws-agreement specification does not address where to place the name/id\r
     of the service (as known outside SLA) being defined in the\r
     agreement/template xml. So, it has been defined an element\r
@@ -43,7 +43,7 @@ Notes about agreements in XiFi:
     The guarantee terms, service description terms, etc, use the attribute\r
     serviceName to reference (internally in the xml) the service. So, there\r
     could be more than one serviceName in a xml (as opposed to the former\r
-    serviceId). In Xifi, there is only one service per agreement, so we\r
+    serviceId). In fed4fire, there is only one service per agreement, so we\r
     can give serviceId and serviceName the same value.\r
 \r
     A ServiceReference defines how a serviceName is known externally: a\r
@@ -68,7 +68,7 @@ Notes about agreements in XiFi:
     (they are used to describe the service to be instantiated), so we can\r
     extrapolate the location as the "abstract location of the metric".\r
 \r
-    In summary, in XiFi, the service properties will hold the metrics being\r
+    In summary, in fed4fire, the service properties will hold the metrics being\r
     monitored for a service.\r
 \r
     And the guarantee terms hold the constraints that are being enforced for\r
@@ -88,11 +88,11 @@ Notes about agreements in XiFi:
             </wsag:ServiceLevelObjective>\r
         </wsag:GuaranteeTerm>\r
 \r
-    * Name is a name for the guarantee term. In Xifi, the name will have the\r
+    * Name is a name for the guarantee term. In fed4fire, the name will have the\r
       value "GT_<metric_name>"\r
     * ServiceName is an internal reference in the agreement to the service\r
       being enforced, as an agreement can created for more than one service.\r
-      In Xifi, to my knowledge, one service: one agreement, so this service\r
+      In fed4fire, to my knowledge, one service: one agreement, so this service\r
       name is not really important.\r
     * KpiName is a name given to the constraint, and I am using the same name\r
       as the service property used in the constraint. This makes more sense\r
@@ -106,7 +106,7 @@ Notes about agreements in XiFi:
 """\r
 \r
 from sla.slaclient import wsag_model\r
-import pdb\r
+import json\r
 \r
 from sla.slaclient.templates.fed4fire.django.factory import Factory\r
 factory = Factory()\r
@@ -133,7 +133,7 @@ def render_slaagreement(data):
     print "render_slaagreement"\r
     template = _getfactory().slaagreement()\r
     #pdb.set_trace()\r
-    rendered = template.render(data) \r
+    rendered = template.render(data)\r
     return rendered\r
 \r
 \r
@@ -196,20 +196,49 @@ class AgreementInput(object):
 \r
     class GuaranteeTerm(object):\r
 \r
+        class GuaranteeScope(object):\r
+\r
+            def __init__(self,\r
+                         servicename="",\r
+                         scope=""):\r
+\r
+                self.servicename = servicename\r
+                self.scope = scope\r
+\r
+            def __repr__(self):\r
+                s = "<GuaranteeScope(servicename={}, scope={})>"\r
+                return s.format(\r
+                    self.servicename,\r
+                    self.scope\r
+                )\r
+\r
         def __init__(self,\r
                      metric_name="",\r
-                     bounds=(0, 0)):\r
+                     bounds=(0, 0),\r
+                     guarantee_scopes=()):\r
             """Creates a GuaranteeTerm.\r
 \r
             Take into account that the GT's name is based on the metric_name.\r
-            :param str metric_name: name of the service property being enforced.\r
-            :param bounds: (lower, upper) bounds of the metric values.\r
+            :param str metric_name: name of the service property being enforced\r
+            :param bounds: (lower, upper) bounds of the metric values\r
             :type bounds: (float, float)\r
             """\r
             self.name = "GT_{}".format(metric_name)\r
             self.metric_name = metric_name\r
             self.kpiname = metric_name\r
             self.bounds = bounds\r
+            self.guarantee_scopes = guarantee_scopes\r
+\r
+        def __repr__(self):\r
+            s = "<GuaranteeTerm(name={}, metric_name={}, " \\r
+                "kpiname={}, bounds={}, guarantee_scopes={})>"\r
+            return s.format(\r
+                self.name,\r
+                self.metric_name,\r
+                self.kpiname,\r
+                self.bounds,\r
+                repr(self.guarantee_scopes)\r
+            )\r
 \r
     def __init__(self,\r
                  agreement_id="",\r
@@ -228,7 +257,7 @@ class AgreementInput(object):
         :param str agreement_name: optional agreement name\r
         :param str service_id: Domain id/name of the service.\r
         :param str consumer: Id of the consumer party in the agreement.\r
-        :param str provider: Resource Id of the provider party in the agreement.\r
+        :param str provider: Resource Id of the provider party in the agreement\r
           The provider must exist previously in the SlaManager.\r
         :param str template_id: TemplateId of the template this agreement is\r
           based on.\r
@@ -248,7 +277,7 @@ class AgreementInput(object):
         self.template_id = template_id\r
         self.expiration_time = expiration_time\r
         self.expiration_time_iso = \\r
-            expiration_time.isoformat() if expiration_time else None\r
+            expiration_time if expiration_time else None\r
         self.service_properties = service_properties\r
         self.guarantee_terms = guarantee_terms\r
 \r
@@ -278,6 +307,11 @@ class AgreementInput(object):
         #\r
         # NOTE: templateinput does not address guaranteeterms (yet)\r
         #\r
+\r
+        for _, gt in slatemplate.guaranteeterms.items():\r
+            gt.scopes[0].scope = self.guarantee_terms[0].guarantee_scopes.scope\r
+            gt.scopes[0].scope = [x.encode('utf-8') for x in gt.scopes[0].scope]\r
+\r
         result = AgreementInput(\r
             agreement_id=self.agreement_id,\r
             agreement_name=self.agreement_name,\r
@@ -287,7 +321,8 @@ class AgreementInput(object):
             template_id=slatemplate.template_id,\r
             expiration_time=self.expiration_time,\r
             service_properties=slatemplate.variables.values(),\r
+            #guarantee_terms=self.guarantee_terms\r
             guarantee_terms=slatemplate.guaranteeterms.values()\r
         )\r
-        print result.guarantee_terms[0]\r
+\r
         return result\r
index f141d6a..271a8f5 100755 (executable)
@@ -1,4 +1,6 @@
 from datetime import datetime
+from dateutil import tz
+import dateutil.parser
 
 """Contains the bean models for the SlaManager xml/json types
 """
@@ -23,7 +25,7 @@ class Agreement(object):
                 repr(self.provider),
                 repr(self.consumer),
                 repr(self.service))
-            
+
         def service_formatted(self):
             return self.service.replace('_', ' ')
 
@@ -31,8 +33,11 @@ class Agreement(object):
             return self.template_id.replace('Service', ' - ')
 
         def time_formatted(self):
-            import dateutil.parser
+            from_zone = tz.tzutc()
+            to_zone = tz.tzlocal()
             time = dateutil.parser.parse(self.expirationtime)
+            time = time.replace(tzinfo=from_zone)
+            time = time.astimezone(to_zone)
             return time.strftime('%d-%m-%Y at %H:%M:%S')
 
     class Property(object):
@@ -43,7 +48,8 @@ class Agreement(object):
             self.location = ""
 
         def __repr__(self):
-            str_ = "<Property(name={}, servicename={}, metric={}, location={})>"
+            str_ = "<Property(name={}, servicename={}, \
+                    metric={}, location={})>"
             return str_.format(
                 repr(self.name),
                 repr(self.servicename),
@@ -69,7 +75,8 @@ class Agreement(object):
                 self.customservicelevel = ""
 
             def __repr__(self):
-                s = "<ServiceLevelObjective(kpiname={}, customservicelevel={})>"
+                s = "<ServiceLevelObjective(kpiname={}, \
+                    customservicelevel={})>"
                 return s.format(
                     repr(self.kpiname),
                     repr(self.customservicelevel)
@@ -113,7 +120,6 @@ class Agreement(object):
 
 
 class Template(Agreement):
-    #egarrido this code has been copied from xifi and has not beeing tested
     def __init__(self):
         super(Template, self).__init__()
         self.template_id = ""
@@ -140,7 +146,8 @@ class Enforcement(object):
         return ("<Enforcement(agreement_id={}, enabled={})>".format(
                 self.agreement_id,
                 self.enabled)
-        )
+                )
+
 
 class AgreementStatus(object):
 
@@ -167,9 +174,9 @@ class AgreementStatus(object):
         return (
             "<AgreementStatus( agreement_id={}, guaranteestatus={}, " +
             "guaranteeterms={})>").format(
-                self.agreement_id,
-                self.guaranteestatus,
-                repr(self.guaranteeterms))
+            self.agreement_id,
+            self.guaranteestatus,
+            repr(self.guaranteeterms))
 
     @staticmethod
     def json_decode(json_obj):
@@ -191,23 +198,25 @@ class Violation(object):
         self.uuid = ""
         self.contract_uuid = ""
         self.service_scope = ""
+        self.service_name = ""
         self.metric_name = ""
         self.datetime = datetime.utcnow()
         self.actual_value = 0
 
     def __repr__(self):
-        return ("<Violation(uuid={}, agremeent_id={}, service_scope={}, " +
-            "metric_name={}, datetime={}, actual_value={})>".format(
+        return ("<Violation(uuid={}, datetime={}, contract_uuid={}, \
+                service_name={}, service_scope={}, metric_name={}, \
+                actual_value={})>\n".format(
                 self.uuid,
+                self.datetime,
                 self.contract_uuid,
+                self.service_name,
                 self.service_scope,
                 self.metric_name,
-                self.datetime,
                 self.actual_value)
-        )
+                )
 
     def format_time(self):
-        # return datetime.strptime(self.datetime.datetime.utcnow,'%Y-%m-%d %H:%M:%S')
         # return str(datetime.fromtimestamp(self.datetime))
         return str(self.datetime)
 
@@ -222,7 +231,8 @@ class Provider(object):
         return ("<Provider(uuid={}, name={})>".format(
                 self.uuid,
                 self.name)
-        )
+                )
+
     def to_xml(self):
         xml = "<provider><uuid>{}</uuid><name>{}</name></provider>""".format(
             self.uuid,
@@ -240,4 +250,4 @@ class Provider(object):
         out = wsag_model.Provider.from_dict(json_obj)
         """
         result = Provider(d["uuid"], d["name"])
-        return result        
+        return result
index 831df53..d32a591 100755 (executable)
@@ -9,7 +9,7 @@ to a more-friendly POJO instances.
 The converters are designed to be pluggable: see ListConverter.
 
 
-Usage: 
+Usage:
 c = AnyConverter() or
 c = ListConverter(AnyOtherConverter())
 
@@ -22,8 +22,14 @@ c.convert(root.getroot())
 
 """
 
-from xml.etree import ElementTree
-from xml.etree.ElementTree import Element
+try:
+    # Much faster and lighter library (C implementation)
+    from xml.etree import cElementTree as ElementTree
+except ImportError:
+    from xml.etree import ElementTree
+
+from xml.etree.ElementTree import QName
+
 import dateutil.parser
 
 from wsag_model import Agreement
@@ -81,7 +87,13 @@ class ListConverter(Converter):
     def convert(self, xmlroot):
         result = []
 
-        for item in xmlroot.find("items"):      # loop through "items" children
+        # Converter for the old xml structure
+        # for item in xmlroot.find("items"): # loop through "items" children
+        #     inner = self.innerconverter.convert(item)
+        #     result.append(inner)
+        # return result
+
+        for item in xmlroot:      # loop through children
             inner = self.innerconverter.convert(item)
             result.append(inner)
         return result
@@ -132,17 +144,19 @@ class EnforcementConverter(Converter):
         result.enabled = xmlroot.find("enabled").text
         return result
 
+
 class ViolationConverter(Converter):
     """Converter for a violation.
 
     Input:
     <violation>
-        <uuid>ce0e148f-dfac-4492-bb26-ad2e9a6965ec</uuid>
-        <contract_uuid>agreement04</contract_uuid>
-        <service_scope></service_scope>
-        <metric_name>Performance</metric_name>
-        <datetime>2014-01-14T11:28:22Z</datetime>
-        <actual_value>0.09555700123360344</actual_value>
+        <uuid>1d94627e-c318-41ba-9c45-42c95b67cc32</uuid>
+        <contract_uuid>26e5d5b6-f5a1-4eb3-bc91-606e8f24fb09</contract_uuid>
+        <service_name>servicename1</service_name>
+        <service_scope>test1</service_scope>
+        <metric_name>UpTime</metric_name>
+        <datetime>2014-07-17T09:32:00+02:00</datetime>
+        <actual_value>0.0</actual_value>
     </violation>
 
     Output:
@@ -155,11 +169,13 @@ class ViolationConverter(Converter):
         result = Violation()
         result.uuid = xmlroot.find("uuid").text
         result.contract_uuid = xmlroot.find("contract_uuid").text
+        result.service_name = xmlroot.find("service_name").text
         result.service_scope = xmlroot.find("service_scope").text
         result.metric_name = xmlroot.find("metric_name").text
         result.actual_value = xmlroot.find("actual_value").text
         dt_str = xmlroot.find("datetime").text
         result.datetime = dateutil.parser.parse(dt_str)
+
         return result
 
 
@@ -168,10 +184,9 @@ class AgreementConverter(Converter):
         """Converter for an ws-agreement agreement or template.
         """
         super(AgreementConverter, self).__init__()
-        self._namespaces = { 
+        self._namespaces = {
             "wsag": "http://www.ggf.org/namespaces/ws-agreement",
             "sla": "http://sla.atos.eu",
-            "xifi": "http://sla.xifi.eu"
         }
         self.agreement_tags = (
             "{{{}}}Agreement".format(self._namespaces["wsag"]),
@@ -185,12 +200,17 @@ class AgreementConverter(Converter):
         :param Element xmlroot: root element of xml to convert.
         :rtype: wsag_model.Agreement
         """
+        for name, value in xmlroot.attrib.items():
+            print '{0}="{1}"'.format(name, value)
+
         if xmlroot.tag in self.agreement_tags:
             result = Agreement()
-            result.agreement_id = xmlroot.attrib["AgreementId"]
+            agreementId = str(QName(self._namespaces["wsag"], "AgreementId"))
+            result.agreement_id = xmlroot.attrib[agreementId]
         elif xmlroot.tag in self.template_tags:
             result = Template()
-            result.template_id = xmlroot.attrib["TemplateId"]
+            templateId = str(QName(self._namespaces["wsag"], "TemplateId"))
+            result.template_id = xmlroot.attrib[templateId]
         else:
             raise ValueError("Not valid root element name: " + xmlroot.tag)
 
@@ -298,7 +318,6 @@ class AgreementConverter(Converter):
         return name, result
 
     def _parse_guarantees(self, elements):
-
         result = {}
         for element in elements:
             key, value = self._parse_guarantee(element)
@@ -341,7 +360,7 @@ def _get_attribute(element, attrname):
     isns = (attrname[0] == '{')
 
     #
-    # Handle qnamed request: 
+    # Handle qnamed request:
     #   attrname = {uri}name
     #
     if isns:
index 1965540..fea71f2 100755 (executable)
@@ -20,6 +20,12 @@ from django.http import HttpResponse
 
 import json
 import traceback
+import re
+from math import ceil
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from dateutil.tz import tzlocal
+from django.conf import settings
 
 
 class Rol:
@@ -93,29 +99,56 @@ class SLAView (FreeAccessView, ThemeView):
         agreement_id = None
         enforcements = {}
         violations = {}
+        keys = ['provider','agreement','date','status','result','ok']
+        ag_info = []
 
         filter_ = None
         form = FilterForm(request.GET)
         if form.is_valid():
-             print "IS VALID"
-             filter_ = _get_filter_from_form(form)
+            filter_ = _get_filter_from_form(form)
 
         consumer_id = _get_consumer_id(request)
-        
-        agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
-        
+
+        #agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
+        agreements = _get_agreements(agreement_id, slice=slicename)
+
         for agreement in agreements:
-            enf = _get_enforcement(agreement.agreement_id)
+            row = []
+            provider = agreement.context.provider
+            row.append(provider) # Provider
+            row.append(agreement) # Agreement
+            row.append(agreement.context.time_formatted()) # Date
+
+            enf = _get_enforcement(agreement.agreement_id, provider)
+
             if enf.enabled == 'true':
-                enforcements[agreement.agreement_id] = "ACTIVE"
-            else:
-                enforcements[agreement.agreement_id] = "UNACTIVE"
-            violations_list = _get_agreement_violations(agreement.agreement_id, "GT_Performance")
-            
-            if len(violations_list):
-                violations[agreement.agreement_id] = float(violations_list[0]["actualValue"])*100
+                row.append('Evaluating') # Status
+                row.append('') # Result
+                row('') # Ok
             else:
-                violations[agreement.agreement_id] = 100
+                if agreement.guaranteestatus == "NON_DETERMINED":
+                    row.append('Provisioned') # Status
+                    row.append('') # Result
+                    row.append('') # Ok
+                
+                else:
+                    row.append('Finished') # Status
+
+                    violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
+                    
+                    if len(violations_list) > 0:
+                        value = '%.2f'%float(violations_list[0].actual_value)
+                        row.append('%d'%(float(value)*100)) # Result
+                    else:
+                        row.append('100') # Result
+
+                    if agreement.guaranteestatus == "VIOLATED":
+                        row.append('false') # Ok
+
+                    if agreement.guaranteestatus == "FULFILLED":
+                        row.append('true') # Ok
+
+            ag_info.append(dict(zip(keys,row)))
 
         template_env = {}
        # write something of our own instead
@@ -126,13 +159,15 @@ class SLAView (FreeAccessView, ThemeView):
         template_env['slicename'] = slicename
         template_env['enforcements'] = enforcements
         template_env['last_violation_list'] = violations
-       
+        template_env['ag_info'] = ag_info
+
+
        # the prelude object in page contains a summary of the requirements() for all plugins
        # define {js,css}_{files,chunks}
         prelude_env = page.prelude_env()
         template_env.update(prelude_env)
-        
-        return render_to_response (self.template_name, template_env, context_instance=RequestContext(request))
+
+        return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
 
 
 class AgreementsFilter(object):
@@ -175,8 +210,8 @@ class ContactForm(forms.Form):
     cc_myself = forms.BooleanField(required=False)
 
 
-def _get_agreements_client():
-    return restclient.Factory.agreements()
+def _get_agreements_client(path=""):
+    return restclient.Factory.agreements(path)
 
 
 def _get_violations_client():
@@ -195,10 +230,10 @@ def _get_agreement(agreement_id):
     agreement, response = agreements_client.getbyid(agreement_id)
     return agreement
 
-def _get_enforcement(agreement_id):
+def _get_enforcement(agreement_id, testbed):
 
     enforcements_client = _get_enforcements_client()
-    enforcement, response = enforcements_client.getbyagreement(agreement_id)
+    enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
     return enforcement
 
 def _get_filter_from_form(form):
@@ -231,11 +266,7 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     except EmptyPage:
         # If page is out of range (e.g. 9999), deliver first page.
         violation_page = paginator.page(1)
-    
-    print "\n******************"
-    print violations[-1]
-    print "******************\n"
-
     context = {
         'agreement_id': agreement_id,
         'guarantee_term': agreement.guaranteeterms[guarantee_name],
@@ -274,18 +305,13 @@ def agreement_details(request, agreement_id):
     return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
     #return render(request, 'agreement_detail.html', context)
 
-
-def _get_agreements_client():
-    return restclient.Factory.agreements()
-
-
 def _get_agreement(agreement_id):
 
     agreements_client = _get_agreements_client()
     agreement, response = agreements_client.getbyid(agreement_id)
     return agreement
 
-def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=None):
+def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
 
     agreements_client = _get_agreements_client()
     if agreement_id is None:
@@ -293,6 +319,9 @@ def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=No
             agreements, response = agreements_client.getbyconsumer(consumer_id)
         elif provider_id is not None:
             agreements, response = agreements_client.getbyprovider(provider_id)
+        elif slice is not None:
+            agreements_client = _get_agreements_client("slice")
+            agreements, response = agreements_client.getbyslice(slice)
         else:
             raise ValueError(
                 "Invalid values: consumer_id and provider_id are None")
@@ -303,7 +332,8 @@ def _get_agreements(agreement_id, provider_id=None, consumer_id=None, filter_=No
     annotator = wsag_helper.AgreementAnnotator()
     for agreement in agreements:
         id_ = agreement.agreement_id
-        status = _get_agreement_status(id_)
+        testbed = agreement.context.provider
+        status = _get_agreement_status(id_, testbed)
         annotator.annotate_agreement(agreement, status)
 
     if filter_ is not None:
@@ -320,55 +350,94 @@ def _get_agreements_by_consumer(consumer_id):
     agreements, response = agreements_client.getbyconsumer(consumer_id)
     return agreements
 
-def _get_agreement_status(agreement_id):
+def _get_agreement_status(agreement_id, testbed):
 
     agreements_client = _get_agreements_client()
-    status, response = agreements_client.getstatus(agreement_id)
+    status, response = agreements_client.getstatus(agreement_id, testbed)
     return status
 
-def _get_agreement_violations(agreement_id, term=None):
+def _get_agreement_violations(agreement_id, testbed, term=None):
 
     violations_client = _get_violations_client()
-    violations, response = violations_client.getbyagreement(agreement_id, term)
+    violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
     return violations
 
 
 class AgreementSimple(APIView):
+
+    regex = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
+
     def build_response(self, code, text):
         response = HttpResponse(text, content_type="text/plain", status=code)
         return response 
 
-    def post( self, request, **kwargs):
+    def post(self, request, **kwargs):
         #import pdb; pdb.set_trace()
         print "------------------------------------------------1"
-        data = {}
-        for key, value in request.DATA.items():
-            new_key = key
-            data[new_key] = value
+        data = request.POST
+
+        url = settings.SLA_MANAGER_URL
+        c = restclient.Client(url)
+        # for key, value in request.DATA.items(): # jgarcia review this
+        #     data[key] = value
         
-        try:
-            template_id = data['template_id']
-        except:
-            return self.build_response(400, 'Invalid template_id')
+        # print "---- DATA: ----"
+        # print "Data type: ", type(data)
+        # for key in data:
+        #     print key, data.getlist(key)
 
         try:
-            user = data['user']
+            # template_id = data['template_id']
+            testbeds = data.getlist("testbeds")
+            user = data["user"]
+            resources = data.getlist("resources")
+            slice_id = data["slice"]
         except:
-            return self.build_response(400, 'Invalid user')
+            print "FAIL!"
+            return self.build_response(400, 'Invalid data')
+
+        selected_resources = {}
+
+        now = datetime.now(tzlocal())
+        expiration_time = now + relativedelta(years=1)
+
+        for testbed in testbeds:
+            selected_resources[testbed] = [r for r in resources if testbed in r]
+            template_id = testbed
+            try:
+                print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
+                result = fed4fireservice.createagreementsimplified(
+                            template_id, user, expiration_time, selected_resources)
+                print result
+            except Exception, e:
+                print traceback.format_exc()
+                print '%s (%s)' % (e, type(e))
+                return self.build_response(400, 'Problem creating agreement')
+
+            agreement_id = re.compile(self.regex).search(result.text).group(0)
+         
+            data = '{{ "id": "{}", \
+                      "slice": "{}", \
+                      "testbed": "{}" }}'.format(agreement_id, slice_id, testbed)
+
+            c.post(
+                "sliver",
+                data,
+                headers = {
+                    "content-type": "application/json",
+                    "accept": "application/xml"
+                }
+            )   
 
-        try:
-            expiration_time = data['expiration_time']
-        except:
-            return self.build_response(400, 'Invalid expiration_time')
+        return self.build_response(200, result)            
 
-        try:
-            print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
-            result = fed4fireservice.createagreementsimplified(template_id, user, expiration_time)
-            print result
-        except Exception, e:
-            print traceback.format_exc()
-            print '%s (%s)' % (e, type(e))
-            
-            return self.build_response(400, 'Problem creating agreement')
+class Testbeds(APIView):
+    def get(self, request, **kwargs):
+        c = restclient.Client("http://157.193.215.125:4001/sla-collector")
+        #url = settings.SLA_MANAGER_URL.replace("/sla","")
+        #c = restclient.Client(url)
+        print "**** URL ******", url
+        SLAtestbeds = c.get("testbeds")
+        # Future work: get SLA description for each testbed
 
-        return self.build_response(200, result)            
+        return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
diff --git a/sla/static/images/sort_asc.png b/sla/static/images/sort_asc.png
new file mode 100644 (file)
index 0000000..a88d797
Binary files /dev/null and b/sla/static/images/sort_asc.png differ
diff --git a/sla/static/images/sort_both.png b/sla/static/images/sort_both.png
new file mode 100644 (file)
index 0000000..8222cdb
Binary files /dev/null and b/sla/static/images/sort_both.png differ
diff --git a/sla/static/images/sort_desc.png b/sla/static/images/sort_desc.png
new file mode 100644 (file)
index 0000000..def071e
Binary files /dev/null and b/sla/static/images/sort_desc.png differ
index f09aa8d..725d7d9 100755 (executable)
@@ -3,32 +3,13 @@
 </div>
 
  <div class="col-md-9">
-   <div class="row" id="agreements">
-    <table class="table dataTable" id="sla_table" >
-        <thead>
-        <tr class="header">
-            <th colspan="2">Provider</th>
-            <!-- <th>Testbed</th>
-            <th>Slice_Id</th>
-            <th>Agreement</th>
-            <th>Metric</th>
-            <th>Violations</th>
-            <th>Result</th> -->
-        </tr>
-        </thead>
-        <tbody>
+   <div class="row" id="agreements" style="padding-top:1em;">
+    
         
-       <tr class="header">
-                       <td><span class="glyphicon glyphicon-chevron-down"></span></td>
-                       <td>iMinds</td>
-       </tr>
-       
-       
-        {% for a in agreements %}
-
+{% for row in ag_info %}
 
 <!-- Modal - columns selector -->
-<div class="modal fade" id="agreementModal{{a.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+<div class="modal fade" id="agreementModal{{row.agreement.agreement_id}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                        
 <style type="text/css" scoped>
         .modal-lg {
                        </div>
                        <div class="modal-body">
 
-                 <dt>Agreement Id</dt>
-                 <dd>{{ a.agreement_id|default:"&nbsp;" }}</dd>
-                 <dt>Provider</dt>
-                 <dd>{{ a.context.provider|default:"&nbsp;" }}</dd>
-                 <dt>Experimenter</dt>
-                 <dd>{{ a.context.consumer|default:"&nbsp;" }}</dd>
-                 <dt>Service</dt>
-                 <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
-                 <dt>Testbed</dt>
-                 <dd>{{ a.context.testbed_formatted }}</dd>
-                 <dt>Accepted on:</dt>
-                 <dd>{{ a.context.time_formatted|default:"&nbsp;" }}</dd>
+                <dt>Agreement Id</dt>
+                <dd>{{ row.agreement.agreement_id|default:"&nbsp;" }}</dd>
+                <dt>Provider</dt>
+                <dd>{{ row.provider|default:"&nbsp;" }}</dd>
+                <dt>Experimenter</dt>
+                <dd>{{ row.agreement.context.consumer|default:"&nbsp;" }}</dd>
+                <dt>Service</dt>
+                <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+                <dt>Testbed</dt>
+                <dd>{{ row.agreement.context.testbed_formatted }}</dd>
+                <dt>Expiration date:</dt>
+                <dd>{{ row.date|default:"&nbsp;" }}</dd>
                        </div>
                        <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </div>
        </div>
 </div>
-       
-       <tr>
-                       {% if a.guaranteestatus == "VIOLATED" %}
-                       <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
-               {% elif a.guaranteestatus == "FULFILLED" %}
-               <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+
+{% endfor %}
+
+      <table class="table table-striped table-bordered" id="sla_table">
+      
+        <thead>
+          <tr> 
+            <th>Provider</th>
+            <th>Agreement</th>
+            <th>Date</th>
+            <th>Status</th>
+            <th>Result</th>
+          </tr>
+        </thead>
+
+        <tbody>
+        {% for row in ag_info %}
+
+        <tr>
+               
+          <td>{{ row.provider }}</td>
+
+          <td><a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{row.agreement.agreement_id}}">{{ row.agreement.context.template_id }}</a></td>
+                 
+          <td>{{ row.date }}</td>
+          <td>{{ row.status }}</td>
+          {% if row.ok == "true" %}
+          <td class="success">99% uptime for {{ row.result }}% resources</td>
+          {% elif row.ok == "false" %}
+          <td class="danger">99% uptime for {{ row.result }}% resources</td>
           {% else %}
           <td></td>
-               {% endif %}
-                 <td>{{ a.context.template_id }}</td>
-          <td>{{ a.context.time_formatted }}</td>
-          
-          {% with a.agreement_id as key %}
-          
-          <td>
-              <!-- <a class="agreement-detail" href="{% url "agreement_details" a.agreement_id %}" data-toggle="modal" data-target="#agreementModal">View Agreement</a> -->
-              <!-- <a class="agreement-detail" href="#" data-agreement="{{ a.agreement_id }}">View Agreement</a> -->
-              <a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{a.agreement_id}}">View Agreement</a>
-          </td>
-
-          {% for k,v in enforcements.items %}
-            {% if key == k %}
-              <td>
-              {% if v == "ACTIVE" %}
-                In progress
-              {% elif v == "UNACTIVE" %}
-                Disabled
-              {% endif %}
-              </td>
-
-              {% if a.guaranteestatus == "VIOLATED" and v == "UNACTIVE" %}
-              <td style="font-weight: bold">
-                Result: 99% uptime for
-                {% for vi, value in last_violation_list.items %}
-                  {% if a.agreement_id == vi %}
-                      {{ value }}%
-                  {% endif %}
-                {% endfor %}
-                resources
-              </td>
-              {% elif a.guaranteestatus == "FULFILLED" and v == "UNACTIVE" %}
-              <td style="font-weight: bold">
-                Result: 99% uptime for
-                {% for vi, value in last_violation_list.items %}
-                  {% if a.agreement_id == vi %}
-                      {{ value }}%
-                  {% endif %}
-                {% endfor %}
-                resources
-              </td>
-              {% endif %}
-            {% endif %}
-
-          {% endfor %}
-          
-          <!-- <td>{{slicename}}</td> -->
-
-          
+          {% endif %}
+          <!-- {% if row.ok == "false" %}
+          <td class="glyphicon glyphicon-remove-sign" style="color:red;"></td>
+          {% elif row.ok == "true" %}
+          <td class="glyphicon glyphicon-ok-sign" style="color:green;"></td>
+          {% else %}
+          <td></td>
+          {% endif %} -->
 
           
-              
-
-            {% endwith %}
-            <!-- {% for tname,t in a.guaranteeterms.items %}
-            <td> {{ t.servicelevelobjective.kpiname }}</td>
-            <td>
-                {% if t.status == "VIOLATED" %}
-
-                  <a class="violation-detail" href="{% url "agreement_term_violations" a.agreement_id t.name %}" data-toggle="modal" data-target="#violationModal">View Violations</a>
-                  <a class="violation-detail" href="#"
-                                       data-agreement="{{ a.agreement_id }}" 
-                                       data-violation="{{ t.name }}">View Violations</a>
-                  <a class="violation-detail" href="#" data-agreement="{{ a.agreement_id }}" data-violation="{{ t.name }}">{{last_violation_list}}</a>
-                  {{ t.name }}
-
-                {% endif %}
-            </td>
-            <td id="status" style="display:none;">
-                {{ a.statusclass }}
-            </td>
-            {% endfor %} -->
-
-
-            
         </tr>
         
-        
         {% endfor %}
         </tbody>
 
 
 <script>
 $(document).ready(function() {
+
+  $('#sla_table').dataTable({
+        "aoColumns": [
+            null,
+            null,
+            null,
+            null,
+            { "orderSequence": [ "desc", "asc" ] }
+        ]
+    });
+
        $('a.violation-detail').click(function () {
                var a = $(this).data('agreement');
                var v = $(this).data('violation');
index 5bc087c..e385baf 100755 (executable)
@@ -3,10 +3,10 @@ from django.conf.urls import patterns, url, include
 from sla import slicetabsla
 
 urlpatterns = patterns('',
-   url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),                       
-    url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
-    url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
-    url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
-    url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
-)
-
+       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
+       url(r'^testbeds/', slicetabsla.Testbeds.as_view(), name="testbeds"),
+       url(r'^(?P<slicename>[^/]+)/?$', slicetabsla.SLAView.as_view(), name="agreements_summary"),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/detail$', slicetabsla.agreement_details, name='agreement_details'),
+       url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$', slicetabsla.agreement_term_violations, name='agreement_term_violations'),
+       url(r'^agreements/simplecreate/?$', slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
+)
\ No newline at end of file
index 988af27..667711d 100644 (file)
@@ -72,7 +72,9 @@ def topmenu_items_live (current, page):
     request=page.request
     # XXX TODO This should be triggered only when user is logged in
     # We might use local storage instead
-    query_pi_auths = Query.get('user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_pi_auths = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
     page.enqueue_query(query_pi_auths)
 #        # even though this plugin does not have any html materialization, the corresponding domid
 #        # must exist because it is searched at init-time to create the JS plugin
index 42a3506..821c662 100644 (file)
@@ -123,6 +123,10 @@ class Page:
         # xxx this is fetched synchroneously..
         self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";\n")
 
+    def expose_js_var(self, name, value):
+        # expose variable as a js value
+        self.add_js_init_chunks("var " + name + "=" + value + ";\n")
+
     def expose_js_manifold_config (self):
         self.add_js_init_chunks(ConfigEngine().manifold_js_export())