diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f420a9f5..fac5f663 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ services: variables: # GestioCOF settings - DJANGO_SETTINGS_MODULE: "cof.settings_dev" + DJANGO_SETTINGS_MODULE: "gestioCOF.settings_dev" DBNAME: "cof_gestion" DBUSER: "cof_gestion" DBPASSWD: "cof_password" diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..1af5efa7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 cof-geek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index c5c212e3..1a3d575e 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,9 @@ Il ne vous reste plus qu'à initialiser les modèles de Django avec la commande python manage.py migrate +Charger les mails indispensables au bon fonctionnement de GestioCOF : + + python manage.py syncmails Une base de donnée pré-remplie est disponible en lançant les commandes : diff --git a/bda/admin.py b/bda/admin.py index 0e9b683b..fc10c326 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals +import autocomplete_light +from datetime import timedelta +from custommail.shortcuts import send_mass_custom_mail -from django.core.mail import send_mail from django.contrib import admin from django.db.models import Sum, Count from django.template.defaultfilters import pluralize @@ -13,10 +12,6 @@ from django import forms from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\ Attribution, Tirage, Quote, CategorieSpectacle, SpectacleRevente -from datetime import timedelta - -import autocomplete_light - class ChoixSpectacleInline(admin.TabularInline): model = ChoixSpectacle @@ -72,66 +67,20 @@ class ParticipantAdmin(admin.ModelAdmin): readonly_fields = ("total",) def send_attribs(self, request, queryset): + datatuple = [] for member in queryset.all(): attribs = member.attributions.all() + context = {'member': member.user} + shortname = "" if len(attribs) == 0: - mail = """Cher-e %s, - -Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as -obtenu aucune place. - -Nous proposons cependant de nombreuses offres hors-tirage tout au long de -l'année, et nous t'invitons à nous contacter si l'une d'entre elles -t'intéresse ! --- -Le Bureau des Arts - -""" - name = member.user.get_full_name() - mail = mail % name + shortname = "bda-attributions-decus" else: - mail = """Cher-e %s, - -Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e -pour les spectacles suivants : - -%s - -*Paiement* -L'intégralité de ces places de spectacles est à régler dès maintenant et AVANT -le %s, au bureau du COF pendant les heures de permanences (du lundi au vendredi -entre 12h et 14h, et entre 18h et 20h). Des facilités de paiement sont bien -évidemment possibles : nous pouvons ne pas encaisser le chèque immédiatement, -ou bien découper votre paiement en deux fois. Pour ceux qui ne pourraient pas -venir payer au bureau, merci de nous contacter par mail. - -*Mode de retrait des places* -Au moment du paiement, certaines places vous seront remises directement, -d'autres seront à récupérer au cours de l'année, d'autres encore seront -nominatives et à retirer le soir même dans les theâtres correspondants. -Pour chaque spectacle, vous recevrez un mail quelques jours avant la -représentation vous indiquant le mode de retrait. - -Nous vous rappelons que l'obtention de places du BdA vous engage à -respecter les règles de fonctionnement : -http://www.cof.ens.fr/bda/?page_id=1370 -Le système de revente des places via les mails BdA-revente sera très -prochainement disponible, directement sur votre compte GestioCOF. - -En vous souhaitant de très beaux spectacles tout au long de l'année, --- -Le Bureau des Arts -""" - attribs_text = "" - name = member.user.get_full_name() - for attrib in attribs: - attribs_text += "- 1 place pour %s\n" % attrib - deadline = member.tirage.fermeture + timedelta(days=7) - mail = mail % (name, attribs_text, - deadline.strftime('%d %b %Y')) - send_mail("Résultats du tirage au sort", mail, - "bda@ens.fr", [member.user.email], - fail_silently=True) + shortname = "bda-attributions" + context['places'] = attribs + print(context) + datatuple.append((shortname, context, "bda@ens.fr", + [member.user.email])) + send_mass_custom_mail(datatuple) count = len(queryset.all()) if count == 1: message_bit = "1 membre a" diff --git a/bda/forms.py b/bda/forms.py index 352914e4..e2a1961b 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -8,7 +8,6 @@ from datetime import timedelta from django import forms from django.forms.models import BaseInlineFormSet -from django.db.models import Q from django.utils import timezone from bda.models import Attribution, Spectacle diff --git a/bda/management/commands/loadbdadevdata.py b/bda/management/commands/loadbdadevdata.py index f348b310..69eab6fc 100644 --- a/bda/management/commands/loadbdadevdata.py +++ b/bda/management/commands/loadbdadevdata.py @@ -6,7 +6,7 @@ import os import random from django.utils import timezone -from django.contrib.auth.models import User +from django.contrib.auth.models import Group from cof.management.base import MyBaseCommand from bda.models import Tirage, Spectacle, Salle, Participant, ChoixSpectacle @@ -77,7 +77,8 @@ class Command(MyBaseCommand): self.stdout.write("Inscription des utilisateurs aux tirages") ChoixSpectacle.objects.all().delete() choices = [] - for user in User.objects.filter(profile__cof__is_cof=True): + cof_members = Group.objects.get(name="cof_members") + for user in cof_members.user_set.all(): for tirage in tirages: part, _ = Participant.objects.get_or_create( user=user, diff --git a/bda/models.py b/bda/models.py index f9087ac1..a405a665 100644 --- a/bda/models.py +++ b/bda/models.py @@ -3,12 +3,11 @@ import calendar import random from datetime import timedelta +from custommail.shortcuts import send_mass_custom_mail from django.contrib.sites.models import Site from django.db import models from django.contrib.auth.models import User -from django.template import loader -from django.core import mail from django.conf import settings from django.utils import timezone, formats @@ -91,33 +90,30 @@ class Spectacle(models.Model): if member.id in members: members[member.id][1] = 2 else: - members[member.id] = [member.first_name, 1, member.email] - # Pour le BdA - members[0] = ['BdA', 1, 'bda@ens.fr'] - members[-1] = ['BdA', 2, 'bda@ens.fr'] + members[member.id] = [member, 1] + # FIXME : faire quelque chose de ça, un utilisateur bda_generic ? + # # Pour le BdA + # members[0] = ['BdA', 1, 'bda@ens.fr'] + # members[-1] = ['BdA', 2, 'bda@ens.fr'] # On écrit un mail personnalisé à chaque participant - mails_to_send = [] - mail_object = str(self) - for member in members.values(): - mail_body = loader.render_to_string('bda/mails/rappel.txt', { - 'name': member[0], - 'nb_attr': member[1], - 'show': self}) - mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['rappels']['FROM'], [member[2]], - [], headers={ - 'Reply-To': settings.MAIL_DATA['rappels']['REPLYTO']}) - mails_to_send.append(mail_tot) - # On envoie les mails - connection = mail.get_connection() - connection.send_messages(mails_to_send) + datatuple = [( + 'bda-rappel', + {'member': member[0], 'nb_attr': member[1], 'show': self}, + settings.MAIL_DATA['rappels']['FROM'], + [member[0].email]) + for member in members.values() + ] + send_mass_custom_mail(datatuple) # On enregistre le fait que l'envoi a bien eu lieu self.rappel_sent = timezone.now() self.save() # On renvoie la liste des destinataires return members.values() + @property + def is_past(self): + return self.date < timezone.now() + class Quote(models.Model): spectacle = models.ForeignKey(Spectacle) @@ -238,26 +234,24 @@ class SpectacleRevente(models.Model): verbose_name = "Revente" def send_notif(self): + """ + Envoie une notification pour indiquer la mise en vente d'une place sur + BdA-Revente à tous les intéressés. + """ inscrits = self.attribution.spectacle.subscribed.select_related('user') - - mails_to_send = [] - mail_object = "%s" % (self.attribution.spectacle) - for participant in inscrits: - mail_body = loader.render_to_string('bda/mails/revente.txt', { - 'user': participant.user, - 'spectacle': self.attribution.spectacle, + datatuple = [( + 'bda-revente', + { + 'member': participant.user, + 'show': self.attribution.spectacle, 'revente': self, - 'domain': Site.objects.get_current().domain}) - mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['revente']['FROM'], - [participant.user.email], - [], headers={ - 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) - mails_to_send.append(mail_tot) - - connection = mail.get_connection() - connection.send_messages(mails_to_send) + 'site': Site.objects.get_current() + }, + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email]) + for participant in inscrits + ] + send_mass_custom_mail(datatuple) self.notif_sent = True self.save() @@ -267,25 +261,18 @@ class SpectacleRevente(models.Model): leur indiquer qu'il est désormais disponible au shotgun. """ inscrits = self.attribution.spectacle.subscribed.select_related('user') - - mails_to_send = [] - mail_object = "%s" % (self.attribution.spectacle) - for participant in inscrits: - mail_body = loader.render_to_string('bda/mails/shotgun.txt', { - 'user': participant.user, - 'spectacle': self.attribution.spectacle, - 'domain': Site.objects.get_current(), - 'mail': self.attribution.participant.user.email}) - mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['revente']['FROM'], - [participant.user.email], - [], headers={ - 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) - mails_to_send.append(mail_tot) - - connection = mail.get_connection() - connection.send_messages(mails_to_send) + datatuple = [( + 'bda-shotgun', + { + 'member': participant.user, + 'show': self.attribution.spectacle, + 'site': Site.objects.get_current(), + }, + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email]) + for participant in inscrits + ] + send_mass_custom_mail(datatuple) self.notif_sent = True # Flag inutile, sauf si l'horloge interne merde self.tirage_done = True @@ -303,56 +290,41 @@ class SpectacleRevente(models.Model): seller = self.seller if inscrits: - mails = [] - mail_subject = "BdA-Revente : {:s}".format(spectacle.title) - # Envoie un mail au gagnant et au vendeur winner = random.choice(inscrits) self.soldTo = winner + datatuple = [] context = { 'acheteur': winner.user, 'vendeur': seller.user, - 'spectacle': spectacle, + 'show': spectacle, } - mails.append(mail.EmailMessage( - mail_subject, - loader.render_to_string('bda/mails/revente-winner.txt', - context), - from_email=settings.MAIL_DATA['revente']['FROM'], - to=[winner.user.email], - reply_to=[seller.user.email], + datatuple.append(( + 'bda-revente-winner', + context, + settings.MAIL_DATA['revente']['FROM'], + [winner.user.email], )) - mails.append(mail.EmailMessage( - mail_subject, - loader.render_to_string('bda/mails/revente-seller.txt', - context), - from_email=settings.MAIL_DATA['revente']['FROM'], - to=[seller.user.email], - reply_to=[winner.user.email], + datatuple.append(( + 'bda-revente-seller', + context, + settings.MAIL_DATA['revente']['FROM'], + [seller.user.email] )) # Envoie un mail aux perdants for inscrit in inscrits: - if inscrit == winner: - continue - - mail_body = loader.render_to_string( - 'bda/mails/revente-loser.txt', - {'acheteur': inscrit.user, - 'vendeur': seller.user, - 'spectacle': spectacle} - ) - mails.append(mail.EmailMessage( - mail_subject, mail_body, - from_email=settings.MAIL_DATA['revente']['FROM'], - to=[inscrit.user.email], - reply_to=[settings.MAIL_DATA['revente']['REPLYTO']], - )) - mail.get_connection().send_messages(mails) - + if inscrit != winner: + context['acheteur'] = inscrit.user + datatuple.append(( + 'bda-revente-loser', + context, + settings.MAIL_DATA['revente']['FROM'], + [inscrit.user.email] + )) + send_mass_custom_mail(datatuple) # Si personne ne veut de la place, elle part au shotgun else: self.shotgun = True - self.tirage_done = True self.save() diff --git a/bda/static/bda/js/jquery-1.6.2.min.js b/bda/static/bda/js/jquery-1.6.2.min.js deleted file mode 100644 index 48590ecb..00000000 --- a/bda/static/bda/js/jquery-1.6.2.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6.2 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu Jun 30 14:16:56 2011 -0400 - */ -(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},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(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. -shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j -)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/bda/static/bda/js/jquery-ui-1.8.15.custom.min.js b/bda/static/bda/js/jquery-ui-1.8.15.custom.min.js deleted file mode 100644 index fc39d245..00000000 --- a/bda/static/bda/js/jquery-ui-1.8.15.custom.min.js +++ /dev/null @@ -1,347 +0,0 @@ -/*! - * jQuery UI 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.15", -keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,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,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d= -this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this, -"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart": -"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight, -outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a, -"tabindex"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&& -a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= -false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); -;/* - * jQuery UI Position 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Position - */ -(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY, -left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+= -k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+(parseInt(c.curCSS(this,"marginRight",true))||0),w=m+q+(parseInt(c.curCSS(this,"marginBottom",true))||0),i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-= -m/2;i.left=Math.round(i.left);i.top=Math.round(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left= -d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= -a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), -g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); -;/* - * jQuery UI Sortable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Sortables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); -this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== -"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&& -!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);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};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; -this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!= -document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a); -return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0], -e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset(); -c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;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 b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(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();d.extend(this,{helper:null, -dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")}, -toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith(); -if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), -this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b= -this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f= -d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")|| -0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out", -a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h- -f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g- -this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this, -this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop", -a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); -a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); -if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", -function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a= -this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); -this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); -b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); -a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ -c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; -if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){var h=this.active;j=a.next();g=this.active.next();e={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):j,oldContent:g};var f=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(j,g,e,b,f);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); -if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(), -e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight|| -e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false", -"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.15", -animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/); -f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide", -paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); -;/* - * jQuery UI Autocomplete 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.position.js - */ -(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= -false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= -a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; -this.menu=d("
    ").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& -a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); -d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& -b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= -this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, -"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); -(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", --1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); -this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, -this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| -this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| -this.first()?":last":":first"))},hasScroll:function(){return this.element.height()")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ -b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
    ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), -h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", -e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); -a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== -b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; -d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== -f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
    ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
    ").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, -function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", -handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, -originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", -f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): -[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); -if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): -e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= -this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- -b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.15",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), -create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(), -height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight); -b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
  • #{label}
  • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& -e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= -d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| -(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a.element.find(a._sanitizeSelector(i)));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=a.element.find("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); -this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= -this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); -if(c.selected>=0&&this.anchors.length){a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash))[0]))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); -this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ -g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", -function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; -this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=a.element.find(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected= --1;c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; -d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= -d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, -e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=c.element.find("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); -j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); -if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, -this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, -load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c, -"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, -url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.15"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k'))}function N(a){return a.bind("mouseout", -function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");b.length&&b.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(d.datepicker._isDisabledDatepicker(J.inline?a.parent()[0]:J.input[0])||!b.length)){b.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); -b.addClass("ui-state-hover");b.hasClass("ui-datepicker-prev")&&b.addClass("ui-datepicker-prev-hover");b.hasClass("ui-datepicker-next")&&b.addClass("ui-datepicker-next-hover")}})}function H(a,b){d.extend(a,b);for(var c in b)if(b[c]==null||b[c]==C)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.15"}});var B=(new Date).getTime(),J;d.extend(M.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, -setDefaults:function(a){H(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g, -"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:N(d('
    '))}},_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", -function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b);b.settings.disabled&&this._disableDatepicker(a)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c== -"focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f==""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker(): -d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a, -b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),true);this._updateDatepicker(b);this._updateAlternate(b);b.settings.disabled&&this._disableDatepicker(a);b.dpDiv.css("display","block")}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+= -1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}H(a.settings,e||{});b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ -2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b= -d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e= -a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().removeClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a, -"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().addClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f== -a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input", -a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);if(d.datepicker._curInst&&d.datepicker._curInst!=b){d.datepicker._datepickerShowing&&d.datepicker._triggerOnClose(d.datepicker._curInst);d.datepicker._curInst.dpDiv.stop(true,true)}var c=d.datepicker._get(b,"beforeShow");H(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos= -d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b, -c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.datepicker._datepickerShowing=true;d.effects&& -d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){this.maxRows=4;var b=d.datepicker._getBorders(a.dpDiv);J=a;a.dpDiv.empty().append(this._generateHTML(a));var c=a.dpDiv.find("iframe.ui-datepicker-cover");c.length&&c.css({left:-b[0],top:-b[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()});a.dpDiv.find("."+ -this._dayOverClass+" a").mouseover();b=this._getNumberOfMonths(a);c=b[1];a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");c>1&&a.dpDiv.addClass("ui-datepicker-multi-"+c).css("width",17*c+"em");a.dpDiv[(b[0]!=1||b[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&& -a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var e=a.yearshtml;setTimeout(function(){e===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);e=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth(): -0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a), -"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_triggerOnClose:function(a){var b=this._get(a,"onClose");if(b)b.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a])},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst= -null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();d.datepicker._triggerOnClose(b);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, -_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"): -0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e["selected"+(c=="M"? -"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a); -this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a, -"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b== -"")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=A+1-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,j-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=j||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y", -RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=k+112?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear; -b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a));if(c=this._get(a,"onSelect")){e=this._formatDate(a);c.apply(a.input?a.input[0]:null,[e,a])}},_getDate:function(a){return!a.currentYear||a.input&&a.input.val()== -""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),j=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?new Date(9999, -9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),k=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=k&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-j,1)),this._getFormatConfig(a)); -n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var s=this._get(a,"nextText");s=!h?s:this.formatDate(s,this._daylightSavingAdjust(new Date(m, -g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+s+"":f?"":''+s+"";j=this._get(a,"currentText");s=this._get(a,"gotoCurrent")&& -a.currentDay?u:b;j=!h?j:this.formatDate(j,s,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
    '+(c?h:"")+(this._isInRange(a,s)?'":"")+(c?"":h)+"
    ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");s=this._get(a,"dayNames");this._get(a,"dayNamesShort");var q=this._get(a,"dayNamesMin"),A=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),D=this._get(a,"showOtherMonths"),K=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var E=this._getDefaultDate(a),w="",x=0;x1)switch(G){case 0:y+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:y+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:y+=" ui-datepicker-group-middle";t="";break}y+='">'}y+='
    '+(/all|left/.test(t)&& -x==0?c?f:n:"")+(/all|right/.test(t)&&x==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,x>0||G>0,A,v)+'
    ';var z=j?'":"";for(t=0;t<7;t++){var r=(t+h)%7;z+="=5?' class="ui-datepicker-week-end"':"")+'>'+q[r]+""}y+=z+"";z=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, -z);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;z=Math.ceil((t+z)/7);this.maxRows=z=l?this.maxRows>z?this.maxRows:z:z;r=this._daylightSavingAdjust(new Date(m,g,1-t));for(var Q=0;Q";var R=!j?"":'";for(t=0;t<7;t++){var I=p?p.apply(a.input?a.input[0]:null,[r]):[true,""],F=r.getMonth()!=g,L=F&&!K||!I[0]||k&&ro;R+='";r.setDate(r.getDate()+1);r=this._daylightSavingAdjust(r)}y+=R+""}g++;if(g>11){g=0;m++}y+="
    '+this._get(a,"weekHeader")+"
    '+this._get(a,"calculateWeek")(r)+""+(F&&!D?" ":L?''+ -r.getDate()+"":''+r.getDate()+"")+"
    "+(l?""+(i[0]>0&&G==i[1]-1?'
    ':""):"");O+=y}w+=O}w+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': -"");a._keyEvent=false;return w},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='
    ',o="";if(h||!j)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(k+=o+(h||!(j&&l)?" ":""));if(!a.yearshtml){a.yearshtml="";if(h||!l)k+=''+c+"";else{g=this._get(a,"yearRange").split(":");var s=(new Date).getFullYear();i=function(q){q=q.match(/c[+-].*/)?c+parseInt(q.substring(1),10):q.match(/[+-].*/)?s+parseInt(q,10):parseInt(q,10);return isNaN(q)?s:q};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b, -e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='";k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="
    ";return k},_adjustInstDate:function(a,b,c){var e=a.drawYear+(c=="Y"?b:0),f=a.drawMonth+ -(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");if(b)b.apply(a.input? -a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);c=this._daylightSavingAdjust(new Date(c, -e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a, -"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=function(a){if(!this.length)return this; -if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));return this.each(function(){typeof a== -"string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new M;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.15";window["DP_jQuery_"+B]=d})(jQuery); -; \ No newline at end of file diff --git a/bda/static/css/bda.css b/bda/static/css/bda.css index d97bb954..4d6ecfbd 100644 --- a/bda/static/css/bda.css +++ b/bda/static/css/bda.css @@ -43,3 +43,6 @@ td { margin: 10px 0px; } +.spectacle-passe { + opacity:0.5; +} diff --git a/bda/templates/bda-participants.html b/bda/templates/bda-participants.html index 3efeccc3..289d1761 100644 --- a/bda/templates/bda-participants.html +++ b/bda/templates/bda-participants.html @@ -47,11 +47,8 @@ {% for participant in participants %}{{participant.name}} : {{participant.nb_places}} places {% endfor %} - - - + - + src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}"> + - + + + {% endblock %} @@ -91,12 +92,6 @@ var django = {

    Inscription au tirage au sort du BdA

    - {% if success %} -

    Votre inscription a été mise à jour avec succès !

    - {% endif %} - {% if stateerror %} -

    Impossible d'enregistrer vos modifications: vous avez apporté d'autres modifications entre temps

    - {% endif %}
    {% csrf_token %} {% include "bda/inscription-formset.html" %} @@ -113,7 +108,7 @@ var django = {

    - 1: cette liste de vœu est ordonnée (du plus important au moins important), pour ajuster la priorité vous pouvez déplacer chaque vœu.
    + 1: cette liste de vœux est ordonnée (du plus important au moins important), pour ajuster la priorité vous pouvez déplacer chaque vœu.

    diff --git a/bda/templates/liste-reventes.html b/bda/templates/bda/liste-reventes.html similarity index 72% rename from bda/templates/liste-reventes.html rename to bda/templates/bda/liste-reventes.html index c0bf8ff0..fcf57345 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/bda/liste-reventes.html @@ -3,15 +3,6 @@ {% block realcontent %}

    Inscriptions pour BdA-Revente

    - {% if success %} -

    Ton inscription a bien été prise en compte !

    - {% endif %} - {% if deja_revente %} -

    Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !

    - {% elif inscrit_revente %} -

    Tu as été inscrit à une revente en cours pour ce spectacle !

    - {% endif %} -
    {% csrf_token %}
    diff --git a/bda/templates/bda/mails-rappel.html b/bda/templates/bda/mails-rappel.html new file mode 100644 index 00000000..73625d1c --- /dev/null +++ b/bda/templates/bda/mails-rappel.html @@ -0,0 +1,43 @@ +{% extends "base_title.html" %} + +{% block realcontent %} +

    Mails de rappels

    + {% if sent %} +

    Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes

    +
      + {% for member in members %} +
    • {{ member.get_full_name }} ({{ member.email }})
    • + {% endfor %} +
    + {% else %} +

    Voulez vous envoyer les mails de rappel pour le spectacle + {{ show.title }} ?

    + {% if show.rappel_sent %} +

    Attention, les mails ont déjà été envoyés le + {{ show.rappel_sent }}

    + {% endif %} + {% endif %} + + {% if not sent %} + + {% csrf_token %} +
    + +
    + + {% endif %} + +
    +
    +

    Forme des mails

    + +

    Une seule place

    + {% for part in exemple_mail_1place %} +
    {{ part }}
    + {% endfor %} + +

    Deux places

    + {% for part in exemple_mail_2places %} +
    {{ part }}
    + {% endfor %} +{% endblock %} diff --git a/bda/templates/bda/mails/buy-shotgun.txt b/bda/templates/bda/mails/buy-shotgun.txt deleted file mode 100644 index d7855143..00000000 --- a/bda/templates/bda/mails/buy-shotgun.txt +++ /dev/null @@ -1,6 +0,0 @@ -Bonjour {{ vendeur.first_name }} ! - -Je souhaiterais racheter ta place pour {{ spectacle.title }} le {{ spectacle.date }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. -Contacte-moi si tu es toujours intéressé·e ! - -{{ acheteur.get_full_name }} ({{ acheteur.email }}) diff --git a/bda/templates/bda/mails/rappel.txt b/bda/templates/bda/mails/rappel.txt deleted file mode 100644 index c6433f8a..00000000 --- a/bda/templates/bda/mails/rappel.txt +++ /dev/null @@ -1,23 +0,0 @@ -Bonjour {{ name }}, - -Nous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:"une place,deux places" }} -pour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre ! -{% if nb_attr == 2 %} -Tu as obtenu deux places pour ce spectacle. Nous te rappelons que -ces places sont strictement réservées aux personnes de moins de 28 ans. -{% endif %} -{% if show.listing %}Pour ce spectacle, tu as reçu des places sur -listing. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la représentation -pour retirer {{ nb_attr|pluralize:"ta place,tes places" }}. -{% else %}Pour assister à ce spectacle, tu dois présenter les billets qui ont -été distribués au burô. -{% endif %} - -Si tu ne peux plus assister à cette représentation, tu peux -revendre ta place via BdA-revente, accessible directement sur -GestioCOF (lien "revendre une place du premier tirage" sur la page -d'accueil https://www.cof.ens.fr/gestion/). - -En te souhaitant un excellent spectacle, - -Le Bureau des Arts diff --git a/bda/templates/bda/mails/revente-loser.txt b/bda/templates/bda/mails/revente-loser.txt deleted file mode 100644 index 6b50944d..00000000 --- a/bda/templates/bda/mails/revente-loser.txt +++ /dev/null @@ -1,9 +0,0 @@ -Bonjour {{ acheteur.first_name }}, - -Tu t'étais inscrit-e pour la revente de la place de {{ vendeur.get_full_name }} -pour {{ spectacle.title }}. -Malheureusement, une autre personne a été tirée au sort pour racheter la place. -Tu pourras certainement retenter ta chance pour une autre revente ! - -À très bientôt, -Le Bureau des Arts diff --git a/bda/templates/bda/mails/revente-new.txt b/bda/templates/bda/mails/revente-new.txt deleted file mode 100644 index b4815e84..00000000 --- a/bda/templates/bda/mails/revente-new.txt +++ /dev/null @@ -1,13 +0,0 @@ -Bonjour {{ vendeur.first_name }}, - -Tu t’es bien inscrit-e pour la revente de {{ spectacle.title }}. - -{% with revente.date_tirage as time %} -Le tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu -le {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil }}). -Si personne ne s’est inscrit pour racheter la place, celle-ci apparaitra parmi -les « Places disponibles immédiatement à la revente » sur GestioCOF. -{% endwith %} - -Bonne revente ! -Le Bureau des Arts diff --git a/bda/templates/bda/mails/revente-seller.txt b/bda/templates/bda/mails/revente-seller.txt deleted file mode 100644 index ec99b98b..00000000 --- a/bda/templates/bda/mails/revente-seller.txt +++ /dev/null @@ -1,7 +0,0 @@ -Bonjour {{ vendeur.first_name }}, - -La personne tirée au sort pour racheter ta place pour {{ spectacle.title }} est {{ acheteur.get_full_name }}. -Tu peux le/la contacter à l'adresse {{ acheteur.email }}, ou en répondant à ce mail. - -Chaleureusement, -Le BdA diff --git a/bda/templates/bda/mails/revente-winner.txt b/bda/templates/bda/mails/revente-winner.txt deleted file mode 100644 index 01ecfb86..00000000 --- a/bda/templates/bda/mails/revente-winner.txt +++ /dev/null @@ -1,7 +0,0 @@ -Bonjour {{ acheteur.first_name }}, - -Tu as été tiré-e au sort pour racheter une place pour {{ spectacle.title }} le {{ spectacle.date }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. -Tu peux contacter le/la vendeur-se à l'adresse {{ vendeur.email }}, ou en répondant à ce mail. - -Chaleureusement, -Le BdA diff --git a/bda/templates/bda/mails/revente.txt b/bda/templates/bda/mails/revente.txt deleted file mode 100644 index 476b10da..00000000 --- a/bda/templates/bda/mails/revente.txt +++ /dev/null @@ -1,14 +0,0 @@ -Bonjour {{ user.first_name }} - -Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) -a été postée sur BdA-Revente. - -{% with revente.date_tirage as time %} -Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant -sur ce lien : http://{{ domain }}/gestion{% url "bda-revente-interested" revente.id %}. -Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à -un tirage au sort le {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil}}). -{% endwith %} - -Chaleureusement, -Le BdA diff --git a/bda/templates/bda/mails/shotgun.txt b/bda/templates/bda/mails/shotgun.txt deleted file mode 100644 index d4cd479f..00000000 --- a/bda/templates/bda/mails/shotgun.txt +++ /dev/null @@ -1,11 +0,0 @@ -Bonjour {{ user.first_name }} - -Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) -a été postée sur BdA-Revente. - -Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour -cette place : elle est disponible immédiatement à l'adresse -http://{{ domain }}/gestion{% url "bda-buy-revente" spectacle.id %}, à la disposition de tous. - -Chaleureusement, -Le BdA diff --git a/bda/templates/bda/resume-inscription-tirage.html b/bda/templates/bda/resume-inscription-tirage.html index 2e0531ca..0ad7ec0e 100644 --- a/bda/templates/bda/resume-inscription-tirage.html +++ b/bda/templates/bda/resume-inscription-tirage.html @@ -1,8 +1,6 @@ {% extends "base_title.html" %} {% block realcontent %} -

    {{ error_title }}

    -

    {{ error_description }}

    {% if choices %}

    Vos vœux:

      diff --git a/bda/templates/resume_places.html b/bda/templates/bda/resume_places.html similarity index 83% rename from bda/templates/resume_places.html rename to bda/templates/bda/resume_places.html index 1449473a..226e697a 100644 --- a/bda/templates/resume_places.html +++ b/bda/templates/bda/resume_places.html @@ -2,9 +2,6 @@ {% block realcontent %}

      Places attribuées

      - {% if warning %} -

      Attention, vous avez reçu plusieurs places pour des spectacles différents à la même date !

      - {% endif %} {% if places %} {% for place in places %} diff --git a/bda/templates/mails-rappel.html b/bda/templates/mails-rappel.html deleted file mode 100644 index 3fc15fa2..00000000 --- a/bda/templates/mails-rappel.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base_title.html" %} - -{% block realcontent %} -{% if sent %} -

      Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes

      -
        -{% for member in members %} -
      • {{ member.get_full_name }} ({{ member.email }})
      • -{% endfor %} -
      -{% else %} -

      Voulez vous envoyer les mails de rappel pour le spectacle - {{ show.title }} ?

      - {% if show.rappel_sent %} -

      Attention, les mails ont déjà été envoyés le - {{ show.rappel_sent }}

      - {% endif %} -{% endif %} - -{% if not sent %} - - {% csrf_token %} -
      - - -{% endif %} - -

      Forme des mails

      - -
      Une seule place

      -
      {{ exemple_mail_1place }}
      - -
      Deux places

      -
      {{ exemple_mail_2places }}
      -{% endblock %} diff --git a/bda/templates/spectacle_list.html b/bda/templates/spectacle_list.html index c7456f6e..d6714335 100644 --- a/bda/templates/spectacle_list.html +++ b/bda/templates/spectacle_list.html @@ -1,6 +1,10 @@ {% extends "base_title.html" %} {% load staticfiles %} +{% block extra_head %} + +{% endblock %} + {% block realcontent %}

      {{tirage_name}}

      Liste des spectacles

      @@ -17,9 +21,9 @@ {% for spectacle in object_list %} - + - +
      {{ spectacle.title }} {{ spectacle.date }}{{ spectacle.date }} {{ spectacle.location }} {{ spectacle.price |floatformat }}€ @@ -28,10 +32,9 @@ {% endfor %}
      - - + + {% block extra_head %}{% endblock %} diff --git a/cof/templates/base_title.html b/cof/templates/base_title.html index c52f29bb..935648ce 100644 --- a/cof/templates/base_title.html +++ b/cof/templates/base_title.html @@ -1,4 +1,4 @@ -{% extends "base_header.html" %} +{% extends "cof/base_header.html" %} {% block interm_content %} diff --git a/cof/templates/cof/autocomplete_user.html b/cof/templates/cof/autocomplete_user.html new file mode 100644 index 00000000..c8e0a6bc --- /dev/null +++ b/cof/templates/cof/autocomplete_user.html @@ -0,0 +1,57 @@ +{% load utils %} +
        + {% if members %} +
      • Membres du COF
      • + + {% for member in members %} + {% if forloop.counter < 5 %} +
      • + + {{ member|highlight_user:q }} + +
      • + {% elif forloop.counter == 5 %} +
      • ...
      • + {% endif %} + {% endfor %} + {% endif %} + + {% if users %} +
      • Utilisateurs de GestioCOF
      • + + {% for user in users %} + {% if forloop.counter < 5 %} +
      • + + {{ user|highlight_user:q }} + +
      • + {% elif forloop.counter == 5 %} +
      • ...
      • + {% endif %} + {% endfor %} + {% endif %} + + {% if clippers %} +
      • Utilisateurs clipper
      • + + {% for clipper in clippers %} + {% if forloop.counter < 5 %} +
      • + + {{ clipper|highlight_clipper:q }} + +
      • + {% elif forloop.counter == 5 %} +
      • ...
      • + {% endif %} + {% endfor %} + {% endif %} + + {% if not options %} +
      • Aucune correspondance trouvée
      • + {% else %} +
      • Pas dans la liste ?
      • + {% endif %} +
      • Créer un compte
      • +
      diff --git a/cof/templates/base_header.html b/cof/templates/cof/base_header.html similarity index 76% rename from cof/templates/base_header.html rename to cof/templates/cof/base_header.html index 801783e8..4713a286 100644 --- a/cof/templates/base_header.html +++ b/cof/templates/cof/base_header.html @@ -10,8 +10,10 @@ {% endblock %}

      {% if user.first_name %}{{ user.first_name }}{% else %}{{ user.username }}{% endif %}, {% if user.profile.is_cof %}au COF{% else %}non-COF{% endif %}

    diff --git a/cof/templates/cof/calendar_subscription.html b/cof/templates/cof/calendar_subscription.html index fca35ad8..92d6df2c 100644 --- a/cof/templates/cof/calendar_subscription.html +++ b/cof/templates/cof/calendar_subscription.html @@ -5,14 +5,6 @@

    Calendrier dynamique

    -{% if success %} -

    Calendrier mis à jour avec succès

    -{% endif %} - -{% if error %} -

    {{ error }}

    -{% endif %} -

    Ce formulaire vous permet de définir un calendrier dynamique compatible avec n'importe quel logiciel ou application d'agenda. Vous pouvez choisir de souscrire aux événements du COF et/ou aux spectacles BdA. diff --git a/cof/templates/details_demande_petit_cours.html b/cof/templates/cof/details_demande_petit_cours.html similarity index 100% rename from cof/templates/details_demande_petit_cours.html rename to cof/templates/cof/details_demande_petit_cours.html diff --git a/cof/templates/event.html b/cof/templates/cof/event.html similarity index 100% rename from cof/templates/event.html rename to cof/templates/cof/event.html diff --git a/cof/templates/registration_form.html b/cof/templates/cof/registration_form.html similarity index 100% rename from cof/templates/registration_form.html rename to cof/templates/cof/registration_form.html diff --git a/cof/templates/registration_post.html b/cof/templates/cof/registration_post.html similarity index 90% rename from cof/templates/registration_post.html rename to cof/templates/cof/registration_post.html index ce2f3786..0ce9d446 100644 --- a/cof/templates/registration_post.html +++ b/cof/templates/cof/registration_post.html @@ -7,6 +7,6 @@ {% if member.profile.is_cof %}Il est désormais membre du COF n°{{ member.profile.num }} !{% endif %}

    {% endif %}
    - {% include "registration_form.html" %} + {% include "cof/registration_form.html" %}
    {% endblock %} diff --git a/cof/templates/survey.html b/cof/templates/cof/survey.html similarity index 100% rename from cof/templates/survey.html rename to cof/templates/cof/survey.html diff --git a/cof/templates/traitement_demande_petit_cours.html b/cof/templates/cof/traitement_demande_petit_cours.html similarity index 84% rename from cof/templates/traitement_demande_petit_cours.html rename to cof/templates/cof/traitement_demande_petit_cours.html index d51f87b5..4be36a13 100644 --- a/cof/templates/traitement_demande_petit_cours.html +++ b/cof/templates/cof/traitement_demande_petit_cours.html @@ -30,10 +30,16 @@

    Mails pour les membres proposés :

    {% for proposeduser, mail in proposed_mails %}
    Pour {{ proposeduser }}:
    -
    {{ mail }}
    + {% with object=mail.0 content=mail.1 %} +
    {{ object }}
    +
    {{ content }}
    + {% endwith %} {% endfor %}

    Mail pour l'auteur de la demande :

    -
    {{ mainmail|safe }}
    + {% with object=mainmail.0 content=mainmail.1 %} +
    {{ object }}
    +
    {{ content|safe }}
    + {% endwith %} {% if redo %}{% endif %} diff --git a/cof/templates/traitement_demande_petit_cours_autre_niveau.html b/cof/templates/cof/traitement_demande_petit_cours_autre_niveau.html similarity index 96% rename from cof/templates/traitement_demande_petit_cours_autre_niveau.html rename to cof/templates/cof/traitement_demande_petit_cours_autre_niveau.html index f92be513..c2c7e734 100644 --- a/cof/templates/traitement_demande_petit_cours_autre_niveau.html +++ b/cof/templates/cof/traitement_demande_petit_cours_autre_niveau.html @@ -16,7 +16,6 @@ {% endif %} - {% if proposals %}
    {% csrf_token %} diff --git a/cof/templates/traitement_demande_petit_cours_success.html b/cof/templates/cof/traitement_demande_petit_cours_success.html similarity index 100% rename from cof/templates/traitement_demande_petit_cours_success.html rename to cof/templates/cof/traitement_demande_petit_cours_success.html diff --git a/cof/templates/demande-petit-cours-raw.html b/cof/templates/demande-petit-cours-raw.html index 7aab243a..000df8f3 100644 --- a/cof/templates/demande-petit-cours-raw.html +++ b/cof/templates/demande-petit-cours-raw.html @@ -1,11 +1,19 @@ +{% extends "base.html" %} + +{% load bootstrap %} + +{% block content %} +
    {% if success %}

    Votre demande a été enregistrée avec succès !

    {% else %} {% csrf_token %} - {{ form.as_table }} + {{ form | bootstrap }}
    {% endif %} +
    +{% endblock %} diff --git a/cof/templates/error.html b/cof/templates/error.html deleted file mode 100644 index 082abcf0..00000000 --- a/cof/templates/error.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "base_title.html" %} - -{% block realcontent %} - {% if error_type == "use_clipper_login" %} -

    Votre identifiant est lié à un compte clipper

    -

    Veuillez vous connecter à l'aide de votre compte clipper

    - {% elif error_type == "no_password" %} -

    Votre compte n'a pas de mot de passe associé

    -

    Veuillez nous contacter pour que nous en définissions un et que nous vous le transmettions !

    - {% else %} -

    {{ error_title }}

    -

    {{ error_description }}

    - {% endif %} -{% endblock %} diff --git a/cof/templates/home.html b/cof/templates/home.html index 0d0edf63..6291c68c 100644 --- a/cof/templates/home.html +++ b/cof/templates/home.html @@ -1,4 +1,4 @@ -{% extends "base_header.html" %} +{% extends "cof/base_header.html" %} {% block homelink %} {% endblock %} diff --git a/cof/templates/inscription-petit-cours.html b/cof/templates/inscription-petit-cours.html index 97182760..4ac0a874 100644 --- a/cof/templates/inscription-petit-cours.html +++ b/cof/templates/inscription-petit-cours.html @@ -2,11 +2,10 @@ {% load staticfiles %} {% block extra_head %} - - - - - + + + + {% endblock %} {% block realcontent %} diff --git a/cof/templates/petits-cours-mail-demandeur.txt b/cof/templates/petits-cours-mail-demandeur.txt deleted file mode 100644 index 8c20834e..00000000 --- a/cof/templates/petits-cours-mail-demandeur.txt +++ /dev/null @@ -1,17 +0,0 @@ -Bonjour, - -Je vous contacte au sujet de votre annonce passée sur le site du COF pour rentrer en contact avec un élève normalien pour des cours particuliers. Voici les coordonnées d'élèves qui sont motivés par de tels cours et correspondent aux critères que vous nous aviez transmis : - -{% for matiere, proposed in proposals %}¤ {{ matiere }} :{% for user in proposed %} - ¤ {{ user.get_full_name }}{% if user.profile.phone %}, {{ user.profile.phone }}{% endif %}{% if user.email %}, {{ user.email }}{% endif %}{% endfor %} - -{% endfor %}{% if unsatisfied %}Nous n'avons cependant pas pu trouver d'élève disponible pour des cours de {% for matiere in unsatisfied %}{% if forloop.counter0 > 0 %}, {% endif %}{{ matiere }}{% endfor %}. - -{% endif %}Si pour une raison ou une autre ces numéros ne suffisaient pas, n'hésitez pas à répondre à cet e-mail et je vous en ferai parvenir d'autres sans problème. -{% if extra|length > 0 %} -{{ extra|safe }} -{% endif %} -Cordialement, - --- -Le COF, BdE de l'ENS diff --git a/cof/templates/petits-cours-mail-eleve.txt b/cof/templates/petits-cours-mail-eleve.txt deleted file mode 100644 index f75fb33f..00000000 --- a/cof/templates/petits-cours-mail-eleve.txt +++ /dev/null @@ -1,28 +0,0 @@ -Salut, - -Le COF a reçu une demande de petit cours qui te correspond. Tu es en haut de la liste d'attente donc on a transmis tes coordonnées, ainsi que celles de 2 autres qui correspondaient aussi (c'est la vie, on donne les numéros 3 par 3 pour que ce soit plus souple). Voici quelques infos sur l'annonce en question : - -¤ Nom : {{ demande.name }} - -¤ Période : {{ demande.quand }} - -¤ Fréquence : {{ demande.freq }} - -¤ Lieu (si préféré) : {{ demande.lieu }} - -¤ Niveau : {{ demande.get_niveau_display }} - -¤ Remarques diverses (désolé pour les balises HTML) : {{ demande.remarques }} - -{% if matieres|length > 1 %}¤ Matières : -{% for matiere in matieres %} ¤ {{ matiere }} -{% endfor %}{% else %}¤ Matière : {% for matiere in matieres %}{{ matiere }} -{% endfor %}{% endif %} -Voilà, cette personne te contactera peut-être sous peu, tu pourras voir les détails directement avec elle (prix, modalités, ...). Pour indication, 30 Euro/h semble être la moyenne. - -Si tu te rends compte qu'en fait tu ne peux pas/plus donner de cours en ce moment, ça serait cool que tu décoches la case "Recevoir des propositions de petits cours" sur GestioCOF. Ensuite dès que tu voudras réapparaître tu pourras recocher la case et tu seras à nouveau sur la liste. - -À bientôt, - --- -Le COF, pour les petits cours diff --git a/cof/templates/registration.html b/cof/templates/registration.html index eb9bfd99..559226b7 100644 --- a/cof/templates/registration.html +++ b/cof/templates/registration.html @@ -4,7 +4,6 @@ {% block page_size %}col-sm-8{% endblock %} {% block extra_head %} - {% endblock %} diff --git a/cof/templatetags/utils.py b/cof/templatetags/utils.py index 16a1f4e3..90855165 100644 --- a/cof/templatetags/utils.py +++ b/cof/templatetags/utils.py @@ -43,7 +43,7 @@ def highlight_user(user, q): @register.filter def highlight_clipper(clipper, q): if clipper.fullname: - text = "%s (%s)" % (clipper.fullname, clipper.username) + text = "%s (%s)" % (clipper.fullname, clipper.clipper) else: - text = clipper.username + text = clipper.clipper return highlight_text(text, q) diff --git a/cof/tests.py b/cof/tests.py index 15106223..0f5a89e8 100644 --- a/cof/tests.py +++ b/cof/tests.py @@ -6,30 +6,20 @@ from cof.models import CofProfile from gestion.tests import create_profile + def create_cofprofile(username): p = create_profile(username) return CofProfile.objects.create(profile=p) + class TestCofProfile(TestCase): def test_str(self): - # creates a group of cof members - group = Group.objects.create(name='cof_members') - - # create a specific permission for all COF members. - ct = ContentType.objects.get(app_label='cof', model='CofProfile') - perm = Permission.objects.create(name='Cof Member', - codename='member', - content_type=ct) - - # bind the two mutherfucker. - group.permissions = [perm] - - # now test it for real cofp = create_cofprofile('foo') # XXX. should by default new CofProfiles be COF members? self.assertFalse(cofp.profile.user.has_perm('cof.member')) # adding/removing a user from the group should impact the # permission + group = Group.objects.get(name='cof_members') cofp.profile.user.groups.add(group) cofp.save() diff --git a/cof/urls.py b/cof/urls.py index 2f02354d..ca310382 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - from django.conf.urls import url -from .petits_cours_views import DemandeListView +from .petits_cours_views import DemandeListView, DemandeDetailView +from .decorators import buro_required from . import views, petits_cours_views + export_patterns = [ url(r'^members$', views.export_members), url(r'^mega/avecremarques$', views.export_mega_remarksonly), @@ -24,10 +22,11 @@ petitcours_patterns = [ name='petits-cours-demande'), url(r'^demande-raw$', petits_cours_views.demande_raw, name='petits-cours-demande-raw'), - url(r'^demandes$', DemandeListView.as_view(), + url(r'^demandes$', + buro_required(DemandeListView.as_view()), name='petits-cours-demandes-list'), - url(r'^demandes/(?P\d+)$', - petits_cours_views.details, + url(r'^demandes/(?P\d+)$', + buro_required(DemandeDetailView.as_view()), name='petits-cours-demande-details'), url(r'^demandes/(?P\d+)/traitement$', petits_cours_views.traitement, diff --git a/cof/views.py b/cof/views.py index 06ecfe11..e1c0e394 100644 --- a/cof/views.py +++ b/cof/views.py @@ -1,21 +1,18 @@ # -*- coding: utf-8 -*- -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - import unicodecsv import uuid from datetime import timedelta from icalendar import Calendar, Event as Vevent +from custommail.shortcuts import send_custom_mail from django.shortcuts import redirect, get_object_or_404, render from django.http import Http404, HttpResponse, HttpResponseForbidden from django.contrib.auth.decorators import login_required -from django.contrib.auth.views import login as django_login_view from django.contrib.auth.models import User from django.contrib.sites.models import Site from django.utils import timezone +from django.contrib import messages import django.utils.six as six from .models import Survey, SurveyAnswer, SurveyQuestion, \ @@ -24,8 +21,7 @@ from .models import Event, EventRegistration, EventOption, \ EventOptionChoice from .models import EventCommentField, EventCommentValue, \ CalendarSubscription -from .shared import send_custom_mail -from .models import CofProfile, Clipper, Club +from .models import CofProfile, Club from .decorators import buro_required, cof_required from .forms import ( EventStatusFilterForm, SurveyForm, SurveyStatusFilterForm, @@ -54,50 +50,6 @@ def home(request): return render(request, "home.html", data) -def login(request): - if request.user.is_authenticated(): - return redirect("cof.views.home") - context = {} - if request.method == "GET" and 'next' in request.GET: - context['next'] = request.GET['next'] - return render(request, "login_switch.html", context) - - -def login_ext(request): - if request.method == "POST" and "username" in request.POST: - try: - user = User.objects.get(username=request.POST["username"]) - if not user.has_usable_password() or user.password in ("", "!"): - profile, created = CofProfile.objects.get_or_create(user=user) - if profile.login_clipper: - return render(request, "error.html", - {"error_type": "use_clipper_login"}) - else: - return render(request, "error.html", - {"error_type": "no_password"}) - except User.DoesNotExist: - pass - context = {} - if request.method == "GET" and 'next' in request.GET: - context['next'] = request.GET['next'] - if request.method == "POST" and 'next' in request.POST: - context['next'] = request.POST['next'] - return django_login_view(request, template_name='login.html', - extra_context=context) - - -@login_required -def logout(request): - try: - profile = request.user.profile - except CofProfile.DoesNotExist: - profile, created = CofProfile.objects.get_or_create(user=request.user) - if profile.login_clipper: - return redirect("django_cas_ng.views.logout") - else: - return redirect("django.contrib.auth.views.logout") - - @login_required def survey(request, survey_id): survey = get_object_or_404(Survey, id=survey_id) @@ -156,10 +108,21 @@ def survey(request, survey_id): except SurveyAnswer.DoesNotExist: current_answer = None form = SurveyForm(survey=survey) - return render(request, "survey.html", {"survey": survey, "form": form, - "success": success, - "deleted": deleted, - "current_answer": current_answer}) + # Messages + if success: + if deleted: + messages.success(request, + "Votre réponse a bien été supprimée") + else: + messages.success(request, + "Votre réponse a bien été enregistrée ! Vous " + "pouvez cependant la modifier jusqu'à la fin " + "du sondage.") + return render(request, "cof/survey.html", { + "survey": survey, + "form": form, + "current_answer": current_answer + }) def get_event_form_choices(event, form): @@ -219,8 +182,13 @@ def event(request, event_id): current_choices=current_registration.options) except EventRegistration.DoesNotExist: form = EventForm(event=event) - return render(request, "event.html", - {"event": event, "form": form, "success": success}) + # Messages + if success: + messages.success(request, "Votre inscription a bien été enregistrée ! " + "Vous pouvez cependant la modifier jusqu'à " + "la fin des inscriptions.") + return render(request, "cof/event.html", + {"event": event, "form": form}) def clean_post_for_status(initial): @@ -311,11 +279,11 @@ def registration_set_ro_fields(user_form, profile_form): @buro_required -def registration_form2(request, login_clipper=None, username=None): +def registration_form2(request, login_clipper=None, username=None, + fullname=None): events = Event.objects.filter(old=False).all() member = None if login_clipper: - clipper = get_object_or_404(Clipper, username=login_clipper) try: # check if the given user is already registered member = User.objects.get(username=login_clipper) username = member.username @@ -326,8 +294,8 @@ def registration_form2(request, login_clipper=None, username=None): user_form = RegistrationUserForm(initial={ 'username': login_clipper, 'email': "%s@clipper.ens.fr" % login_clipper}) - if clipper.fullname: - bits = clipper.fullname.split(" ") + if fullname: + bits = fullname.split(" ") user_form.fields['first_name'].initial = bits[0] if len(bits) > 1: user_form.fields['last_name'].initial = " ".join(bits[1:]) @@ -370,7 +338,7 @@ def registration_form2(request, login_clipper=None, username=None): cofprofile_form = RegistrationCofProfileForm() event_formset = EventFormset(events=events, prefix='events') clubs_form = ClubsForm() - return render(request, "registration_form.html", + return render(request, "cof/registration_form.html", {"member": member, "login_clipper": login_clipper, "user_form": user_form, "profile_form": profile_form, @@ -409,12 +377,12 @@ def registration(request): try: member = User.objects.get(username=username) user_form = RegistrationUserForm(request_dict, instance=member) - except User.DoesNotExist: - try: - clipper = Clipper.objects.get(username=username) - login_clipper = clipper.username - except Clipper.DoesNotExist: + if member.profile.login_clipper: + login_clipper = member.profile.login_clipper + else: user_form.force_long_username() + except User.DoesNotExist: + user_form.force_long_username() else: user_form.force_long_username() @@ -445,10 +413,12 @@ def registration(request): )) if forms_are_valid: # Enregistrement du profil - profile_form.save() - cofprofile = cofprofile_form.save() - if cofprofile.is_cof and not was_cof: - send_custom_mail(member, "bienvenue") + profile = profile_form.save() + if profile.is_cof and not was_cof: + send_custom_mail( + "welcome", "cof@ens.fr", [member.email], + context={'member': member}, + ) # Enregistrement des inscriptions aux événements for form in event_formset: if 'status' not in form.cleaned_data: @@ -471,26 +441,37 @@ def registration(request): current_registration.paid = \ (form.cleaned_data['status'] == 'paid') current_registration.save() - if form.event.title == "Mega 15" and created_reg: - field = EventCommentField.objects.get( - event=form.event, name="Commentaires") - try: - comments = EventCommentValue.objects.get( - commentfield=field, - registration=current_registration).content - except EventCommentValue.DoesNotExist: - comments = field.default - send_custom_mail(member, "mega", - {"remarques": comments}) + # if form.event.title == "Mega 15" and created_reg: + # field = EventCommentField.objects.get( + # event=form.event, name="Commentaires") + # try: + # comments = EventCommentValue.objects.get( + # commentfield=field, + # registration=current_registration).content + # except EventCommentValue.DoesNotExist: + # comments = field.default + # FIXME : il faut faire quelque chose de propre ici, + # par exemple écrire un mail générique pour + # l'inscription aux événements et/ou donner la + # possibilité d'associer un mail aux événements + # send_custom_mail(...) # Enregistrement des inscriptions aux clubs member.clubs.clear() for club in clubs_form.cleaned_data['clubs']: club.membres.add(member) club.save() success = True - return render(request, "registration_post.html", - {"success": success, - "user_form": user_form, + # Messages + if success: + msg = ("L'inscription de {:s} ({:s}) a été " + "enregistrée avec succès" + .format(member.get_full_name(), member.email)) + if member.profile.is_cof: + msg += "Il est désormais membre du COF n°{:d} !".format( + member.profile.num) + messages.success(request, msg, extra_tags='safe') + return render(request, "cof/registration_post.html", + {"user_form": user_form, "profile_form": profile_form, "cofprofile_form": cofprofile_form, "member": member, @@ -551,7 +532,7 @@ def export_members(request): response['Content-Disposition'] = 'attachment; filename=membres_cof.csv' writer = unicodecsv.writer(response) - for profile in CofProfile.objects.filter(is_cof=True).all(): + for profile in CofProfile.objects.filter(profile__user__groups__name='cof_members').all(): user = profile.user bits = [profile.num, user.username, user.first_name, user.last_name, user.email, profile.phone, profile.occupation, @@ -660,7 +641,7 @@ def utile_bda(request): @buro_required def liste_bdadiff(request): titre = "BdA diffusion" - personnes = CofProfile.objects.filter(mailing_bda=True, is_cof=True).all() + personnes = CofProfile.objects.filter(mailing_bda=True, profile__user__groups__name='cof_members').all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @@ -669,7 +650,7 @@ def liste_bdadiff(request): def liste_bdarevente(request): titre = "BdA revente" personnes = CofProfile.objects.filter(mailing_bda_revente=True, - is_cof=True).all() + profile__user__groups__name='cof_members').all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @@ -677,7 +658,7 @@ def liste_bdarevente(request): @buro_required def liste_diffcof(request): titre = "Diffusion COF" - personnes = CofProfile.objects.filter(mailing_cof=True, is_cof=True).all() + personnes = CofProfile.objects.filter(mailing_cof=True, user__groups__name='cof_members').all() return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) @@ -697,13 +678,15 @@ def calendar(request): subscription.token = uuid.uuid4() subscription.save() form.save_m2m() + messages.success(request, + "Calendrier mis à jour avec succès.") return render(request, "cof/calendar_subscription.html", {'form': form, - 'success': True, 'token': str(subscription.token)}) else: + messages.error(request, "Formulaire incorrect.") return render(request, "cof/calendar_subscription.html", - {'form': form, 'error': "Formulaire incorrect"}) + {'form': form}) else: return render(request, "cof/calendar_subscription.html", {'form': CalendarForm(instance=instance), diff --git a/gestioCOF/settings_dev.py b/gestioCOF/settings_dev.py index 9c1f6347..253f924f 100644 --- a/gestioCOF/settings_dev.py +++ b/gestioCOF/settings_dev.py @@ -9,10 +9,6 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.8/ref/settings/ """ -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os @@ -37,7 +33,6 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', - 'grappelli', 'django.contrib.admin', 'django.contrib.admindocs', 'autocomplete_light', @@ -52,6 +47,7 @@ INSTALLED_APPS = ( 'cof', 'gestion', 'kfet', + 'custommail', ) MIDDLEWARE_CLASSES = ( @@ -83,7 +79,7 @@ TEMPLATES = [ 'django.core.context_processors.i18n', 'django.core.context_processors.media', 'django.core.context_processors.static', - 'cof.shared.context_processor', + 'gestion.context_processors.context_processor', 'kfet.context_processors.auth', ], }, @@ -133,9 +129,6 @@ MEDIA_URL = '/media/' # Various additional settings SITE_ID = 1 -GRAPPELLI_ADMIN_HEADLINE = "GestioCOF" -GRAPPELLI_ADMIN_TITLE = "GestioCOF" - MAIL_DATA = { 'petits_cours': { 'FROM': "Le COF ", @@ -149,7 +142,7 @@ MAIL_DATA = { 'REPLYTO': 'BdA-Revente '}, } -LOGIN_URL = "cof-login" +LOGIN_URL = "gestion:login" LOGIN_REDIRECT_URL = "home" CAS_SERVER_URL = 'https://cas.eleves.ens.fr/' @@ -158,10 +151,12 @@ CAS_REDIRECT_URL = '/' CAS_EMAIL_FORMAT = "%s@clipper.ens.fr" AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', - 'cof.shared.COFCASBackend', + 'gestion.backends.COFCASBackend', 'kfet.backends.GenericTeamBackend', ) +# LDAP_SERVER_URL = 'ldaps://ldap.spi.ens.fr:636' + # EMAIL_HOST="nef.ens.fr" RECAPTCHA_PUBLIC_KEY = "DUMMY" diff --git a/gestioCOF/urls.py b/gestioCOF/urls.py index d4a01618..ec531778 100644 --- a/gestioCOF/urls.py +++ b/gestioCOF/urls.py @@ -4,26 +4,22 @@ Fichier principal de configuration des urls du projet GestioCOF """ -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - import autocomplete_light from django.conf import settings from django.conf.urls import include, url from django.conf.urls.static import static from django.contrib import admin -from django.views.generic.base import TemplateView from django.contrib.auth import views as django_views -from django_cas_ng import views as django_cas_views -from cof import views as cof_views, csv_views +from cof import views as cof_views from cof.urls import export_patterns, petitcours_patterns, \ surveys_patterns, events_patterns, calendar_patterns, \ clubs_patterns from cof.autocomplete import autocomplete +from gestion import views as gestion_views + autocomplete_light.autodiscover() admin.autodiscover() @@ -32,6 +28,10 @@ urlpatterns = [ url(r'^$', cof_views.home, name='home'), # The common views url(r"^", include("gestion.urls", namespace='gestion')), + # Admin urls + url(r'^admin/logout/', gestion_views.logout), + url(r'^admin/doc/', include('django.contrib.admindocs.urls')), + url(r'^admin/', include(admin.site.urls)), # Le BdA url(r'^bda/', include('bda.urls')), # Les exports @@ -46,15 +46,6 @@ urlpatterns = [ url(r'^calendar/', include(calendar_patterns)), # Clubs url(r'^clubs/', include(clubs_patterns)), - # Authentification - url(r'^cof/denied$', TemplateView.as_view(template_name='cof-denied.html'), - name="cof-denied"), - url(r'^cas/login$', django_cas_views.login, name="cas_login_view"), - url(r'^cas/logout$', django_cas_views.logout), - url(r'^outsider/login$', cof_views.login_ext), - url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}), - url(r'^login$', cof_views.login, name="cof-login"), - url(r'^logout$', cof_views.logout), # Infos persos url(r'^outsider/password-change$', django_views.password_change), url(r'^outsider/password-change-done$', @@ -71,14 +62,6 @@ urlpatterns = [ # Autocompletion url(r'^autocomplete/registration$', autocomplete), url(r'^autocomplete/', include('autocomplete_light.urls')), - # Interface admin - url(r'^admin/logout/', cof_views.logout), - url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - url(r'^admin/(?P[\d\w]+)/(?P[\d\w]+)/csv/', - csv_views.admin_list_export, - {'fields': ['username', ]}), - url(r'^admin/', include(admin.site.urls)), - url(r'^grappelli/', include('grappelli.urls')), # Liens utiles du COF et du BdA url(r'^utile_cof$', cof_views.utile_cof), url(r'^utile_bda$', cof_views.utile_bda), diff --git a/gestion/admin.py b/gestion/admin.py index 8c38f3f3..52e3cb55 100644 --- a/gestion/admin.py +++ b/gestion/admin.py @@ -1,3 +1,20 @@ from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User -# Register your models here. +from .models import Profile + + +class ProfileInline(admin.StackedInline): + model = Profile + inline_classes = ["collapse open"] + + +class UserProfileAdmin(UserAdmin): + inlines = [ + ProfileInline, + ] + + +admin.site.unregister(User) +admin.site.register(User, UserProfileAdmin) diff --git a/gestion/backends.py b/gestion/backends.py new file mode 100644 index 00000000..9cc87abe --- /dev/null +++ b/gestion/backends.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +from django.conf import settings +from django_cas_ng.backends import CASBackend +from django_cas_ng.utils import get_cas_client +from django.contrib.auth import get_user_model + +from gestion.models import Profile + +User = get_user_model() + + +class COFCASBackend(CASBackend): + def authenticate_cas(self, ticket, service, request): + """Verifies CAS ticket and gets or creates User object""" + + client = get_cas_client(service_url=service) + username, attributes, _ = client.verify_ticket(ticket) + if attributes: + request.session['attributes'] = attributes + if not username: + return None + + # Le CAS de l'ENS accepte les logins avec des espaces au début + # et à la fin, ainsi qu’avec une casse variable. On normalise pour + # éviter les doublons. + username = username.strip().lower() + + profiles = Profile.objects.filter(login_clipper=username) + if len(profiles) > 0: + # XXX. We have to deal with multiple profiles, this should not + # happen + # profile = profiles.order_by('-is_cof')[0] + profile = profiles.first() + user = profile.user + return user + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + # user will have an "unusable" password + user = User.objects.create_user(username, '') + user.save() + return user + + def authenticate(self, ticket, service, request): + """Authenticates CAS ticket and retrieves user data""" + user = self.authenticate_cas(ticket, service, request) + if user is None: + return user + profile = user.profile + if not profile.login_clipper: + profile.login_clipper = user.username + profile.save() + if not user.email: + user.email = settings.CAS_EMAIL_FORMAT % profile.login_clipper + user.save() + return user diff --git a/gestion/context_processors.py b/gestion/context_processors.py new file mode 100644 index 00000000..d909f6c2 --- /dev/null +++ b/gestion/context_processors.py @@ -0,0 +1,10 @@ +from django.contrib.sites.models import Site + + +def context_processor(request): + '''Append extra data to the context of the given request''' + data = { + "user": request.user, + "site": Site.objects.get_current(), + } + return data diff --git a/gestion/management/commands/syncmails.py b/gestion/management/commands/syncmails.py new file mode 100644 index 00000000..c69633d2 --- /dev/null +++ b/gestion/management/commands/syncmails.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +""" +Import des mails de GestioCOF dans la base de donnée +""" + +import json +import os +from custommail.models import Type, CustomMail, Variable + +from django.core.management.base import BaseCommand +from django.contrib.contenttypes.models import ContentType + + +class Command(BaseCommand): + help = ("Va chercher les données mails de GestioCOF stocké au format json " + "dans /gestion/management/data/custommails.json. Le format des " + "données est celui donné par la commande :" + " `python manage.py dumpdata custommail --natural-foreign` " + "La bonne façon de mettre à jour ce fichier est donc de le " + "charger à l'aide de syncmails, le faire les modifications à " + "l'aide de l'interface administration et/ou du shell puis de le " + "remplacer par le nouveau résultat de la commande précédente.") + + def handle(self, *args, **options): + path = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + 'data', 'custommail.json') + with open(path, 'r') as jsonfile: + mail_data = json.load(jsonfile) + + # On se souvient à quel objet correspond quel pk du json + assoc = {'types': {}, 'mails': {}} + status = {'synced': 0, 'unchanged': 0} + + for obj in mail_data: + fields = obj['fields'] + + # Pour les trois types d'objets : + # - On récupère les objets référencés par les clefs étrangères + # - On crée l'objet si nécessaire + # - On le stocke éventuellement dans les deux dictionnaires définis + # plus haut + + # Variable types + if obj['model'] == 'custommail.variabletype': + fields['inner1'] = assoc['types'].get(fields['inner1']) + fields['inner2'] = assoc['types'].get(fields['inner2']) + if fields['kind'] == 'model': + fields['content_type'] = ( + ContentType.objects + .get_by_natural_key(*fields['content_type']) + ) + var_type, _ = Type.objects.get_or_create(**fields) + assoc['types'][obj['pk']] = var_type + + # Custom mails + if obj['model'] == 'custommail.custommail': + mail = None + try: + mail = CustomMail.objects.get( + shortname=fields['shortname']) + status['unchanged'] += 1 + except CustomMail.DoesNotExist: + mail = CustomMail.objects.create(**fields) + status['synced'] += 1 + self.stdout.write( + 'SYNCED {:s}'.format(fields['shortname'])) + assoc['mails'][obj['pk']] = mail + + # Variables + if obj['model'] == 'custommail.custommailvariable': + fields['custommail'] = assoc['mails'].get(fields['custommail']) + fields['type'] = assoc['types'].get(fields['type']) + try: + Variable.objects.get( + custommail=fields['custommail'], + name=fields['name'] + ) + except Variable.DoesNotExist: + Variable.objects.create(**fields) + + # C'est agréable d'avoir le résultat affiché + self.stdout.write( + '{synced:d} mails synchronized {unchanged:d} unchanged' + .format(**status) + ) diff --git a/gestion/management/data/custommail.json b/gestion/management/data/custommail.json new file mode 100644 index 00000000..1fb9d289 --- /dev/null +++ b/gestion/management/data/custommail.json @@ -0,0 +1,587 @@ +[ +{ + "model": "custommail.variabletype", + "pk": 1, + "fields": { + "content_type": [ + "auth", + "user" + ], + "inner1": null, + "kind": "model", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 2, + "fields": { + "content_type": null, + "inner1": null, + "kind": "int", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 3, + "fields": { + "content_type": [ + "bda", + "spectacle" + ], + "inner1": null, + "kind": "model", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 4, + "fields": { + "content_type": [ + "bda", + "spectaclerevente" + ], + "inner1": null, + "kind": "model", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 5, + "fields": { + "content_type": [ + "sites", + "site" + ], + "inner1": null, + "kind": "model", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 6, + "fields": { + "content_type": [ + "cof", + "petitcoursdemande" + ], + "inner1": null, + "kind": "model", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 7, + "fields": { + "content_type": null, + "inner1": null, + "kind": "list", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 8, + "fields": { + "content_type": null, + "inner1": 1, + "kind": "list", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 9, + "fields": { + "content_type": null, + "inner1": null, + "kind": "pair", + "inner2": 8 + } +}, +{ + "model": "custommail.variabletype", + "pk": 10, + "fields": { + "content_type": null, + "inner1": 9, + "kind": "list", + "inner2": null + } +}, +{ + "model": "custommail.variabletype", + "pk": 11, + "fields": { + "content_type": null, + "inner1": 3, + "kind": "list", + "inner2": null + } +}, +{ + "model": "custommail.custommail", + "pk": 1, + "fields": { + "shortname": "welcome", + "subject": "Bienvenue au COF", + "description": "Mail de bienvenue au COF envoy\u00e9 automatiquement \u00e0 l'inscription d'un nouveau membre", + "body": "Bonjour {{ member.first_name }} et bienvenue au COF !\r\n\r\nTu trouveras plein de trucs cool sur le site du COF : https://www.cof.ens.fr/ et notre page Facebook : https://www.facebook.com/cof.ulm\r\nEt n'oublie pas d'aller d\u00e9couvrir GestioCOF, la plateforme de gestion du COF !\r\nSi tu as des questions, tu peux nous envoyer un mail \u00e0 cof@ens.fr (on aime le spam), ou passer nous voir au Bur\u00f4 pr\u00e8s de la Cour\u00f4 du lundi au vendredi de 12h \u00e0 14h et de 18h \u00e0 20h.\r\n\r\nRetrouvez les \u00e9v\u00e8nements de rentr\u00e9e pour les conscrit.e.s et les vieux/vieilles organis\u00e9s par le COF et ses clubs ici : http://www.cof.ens.fr/depot/Rentree.pdf \r\n\r\nAmicalement,\r\n\r\nTon COF qui t'aime." + } +}, +{ + "model": "custommail.custommail", + "pk": 2, + "fields": { + "shortname": "bda-rappel", + "subject": "{{ show }}", + "description": "Mail de rappel pour les spectacles BdA", + "body": "Bonjour {{ member.first_name }},\r\n\r\nNous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:\"une place,deux places\" }}\r\npour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre !\r\n{% if nb_attr == 2 %}\r\nTu as obtenu deux places pour ce spectacle. Nous te rappelons que\r\nces places sont strictement r\u00e9serv\u00e9es aux personnes de moins de 28 ans.\r\n{% endif %}\r\n{% if show.listing %}Pour ce spectacle, tu as re\u00e7u des places sur\r\nlisting. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la repr\u00e9sentation\r\npour retirer {{ nb_attr|pluralize:\"ta place,tes places\" }}.\r\n{% else %}Pour assister \u00e0 ce spectacle, tu dois pr\u00e9senter les billets qui ont\r\n\u00e9t\u00e9 distribu\u00e9s au bur\u00f4.\r\n{% endif %}\r\n\r\nSi tu ne peux plus assister \u00e0 cette repr\u00e9sentation, tu peux\r\nrevendre ta place via BdA-revente, accessible directement sur\r\nGestioCOF (lien \"revendre une place du premier tirage\" sur la page\r\nd'accueil https://www.cof.ens.fr/gestion/).\r\n\r\nEn te souhaitant un excellent spectacle,\r\n\r\nLe Bureau des Arts" + } +}, +{ + "model": "custommail.custommail", + "pk": 3, + "fields": { + "shortname": "bda-revente", + "subject": "{{ show }}", + "description": "Notification envoy\u00e9e \u00e0 toutes les personnes int\u00e9ress\u00e9es par un spectacle pour le signaler qu'une place vient d'\u00eatre mise en vente.", + "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nSi ce spectacle t'int\u00e9resse toujours, merci de nous le signaler en cliquant\r\nsur ce lien : http://{{ site }}{% url \"bda-revente-interested\" revente.id %}.\r\nDans le cas o\u00f9 plusieurs personnes seraient int\u00e9ress\u00e9es, nous proc\u00e8derons \u00e0\r\nun tirage au sort le {{ revente.date_tirage|date:\"DATE_FORMAT\" }}.\r\n\r\nChaleureusement,\r\nLe BdA" + } +}, +{ + "model": "custommail.custommail", + "pk": 4, + "fields": { + "shortname": "bda-shotgun", + "subject": "{{ show }}", + "description": "Notification signalant qu'une place est au shotgun aux personnes int\u00e9ress\u00e9es.", + "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nPuisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour\r\ncette place : elle est disponible imm\u00e9diatement \u00e0 l'adresse\r\nhttp://{{ site }}{% url \"bda-buy-revente\" show.id %}, \u00e0 la disposition de tous.\r\n\r\nChaleureusement,\r\nLe BdA" + } +}, +{ + "model": "custommail.custommail", + "pk": 5, + "fields": { + "shortname": "bda-revente-winner", + "subject": "BdA-Revente : {{ show.title }}", + "description": "Mail envoy\u00e9 au gagnant d'un tirage BdA-Revente", + "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu as \u00e9t\u00e9 tir\u00e9-e au sort pour racheter une place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nTu peux contacter le/la vendeur-se \u00e0 l'adresse {{ vendeur.email }}.\r\n\r\nChaleureusement,\r\nLe BdA" + } +}, +{ + "model": "custommail.custommail", + "pk": 6, + "fields": { + "shortname": "bda-revente-loser", + "subject": "BdA-Revente : {{ show.title }}", + "description": "Notification envoy\u00e9e aux perdants d'un tirage de revente.", + "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu t'\u00e9tais inscrit-e pour la revente de la place de {{ vendeur.get_full_name }}\r\npour {{ show.title }}.\r\nMalheureusement, une autre personne a \u00e9t\u00e9 tir\u00e9e au sort pour racheter la place.\r\nTu pourras certainement retenter ta chance pour une autre revente !\r\n\r\n\u00c0 tr\u00e8s bient\u00f4t,\r\nLe Bureau des Arts" + } +}, +{ + "model": "custommail.custommail", + "pk": 7, + "fields": { + "shortname": "bda-revente-seller", + "subject": "BdA-Revente : {{ show.title }}", + "description": "Notification envoy\u00e9e au vendeur d'une place pour lui indiquer qu'elle vient d'\u00eatre attribu\u00e9e", + "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nLa personne tir\u00e9e au sort pour racheter ta place pour {{ show.title }} est {{ acheteur.get_full_name }}.\r\nTu peux le/la contacter \u00e0 l'adresse {{ acheteur.email }}, ou en r\u00e9pondant \u00e0 ce mail.\r\n\r\nChaleureusement,\r\nLe BdA" + } +}, +{ + "model": "custommail.custommail", + "pk": 8, + "fields": { + "shortname": "bda-revente-new", + "subject": "BdA-Revente : {{ show.title }}", + "description": "Notification signalant au vendeur d'une place que sa mise en vente a bien eu lieu et lui donnant quelques informations compl\u00e9mentaires.", + "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nTu t\u2019es bien inscrit-e pour la revente de {{ show.title }}.\r\n\r\n{% with revente.date_tirage as time %}\r\nLe tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu\r\nle {{ time|date:\"DATE_FORMAT\" }} \u00e0 {{ time|time:\"TIME_FORMAT\" }} (dans {{time|timeuntil }}).\r\nSi personne ne s\u2019est inscrit pour racheter la place, celle-ci apparaitra parmi\r\nles \u00ab Places disponibles imm\u00e9diatement \u00e0 la revente \u00bb sur GestioCOF.\r\n{% endwith %}\r\n\r\nBonne revente !\r\nLe Bureau des Arts" + } +}, +{ + "model": "custommail.custommail", + "pk": 9, + "fields": { + "shortname": "bda-buy-shotgun", + "subject": "BdA-Revente : {{ show.title }}", + "description": "Mail envoy\u00e9 au revendeur lors d'un achat au shotgun.", + "body": "Bonjour {{ vendeur.first_name }} !\r\n\r\nJe souhaiterais racheter ta place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nContacte-moi si tu es toujours int\u00e9ress\u00e9\u00b7e !\r\n\r\n{{ acheteur.get_full_name }} ({{ acheteur.email }})" + } +}, +{ + "model": "custommail.custommail", + "pk": 10, + "fields": { + "shortname": "petit-cours-mail-eleve", + "subject": "Petits cours ENS par le COF", + "description": "Mail envoy\u00e9 aux personnes dont ont a donn\u00e9 les contacts \u00e0 des demandeurs de petits cours", + "body": "Salut,\r\n\r\nLe COF a re\u00e7u une demande de petit cours qui te correspond. Tu es en haut de la liste d'attente donc on a transmis tes coordonn\u00e9es, ainsi que celles de 2 autres qui correspondaient aussi (c'est la vie, on donne les num\u00e9ros 3 par 3 pour que ce soit plus souple). Voici quelques infos sur l'annonce en question :\r\n\r\n\u00a4 Nom : {{ demande.name }}\r\n\r\n\u00a4 P\u00e9riode : {{ demande.quand }}\r\n\r\n\u00a4 Fr\u00e9quence : {{ demande.freq }}\r\n\r\n\u00a4 Lieu (si pr\u00e9f\u00e9r\u00e9) : {{ demande.lieu }}\r\n\r\n\u00a4 Niveau : {{ demande.get_niveau_display }}\r\n\r\n\u00a4 Remarques diverses (d\u00e9sol\u00e9 pour les balises HTML) : {{ demande.remarques }}\r\n\r\n{% if matieres|length > 1 %}\u00a4 Mati\u00e8res :\r\n{% for matiere in matieres %} \u00a4 {{ matiere }}\r\n{% endfor %}{% else %}\u00a4 Mati\u00e8re : {% for matiere in matieres %}{{ matiere }}\r\n{% endfor %}{% endif %}\r\nVoil\u00e0, cette personne te contactera peut-\u00eatre sous peu, tu pourras voir les d\u00e9tails directement avec elle (prix, modalit\u00e9s, ...). Pour indication, 30 Euro/h semble \u00eatre la moyenne.\r\n\r\nSi tu te rends compte qu'en fait tu ne peux pas/plus donner de cours en ce moment, \u00e7a serait cool que tu d\u00e9coches la case \"Recevoir des propositions de petits cours\" sur GestioCOF. Ensuite d\u00e8s que tu voudras r\u00e9appara\u00eetre tu pourras recocher la case et tu seras \u00e0 nouveau sur la liste.\r\n\r\n\u00c0 bient\u00f4t,\r\n\r\n--\r\nLe COF, pour les petits cours" + } +}, +{ + "model": "custommail.custommail", + "pk": 11, + "fields": { + "shortname": "petits-cours-mail-demandeur", + "subject": "Cours particuliers ENS", + "description": "Mail envoy\u00e9 aux personnent qui demandent des petits cours lorsque leur demande est trait\u00e9e.\r\n\r\n(Ne pas toucher \u00e0 {{ extra|safe }})", + "body": "Bonjour,\r\n\r\nJe vous contacte au sujet de votre annonce pass\u00e9e sur le site du COF pour rentrer en contact avec un \u00e9l\u00e8ve normalien pour des cours particuliers. Voici les coordonn\u00e9es d'\u00e9l\u00e8ves qui sont motiv\u00e9s par de tels cours et correspondent aux crit\u00e8res que vous nous aviez transmis :\r\n\r\n{% for matiere, proposed in proposals %}\u00a4 {{ matiere }} :{% for user in proposed %}\r\n \u00a4 {{ user.get_full_name }}{% if user.profile.phone %}, {{ user.profile.phone }}{% endif %}{% if user.email %}, {{ user.email }}{% endif %}{% endfor %}\r\n\r\n{% endfor %}{% if unsatisfied %}Nous n'avons cependant pas pu trouver d'\u00e9l\u00e8ve disponible pour des cours de {% for matiere in unsatisfied %}{% if forloop.counter0 > 0 %}, {% endif %}{{ matiere }}{% endfor %}.\r\n\r\n{% endif %}Si pour une raison ou une autre ces num\u00e9ros ne suffisaient pas, n'h\u00e9sitez pas \u00e0 r\u00e9pondre \u00e0 cet e-mail et je vous en ferai parvenir d'autres sans probl\u00e8me.\r\n{% if extra|length > 0 %}\r\n{{ extra|safe }}\r\n{% endif %}\r\nCordialement,\r\n\r\n--\r\nLe COF, BdE de l'ENS" + } +}, +{ + "model": "custommail.custommail", + "pk": 12, + "fields": { + "shortname": "bda-attributions", + "subject": "R\u00e9sultats du tirage au sort", + "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux gagnants d'une ou plusieurs places", + "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Tu as \u00e9t\u00e9 s\u00e9lectionn\u00e9-e\r\npour les spectacles suivants :\r\n{% for place in places %}\r\n- 1 place pour {{ place }}{% endfor %}\r\n\r\n*Paiement*\r\nL'int\u00e9gralit\u00e9 de ces places de spectacles est \u00e0 r\u00e9gler d\u00e8s maintenant et AVANT\r\nvendredi prochain, au bureau du COF pendant les heures de permanences (du lundi au vendredi\r\nentre 12h et 14h, et entre 18h et 20h). Des facilit\u00e9s de paiement sont bien\r\n\u00e9videmment possibles : nous pouvons ne pas encaisser le ch\u00e8que imm\u00e9diatement,\r\nou bien d\u00e9couper votre paiement en deux fois. Pour ceux qui ne pourraient pas\r\nvenir payer au bureau, merci de nous contacter par mail.\r\n\r\n*Mode de retrait des places*\r\nAu moment du paiement, certaines places vous seront remises directement,\r\nd'autres seront \u00e0 r\u00e9cup\u00e9rer au cours de l'ann\u00e9e, d'autres encore seront\r\nnominatives et \u00e0 retirer le soir m\u00eame dans les the\u00e2tres correspondants.\r\nPour chaque spectacle, vous recevrez un mail quelques jours avant la\r\nrepr\u00e9sentation vous indiquant le mode de retrait.\r\n\r\nNous vous rappelons que l'obtention de places du BdA vous engage \u00e0\r\nrespecter les r\u00e8gles de fonctionnement :\r\nhttp://www.cof.ens.fr/bda/?page_id=1370\r\nUn syst\u00e8me de revente des places via les mails BdA-revente disponible\r\ndirectement sur votre compte GestioCOF.\r\n\r\nEn vous souhaitant de tr\u00e8s beaux spectacles tout au long de l'ann\u00e9e,\r\n--\r\nLe Bureau des Arts" + } +}, +{ + "model": "custommail.custommail", + "pk": 13, + "fields": { + "shortname": "bda-attributions-decus", + "subject": "R\u00e9sultats du tirage au sort", + "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux personnes n'ayant pas obtenu de place", + "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as\r\nobtenu aucune place.\r\n\r\nNous proposons cependant de nombreuses offres hors-tirage tout au long de\r\nl'ann\u00e9e, et nous t'invitons \u00e0 nous contacter si l'une d'entre elles\r\nt'int\u00e9resse !\r\n--\r\nLe Bureau des Arts" + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 1, + "fields": { + "name": "member", + "description": "Utilisateur de GestioCOF", + "custommail": 1, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 2, + "fields": { + "name": "member", + "description": "Utilisateur ayant eu une place pour ce spectacle", + "custommail": 2, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 3, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 2, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 4, + "fields": { + "name": "nb_attr", + "description": "Nombre de places obtenues", + "custommail": 2, + "type": 2 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 5, + "fields": { + "name": "revente", + "description": "Revente mentionn\u00e9e dans le mail", + "custommail": 3, + "type": 4 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 6, + "fields": { + "name": "member", + "description": "Personne int\u00e9ress\u00e9e par la place", + "custommail": 3, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 7, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 3, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 8, + "fields": { + "name": "site", + "description": "Site web (gestioCOF)", + "custommail": 3, + "type": 5 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 9, + "fields": { + "name": "site", + "description": "Site web (gestioCOF)", + "custommail": 4, + "type": 5 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 10, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 4, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 11, + "fields": { + "name": "member", + "description": "Personne int\u00e9ress\u00e9e par la place", + "custommail": 4, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 12, + "fields": { + "name": "acheteur", + "description": "Gagnant-e du tirage", + "custommail": 5, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 13, + "fields": { + "name": "vendeur", + "description": "Personne qui vend une place", + "custommail": 5, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 14, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 5, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 15, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 6, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 16, + "fields": { + "name": "vendeur", + "description": "Personne qui vend une place", + "custommail": 6, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 17, + "fields": { + "name": "acheteur", + "description": "Personne inscrite au tirage qui n'a pas eu la place", + "custommail": 6, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 18, + "fields": { + "name": "acheteur", + "description": "Gagnant-e du tirage", + "custommail": 7, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 19, + "fields": { + "name": "vendeur", + "description": "Personne qui vend une place", + "custommail": 7, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 20, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 7, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 21, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 8, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 22, + "fields": { + "name": "vendeur", + "description": "Personne qui vend la place", + "custommail": 8, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 23, + "fields": { + "name": "revente", + "description": "Revente mentionn\u00e9e dans le mail", + "custommail": 8, + "type": 4 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 24, + "fields": { + "name": "vendeur", + "description": "Personne qui vend la place", + "custommail": 9, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 25, + "fields": { + "name": "show", + "description": "Spectacle", + "custommail": 9, + "type": 3 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 26, + "fields": { + "name": "acheteur", + "description": "Personne qui prend la place au shotgun", + "custommail": 9, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 27, + "fields": { + "name": "demande", + "description": "Demande de petit cours", + "custommail": 10, + "type": 6 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 28, + "fields": { + "name": "matieres", + "description": "Liste des mati\u00e8res concern\u00e9es par la demande", + "custommail": 10, + "type": 7 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 29, + "fields": { + "name": "proposals", + "description": "Liste associant une liste d'enseignants \u00e0 chaque mati\u00e8re", + "custommail": 11, + "type": 10 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 30, + "fields": { + "name": "unsatisfied", + "description": "Liste des mati\u00e8res pour lesquelles on n'a pas d'enseigant \u00e0 proposer", + "custommail": 11, + "type": 7 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 31, + "fields": { + "name": "places", + "description": "Places de spectacle du participant", + "custommail": 12, + "type": 11 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 32, + "fields": { + "name": "member", + "description": "Participant du tirage au sort", + "custommail": 12, + "type": 1 + } +}, +{ + "model": "custommail.custommailvariable", + "pk": 33, + "fields": { + "name": "member", + "description": "Participant du tirage au sort", + "custommail": 13, + "type": 1 + } +} +] diff --git a/gestion/shared.py b/gestion/shared.py new file mode 100644 index 00000000..39bc5da7 --- /dev/null +++ b/gestion/shared.py @@ -0,0 +1,27 @@ +""" +Locking/unlocking tools to prevent tables to be corrupted +""" + +from django.db import connection + + +def lock_table(*models): + query = "LOCK TABLES " + for i, model in enumerate(models): + table = model._meta.db_table + if i > 0: + query += ", " + query += "%s WRITE" % table + cursor = connection.cursor() + cursor.execute(query) + row = cursor.fetchone() + return row + + +def unlock_tables(*models): + cursor = connection.cursor() + cursor.execute("UNLOCK TABLES") + row = cursor.fetchone() + return row + +unlock_table = unlock_tables diff --git a/gestion/templates/gestion/error.html b/gestion/templates/gestion/error.html new file mode 100644 index 00000000..a35d2872 --- /dev/null +++ b/gestion/templates/gestion/error.html @@ -0,0 +1,20 @@ +{% extends "base_title.html" %} + +{% block realcontent %} + {% if error_type == "use_clipper_login" %} +

    Votre identifiant est lié à un compte clipper

    +

    + Veuillez vous connecter à l'aide de votre + compte clipper +

    + {% elif error_type == "no_password" %} +

    Votre compte n'a pas de mot de passe associé

    +

    + Veuillez nous contacter pour que + nous en définissions un et que nous vous le transmettions ! +

    + {% else %} +

    {{ error_title }}

    +

    {{ error_description }}

    + {% endif %} +{% endblock %} diff --git a/cof/templates/login.html b/gestion/templates/gestion/login.html similarity index 93% rename from cof/templates/login.html rename to gestion/templates/gestion/login.html index 67b2134d..65329371 100644 --- a/cof/templates/login.html +++ b/gestion/templates/gestion/login.html @@ -15,7 +15,7 @@

    Identifiants incorrects.

    {% endif %}
    + action="{% url 'gestion:login_ext' %}?next={{ next|urlencode }}"> {% csrf_token %}
    diff --git a/cof/templates/login_switch.html b/gestion/templates/gestion/login_switch.html similarity index 70% rename from cof/templates/login_switch.html rename to gestion/templates/gestion/login_switch.html index 7945973e..f5901ea6 100644 --- a/cof/templates/login_switch.html +++ b/gestion/templates/gestion/login_switch.html @@ -12,13 +12,13 @@
    -
    - Compte clipper -
    + href="{% url 'gestion:cas_login' %}?next={{ next|urlencode }}"> +
    + Compte clipper +
    + href="{% url 'gestion:login_ext' %}?next={{ next|urlencode }}">
    Extérieur
    diff --git a/gestion/tests.py b/gestion/tests.py index 2e244271..21e532ed 100644 --- a/gestion/tests.py +++ b/gestion/tests.py @@ -18,9 +18,9 @@ def create_profile(username): In order to create a profile, I need to create a User first. This is annoying in most situations, as I just want a profile. """ - u = User.objects.create(username=username, - first_name=username.title(), - last_name=username.title()) + User.objects.create(username=username, + first_name=username.title(), + last_name=username.title()) p, = Profile.objects.filter(user__username=username) return p @@ -55,9 +55,9 @@ class SimpleTest(TestCase): # each profile is linked to at most one account of the same type. p1 = create_profile('bar') p2 = create_profile('baz') - pkfet1 = Account.objects.create(profile=p1, trigramme='BAR') - pcof2 = CofProfile.objects.create(profile=p2) - pkfet2 = Account.objects.create(profile=p2, trigramme='BAZ') + Account.objects.create(profile=p1, trigramme='BAR') + CofProfile.objects.create(profile=p2) + Account.objects.create(profile=p2, trigramme='BAZ') self.assertRaises(IntegrityError, CofProfile.objects.create, profile=p2) @@ -65,8 +65,58 @@ class SimpleTest(TestCase): class TestProfile(TestCase): @patch('kfet.signals.messages') def test_profile(self, mock_messages): - root = User.objects.create_superuser('root', 'foo@bar.com', 'root') + # Test that the root user can log in + User.objects.create_superuser('root', 'foo@bar.com', 'root') c = Client() c.login(username='root', password='root') response = c.get('/') self.assertEqual(response.status_code, 200) + + # Test the profile edition + post_data = { + "first_name": "foo", + "last_name": "bar", + "phone": "0123456789", + "departement": "baz" + } + c.post("/profile", post_data) + user = User.objects.get(username="root") + self.assertEqual(user.first_name, post_data['first_name']) + self.assertEqual(user.last_name, post_data["last_name"]) + self.assertEqual(user.profile.phone, post_data["phone"]) + self.assertEqual(user.profile.departement, post_data["departement"]) + + +class AuthTest(TestCase): + def test_login(self): + client = Client() + # Setup a regular Django user + user = User.objects.create(username="foo") + user.set_password("bar") + user.save() + # Test the django auth + resp = client.post( + "/outsider/login", + {"username": "foo", "password": "bar"}, + follow=True + ) + self.assertEqual(resp.status_code, 200) + resp = client.get("/logout") + self.assertEqual(resp.status_code, 200) + # Give the user a clipper login + user.profile.login_clipper = "foo" + user.profile.save() + # Assert that it cannot use the regular auth + resp = client.post( + "/outsider/login", + {"username": "foo", "password": "bar"} + ) + self.assertIn("error_type", resp.context) + self.assertEqual(resp.context["error_type"], "use_clipper_login") + # Test the CAS redirect + resp = client.get("/cas/login") + self.assertEqual(resp.status_code, 302) + self.assertEqual( + resp.url.split('?')[0], + "https://cas.eleves.ens.fr/login" + ) diff --git a/gestion/urls.py b/gestion/urls.py index 037101dc..55e5658a 100644 --- a/gestion/urls.py +++ b/gestion/urls.py @@ -1,8 +1,24 @@ -from django.conf.urls import url +from django.conf.urls import url, include +from django.views.generic.base import TemplateView +from django.contrib.auth import views as django_views +from django.contrib import admin +from django_cas_ng import views as django_cas_views from . import views urlpatterns = [ + # Profile edition url(r"^profile/?$", views.profile, name="profile"), + + # Authentication + url(r'^cof/denied$', + TemplateView.as_view(template_name='cof-denied.html'), + name="denied"), + url(r'^cas/login$', django_cas_views.login, name="cas_login"), + url(r'^cas/logout$', django_cas_views.logout, name="cas_logout"), + url(r'^outsider/login$', views.login_ext, name="login_ext"), + url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}), + url(r'^login$', views.login, name="login"), + url(r'^logout$', views.logout, name="logout"), ] diff --git a/gestion/views.py b/gestion/views.py index a4e1d71c..7b3a4997 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -1,9 +1,59 @@ -from django.shortcuts import render +""" +The common views of the different organisations. +- Authentication +- Profile edition +""" + +from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.contrib.auth.views import ( + login as django_login, logout as django_logout +) from .forms import ProfileForm, UserForm +def login(request): + if request.user.is_authenticated(): + return redirect("cof.views.home") + context = {} + # Fetch the next page from the request data + if request.method == "GET" and 'next' in request.GET: + context['next'] = request.GET['next'] + return render(request, "gestion/login_switch.html", context) + + +def login_ext(request): + if request.method == "POST" and "username" in request.POST: + try: + user = User.objects.get(username=request.POST["username"]) + if user.profile.login_clipper: + return render(request, "gestion/error.html", + {"error_type": "use_clipper_login"}) + if not user.has_usable_password() or user.password in ("", "!"): + return render(request, "gestion/error.html", + {"error_type": "no_password"}) + except User.DoesNotExist: + pass + context = {} + # Fetch the next page from the request data + if request.method == "GET" and 'next' in request.GET: + context['next'] = request.GET['next'] + if request.method == "POST" and 'next' in request.POST: + context['next'] = request.POST['next'] + return django_login(request, template_name='gestion/login.html', + extra_context=context) + + +@login_required +def logout(request): + if request.user.profile.login_clipper: + return redirect("gestion:cas_logout") + else: + return django_logout(request) + + @login_required def profile(request): success = False @@ -11,7 +61,7 @@ def profile(request): if request.method == "POST": user_form = UserForm(request.POST, instance=user) profile_form = ProfileForm(request.POST, instance=user.profile) - if all((user_form.is_valid(), profile_form.is_valid())): + if (user_form.is_valid() and profile_form.is_valid()): user_form.save() profile_form.save() success = True diff --git a/kfet/autocomplete.py b/kfet/autocomplete.py index ec8edd5f..dd406fde 100644 --- a/kfet/autocomplete.py +++ b/kfet/autocomplete.py @@ -1,21 +1,29 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * +from ldap3 import Connection from django.shortcuts import render from django.http import Http404 from django.db.models import Q -from cof.models import User, Clipper +from django.conf import settings +from django.contrib.auth.models import User, Group + from kfet.decorators import teamkfet_required from kfet.models import Account + +class Clipper(object): + def __init__(self, clipper, fullname): + self.clipper = clipper + self.fullname = fullname + + @teamkfet_required def account_create(request): if "q" not in request.GET: raise Http404 q = request.GET.get("q") + cof_members = Group.objects.get(name="cof_members") if (len(q) == 0): return render(request, "kfet/account_create_autocomplete.html") @@ -25,58 +33,73 @@ def account_create(request): queries = {} search_words = q.split() - queries['kfet'] = Account.objects - queries['users_cof'] = User.objects.filter(Q(profile__cof__is_cof = True)) - queries['users_notcof'] = User.objects.filter(Q(profile__cof__is_cof = False)) - queries['clippers'] = Clipper.objects + # Fetching data from User and Account tables + queries['kfet'] = Account.objects + queries['users_cof'] = User.objects.filter(groups=cof_members) + queries['users_notcof'] = User.objects.exclude(groups=cof_members) for word in search_words: queries['kfet'] = queries['kfet'].filter( - Q(profile__user__username__icontains = word) - | Q(profile__user__first_name__icontains = word) - | Q(profile__user__last_name__icontains = word) - ) + Q(profile__user__username__icontains=word) + | Q(profile__user__first_name__icontains=word) + | Q(profile__user__last_name__icontains=word) + ) queries['users_cof'] = queries['users_cof'].filter( - Q(username__icontains = word) - | Q(first_name__icontains = word) - | Q(last_name__icontains = word) - ) + Q(username__icontains=word) + | Q(first_name__icontains=word) + | Q(last_name__icontains=word) + ) queries['users_notcof'] = queries['users_notcof'].filter( - Q(username__icontains = word) - | Q(first_name__icontains = word) - | Q(last_name__icontains = word) - ) - queries['clippers'] = queries['clippers'].filter( - Q(username__icontains = word) - | Q(fullname__icontains = word) - ) + Q(username__icontains=word) + | Q(first_name__icontains=word) + | Q(last_name__icontains=word) + ) + # Clearing redundancies queries['kfet'] = queries['kfet'].distinct() + usernames = set( + queries['kfet'].values_list('profile__user__username', flat=True) + ) + queries['kfet'] = [ + (account, account.profile.user) + for account in queries['kfet'] + ] - usernames = list( \ - queries['kfet'].values_list('profile__user__username', flat=True)) - - queries['kfet'] = [ (account, account.profile.user) \ - for account in queries['kfet'] ] - - queries['users_cof'] = \ + queries['users_cof'] = ( queries['users_cof'].exclude(username__in=usernames).distinct() - queries['users_notcof'] = \ + ) + queries['users_notcof'] = ( queries['users_notcof'].exclude(username__in=usernames).distinct() + ) + usernames |= set( + queries['users_cof'].values_list('username', flat=True) + ) + usernames |= set( + queries['users_notcof'].values_list('username', flat=True) + ) - usernames += list( \ - queries['users_cof'].values_list('username', flat=True)) - usernames += list( \ - queries['users_notcof'].values_list('username', flat=True)) - - queries['clippers'] = \ - queries['clippers'].exclude(username__in=usernames).distinct() + # Fetching data from the SPI + if hasattr(settings, 'LDAP_SERVER_URL'): + # Fetching + ldap_query = '(|{:s})'.format(''.join( + ['(cn=*{bit:s}*)(uid=*{bit:s}*)'.format(bit=bit) + for bit in search_words] + )) + with Connection(settings.LDAP_SERVER_URL) as conn: + conn.search( + 'dc=spi,dc=ens,dc=fr', ldap_query, + attributes=['uid', 'cn'] + ) + queries['clippers'] = conn.entries + # Clearing redundancies + queries['clippers'] = [ + Clipper(clipper.uid, clipper.cn) + for clipper in queries['clippers'] + if str(clipper.uid) not in usernames + ] + # Resulting data data.update(queries) - - options = 0 - for query in queries.values(): - options += len(query) - data['options'] = options + data['options'] = any(queries.values()) return render(request, "kfet/account_create_autocomplete.html", data) diff --git a/kfet/fixtures/accounts.json b/kfet/fixtures/accounts.json deleted file mode 100644 index c532abcf..00000000 --- a/kfet/fixtures/accounts.json +++ /dev/null @@ -1,1178 +0,0 @@ -[ -{ - "pk": 1, - "fields": { - "nickname": "", - "password": null, - "profile": 1, - "created_at": "2017-01-02T23:13:49.236Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "000" - }, - "model": "kfet.account" -}, -{ - "pk": 2, - "fields": { - "nickname": "", - "password": null, - "profile": 2, - "created_at": "2017-01-02T23:13:49.242Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "001" - }, - "model": "kfet.account" -}, -{ - "pk": 3, - "fields": { - "nickname": "", - "password": null, - "profile": 3, - "created_at": "2017-01-02T23:13:49.245Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "002" - }, - "model": "kfet.account" -}, -{ - "pk": 4, - "fields": { - "nickname": "", - "password": null, - "profile": 4, - "created_at": "2017-01-02T23:13:49.250Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "003" - }, - "model": "kfet.account" -}, -{ - "pk": 5, - "fields": { - "nickname": "", - "password": null, - "profile": 5, - "created_at": "2017-01-02T23:13:49.253Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "004" - }, - "model": "kfet.account" -}, -{ - "pk": 6, - "fields": { - "nickname": "", - "password": null, - "profile": 6, - "created_at": "2017-01-02T23:13:49.256Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "005" - }, - "model": "kfet.account" -}, -{ - "pk": 7, - "fields": { - "nickname": "", - "password": null, - "profile": 7, - "created_at": "2017-01-02T23:13:49.258Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "006" - }, - "model": "kfet.account" -}, -{ - "pk": 8, - "fields": { - "nickname": "", - "password": null, - "profile": 8, - "created_at": "2017-01-02T23:13:49.259Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "007" - }, - "model": "kfet.account" -}, -{ - "pk": 9, - "fields": { - "nickname": "", - "password": null, - "profile": 9, - "created_at": "2017-01-02T23:13:49.261Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "008" - }, - "model": "kfet.account" -}, -{ - "pk": 10, - "fields": { - "nickname": "", - "password": null, - "profile": 10, - "created_at": "2017-01-02T23:13:49.262Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "009" - }, - "model": "kfet.account" -}, -{ - "pk": 11, - "fields": { - "nickname": "", - "password": null, - "profile": 11, - "created_at": "2017-01-02T23:13:49.264Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "010" - }, - "model": "kfet.account" -}, -{ - "pk": 12, - "fields": { - "nickname": "", - "password": null, - "profile": 12, - "created_at": "2017-01-02T23:13:49.265Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "011" - }, - "model": "kfet.account" -}, -{ - "pk": 13, - "fields": { - "nickname": "", - "password": null, - "profile": 13, - "created_at": "2017-01-02T23:13:49.266Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "012" - }, - "model": "kfet.account" -}, -{ - "pk": 14, - "fields": { - "nickname": "", - "password": null, - "profile": 14, - "created_at": "2017-01-02T23:13:49.267Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "013" - }, - "model": "kfet.account" -}, -{ - "pk": 15, - "fields": { - "nickname": "", - "password": null, - "profile": 15, - "created_at": "2017-01-02T23:13:49.268Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "014" - }, - "model": "kfet.account" -}, -{ - "pk": 16, - "fields": { - "nickname": "", - "password": null, - "profile": 16, - "created_at": "2017-01-02T23:13:49.269Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "015" - }, - "model": "kfet.account" -}, -{ - "pk": 17, - "fields": { - "nickname": "", - "password": null, - "profile": 17, - "created_at": "2017-01-02T23:13:49.270Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "016" - }, - "model": "kfet.account" -}, -{ - "pk": 18, - "fields": { - "nickname": "", - "password": null, - "profile": 18, - "created_at": "2017-01-02T23:13:49.271Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "017" - }, - "model": "kfet.account" -}, -{ - "pk": 19, - "fields": { - "nickname": "", - "password": null, - "profile": 19, - "created_at": "2017-01-02T23:13:49.272Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "018" - }, - "model": "kfet.account" -}, -{ - "pk": 20, - "fields": { - "nickname": "", - "password": null, - "profile": 20, - "created_at": "2017-01-02T23:13:49.273Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "019" - }, - "model": "kfet.account" -}, -{ - "pk": 21, - "fields": { - "nickname": "", - "password": null, - "profile": 21, - "created_at": "2017-01-02T23:13:49.274Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "020" - }, - "model": "kfet.account" -}, -{ - "pk": 22, - "fields": { - "nickname": "", - "password": null, - "profile": 22, - "created_at": "2017-01-02T23:13:49.274Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "021" - }, - "model": "kfet.account" -}, -{ - "pk": 23, - "fields": { - "nickname": "", - "password": null, - "profile": 23, - "created_at": "2017-01-02T23:13:49.275Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "022" - }, - "model": "kfet.account" -}, -{ - "pk": 24, - "fields": { - "nickname": "", - "password": null, - "profile": 24, - "created_at": "2017-01-02T23:13:49.276Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "023" - }, - "model": "kfet.account" -}, -{ - "pk": 25, - "fields": { - "nickname": "", - "password": null, - "profile": 25, - "created_at": "2017-01-02T23:13:49.277Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "024" - }, - "model": "kfet.account" -}, -{ - "pk": 26, - "fields": { - "nickname": "", - "password": null, - "profile": 26, - "created_at": "2017-01-02T23:13:49.296Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "025" - }, - "model": "kfet.account" -}, -{ - "pk": 27, - "fields": { - "nickname": "", - "password": null, - "profile": 27, - "created_at": "2017-01-02T23:13:49.297Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "026" - }, - "model": "kfet.account" -}, -{ - "pk": 28, - "fields": { - "nickname": "", - "password": null, - "profile": 28, - "created_at": "2017-01-02T23:13:49.298Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "027" - }, - "model": "kfet.account" -}, -{ - "pk": 29, - "fields": { - "nickname": "", - "password": null, - "profile": 29, - "created_at": "2017-01-02T23:13:49.299Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "028" - }, - "model": "kfet.account" -}, -{ - "pk": 30, - "fields": { - "nickname": "", - "password": null, - "profile": 30, - "created_at": "2017-01-02T23:13:49.300Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "029" - }, - "model": "kfet.account" -}, -{ - "pk": 31, - "fields": { - "nickname": "", - "password": null, - "profile": 31, - "created_at": "2017-01-02T23:13:49.301Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "030" - }, - "model": "kfet.account" -}, -{ - "pk": 32, - "fields": { - "nickname": "", - "password": null, - "profile": 32, - "created_at": "2017-01-02T23:13:49.302Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "031" - }, - "model": "kfet.account" -}, -{ - "pk": 33, - "fields": { - "nickname": "", - "password": null, - "profile": 33, - "created_at": "2017-01-02T23:13:49.302Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "032" - }, - "model": "kfet.account" -}, -{ - "pk": 34, - "fields": { - "nickname": "", - "password": null, - "profile": 34, - "created_at": "2017-01-02T23:13:49.303Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "033" - }, - "model": "kfet.account" -}, -{ - "pk": 35, - "fields": { - "nickname": "", - "password": null, - "profile": 35, - "created_at": "2017-01-02T23:13:49.304Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "034" - }, - "model": "kfet.account" -}, -{ - "pk": 36, - "fields": { - "nickname": "", - "password": null, - "profile": 36, - "created_at": "2017-01-02T23:13:49.305Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "035" - }, - "model": "kfet.account" -}, -{ - "pk": 37, - "fields": { - "nickname": "", - "password": null, - "profile": 37, - "created_at": "2017-01-02T23:13:49.306Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "036" - }, - "model": "kfet.account" -}, -{ - "pk": 38, - "fields": { - "nickname": "", - "password": null, - "profile": 38, - "created_at": "2017-01-02T23:13:49.307Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "037" - }, - "model": "kfet.account" -}, -{ - "pk": 39, - "fields": { - "nickname": "", - "password": null, - "profile": 39, - "created_at": "2017-01-02T23:13:49.307Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "038" - }, - "model": "kfet.account" -}, -{ - "pk": 40, - "fields": { - "nickname": "", - "password": null, - "profile": 40, - "created_at": "2017-01-02T23:13:49.308Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "039" - }, - "model": "kfet.account" -}, -{ - "pk": 41, - "fields": { - "nickname": "", - "password": null, - "profile": 64, - "created_at": "2017-01-02T23:21:11.760Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "100" - }, - "model": "kfet.account" -}, -{ - "pk": 42, - "fields": { - "nickname": "", - "password": null, - "profile": 65, - "created_at": "2017-01-02T23:21:11.766Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "101" - }, - "model": "kfet.account" -}, -{ - "pk": 43, - "fields": { - "nickname": "", - "password": null, - "profile": 66, - "created_at": "2017-01-02T23:21:11.768Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "102" - }, - "model": "kfet.account" -}, -{ - "pk": 44, - "fields": { - "nickname": "", - "password": null, - "profile": 67, - "created_at": "2017-01-02T23:21:11.769Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "103" - }, - "model": "kfet.account" -}, -{ - "pk": 45, - "fields": { - "nickname": "", - "password": null, - "profile": 68, - "created_at": "2017-01-02T23:21:11.770Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "104" - }, - "model": "kfet.account" -}, -{ - "pk": 46, - "fields": { - "nickname": "", - "password": null, - "profile": 69, - "created_at": "2017-01-02T23:21:11.771Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "105" - }, - "model": "kfet.account" -}, -{ - "pk": 47, - "fields": { - "nickname": "", - "password": null, - "profile": 70, - "created_at": "2017-01-02T23:21:11.773Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "106" - }, - "model": "kfet.account" -}, -{ - "pk": 48, - "fields": { - "nickname": "", - "password": null, - "profile": 71, - "created_at": "2017-01-02T23:21:11.775Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "107" - }, - "model": "kfet.account" -}, -{ - "pk": 49, - "fields": { - "nickname": "", - "password": null, - "profile": 72, - "created_at": "2017-01-02T23:21:11.776Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "108" - }, - "model": "kfet.account" -}, -{ - "pk": 50, - "fields": { - "nickname": "", - "password": null, - "profile": 73, - "created_at": "2017-01-02T23:21:11.777Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "109" - }, - "model": "kfet.account" -}, -{ - "pk": 51, - "fields": { - "nickname": "", - "password": null, - "profile": 74, - "created_at": "2017-01-02T23:21:11.778Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "110" - }, - "model": "kfet.account" -}, -{ - "pk": 52, - "fields": { - "nickname": "", - "password": null, - "profile": 75, - "created_at": "2017-01-02T23:21:11.779Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "111" - }, - "model": "kfet.account" -}, -{ - "pk": 53, - "fields": { - "nickname": "", - "password": null, - "profile": 76, - "created_at": "2017-01-02T23:21:11.780Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "112" - }, - "model": "kfet.account" -}, -{ - "pk": 54, - "fields": { - "nickname": "", - "password": null, - "profile": 77, - "created_at": "2017-01-02T23:21:11.781Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "113" - }, - "model": "kfet.account" -}, -{ - "pk": 55, - "fields": { - "nickname": "", - "password": null, - "profile": 78, - "created_at": "2017-01-02T23:21:11.783Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "114" - }, - "model": "kfet.account" -}, -{ - "pk": 56, - "fields": { - "nickname": "", - "password": null, - "profile": 79, - "created_at": "2017-01-02T23:21:11.784Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "115" - }, - "model": "kfet.account" -}, -{ - "pk": 57, - "fields": { - "nickname": "", - "password": null, - "profile": 80, - "created_at": "2017-01-02T23:21:11.785Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "116" - }, - "model": "kfet.account" -}, -{ - "pk": 58, - "fields": { - "nickname": "", - "password": null, - "profile": 81, - "created_at": "2017-01-02T23:21:11.786Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "117" - }, - "model": "kfet.account" -}, -{ - "pk": 59, - "fields": { - "nickname": "", - "password": null, - "profile": 82, - "created_at": "2017-01-02T23:21:11.787Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "118" - }, - "model": "kfet.account" -}, -{ - "pk": 60, - "fields": { - "nickname": "", - "password": null, - "profile": 83, - "created_at": "2017-01-02T23:21:11.788Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "119" - }, - "model": "kfet.account" -}, -{ - "pk": 61, - "fields": { - "nickname": "", - "password": null, - "profile": 84, - "created_at": "2017-01-02T23:21:11.789Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "120" - }, - "model": "kfet.account" -}, -{ - "pk": 62, - "fields": { - "nickname": "", - "password": null, - "profile": 85, - "created_at": "2017-01-02T23:21:11.790Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "121" - }, - "model": "kfet.account" -}, -{ - "pk": 63, - "fields": { - "nickname": "", - "password": null, - "profile": 86, - "created_at": "2017-01-02T23:21:11.791Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "122" - }, - "model": "kfet.account" -}, -{ - "pk": 64, - "fields": { - "nickname": "", - "password": null, - "profile": 87, - "created_at": "2017-01-02T23:21:11.792Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "123" - }, - "model": "kfet.account" -}, -{ - "pk": 65, - "fields": { - "nickname": "", - "password": null, - "profile": 88, - "created_at": "2017-01-02T23:21:11.793Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "124" - }, - "model": "kfet.account" -}, -{ - "pk": 66, - "fields": { - "nickname": "", - "password": null, - "profile": 89, - "created_at": "2017-01-02T23:21:11.794Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "125" - }, - "model": "kfet.account" -}, -{ - "pk": 67, - "fields": { - "nickname": "", - "password": null, - "profile": 90, - "created_at": "2017-01-02T23:21:11.795Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "126" - }, - "model": "kfet.account" -}, -{ - "pk": 68, - "fields": { - "nickname": "", - "password": null, - "profile": 91, - "created_at": "2017-01-02T23:21:11.796Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "127" - }, - "model": "kfet.account" -}, -{ - "pk": 69, - "fields": { - "nickname": "", - "password": null, - "profile": 92, - "created_at": "2017-01-02T23:21:11.797Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "128" - }, - "model": "kfet.account" -}, -{ - "pk": 70, - "fields": { - "nickname": "", - "password": null, - "profile": 93, - "created_at": "2017-01-02T23:21:11.798Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "129" - }, - "model": "kfet.account" -}, -{ - "pk": 71, - "fields": { - "nickname": "", - "password": null, - "profile": 94, - "created_at": "2017-01-02T23:21:11.799Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "130" - }, - "model": "kfet.account" -}, -{ - "pk": 72, - "fields": { - "nickname": "", - "password": null, - "profile": 95, - "created_at": "2017-01-02T23:21:11.800Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "131" - }, - "model": "kfet.account" -}, -{ - "pk": 73, - "fields": { - "nickname": "", - "password": null, - "profile": 96, - "created_at": "2017-01-02T23:21:11.801Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "132" - }, - "model": "kfet.account" -}, -{ - "pk": 74, - "fields": { - "nickname": "", - "password": null, - "profile": 97, - "created_at": "2017-01-02T23:21:11.802Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "133" - }, - "model": "kfet.account" -}, -{ - "pk": 75, - "fields": { - "nickname": "", - "password": null, - "profile": 98, - "created_at": "2017-01-02T23:21:11.803Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "134" - }, - "model": "kfet.account" -}, -{ - "pk": 76, - "fields": { - "nickname": "", - "password": null, - "profile": 99, - "created_at": "2017-01-02T23:21:11.804Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "135" - }, - "model": "kfet.account" -}, -{ - "pk": 77, - "fields": { - "nickname": "", - "password": null, - "profile": 100, - "created_at": "2017-01-02T23:21:11.805Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "136" - }, - "model": "kfet.account" -}, -{ - "pk": 78, - "fields": { - "nickname": "", - "password": null, - "profile": 101, - "created_at": "2017-01-02T23:21:11.806Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "137" - }, - "model": "kfet.account" -}, -{ - "pk": 79, - "fields": { - "nickname": "", - "password": null, - "profile": 102, - "created_at": "2017-01-02T23:21:11.807Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "138" - }, - "model": "kfet.account" -}, -{ - "pk": 80, - "fields": { - "nickname": "", - "password": null, - "profile": 103, - "created_at": "2017-01-02T23:21:11.807Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "139" - }, - "model": "kfet.account" -}, -{ - "pk": 81, - "fields": { - "nickname": "", - "password": null, - "profile": 63, - "created_at": "2017-01-03T00:26:41.482Z", - "is_frozen": false, - "balance": "0.00", - "promo": 2016, - "trigramme": "LIQ" - }, - "model": "kfet.account" -}, -{ - "pk": 1, - "fields": { - "valid_to": "2999-12-31T23:00:00Z", - "name": "standard", - "balance": "0.00", - "is_protected": false, - "valid_from": "1921-01-03T00:00:00Z", - "created_by": 1 - }, - "model": "kfet.checkout" -}, -{ - "pk": 1, - "fields": { - "balance_new": "0.00", - "taken_200": 0, - "taken_005": 0, - "taken_500": 0, - "taken_2": 0, - "balance_old": "0.00", - "taken_20": 0, - "taken_5": 0, - "taken_02": 0, - "taken_10": 0, - "checkout": 1, - "taken_1": 0, - "not_count": false, - "taken_01": 0, - "by": 1, - "amount_error": "0.00", - "taken_05": 0, - "taken_cheque": "0.00", - "at": "2017-01-02T23:37:18.838Z", - "amount_taken": "0.00", - "taken_50": 0, - "taken_001": 0, - "taken_100": 0, - "taken_002": 0 - }, - "model": "kfet.checkoutstatement" -} -] diff --git a/kfet/fixtures/groups.json b/kfet/fixtures/groups.json deleted file mode 100644 index ddafcbd8..00000000 --- a/kfet/fixtures/groups.json +++ /dev/null @@ -1,98 +0,0 @@ -[ -{ - "model": "auth.group", - "pk": 1, - "fields": { - "name": "K-F\u00eat chef", - "permissions": [ - 115, - 116, - 117, - 118, - 119, - 120, - 133, - 134, - 135, - 130, - 131, - 132, - 136, - 137, - 138, - 121, - 122, - 123, - 127, - 128, - 129, - 124, - 125, - 126, - 188, - 189, - 190, - 169, - 176, - 183, - 170, - 171, - 182, - 172, - 178, - 177, - 181, - 175, - 179, - 173, - 174, - 184, - 180, - 139, - 140, - 141, - 142, - 143, - 144, - 166, - 167, - 168, - 163, - 164, - 165, - 151, - 152, - 153, - 154, - 155, - 156, - 185, - 186, - 187, - 145, - 146, - 147, - 148, - 149, - 150, - 160, - 161, - 162, - 157, - 158, - 159 - ] - } -}, -{ - "model": "auth.group", - "pk": 2, - "fields": { - "name": "K-F\u00eat girl", - "permissions": [ - 172, - 173 - ] - } -} -] diff --git a/kfet/management/commands/loadkfetdevdata.py b/kfet/management/commands/loadkfetdevdata.py new file mode 100644 index 00000000..8c2ce815 --- /dev/null +++ b/kfet/management/commands/loadkfetdevdata.py @@ -0,0 +1,170 @@ +""" +Crée des utilisateurs, des articles et des opérations aléatoires +""" + +import os +import random +from datetime import timedelta +from decimal import Decimal + +from django.utils import timezone +from django.contrib.auth.models import User, Group, Permission, ContentType + +from cof.management.base import MyBaseCommand +from gestion.models import Profile +from kfet.models import Account, Article, OperationGroup, Operation, Checkout + +# Où sont stockés les fichiers json +DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), + 'data') + + +class Command(MyBaseCommand): + help = "Crée des utilisateurs, des articles et des opérations aléatoires" + + def handle(self, *args, **options): + # --- + # Groupes + # --- + + Group.objects.filter(name__icontains='K-Fêt').delete() + + group_chef = Group(name="K-Fêt César") + group_boy = Group(name="K-Fêt Légionnaire") + + group_chef.save() + group_boy.save() + + permissions_chef = Permission.objects.filter( + content_type__in=ContentType.objects.filter( + app_label='kfet')) + permissions_boy = Permission.objects.filter( + codename__in=['is_team', 'perform_deposit']) + + group_chef.permissions.add(*permissions_chef) + group_boy.permissions.add(*permissions_boy) + + # --- + # Comptes + # --- + + self.stdout.write("Création des comptes K-Fêt") + + gaulois = Profile.objects.filter(user__last_name='Gaulois') + gaulois_trigramme = map('{:03d}'.format, range(50)) + + romains = Profile.objects.filter(user__last_name='Romain') + romains_trigramme = map(lambda x: str(100+x), range(99)) + + created_accounts = 0 + team_accounts = 0 + + for (profile, trigramme) in zip(gaulois, gaulois_trigramme): + account, created = Account.objects.get_or_create( + trigramme=trigramme, + profile=profile, + defaults={'balance': random.randint(1, 999)/10} + ) + created_accounts += int(created) + + if profile.user.first_name == 'Abraracourcix': + profile.user.groups.add(group_chef) + + for (profile, trigramme) in zip(romains, romains_trigramme): + account, created = Account.objects.get_or_create( + trigramme=trigramme, + profile=profile, + defaults={'balance': random.randint(1, 999)/10} + ) + created_accounts += int(created) + + if random.random() > 0.75 and created: + profile.user.groups.add(group_boy) + team_accounts += 1 + + self.stdout.write("- {:d} comptes créés, {:d} dans l'équipe K-Fêt" + .format(created_accounts, team_accounts)) + + # Compte liquide + + liq_user, _ = User.objects.get_or_create(username='liquide') + liq_profile, _ = Profile.objects.get_or_create(user=liq_user) + liq_account, _ = Account.objects.get_or_create(profile=liq_profile, + trigramme='LIQ') + + # --- + # Caisse + # --- + + checkout, _ = Checkout.objects.get_or_create( + created_by=Account.objects.get(trigramme='000'), + name='Chaudron', + valid_from=timezone.now(), + valid_to=timezone.now() + timedelta(days=365) + ) + + # --- + # Opérations + # --- + + self.stdout.write("Génération d'opérations") + + articles = Article.objects.all() + accounts = Account.objects.exclude(trigramme='LIQ') + + num_op = 100 + # Operations are put uniformly over the span of a week + past_date = 3600*24*7 + + for i in range(num_op): + if random.random() > 0.25: + account = random.choice(accounts) + else: + account = liq_account + + amount = Decimal('0') + at = timezone.now() - timedelta( + seconds=random.randint(0, past_date)) + + opegroup = OperationGroup( + on_acc=account, + checkout=checkout, + at=at, + is_cof=False + ) + if hasattr(account.profile, "cof"): + opegroup.is_cof = account.profile.cof.is_cof + opegroup.save() + opegroup.save() + + for j in range(random.randint(1, 4)): + typevar = random.random() + if typevar > 0.9 and account != liq_account: + ope = Operation( + group=opegroup, + type=Operation.DEPOSIT, + amount=Decimal(random.randint(1, 99)/10,) + ) + elif typevar > 0.8 and account != liq_account: + ope = Operation( + group=opegroup, + type=Operation.WITHDRAW, + amount=-Decimal(random.randint(1, 99)/10,) + ) + else: + article = random.choice(articles) + nb = random.randint(1, 5) + + ope = Operation( + group=opegroup, + type=Operation.PURCHASE, + amount=-article.price*nb, + article=article, + article_nb=nb + ) + + ope.save() + amount += ope.amount + + opegroup.amount = amount + opegroup.save() diff --git a/kfet/templates/kfet/account_create_autocomplete.html b/kfet/templates/kfet/account_create_autocomplete.html index 1185c3a8..2f326801 100644 --- a/kfet/templates/kfet/account_create_autocomplete.html +++ b/kfet/templates/kfet/account_create_autocomplete.html @@ -36,7 +36,7 @@
  • Utilisateurs clipper
  • {% for clipper in clippers %}
  • - + {{ clipper|highlight_clipper:q }}
  • diff --git a/kfet/templates/kfet/base_nav.html b/kfet/templates/kfet/base_nav.html index 79a7bd96..7fcd3e40 100644 --- a/kfet/templates/kfet/base_nav.html +++ b/kfet/templates/kfet/base_nav.html @@ -51,7 +51,7 @@ {% endif %} {% if user.is_authenticated %} -
  • +
  • {% endif %}
    diff --git a/kfet/urls.py b/kfet/urls.py index 9b9ebf21..d54349d4 100644 --- a/kfet/urls.py +++ b/kfet/urls.py @@ -35,7 +35,8 @@ urlpatterns = [ name = 'kfet.account.create_special'), url(r'^accounts/new/user/(?P.+)$', views.account_create_ajax, name = 'kfet.account.create.fromuser'), - url(r'^accounts/new/clipper/(?P.+)$', views.account_create_ajax, + url(r'^accounts/new/clipper/(?P[\w-]+)/(?P.*)$', + views.account_create_ajax, name = 'kfet.account.create.fromclipper'), url(r'^accounts/new/empty$', views.account_create_ajax, name = 'kfet.account.create.empty'), diff --git a/kfet/views.py b/kfet/views.py index f45ab124..6febbda6 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * from collections import defaultdict from datetime import timedelta import hashlib @@ -10,29 +7,30 @@ import heapq import statistics from django.shortcuts import render, get_object_or_404, redirect -from django.core.exceptions import PermissionDenied, ValidationError +from django.core.exceptions import PermissionDenied from django.core.cache import cache from django.views.generic import ListView, DetailView -from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView +from django.views.generic.edit import CreateView, UpdateView from django.core.urlresolvers import reverse_lazy from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.contrib.auth import authenticate, login from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.models import User, Permission, Group -from django.http import HttpResponse, JsonResponse, Http404 -from django.forms import modelformset_factory, formset_factory -from django.db import IntegrityError, transaction -from django.db.models import F, Sum, Prefetch, Count, Func +from django.http import JsonResponse, Http404 +from django.forms import formset_factory +from django.db import transaction +from django.db.models import F, Sum, Prefetch, Count from django.db.models.functions import Coalesce from django.utils import timezone from django.utils.crypto import get_random_string from gestion.models import Profile -from cof.models import Clipper from kfet.decorators import teamkfet_required -from kfet.models import (Account, Checkout, Article, Settings, AccountNegative, - CheckoutStatement, GenericTeamToken, Supplier, SupplierArticle, Inventory, - InventoryArticle, Order, OrderArticle) +from kfet.models import ( + Account, Checkout, Article, Settings, AccountNegative, CheckoutStatement, + GenericTeamToken, Supplier, SupplierArticle, Inventory, InventoryArticle, + Order, OrderArticle +) from kfet.forms import * from kfet import consumers import django_cas_ng @@ -223,19 +221,20 @@ def account_form_set_readonly_fields(user_form, cof_form): cof_form.fields['login_clipper'].widget.attrs['readonly'] = True cof_form.fields['is_cof'].widget.attrs['disabled'] = True -def get_account_create_forms(request=None, username=None, login_clipper=None): +def get_account_create_forms(request=None, username=None, login_clipper=None, + fullname=None): user = None - clipper = None + clipper = False if login_clipper and (login_clipper == username or not username): # à partir d'un clipper # le user associé à ce clipper ne devrait pas encore exister - clipper = get_object_or_404(Clipper, username = login_clipper) + clipper = True try: # Vérification que clipper ne soit pas déjà dans User user = User.objects.get(username=login_clipper) # Ici, on nous a menti, le user existe déjà username = user.username - clipper = None + clipper = False except User.DoesNotExist: # Clipper (sans user déjà existant) @@ -243,9 +242,9 @@ def get_account_create_forms(request=None, username=None, login_clipper=None): user_initial = { 'username' : login_clipper, 'email' : "%s@clipper.ens.fr" % login_clipper} - if clipper.fullname: + if fullname: # Prefill du nom et prénom - names = clipper.fullname.split() + names = fullname.split() # Le premier, c'est le prénom user_initial['first_name'] = names[0] if len(names) > 1: @@ -309,8 +308,11 @@ def get_account_create_forms(request=None, username=None, login_clipper=None): @login_required @teamkfet_required -def account_create_ajax(request, username=None, login_clipper=None): - forms = get_account_create_forms(request=None, username=username, login_clipper=login_clipper) +def account_create_ajax(request, username=None, login_clipper=None, + fullname=None): + forms = get_account_create_forms( + request=None, username=username, login_clipper=login_clipper, + fullname=fullname) return render(request, "kfet/account_create_form.html", { 'account_form' : forms['account_form'], 'cof_form' : forms['cof_form'], diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index 04234e2d..42ced84d 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -21,7 +21,7 @@ echo "mysql-server mysql-server/root_password_again password $DBPASSWD" | debcon apt-get install -y mysql-server mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME; GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBUSER'@'localhost' IDENTIFIED BY '$DBPASSWD'" -mysql -uroot -p$DBPASSWD -e "CREATE DATABASE test_$DBNAME; GRANT ALL PRIVILEGES ON test_$DBNAME.* TO '$DBUSER'@'localhost'" +mysql -uroot -p$DBPASSWD -e "GRANT ALL PRIVILEGES ON test_$DBNAME.* TO '$DBUSER'@'localhost'" # Installation et configuration d'Apache apt-get install -y apache2 diff --git a/provisioning/prepare_django.sh b/provisioning/prepare_django.sh index 28066579..4ec1a70f 100644 --- a/provisioning/prepare_django.sh +++ b/provisioning/prepare_django.sh @@ -3,6 +3,7 @@ source ~/venv/bin/activate python manage.py migrate -python manage.py loaddata gestion sites +python manage.py loaddata gestion sites articles python manage.py loaddevdata +python manage.py syncmails python manage.py collectstatic --noinput diff --git a/requirements.txt b/requirements.txt index ef2b3669..06f6c46e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,6 @@ asgi-redis==0.14.0 statistics==1.0.3.5 future==0.15.2 django-widget-tweaks==1.4.1 +git+https://git.eleves.ens.fr/cof-geek/django_custommail.git#egg=django_custommail +ldap3 git+https://github.com/Aureplop/channels.git#egg=channels diff --git a/sync_clipper.py b/sync_clipper.py deleted file mode 100644 index b959d521..00000000 --- a/sync_clipper.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gestioCOF.settings") - - from cof.models import Clipper - current = {} - print("[ FETCHING ]") - for clipper in Clipper.objects.all(): - current[clipper.username] = clipper - print("[ SYNCING ]") - for line in sys.stdin: - bits = line.split(":") - username = bits[0] - fullname = bits[4] - if username in current: - clipper = current[username] - if clipper.fullname != fullname: - clipper.fullname = fullname - clipper.save() - print("Updated", username) - else: - clipper = Clipper(username=username, fullname=fullname) - clipper.save() - print("Created", username) - print("[ DONE ]") diff --git a/sync_clipper.sh b/sync_clipper.sh deleted file mode 100644 index dc996d30..00000000 --- a/sync_clipper.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -ssh cof@sas.eleves.ens.fr ypcat passwd | python sync_clipper.py