Merge branch 'master' of github.com:OpenSlides/OpenSlides

This commit is contained in:
Oskar Hahn 2013-03-14 22:44:11 +01:00
commit 43cd5aba00
41 changed files with 1101 additions and 758 deletions

View File

@ -9,3 +9,4 @@ script:
- export DJANGO_SETTINGS_MODULE=tests.settings - export DJANGO_SETTINGS_MODULE=tests.settings
- coverage run ./manage.py test tests && coverage report -m - coverage run ./manage.py test tests && coverage report -m
- pep8 --max-line-length=150 --exclude="urls.py," --statistics openslides - pep8 --max-line-length=150 --exclude="urls.py," --statistics openslides
- pep8 --max-line-length=150 --statistics tests

View File

@ -22,9 +22,6 @@ from openslides.utils.views import FormView, TemplateView
from .forms import GeneralConfigForm from .forms import GeneralConfigForm
from .models import config from .models import config
# TODO: Do not import the participant module in config
from openslides.participant.api import get_or_create_anonymous_group
class GeneralConfig(FormView): class GeneralConfig(FormView):
""" """
@ -62,7 +59,6 @@ class GeneralConfig(FormView):
# system # system
if form.cleaned_data['system_enable_anonymous']: if form.cleaned_data['system_enable_anonymous']:
config['system_enable_anonymous'] = True config['system_enable_anonymous'] = True
get_or_create_anonymous_group()
else: else:
config['system_enable_anonymous'] = False config['system_enable_anonymous'] = False

View File

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.core.signals
~~~~~~~~~~~~~~~~~~~~~~~~~
Core Signals.
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.dispatch import Signal
post_database_setup = Signal()

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: OpenSlides 1.3\n" "Project-Id-Version: OpenSlides 1.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-05 14:24+0100\n" "POT-Creation-Date: 2013-03-12 21:29+0100\n"
"PO-Revision-Date: 2012-07-28 11:07+0200\n" "PO-Revision-Date: 2012-07-28 11:07+0200\n"
"Last-Translator: Oskar Hahn <mail@oshahn.de>\n" "Last-Translator: Oskar Hahn <mail@oshahn.de>\n"
"Language: de\n" "Language: de\n"
@ -20,3 +20,43 @@ msgstr ""
#, c-format #, c-format
msgid ", of which %s are hidden." msgid ", of which %s are hidden."
msgstr ", davon %s verborgen." msgstr ", davon %s verborgen."
#: static/javascript/dataTables.bootstrap.js:19
msgid "_MENU_ participants per page"
msgstr "_MENU_ Teilnehmer/innen pro Seite"
#: static/javascript/dataTables.bootstrap.js:20
msgid "Search:"
msgstr "Suche:"
#: static/javascript/dataTables.bootstrap.js:21
msgid "Showing _START_ to _END_ of _TOTAL_ participants"
msgstr "_START_ bis _END_ von _TOTAL_ Teilnehmer/innen"
#: static/javascript/dataTables.bootstrap.js:22
msgid "Showing 0 participants"
msgstr "0 Teilnehmer/innen"
#: static/javascript/dataTables.bootstrap.js:23
msgid "(filtered from _MAX_ total entries)"
msgstr "(gefiltert von _MAX_ Einträgen)"
#: static/javascript/dataTables.bootstrap.js:24
msgid "No matching records found"
msgstr "Keine passenden Einträge gefunden"
#: static/javascript/dataTables.bootstrap.js:25
msgid "First"
msgstr "Erster"
#: static/javascript/dataTables.bootstrap.js:26
msgid "Last"
msgstr "Letzter"
#: static/javascript/dataTables.bootstrap.js:27
msgid "Next"
msgstr "Weiter"
#: static/javascript/dataTables.bootstrap.js:28
msgid "Previous"
msgstr "Zurück"

View File

@ -27,6 +27,7 @@ from django.core.management import execute_from_command_line
from openslides import get_version from openslides import get_version
from openslides.utils.tornado_webserver import run_tornado from openslides.utils.tornado_webserver import run_tornado
CONFIG_TEMPLATE = """#!/usr/bin/env python CONFIG_TEMPLATE = """#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
@ -270,7 +271,6 @@ def run_syncdb():
# now initialize the database # now initialize the database
argv = ["", "syncdb", "--noinput"] argv = ["", "syncdb", "--noinput"]
execute_from_command_line(argv) execute_from_command_line(argv)
execute_from_command_line(["", "loaddata", "groups_de"])
def set_system_url(url): def set_system_url(url):

View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
openslides.motion openslides.motion

View File

@ -1,280 +0,0 @@
[
{
"pk":1,
"model":"motion.workflow",
"fields":{
"name":"Simple Workflow",
"first_state":1
}
},
{
"pk":2,
"model":"motion.workflow",
"fields":{
"name":"Complex Workflow",
"first_state":5
}
},
{
"pk":1,
"model":"motion.state",
"fields":{
"name":"submitted",
"workflow":1,
"dont_set_new_version_active":false,
"allow_submitter_edit":true,
"next_states":[
2,
3,
4
],
"allow_support":true,
"action_word":"",
"icon":"",
"versioning":false,
"allow_create_poll":true
}
},
{
"pk":2,
"model":"motion.state",
"fields":{
"name":"accepted",
"workflow":1,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"accept",
"icon":"",
"versioning":false,
"allow_create_poll":false
}
},
{
"pk":3,
"model":"motion.state",
"fields":{
"name":"rejected",
"workflow":1,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"reject",
"icon":"",
"versioning":false,
"allow_create_poll":false
}
},
{
"pk":4,
"model":"motion.state",
"fields":{
"name":"not decided",
"workflow":1,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"do not decide",
"icon":"",
"versioning":false,
"allow_create_poll":false
}
},
{
"pk":5,
"model":"motion.state",
"fields":{
"name":"published",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":true,
"next_states":[
6,
9,
14
],
"allow_support":true,
"action_word":"",
"icon":"",
"versioning":false,
"allow_create_poll":false
}
},
{
"pk":6,
"model":"motion.state",
"fields":{
"name":"permitted",
"workflow":2,
"dont_set_new_version_active":true,
"allow_submitter_edit":true,
"next_states":[
7,
8,
9,
10,
11,
12,
13
],
"allow_support":false,
"action_word":"permit",
"icon":"",
"versioning":true,
"allow_create_poll":true
}
},
{
"pk":7,
"model":"motion.state",
"fields":{
"name":"accepted",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"accept",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":8,
"model":"motion.state",
"fields":{
"name":"rejected",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"reject",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":9,
"model":"motion.state",
"fields":{
"name":"withdrawed",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"withdraw",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":10,
"model":"motion.state",
"fields":{
"name":"adjourned",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"adjourn",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":11,
"model":"motion.state",
"fields":{
"name":"not concerned",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":12,
"model":"motion.state",
"fields":{
"name":"commited a bill",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"commit a bill",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":13,
"model":"motion.state",
"fields":{
"name":"needs review",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
},
{
"pk":14,
"model":"motion.state",
"fields":{
"name":"rejected (not authorized)",
"workflow":2,
"dont_set_new_version_active":false,
"allow_submitter_edit":false,
"next_states":[
],
"allow_support":false,
"action_word":"reject (not authorized)",
"icon":"",
"versioning":true,
"allow_create_poll":false
}
}
]

View File

@ -15,7 +15,7 @@ from django.utils.translation import ugettext as _
from openslides.utils.forms import CssClassMixin from openslides.utils.forms import CssClassMixin
from openslides.utils.person import PersonFormField, MultiplePersonFormField from openslides.utils.person import PersonFormField, MultiplePersonFormField
from .models import Motion, Workflow from .models import Motion, Workflow, Category
class BaseMotionForm(forms.ModelForm, CssClassMixin): class BaseMotionForm(forms.ModelForm, CssClassMixin):
@ -90,6 +90,18 @@ class MotionDisableVersioningMixin(forms.ModelForm):
last_version will be used.""" last_version will be used."""
class MotionCategoryMixin(forms.ModelForm):
"""Mixin to let the user choose the category for the motion."""
category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False)
class MotionIdentifierMixin(forms.ModelForm):
"""Mixin to let the user choose the identifier for the motion."""
identifier = forms.CharField(required=False)
class ConfigForm(CssClassMixin, forms.Form): class ConfigForm(CssClassMixin, forms.Form):
"""Form for the configuration tab of OpenSlides.""" """Form for the configuration tab of OpenSlides."""
motion_min_supporters = forms.IntegerField( motion_min_supporters = forms.IntegerField(

View File

@ -16,7 +16,7 @@
from datetime import datetime from datetime import datetime
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models, IntegrityError
from django.db.models import Max from django.db.models import Max
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import formats from django.utils import formats
@ -65,7 +65,15 @@ class Motion(SlideMixin, models.Model):
unique=True) unique=True)
"""A string as human readable identifier for the motion.""" """A string as human readable identifier for the motion."""
# category = models.ForeignKey('Category', null=True, blank=True) identifier_number = models.IntegerField(null=True)
"""Counts the number of the motion in one category.
Needed to find the next free motion-identifier.
"""
category = models.ForeignKey('Category', null=True, blank=True)
"""ForeignKey to one category of motions."""
# TODO: proposal # TODO: proposal
#master = models.ForeignKey('self', null=True, blank=True) #master = models.ForeignKey('self', null=True, blank=True)
@ -168,6 +176,33 @@ class Motion(SlideMixin, models.Model):
if link == 'delete': if link == 'delete':
return reverse('motion_delete', args=[str(self.id)]) return reverse('motion_delete', args=[str(self.id)])
def set_identifier(self):
if config['motion_identifier'] == 'manually':
# Do not set an identifier.
return
elif config['motion_identifier'] == 'per_category':
motions = Motion.objects.filter(category=self.category)
else:
motions = Motion.objects.all()
number = motions.aggregate(Max('identifier_number'))['identifier_number__max'] or 0
if self.category is None or not self.category.prefix:
prefix = ''
else:
prefix = self.category.prefix + ' '
while True:
number += 1
self.identifier = '%s%d' % (prefix, number)
try:
self.save()
except IntegrityError:
continue
else:
self.number = number
self.save()
break
def get_title(self): def get_title(self):
"""Get the title of the motion. """Get the title of the motion.
@ -344,12 +379,25 @@ class Motion(SlideMixin, models.Model):
else: else:
raise WorkflowError('You can not create a poll in state %s.' % self.state.name) raise WorkflowError('You can not create a poll in state %s.' % self.state.name)
def set_state(self, state):
"""Set the state of the motion.
State can be the id of a state object or a state object.
"""
if type(state) is int:
state = State.objects.get(pk=state)
if not state.dont_set_identifier:
self.set_identifier()
self.state = state
def reset_state(self): def reset_state(self):
"""Set the state to the default state. If the motion is new, it chooses the default workflow from config.""" """Set the state to the default state. If the motion is new, it chooses the default workflow from config."""
if self.state: if self.state:
self.state = self.state.workflow.first_state self.state = self.state.workflow.first_state
else: else:
self.state = Workflow.objects.get(pk=config['motion_workflow']).first_state self.state = (Workflow.objects.get(pk=config['motion_workflow']).first_state or
Workflow.objects.get(pk=config['motion_workflow']).state_set.all()[0])
def slide(self): def slide(self):
"""Return the slide dict.""" """Return the slide dict."""
@ -523,12 +571,24 @@ class MotionSupporter(models.Model):
return unicode(self.person) return unicode(self.person)
## class Category(models.Model): class Category(models.Model):
## name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name")) name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name"))
## prefix = models.CharField(max_length=32, verbose_name=ugettext_lazy("Category prefix")) """Name of the category."""
## def __unicode__(self): prefix = models.CharField(blank=True, max_length=32, verbose_name=ugettext_lazy("Category prefix"))
## return self.name """Prefix of the category.
Used to build the identifier of a motion.
"""
def __unicode__(self):
return self.name
def get_absolute_url(self, link='update'):
if link == 'update' or link == 'edit':
return reverse('motion_category_update', args=[str(self.id)])
if link == 'delete':
return reverse('motion_category_delete', args=[str(self.id)])
## class Comment(models.Model): ## class Comment(models.Model):
@ -684,6 +744,12 @@ class State(models.Model):
dont_set_new_version_active = models.BooleanField(default=False) dont_set_new_version_active = models.BooleanField(default=False)
"""If true, new versions are not automaticly set active.""" """If true, new versions are not automaticly set active."""
dont_set_identifier = models.BooleanField(default=False)
"""Decides if the motion gets an identifier.
If true, the motion does not get an identifier if the state change to
this one, else it does."""
def __unicode__(self): def __unicode__(self):
"""Returns the name of the state.""" """Returns the name of the state."""
return self.name return self.name
@ -716,7 +782,7 @@ class Workflow(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
"""A string representing the workflow.""" """A string representing the workflow."""
first_state = models.OneToOneField(State, related_name='+') first_state = models.OneToOneField(State, related_name='+', null=True)
"""A one-to-one relation to a state, the starting point for the workflow.""" """A one-to-one relation to a state, the starting point for the workflow."""
def __unicode__(self): def __unicode__(self):
@ -733,5 +799,5 @@ class Workflow(models.Model):
def check_first_state(self): def check_first_state(self):
"""Checks whether the first_state itself belongs to the workflow.""" """Checks whether the first_state itself belongs to the workflow."""
if not self.first_state.workflow == self: if self.first_state and not self.first_state.workflow == self:
raise WorkflowError('%s can not be first state of %s because it does not belong to it.' % (self.first_state, self)) raise WorkflowError('%s can not be first state of %s because it does not belong to it.' % (self.first_state, self))

View File

@ -11,9 +11,12 @@
""" """
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _, ugettext_noop
from openslides.config.signals import default_config_value from openslides.config.signals import default_config_value
from openslides.core.signals import post_database_setup
from .models import Workflow, State
@receiver(default_config_value, dispatch_uid="motion_default_config") @receiver(default_config_value, dispatch_uid="motion_default_config")
@ -28,3 +31,77 @@ def default_config(sender, key, **kwargs):
'motion_pdf_preamble': '', 'motion_pdf_preamble': '',
'motion_allow_disable_versioning': False, 'motion_allow_disable_versioning': False,
'motion_workflow': 1}.get(key) 'motion_workflow': 1}.get(key)
@receiver(post_database_setup, dispatch_uid='motion_create_builtin_workflows')
def create_builtin_workflows(sender, **kwargs):
"""
Creates a simple and a complex workflow.
"""
workflow_1 = Workflow.objects.create(name=ugettext_noop('Simple Workflow'))
state_1_1 = State.objects.create(name=ugettext_noop('submitted'),
workflow=workflow_1,
allow_create_poll=True,
allow_support=True,
allow_submitter_edit=True)
state_1_2 = State.objects.create(name=ugettext_noop('accepted'),
workflow=workflow_1,
action_word=ugettext_noop('Accept'))
state_1_3 = State.objects.create(name=ugettext_noop('rejected'),
workflow=workflow_1,
action_word=ugettext_noop('Reject'))
state_1_4 = State.objects.create(name=ugettext_noop('not decided'),
workflow=workflow_1,
action_word=ugettext_noop('Do not decide'))
state_1_1.next_states.add(state_1_2, state_1_3, state_1_4)
workflow_1.first_state = state_1_1
workflow_1.save()
workflow_2 = Workflow.objects.create(name=ugettext_noop('Complex Workflow'))
state_2_1 = State.objects.create(name=ugettext_noop('published'),
workflow=workflow_2,
allow_support=True,
allow_submitter_edit=True,
dont_set_identifier=True)
state_2_2 = State.objects.create(name=ugettext_noop('permitted'),
workflow=workflow_2,
action_word=ugettext_noop('Permit'),
allow_create_poll=True,
allow_submitter_edit=True,
versioning=True,
dont_set_new_version_active=True)
state_2_3 = State.objects.create(name=ugettext_noop('accepted'),
workflow=workflow_2,
action_word=ugettext_noop('Accept'),
versioning=True)
state_2_4 = State.objects.create(name=ugettext_noop('rejected'),
workflow=workflow_2,
action_word=ugettext_noop('Reject'),
versioning=True)
state_2_5 = State.objects.create(name=ugettext_noop('withdrawed'),
workflow=workflow_2,
action_word=ugettext_noop('Withdraw'),
versioning=True)
state_2_6 = State.objects.create(name=ugettext_noop('adjourned'),
workflow=workflow_2,
action_word=ugettext_noop('Adjourn'),
versioning=True)
state_2_7 = State.objects.create(name=ugettext_noop('not concerned'),
workflow=workflow_2,
action_word=ugettext_noop('Do not concern'),
versioning=True)
state_2_8 = State.objects.create(name=ugettext_noop('commited a bill'),
workflow=workflow_2,
action_word=ugettext_noop('Commit a bill'),
versioning=True)
state_2_9 = State.objects.create(name=ugettext_noop('needs review'),
workflow=workflow_2,
versioning=True)
state_2_10 = State.objects.create(name=ugettext_noop('rejected (not authorized)'),
workflow=workflow_2,
action_word=ugettext_noop('reject (not authorized)'),
versioning=True)
state_2_1.next_states.add(state_2_2, state_2_5, state_2_10)
state_2_2.next_states.add(state_2_3, state_2_4, state_2_5, state_2_6, state_2_7, state_2_8, state_2_9)
workflow_2.first_state = state_2_1
workflow_2.save()

View File

@ -0,0 +1,33 @@
{% extends "base.html" %}
{% load tags %}
{% load i18n %}
{% block title %}
{{ block.super }}
{% if motion %}
{% trans "Edit category" %}
{% else %}
{% trans "New category" %}
{% endif %}
{% endblock %}
{% block content %}
<h1>
{% if motion %}
{% trans "Edit category" %}
{% else %}
{% trans "New category" %}
{% endif %}
</h1>
<form action="" method="post">{% csrf_token %}
{% include "form.html" %}
<p>
{% include "formbuttons_saveapply.html" %}
<a href='{% url 'motion_list' %}' class="btn">
{% trans 'Cancel' %}
</a>
</p>
<small>* {% trans "required" %}</small>
</form>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% load tags %}
{% load i18n %}
{% block title %}{{ block.super }} {% trans "Motions" %}{% endblock %}
{% block content %}
<h1>{% trans "Categories" %}</h1>
{% for category in category_list %}
<p><a href="{% model_url category 'update' %}">{{ category }}</a></p>
{% empty %}
<p>No Categories</p>
{% endfor %}
</table>
{% endblock %}

View File

@ -8,11 +8,11 @@
{% block content %} {% block content %}
<h1> <h1>
{{ motion.title }} {{ motion.title }} {{ motion.category }}
<br> <br>
<small> <small>
{% if motion.number != None %} {% if motion.identifier != None %}
{% trans "Motion" %} {{ motion.number }}, {% trans "Motion" %} {{ motion.identifier }},
{% else %} {% else %}
<i>[{% trans "no number" %}]</i>, <i>[{% trans "no number" %}]</i>,
{% endif %} {% endif %}

View File

@ -19,8 +19,9 @@ urlpatterns = patterns('openslides.motion.views',
name='motion_list', name='motion_list',
), ),
url(r'^create/$', url(r'^new/$',
'motion_create', 'motion_create',
# TODO: rename to motion_create
name='motion_new', name='motion_new',
), ),
@ -39,6 +40,11 @@ urlpatterns = patterns('openslides.motion.views',
name='motion_delete', name='motion_delete',
), ),
url(r'^(?P<pk>\d+)/set_identifier/',
'set_identifier',
name='motion_set_identifier',
),
url(r'^(?P<pk>\d+)/version/(?P<version_number>\d+)/$', url(r'^(?P<pk>\d+)/version/(?P<version_number>\d+)/$',
'motion_detail', 'motion_detail',
name='motion_version_detail', name='motion_version_detail',
@ -103,4 +109,24 @@ urlpatterns = patterns('openslides.motion.views',
'motion_detail_pdf', 'motion_detail_pdf',
name='motion_detail_pdf', name='motion_detail_pdf',
), ),
url(r'^category/$',
'category_list',
name='motion_category_list',
),
url(r'^category/new/$',
'category_create',
name='motion_category_create',
),
url(r'^category/(?P<pk>\d+)/edit/$',
'category_update',
name='motion_category_update',
),
url(r'^category/(?P<pk>\d+)/del/$',
'category_delete',
name='motion_category_delete',
),
) )

View File

@ -32,12 +32,18 @@ from openslides.projector.projector import Widget, SLIDE
from openslides.config.models import config from openslides.config.models import config
from openslides.agenda.models import Item from openslides.agenda.models import Item
from .models import Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion, State, WorkflowError from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
MotionVersion, State, WorkflowError, Category)
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
MotionDisableVersioningMixin, ConfigForm) MotionDisableVersioningMixin, ConfigForm, MotionCategoryMixin,
MotionIdentifierMixin)
from .pdf import motions_to_pdf, motion_to_pdf from .pdf import motions_to_pdf, motion_to_pdf
# TODO: into the config-tab
config['motion_identifier'] = ('manually', 'per_category', 'serially_numbered')[2]
class MotionListView(ListView): class MotionListView(ListView):
"""View, to list all motions.""" """View, to list all motions."""
permission_required = 'motion.can_see_motion' permission_required = 'motion.can_see_motion'
@ -97,6 +103,16 @@ class MotionMixin(object):
except KeyError: except KeyError:
pass pass
try:
self.object.category = form.cleaned_data['category']
except KeyError:
pass
try:
self.object.identifier = form.cleaned_data['identifier']
except KeyError:
pass
def post_save(self, form): def post_save(self, form):
"""Save the submitter an the supporter so the motion.""" """Save the submitter an the supporter so the motion."""
super(MotionMixin, self).post_save(form) super(MotionMixin, self).post_save(form)
@ -119,10 +135,17 @@ class MotionMixin(object):
will be mixed in dependence of some config values. See motion.forms will be mixed in dependence of some config values. See motion.forms
for more information on the mixins. for more information on the mixins.
""" """
form_classes = []
if (self.request.user.has_perm('motion.can_manage_motion') and
config['motion_identifier'] == 'manually'):
form_classes.append(MotionIdentifierMixin)
form_classes.append(BaseMotionForm)
form_classes = [BaseMotionForm]
if self.request.user.has_perm('motion.can_manage_motion'): if self.request.user.has_perm('motion.can_manage_motion'):
form_classes.append(MotionSubmitterMixin) form_classes.append(MotionSubmitterMixin)
form_classes.append(MotionCategoryMixin)
if config['motion_min_supporters'] > 0: if config['motion_min_supporters'] > 0:
form_classes.append(MotionSupporterMixin) form_classes.append(MotionSupporterMixin)
if self.object: if self.object:
@ -228,6 +251,30 @@ class VersionRejectView(GetVersionMixin, SingleObjectMixin, QuestionMixin, Redir
version_reject = VersionRejectView.as_view() version_reject = VersionRejectView.as_view()
class SetIdentifierView(SingleObjectMixin, RedirectView):
"""Set the identifier of the motion.
See motion.set_identifier for more informations
"""
permission_required = 'motion.can_manage_motion'
model = Motion
url_name = 'motion_detail'
def get(self, request, *args, **kwargs):
"""Set self.object to a motion."""
self.object = self.get_object()
return super(SetIdentifierView, self).get(request, *args, **kwargs)
def pre_redirect(self, request, *args, **kwargs):
"""Set the identifier."""
self.object.set_identifier()
def get_url_name_args(self):
return [self.object.id]
set_identifier = SetIdentifierView.as_view()
class SupportView(SingleObjectMixin, QuestionMixin, RedirectView): class SupportView(SingleObjectMixin, QuestionMixin, RedirectView):
"""View to support or unsupport a motion. """View to support or unsupport a motion.
@ -399,7 +446,7 @@ class MotionSetStateView(SingleObjectMixin, RedirectView):
if self.reset: if self.reset:
self.object.reset_state() self.object.reset_state()
else: else:
self.object.state = State.objects.get(pk=kwargs['state']) self.object.set_state(int(kwargs['state']))
except WorkflowError, e: # TODO: Is a WorkflowError still possible here? except WorkflowError, e: # TODO: Is a WorkflowError still possible here?
messages.error(request, e) messages.error(request, e)
else: else:
@ -473,6 +520,35 @@ motion_list_pdf = MotionPDFView.as_view(print_all_motions=True)
motion_detail_pdf = MotionPDFView.as_view(print_all_motions=False) motion_detail_pdf = MotionPDFView.as_view(print_all_motions=False)
class CategoryListView(ListView):
permission_required = 'motion.can_manage_motion'
model = Category
category_list = CategoryListView.as_view()
class CategoryCreateView(CreateView):
permission_required = 'motion.can_manage_motion'
model = Category
category_create = CategoryCreateView.as_view()
class CategoryUpdateView(UpdateView):
permission_required = 'motion.can_manage_motion'
model = Category
category_update = CategoryUpdateView.as_view()
class CategoryDeleteView(DeleteView):
permission_required = 'motion.can_manage_motion'
model = Category
success_url_name = 'motion_category_list'
category_delete = CategoryDeleteView.as_view()
class Config(FormView): class Config(FormView):
"""The View for the config tab.""" """The View for the config tab."""
permission_required = 'config.can_manage_config' permission_required = 'config.can_manage_config'

View File

@ -1,55 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.motion.workflow
~~~~~~~~~~~~~~~~~~~~~~~~~~
This file is only for development. It will be moved out of
the openslides module before the next release.
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.utils.translation import ugettext_noop
from .models import Workflow, State
def _init_builtin_workflows():
"""
Saves a simple and a complex workflow into the database.
This function is only called manually and lives here only for development.
"""
workflow_1 = Workflow(name=ugettext_noop('Simple Workflow'), id=1)
state_1_1 = State.objects.create(name=ugettext_noop('submitted'), workflow=workflow_1,
allow_create_poll=True, allow_support=True, allow_submitter_edit=True)
state_1_2 = State.objects.create(name=ugettext_noop('accepted'), workflow=workflow_1, action_word=ugettext_noop('accept'))
state_1_3 = State.objects.create(name=ugettext_noop('rejected'), workflow=workflow_1, action_word=ugettext_noop('reject'))
state_1_4 = State.objects.create(name=ugettext_noop('not decided'), workflow=workflow_1, action_word=ugettext_noop('do not decide'))
state_1_1.next_states.add(state_1_2, state_1_3, state_1_4)
state_1_1.save() # Is this neccessary?
workflow_1.first_state = state_1_1
workflow_1.save()
workflow_2 = Workflow(name=ugettext_noop('Complex Workflow'), id=2)
state_2_1 = State.objects.create(name=ugettext_noop('published'), workflow=workflow_2, allow_support=True, allow_submitter_edit=True)
state_2_2 = State.objects.create(name=ugettext_noop('permitted'), workflow=workflow_2, action_word=ugettext_noop('permit'),
allow_create_poll=True, allow_submitter_edit=True, versioning=True, dont_set_new_version_active=True)
state_2_3 = State.objects.create(name=ugettext_noop('accepted'), workflow=workflow_2, action_word=ugettext_noop('accept'), versioning=True)
state_2_4 = State.objects.create(name=ugettext_noop('rejected'), workflow=workflow_2, action_word=ugettext_noop('reject'), versioning=True)
state_2_5 = State.objects.create(name=ugettext_noop('withdrawed'), workflow=workflow_2,
action_word=ugettext_noop('withdraw'), versioning=True)
state_2_6 = State.objects.create(name=ugettext_noop('adjourned'), workflow=workflow_2, action_word=ugettext_noop('adjourn'), versioning=True)
state_2_7 = State.objects.create(name=ugettext_noop('not concerned'), workflow=workflow_2, versioning=True)
state_2_8 = State.objects.create(name=ugettext_noop('commited a bill'), workflow=workflow_2,
action_word=ugettext_noop('commit a bill'), versioning=True)
state_2_9 = State.objects.create(name=ugettext_noop('needs review'), workflow=workflow_2, versioning=True)
state_2_10 = State.objects.create(name=ugettext_noop('rejected (not authorized)'), workflow=workflow_2,
action_word=ugettext_noop('reject (not authorized)'), versioning=True)
state_2_1.next_states.add(state_2_2, state_2_5, state_2_10)
state_2_2.next_states.add(state_2_3, state_2_4, state_2_5, state_2_6, state_2_7, state_2_8, state_2_9)
state_2_1.save() # Is this neccessary?
state_2_2.save() # Is this neccessary?
workflow_2.first_state = state_2_1
workflow_2.save()

View File

@ -1,3 +1,18 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.participant
~~~~~~~~~~~~~~~~~~~~~~
The OpenSlides participant app.
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.utils.translation import ugettext_noop from django.utils.translation import ugettext_noop
import openslides.participant.signals
NAME = ugettext_noop('Participant') NAME = ugettext_noop('Participant')

View File

@ -97,21 +97,8 @@ def import_users(csv_file):
return (count_success, error_messages) return (count_success, error_messages)
def get_or_create_registered_group(): def get_registered_group():
registered, created = Group.objects.get_or_create( """
name__iexact='Registered', defaults={'name': 'Registered'}) Returns the Group 'Registered'. Upper and lower case is possible.
if created: """
registered.permissions = Permission.objects.filter( return Group.objects.get(name__iexact='Registered')
codename__in=DEFAULT_PERMS)
registered.save()
return registered
def get_or_create_anonymous_group():
anonymous, created = Group.objects.get_or_create(
name__iexact='Anonymous', defaults={'name': 'Anonymous'})
if created:
anonymous.permissions = Permission.objects.filter(
codename__in=DEFAULT_PERMS)
anonymous.save()
return anonymous

View File

@ -1,233 +0,0 @@
[
{
"pk": 1,
"model": "auth.group",
"fields": {
"name": "Beobachter/in",
"permissions": [
[
"can_see_agenda",
"agenda",
"item"
],
[
"can_create_motion",
"motion",
"motion"
],
[
"can_see_motion",
"motion",
"motion"
],
[
"can_nominate_other",
"assignment",
"assignment"
],
[
"can_nominate_self",
"assignment",
"assignment"
],
[
"can_see_assignment",
"assignment",
"assignment"
],
[
"can_see_participant",
"participant",
"user"
],
[
"can_see_projector",
"projector",
"projectorslide"
],
[
"can_see_dashboard",
"projector",
"projectorslide"
]
]
}
},
{
"pk": 2,
"model": "auth.group",
"fields": {
"name": "Delegierte/r",
"permissions": [
[
"can_see_agenda",
"agenda",
"item"
],
[
"can_create_motion",
"motion",
"motion"
],
[
"can_see_motion",
"motion",
"motion"
],
[
"can_support_motion",
"motion",
"motion"
],
[
"can_nominate_other",
"assignment",
"assignment"
],
[
"can_nominate_self",
"assignment",
"assignment"
],
[
"can_see_assignment",
"assignment",
"assignment"
],
[
"can_see_participant",
"participant",
"user"
],
[
"can_see_projector",
"projector",
"projectorslide"
],
[
"can_see_dashboard",
"projector",
"projectorslide"
]
]
}
},
{
"pk": 3,
"model": "auth.group",
"fields": {
"name": "Versammlungsleitung",
"permissions": [
[
"can_manage_agenda",
"agenda",
"item"
],
[
"can_see_agenda",
"agenda",
"item"
],
[
"can_create_motion",
"motion",
"motion"
],
[
"can_manage_motion",
"motion",
"motion"
],
[
"can_see_motion",
"motion",
"motion"
],
[
"can_manage_assignment",
"assignment",
"assignment"
],
[
"can_nominate_other",
"assignment",
"assignment"
],
[
"can_nominate_self",
"assignment",
"assignment"
],
[
"can_see_assignment",
"assignment",
"assignment"
],
[
"can_manage_config",
"config",
"configstore"
],
[
"can_manage_participant",
"participant",
"user"
],
[
"can_see_participant",
"participant",
"user"
],
[
"can_manage_projector",
"projector",
"projectorslide"
],
[
"can_see_projector",
"projector",
"projectorslide"
],
[
"can_see_dashboard",
"projector",
"projectorslide"
]
]
}
},
{
"pk": 4,
"model": "auth.group",
"fields": {
"name": "Teilnehmerverwaltung",
"permissions": [
[
"can_see_agenda",
"agenda",
"item"
],
[
"can_manage_participant",
"participant",
"user"
],
[
"can_see_participant",
"participant",
"user"
],
[
"can_see_projector",
"projector",
"projectorslide"
],
[
"can_see_dashboard",
"projector",
"projectorslide"
]
]
}
}
]

View File

@ -19,7 +19,7 @@ from openslides.utils.forms import (
CssClassMixin, LocalizedModelMultipleChoiceField) CssClassMixin, LocalizedModelMultipleChoiceField)
from openslides.participant.models import User, Group from openslides.participant.models import User, Group
from openslides.participant.api import get_or_create_registered_group from openslides.participant.api import get_registered_group
class UserCreateForm(forms.ModelForm, CssClassMixin): class UserCreateForm(forms.ModelForm, CssClassMixin):
@ -30,7 +30,7 @@ class UserCreateForm(forms.ModelForm, CssClassMixin):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if kwargs.get('instance', None) is None: if kwargs.get('instance', None) is None:
initial = kwargs.setdefault('initial', {}) initial = kwargs.setdefault('initial', {})
registered = get_or_create_registered_group() registered = get_registered_group()
initial['groups'] = [registered.pk] initial['groups'] = [registered.pk]
super(UserCreateForm, self).__init__(*args, **kwargs) super(UserCreateForm, self).__init__(*args, **kwargs)

View File

@ -257,9 +257,9 @@ def djangogroup_post_save(sender, instance, signal, *args, **kwargs):
@receiver(signals.post_save, sender=User) @receiver(signals.post_save, sender=User)
def user_post_save(sender, instance, *args, **kwargs): def user_post_save(sender, instance, *args, **kwargs):
from openslides.participant.api import get_or_create_registered_group
if not kwargs['created']: if not kwargs['created']:
return return
registered = get_or_create_registered_group() from openslides.participant.api import get_registered_group # TODO: Test, if global import is possible
registered = get_registered_group()
instance.groups.add(registered) instance.groups.add(registered)
instance.save() instance.save()

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.participant.signals
~~~~~~~~~~~~~~~~~~~~~~~~~
Signals for the participant app.
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.dispatch import receiver
from django.utils.translation import ugettext_noop
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission
from openslides.core.signals import post_database_setup
from .models import Group
@receiver(post_database_setup, dispatch_uid='participant_create_builtin_groups')
def create_builtin_groups(sender, **kwargs):
"""
Creates the builtin groups: Anonymous, Registered, Delegates and Staff.
"""
# Anonymous and Registered
ct_projector = ContentType.objects.get(app_label='projector', model='projectorslide')
perm_1 = Permission.objects.get(content_type=ct_projector, codename='can_see_projector')
perm_2 = Permission.objects.get(content_type=ct_projector, codename='can_see_dashboard')
ct_agenda = ContentType.objects.get(app_label='agenda', model='item')
perm_3 = Permission.objects.get(content_type=ct_agenda, codename='can_see_agenda')
ct_motion = ContentType.objects.get(app_label='motion', model='motion')
perm_4 = Permission.objects.get(content_type=ct_motion, codename='can_see_motion')
ct_assignment = ContentType.objects.get(app_label='assignment', model='assignment')
perm_5 = Permission.objects.get(content_type=ct_assignment, codename='can_see_assignment')
ct_participant = ContentType.objects.get(app_label='participant', model='user')
perm_6 = Permission.objects.get(content_type=ct_participant, codename='can_see_participant')
group_anonymous = Group.objects.create(name=ugettext_noop('Anonymous'))
group_anonymous.permissions.add(perm_1, perm_2, perm_3, perm_4, perm_5, perm_6)
group_registered = Group.objects.create(name=ugettext_noop('Registered'))
group_registered.permissions.add(perm_1, perm_2, perm_3, perm_4, perm_5, perm_6)
# Delegates
perm_7 = Permission.objects.get(content_type=ct_motion, codename='can_create_motion')
perm_8 = Permission.objects.get(content_type=ct_motion, codename='can_support_motion')
perm_9 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_other')
perm_10 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_self')
group_delegates = Group.objects.create(name=ugettext_noop('Delegates'))
group_delegates.permissions.add(perm_7, perm_8, perm_9, perm_10)
# Staff
perm_11 = Permission.objects.get(content_type=ct_agenda, codename='can_manage_agenda')
perm_12 = Permission.objects.get(content_type=ct_motion, codename='can_manage_motion')
perm_13 = Permission.objects.get(content_type=ct_assignment, codename='can_manage_assignment')
perm_14 = Permission.objects.get(content_type=ct_participant, codename='can_manage_participant')
perm_15 = Permission.objects.get(content_type=ct_projector, codename='can_manage_projector')
ct_config = ContentType.objects.get(app_label='config', model='configstore')
perm_16 = Permission.objects.get(content_type=ct_config, codename='can_manage_config')
group_staff = Group.objects.create(name=ugettext_noop('Staff'))
group_staff.permissions.add(perm_7, perm_9, perm_10, perm_11, perm_12, perm_13, perm_14, perm_15, perm_16)

View File

@ -6,10 +6,16 @@
{% block title %}{{ block.super }} {% trans "Participants" %}{% endblock %} {% block title %}{{ block.super }} {% trans "Participants" %}{% endblock %}
{% block header %}
<link href="{% static 'styles/dataTables/dataTables.bootstrap.css' %}" type="text/css" rel="stylesheet">
{% endblock %}
{% block javascript %} {% block javascript %}
{% if perms.participant.can_manage_participant %} {% if perms.participant.can_manage_participant %}
<script type="text/javascript" src="{% static 'javascript/participant.js' %}"></script> <script type="text/javascript" src="{% static 'javascript/participant.js' %}"></script>
{% endif %} {% endif %}
<script src="{% static 'javascript/jquery.dataTables.min.js' %}" type="text/javascript"></script>
<script src="{% static 'javascript/dataTables.bootstrap.js' %}" type="text/javascript"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -49,67 +55,39 @@
</small> </small>
</h1> </h1>
<form action="" name="filter" method="get"> <table id="dataTableParticipants" class="table table-striped table-bordered" cellpadding="0" cellspacing="0" border="0">
{% trans "Filter" %}: <thead>
<div class="control-group">
<select class="span2" name="gender" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Gender" %} --</option>
<option value="male"{% if 'male' in sortfilter.gender %} selected{% endif %}>{% trans "Male" %}</option>
<option value="female"{% if 'female' in sortfilter.gender %} selected{% endif %}>{% trans "Female" %}</option>
<option value=""{% if '' in sortfilter.gender %} selected{% endif %}>{% trans "Not specified" %}</option>
</select>
<select class="span2" name="structure_level" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Structure level" %} --</option>
{% for level in structure_levels %}
<option value="{{ level }}"{% if level in sortfilter.structure_level %} selected{% endif %}>
{{ level }}</option>
{% endfor %}
</select>
<select class="span2" name="type" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Type" %} --</option>
<option value="delegate"{% if 'delegate' in sortfilter.type %} selected{% endif %}>{% trans "Delegate" %}</option>
<option value="observer"{% if 'observer' in sortfilter.type %} selected{% endif %}>{% trans "Observer" %}</option>
<option value="staff"{% if 'staff' in sortfilter.type %} selected{% endif %}>{% trans "Staff" %}</option>
<option value="guest"{% if 'guest' in sortfilter.type %} selected{% endif %}>{% trans "Guest" %}</option>
<option value=""{% if '' in sortfilter.type %} selected{% endif %}>{% trans "Not specified" %}</option>
</select>
<select class="span2" name="committee" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Committee" %} --</option>
{% for committee in committees %}
<option value="{{ committee }}"{% if committee in sortfilter.committee %} selected{% endif %}>
{{ committee }}</option>
{% endfor %}
</select>
<select class="span2" name="status" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Status" %} --</option>
<option value="1"{% if '1' in sortfilter.status %} selected{% endif %}>{% trans "Active" %}</option>
<option value="0"{% if '0' in sortfilter.status %} selected{% endif %}>{% trans "Inactive" %}</option>
</select>
</div>
</form>
<small><i>
{% if users.count == allusers %}
{{ users.count }}
{% blocktrans count counter=users.count %}participant{% plural %}participants{% endblocktrans %}
{% else %}
{{ users.count }} {% trans "of" %} {{ allusers }} {% trans "Participants" %} (= {{ percent }} %)
{% endif %}
</i></small>
<table class="table table-striped table-bordered">
<tr> <tr>
<th><a href="?sort=first_name&reverse={% if 'first_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "First Name" %}</a></th> <th>{% trans "Present" %}</th>
<th><a href="?sort=last_name&reverse={% if 'last_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Last Name" %}</a></th> <th>{% trans "First Name" %}</th>
<th class="optional"><a href="?sort=structure_level&reverse={% if 'structure_level' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Structure level" %}</a></th> <th>{% trans "Last Name" %}</th>
<th class="optional"><a href="?sort=type&reverse={% if 'type' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Type" %}</a></th> <th class="optional">{% trans "Structure level" %}</th>
<th class="optional"><a href="?sort=committee&reverse={% if 'committee' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Committee" %}</a></th> <th class="optional">{% trans "Type" %}</th>
<th class="optional">{% trans "Committee" %}</th>
{% if perms.participant.can_manage_participant %} {% if perms.participant.can_manage_participant %}
<th class="optional"><a href="?sort=comment&reverse={% if 'comment' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Comment" %}</a></th> <th class="optional">{% trans "Comment" %}</th>
<th class="optional"><a href="?sort=last_login&reverse={% if 'last_login' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Last Login" %}</a></th> <th class="optional">{% trans "Last Login" %}</th>
<th class="mini_width">{% trans "Actions" %}</th> <th class="mini_width">{% trans "Actions" %}</th>
{% endif %} {% endif %}
</tr> </tr>
</thead>
<tbody>
{% for user in users %} {% for user in users %}
<tr class="{% if user.active %}activeline{% endif %}"> <tr class="{% if user.active %}activeline{% endif %}">
<td>{% if perms.participant.can_manage_participant %}
{% if user != request_user and not user.is_superuser %}
<a href="{% url 'user_status_toggle' user.id %}"
class="status_link btn btn-mini {% if user.is_active %}btn-success{% endif %}"
title="{% if user.is_active %}{% trans 'present' %}{% else %}{% trans 'absent' %}{% endif %}">
<i class="{% if user.is_active %}icon-on{% else %}icon-off{% endif %}"></i>
</a>
{% endif %}
{% else %}
<span class="status_link">
<i class="status_link {% if user.is_active %}icon-on{% else %}icon-off{% endif %}"
title="{% if user.is_active %}{% trans 'present' %}{% else %}{% trans 'absent' %}{% endif %}"></i>
{% endif %}
</td>
<td><a href="{% url 'user_view' user.id %}">{{ user.first_name }}</a></td> <td><a href="{% url 'user_view' user.id %}">{{ user.first_name }}</a></td>
<td><a href="{% url 'user_view' user.id %}">{{ user.last_name }}</a></td> <td><a href="{% url 'user_view' user.id %}">{{ user.last_name }}</a></td>
<td class="optional">{{ user.structure_level }}</td> <td class="optional">{{ user.structure_level }}</td>
@ -137,13 +115,6 @@
<i class="icon-remove"></i> <i class="icon-remove"></i>
</a> </a>
{% endif %} {% endif %}
{% if user != request_user and not user.is_superuser %}
<a href="{% url 'user_status_toggle' user.id %}"
class="status_link btn btn-mini {% if user.is_active %}btn-success{% endif %}"
title="{% trans 'Change status (active/inactive)' %}">
<i class="{% if user.is_active %}icon-on{% else %}icon-off{% endif %}"></i>
</a>
{% endif %}
</span> </span>
</td> </td>
{% endif %} {% endif %}
@ -153,5 +124,6 @@
<td colspan="9"><i>{% trans "No participants available." %}</i></td> <td colspan="9"><i>{% trans "No participants available." %}</i></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody>
</table> </table>
{% endblock %} {% endblock %}

View File

@ -53,84 +53,20 @@ class UserOverview(ListView):
context_object_name = 'users' context_object_name = 'users'
def get_queryset(self): def get_queryset(self):
try:
sortfilter = encodedict(parse_qs(
self.request.COOKIES['participant_sortfilter']))
except KeyError:
sortfilter = {}
for value in ['gender', 'structure_level', 'type', 'committee', 'status',
'sort', 'reverse']:
if value in self.request.REQUEST:
if self.request.REQUEST[value] == '---':
try:
del sortfilter[value]
except KeyError:
pass
else:
sortfilter[value] = [self.request.REQUEST[value]]
query = User.objects query = User.objects
if 'gender' in sortfilter:
query = query.filter(gender__iexact=sortfilter['gender'][0])
if 'structure_level' in sortfilter:
query = query.filter(structure_level__iexact=sortfilter['structure_level'][0])
if 'type' in sortfilter:
query = query.filter(type__iexact=sortfilter['type'][0])
if 'committee' in sortfilter:
query = query.filter(committee__iexact=sortfilter['committee'][0])
if 'status' in sortfilter:
query = query.filter(is_active=sortfilter['status'][0])
if 'sort' in sortfilter:
if sortfilter['sort'][0] in ['first_name', 'last_name', 'last_login']:
query = query.order_by(sortfilter['sort'][0])
elif (sortfilter['sort'][0] in
['structure_level', 'type', 'committee', 'comment']):
query = query.order_by(
'%s' % sortfilter['sort'][0])
else:
if config['participant_sort_users_by_first_name']: if config['participant_sort_users_by_first_name']:
query = query.order_by('first_name') query = query.order_by('first_name')
else: else:
query = query.order_by('last_name') query = query.order_by('last_name')
if 'reverse' in sortfilter:
query = query.reverse()
self.sortfilter = sortfilter
return query.all() return query.all()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(UserOverview, self).get_context_data(**kwargs) context = super(UserOverview, self).get_context_data(**kwargs)
all_users = User.objects.count() all_users = User.objects.count()
# quotient of selected users and all users
if all_users > 0:
percent = self.object_list.count() * 100 / float(all_users)
else:
percent = 0
# list of all existing categories
structure_levels = [
p['structure_level'] for p in
User.objects.values('structure_level').exclude(structure_level='').distinct()]
# list of all existing committees
committees = [
p['committee'] for p in
User.objects.values('committee').exclude(committee='').distinct()]
# context vars # context vars
context.update({ context.update({
'allusers': all_users, 'allusers': all_users,
'request_user': self.request.user, 'request_user': self.request.user})
'percent': round(percent, 1),
'structure_levels': structure_levels,
'committees': committees,
'cookie': [
'participant_sortfilter', urlencode(decodedict(self.sortfilter),
doseq=True)],
'sortfilter': self.sortfilter})
return context return context
@ -343,6 +279,7 @@ class UserImportView(FormView):
permission_required = 'participant.can_manage_participant' permission_required = 'participant.can_manage_participant'
template_name = 'participant/import.html' template_name = 'participant/import.html'
form_class = UserImportForm form_class = UserImportForm
success_url_name = 'user_import'
def form_valid(self, form): def form_valid(self, form):
# check for valid encoding (will raise UnicodeDecodeError if not) # check for valid encoding (will raise UnicodeDecodeError if not)

View File

@ -0,0 +1,177 @@
/*!
* DataTables jquery plugin (for Twitter Bootstrap style)
*
* Copyright 2012
* DataTables is dual licensed under the GPL v2 license or a BSD (3-point) license.
* http://www.datatables.net
* http://www.datatables.net/blog/Twitter_Bootstrap_2
*
*/
/* Table initialisation */
$(document).ready(function() {
$('#dataTableParticipants').dataTable( {
"aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
"aoColumnDefs": [
{ "bSortable": false, "aTargets": [ -1 ] }
],
"oLanguage": {
"sLengthMenu": gettext("_MENU_ participants per page"),
"sSearch": gettext("Search:"),
"sInfo": gettext("Showing _START_ to _END_ of _TOTAL_ participants"),
"sInfoEmpty": gettext("Showing 0 participants"),
"sInfoFiltered": gettext("(filtered from _MAX_ total entries)"),
"sZeroRecords": gettext("No matching records found"),
"sFirst": gettext("First"),
"sLast": gettext("Last"),
"sNext": gettext("Next"),
"sPrevious": gettext("Previous"),
}
} );
} );
/* Set the defaults for DataTables initialisation */
$.extend( true, $.fn.dataTable.defaults, {
"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
"sPaginationType": "bootstrap",
} );
/* Default class modification */
$.extend( $.fn.dataTableExt.oStdClasses, {
"sWrapper": "dataTables_wrapper form-inline"
} );
/* API method to get paging information */
$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
{
return {
"iStart": oSettings._iDisplayStart,
"iEnd": oSettings.fnDisplayEnd(),
"iLength": oSettings._iDisplayLength,
"iTotal": oSettings.fnRecordsTotal(),
"iFilteredTotal": oSettings.fnRecordsDisplay(),
"iPage": oSettings._iDisplayLength === -1 ?
0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
"iTotalPages": oSettings._iDisplayLength === -1 ?
0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
};
};
/* Bootstrap style pagination control */
$.extend( $.fn.dataTableExt.oPagination, {
"bootstrap": {
"fnInit": function( oSettings, nPaging, fnDraw ) {
var oLang = oSettings.oLanguage.oPaginate;
var fnClickHandler = function ( e ) {
e.preventDefault();
if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {
fnDraw( oSettings );
}
};
$(nPaging).addClass('pagination').append(
'<ul>'+
'<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+
'<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+
'</ul>'
);
var els = $('a', nPaging);
$(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
$(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
},
"fnUpdate": function ( oSettings, fnDraw ) {
var iListLength = 5;
var oPaging = oSettings.oInstance.fnPagingInfo();
var an = oSettings.aanFeatures.p;
var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
if ( oPaging.iTotalPages < iListLength) {
iStart = 1;
iEnd = oPaging.iTotalPages;
}
else if ( oPaging.iPage <= iHalf ) {
iStart = 1;
iEnd = iListLength;
} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
iStart = oPaging.iTotalPages - iListLength + 1;
iEnd = oPaging.iTotalPages;
} else {
iStart = oPaging.iPage - iHalf + 1;
iEnd = iStart + iListLength - 1;
}
for ( i=0, ien=an.length ; i<ien ; i++ ) {
// Remove the middle elements
$('li:gt(0)', an[i]).filter(':not(:last)').remove();
// Add the new list items and their event handlers
for ( j=iStart ; j<=iEnd ; j++ ) {
sClass = (j==oPaging.iPage+1) ? 'class="active"' : '';
$('<li '+sClass+'><a href="#">'+j+'</a></li>')
.insertBefore( $('li:last', an[i])[0] )
.bind('click', function (e) {
e.preventDefault();
oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
fnDraw( oSettings );
} );
}
// Add / remove disabled classes from the static elements
if ( oPaging.iPage === 0 ) {
$('li:first', an[i]).addClass('disabled');
} else {
$('li:first', an[i]).removeClass('disabled');
}
if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
$('li:last', an[i]).addClass('disabled');
} else {
$('li:last', an[i]).removeClass('disabled');
}
}
}
}
} );
/*
* TableTools Bootstrap compatibility
* Required TableTools 2.1+
*/
if ( $.fn.DataTable.TableTools ) {
// Set the classes that TableTools uses to something suitable for Bootstrap
$.extend( true, $.fn.DataTable.TableTools.classes, {
"container": "DTTT btn-group",
"buttons": {
"normal": "btn",
"disabled": "disabled"
},
"collection": {
"container": "DTTT_dropdown dropdown-menu",
"buttons": {
"normal": "",
"disabled": "disabled"
}
},
"print": {
"info": "DTTT_print_info modal"
},
"select": {
"row": "active"
}
} );
// Have the collection use a bootstrap compatible dropdown
$.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
"collection": {
"container": "ul",
"button": "li",
"liner": "a"
}
} );
}

View File

@ -0,0 +1,155 @@
/*
* File: jquery.dataTables.min.js
* Version: 1.9.4
* Author: Allan Jardine (www.sprymedia.co.uk)
* Info: www.datatables.net
*
* Copyright 2008-2012 Allan Jardine, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, available at:
* http://datatables.net/license_gpl2
* http://datatables.net/license_bsd
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
*/
(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=
L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==
h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function G(a,b){var c=r(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function R(a,b){var c=r(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function t(a){return r(a,"bVisible").length}
function r(a,b){var c=[];h.map(a.aoColumns,function(a,i){a[b]&&c.push(i)});return c}function B(a){for(var b=j.ext.aTypes,c=b.length,d=0;d<c;d++){var i=b[d](a);if(null!==i)return i}return"string"}function u(a,b){for(var c=b.split(","),d=[],i=0,f=a.aoColumns.length;i<f;i++)for(var g=0;g<f;g++)if(a.aoColumns[i].sName==c[g]){d.push(g);break}return d}function M(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";return b.length==d?"":b.slice(0,-1)}function ta(a,b,c,d){var i,f,
g,e,w;if(b)for(i=b.length-1;0<=i;i--){var j=b[i].aTargets;h.isArray(j)||D(a,1,"aTargets must be an array of targets, not a "+typeof j);f=0;for(g=j.length;f<g;f++)if("number"===typeof j[f]&&0<=j[f]){for(;a.aoColumns.length<=j[f];)o(a);d(j[f],b[i])}else if("number"===typeof j[f]&&0>j[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;e<w;e++)("_all"==j[f]||h(a.aoColumns[e].nTh).hasClass(j[f]))&&d(e,b[i])}}if(c){i=0;for(a=c.length;i<a;i++)d(i,c[i])}}function H(a,
b){var c;c=h.isArray(b)?b.slice():h.extend(!0,{},b);var d=a.aoData.length,i=h.extend(!0,{},j.models.oRow);i._aData=c;a.aoData.push(i);for(var f,i=0,g=a.aoColumns.length;i<g;i++)c=a.aoColumns[i],"function"===typeof c.fnRender&&c.bUseRendered&&null!==c.mData?F(a,d,i,S(a,d,i)):F(a,d,i,v(a,d,i)),c._bAutoType&&"string"!=c.sType&&(f=v(a,d,i,"type"),null!==f&&""!==f&&(f=B(f),null===c.sType?c.sType=f:c.sType!=f&&"html"!=c.sType&&(c.sType="string")));a.aiDisplayMaster.push(d);a.oFeatures.bDeferRender||ea(a,
d);return d}function ua(a){var b,c,d,i,f,g,e;if(a.bDeferLoading||null===a.sAjaxSource)for(b=a.nTBody.firstChild;b;){if("TR"==b.nodeName.toUpperCase()){c=a.aoData.length;b._DT_RowIndex=c;a.aoData.push(h.extend(!0,{},j.models.oRow,{nTr:b}));a.aiDisplayMaster.push(c);f=b.firstChild;for(d=0;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)F(a,c,d,h.trim(f.innerHTML)),d++;f=f.nextSibling}}b=b.nextSibling}i=T(a);d=[];b=0;for(c=i.length;b<c;b++)for(f=i[b].firstChild;f;)g=f.nodeName.toUpperCase(),("TD"==
g||"TH"==g)&&d.push(f),f=f.nextSibling;c=0;for(i=a.aoColumns.length;c<i;c++){e=a.aoColumns[c];null===e.sTitle&&(e.sTitle=e.nTh.innerHTML);var w=e._bAutoType,o="function"===typeof e.fnRender,k=null!==e.sClass,n=e.bVisible,m,p;if(w||o||k||!n){g=0;for(b=a.aoData.length;g<b;g++)f=a.aoData[g],m=d[g*i+c],w&&"string"!=e.sType&&(p=v(a,g,c,"type"),""!==p&&(p=B(p),null===e.sType?e.sType=p:e.sType!=p&&"html"!=e.sType&&(e.sType="string"))),e.mRender?m.innerHTML=v(a,g,c,"display"):e.mData!==c&&(m.innerHTML=v(a,
g,c,"display")),o&&(p=S(a,g,c),m.innerHTML=p,e.bUseRendered&&F(a,g,c,p)),k&&(m.className+=" "+e.sClass),n?f._anHidden[c]=null:(f._anHidden[c]=m,m.parentNode.removeChild(m)),e.fnCreatedCell&&e.fnCreatedCell.call(a.oInstance,m,v(a,g,c,"display"),f._aData,g,c)}}if(0!==a.aoRowCreatedCallback.length){b=0;for(c=a.aoData.length;b<c;b++)f=a.aoData[b],A(a,"aoRowCreatedCallback",null,[f.nTr,f._aData,b])}}function I(a,b){return b._DT_RowIndex!==n?b._DT_RowIndex:null}function fa(a,b,c){for(var b=J(a,b),d=0,a=
a.aoColumns.length;d<a;d++)if(b[d]===c)return d;return-1}function Y(a,b,c,d){for(var i=[],f=0,g=d.length;f<g;f++)i.push(v(a,b,d[f],c));return i}function v(a,b,c,d){var i=a.aoColumns[c];if((c=i.fnGetData(a.aoData[b]._aData,d))===n)return a.iDrawError!=a.iDraw&&null===i.sDefaultContent&&(D(a,0,"Requested unknown parameter "+("function"==typeof i.mData?"{mData function}":"'"+i.mData+"'")+" from the data source for row "+b),a.iDrawError=a.iDraw),i.sDefaultContent;if(null===c&&null!==i.sDefaultContent)c=
i.sDefaultContent;else if("function"===typeof c)return c();return"display"==d&&null===c?"":c}function F(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d)}function Q(a){if(null===a)return function(){return null};if("function"===typeof a)return function(b,d,i){return a(b,d,i)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var f=i.split("."),g;if(""!==i){var e=0;for(g=f.length;e<g;e++){if(i=f[e].match(U)){f[e]=f[e].replace(U,"");""!==f[e]&&(a=a[f[e]]);
g=[];f.splice(0,e+1);for(var f=f.join("."),e=0,h=a.length;e<h;e++)g.push(b(a[e],d,f));a=i[0].substring(1,i[0].length-1);a=""===a?g:g.join(a);break}if(null===a||a[f[e]]===n)return n;a=a[f[e]]}}return a};return function(c,d){return b(c,d,a)}}return function(b){return b[a]}}function L(a){if(null===a)return function(){};if("function"===typeof a)return function(b,d){a(b,"set",d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var i=i.split("."),f,g,e=0;for(g=
i.length-1;e<g;e++){if(f=i[e].match(U)){i[e]=i[e].replace(U,"");a[i[e]]=[];f=i.slice();f.splice(0,e+1);g=f.join(".");for(var h=0,j=d.length;h<j;h++)f={},b(f,d[h],g),a[i[e]].push(f);return}if(null===a[i[e]]||a[i[e]]===n)a[i[e]]={};a=a[i[e]]}a[i[i.length-1].replace(U,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Z(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function ga(a){a.aoData.splice(0,a.aoData.length);a.aiDisplayMaster.splice(0,
a.aiDisplayMaster.length);a.aiDisplay.splice(0,a.aiDisplay.length);y(a)}function ha(a,b){for(var c=-1,d=0,i=a.length;d<i;d++)a[d]==b?c=d:a[d]>b&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&
(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i<f;i++){var g=a.aoColumns[i];d=l.createElement(g.sCellType);d.innerHTML="function"===typeof g.fnRender&&(!g.bUseRendered||null===g.mData)?S(a,b,i):v(a,b,i,"display");null!==g.sClass&&(d.className=g.sClass);g.bVisible?(c.nTr.appendChild(d),c._anHidden[i]=null):c._anHidden[i]=d;g.fnCreatedCell&&g.fnCreatedCell.call(a.oInstance,d,v(a,b,i,"display"),c._aData,b,i)}A(a,"aoRowCreatedCallback",null,[c.nTr,c._aData,b])}}function va(a){var b,
c,d;if(0!==h("th, td",a.nTHead).length){b=0;for(d=a.aoColumns.length;b<d;b++)if(c=a.aoColumns[b].nTh,c.setAttribute("role","columnheader"),a.aoColumns[b].bSortable&&(c.setAttribute("tabindex",a.iTabIndex),c.setAttribute("aria-controls",a.sTableId)),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{var i=l.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++)c=a.aoColumns[b].nTh,c.innerHTML=a.aoColumns[b].sTitle,
c.setAttribute("tabindex","0"),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),i.appendChild(c);h(a.nTHead).html("")[0].appendChild(i);V(a.aoHeader,a.nTHead)}h(a.nTHead).children("tr").attr("role","row");if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;i=l.createElement("div");i.className=a.oClasses.sSortJUIWrapper;h(c).contents().appendTo(i);var f=l.createElement("span");f.className=a.oClasses.sSortIcon;i.appendChild(f);c.appendChild(i)}}if(a.oFeatures.bSort)for(b=
0;b<a.aoColumns.length;b++)!1!==a.aoColumns[b].bSortable?ia(a,a.aoColumns[b].nTh,b):h(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone);""!==a.oClasses.sFooterTH&&h(a.nTFoot).children("tr").children("th").addClass(a.oClasses.sFooterTH);if(null!==a.nTFoot){c=N(a,null,a.aoFooter);b=0;for(d=a.aoColumns.length;b<d;b++)c[b]&&(a.aoColumns[b].nTf=c[b],a.aoColumns[b].sClass&&h(c[b]).addClass(a.aoColumns[b].sClass))}}function W(a,b,c){var d,i,f,g=[],e=[],h=a.aoColumns.length,j;c===n&&(c=!1);d=0;for(i=
b.length;d<i;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=h-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);e.push([])}d=0;for(i=g.length;d<i;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(j=h=1,e[d][f]===n){a.appendChild(g[d][f].cell);for(e[d][f]=1;g[d+h]!==n&&g[d][f].cell==g[d+h][f].cell;)e[d+h][f]=1,h++;for(;g[d][f+j]!==n&&g[d][f].cell==g[d][f+j].cell;){for(c=0;c<h;c++)e[d+c][f+j]=1;j++}g[d][f].cell.rowSpan=h;g[d][f].cell.colSpan=j}}}function x(a){var b=
A(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))E(a,!1);else{var c,d,b=[],i=0,f=a.asStripeClasses.length;c=a.aoOpenRows.length;a.bDrawing=!0;a.iInitDisplayStart!==n&&-1!=a.iInitDisplayStart&&(a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g=
a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g<d;g++){var e=a.aoData[a.aiDisplay[g]];null===e.nTr&&ea(a,a.aiDisplay[g]);var j=e.nTr;if(0!==f){var o=a.asStripeClasses[i%f];e._sRowStripe!=o&&(h(j).removeClass(e._sRowStripe).addClass(o),e._sRowStripe=o)}A(a,"aoRowCallback",null,[j,a.aoData[a.aiDisplay[g]]._aData,i,g]);b.push(j);i++;if(0!==c)for(e=0;e<c;e++)if(j==a.aoOpenRows[e].nParent){b.push(a.aoOpenRows[e].nTr);break}}}else b[0]=l.createElement("tr"),a.asStripeClasses[0]&&
(b[0].className=a.asStripeClasses[0]),c=a.oLanguage,f=c.sZeroRecords,1==a.iDraw&&null!==a.sAjaxSource&&!a.oFeatures.bServerSide?f=c.sLoadingRecords:c.sEmptyTable&&0===a.fnRecordsTotal()&&(f=c.sEmptyTable),c=l.createElement("td"),c.setAttribute("valign","top"),c.colSpan=t(a),c.className=a.oClasses.sRowEmpty,c.innerHTML=ja(a,f),b[i].appendChild(c);A(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);A(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],
Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);i=l.createDocumentFragment();c=l.createDocumentFragment();if(a.nTBody){f=a.nTBody.parentNode;c.appendChild(a.nTBody);if(!a.oScroll.bInfinite||!a._bInitComplete||a.bSorted||a.bFiltered)for(;c=a.nTBody.firstChild;)a.nTBody.removeChild(c);c=0;for(d=b.length;c<d;c++)i.appendChild(b[c]);a.nTBody.appendChild(i);null!==f&&f.appendChild(a.nTBody)}A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1;a.oFeatures.bServerSide&&(E(a,!1),
a._bInitComplete||$(a))}}function aa(a){a.oFeatures.bSort?O(a,a.oPreviousSearch):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(y(a),x(a))}function xa(a){var b=h("<div></div>")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('<div id="'+a.sTableId+'_wrapper" class="'+a.oClasses.sWrapper+'" role="grid"></div>')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m<d.length;m++){f=0;g=d[m];if("<"==g){e=h("<div></div>")[0];w=d[m+
1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f=
1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k<w;k++)if(g==e[k].cFeature){(i=e[k].fnInit(a))&&(f=1);break}}1==f&&null!==i&&("object"!==typeof a.aanFeatures[g]&&(a.aanFeatures[g]=[]),a.aanFeatures[g].push(i),c.appendChild(i))}b.parentNode.replaceChild(a.nTableWrapper,b)}function V(a,b){var c=h(b).children("tr"),d,i,f,g,e,j,o,k,m,p;a.splice(0,a.length);
f=0;for(j=c.length;f<j;f++)a.push([]);f=0;for(j=c.length;f<j;f++){d=c[f];for(i=d.firstChild;i;){if("TD"==i.nodeName.toUpperCase()||"TH"==i.nodeName.toUpperCase()){k=1*i.getAttribute("colspan");m=1*i.getAttribute("rowspan");k=!k||0===k||1===k?1:k;m=!m||0===m||1===m?1:m;g=0;for(e=a[f];e[g];)g++;o=g;p=1===k?!0:!1;for(e=0;e<k;e++)for(g=0;g<m;g++)a[f+g][o+e]={cell:i,unique:p},a[f+g].nTr=d}i=i.nextSibling}}}function N(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],V(c,b)));for(var b=0,i=c.length;b<i;b++)for(var f=
0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function wa(a){if(a.bAjaxDataGet){a.iDraw++;E(a,!0);var b=Ea(a);ka(a,b);a.fnServerData.call(a.oInstance,a.sAjaxSource,b,function(b){Fa(a,b)},a);return!1}return!0}function Ea(a){var b=a.aoColumns.length,c=[],d,i,f,g;c.push({name:"sEcho",value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:M(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength",
value:!1!==a.oFeatures.bPaginate?a._iDisplayLength:-1});for(f=0;f<b;f++)d=a.aoColumns[f].mData,c.push({name:"mDataProp_"+f,value:"function"===typeof d?"function":d});if(!1!==a.oFeatures.bFilter){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(f=0;f<b;f++)c.push({name:"sSearch_"+f,value:a.aoPreSearchCols[f].sSearch}),c.push({name:"bRegex_"+f,value:a.aoPreSearchCols[f].bRegex}),c.push({name:"bSearchable_"+f,value:a.aoColumns[f].bSearchable})}if(!1!==
a.oFeatures.bSort){var e=0;d=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(f=0;f<d.length;f++){i=a.aoColumns[d[f][0]].aDataSort;for(g=0;g<i.length;g++)c.push({name:"iSortCol_"+e,value:i[g]}),c.push({name:"sSortDir_"+e,value:d[f][1]}),e++}c.push({name:"iSortingCols",value:e});for(f=0;f<b;f++)c.push({name:"bSortable_"+f,value:a.aoColumns[f].bSortable})}return c}function ka(a,b){A(a,"aoServerParams","serverParams",[b])}function Fa(a,b){if(b.sEcho!==n){if(1*b.sEcho<
a.iDraw)return;a.iDraw=1*b.sEcho}(!a.oScroll.bInfinite||a.oScroll.bInfinite&&(a.bSorted||a.bFiltered))&&ga(a);a._iRecordsTotal=parseInt(b.iTotalRecords,10);a._iRecordsDisplay=parseInt(b.iTotalDisplayRecords,10);var c=M(a),c=b.sColumns!==n&&""!==c&&b.sColumns!=c,d;c&&(d=u(a,b.sColumns));for(var i=Q(a.sAjaxDataProp)(b),f=0,g=i.length;f<g;f++)if(c){for(var e=[],h=0,j=a.aoColumns.length;h<j;h++)e.push(i[f][d[h]]);H(a,e)}else H(a,i[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;x(a);a.bAjaxDataGet=
!0;E(a,!1)}function za(a){var b=a.oPreviousSearch,c=a.oLanguage.sSearch,c=-1!==c.indexOf("_INPUT_")?c.replace("_INPUT_",'<input type="text" />'):""===c?'<input type="text" />':c+' <input type="text" />',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="<label>"+c+"</label>";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"&quot;"));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,
g=0,e=c.length;g<e;g++)c[g]!=h(this).parents("div.dataTables_filter")[0]&&h(c[g]._DT_Input).val(d);d!=b.sSearch&&K(a,{sSearch:d,bRegex:b.bRegex,bSmart:b.bSmart,bCaseInsensitive:b.bCaseInsensitive})});c.attr("aria-controls",a.sTableId).bind("keypress.DT",function(a){if(a.keyCode==13)return false});return d}function K(a,b,c){var d=a.oPreviousSearch,i=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};if(a.oFeatures.bServerSide)f(b);
else{Ga(a,b.sSearch,c,b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<a.aoPreSearchCols.length;b++)Ha(a,i[b].sSearch,b,i[b].bRegex,i[b].bSmart,i[b].bCaseInsensitive);Ia(a)}a.bFiltered=!0;h(a.oInstance).trigger("filter",a);a._iDisplayStart=0;y(a);x(a);la(a,0)}function Ia(a){for(var b=j.ext.afnFiltering,c=r(a,"bSearchable"),d=0,i=b.length;d<i;d++)for(var f=0,g=0,e=a.aiDisplay.length;g<e;g++){var h=a.aiDisplay[g-f];b[d](a,Y(a,h,"filter",c),h)||(a.aiDisplay.splice(g-f,1),f++)}}function Ha(a,b,c,
d,i,f){if(""!==b)for(var g=0,b=ma(b,d,i,f),d=a.aiDisplay.length-1;0<=d;d--)i=Ja(v(a,a.aiDisplay[d],c,"filter"),a.aoColumns[c].sType),b.test(i)||(a.aiDisplay.splice(d,1),g++)}function Ga(a,b,c,d,i,f){d=ma(b,d,i,f);i=a.oPreviousSearch;c||(c=0);0!==j.ext.afnFiltering.length&&(c=1);if(0>=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0,
a.aiDisplay.length);la(a,1);for(b=0;b<a.aiDisplayMaster.length;b++)d.test(a.asDataSearch[b])&&a.aiDisplay.push(a.aiDisplayMaster[b])}else for(b=c=0;b<a.asDataSearch.length;b++)d.test(a.asDataSearch[b])||(a.aiDisplay.splice(b-c,1),c++)}function la(a,b){if(!a.oFeatures.bServerSide){a.asDataSearch=[];for(var c=r(a,"bSearchable"),d=1===b?a.aiDisplayMaster:a.aiDisplay,i=0,f=d.length;i<f;i++)a.asDataSearch[i]=na(a,Y(a,d[i],"filter",c))}}function na(a,b){var c=b.join(" ");-1!==c.indexOf("&")&&(c=h("<div>").html(c).text());
return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),
"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g);
null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b<c;b++)h(a[b]).html(g)}}function ja(a,b){var c=a.fnFormatNumber(a._iDisplayStart+1),d=a.fnDisplayEnd(),d=a.fnFormatNumber(d),i=a.fnRecordsDisplay(),i=a.fnFormatNumber(i),f=a.fnRecordsTotal(),f=a.fnFormatNumber(f);a.oScroll.bInfinite&&(c=a.fnFormatNumber(1));return b.replace(/_START_/g,c).replace(/_END_/g,d).replace(/_TOTAL_/g,i).replace(/_MAX_/g,f)}function ba(a){var b,c,d=a.iInitDisplayStart;
if(!1===a.bInitialised)setTimeout(function(){ba(a)},200);else{xa(a);va(a);W(a,a.aoHeader);a.nTFoot&&W(a,a.aoFooter);E(a,!0);a.oFeatures.bAutoWidth&&da(a);b=0;for(c=a.aoColumns.length;b<c;b++)null!==a.aoColumns[b].sWidth&&(a.aoColumns[b].nTh.style.width=q(a.aoColumns[b].sWidth));a.oFeatures.bSort?O(a):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(a.aiDisplay=a.aiDisplayMaster.slice(),y(a),x(a));null!==a.sAjaxSource&&!a.oFeatures.bServerSide?(c=[],ka(a,c),a.fnServerData.call(a.oInstance,a.sAjaxSource,
c,function(c){var f=a.sAjaxDataProp!==""?Q(a.sAjaxDataProp)(c):c;for(b=0;b<f.length;b++)H(a,f[b]);a.iInitDisplayStart=d;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();y(a);x(a)}E(a,false);$(a,c)},a)):a.oFeatures.bServerSide||(E(a,!1),$(a))}}function $(a,b){a._bInitComplete=!0;A(a,"aoInitComplete","init",[a,b])}function pa(a){var b=j.defaults.oLanguage;!a.sEmptyTable&&(a.sZeroRecords&&"No data available in table"===b.sEmptyTable)&&p(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&
(a.sZeroRecords&&"Loading..."===b.sLoadingRecords)&&p(a,a,"sZeroRecords","sLoadingRecords")}function ya(a){if(a.oScroll.bInfinite)return null;var b='<select size="1" '+('name="'+a.sTableId+'_length"')+">",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c<d;c++)b+='<option value="'+i[0][c]+'">'+i[1][c]+"</option>"}else{c=0;for(d=i.length;c<d;c++)b+='<option value="'+i[c]+'">'+i[c]+"</option>"}b+="</select>";i=l.createElement("div");a.aanFeatures.l||
(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="<label>"+a.oLanguage.sLengthMenu.replace("_MENU_",b)+"</label>";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&h("select",i[c]).val(b);a._iDisplayLength=parseInt(b,10);y(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart<
0)a._iDisplayStart=0}if(a._iDisplayLength==-1)a._iDisplayStart=0;x(a)});h("select",i).attr("aria-controls",a.sTableId);return i}function y(a){a._iDisplayEnd=!1===a.oFeatures.bPaginate?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a,
b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=
0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay()&&(a._iDisplayStart+=a._iDisplayLength):a._iDisplayStart=0;else if("last"==b)if(0<=a._iDisplayLength){var d=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(d-1)*a._iDisplayLength}else a._iDisplayStart=0;else D(a,0,"Unknown paging action: "+b);h(a.oInstance).trigger("page",a);return c!=a._iDisplayStart}function Aa(a){var b=l.createElement("div");a.aanFeatures.r||(b.id=a.sTableId+
"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function E(a,b){if(a.oFeatures.bProcessing)for(var c=a.aanFeatures.r,d=0,i=c.length;d<i;d++)c[d].style.visibility=b?"visible":"hidden";h(a.oInstance).trigger("processing",[a,b])}function Ba(a){if(""===a.oScroll.sX&&""===a.oScroll.sY)return a.nTable;var b=l.createElement("div"),c=l.createElement("div"),d=l.createElement("div"),i=l.createElement("div"),f=l.createElement("div"),
g=l.createElement("div"),e=a.nTable.cloneNode(!1),j=a.nTable.cloneNode(!1),o=a.nTable.getElementsByTagName("thead")[0],k=0===a.nTable.getElementsByTagName("tfoot").length?null:a.nTable.getElementsByTagName("tfoot")[0],m=a.oClasses;c.appendChild(d);f.appendChild(g);i.appendChild(a.nTable);b.appendChild(c);b.appendChild(i);d.appendChild(e);e.appendChild(o);null!==k&&(b.appendChild(f),g.appendChild(j),j.appendChild(k));b.className=m.sScrollWrapper;c.className=m.sScrollHead;d.className=m.sScrollHeadInner;
i.className=m.sScrollBody;f.className=m.sScrollFoot;g.className=m.sScrollFootInner;a.oScroll.bAutoCss&&(c.style.overflow="hidden",c.style.position="relative",f.style.overflow="hidden",i.style.overflow="auto");c.style.border="0";c.style.width="100%";f.style.border="0";d.style.width=""!==a.oScroll.sXInner?a.oScroll.sXInner:"100%";e.removeAttribute("id");e.style.marginLeft="0";a.nTable.style.marginLeft="0";null!==k&&(j.removeAttribute("id"),j.style.marginLeft="0");d=h(a.nTable).children("caption");0<
d.length&&(d=d[0],"top"===d._captionSide?e.appendChild(d):"bottom"===d._captionSide&&k&&j.appendChild(d));""!==a.oScroll.sX&&(c.style.width=q(a.oScroll.sX),i.style.width=q(a.oScroll.sX),null!==k&&(f.style.width=q(a.oScroll.sX)),h(i).scroll(function(){c.scrollLeft=this.scrollLeft;if(k!==null)f.scrollLeft=this.scrollLeft}));""!==a.oScroll.sY&&(i.style.height=q(a.oScroll.sY));a.aoDrawCallback.push({fn:La,sName:"scrolling"});a.oScroll.bInfinite&&h(i).scroll(function(){if(!a.bDrawing&&h(this).scrollTop()!==
0&&h(this).scrollTop()+h(this).height()>h(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()<a.fnRecordsDisplay()){qa(a,"next");y(a);x(a)}});a.nScrollHead=c;a.nScrollFoot=f;return b}function La(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],d=a.nTable.parentNode,i,f,g,e,j,o,k,m,p=[],n=[],l=null!==a.nTFoot?a.nScrollFoot.getElementsByTagName("div")[0]:null,R=null!==a.nTFoot?l.getElementsByTagName("table")[0]:null,r=a.oBrowser.bScrollOversize,s=function(a){k=
a.style;k.paddingTop="0";k.paddingBottom="0";k.borderTopWidth="0";k.borderBottomWidth="0";k.height=0};h(a.nTable).children("thead, tfoot").remove();i=h(a.nTHead).clone()[0];a.nTable.insertBefore(i,a.nTable.childNodes[0]);g=a.nTHead.getElementsByTagName("tr");e=i.getElementsByTagName("tr");null!==a.nTFoot&&(j=h(a.nTFoot).clone()[0],a.nTable.insertBefore(j,a.nTable.childNodes[1]),o=a.nTFoot.getElementsByTagName("tr"),j=j.getElementsByTagName("tr"));""===a.oScroll.sX&&(d.style.width="100%",b.parentNode.style.width=
"100%");var t=N(a,i);i=0;for(f=t.length;i<f;i++)m=G(a,i),t[i].style.width=a.aoColumns[m].sWidth;null!==a.nTFoot&&C(function(a){a.style.width=""},j);a.oScroll.bCollapse&&""!==a.oScroll.sY&&(d.style.height=d.offsetHeight+a.nTHead.offsetHeight+"px");i=h(a.nTable).outerWidth();if(""===a.oScroll.sX){if(a.nTable.style.width="100%",r&&(h("tbody",d).height()>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=
q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()<h(a.nTable).height()?(a.nTable.style.width=q(i-a.oScroll.iBarWidth),h(a.nTable).outerWidth()>i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML=
"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()<i){g=d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):
""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth>
d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeight<d.offsetHeight&&(d.style.height=q(a.nTable.offsetHeight+r)));r=h(a.nTable).outerWidth();c.style.width=q(r);b.style.width=q(r);c=h(a.nTable).height()>d.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d=
0,i=0,f=b.length,g,e;i<f;){g=b[i].firstChild;for(e=c?c[i].firstChild:null;g;)1===g.nodeType&&(c?a(g,e,d):a(g,d),d++),g=g.nextSibling,e=c?e.nextSibling:null;i++}}function Ma(a,b){if(!a||null===a||""===a)return 0;b||(b=l.body);var c,d=l.createElement("div");d.style.width=q(a);b.appendChild(d);c=d.offsetWidth;b.removeChild(d);return c}function da(a){var b=0,c,d=0,i=a.aoColumns.length,f,e,j=h("th",a.nTHead),o=a.nTable.getAttribute("width");e=a.nTable.parentNode;for(f=0;f<i;f++)a.aoColumns[f].bVisible&&
(d++,null!==a.aoColumns[f].sWidth&&(c=Ma(a.aoColumns[f].sWidthOrig,e),null!==c&&(a.aoColumns[f].sWidth=q(c)),b++));if(i==j.length&&0===b&&d==i&&""===a.oScroll.sX&&""===a.oScroll.sY)for(f=0;f<a.aoColumns.length;f++)c=h(j[f]).width(),null!==c&&(a.aoColumns[f].sWidth=q(c));else{b=a.nTable.cloneNode(!1);f=a.nTHead.cloneNode(!0);d=l.createElement("tbody");c=l.createElement("tr");b.removeAttribute("id");b.appendChild(f);null!==a.nTFoot&&(b.appendChild(a.nTFoot.cloneNode(!0)),C(function(a){a.style.width=
""},b.getElementsByTagName("tr")));b.appendChild(d);d.appendChild(c);d=h("thead th",b);0===d.length&&(d=h("tbody tr:eq(0)>td",b));j=N(a,f);for(f=d=0;f<i;f++){var k=a.aoColumns[f];k.bVisible&&null!==k.sWidthOrig&&""!==k.sWidthOrig?j[f-d].style.width=q(k.sWidthOrig):k.bVisible?j[f-d].style.width="":d++}for(f=0;f<i;f++)a.aoColumns[f].bVisible&&(d=Na(a,f),null!==d&&(d=d.cloneNode(!0),""!==a.aoColumns[f].sContentPadding&&(d.innerHTML+=a.aoColumns[f].sContentPadding),c.appendChild(d)));e.appendChild(b);
""!==a.oScroll.sX&&""!==a.oScroll.sXInner?b.style.width=q(a.oScroll.sXInner):""!==a.oScroll.sX?(b.style.width="",h(b).width()<e.offsetWidth&&(b.style.width=q(e.offsetWidth))):""!==a.oScroll.sY?b.style.width=q(e.offsetWidth):o&&(b.style.width=q(o));b.style.visibility="hidden";Oa(a,b);i=h("tbody tr:eq(0)",b).children();0===i.length&&(i=N(a,h("thead",b)[0]));if(""!==a.oScroll.sX){for(f=d=e=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=null===a.aoColumns[f].sWidthOrig?e+h(i[d]).outerWidth():
e+(parseInt(a.aoColumns[f].sWidth.replace("px",""),10)+(h(i[d]).outerWidth()-h(i[d]).width())),d++);b.style.width=q(e);a.nTable.style.width=q(e)}for(f=d=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=h(i[d]).width(),null!==e&&0<e&&(a.aoColumns[f].sWidth=q(e)),d++);i=h(b).css("width");a.nTable.style.width=-1!==i.indexOf("%")?i:q(h(b).outerWidth());b.parentNode.removeChild(b)}o&&(a.nTable.style.width=q(o))}function Oa(a,b){""===a.oScroll.sX&&""!==a.oScroll.sY?(h(b).width(),b.style.width=q(h(b).outerWidth()-
a.oScroll.iBarWidth)):""!==a.oScroll.sX&&(b.style.width=q(h(b).outerWidth()))}function Na(a,b){var c=Pa(a,b);if(0>c)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i<a.aoData.length;i++){var e=v(a,i,b,"display")+"",e=e.replace(/<.*?>/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);
return 48>b||57<b?a:a+"px"}function Qa(){var a=l.createElement("p"),b=a.style;b.width="100%";b.height="200px";b.padding="0px";var c=l.createElement("div"),b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.padding="0px";b.overflow="hidden";c.appendChild(a);l.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;b==a&&(a=c.clientWidth);l.body.removeChild(c);return b-a}function O(a,b){var c,d,i,e,g,k,o=[],m=[],p=
j.ext.oSort,l=a.aoData,q=a.aoColumns,G=a.oLanguage.oAria;if(!a.oFeatures.bServerSide&&(0!==a.aaSorting.length||null!==a.aaSortingFixed)){o=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(c=0;c<o.length;c++)if(d=o[c][0],i=R(a,d),e=a.aoColumns[d].sSortDataType,j.ext.afnSortData[e])if(g=j.ext.afnSortData[e].call(a.oInstance,a,d,i),g.length===l.length){i=0;for(e=l.length;i<e;i++)F(a,i,d,g[i])}else D(a,0,"Returned data sort array (col "+d+") is the wrong length");c=
0;for(d=a.aiDisplayMaster.length;c<d;c++)m[a.aiDisplayMaster[c]]=c;var r=o.length,s;c=0;for(d=l.length;c<d;c++)for(i=0;i<r;i++){s=q[o[i][0]].aDataSort;g=0;for(k=s.length;g<k;g++)e=q[s[g]].sType,e=p[(e?e:"string")+"-pre"],l[c]._aSortData[s[g]]=e?e(v(a,c,s[g],"sort")):v(a,c,s[g],"sort")}a.aiDisplayMaster.sort(function(a,b){var c,d,e,i,f;for(c=0;c<r;c++){f=q[o[c][0]].aDataSort;d=0;for(e=f.length;d<e;d++)if(i=q[f[d]].sType,i=p[(i?i:"string")+"-"+o[c][1]](l[a]._aSortData[f[d]],l[b]._aSortData[f[d]]),0!==
i)return i}return p["numeric-asc"](m[a],m[b])})}(b===n||b)&&!a.oFeatures.bDeferRender&&P(a);c=0;for(d=a.aoColumns.length;c<d;c++)e=q[c].sTitle.replace(/<.*?>/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0<o.length&&o[0][0]==c?(i.setAttribute("aria-sort","asc"==o[0][1]?"ascending":"descending"),i.setAttribute("aria-label",e+("asc"==(q[c].asSorting[o[0][2]+1]?q[c].asSorting[o[0][2]+1]:q[c].asSorting[0])?G.sSortAscending:G.sSortDescending))):i.setAttribute("aria-label",
e+("asc"==q[c].asSorting[0]?G.sSortAscending:G.sSortDescending)):i.setAttribute("aria-label",e);a.bSorted=!0;h(a.oInstance).trigger("sort",a);a.oFeatures.bFilter?K(a,a.oPreviousSearch,1):(a.aiDisplay=a.aiDisplayMaster.slice(),a._iDisplayStart=0,y(a),x(a))}function ia(a,b,c,d){Ra(b,{},function(b){if(!1!==a.aoColumns[c].bSortable){var e=function(){var d,e;if(b.shiftKey){for(var f=!1,h=0;h<a.aaSorting.length;h++)if(a.aaSorting[h][0]==c){f=!0;d=a.aaSorting[h][0];e=a.aaSorting[h][2]+1;a.aoColumns[d].asSorting[e]?
(a.aaSorting[h][1]=a.aoColumns[d].asSorting[e],a.aaSorting[h][2]=e):a.aaSorting.splice(h,1);break}!1===f&&a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}else 1==a.aaSorting.length&&a.aaSorting[0][0]==c?(d=a.aaSorting[0][0],e=a.aaSorting[0][2]+1,a.aoColumns[d].asSorting[e]||(e=0),a.aaSorting[0][1]=a.aoColumns[d].asSorting[e],a.aaSorting[0][2]=e):(a.aaSorting.splice(0,a.aaSorting.length),a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0]));O(a)};a.oFeatures.bProcessing?(E(a,!0),setTimeout(function(){e();
a.oFeatures.bServerSide||E(a,!1)},0)):e();"function"==typeof d&&d(a)}})}function P(a){var b,c,d,e,f,g=a.aoColumns.length,j=a.oClasses;for(b=0;b<g;b++)a.aoColumns[b].bSortable&&h(a.aoColumns[b].nTh).removeClass(j.sSortAsc+" "+j.sSortDesc+" "+a.aoColumns[b].sSortingClass);c=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){f=a.aoColumns[b].sSortingClass;e=-1;for(d=0;d<c.length;d++)if(c[d][0]==b){f="asc"==c[d][1]?
j.sSortAsc:j.sSortDesc;e=d;break}h(a.aoColumns[b].nTh).addClass(f);a.bJUI&&(f=h("span."+j.sSortIcon,a.aoColumns[b].nTh),f.removeClass(j.sSortJUIAsc+" "+j.sSortJUIDesc+" "+j.sSortJUI+" "+j.sSortJUIAscAllowed+" "+j.sSortJUIDescAllowed),f.addClass(-1==e?a.aoColumns[b].sSortingClassJUI:"asc"==c[e][1]?j.sSortJUIAsc:j.sSortJUIDesc))}else h(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);f=j.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){a=J(a);e=[];for(b=0;b<g;b++)e.push("");b=0;
for(d=1;b<c.length;b++)j=parseInt(c[b][0],10),e[j]=f+d,3>d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b<c;b++)j=b%g,d=a[b].className,o=e[j],j=d.replace(f,o),j!=d?a[b].className=h.trim(j):0<o.length&&-1==d.indexOf(o)&&(a[b].className=d+" "+o)}}function ra(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b,c;b=a.oScroll.bInfinite;var d={iCreate:(new Date).getTime(),iStart:b?0:a._iDisplayStart,iEnd:b?a._iDisplayLength:a._iDisplayEnd,iLength:a._iDisplayLength,aaSorting:h.extend(!0,[],a.aaSorting),
oSearch:h.extend(!0,{},a.oPreviousSearch),aoSearchCols:h.extend(!0,[],a.aoPreSearchCols),abVisCols:[]};b=0;for(c=a.aoColumns.length;b<c;b++)d.abVisCols.push(a.aoColumns[b].bVisible);A(a,"aoStateSaveParams","stateSaveParams",[a,d]);a.fnStateSave.call(a.oInstance,a,d)}}function Sa(a,b){if(a.oFeatures.bStateSave){var c=a.fnStateLoad.call(a.oInstance,a);if(c){var d=A(a,"aoStateLoadParams","stateLoadParams",[a,c]);if(-1===h.inArray(!1,d)){a.oLoadedState=h.extend(!0,{},c);a._iDisplayStart=c.iStart;a.iInitDisplayStart=
c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();h.extend(a.oPreviousSearch,c.oSearch);h.extend(!0,a.aoPreSearchCols,c.aoSearchCols);b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++)b.saved_aoColumns[d]={},b.saved_aoColumns[d].bVisible=c.abVisCols[d];A(a,"aoStateLoaded","stateLoaded",[a,c])}}}}function s(a){for(var b=0;b<j.settings.length;b++)if(j.settings[b].nTable===a)return j.settings[b];return null}function T(a){for(var b=
[],a=a.aoData,c=0,d=a.length;c<d;c++)null!==a[c].nTr&&b.push(a[c].nTr);return b}function J(a,b){var c=[],d,e,f,g,h,j;e=0;var o=a.aoData.length;b!==n&&(e=b,o=b+1);for(f=e;f<o;f++)if(j=a.aoData[f],null!==j.nTr){e=[];for(d=j.nTr.firstChild;d;)g=d.nodeName.toLowerCase(),("td"==g||"th"==g)&&e.push(d),d=d.nextSibling;g=d=0;for(h=a.aoColumns.length;g<h;g++)a.aoColumns[g].bVisible?c.push(e[g-d]):(c.push(j._anHidden[g]),d++)}return c}function D(a,b,c){a=null===a?"DataTables warning: "+c:"DataTables warning (table id = '"+
a.sTableId+"'): "+c;if(0===b)if("alert"==j.ext.sErrMode)alert(a);else throw Error(a);else X.console&&console.log&&console.log(a)}function p(a,b,c,d){d===n&&(d=c);b[c]!==n&&(a[d]=b[c])}function Ta(a,b){var c,d;for(d in b)b.hasOwnProperty(d)&&(c=b[d],"object"===typeof e[d]&&null!==c&&!1===h.isArray(c)?h.extend(!0,a[d],c):a[d]=c);return a}function Ra(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&c(a)}).bind("selectstart.DT",function(){return!1})}
function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function A(a,b,c,d){for(var b=a[b],e=[],f=b.length-1;0<=f;f--)e.push(b[f].fn.apply(a.oInstance,d));null!==c&&h(a.oInstance).trigger(c,d);return e}function Ua(a){var b=h('<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden"><div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;"><div id="DT_BrowserTest" style="width:100%; height:10px;"></div></div></div>')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize=
100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f?
"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("current"==b.order&&"none"==b.filter){c=0;for(d=k.length;c<d;c++)(f=g[k[c]].nTr)&&e.push(f)}else if("current"==b.order&&"applied"==b.filter){c=0;for(d=o.length;c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("original"==
b.order&&"none"==b.filter){c=0;for(d=g.length;c<d;c++)(f=g[c].nTr)&&e.push(f)}else if("original"==b.order&&"applied"==b.filter){c=0;for(d=g.length;c<d;c++)f=g[c].nTr,-1!==h.inArray(c,o)&&f&&e.push(f)}else D(d,1,"Unknown selection options");e=h(e);c=e.filter(a);e=e.find(a);return h([].concat(h.makeArray(c),h.makeArray(e)))};this._=function(a,b){var c=[],d,e,f=this.$(a,b);d=0;for(e=f.length;d<e;d++)c.push(this.fnGetData(f[d]));return c};this.fnAddData=function(a,b){if(0===a.length)return[];var c=[],
d,e=s(this[j.ext.iApiIndex]);if("object"===typeof a[0]&&null!==a[0])for(var f=0;f<a.length;f++){d=H(e,a[f]);if(-1==d)return c;c.push(d)}else{d=H(e,a);if(-1==d)return c;c.push(d)}e.aiDisplay=e.aiDisplayMaster.slice();(b===n||b)&&aa(e);return c};this.fnAdjustColumnSizing=function(a){var b=s(this[j.ext.iApiIndex]);k(b);a===n||a?this.fnDraw(!1):(""!==b.oScroll.sX||""!==b.oScroll.sY)&&this.oApi._fnScrollDraw(b)};this.fnClearTable=function(a){var b=s(this[j.ext.iApiIndex]);ga(b);(a===n||a)&&x(b)};this.fnClose=
function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr),b.aoOpenRows.splice(c,1),0;return 1};this.fnDeleteRow=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,a="object"===typeof a?I(d,a):a,g=d.aoData.splice(a,1);e=0;for(f=d.aoData.length;e<f;e++)null!==d.aoData[e].nTr&&(d.aoData[e].nTr._DT_RowIndex=e);e=h.inArray(a,d.aiDisplay);d.asDataSearch.splice(e,1);ha(d.aiDisplayMaster,
a);ha(d.aiDisplay,a);"function"===typeof b&&b.call(this,d,g);d._iDisplayStart>=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;i<f;i++)!1===b.aoColumns[i].bVisible&&this.fnSetColumnVis(i,!0)}h(b.nTableWrapper).find("*").andSelf().unbind(".DT");
h("tbody>tr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc,
b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i<f;i++)null!==b.aoData[i].nTr&&d.appendChild(b.aoData[i].nTr);!0===b.oFeatures.bAutoWidth&&
(b.nTable.style.width=q(b.sDestroyWidth));if(f=b.asDestroyStripes.length){a=h(d).children("tr");for(i=0;i<f;i++)a.filter(":nth-child("+f+"n + "+i+")").addClass(b.asDestroyStripes[i])}i=0;for(f=j.settings.length;i<f;i++)j.settings[i]==b&&j.settings.splice(i,1);e=b=null};this.fnDraw=function(a){var b=s(this[j.ext.iApiIndex]);!1===a?(y(b),x(b)):aa(b)};this.fnFilter=function(a,b,c,d,e,f){var g=s(this[j.ext.iApiIndex]);if(g.oFeatures.bFilter){if(c===n||null===c)c=!1;if(d===n||null===d)d=!0;if(e===n||null===
e)e=!0;if(f===n||null===f)f=!0;if(b===n||null===b){if(K(g,{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f},1),e&&g.aanFeatures.f){b=g.aanFeatures.f;c=0;for(d=b.length;c<d;c++)try{b[c]._DT_Input!=l.activeElement&&h(b[c]._DT_Input).val(a)}catch(o){h(b[c]._DT_Input).val(a)}}}else h.extend(g.aoPreSearchCols[b],{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f}),K(g,g.oPreviousSearch,1)}};this.fnGetData=function(a,b){var c=s(this[j.ext.iApiIndex]);if(a!==n){var d=a;if("object"===typeof a){var e=a.nodeName.toLowerCase();
"tr"===e?d=I(c,a):"td"===e&&(d=I(c,a.parentNode),b=fa(c,d,a))}return b!==n?v(c,d,b,""):c.aoData[d]!==n?c.aoData[d]._aData:null}return Z(c)};this.fnGetNodes=function(a){var b=s(this[j.ext.iApiIndex]);return a!==n?b.aoData[a]!==n?b.aoData[a].nTr:null:T(b)};this.fnGetPosition=function(a){var b=s(this[j.ext.iApiIndex]),c=a.nodeName.toUpperCase();return"TR"==c?I(b,a):"TD"==c||"TH"==c?(c=I(b,a.parentNode),a=fa(b,c,a),[c,R(b,a),a]):null};this.fnIsOpen=function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<
b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return!0;return!1};this.fnOpen=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e=T(d);if(-1!==h.inArray(a,e)){this.fnClose(a);var e=l.createElement("tr"),f=l.createElement("td");e.appendChild(f);f.className=c;f.colSpan=t(d);"string"===typeof b?f.innerHTML=b:h(f).html(b);b=h("tr",d.nTBody);-1!=h.inArray(a,b)&&h(e).insertAfter(a);d.aoOpenRows.push({nTr:e,nParent:a});return e}};this.fnPageChange=function(a,b){var c=s(this[j.ext.iApiIndex]);qa(c,a);
y(c);(b===n||b)&&x(c)};this.fnSetColumnVis=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,g=d.aoColumns,h=d.aoData,o,m;if(g[a].bVisible!=b){if(b){for(e=f=0;e<a;e++)g[e].bVisible&&f++;m=f>=t(d);if(!m)for(e=a;e<g.length;e++)if(g[e].bVisible){o=e;break}e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(m?h[e].nTr.appendChild(h[e]._anHidden[a]):h[e].nTr.insertBefore(h[e]._anHidden[a],J(d,e)[o]))}else{e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(o=J(d,e)[a],h[e]._anHidden[a]=o,o.parentNode.removeChild(o))}g[a].bVisible=
b;W(d,d.aoHeader);d.nTFoot&&W(d,d.aoFooter);e=0;for(f=d.aoOpenRows.length;e<f;e++)d.aoOpenRows[e].nTr.colSpan=t(d);if(c===n||c)k(d),x(d);ra(d)}};this.fnSettings=function(){return s(this[j.ext.iApiIndex])};this.fnSort=function(a){var b=s(this[j.ext.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){ia(s(this[j.ext.iApiIndex]),a,b,c)};this.fnUpdate=function(a,b,c,d,e){var f=s(this[j.ext.iApiIndex]),b="object"===typeof b?I(f,b):b;if(h.isArray(a)&&c===n){f.aoData[b]._aData=a.slice();
for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else if(h.isPlainObject(a)&&c===n){f.aoData[b]._aData=h.extend(!0,{},a);for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else{F(f,b,c,a);var a=v(f,b,c,"display"),g=f.aoColumns[c];null!==g.fnRender&&(a=S(f,b,c),g.bUseRendered&&F(f,b,c,a));null!==f.aoData[b].nTr&&(J(f,b)[c].innerHTML=a)}c=h.inArray(b,f.aiDisplay);f.asDataSearch[c]=na(f,Y(f,b,"filter",r(f,"bSearchable")));(e===n||e)&&k(f);(d===n||d)&&aa(f);return 0};
this.fnVersionCheck=j.ext.fnVersionCheck;this.oApi={_fnExternApiFunc:Va,_fnInitialise:ba,_fnInitComplete:$,_fnLanguageCompat:pa,_fnAddColumn:o,_fnColumnOptions:m,_fnAddData:H,_fnCreateTr:ea,_fnGatherData:ua,_fnBuildHead:va,_fnDrawHead:W,_fnDraw:x,_fnReDraw:aa,_fnAjaxUpdate:wa,_fnAjaxParameters:Ea,_fnAjaxUpdateDraw:Fa,_fnServerParams:ka,_fnAddOptionsHtml:xa,_fnFeatureHtmlTable:Ba,_fnScrollDraw:La,_fnAdjustColumnSizing:k,_fnFeatureHtmlFilter:za,_fnFilterComplete:K,_fnFilterCustom:Ia,_fnFilterColumn:Ha,
_fnFilter:Ga,_fnBuildSearchArray:la,_fnBuildSearchRow:na,_fnFilterCreateSearch:ma,_fnDataToSearch:Ja,_fnSort:O,_fnSortAttachListener:ia,_fnSortingClasses:P,_fnFeatureHtmlPaginate:Da,_fnPageChange:qa,_fnFeatureHtmlInfo:Ca,_fnUpdateInfo:Ka,_fnFeatureHtmlLength:ya,_fnFeatureHtmlProcessing:Aa,_fnProcessingDisplay:E,_fnVisibleToColumnIndex:G,_fnColumnIndexToVisible:R,_fnNodeToDataIndex:I,_fnVisbleColumns:t,_fnCalculateEnd:y,_fnConvertToWidth:Ma,_fnCalculateColumnWidths:da,_fnScrollingWidthAdjust:Oa,_fnGetWidestNode:Na,
_fnGetMaxLenString:Pa,_fnStringToCss:q,_fnDetectType:B,_fnSettingsFromNode:s,_fnGetDataMaster:Z,_fnGetTrNodes:T,_fnGetTdNodes:J,_fnEscapeRegex:oa,_fnDeleteIndex:ha,_fnReOrderIndex:u,_fnColumnOrdering:M,_fnLog:D,_fnClearTable:ga,_fnSaveState:ra,_fnLoadState:Sa,_fnCreateCookie:function(a,b,c,d,e){var f=new Date;f.setTime(f.getTime()+1E3*c);var c=X.location.pathname.split("/"),a=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase(),g;null!==e?(g="function"===typeof h.parseJSON?h.parseJSON(b):eval("("+b+")"),
b=e(a,g,f.toGMTString(),c.join("/")+"/")):b=a+"="+encodeURIComponent(b)+"; expires="+f.toGMTString()+"; path="+c.join("/")+"/";a=l.cookie.split(";");e=b.split(";")[0].length;f=[];if(4096<e+l.cookie.length+10){for(var j=0,o=a.length;j<o;j++)if(-1!=a[j].indexOf(d)){var k=a[j].split("=");try{(g=eval("("+decodeURIComponent(k[1])+")"))&&g.iCreate&&f.push({name:k[0],time:g.iCreate})}catch(m){}}for(f.sort(function(a,b){return b.time-a.time});4096<e+l.cookie.length+10;){if(0===f.length)return;d=f.pop();l.cookie=
d.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}}l.cookie=b},_fnReadCookie:function(a){for(var b=X.location.pathname.split("/"),a=a+"_"+b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=",b=l.cookie.split(";"),c=0;c<b.length;c++){for(var d=b[c];" "==d.charAt(0);)d=d.substring(1,d.length);if(0===d.indexOf(a))return decodeURIComponent(d.substring(a.length,d.length))}return null},_fnDetectHeader:V,_fnGetUniqueThs:N,_fnScrollBarWidth:Qa,_fnApplyToChildren:C,_fnMap:p,_fnGetRowData:Y,
_fnGetCellData:v,_fnSetCellData:F,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:L,_fnApplyColumnDefs:ta,_fnBindAction:Ra,_fnExtend:Ta,_fnCallbackReg:z,_fnCallbackFire:A,_fnJsonString:Wa,_fnRender:S,_fnNodeToColumnIndex:fa,_fnInfoMacros:ja,_fnBrowserDetect:Ua,_fnGetColumns:r};h.extend(j.ext.oApi,this.oApi);for(var sa in j.ext.oApi)sa&&(this[sa]=Va(sa));var ca=this;this.each(function(){var a=0,b,c,d;c=this.getAttribute("id");var i=!1,f=!1;if("table"!=this.nodeName.toLowerCase())D(null,0,"Attempted to initialise DataTables on a node which is not a table: "+
this.nodeName);else{a=0;for(b=j.settings.length;a<b;a++){if(j.settings[a].nTable==this){if(e===n||e.bRetrieve)return j.settings[a].oInstance;if(e.bDestroy){j.settings[a].oInstance.fnDestroy();break}else{D(j.settings[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, pass no arguments or see the docs for bRetrieve and bDestroy");return}}if(j.settings[a].sTableId==this.id){j.settings.splice(a,1);break}}if(null===c||""===c)this.id=c="DataTables_Table_"+j.ext._oExternConfig.iNextUnique++;
var g=h.extend(!0,{},j.models.oSettings,{nTable:this,oApi:ca.oApi,oInit:e,sDestroyWidth:h(this).width(),sInstance:c,sTableId:c});j.settings.push(g);g.oInstance=1===ca.length?ca:h(this).dataTable();e||(e={});e.oLanguage&&pa(e.oLanguage);e=Ta(h.extend(!0,{},j.defaults),e);p(g.oFeatures,e,"bPaginate");p(g.oFeatures,e,"bLengthChange");p(g.oFeatures,e,"bFilter");p(g.oFeatures,e,"bSort");p(g.oFeatures,e,"bInfo");p(g.oFeatures,e,"bProcessing");p(g.oFeatures,e,"bAutoWidth");p(g.oFeatures,e,"bSortClasses");
p(g.oFeatures,e,"bServerSide");p(g.oFeatures,e,"bDeferRender");p(g.oScroll,e,"sScrollX","sX");p(g.oScroll,e,"sScrollXInner","sXInner");p(g.oScroll,e,"sScrollY","sY");p(g.oScroll,e,"bScrollCollapse","bCollapse");p(g.oScroll,e,"bScrollInfinite","bInfinite");p(g.oScroll,e,"iScrollLoadGap","iLoadGap");p(g.oScroll,e,"bScrollAutoCss","bAutoCss");p(g,e,"asStripeClasses");p(g,e,"asStripClasses","asStripeClasses");p(g,e,"fnServerData");p(g,e,"fnFormatNumber");p(g,e,"sServerMethod");p(g,e,"aaSorting");p(g,
e,"aaSortingFixed");p(g,e,"aLengthMenu");p(g,e,"sPaginationType");p(g,e,"sAjaxSource");p(g,e,"sAjaxDataProp");p(g,e,"iCookieDuration");p(g,e,"sCookiePrefix");p(g,e,"sDom");p(g,e,"bSortCellsTop");p(g,e,"iTabIndex");p(g,e,"oSearch","oPreviousSearch");p(g,e,"aoSearchCols","aoPreSearchCols");p(g,e,"iDisplayLength","_iDisplayLength");p(g,e,"bJQueryUI","bJUI");p(g,e,"fnCookieCallback");p(g,e,"fnStateLoad");p(g,e,"fnStateSave");p(g.oLanguage,e,"fnInfoCallback");z(g,"aoDrawCallback",e.fnDrawCallback,"user");
z(g,"aoServerParams",e.fnServerParams,"user");z(g,"aoStateSaveParams",e.fnStateSaveParams,"user");z(g,"aoStateLoadParams",e.fnStateLoadParams,"user");z(g,"aoStateLoaded",e.fnStateLoaded,"user");z(g,"aoRowCallback",e.fnRowCallback,"user");z(g,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(g,"aoHeaderCallback",e.fnHeaderCallback,"user");z(g,"aoFooterCallback",e.fnFooterCallback,"user");z(g,"aoInitComplete",e.fnInitComplete,"user");z(g,"aoPreDrawCallback",e.fnPreDrawCallback,"user");g.oFeatures.bServerSide&&
g.oFeatures.bSort&&g.oFeatures.bSortClasses?z(g,"aoDrawCallback",P,"server_side_sort_classes"):g.oFeatures.bDeferRender&&z(g,"aoDrawCallback",P,"defer_sort_classes");e.bJQueryUI?(h.extend(g.oClasses,j.ext.oJUIClasses),e.sDom===j.defaults.sDom&&"lfrtip"===j.defaults.sDom&&(g.sDom='<"H"lfr>t<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart,
g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0,
g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a<b;a++)d.hasClass(g.asStripeClasses[a])&&(c=!0,g.asDestroyStripes.push(g.asStripeClasses[a]));c&&d.removeClass(g.asStripeClasses.join(" "))}c=[];a=this.getElementsByTagName("thead");0!==a.length&&(V(g.aoHeader,a[0]),c=N(g));if(null===e.aoColumns){d=[];a=0;for(b=
c.length;a<b;a++)d.push(null)}else d=e.aoColumns;a=0;for(b=d.length;a<b;a++)e.saved_aoColumns!==n&&e.saved_aoColumns.length==b&&(null===d[a]&&(d[a]={}),d[a].bVisible=e.saved_aoColumns[a].bVisible),o(g,c?c[a]:null);ta(g,e.aoColumnDefs,d,function(a,b){m(g,a,b)});a=0;for(b=g.aaSorting.length;a<b;a++){g.aaSorting[a][0]>=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]=
k.asSorting[0]);c=0;for(d=k.asSorting.length;c<d;c++)if(g.aaSorting[a][1]==k.asSorting[c]){g.aaSorting[a][2]=c;break}}P(g);Ua(g);a=h(this).children("caption").each(function(){this._captionSide=h(this).css("caption-side")});b=h(this).children("thead");0===b.length&&(b=[l.createElement("thead")],this.appendChild(b[0]));g.nTHead=b[0];b=h(this).children("tbody");0===b.length&&(b=[l.createElement("tbody")],this.appendChild(b[0]));g.nTBody=b[0];g.nTBody.setAttribute("role","alert");g.nTBody.setAttribute("aria-live",
"polite");g.nTBody.setAttribute("aria-relevant","all");b=h(this).children("tfoot");if(0===b.length&&0<a.length&&(""!==g.oScroll.sX||""!==g.oScroll.sY))b=[l.createElement("tfoot")],this.appendChild(b[0]);0<b.length&&(g.nTFoot=b[0],V(g.aoFooter,g.nTFoot));if(f)for(a=0;a<e.aaData.length;a++)H(g,e.aaData[a]);else ua(g);g.aiDisplay=g.aiDisplayMaster.slice();g.bInitialised=!0;!1===i&&ba(g)}});ca=null;return this};j.fnVersionCheck=function(e){for(var h=function(e,h){for(;e.length<h;)e+="0";return e},m=j.ext.sVersion.split("."),
e=e.split("."),k="",n="",l=0,t=e.length;l<t;l++)k+=h(m[l],3),n+=h(e[l],3);return parseInt(k,10)>=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;m<h.length;m++)if(h[m].nTable===e||h[m].nScrollHead===e||h[m].nScrollFoot===e)return!0;return!1};j.fnTables=function(e){var o=[];jQuery.each(j.settings,function(j,k){(!e||!0===e&&h(k.nTable).is(":visible"))&&o.push(k.nTable)});return o};j.version="1.9.4";j.settings=[];j.models={};j.models.ext={afnFiltering:[],afnSortData:[],aoFeatures:[],
aTypes:[],fnVersionCheck:j.fnVersionCheck,iApiIndex:0,ofnSearch:{},oApi:{},oStdClasses:{},oJUIClasses:{},oPagination:{},oSort:{},sVersion:j.version,sErrMode:"alert",_oExternConfig:{iNextUnique:0}};j.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};j.models.oRow={nTr:null,_aData:[],_aSortData:[],_anHidden:[],_sRowStripe:""};j.models.oColumn={aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bUseRendered:null,bVisible:null,_bAutoType:!0,fnCreatedCell:null,fnGetData:null,
fnRender:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};j.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,
bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollAutoCss:!0,bScrollCollapse:!1,bScrollInfinite:!1,bServerSide:!1,bSort:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCookieCallback:null,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(e){if(1E3>e)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k<h;k++)0===k%3&&0!==k&&(j=this.oLanguage.sInfoThousands+j),j=e[h-k-1]+j;return j},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,
fnRowCallback:null,fnServerData:function(e,j,m,k){k.jqXHR=h.ajax({url:e,data:j,success:function(e){e.sError&&k.oApi._fnLog(k,0,e.sError);h(k.oInstance).trigger("xhr",[k,e]);m(e)},dataType:"json",cache:!1,type:k.sServerMethod,error:function(e,h){"parsererror"==h&&k.oApi._fnLog(k,0,"DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})},fnServerParams:null,fnStateLoad:function(e){var e=this.oApi._fnReadCookie(e.sCookiePrefix+e.sInstance),j;try{j=
"function"===typeof h.parseJSON?h.parseJSON(e):eval("("+e+")")}catch(m){j=null}return j},fnStateLoadParams:null,fnStateLoaded:null,fnStateSave:function(e,h){this.oApi._fnCreateCookie(e.sCookiePrefix+e.sInstance,this.oApi._fnJsonString(h),e.iCookieDuration,e.sCookiePrefix,e.fnCookieCallback)},fnStateSaveParams:null,iCookieDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iScrollLoadGap:100,iTabIndex:0,oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},
oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sInfoThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},j.models.oSearch),sAjaxDataProp:"aaData",
sAjaxSource:null,sCookiePrefix:"SpryMedia_DataTables_",sDom:"lfrtip",sPaginationType:"two_button",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET"};j.defaults.columns={aDataSort:null,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bUseRendered:!0,bVisible:!0,fnCreatedCell:null,fnRender:null,iDataSort:-1,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};j.models.oSettings={oFeatures:{bAutoWidth:null,
bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortClasses:null,bStateSave:null},oScroll:{bAutoCss:null,bCollapse:null,bInfinite:null,iBarWidth:0,iLoadGap:null,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1},aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],asDataSearch:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:null,
asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iCookieDuration:0,sCookiePrefix:"",fnCookieCallback:null,aoStateSave:[],aoStateLoad:[],
oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iDisplayEnd:10,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsTotal,10):this.aiDisplayMaster.length},
fnRecordsDisplay:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsDisplay,10):this.aiDisplay.length},fnDisplayEnd:function(){return this.oFeatures.bServerSide?!1===this.oFeatures.bPaginate||-1==this._iDisplayLength?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iRecordsDisplay):this._iDisplayEnd},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null};j.ext=h.extend(!0,{},j.models.ext);h.extend(j.ext.oStdClasses,
{sTable:"dataTable",sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",sPageButtonStaticDisabled:"paginate_button paginate_button_disabled",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",
sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"",sJUIHeader:"",sJUIFooter:""});h.extend(j.ext.oJUIClasses,j.ext.oStdClasses,{sPagePrevEnabled:"fg-button ui-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",sPageNextEnabled:"fg-button ui-button ui-state-default ui-corner-right",
sPageNextDisabled:"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-button ui-state-default",sPageButtonActive:"fg-button ui-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPageLast:"last ui-corner-tr ui-corner-br",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",
sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",
sScrollHead:"dataTables_scrollHead ui-state-default",sScrollFoot:"dataTables_scrollFoot ui-state-default",sFooterTH:"ui-state-default",sJUIHeader:"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",sJUIFooter:"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"});h.extend(j.ext.oPagination,{two_button:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)},k=!e.bJUI?'<a class="'+
e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sPrevious+'</a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sNext+"</a>":'<a class="'+e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUIPrev+'"></span></a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUINext+'"></span></a>';h(j).append(k);var l=h("a",j),
k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l<n;l++)if(k=j[l].firstChild)k.className=0===e._iDisplayStart?h.sPagePrevDisabled:h.sPagePrevEnabled,k=k.nextSibling,
k.className=e.fnDisplayEnd()==e.fnRecordsDisplay()?h.sPageNextDisabled:h.sPageNextEnabled}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,l=e.oClasses,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)};h(j).append('<a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageFirst+'">'+k.sFirst+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPagePrevious+'">'+k.sPrevious+'</a><span></span><a tabindex="'+e.iTabIndex+'" class="'+
l.sPageButton+" "+l.sPageNext+'">'+k.sNext+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageLast+'">'+k.sLast+"</a>");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")},
fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l<m?(r=1,k=l):n<=k?(r=1,k=m):n>=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+=
n!==m?'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButton+'">'+e.fnFormatNumber(m)+"</a>":'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButtonActive+'">'+e.fnFormatNumber(m)+"</a>";m=0;for(k=M.length;m<k;m++)u=M[m],u.hasChildNodes()&&(h("span:eq(0)",u).html(t).children("a").each(L),u=u.getElementsByTagName("a"),u=[u[0],u[1],u[u.length-2],u[u.length-1]],h(u).removeClass(B.sPageButton+" "+B.sPageButtonActive+" "+B.sPageButtonStaticDisabled),h([u[0],u[1]]).addClass(1==n?B.sPageButtonStaticDisabled:
B.sPageButton),h([u[2],u[3]]).addClass(0===l||n===l||-1===e._iDisplayLength?B.sPageButtonStaticDisabled:B.sPageButton))}}}});h.extend(j.ext.oSort,{"string-pre":function(e){"string"!=typeof e&&(e=null!==e&&e.toString?e.toString():"");return e.toLowerCase()},"string-asc":function(e,h){return e<h?-1:e>h?1:0},"string-desc":function(e,h){return e<h?1:e>h?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return e<h?-1:e>h?1:0},"html-desc":function(e,h){return e<
h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null;
for(var k=1;k<e.length;k++){h=e.charAt(k);if(-1=="0123456789.".indexOf(h))return null;if("."==h){if(j)return null;j=!0}}return"numeric"},function(e){var h=Date.parse(e);return null!==h&&!isNaN(h)||"string"===typeof e&&0===e.length?"date":null},function(e){return"string"===typeof e&&-1!=e.indexOf("<")&&-1!=e.indexOf(">")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&&
L(jQuery)})(window,document);

View File

@ -0,0 +1,188 @@
/*!
* Bootstrap style for DataTables jquery plugin
*
* Copyright 2012
* DataTables is dual licensed under the GPL v2 license or a BSD (3-point) license.
* http://www.datatables.net
* http://www.datatables.net/blog/Twitter_Bootstrap_2
*
*/
div.dataTables_length label {
float: left;
text-align: left;
}
div.dataTables_length select {
width: 75px;
}
div.dataTables_filter label {
float: right;
}
div.dataTables_info {
padding-top: 8px;
}
div.dataTables_paginate {
float: right;
margin: 0;
}
table.table {
clear: both;
margin-bottom: 6px !important;
max-width: none !important;
}
table.table thead .sorting,
table.table thead .sorting_asc,
table.table thead .sorting_desc,
table.table thead .sorting_asc_disabled,
table.table thead .sorting_desc_disabled {
cursor: pointer;
*cursor: hand;
}
table.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; }
table.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; }
table.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; }
table.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; }
table.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; }
table.dataTable th:active {
outline: none;
}
/* Scrolling */
div.dataTables_scrollHead table {
margin-bottom: 0 !important;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
div.dataTables_scrollHead table thead tr:last-child th:first-child,
div.dataTables_scrollHead table thead tr:last-child td:first-child {
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.dataTables_scrollBody table {
border-top: none;
margin-bottom: 0 !important;
}
div.dataTables_scrollBody tbody tr:first-child th,
div.dataTables_scrollBody tbody tr:first-child td {
border-top: none;
}
div.dataTables_scrollFoot table {
border-top: none;
}
/*
* TableTools styles
*/
.table tbody tr.active td,
.table tbody tr.active th {
background-color: #08C;
color: white;
}
.table tbody tr.active:hover td,
.table tbody tr.active:hover th {
background-color: #0075b0 !important;
}
.table-striped tbody tr.active:nth-child(odd) td,
.table-striped tbody tr.active:nth-child(odd) th {
background-color: #017ebc;
}
table.DTTT_selectable tbody tr {
cursor: pointer;
*cursor: hand;
}
div.DTTT .btn {
color: #333 !important;
font-size: 12px;
}
div.DTTT .btn:hover {
text-decoration: none !important;
}
ul.DTTT_dropdown.dropdown-menu a {
color: #333 !important; /* needed only when demo_page.css is included */
}
ul.DTTT_dropdown.dropdown-menu li:hover a {
background-color: #0088cc;
color: white !important;
}
/* TableTools information display */
div.DTTT_print_info.modal {
height: 150px;
margin-top: -75px;
text-align: center;
}
div.DTTT_print_info h6 {
font-weight: normal;
font-size: 28px;
line-height: 28px;
margin: 1em;
}
div.DTTT_print_info p {
font-size: 14px;
line-height: 20px;
}
/*
* FixedColumns styles
*/
div.DTFC_LeftHeadWrapper table,
div.DTFC_LeftFootWrapper table,
table.DTFC_Cloned tr.even {
background-color: white;
}
div.DTFC_LeftHeadWrapper table {
margin-bottom: 0 !important;
border-top-right-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,
div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.DTFC_LeftBodyWrapper table {
border-top: none;
margin-bottom: 0 !important;
}
div.DTFC_LeftBodyWrapper tbody tr:first-child th,
div.DTFC_LeftBodyWrapper tbody tr:first-child td {
border-top: none;
}
div.DTFC_LeftFootWrapper table {
border-top: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.utils.management.commands.syncdb
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overrides the Django syncdb command to setup the database.
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.core.management.commands.syncdb import Command as _Command
from openslides.core.signals import post_database_setup
class Command(_Command):
"""
Setup the database and sends the signal post_database_setup.
"""
def handle_noargs(self, *args, **kwargs):
return_value = super(Command, self).handle_noargs(*args, **kwargs)
post_database_setup.send(sender=self)
return return_value

27
openslides/utils/test.py Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.utils.test
~~~~~~~~~~~~~~~~~~~~~
Unit test class.
:copyright: 2011-2013 by OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.test import TestCase as _TestCase
from openslides.core.signals import post_database_setup
class TestCase(_TestCase):
"""
Overwrites Django's TestCase class to call the post_database_setup
signal after the preparation of every test.
"""
def _pre_setup(self, *args, **kwargs):
return_value = super(TestCase, self)._pre_setup(*args, **kwargs)
post_database_setup.send(sender=self)
return return_value

View File

@ -304,7 +304,8 @@ class DeleteView(SingleObjectMixin, QuestionMixin, RedirectView):
return super(DeleteView, self).get(request, *args, **kwargs) return super(DeleteView, self).get(request, *args, **kwargs)
def get_redirect_url(self, **kwargs): def get_redirect_url(self, **kwargs):
if self.request.method == 'GET' and self.question_url_name is None: if self.question_url_name is None and (self.request.method == 'GET' or
self.get_answer() == 'no'):
return self.object.get_absolute_url() return self.object.get_absolute_url()
else: else:
return super(DeleteView, self).get_redirect_url(**kwargs) return super(DeleteView, self).get_redirect_url(**kwargs)

View File

@ -10,10 +10,10 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.test import TestCase
from django.test.client import Client from django.test.client import Client
from django.db.models.query import EmptyQuerySet from django.db.models.query import EmptyQuerySet
from openslides.utils.test import TestCase
from openslides.projector.api import get_active_slide from openslides.projector.api import get_active_slide
from openslides.participant.models import User from openslides.participant.models import User
from openslides.agenda.models import Item from openslides.agenda.models import Item
@ -95,7 +95,6 @@ class ItemTest(TestCase):
self.assertEqual(self.item5.print_related_type(), 'Releateditem') self.assertEqual(self.item5.print_related_type(), 'Releateditem')
class ViewTest(TestCase): class ViewTest(TestCase):
def setUp(self): def setUp(self):
self.item1 = Item.objects.create(title='item1') self.item1 = Item.objects.create(title='item1')

View File

@ -8,8 +8,7 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.test import TestCase from openslides.utils.test import TestCase
from openslides.participant.models import User from openslides.participant.models import User
from openslides.config.models import config from openslides.config.models import config
from openslides.motion.models import Motion, Workflow, State from openslides.motion.models import Motion, Workflow, State
@ -113,18 +112,18 @@ class ModelTest(TestCase):
self.motion.state = State.objects.get(pk=6) self.motion.state = State.objects.get(pk=6)
self.assertEqual(self.motion.state.name, 'permitted') self.assertEqual(self.motion.state.name, 'permitted')
self.assertEqual(self.motion.state.get_action_word(), 'permit') self.assertEqual(self.motion.state.get_action_word(), 'Permit')
with self.assertRaises(WorkflowError): with self.assertRaises(WorkflowError):
self.motion.support(self.test_user) self.motion.support(self.test_user)
with self.assertRaises(WorkflowError): with self.assertRaises(WorkflowError):
self.motion.unsupport(self.test_user) self.motion.unsupport(self.test_user)
def test_new_states_or_workflows(self): def test_new_states_or_workflows(self):
workflow_1 = Workflow(name='W1', id=1000) workflow_1 = Workflow.objects.create(name='W1')
state_1 = State.objects.create(name='S1', workflow=workflow_1) state_1 = State.objects.create(name='S1', workflow=workflow_1)
workflow_1.first_state = state_1 workflow_1.first_state = state_1
workflow_1.save() workflow_1.save()
workflow_2 = Workflow(name='W2', id=2000) workflow_2 = Workflow.objects.create(name='W2')
state_2 = State.objects.create(name='S2', workflow=workflow_2) state_2 = State.objects.create(name='S2', workflow=workflow_2)
workflow_2.first_state = state_2 workflow_2.first_state = state_2
workflow_2.save() workflow_2.save()

View File

@ -7,9 +7,9 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.test import TestCase
from openslides import get_version, get_git_commit_id from openslides import get_version, get_git_commit_id
from openslides.utils.test import TestCase
class InitTest(TestCase): class InitTest(TestCase):
def test_get_version(self): def test_get_version(self):

View File

@ -10,8 +10,7 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.test import TestCase from openslides.utils.test import TestCase
from openslides.utils.person import get_person, Persons from openslides.utils.person import get_person, Persons
from openslides.participant.api import gen_username, gen_password from openslides.participant.api import gen_username, gen_password
from openslides.participant.models import User, Group from openslides.participant.models import User, Group