Commit 6b94127b3df5d75cb1158b70aa526c5ab23954b7

Authored by Jean Ferri
2 parents d281e23b 13be02ef

Merge pull request #5 from TracyWebTech/master

Last update from PNUD contract
Showing 48 changed files with 1831 additions and 351 deletions   Show diff stats
puppet/modules/colab/manifests/cronjobs.pp
@@ -47,15 +47,15 @@ class colab::cronjobs { @@ -47,15 +47,15 @@ class colab::cronjobs {
47 require => File['/mnt/mailman/'], 47 require => File['/mnt/mailman/'],
48 } 48 }
49 49
50 - cron { 'mount-sshfs':  
51 - command => 'test -e /mnt/mailman/archives/flag || sshfs root@listas.interlegis.gov.br:/var/lib/mailman/archives/private /mnt/mailman/archives/ -o ro,nosuid,nodev,max_read=65536,allow_other,IdentityFile=/root/.ssh/id_rsa && touch /mnt/mailman/archives/flag &> /dev/null',  
52 - minute => '*/5',  
53 - user => 'root',  
54 - require => [  
55 - File['/mnt/mailman/archives/'],  
56 - #File['root-ssh-private-key'],  
57 - Package['sshfs'],  
58 - ],  
59 - } 50 + #cron { 'mount-sshfs':
  51 + # command => 'test -e /mnt/mailman/archives/flag || sshfs root@listas.interlegis.gov.br:/var/lib/mailman/archives/private /mnt/mailman/archives/ -o ro,nosuid,nodev,max_read=65536,allow_other,IdentityFile=/root/.ssh/id_rsa && touch /mnt/mailman/archives/flag &> /dev/null',
  52 + # minute => '*/5',
  53 + # user => 'root',
  54 + # require => [
  55 + # File['/mnt/mailman/archives/'],
  56 + # #File['root-ssh-private-key'],
  57 + # Package['sshfs'],
  58 + # ],
  59 + #}
60 60
61 } 61 }
puppet/modules/colab/manifests/init.pp
@@ -20,11 +20,13 @@ class colab { @@ -20,11 +20,13 @@ class colab {
20 } 20 }
21 21
22 Mailalias { 22 Mailalias {
23 - notify => Exec['newaliases'], 23 + notify => Exec['newaliases'],
  24 + require => Class['postfix'],
24 } 25 }
25 26
26 exec { 'newaliases': 27 exec { 'newaliases':
27 - path => '/usr/bin/newaliases', 28 + command => 'sendmail -bi',
  29 + path => '/usr/sbin',
28 refreshonly => true, 30 refreshonly => true,
29 } 31 }
30 32
puppet/modules/colab/manifests/requirements.pp
@@ -25,7 +25,6 @@ class colab::requirements { @@ -25,7 +25,6 @@ class colab::requirements {
25 # XMPP connection manager 25 # XMPP connection manager
26 package { 'punjab': 26 package { 'punjab':
27 ensure => installed, 27 ensure => installed,
28 - source => 'git+https://github.com/twonds/punjab@c96ffe4#egg=punjab',  
29 provider => pip, 28 provider => pip,
30 require => Package['python-pip'], 29 require => Package['python-pip'],
31 } 30 }
requirements.txt
1 -Django>=1.6,<1.7 1 +Django>=1.6.1,<1.7
2 South==0.8.1 2 South==0.8.1
3 psycopg2==2.5.1 3 psycopg2==2.5.1
4 django-piston==0.2.3 4 django-piston==0.2.3
@@ -17,6 +17,7 @@ python-memcached==1.53 @@ -17,6 +17,7 @@ python-memcached==1.53
17 django-hitcounter==0.1.1 17 django-hitcounter==0.1.1
18 Pillow==2.2.1 18 Pillow==2.2.1
19 django-i18n-model==0.0.7 19 django-i18n-model==0.0.7
  20 +django-tastypie==0.11.0
20 21
21 gunicorn==18.0 22 gunicorn==18.0
22 gevent==0.13.8 23 gevent==0.13.8
@@ -31,7 +32,7 @@ git+https://github.com/mozilla/django-browserid @@ -31,7 +32,7 @@ git+https://github.com/mozilla/django-browserid
31 django-revproxy==0.2.7 32 django-revproxy==0.2.7
32 33
33 # Converse.js (XMPP client) 34 # Converse.js (XMPP client)
34 -django-conversejs==0.2.9 35 +django-conversejs==0.3
35 git+https://github.com/TracyWebTech/SleekXMPP@fix-gevent 36 git+https://github.com/TracyWebTech/SleekXMPP@fix-gevent
36 37
37 # Feedzilla (planet) and deps 38 # Feedzilla (planet) and deps
src/accounts/forms.py
@@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _ @@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _
6 6
7 from conversejs.models import XMPPAccount 7 from conversejs.models import XMPPAccount
8 8
  9 +from accounts.utils import mailman
9 from super_archives.models import MailingList 10 from super_archives.models import MailingList
10 from .utils.validators import validate_social_account 11 from .utils.validators import validate_social_account
11 12
@@ -49,19 +50,29 @@ class UserCreationForm(UserForm): @@ -49,19 +50,29 @@ class UserCreationForm(UserForm):
49 50
50 51
51 class UserUpdateForm(UserForm): 52 class UserUpdateForm(UserForm):
  53 + bio = forms.CharField(
  54 + widget=forms.Textarea(attrs={'rows': '6', 'maxlength': '200'}),
  55 + max_length=200,
  56 + label=_(u'Bio'),
  57 + help_text=_(u'Write something about you in 200 characters or less.'),
  58 + required=False,
  59 + )
52 60
53 class Meta: 61 class Meta:
54 model = User 62 model = User
55 fields = ('first_name', 'last_name', 63 fields = ('first_name', 'last_name',
56 'institution', 'role', 'twitter', 'facebook', 64 'institution', 'role', 'twitter', 'facebook',
57 - 'google_talk', 'webpage') 65 + 'google_talk', 'github', 'webpage', 'bio')
58 66
59 twitter = SocialAccountField(url='https://twitter.com/', required=False) 67 twitter = SocialAccountField(url='https://twitter.com/', required=False)
60 facebook = SocialAccountField(url='https://graph.facebook.com/', required=False) 68 facebook = SocialAccountField(url='https://graph.facebook.com/', required=False)
61 69
62 70
63 class ListsForm(forms.Form): 71 class ListsForm(forms.Form):
64 - LISTS_NAMES = ((list.name, list.name) for list in MailingList.objects.all()) 72 + LISTS_NAMES = ((
  73 + listname, u'{} ({})'.format(listname, description)
  74 + ) for listname, description in mailman.all_lists(description=True))
  75 +
65 lists = forms.MultipleChoiceField(label=_(u'Mailing lists'), 76 lists = forms.MultipleChoiceField(label=_(u'Mailing lists'),
66 required=False, 77 required=False,
67 widget=forms.CheckboxSelectMultiple, 78 widget=forms.CheckboxSelectMultiple,
src/accounts/migrations/0007_remove_at_from_username.py 0 → 100644
@@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import DataMigration
  5 +from django.db import models
  6 +
  7 +class Migration(DataMigration):
  8 +
  9 + def forwards(self, orm):
  10 + "Write your forwards methods here."
  11 + # Note: Don't use "from appname.models import ModelName".
  12 + # Use orm.ModelName to refer to models in this application,
  13 + # and orm['appname.ModelName'] for models in other applications.
  14 + for u in orm.User.objects.filter(username__contains='@'):
  15 + u.username = u.username.split('@')[0]
  16 + u.save()
  17 +
  18 + def backwards(self, orm):
  19 + pass
  20 +
  21 + models = {
  22 + u'accounts.user': {
  23 + 'Meta': {'object_name': 'User'},
  24 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  25 + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
  26 + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  27 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  28 + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
  29 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
  30 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  31 + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  32 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  33 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  34 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  35 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  36 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  37 + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
  38 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  39 + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  40 + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  41 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
  42 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
  43 + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
  44 + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
  45 + },
  46 + u'auth.group': {
  47 + 'Meta': {'object_name': 'Group'},
  48 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  49 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  50 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  51 + },
  52 + u'auth.permission': {
  53 + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
  54 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  55 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
  56 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  57 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  58 + },
  59 + u'contenttypes.contenttype': {
  60 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  61 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  62 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  63 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  64 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  65 + }
  66 + }
  67 +
  68 + complete_apps = ['accounts']
  69 + symmetrical = True
src/accounts/migrations/0008_auto__add_field_user_bio.py 0 → 100644
@@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import SchemaMigration
  5 +from django.db import models
  6 +
  7 +
  8 +class Migration(SchemaMigration):
  9 +
  10 + def forwards(self, orm):
  11 + # Adding field 'User.bio'
  12 + db.add_column(u'accounts_user', 'bio',
  13 + self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True),
  14 + keep_default=False)
  15 +
  16 +
  17 + def backwards(self, orm):
  18 + # Deleting field 'User.bio'
  19 + db.delete_column(u'accounts_user', 'bio')
  20 +
  21 +
  22 + models = {
  23 + u'accounts.user': {
  24 + 'Meta': {'object_name': 'User'},
  25 + 'bio': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
  26 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  27 + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
  28 + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  29 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  30 + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
  31 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
  32 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  33 + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  34 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  35 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  36 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  37 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  38 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  39 + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
  40 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  41 + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  42 + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  43 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
  44 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
  45 + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
  46 + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
  47 + },
  48 + u'auth.group': {
  49 + 'Meta': {'object_name': 'Group'},
  50 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  51 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  52 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  53 + },
  54 + u'auth.permission': {
  55 + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
  56 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  57 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
  58 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  59 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  60 + },
  61 + u'contenttypes.contenttype': {
  62 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  63 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  64 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  65 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  66 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  67 + }
  68 + }
  69 +
  70 + complete_apps = ['accounts']
0 \ No newline at end of file 71 \ No newline at end of file
src/accounts/migrations/0009_auto__add_field_user_identi_ca.py 0 → 100644
@@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import SchemaMigration
  5 +from django.db import models
  6 +
  7 +
  8 +class Migration(SchemaMigration):
  9 +
  10 + def forwards(self, orm):
  11 + # Adding field 'User.identi_ca'
  12 + db.add_column(u'accounts_user', 'identi_ca',
  13 + self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True),
  14 + keep_default=False)
  15 +
  16 +
  17 + def backwards(self, orm):
  18 + # Deleting field 'User.identi_ca'
  19 + db.delete_column(u'accounts_user', 'identi_ca')
  20 +
  21 +
  22 + models = {
  23 + u'accounts.user': {
  24 + 'Meta': {'object_name': 'User'},
  25 + 'bio': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
  26 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  27 + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
  28 + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  29 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  30 + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
  31 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
  32 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  33 + 'identi_ca': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  34 + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  35 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  36 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  37 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  38 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  39 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  40 + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
  41 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  42 + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  43 + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  44 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
  45 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
  46 + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
  47 + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
  48 + },
  49 + u'auth.group': {
  50 + 'Meta': {'object_name': 'Group'},
  51 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  52 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  53 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  54 + },
  55 + u'auth.permission': {
  56 + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
  57 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  58 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
  59 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  60 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  61 + },
  62 + u'contenttypes.contenttype': {
  63 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  64 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  65 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  66 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  67 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  68 + }
  69 + }
  70 +
  71 + complete_apps = ['accounts']
0 \ No newline at end of file 72 \ No newline at end of file
src/accounts/migrations/0010_auto__del_field_user_identi_ca__add_field_user_github.py 0 → 100644
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from south.db import db
  4 +from south.v2 import SchemaMigration
  5 +from django.db import models
  6 +
  7 +
  8 +class Migration(SchemaMigration):
  9 +
  10 + def forwards(self, orm):
  11 + # Deleting field 'User.identi_ca'
  12 + db.delete_column(u'accounts_user', 'identi_ca')
  13 +
  14 + # Adding field 'User.github'
  15 + db.add_column(u'accounts_user', 'github',
  16 + self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True),
  17 + keep_default=False)
  18 +
  19 +
  20 + def backwards(self, orm):
  21 + # Adding field 'User.identi_ca'
  22 + db.add_column(u'accounts_user', 'identi_ca',
  23 + self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True),
  24 + keep_default=False)
  25 +
  26 + # Deleting field 'User.github'
  27 + db.delete_column(u'accounts_user', 'github')
  28 +
  29 +
  30 + models = {
  31 + u'accounts.user': {
  32 + 'Meta': {'object_name': 'User'},
  33 + 'bio': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
  34 + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  35 + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
  36 + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  37 + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  38 + 'github': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  39 + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
  40 + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
  41 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  42 + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  43 + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
  44 + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  45 + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  46 + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
  47 + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
  48 + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
  49 + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
  50 + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  51 + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
  52 + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
  53 + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
  54 + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
  55 + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'})
  56 + },
  57 + u'auth.group': {
  58 + 'Meta': {'object_name': 'Group'},
  59 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  60 + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
  61 + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
  62 + },
  63 + u'auth.permission': {
  64 + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
  65 + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  66 + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
  67 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  68 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
  69 + },
  70 + u'contenttypes.contenttype': {
  71 + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
  72 + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  73 + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  74 + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  75 + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
  76 + }
  77 + }
  78 +
  79 + complete_apps = ['accounts']
0 \ No newline at end of file 80 \ No newline at end of file
src/accounts/models.py
@@ -5,7 +5,9 @@ import urlparse @@ -5,7 +5,9 @@ import urlparse
5 from django.db import models, DatabaseError 5 from django.db import models, DatabaseError
6 from django.contrib.auth.hashers import check_password 6 from django.contrib.auth.hashers import check_password
7 from django.contrib.auth.models import AbstractUser 7 from django.contrib.auth.models import AbstractUser
  8 +from django.core import validators
8 from django.core.urlresolvers import reverse 9 from django.core.urlresolvers import reverse
  10 +from django.utils.translation import ugettext_lazy as _
9 11
10 from conversejs import xmpp 12 from conversejs import xmpp
11 13
@@ -18,9 +20,12 @@ class User(AbstractUser): @@ -18,9 +20,12 @@ class User(AbstractUser):
18 twitter = models.CharField(max_length=128, null=True, blank=True) 20 twitter = models.CharField(max_length=128, null=True, blank=True)
19 facebook = models.CharField(max_length=128, null=True, blank=True) 21 facebook = models.CharField(max_length=128, null=True, blank=True)
20 google_talk = models.EmailField(null=True, blank=True) 22 google_talk = models.EmailField(null=True, blank=True)
  23 + github = models.CharField(max_length=128, null=True, blank=True,
  24 + verbose_name=u'github')
21 webpage = models.CharField(max_length=256, null=True, blank=True) 25 webpage = models.CharField(max_length=256, null=True, blank=True)
22 verification_hash = models.CharField(max_length=32, null=True, blank=True) 26 verification_hash = models.CharField(max_length=32, null=True, blank=True)
23 modified = models.DateTimeField(auto_now=True) 27 modified = models.DateTimeField(auto_now=True)
  28 + bio = models.CharField(max_length=200, null=True, blank=True)
24 29
25 def check_password(self, raw_password): 30 def check_password(self, raw_password):
26 31
@@ -50,3 +55,12 @@ class User(AbstractUser): @@ -50,3 +55,12 @@ class User(AbstractUser):
50 # The following workaroud allows to change email field to unique 55 # The following workaroud allows to change email field to unique
51 # without having to rewrite all AbstractUser here 56 # without having to rewrite all AbstractUser here
52 User._meta.get_field('email')._unique = True 57 User._meta.get_field('email')._unique = True
  58 +User._meta.get_field('username').help_text = _(
  59 + u'Required. 30 characters or fewer. Letters, digits and '
  60 + u'./+/-/_ only.'
  61 +)
  62 +User._meta.get_field('username').validators[0] = validators.RegexValidator(
  63 + r'^[\w.+-]+$',
  64 + _('Enter a valid username.'),
  65 + 'invalid'
  66 +)
src/accounts/search_indexes.py
@@ -41,9 +41,6 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable): @@ -41,9 +41,6 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable):
41 self._badge_counters = get_users_counters() 41 self._badge_counters = get_users_counters()
42 return self._badge_counters 42 return self._badge_counters
43 43
44 - def get_updated_field(self):  
45 - return 'modified'  
46 -  
47 def prepare(self, obj): 44 def prepare(self, obj):
48 prepared_data = super(UserIndex, self).prepare(obj) 45 prepared_data = super(UserIndex, self).prepare(obj)
49 46
src/accounts/templates/accounts/manage_subscriptions.html
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 {% block main-content %} 4 {% block main-content %}
5 5
6 - <h2>{% blocktrans %}Mailing List Subscriptions{% endblocktrans %}</h2> 6 + <h2>{% blocktrans %}Group Subscriptions{% endblocktrans %}</h2>
7 <h3>{% gravatar user_.email 50 %} {{ user_.get_full_name }} ({{ user_.username }})</h3> 7 <h3>{% gravatar user_.email 50 %} {{ user_.get_full_name }} ({{ user_.username }})</h3>
8 <br> 8 <br>
9 9
@@ -19,9 +19,9 @@ @@ -19,9 +19,9 @@
19 </div> 19 </div>
20 <div class="panel-body"> 20 <div class="panel-body">
21 {% for list, checked in lists %} 21 {% for list, checked in lists %}
22 - <div class="checkbox"> 22 + <div class="checkbox" title="{{ list.description }}">
23 <label> 23 <label>
24 - <input name="{{ email }}" value="{{ list }}" type="checkbox" {% if checked %}checked{% endif%}>{{ list }}</input> 24 + <input name="{{ email }}" value="{{ list.listname }}" type="checkbox" {% if checked %}checked{% endif%}>{{ list.listname }}</input>
25 </label> 25 </label>
26 </div> 26 </div>
27 {% endfor %} 27 {% endfor %}
src/accounts/templates/accounts/user_create_form.html
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 <div class="col-md-6 col-lg-6 col-sm-6 col-xs-12" style="display: inline-block; vertical-align:top;"> 43 <div class="col-md-6 col-lg-6 col-sm-6 col-xs-12" style="display: inline-block; vertical-align:top;">
44 <div class="well"> 44 <div class="well">
45 <fieldset> 45 <fieldset>
46 - <legend>{% trans 'Subscribe to mail lists' %}</legend> 46 + <legend>{% trans 'Subscribe to groups' %}</legend>
47 {% for choice in lists_form.lists %} 47 {% for choice in lists_form.lists %}
48 <div class="checkbox">{{ choice }}</div> 48 <div class="checkbox">{{ choice }}</div>
49 {% endfor %} 49 {% endfor %}
src/accounts/templates/accounts/user_detail.html
@@ -4,8 +4,11 @@ @@ -4,8 +4,11 @@
4 4
5 5
6 {% block head_js %} 6 {% block head_js %}
7 - {% include "pizza-chart.html" with chart_data=type_count chart_div="collabs" chart_height=300 %}  
8 - {% include "pizza-chart.html" with chart_data=list_activity chart_div="collabs2" chart_height=300 %} 7 + {% trans "Messages" as group_collabs %}
  8 + {% trans "Contributions" as type_collabs %}
  9 +
  10 + {% include "pizza-chart.html" with chart_data=type_count chart_div="collabs" chart_height=300 name=type_collabs %}
  11 + {% include "pizza-chart.html" with chart_data=list_activity chart_div="collabs2" chart_height=300 name=group_collabs %}
9 {% endblock %} 12 {% endblock %}
10 13
11 {% block main-content %} 14 {% block main-content %}
@@ -22,16 +25,26 @@ @@ -22,16 +25,26 @@
22 </h1> 25 </h1>
23 26
24 {% if request.user == user_ or request.user.is_superuser %} 27 {% if request.user == user_ or request.user.is_superuser %}
25 - <a class="btn btn-info" href="{% url 'user_profile_update' user_ %}"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{% trans "profile"|title %}</a>  
26 - <a class="btn btn-info" href="{% url 'user_list_subscriptions' user_ %}"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{% trans "list membership"|title %}</a> 28 + <a class="btn btn-info" href="{% url 'user_profile_update' user_ %}"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{% trans "edit profile"|title %}</a>
  29 + <a class="btn btn-info" href="{% url 'user_list_subscriptions' user_ %}"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{% trans "group membership"|title %}</a>
  30 + {% endif %}
  31 +
  32 + {% if request.user.is_active %}
  33 + {% if user_.bio %}
  34 + <div class="divider"></div>
  35 + <ul class="unstyled-list">
  36 + <li>
  37 + <strong>{% trans 'Bio' %}</strong>
  38 + </li>
  39 + <li class="text-muted"> {{ user_.bio }}</li>
  40 + </ul>
  41 + {% endif %}
27 {% endif %} 42 {% endif %}
28 43
29 <div class="divider"></div> 44 <div class="divider"></div>
30 {% if request.user.is_active %} 45 {% if request.user.is_active %}
31 <ul class="unstyled-list"> 46 <ul class="unstyled-list">
32 - {% for email in user_.emails.iterator %}  
33 - <li><span class="icon-envelope icon-fixed-width"></span> {{ email.address }}</li>  
34 - {% endfor %} 47 + <li><span class="icon-envelope icon-fixed-width"></span> <a href="mailto:{{ user_.email }}">{{ user_.email }}</a></li>
35 </ul> 48 </ul>
36 <div class="divider"></div> 49 <div class="divider"></div>
37 {% endif %} 50 {% endif %}
@@ -48,26 +61,31 @@ @@ -48,26 +61,31 @@
48 {% if request.user.is_active %} 61 {% if request.user.is_active %}
49 <li> 62 <li>
50 {% if user_.twitter %} 63 {% if user_.twitter %}
51 - <span class="icon-twitter icon-fixed-width"></span> <a target="_blank" href="{{ user_.twitter_link }}" title="{% trans 'Twitter account' %}">{{ user_.twitter }}</a> 64 + <span class="icon-twitter icon-fixed-width" title="{% trans 'Twitter account' %}"></span> <a target="_blank" href="{{ user_.twitter_link }}" title="{% trans 'Twitter account' %}">{{ user_.twitter }}</a>
52 {% endif %} 65 {% endif %}
53 {% if user_.facebook %} 66 {% if user_.facebook %}
54 - <span class="icon-facebook icon-fixed-width"></span> <a target="_blank" href="{{ user_.facebook_link }}" title="{% trans 'Facebook account' %}">{{ user_.facebook }}</a> 67 + <span class="icon-facebook icon-fixed-width" title="{% trans 'Facebook account' %}"></span> <a target="_blank" href="{{ user_.facebook_link }}" title="{% trans 'Facebook account' %}">{{ user_.facebook }}</a>
55 {% endif %} 68 {% endif %}
56 </li> 69 </li>
57 70
58 {% if user_.google_talk %} 71 {% if user_.google_talk %}
59 - <li><span class="icon-google-plus icon-fixed-width"></span> {{ user_.google_talk }}</li> 72 + <li><span class="icon-google-plus icon-fixed-width" title="{% trans 'Google talk account' %}"></span> {{ user_.google_talk }}</li>
  73 + {% endif %}
  74 +
  75 + {% if user_.github %}
  76 + <li><span class="icon-github icon-fixed-width" title="{% trans 'Github account' %}"></span> <a target="_blank" href="https://github.com/{{ user_.github }}">{{ user_.github }}</a></li>
60 {% endif %} 77 {% endif %}
  78 +
61 {% if user_.webpage %} 79 {% if user_.webpage %}
62 - <li><span class="icon-link icon-fixed-width"></span> <a target="_blank" href="{{ user_.webpage }}" title="{% trans 'Personal webpage' %}">{{ user_.webpage }}</a></li> 80 + <li><span class="icon-link icon-fixed-width" title="{% trans 'Personal webpage' %}"></span> <a target="_blank" href="{{ user_.webpage }}" title="{% trans 'Personal webpage' %}">{{ user_.webpage }}</a></li>
63 {% endif %} 81 {% endif %}
64 {% endif %} 82 {% endif %}
65 </ul> 83 </ul>
66 84
67 {% if user_.mailinglists %} 85 {% if user_.mailinglists %}
68 - <b>{% trans 'Subscribes: ' %}</b> 86 + <b>{% trans 'Groups: ' %}</b>
69 {% for list in user_.mailinglists %} 87 {% for list in user_.mailinglists %}
70 - <span class="label label-primary">{{ list }}</span> 88 + <a href="{% url 'haystack_search' %}?order=latest&amp;type=thread&amp;list={{ list }}"><span class="label label-primary">{{ list }}</span></a>
71 {% endfor %} 89 {% endfor %}
72 {% endif %} 90 {% endif %}
73 91
@@ -78,7 +96,7 @@ @@ -78,7 +96,7 @@
78 <div class="col-lg-4 col-md-4 col-sm-7"> 96 <div class="col-lg-4 col-md-4 col-sm-7">
79 <div class="panel panel-default"> 97 <div class="panel panel-default">
80 <div class="panel-heading"> 98 <div class="panel-heading">
81 - <h3 class="panel-title">{% trans "Contributions by Area" %}</h3> 99 + <h3 class="panel-title">{% trans "Contributions by Type" %}</h3>
82 </div> 100 </div>
83 <div class="panel-body"> 101 <div class="panel-body">
84 <div id="collabs"></div> 102 <div id="collabs"></div>
@@ -90,7 +108,7 @@ @@ -90,7 +108,7 @@
90 <div class="col-lg-4 col-md-4 col-sm-7"> 108 <div class="col-lg-4 col-md-4 col-sm-7">
91 <div class="panel panel-default"> 109 <div class="panel panel-default">
92 <div class="panel-heading"> 110 <div class="panel-heading">
93 - <h3 class="panel-title">{% trans "Mailing list Participation" %}</h3> 111 + <h3 class="panel-title">{% trans "Participation by Group" %}</h3>
94 </div> 112 </div>
95 <div class="panel-body"> 113 <div class="panel-body">
96 <div id="collabs2"></div> 114 <div id="collabs2"></div>
@@ -130,6 +148,10 @@ @@ -130,6 +148,10 @@
130 <li>{% trans "There are no posts by this user so far." %}</li> 148 <li>{% trans "There are no posts by this user so far." %}</li>
131 {% endfor %} 149 {% endfor %}
132 </ul> 150 </ul>
  151 + <a href="{% url 'haystack_search' %}?type=thread&amp;author={{ user_.username }}">
  152 + {% trans "View more discussions..." %}
  153 + </a>
  154 + <div>&nbsp;</div>
133 </div> 155 </div>
134 156
135 <div class="col-lg-6 col-md-6 col-sm-12"> 157 <div class="col-lg-6 col-md-6 col-sm-12">
@@ -141,6 +163,10 @@ @@ -141,6 +163,10 @@
141 <li>{% trans "No contributions of this user so far." %}</li> 163 <li>{% trans "No contributions of this user so far." %}</li>
142 {% endfor %} 164 {% endfor %}
143 </ul> 165 </ul>
  166 + <a href="{% url 'haystack_search' %}?order=latest&amp;collaborators={{ user_.username }}">
  167 + {% trans "View more contributions..." %}
  168 + </a>
  169 + <div>&nbsp;</div>
144 </div> 170 </div>
145 171
146 </div> 172 </div>
src/accounts/templates/accounts/user_update_form.html
@@ -178,22 +178,26 @@ $(function() { @@ -178,22 +178,26 @@ $(function() {
178 </div> 178 </div>
179 </div> 179 </div>
180 </div> 180 </div>
  181 + </div>
181 182
182 - <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">  
183 - <div class="panel panel-default">  
184 - <div class="panel-heading">  
185 - <h3 class="panel-title">{% trans "Change SVN and XMPP Client password" %}</h3>  
186 - </div>  
187 - <div class="panel-body">  
188 - <div class="form-group">  
189 - {% trans "You don't need to change this password. Change it only if you really know what you are doing." %}  
190 - </div>  
191 - <a href="{% url 'change_password' %}" class="btn btn-primary pull-right">{% trans "Change Password" %}</a> 183 + <div class="row">
  184 + <div class="col-lg-12">
  185 + <div class="panel panel-default">
  186 + <div class="panel-heading">
  187 + <h3 class="panel-title">
  188 + {% blocktrans %}Change <a href="http://repositorio.interlegis.gov.br/">SVN</a> and <a href="http://mensageiro.interlegis.gov.br/">XMPP Client</a> password{% endblocktrans %}
  189 + </h3>
  190 + </div>
  191 + <div class="panel-body">
  192 + <div class="form-group">
  193 + {% trans "This feature is available only for who needs to change the password for some reason as having an old user with the same username, forgot your password to commit, usage of other XMPP Client for connection. Usually, you won't need to change this password. Only change it if you are sure about what you are doing." %}
192 </div> 194 </div>
  195 + <a href="{% url 'change_password' %}" class="btn btn-default pull-right"><span class="icon-warning-sign"></span> {% trans "Change Password" %}</a>
193 </div> 196 </div>
194 </div> 197 </div>
195 - 198 + </div>
196 </div> 199 </div>
  200 +
197 <div class="row"> 201 <div class="row">
198 <div class="submit"> 202 <div class="submit">
199 <button type="submit" class="btn btn-primary btn-lg btn-block">{% trans "Update" %}</button> 203 <button type="submit" class="btn btn-primary btn-lg btn-block">{% trans "Update" %}</button>
src/accounts/utils/mailman.py
@@ -44,18 +44,22 @@ def update_subscription(address, lists): @@ -44,18 +44,22 @@ def update_subscription(address, lists):
44 subscribe(maillist, address) 44 subscribe(maillist, address)
45 45
46 46
47 -def address_lists(address): 47 +def address_lists(address, description=''):
48 url = get_url() 48 url = get_url()
  49 +
  50 + params = {'address': address,
  51 + 'description': description}
  52 +
49 try: 53 try:
50 - lists = requests.get(url, timeout=TIMEOUT, params={'address': address}) 54 + lists = requests.get(url, timeout=TIMEOUT, params=params)
51 except requests.exceptions.RequestException: 55 except requests.exceptions.RequestException:
52 return [] 56 return []
53 57
54 return lists.json() 58 return lists.json()
55 59
56 60
57 -def all_lists():  
58 - return address_lists('') 61 +def all_lists(*args, **kwargs):
  62 + return address_lists('', *args, **kwargs)
59 63
60 64
61 def user_lists(user): 65 def user_lists(user):
@@ -65,3 +69,12 @@ def user_lists(user): @@ -65,3 +69,12 @@ def user_lists(user):
65 list_set.update(address_lists(email)) 69 list_set.update(address_lists(email))
66 70
67 return tuple(list_set) 71 return tuple(list_set)
  72 +
  73 +
  74 +def get_list_description(listname, lists=None):
  75 + if not lists:
  76 + lists = dict(all_lists(description=True))
  77 + elif not isinstance(lists, dict):
  78 + lists = dict(lists)
  79 +
  80 + return lists.get(listname)
src/accounts/views.py
@@ -23,6 +23,7 @@ from haystack.query import SearchQuerySet @@ -23,6 +23,7 @@ from haystack.query import SearchQuerySet
23 from super_archives.models import EmailAddress, Message 23 from super_archives.models import EmailAddress, Message
24 from super_archives.utils.email import send_email_lists 24 from super_archives.utils.email import send_email_lists
25 from search.utils import trans 25 from search.utils import trans
  26 +from proxy.models import WikiCollabCount, TicketCollabCount
26 from .forms import (UserCreationForm, ListsForm, UserUpdateForm, 27 from .forms import (UserCreationForm, ListsForm, UserUpdateForm,
27 ChangeXMPPPasswordForm) 28 ChangeXMPPPasswordForm)
28 from .errors import XMPPChangePwdException 29 from .errors import XMPPChangePwdException
@@ -65,11 +66,28 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): @@ -65,11 +66,28 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
65 {'fullname_and_username__contains': user.username}, 66 {'fullname_and_username__contains': user.username},
66 ) 67 )
67 68
  69 + counter_class = {
  70 + 'wiki': WikiCollabCount,
  71 + 'ticket': TicketCollabCount,
  72 + }
  73 +
  74 + messages = Message.objects.filter(from_address__user__pk=user.pk)
68 for type in ['thread', 'ticket', 'wiki', 'changeset', 'attachment']: 75 for type in ['thread', 'ticket', 'wiki', 'changeset', 'attachment']:
69 - sqs = SearchQuerySet()  
70 - for filter_or in fields_or_lookup:  
71 - sqs = sqs.filter_or(type=type, **filter_or)  
72 - count_types[trans(type)] = sqs.count() 76 + CounterClass = counter_class.get(type)
  77 + if CounterClass:
  78 + try:
  79 + counter = CounterClass.objects.get(author=user.username)
  80 + except CounterClass.DoesNotExist:
  81 + count_types[trans(type)] = 0
  82 + else:
  83 + count_types[trans(type)] = counter.count
  84 + elif type == 'thread':
  85 + count_types[trans(type)] = messages.count()
  86 + else:
  87 + sqs = SearchQuerySet()
  88 + for filter_or in fields_or_lookup:
  89 + sqs = sqs.filter_or(type=type, **filter_or)
  90 + count_types[trans(type)] = sqs.count()
73 91
74 context['type_count'] = count_types 92 context['type_count'] = count_types
75 93
@@ -85,7 +103,6 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): @@ -85,7 +103,6 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
85 context['emails'] = query[:10] 103 context['emails'] = query[:10]
86 104
87 count_by = 'thread__mailinglist__name' 105 count_by = 'thread__mailinglist__name'
88 - messages = Message.objects.filter(from_address__user__pk=user.pk)  
89 context['list_activity'] = dict(messages.values_list(count_by)\ 106 context['list_activity'] = dict(messages.values_list(count_by)\
90 .annotate(Count(count_by))\ 107 .annotate(Count(count_by))\
91 .order_by(count_by)) 108 .order_by(count_by))
@@ -157,17 +174,20 @@ class ManageUserSubscriptionsView(UserProfileBaseMixin, DetailView): @@ -157,17 +174,20 @@ class ManageUserSubscriptionsView(UserProfileBaseMixin, DetailView):
157 174
158 user = self.get_object() 175 user = self.get_object()
159 emails = user.emails.values_list('address', flat=True) 176 emails = user.emails.values_list('address', flat=True)
160 - all_lists = mailman.all_lists() 177 + all_lists = mailman.all_lists(description=True)
161 178
162 for email in emails: 179 for email in emails:
163 lists = [] 180 lists = []
164 lists_for_address = mailman.address_lists(email) 181 lists_for_address = mailman.address_lists(email)
165 - for listname in all_lists: 182 + for listname, description in all_lists:
166 if listname in lists_for_address: 183 if listname in lists_for_address:
167 checked = True 184 checked = True
168 else: 185 else:
169 checked = False 186 checked = False
170 - lists.append((listname, checked)) 187 + lists.append((
  188 + {'listname': listname, 'description': description},
  189 + checked
  190 + ))
171 191
172 context['membership'].update({email: lists}) 192 context['membership'].update({email: lists})
173 193
src/api/resources.py 0 → 100644
@@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +from django.contrib.auth import get_user_model
  4 +
  5 +from tastypie import fields
  6 +from tastypie.constants import ALL_WITH_RELATIONS, ALL
  7 +from tastypie.resources import ModelResource
  8 +
  9 +from super_archives.models import Message, EmailAddress
  10 +from proxy.models import Revision, Ticket, Wiki
  11 +
  12 +
  13 +User = get_user_model()
  14 +
  15 +
  16 +class UserResource(ModelResource):
  17 + class Meta:
  18 + queryset = User.objects.filter(is_active=True)
  19 + resource_name = 'user'
  20 + fields = ['username', 'institution', 'role', 'bio', 'first_name',
  21 + 'last_name', 'email']
  22 + allowed_methods = ['get', ]
  23 + filtering = {
  24 + 'email': ('exact', ),
  25 + 'username': ALL,
  26 + 'institution': ALL,
  27 + 'role': ALL,
  28 + 'bio': ALL,
  29 + }
  30 +
  31 + def dehydrate_email(self, bundle):
  32 + return ''
  33 +
  34 +
  35 +class EmailAddressResource(ModelResource):
  36 + user = fields.ForeignKey(UserResource, 'user', full=False, null=True)
  37 +
  38 + class Meta:
  39 + queryset = EmailAddress.objects.all()
  40 + resource_name = 'emailaddress'
  41 + excludes = ['md5', ]
  42 + allowed_methods = ['get', ]
  43 + filtering = {
  44 + 'address': ('exact', ),
  45 + 'user': ALL_WITH_RELATIONS,
  46 + 'real_name': ALL,
  47 + }
  48 +
  49 + def dehydrate_address(self, bundle):
  50 + return ''
  51 +
  52 +
  53 +class MessageResource(ModelResource):
  54 + from_address = fields.ForeignKey(EmailAddressResource, 'from_address',
  55 + full=False)
  56 +
  57 + class Meta:
  58 + queryset = Message.objects.all()
  59 + resource_name = 'message'
  60 + excludes = ['spam', 'subject_clean', 'message_id']
  61 + filtering = {
  62 + 'from_address': ALL_WITH_RELATIONS,
  63 + 'subject': ALL,
  64 + 'body': ALL,
  65 + 'received_time': ALL,
  66 + }
  67 +
  68 +
  69 +class RevisionResource(ModelResource):
  70 + class Meta:
  71 + queryset = Revision.objects.all()
  72 + resource_name = 'revision'
  73 + excludes = ['collaborators', ]
  74 + filtering = {
  75 + 'key': ALL,
  76 + 'rev': ALL,
  77 + 'author': ALL,
  78 + 'message': ALL,
  79 + 'repository_name': ALL,
  80 + 'created': ALL,
  81 + }
  82 +
  83 +
  84 +class TicketResource(ModelResource):
  85 + class Meta:
  86 + queryset = Ticket.objects.all()
  87 + resource_name = 'ticket'
  88 + excludes = ['collaborators', ]
  89 + filtering = {
  90 + 'id': ALL,
  91 + 'summary': ALL,
  92 + 'description': ALL,
  93 + 'milestone': ALL,
  94 + 'priority': ALL,
  95 + 'component': ALL,
  96 + 'version': ALL,
  97 + 'severity': ALL,
  98 + 'reporter': ALL,
  99 + 'author': ALL,
  100 + 'status': ALL,
  101 + 'keywords': ALL,
  102 + 'created': ALL,
  103 + 'modified': ALL,
  104 + 'modified_by': ALL,
  105 + }
  106 +
  107 +
  108 +class WikiResource(ModelResource):
  109 + class Meta:
  110 + queryset = Wiki.objects.all()
  111 + resource_name = 'wiki'
  112 + excludes = ['collaborators', ]
  113 + filtering = {
  114 + 'name': ALL,
  115 + 'wiki_text': ALL,
  116 + 'author': ALL,
  117 + 'name': ALL,
  118 + 'created': ALL,
  119 + 'modified': ALL,
  120 + 'modified_by': ALL,
  121 + }
src/api/urls.py
  1 +# -*- coding: utf-8 -*-
1 2
2 from django.conf.urls import patterns, include, url 3 from django.conf.urls import patterns, include, url
3 4
  5 +from tastypie.api import Api
  6 +
  7 +from .resources import (UserResource, EmailAddressResource, MessageResource,
  8 + RevisionResource, TicketResource, WikiResource)
4 from .views import VoteView 9 from .views import VoteView
5 10
6 11
  12 +api = Api(api_name='v1')
  13 +api.register(UserResource())
  14 +api.register(EmailAddressResource())
  15 +api.register(MessageResource())
  16 +api.register(RevisionResource())
  17 +api.register(TicketResource())
  18 +api.register(WikiResource())
  19 +
  20 +
7 urlpatterns = patterns('', 21 urlpatterns = patterns('',
8 url(r'message/(?P<msg_id>\d+)/vote$', VoteView.as_view()), 22 url(r'message/(?P<msg_id>\d+)/vote$', VoteView.as_view()),
  23 +
  24 + # tastypie urls
  25 + url(r'', include(api.urls)),
9 ) 26 )
src/badger/utils.py
@@ -2,16 +2,14 @@ @@ -2,16 +2,14 @@
2 2
3 from django.db.models import Count 3 from django.db.models import Count
4 4
5 -from proxy.models import Revision, Ticket, Wiki 5 +from proxy.models import (Revision, Ticket, Wiki,
  6 + WikiCollabCount, TicketCollabCount)
6 from accounts.models import User 7 from accounts.models import User
7 8
8 9
9 def get_wiki_counters(): 10 def get_wiki_counters():
10 - return {  
11 - author: count for author, count in Wiki.objects.values_list(  
12 - 'author'  
13 - ).annotate(count=Count('author'))  
14 - } 11 + return {author: count for author, count in
  12 + WikiCollabCount.objects.values_list()}
15 13
16 14
17 def get_revision_counters(): 15 def get_revision_counters():
@@ -23,11 +21,8 @@ def get_revision_counters(): @@ -23,11 +21,8 @@ def get_revision_counters():
23 21
24 22
25 def get_ticket_counters(): 23 def get_ticket_counters():
26 - return {  
27 - author: count for author, count in Ticket.objects.values_list(  
28 - 'author'  
29 - ).annotate(count=Count('author'))  
30 - } 24 + return {author: count for author, count in
  25 + TicketCollabCount.objects.values_list()}
31 26
32 27
33 def get_users_counters(): 28 def get_users_counters():
src/colab/custom_settings.py
@@ -210,6 +210,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( @@ -210,6 +210,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
210 'django_browserid.context_processors.browserid', 210 'django_browserid.context_processors.browserid',
211 'django_mobile.context_processors.is_mobile', 211 'django_mobile.context_processors.is_mobile',
212 'super_archives.context_processors.mailarchive', 212 'super_archives.context_processors.mailarchive',
  213 + 'home.context_processors.robots',
213 ) 214 )
214 215
215 MIDDLEWARE_CLASSES = ( 216 MIDDLEWARE_CLASSES = (
@@ -294,6 +295,12 @@ REVPROXY_ADD_REMOTE_USER = True @@ -294,6 +295,12 @@ REVPROXY_ADD_REMOTE_USER = True
294 CONVERSEJS_BOSH_SERVICE_URL = SITE_URL + '/http-bind' 295 CONVERSEJS_BOSH_SERVICE_URL = SITE_URL + '/http-bind'
295 296
296 CONVERSEJS_AUTO_REGISTER = 'mensageiro.interlegis.gov.br' 297 CONVERSEJS_AUTO_REGISTER = 'mensageiro.interlegis.gov.br'
  298 +CONVERSEJS_ALLOW_CONTACT_REQUESTS = False
  299 +CONVERSEJS_SHOW_ONLY_ONLINE_USERS = True
  300 +
  301 +
  302 +# Tastypie settings
  303 +TASTYPIE_DEFAULT_FORMATS = ['json', ]
297 304
298 305
299 try: 306 try:
src/colab/local_settings-dev.py
@@ -38,3 +38,5 @@ COLAB_CI_URL = &#39;http://localhost:8080/ci/&#39; @@ -38,3 +38,5 @@ COLAB_CI_URL = &#39;http://localhost:8080/ci/&#39;
38 CONVERSEJS_ENABLED = False 38 CONVERSEJS_ENABLED = False
39 39
40 DIAZO_THEME = SITE_URL 40 DIAZO_THEME = SITE_URL
  41 +
  42 +ROBOTS_NOINDEX = True
src/colab/urls.py
@@ -12,6 +12,10 @@ admin.autodiscover() @@ -12,6 +12,10 @@ admin.autodiscover()
12 12
13 urlpatterns = patterns('', 13 urlpatterns = patterns('',
14 url(r'^$', 'home.views.index', name='home'), 14 url(r'^$', 'home.views.index', name='home'),
  15 + url(r'^robots.txt$', 'home.views.robots', name='robots'),
  16 +
  17 + url(r'^open-data/$', TemplateView.as_view(template_name='open-data.html'),
  18 + name='opendata'),
15 19
16 url(r'^search/', include('search.urls')), 20 url(r'^search/', include('search.urls')),
17 url(r'^archives/', include('super_archives.urls')), 21 url(r'^archives/', include('super_archives.urls')),
src/home/context_processors.py 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +from django.conf import settings
  2 +
  3 +def robots(request):
  4 + return {'ROBOTS_NOINDEX': getattr(settings, 'ROBOTS_NOINDEX', False)}
src/home/views.py
1 1
2 from collections import OrderedDict 2 from collections import OrderedDict
3 3
  4 +from django.conf import settings
  5 +from django.core.cache import cache
4 from django.shortcuts import render 6 from django.shortcuts import render
5 -from django.utils import timezone 7 +from django.http import HttpResponse, Http404
6 8
7 from search.utils import trans 9 from search.utils import trans
8 from haystack.query import SearchQuerySet 10 from haystack.query import SearchQuerySet
9 11
  12 +from proxy.models import WikiCollabCount, TicketCollabCount
10 from super_archives.models import Thread 13 from super_archives.models import Thread
11 14
12 15
@@ -17,13 +20,22 @@ def index(request): @@ -17,13 +20,22 @@ def index(request):
17 latest_threads = Thread.objects.all()[:6] 20 latest_threads = Thread.objects.all()[:6]
18 hottest_threads = Thread.highest_score.from_haystack()[:6] 21 hottest_threads = Thread.highest_score.from_haystack()[:6]
19 22
20 - count_types = OrderedDict()  
21 - six_months = timezone.now() - timezone.timedelta(days=180)  
22 - for type in ['thread', 'ticket', 'wiki', 'changeset', 'attachment']:  
23 - count_types[trans(type)] = SearchQuerySet().filter(  
24 - type=type,  
25 - modified__gte=six_months,  
26 - ).count() 23 + count_types = cache.get('home_chart')
  24 + if count_types is None:
  25 + count_types = OrderedDict()
  26 + for type in ['thread', 'changeset', 'attachment']:
  27 + count_types[trans(type)] = SearchQuerySet().filter(
  28 + type=type,
  29 + ).count()
  30 +
  31 + count_types[trans('ticket')] = sum([
  32 + ticket.count for ticket in TicketCollabCount.objects.all()
  33 + ])
  34 +
  35 + count_types[trans('wiki')] = sum([
  36 + wiki.count for wiki in WikiCollabCount.objects.all()
  37 + ])
  38 + cache.set('home_chart', count_types)
27 39
28 context = { 40 context = {
29 'hottest_threads': hottest_threads[:6], 41 'hottest_threads': hottest_threads[:6],
@@ -34,3 +46,11 @@ def index(request): @@ -34,3 +46,11 @@ def index(request):
34 )[:6], 46 )[:6],
35 } 47 }
36 return render(request, 'home.html', context) 48 return render(request, 'home.html', context)
  49 +
  50 +
  51 +def robots(request):
  52 + if getattr(settings, 'ROBOTS_NOINDEX', False):
  53 + return HttpResponse('User-agent: *\nDisallow: /',
  54 + content_type='text/plain')
  55 +
  56 + raise Http404
src/locale/pt_BR/LC_MESSAGES/django.mo
No preview for this file type
src/locale/pt_BR/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid &quot;&quot; @@ -7,7 +7,7 @@ msgid &quot;&quot;
7 msgstr "" 7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n" 8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n" 9 "Report-Msgid-Bugs-To: \n"
10 -"POT-Creation-Date: 2013-11-26 13:17+0000\n" 10 +"POT-Creation-Date: 2013-12-19 11:20+0000\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n" 13 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -29,35 +29,52 @@ msgstr &quot;Permissões&quot; @@ -29,35 +29,52 @@ msgstr &quot;Permissões&quot;
29 msgid "Important dates" 29 msgid "Important dates"
30 msgstr "Datas importantes" 30 msgstr "Datas importantes"
31 31
32 -#: accounts/forms.py:24 32 +#: accounts/forms.py:25
33 msgid "Social account does not exist" 33 msgid "Social account does not exist"
34 msgstr "Conta social não existe" 34 msgstr "Conta social não existe"
35 35
36 -#: accounts/forms.py:65 36 +#: accounts/forms.py:56 accounts/templates/accounts/user_detail.html:34
  37 +msgid "Bio"
  38 +msgstr "Bio"
  39 +
  40 +#: accounts/forms.py:57
  41 +msgid "Write something about you in 200 characters or less."
  42 +msgstr "Escreva algo sobre você em 200 caracteres ou menos."
  43 +
  44 +#: accounts/forms.py:76
37 msgid "Mailing lists" 45 msgid "Mailing lists"
38 msgstr "Listas de e-mail" 46 msgstr "Listas de e-mail"
39 47
40 -#: accounts/forms.py:72 48 +#: accounts/forms.py:83
41 msgid "Password" 49 msgid "Password"
42 msgstr "Senha" 50 msgstr "Senha"
43 51
44 -#: accounts/forms.py:74 52 +#: accounts/forms.py:85
45 msgid "Password confirmation" 53 msgid "Password confirmation"
46 msgstr "Confirmação de senha" 54 msgstr "Confirmação de senha"
47 55
48 -#: accounts/forms.py:76 56 +#: accounts/forms.py:87
49 msgid "Enter the same password as above, for verification." 57 msgid "Enter the same password as above, for verification."
50 msgstr "Digite a mesma senha que acima, para verificação." 58 msgstr "Digite a mesma senha que acima, para verificação."
51 59
52 -#: accounts/forms.py:94 60 +#: accounts/forms.py:105
53 msgid "Password mismatch" 61 msgid "Password mismatch"
54 msgstr "Senhas diferentes" 62 msgstr "Senhas diferentes"
55 63
56 -#: accounts/views.py:127 64 +#: accounts/models.py:59
  65 +msgid "Required. 30 characters or fewer. Letters, digits and ./+/-/_ only."
  66 +msgstr ""
  67 +"Obrigatório. 30 caracteres ou menos. Letras, números e ./+/-/_ somente."
  68 +
  69 +#: accounts/models.py:64
  70 +msgid "Enter a valid username."
  71 +msgstr "Insira um nome de usuário válido."
  72 +
  73 +#: accounts/views.py:144
57 msgid "Your profile has been created!" 74 msgid "Your profile has been created!"
58 msgstr "Seu perfil foi criado!" 75 msgstr "Seu perfil foi criado!"
59 76
60 -#: accounts/views.py:128 77 +#: accounts/views.py:145
61 msgid "" 78 msgid ""
62 "You must login to validated your profile. Profiles not validated are deleted " 79 "You must login to validated your profile. Profiles not validated are deleted "
63 "in 24h." 80 "in 24h."
@@ -65,12 +82,12 @@ msgstr &quot;&quot; @@ -65,12 +82,12 @@ msgstr &quot;&quot;
65 "Você deve se logar para validar seu perfil. Perfis não validados serão " 82 "Você deve se logar para validar seu perfil. Perfis não validados serão "
66 "deletados em 24h." 83 "deletados em 24h."
67 84
68 -#: accounts/views.py:209 85 +#: accounts/views.py:229
69 msgid "Could not change your password. Please, try again later." 86 msgid "Could not change your password. Please, try again later."
70 msgstr "" 87 msgstr ""
71 "Não conseguimos alterar sua senha. Por favor, tente novamente mais tarde." 88 "Não conseguimos alterar sua senha. Por favor, tente novamente mais tarde."
72 89
73 -#: accounts/views.py:218 90 +#: accounts/views.py:238
74 msgid "You've changed your password successfully!" 91 msgid "You've changed your password successfully!"
75 msgstr "Senha alterada com sucesso!" 92 msgstr "Senha alterada com sucesso!"
76 93
@@ -81,16 +98,16 @@ msgstr &quot;%(count)s usuários deletados.&quot; @@ -81,16 +98,16 @@ msgstr &quot;%(count)s usuários deletados.&quot;
81 98
82 #: accounts/templates/accounts/change_password.html:8 99 #: accounts/templates/accounts/change_password.html:8
83 msgid "Change XMPP Client and SVN Password" 100 msgid "Change XMPP Client and SVN Password"
84 -msgstr "Trocar senha do SVN e do Mensageiro" 101 +msgstr "Trocar senha do Repositório e do Mensageiro"
85 102
86 #: accounts/templates/accounts/change_password.html:17 103 #: accounts/templates/accounts/change_password.html:17
87 -#: accounts/templates/accounts/user_update_form.html:191 104 +#: accounts/templates/accounts/user_update_form.html:195
88 msgid "Change Password" 105 msgid "Change Password"
89 msgstr "Trocar senha" 106 msgstr "Trocar senha"
90 107
91 #: accounts/templates/accounts/manage_subscriptions.html:6 108 #: accounts/templates/accounts/manage_subscriptions.html:6
92 -msgid "Mailing List Subscriptions"  
93 -msgstr "Inscrições em listas de e-mails" 109 +msgid "Group Subscriptions"
  110 +msgstr "Inscrições em grupos"
94 111
95 #: accounts/templates/accounts/manage_subscriptions.html:36 112 #: accounts/templates/accounts/manage_subscriptions.html:36
96 msgid "Update subscriptions" 113 msgid "Update subscriptions"
@@ -113,65 +130,82 @@ msgid &quot;Personal Information&quot; @@ -113,65 +130,82 @@ msgid &quot;Personal Information&quot;
113 msgstr "Informações pessoais" 130 msgstr "Informações pessoais"
114 131
115 #: accounts/templates/accounts/user_create_form.html:46 132 #: accounts/templates/accounts/user_create_form.html:46
116 -msgid "Subscribe to mail lists"  
117 -msgstr "Inscreva-se para listas de e-mails" 133 +msgid "Subscribe to groups"
  134 +msgstr "Inscreva-se nos grupos"
118 135
119 -#: accounts/templates/accounts/user_create_form.html:60 templates/base.html:97 136 +#: accounts/templates/accounts/user_create_form.html:60 templates/base.html:98
120 msgid "Register" 137 msgid "Register"
121 msgstr "Cadastre-se" 138 msgstr "Cadastre-se"
122 139
123 #: accounts/templates/accounts/user_detail.html:25 140 #: accounts/templates/accounts/user_detail.html:25
124 -msgid "profile"  
125 -msgstr "perfil" 141 +msgid "edit profile"
  142 +msgstr "editar perfil"
126 143
127 #: accounts/templates/accounts/user_detail.html:26 144 #: accounts/templates/accounts/user_detail.html:26
128 -msgid "list membership"  
129 -msgstr "participação em listas" 145 +msgid "group membership"
  146 +msgstr "Inscrições nos grupos"
130 147
131 -#: accounts/templates/accounts/user_detail.html:51 148 +#: accounts/templates/accounts/user_detail.html:61
132 msgid "Twitter account" 149 msgid "Twitter account"
133 msgstr "Conta Twitter" 150 msgstr "Conta Twitter"
134 151
135 -#: accounts/templates/accounts/user_detail.html:54 152 +#: accounts/templates/accounts/user_detail.html:64
136 msgid "Facebook account" 153 msgid "Facebook account"
137 msgstr "Conta Facebook" 154 msgstr "Conta Facebook"
138 155
139 -#: accounts/templates/accounts/user_detail.html:62 156 +#: accounts/templates/accounts/user_detail.html:69
  157 +msgid "Google talk account"
  158 +msgstr "Conta Google"
  159 +
  160 +#: accounts/templates/accounts/user_detail.html:73
  161 +msgid "Github account"
  162 +msgstr "Conta Github"
  163 +
  164 +#: accounts/templates/accounts/user_detail.html:77
140 msgid "Personal webpage" 165 msgid "Personal webpage"
141 msgstr "Página web pessoal" 166 msgstr "Página web pessoal"
142 167
143 -#: accounts/templates/accounts/user_detail.html:68  
144 -msgid "Subscribes: "  
145 -msgstr "Inscrições: " 168 +#: accounts/templates/accounts/user_detail.html:83
  169 +msgid "Groups: "
  170 +msgstr "Grupos: "
146 171
147 -#: accounts/templates/accounts/user_detail.html:81  
148 -msgid "Contributions by Area"  
149 -msgstr "Contribuições por área" 172 +#: accounts/templates/accounts/user_detail.html:96
  173 +msgid "Contributions by Type"
  174 +msgstr "Contribuições por tipo"
150 175
151 -#: accounts/templates/accounts/user_detail.html:93  
152 -msgid "Mailing list Participation"  
153 -msgstr "Participação em listas de e-mail" 176 +#: accounts/templates/accounts/user_detail.html:108
  177 +msgid "Participation by Group"
  178 +msgstr "Participação por grupo"
154 179
155 -#: accounts/templates/accounts/user_detail.html:106 badger/models.py:71 180 +#: accounts/templates/accounts/user_detail.html:121 badger/models.py:70
156 msgid "Badges" 181 msgid "Badges"
157 msgstr "Medalhas" 182 msgstr "Medalhas"
158 183
159 -#: accounts/templates/accounts/user_detail.html:125 184 +#: accounts/templates/accounts/user_detail.html:140
160 msgid "Latest posted" 185 msgid "Latest posted"
161 msgstr "Últimas postagens" 186 msgstr "Últimas postagens"
162 187
163 -#: accounts/templates/accounts/user_detail.html:130 188 +#: accounts/templates/accounts/user_detail.html:145
164 msgid "There are no posts by this user so far." 189 msgid "There are no posts by this user so far."
165 msgstr "Não há posts deste usuário até agora." 190 msgstr "Não há posts deste usuário até agora."
166 191
167 -#: accounts/templates/accounts/user_detail.html:136 badger/models.py:24 192 +#: accounts/templates/accounts/user_detail.html:149 templates/home.html:57
  193 +#: templates/home.html.py:76
  194 +msgid "View more discussions..."
  195 +msgstr "Ver mais discussões..."
  196 +
  197 +#: accounts/templates/accounts/user_detail.html:155 badger/models.py:23
168 msgid "Contributions" 198 msgid "Contributions"
169 msgstr "Contribuições" 199 msgstr "Contribuições"
170 200
171 -#: accounts/templates/accounts/user_detail.html:141 201 +#: accounts/templates/accounts/user_detail.html:160
172 msgid "No contributions of this user so far." 202 msgid "No contributions of this user so far."
173 msgstr "Não há posts deste usuário até agora." 203 msgstr "Não há posts deste usuário até agora."
174 204
  205 +#: accounts/templates/accounts/user_detail.html:164
  206 +msgid "View more contributions..."
  207 +msgstr "Ver mais colaborações..."
  208 +
175 #: accounts/templates/accounts/user_update_form.html:65 209 #: accounts/templates/accounts/user_update_form.html:65
176 msgid "We sent a verification email to " 210 msgid "We sent a verification email to "
177 msgstr "Enviamos um email de verificação para " 211 msgstr "Enviamos um email de verificação para "
@@ -229,96 +263,115 @@ msgstr &quot;Adicionar outro endereço de e-mail&quot; @@ -229,96 +263,115 @@ msgstr &quot;Adicionar outro endereço de e-mail&quot;
229 msgid "Add" 263 msgid "Add"
230 msgstr "Adicionar" 264 msgstr "Adicionar"
231 265
232 -#: accounts/templates/accounts/user_update_form.html:185  
233 -msgid "Change SVN and XMPP Client password"  
234 -msgstr "Trocar a senha do SVN e do Mensageiro" 266 +#: accounts/templates/accounts/user_update_form.html:188
  267 +msgid ""
  268 +"Change <a href=\"http://repositorio.interlegis.gov.br/\">SVN</a> and <a href="
  269 +"\"http://mensageiro.interlegis.gov.br/\">XMPP Client</a> password"
  270 +msgstr ""
  271 +"Trocar a senha do <a href=\"http://repositorio.interlegis.gov.br/"
  272 +"\">Repositório</a> e do <a href=\"http://mensageiro.interlegis.gov.br/"
  273 +"\">Mensageiro</a>"
235 274
236 -#: accounts/templates/accounts/user_update_form.html:189 275 +#: accounts/templates/accounts/user_update_form.html:193
237 msgid "" 276 msgid ""
238 -"You don't need to change this password. Change it only if you really know "  
239 -"what you are doing." 277 +"This feature is available only for who needs to change the password for some "
  278 +"reason as having an old user with the same username, forgot your password to "
  279 +"commit, usage of other XMPP Client for connection. Usually, you won't need "
  280 +"to change this password. Only change it if you are sure about what you are "
  281 +"doing."
240 msgstr "" 282 msgstr ""
241 -"Você não precisa trocar essa senha. Troque-a somente se tem certeza do que "  
242 -"está fazendo." 283 +"Este recurso está disponível para quem precisa trocar a senha por algum "
  284 +"motivo como ter um usuário antigo com mesmo nome de usuário, esqueceu da "
  285 +"senha antiga para commit, uso de outro cliente XMPP para conexão. "
  286 +"Normalmente, você não terá que trocar essa senha. Somente troque essa senha "
  287 +"se tiver certeza do que está fazendo."
243 288
244 -#: accounts/templates/accounts/user_update_form.html:199 289 +#: accounts/templates/accounts/user_update_form.html:203
245 msgid "Update" 290 msgid "Update"
246 msgstr "Atualizar" 291 msgstr "Atualizar"
247 292
248 -#: badger/models.py:13 293 +#: badger/forms.py:19 badger/models.py:40 colab/custom_settings.py:53
  294 +msgid "Image"
  295 +msgstr "Imagem"
  296 +
  297 +#: badger/forms.py:30
  298 +msgid "You must add an Image"
  299 +msgstr "Você deve adicionar uma imagem"
  300 +
  301 +#: badger/models.py:12
249 msgid "Greater than or equal" 302 msgid "Greater than or equal"
250 msgstr "Maior que ou igual" 303 msgstr "Maior que ou igual"
251 304
252 -#: badger/models.py:14 305 +#: badger/models.py:13
253 msgid "less than or equal" 306 msgid "less than or equal"
254 msgstr "menor que ou igual" 307 msgstr "menor que ou igual"
255 308
256 -#: badger/models.py:15 309 +#: badger/models.py:14
257 msgid "Equal" 310 msgid "Equal"
258 msgstr "Igual" 311 msgstr "Igual"
259 312
260 -#: badger/models.py:16 313 +#: badger/models.py:15
261 msgid "Biggest" 314 msgid "Biggest"
262 msgstr "Maior" 315 msgstr "Maior"
263 316
264 -#: badger/models.py:19 317 +#: badger/models.py:18
265 msgid "Automatically" 318 msgid "Automatically"
266 msgstr "Automaticamente" 319 msgstr "Automaticamente"
267 320
268 -#: badger/models.py:20 321 +#: badger/models.py:19
269 msgid "Manual" 322 msgid "Manual"
270 msgstr "Manual" 323 msgstr "Manual"
271 324
272 -#: badger/models.py:23 super_archives/models.py:258 325 +#: badger/models.py:22 super_archives/models.py:258
273 msgid "Messages" 326 msgid "Messages"
274 msgstr "Mensagens" 327 msgstr "Mensagens"
275 328
276 -#: badger/models.py:25 329 +#: badger/models.py:24
277 msgid "Wikis" 330 msgid "Wikis"
278 msgstr "Wikis" 331 msgstr "Wikis"
279 332
280 -#: badger/models.py:26 333 +#: badger/models.py:25
281 msgid "Revisions" 334 msgid "Revisions"
282 msgstr "Conjunto de mudanças" 335 msgstr "Conjunto de mudanças"
283 336
284 -#: badger/models.py:27 search/views.py:42 337 +#: badger/models.py:26 search/views.py:42
285 #: search/templates/search/includes/search_filters.html:124 338 #: search/templates/search/includes/search_filters.html:124
286 msgid "Ticket" 339 msgid "Ticket"
287 msgstr "Tíquetes" 340 msgstr "Tíquetes"
288 341
289 -#: badger/models.py:37 342 +#: badger/models.py:36
290 msgid "Title" 343 msgid "Title"
291 msgstr "Título" 344 msgstr "Título"
292 345
293 -#: badger/models.py:39 346 +#: badger/models.py:38
294 msgid "Description" 347 msgid "Description"
295 msgstr "Descrição" 348 msgstr "Descrição"
296 349
297 -#: badger/models.py:42 search/forms.py:18 350 +#: badger/models.py:41 search/forms.py:18
298 msgid "Type" 351 msgid "Type"
299 msgstr "Tipo" 352 msgstr "Tipo"
300 353
301 -#: badger/models.py:44 354 +#: badger/models.py:43
302 msgid "User attribute" 355 msgid "User attribute"
303 msgstr "Atributo do usuário" 356 msgstr "Atributo do usuário"
304 357
305 -#: badger/models.py:50 358 +#: badger/models.py:49
306 msgid "Comparison" 359 msgid "Comparison"
307 msgstr "Comparação" 360 msgstr "Comparação"
308 361
309 -#: badger/models.py:57 362 +#: badger/models.py:56
310 msgid "Value" 363 msgid "Value"
311 msgstr "Valor" 364 msgstr "Valor"
312 365
313 -#: badger/models.py:63 366 +#: badger/models.py:62
314 msgid "Awardees" 367 msgid "Awardees"
315 msgstr "Premiados" 368 msgstr "Premiados"
316 369
317 -#: badger/models.py:67 370 +#: badger/models.py:66
318 msgid "Order" 371 msgid "Order"
319 msgstr "Ordem" 372 msgstr "Ordem"
320 373
321 -#: badger/models.py:70 374 +#: badger/models.py:69
322 msgid "Badge" 375 msgid "Badge"
323 msgstr "Medalha" 376 msgstr "Medalha"
324 377
@@ -362,19 +415,15 @@ msgstr &quot;Código&quot; @@ -362,19 +415,15 @@ msgstr &quot;Código&quot;
362 msgid "Compressed" 415 msgid "Compressed"
363 msgstr "Compactado" 416 msgstr "Compactado"
364 417
365 -#: colab/custom_settings.py:53  
366 -msgid "Image"  
367 -msgstr "Imagem"  
368 -  
369 #: colab/custom_settings.py:55 418 #: colab/custom_settings.py:55
370 msgid "Spreadsheet" 419 msgid "Spreadsheet"
371 msgstr "Planilha" 420 msgstr "Planilha"
372 421
373 -#: colab/custom_settings.py:263 422 +#: colab/custom_settings.py:265
374 msgid "Planet Colab" 423 msgid "Planet Colab"
375 msgstr "" 424 msgstr ""
376 425
377 -#: colab/custom_settings.py:264 426 +#: colab/custom_settings.py:266
378 msgid "Colab blog aggregator" 427 msgid "Colab blog aggregator"
379 msgstr "Agregador de blog Colab" 428 msgstr "Agregador de blog Colab"
380 429
@@ -390,9 +439,9 @@ msgstr &quot;em&quot; @@ -390,9 +439,9 @@ msgstr &quot;em&quot;
390 msgid "Read original" 439 msgid "Read original"
391 msgstr "Leia o original" 440 msgstr "Leia o original"
392 441
393 -#: planet/templates/feedzilla/base.html:5 templates/base.html:75  
394 -msgid "Planet"  
395 -msgstr "" 442 +#: planet/templates/feedzilla/base.html:5
  443 +msgid "Planet - Community Blogs"
  444 +msgstr "Planet - Blogs da comunidade"
396 445
397 #: planet/templates/feedzilla/base.html:15 446 #: planet/templates/feedzilla/base.html:15
398 msgid "Tags" 447 msgid "Tags"
@@ -402,7 +451,7 @@ msgstr &quot;Etiquetas&quot; @@ -402,7 +451,7 @@ msgstr &quot;Etiquetas&quot;
402 msgid "Source Blogs" 451 msgid "Source Blogs"
403 msgstr "Blogs de origem" 452 msgstr "Blogs de origem"
404 453
405 -#: planet/templates/feedzilla/base.html:22 454 +#: planet/templates/feedzilla/base.html:23
406 #: planet/templates/feedzilla/submit_blog.html:5 455 #: planet/templates/feedzilla/submit_blog.html:5
407 msgid "Submit a blog" 456 msgid "Submit a blog"
408 msgstr "Sugerir um blog" 457 msgstr "Sugerir um blog"
@@ -456,7 +505,7 @@ msgid &quot;Latest collaborations&quot; @@ -456,7 +505,7 @@ msgid &quot;Latest collaborations&quot;
456 msgstr "Últimas colaborações" 505 msgstr "Últimas colaborações"
457 506
458 #: search/forms.py:16 search/templates/search/search.html:41 507 #: search/forms.py:16 search/templates/search/search.html:41
459 -#: templates/base.html:91 508 +#: templates/base.html:92
460 msgid "Search" 509 msgid "Search"
461 msgstr "Busca" 510 msgstr "Busca"
462 511
@@ -465,89 +514,93 @@ msgstr &quot;Busca&quot; @@ -465,89 +514,93 @@ msgstr &quot;Busca&quot;
465 msgid "Author" 514 msgid "Author"
466 msgstr "Autor" 515 msgstr "Autor"
467 516
468 -#: search/forms.py:21 search/views.py:70 517 +#: search/forms.py:20
  518 +msgid "Modified by"
  519 +msgstr "Modificado por"
  520 +
  521 +#: search/forms.py:22 search/views.py:70
469 msgid "Status" 522 msgid "Status"
470 msgstr "" 523 msgstr ""
471 524
472 -#: search/forms.py:25 search/views.py:36 525 +#: search/forms.py:26 search/views.py:36
473 msgid "Mailinglist" 526 msgid "Mailinglist"
474 msgstr "Lista de email" 527 msgstr "Lista de email"
475 528
476 -#: search/forms.py:29 search/views.py:46 529 +#: search/forms.py:30 search/views.py:46
477 msgid "Milestone" 530 msgid "Milestone"
478 msgstr "Etapa" 531 msgstr "Etapa"
479 532
480 -#: search/forms.py:30 search/views.py:51 533 +#: search/forms.py:31 search/views.py:51
481 msgid "Priority" 534 msgid "Priority"
482 msgstr "Prioridade" 535 msgstr "Prioridade"
483 536
484 -#: search/forms.py:31 search/views.py:56 537 +#: search/forms.py:32 search/views.py:56
485 msgid "Component" 538 msgid "Component"
486 msgstr "Componente" 539 msgstr "Componente"
487 540
488 -#: search/forms.py:32 search/views.py:61 541 +#: search/forms.py:33 search/views.py:61
489 msgid "Severity" 542 msgid "Severity"
490 msgstr "Seriedade" 543 msgstr "Seriedade"
491 544
492 -#: search/forms.py:33 search/views.py:66 545 +#: search/forms.py:34 search/views.py:66
493 msgid "Reporter" 546 msgid "Reporter"
494 msgstr "Relator" 547 msgstr "Relator"
495 548
496 -#: search/forms.py:34 search/views.py:73 549 +#: search/forms.py:35 search/views.py:73
497 msgid "Keywords" 550 msgid "Keywords"
498 msgstr "Palavras chaves" 551 msgstr "Palavras chaves"
499 552
500 -#: search/forms.py:35 search/views.py:25 search/views.py:78 553 +#: search/forms.py:36 search/views.py:25 search/views.py:78
501 msgid "Collaborators" 554 msgid "Collaborators"
502 msgstr "Colaboradores" 555 msgstr "Colaboradores"
503 556
504 -#: search/forms.py:36 search/views.py:89 557 +#: search/forms.py:37 search/views.py:89
505 msgid "Repository" 558 msgid "Repository"
506 msgstr "Repositório" 559 msgstr "Repositório"
507 560
508 -#: search/forms.py:37 search/views.py:99 561 +#: search/forms.py:38 search/views.py:99
509 msgid "Username" 562 msgid "Username"
510 msgstr "Usuário" 563 msgstr "Usuário"
511 564
512 -#: search/forms.py:38 search/views.py:102 565 +#: search/forms.py:39 search/views.py:102
513 msgid "Name" 566 msgid "Name"
514 msgstr "Nome" 567 msgstr "Nome"
515 568
516 -#: search/forms.py:39 search/views.py:105 569 +#: search/forms.py:40 search/views.py:105
517 msgid "Institution" 570 msgid "Institution"
518 msgstr "Instituição" 571 msgstr "Instituição"
519 572
520 -#: search/forms.py:40 search/views.py:108 573 +#: search/forms.py:41 search/views.py:108
521 msgid "Role" 574 msgid "Role"
522 msgstr "Cargo" 575 msgstr "Cargo"
523 576
524 -#: search/forms.py:41 search/templates/search/includes/search_filters.html:151 577 +#: search/forms.py:42 search/templates/search/includes/search_filters.html:151
525 #: search/templates/search/includes/search_filters.html:153 578 #: search/templates/search/includes/search_filters.html:153
526 #: search/templates/search/includes/search_filters.html:185 579 #: search/templates/search/includes/search_filters.html:185
527 #: search/templates/search/includes/search_filters.html:186 580 #: search/templates/search/includes/search_filters.html:186
528 msgid "Since" 581 msgid "Since"
529 msgstr "Desde" 582 msgstr "Desde"
530 583
531 -#: search/forms.py:42 search/templates/search/includes/search_filters.html:160 584 +#: search/forms.py:43 search/templates/search/includes/search_filters.html:160
532 #: search/templates/search/includes/search_filters.html:162 585 #: search/templates/search/includes/search_filters.html:162
533 #: search/templates/search/includes/search_filters.html:189 586 #: search/templates/search/includes/search_filters.html:189
534 #: search/templates/search/includes/search_filters.html:190 587 #: search/templates/search/includes/search_filters.html:190
535 msgid "Until" 588 msgid "Until"
536 msgstr "Até" 589 msgstr "Até"
537 590
538 -#: search/forms.py:43 search/views.py:116 591 +#: search/forms.py:44 search/views.py:116
539 msgid "Filename" 592 msgid "Filename"
540 msgstr "Nome do arquivo" 593 msgstr "Nome do arquivo"
541 594
542 -#: search/forms.py:44 search/views.py:122 595 +#: search/forms.py:45 search/views.py:122
543 msgid "Used by" 596 msgid "Used by"
544 msgstr "Usado por" 597 msgstr "Usado por"
545 598
546 -#: search/forms.py:45 search/views.py:125 599 +#: search/forms.py:46 search/views.py:125
547 msgid "File type" 600 msgid "File type"
548 msgstr "Tipo do arquivo" 601 msgstr "Tipo do arquivo"
549 602
550 -#: search/forms.py:46 search/views.py:128 603 +#: search/forms.py:47 search/views.py:128
551 msgid "Size" 604 msgid "Size"
552 msgstr "Tamanho" 605 msgstr "Tamanho"
553 606
@@ -627,7 +680,9 @@ msgstr &quot;Ordenar por&quot; @@ -627,7 +680,9 @@ msgstr &quot;Ordenar por&quot;
627 msgid "Types" 680 msgid "Types"
628 msgstr "Tipos" 681 msgstr "Tipos"
629 682
630 -#: super_archives/models.py:62 super_archives/templates/message-thread.html:4 683 +#: super_archives/models.py:62
  684 +#: super_archives/templates/message-preview.html:62
  685 +#: super_archives/templates/message-thread.html:4
631 msgid "Anonymous" 686 msgid "Anonymous"
632 msgstr "Anônimo" 687 msgstr "Anônimo"
633 688
@@ -683,35 +738,37 @@ msgstr &quot;Por favor, digite o corpo da mensagem&quot; @@ -683,35 +738,37 @@ msgstr &quot;Por favor, digite o corpo da mensagem&quot;
683 msgid "Message" 738 msgid "Message"
684 msgstr "Mensagem" 739 msgstr "Mensagem"
685 740
686 -#: super_archives/views.py:90 741 +#: super_archives/views.py:92
687 msgid "Error trying to connect to Mailman API" 742 msgid "Error trying to connect to Mailman API"
688 msgstr "Erro na conexão com a API do Mailman" 743 msgstr "Erro na conexão com a API do Mailman"
689 744
690 -#: super_archives/views.py:93 745 +#: super_archives/views.py:95
691 msgid "Timeout trying to connect to Mailman API" 746 msgid "Timeout trying to connect to Mailman API"
692 msgstr "Tempo de espera esgotado na conexão com a API do Mailman" 747 msgstr "Tempo de espera esgotado na conexão com a API do Mailman"
693 748
694 -#: super_archives/views.py:96 749 +#: super_archives/views.py:99
695 msgid "" 750 msgid ""
696 -"Your message was sent. It may take some minutes before it's delivered. Why "  
697 -"don't you breath some fresh air in the meanwhile?" 751 +"Your message was sent to this topic. It may take some minutes before it's "
  752 +"delivered by email to the group. Why don't you breath some fresh air in the "
  753 +"meanwhile?"
698 msgstr "" 754 msgstr ""
699 -"Sua mensagem foi enviada. Pode levar alguns minutos antes de ser entregue. "  
700 -"Por quê você respira um ar fresco enquanto isso?" 755 +"Sua mensagem foi enviada para esse tópico. Pode levar alguns minutos até ser "
  756 +"entregue via e-mail para o grupo. Por quê você não respira um ar fresco "
  757 +"enquanto isso?"
701 758
702 -#: super_archives/views.py:104 759 +#: super_archives/views.py:108
703 msgid "You cannot send an empty email" 760 msgid "You cannot send an empty email"
704 msgstr "Você não pode enviar um e-mail vazio" 761 msgstr "Você não pode enviar um e-mail vazio"
705 762
706 -#: super_archives/views.py:106 763 +#: super_archives/views.py:110
707 msgid "Mailing list does not exist" 764 msgid "Mailing list does not exist"
708 msgstr "Lista de e-mail não existe" 765 msgstr "Lista de e-mail não existe"
709 766
710 -#: super_archives/views.py:108 767 +#: super_archives/views.py:112
711 msgid "Unknown error trying to connect to Mailman API" 768 msgid "Unknown error trying to connect to Mailman API"
712 msgstr "Erro desconhecido na conexão com a API do Mailman" 769 msgstr "Erro desconhecido na conexão com a API do Mailman"
713 770
714 -#: super_archives/views.py:143 771 +#: super_archives/views.py:151
715 msgid "" 772 msgid ""
716 "The email address you are trying to verify either has already been verified " 773 "The email address you are trying to verify either has already been verified "
717 "or does not exist." 774 "or does not exist."
@@ -719,7 +776,7 @@ msgstr &quot;&quot; @@ -719,7 +776,7 @@ msgstr &quot;&quot;
719 "O endereço de e-mail que você está tentando verificar ou já foi verificado " 776 "O endereço de e-mail que você está tentando verificar ou já foi verificado "
720 "ou não existe." 777 "ou não existe."
721 778
722 -#: super_archives/views.py:154 779 +#: super_archives/views.py:162
723 msgid "" 780 msgid ""
724 "The email address you are trying to verify is already an active email " 781 "The email address you are trying to verify is already an active email "
725 "address." 782 "address."
@@ -727,73 +784,78 @@ msgstr &quot;&quot; @@ -727,73 +784,78 @@ msgstr &quot;&quot;
727 "O endereço de e-mail que você está tentando verificar já é um endereço de e-" 784 "O endereço de e-mail que você está tentando verificar já é um endereço de e-"
728 "mail ativo" 785 "mail ativo"
729 786
730 -#: super_archives/views.py:164 787 +#: super_archives/views.py:172
731 msgid "Email address verified!" 788 msgid "Email address verified!"
732 msgstr "Endereço de e-mail verificado!" 789 msgstr "Endereço de e-mail verificado!"
733 790
  791 +#: super_archives/management/commands/import_emails.py:205
  792 +msgid "[Colab] Warning - Email sent with a blank subject."
  793 +msgstr "[Colab] Aviso - E-mail enviado com o campo assunto em branco."
  794 +
734 #: super_archives/templates/message-preview.html:42 795 #: super_archives/templates/message-preview.html:42
  796 +#: super_archives/templates/message-preview.html:62
735 msgid "by" 797 msgid "by"
736 msgstr "por" 798 msgstr "por"
737 799
738 -#: super_archives/templates/message-preview.html:57  
739 -#: super_archives/templates/message-thread.html:157 800 +#: super_archives/templates/message-preview.html:65
  801 +#: super_archives/templates/message-thread.html:161
740 msgid "ago" 802 msgid "ago"
741 msgstr "atrás" 803 msgstr "atrás"
742 804
743 -#: super_archives/templates/message-thread.html:33 805 +#: super_archives/templates/message-thread.html:35
744 msgid "You must login before voting." 806 msgid "You must login before voting."
745 msgstr "Você deve estar logado antes de votar." 807 msgstr "Você deve estar logado antes de votar."
746 808
747 -#: super_archives/templates/message-thread.html:128 809 +#: super_archives/templates/message-thread.html:132
748 msgid "Order by" 810 msgid "Order by"
749 msgstr "Ordernar por" 811 msgstr "Ordernar por"
750 812
751 -#: super_archives/templates/message-thread.html:132 813 +#: super_archives/templates/message-thread.html:136
752 msgid "Votes" 814 msgid "Votes"
753 msgstr "Votos" 815 msgstr "Votos"
754 816
755 -#: super_archives/templates/message-thread.html:136 817 +#: super_archives/templates/message-thread.html:140
756 msgid "Date" 818 msgid "Date"
757 msgstr "Data" 819 msgstr "Data"
758 820
759 -#: super_archives/templates/message-thread.html:141 821 +#: super_archives/templates/message-thread.html:145
760 msgid "Related:" 822 msgid "Related:"
761 msgstr "Relacionado:" 823 msgstr "Relacionado:"
762 824
763 -#: super_archives/templates/message-thread.html:152 825 +#: super_archives/templates/message-thread.html:156
764 msgid "Statistics:" 826 msgid "Statistics:"
765 msgstr "Estátisticas:" 827 msgstr "Estátisticas:"
766 828
767 -#: super_archives/templates/message-thread.html:156 829 +#: super_archives/templates/message-thread.html:160
768 msgid "started at" 830 msgid "started at"
769 msgstr "começou às" 831 msgstr "começou às"
770 832
771 -#: super_archives/templates/message-thread.html:162 833 +#: super_archives/templates/message-thread.html:166
772 msgid "viewed" 834 msgid "viewed"
773 msgstr "visualizado" 835 msgstr "visualizado"
774 836
775 -#: super_archives/templates/message-thread.html:163  
776 -#: super_archives/templates/message-thread.html:168  
777 -#: super_archives/templates/message-thread.html:173 837 +#: super_archives/templates/message-thread.html:167
  838 +#: super_archives/templates/message-thread.html:172
  839 +#: super_archives/templates/message-thread.html:177
778 msgid "times" 840 msgid "times"
779 msgstr "vezes" 841 msgstr "vezes"
780 842
781 -#: super_archives/templates/message-thread.html:167 843 +#: super_archives/templates/message-thread.html:171
782 msgid "answered" 844 msgid "answered"
783 msgstr "respondido" 845 msgstr "respondido"
784 846
785 -#: super_archives/templates/message-thread.html:172 847 +#: super_archives/templates/message-thread.html:176
786 msgid "voted" 848 msgid "voted"
787 msgstr "votado" 849 msgstr "votado"
788 850
789 -#: super_archives/templates/message-thread.html:178 851 +#: super_archives/templates/message-thread.html:182
790 msgid "Tags:" 852 msgid "Tags:"
791 msgstr "Etiquetas:" 853 msgstr "Etiquetas:"
792 854
793 #: super_archives/templates/superarchives/thread-dashboard.html:5 855 #: super_archives/templates/superarchives/thread-dashboard.html:5
794 -#: templates/base.html:72  
795 -msgid "Discussions"  
796 -msgstr "Discussões" 856 +#: templates/base.html:73
  857 +msgid "Groups"
  858 +msgstr "Grupos"
797 859
798 #: super_archives/templates/superarchives/thread-dashboard.html:15 860 #: super_archives/templates/superarchives/thread-dashboard.html:15
799 msgid "latest" 861 msgid "latest"
@@ -808,6 +870,33 @@ msgstr &quot;mais...&quot; @@ -808,6 +870,33 @@ msgstr &quot;mais...&quot;
808 msgid "most relevant" 870 msgid "most relevant"
809 msgstr "mais relevantes" 871 msgstr "mais relevantes"
810 872
  873 +#: super_archives/templates/superarchives/emails/email_blank_subject.txt:2
  874 +msgid "Hello"
  875 +msgstr "Olá"
  876 +
  877 +#: super_archives/templates/superarchives/emails/email_blank_subject.txt:3
  878 +#, python-format
  879 +msgid ""
  880 +"\n"
  881 +"You've sent an email to %(mailinglist)s with a blank subject and the "
  882 +"following content:\n"
  883 +"\n"
  884 +"\"%(body)s\"\n"
  885 +"\n"
  886 +"Please, fill the subject in every email you send it.\n"
  887 +"\n"
  888 +"Thank you.\n"
  889 +msgstr ""
  890 +"\n"
  891 +"Você enviou um e-mail para %(mailinglist)s com o campo Assunto em branco e o "
  892 +"seguinte conteúdo:\n"
  893 +"\n"
  894 +"\"%(body)s\"\n"
  895 +"\n"
  896 +"Por favor, preencha o assunto em todos os e-mails que você enviar.\n"
  897 +"\n"
  898 +"Obrigado.\n"
  899 +
811 #: super_archives/templates/superarchives/emails/email_verification.txt:2 900 #: super_archives/templates/superarchives/emails/email_verification.txt:2
812 #, python-format 901 #, python-format
813 msgid "" 902 msgid ""
@@ -826,15 +915,20 @@ msgstr &quot;&quot; @@ -826,15 +915,20 @@ msgstr &quot;&quot;
826 "Se você não é %(username)s ou não pediu uma verificação você pode ignorar " 915 "Se você não é %(username)s ou não pediu uma verificação você pode ignorar "
827 "esse e-mail" 916 "esse e-mail"
828 917
829 -#: super_archives/templates/superarchives/includes/message.html:39 918 +#: super_archives/templates/superarchives/includes/message.html:17
  919 +#: super_archives/templates/superarchives/includes/message.html:18
  920 +msgid "Link to this message"
  921 +msgstr "Link para essa mensagem"
  922 +
  923 +#: super_archives/templates/superarchives/includes/message.html:46
830 msgid "Reply" 924 msgid "Reply"
831 msgstr "Responder" 925 msgstr "Responder"
832 926
833 -#: super_archives/templates/superarchives/includes/message.html:56 927 +#: super_archives/templates/superarchives/includes/message.html:63
834 msgid "Send a message" 928 msgid "Send a message"
835 msgstr "Enviar uma mensagem" 929 msgstr "Enviar uma mensagem"
836 930
837 -#: super_archives/templates/superarchives/includes/message.html:59 931 +#: super_archives/templates/superarchives/includes/message.html:66
838 msgid "" 932 msgid ""
839 "After sending a message it will take few minutes before it shows up in here. " 933 "After sending a message it will take few minutes before it shows up in here. "
840 "Why don't you grab a coffee?" 934 "Why don't you grab a coffee?"
@@ -842,7 +936,7 @@ msgstr &quot;&quot; @@ -842,7 +936,7 @@ msgstr &quot;&quot;
842 "Depois de enviar uma mensagem levará alguns minutos antes dela aparecer " 936 "Depois de enviar uma mensagem levará alguns minutos antes dela aparecer "
843 "aqui. Por que você não pega um café?" 937 "aqui. Por que você não pega um café?"
844 938
845 -#: super_archives/templates/superarchives/includes/message.html:62 939 +#: super_archives/templates/superarchives/includes/message.html:69
846 msgid "Send" 940 msgid "Send"
847 msgstr "Enviar" 941 msgstr "Enviar"
848 942
@@ -862,51 +956,63 @@ msgstr &quot;Não encontrado. Continue procurando! :)&quot; @@ -862,51 +956,63 @@ msgstr &quot;Não encontrado. Continue procurando! :)&quot;
862 msgid "Ooopz... something went wrong!" 956 msgid "Ooopz... something went wrong!"
863 msgstr "Opa... algo saiu errado!" 957 msgstr "Opa... algo saiu errado!"
864 958
865 -#: templates/base.html:78 959 +#: templates/base.html:76
  960 +msgid "Planet"
  961 +msgstr ""
  962 +
  963 +#: templates/base.html:79
866 msgid "Contribute" 964 msgid "Contribute"
867 msgstr "Contribua" 965 msgstr "Contribua"
868 966
869 #: templates/base.html:82 967 #: templates/base.html:82
870 -msgid "New Ticket"  
871 -msgstr "Novo Tíquete"  
872 -  
873 -#: templates/base.html:84  
874 msgid "Timeline" 968 msgid "Timeline"
875 msgstr "Histórico" 969 msgstr "Histórico"
876 970
877 -#: templates/base.html:85 971 +#: templates/base.html:83
878 msgid "Roadmap" 972 msgid "Roadmap"
879 msgstr "Planejamento" 973 msgstr "Planejamento"
880 974
881 -#: templates/base.html:86  
882 -msgid "Browse Source"  
883 -msgstr "Ver Código" 975 +#: templates/base.html:85
  976 +msgid "New Ticket"
  977 +msgstr "Novo Tíquete"
884 978
885 #: templates/base.html:87 979 #: templates/base.html:87
886 msgid "View Tickets" 980 msgid "View Tickets"
887 msgstr "Visualizar Tiquetes" 981 msgstr "Visualizar Tiquetes"
888 982
889 -#: templates/base.html:111 983 +#: templates/base.html:88
  984 +msgid "Browse Source"
  985 +msgstr "Ver Códigos Fontes"
  986 +
  987 +#: templates/base.html:99
  988 +msgid "Login"
  989 +msgstr "Entrar"
  990 +
  991 +#: templates/base.html:113
890 msgid "My Profile" 992 msgid "My Profile"
891 msgstr "Meu Perfil" 993 msgstr "Meu Perfil"
892 994
893 -#: templates/base.html:123 templates/base.html.py:126 995 +#: templates/base.html:114
  996 +msgid "Logout"
  997 +msgstr "Sair"
  998 +
  999 +#: templates/base.html:126 templates/base.html.py:129
894 msgid "Search here..." 1000 msgid "Search here..."
895 msgstr "Pesquise aqui..." 1001 msgstr "Pesquise aqui..."
896 1002
897 -#: templates/base.html:139 1003 +#: templates/base.html:142
898 msgid "The login has failed. Please, try again." 1004 msgid "The login has failed. Please, try again."
899 msgstr "O login falhou. Por favor, tente novamente." 1005 msgstr "O login falhou. Por favor, tente novamente."
900 1006
901 -#: templates/base.html:164 1007 +#: templates/base.html:167
902 msgid "Last email imported at" 1008 msgid "Last email imported at"
903 msgstr "Último e-mail importado em" 1009 msgstr "Último e-mail importado em"
904 1010
905 -#: templates/base.html:169 1011 +#: templates/base.html:172
906 msgid "The contents of this site is published under license" 1012 msgid "The contents of this site is published under license"
907 msgstr "O conteúdo deste site está publicado sob a licença" 1013 msgstr "O conteúdo deste site está publicado sob a licença"
908 1014
909 -#: templates/base.html:171 1015 +#: templates/base.html:174
910 msgid "Creative Commons - attribution, non-commercial" 1016 msgid "Creative Commons - attribution, non-commercial"
911 msgstr "Creative Commons - atribuição e não-comercial" 1017 msgstr "Creative Commons - atribuição e não-comercial"
912 1018
@@ -934,10 +1040,6 @@ msgstr &quot;Discussões Mais Relevantes&quot; @@ -934,10 +1040,6 @@ msgstr &quot;Discussões Mais Relevantes&quot;
934 msgid "RSS - Most Relevant Threads" 1040 msgid "RSS - Most Relevant Threads"
935 msgstr "RSS - Discussões Mais Relevantes" 1041 msgstr "RSS - Discussões Mais Relevantes"
936 1042
937 -#: templates/home.html:57 templates/home.html.py:76  
938 -msgid "View more discussions..."  
939 -msgstr "Ver mais discussões..."  
940 -  
941 #: templates/home.html:64 1043 #: templates/home.html:64
942 msgid "Latest Threads" 1044 msgid "Latest Threads"
943 msgstr "Últimas Discussões" 1045 msgstr "Últimas Discussões"
@@ -954,6 +1056,37 @@ msgstr &quot;Vontade de ajudar&quot; @@ -954,6 +1056,37 @@ msgstr &quot;Vontade de ajudar&quot;
954 msgid "INTERLEGIS COMMUNITIES" 1056 msgid "INTERLEGIS COMMUNITIES"
955 msgstr "COMUNIDADES INTERLEGIS" 1057 msgstr "COMUNIDADES INTERLEGIS"
956 1058
  1059 +#~ msgid "Identi.ca account"
  1060 +#~ msgstr "Conta Identi.ca"
  1061 +
  1062 +#~ msgid "Biography"
  1063 +#~ msgstr "Biografia"
  1064 +
  1065 +#~ msgid "Other Collaborations"
  1066 +#~ msgstr "Outras Colaborações"
  1067 +
  1068 +#~ msgid "Community Blogs"
  1069 +#~ msgstr "Blogs da comunidade"
  1070 +
  1071 +#~ msgid "Mailing List Subscriptions"
  1072 +#~ msgstr "Inscrições em listas de e-mails"
  1073 +
  1074 +#~ msgid "Change SVN and XMPP Client password"
  1075 +#~ msgstr "Trocar a senha do SVN e do Mensageiro"
  1076 +
  1077 +#~ msgid ""
  1078 +#~ "You don't need to change this password. Change it only if you really know "
  1079 +#~ "what you are doing."
  1080 +#~ msgstr ""
  1081 +#~ "Você não precisa trocar essa senha. Troque-a somente se tem certeza do "
  1082 +#~ "que está fazendo."
  1083 +
  1084 +#~ msgid "Subscribes: "
  1085 +#~ msgstr "Inscrições: "
  1086 +
  1087 +#~ msgid "Discussions"
  1088 +#~ msgstr "Discussões"
  1089 +
957 #~ msgid "Community inside participations" 1090 #~ msgid "Community inside participations"
958 #~ msgstr "Participações internas da comunidade" 1091 #~ msgstr "Participações internas da comunidade"
959 1092
src/planet/templates/feedzilla/base.html
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 {% load i18n feedzilla_tags %} 2 {% load i18n feedzilla_tags %}
3 3
4 {% block main-content %} 4 {% block main-content %}
5 - <h2>{% trans 'Planet' %}</h2> 5 + <h2>{% trans 'Planet - Community Blogs' %}</h2>
6 <hr/> 6 <hr/>
7 7
8 <div id="planet" class="row"> 8 <div id="planet" class="row">
@@ -17,10 +17,12 @@ @@ -17,10 +17,12 @@
17 </div> 17 </div>
18 <div class="well"> 18 <div class="well">
19 <h3>{% trans 'Source Blogs' %}</h3> 19 <h3>{% trans 'Source Blogs' %}</h3>
20 - {% feedzilla_donor_list %}  
21 - <div class="text-center">  
22 - <a class="btn btn-primary" href="{% url "feedzilla_submit_blog" %}">{% trans "Submit a blog" %}</a>  
23 - </div> 20 + {% feedzilla_donor_list order_by="title" %}
  21 + {% if user.is_authenticated %}
  22 + <div class="text-center">
  23 + <a class="btn btn-primary" href="{% url "feedzilla_submit_blog" %}">{% trans "Submit a blog" %}</a>
  24 + </div>
  25 + {% endif %}
24 </div> 26 </div>
25 </div> 27 </div>
26 </div> 28 </div>
src/proxy/migrations/0005_adding_modified_by.py 0 → 100644
@@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from django.db import connections
  4 +from south.db import db
  5 +from south.v2 import DataMigration
  6 +from django.db import models
  7 +
  8 +class Migration(DataMigration):
  9 +
  10 + def forwards(self, orm):
  11 + # Selecting trac database
  12 + connection = connections['trac']
  13 +
  14 + cursor = connection.cursor()
  15 + cursor.execute('''
  16 + CREATE OR REPLACE VIEW wiki_view AS SELECT
  17 + wiki.name AS name,
  18 + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  19 + AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  20 + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  21 + AND wiki3.version = 1) AS author,
  22 + string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  23 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  24 + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
  25 + (SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
  26 + AND wiki4.version = MAX(wiki.version)) AS modified_by
  27 + FROM wiki
  28 + GROUP BY wiki.name;
  29 +
  30 + CREATE OR REPLACE VIEW ticket_view AS SELECT
  31 + ticket.id AS id,
  32 + ticket.summary as summary,
  33 + ticket.description as description,
  34 + ticket.milestone as milestone,
  35 + ticket.priority as priority,
  36 + ticket.component as component,
  37 + ticket.version as version,
  38 + ticket.severity as severity,
  39 + ticket.reporter as reporter,
  40 + ticket.reporter as author,
  41 + ticket.status as status,
  42 + ticket.keywords as keywords,
  43 + (SELECT
  44 + string_agg(DISTINCT ticket_change.author, ', ')
  45 + FROM ticket_change WHERE ticket_change.ticket = ticket.id
  46 + GROUP BY ticket_change.ticket) as collaborators,
  47 + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  48 + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
  49 + (SELECT
  50 + ticket_change.author
  51 + FROM ticket_change
  52 + WHERE ticket_change.ticket = ticket.id
  53 + AND ticket_change.time = ticket.changetime
  54 + LIMIT 1
  55 + ) AS modified_by
  56 + FROM ticket;
  57 + ''')
  58 +
  59 +
  60 + def backwards(self, orm):
  61 + # Selecting trac database
  62 + connection = connections['trac']
  63 +
  64 + cursor = connection.cursor()
  65 + cursor.execute('''
  66 + ALTER VIEW wiki_view ALTER COLUMN modified_by DROP DEFAULT;
  67 + ALTER VIEW ticket_view ALTER COLUMN modified_by DROP DEFAULT;
  68 + ''')
  69 +
  70 +
  71 + models = {
  72 + u'proxy.attachment': {
  73 + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},
  74 + 'attach_id': ('django.db.models.fields.TextField', [], {}),
  75 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  76 + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
  77 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  78 + 'filename': ('django.db.models.fields.TextField', [], {}),
  79 + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  80 + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
  81 + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  82 + 'used_by': ('django.db.models.fields.TextField', [], {})
  83 + },
  84 + u'proxy.revision': {
  85 + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},
  86 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  87 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  88 + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  89 + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  90 + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  91 + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  92 + },
  93 + u'proxy.ticket': {
  94 + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},
  95 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  96 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  97 + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  98 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  99 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  100 + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
  101 + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  102 + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  103 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  104 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  105 + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  106 + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  107 + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  108 + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  109 + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  110 + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  111 + },
  112 + u'proxy.wiki': {
  113 + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},
  114 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  115 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  116 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  117 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  118 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  119 + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  120 + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  121 + }
  122 + }
  123 +
  124 + complete_apps = ['proxy']
  125 + symmetrical = True
src/proxy/migrations/0006_views_to_count_collabs.py 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +# -*- coding: utf-8 -*-
  2 +from django.db import connections
  3 +from south.v2 import DataMigration
  4 +
  5 +class Migration(DataMigration):
  6 +
  7 + def forwards(self, orm):
  8 + # Selecting trac database
  9 + connection = connections['trac']
  10 +
  11 + cursor = connection.cursor()
  12 + cursor.execute('''
  13 + CREATE OR REPLACE VIEW ticket_collab_count_view AS
  14 + SELECT
  15 + COALESCE (t1.author, t2.author) as author,
  16 + (COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count
  17 + FROM
  18 + (SELECT author, count(*) as count
  19 + FROM ticket_change
  20 + GROUP BY author
  21 + ORDER BY author
  22 + ) AS t1
  23 + FULL OUTER JOIN
  24 + (SELECT reporter as author, count(*) as count
  25 + FROM ticket
  26 + GROUP BY reporter
  27 + ORDER BY reporter
  28 + ) AS t2
  29 + ON t1.author = t2.author;
  30 +
  31 + CREATE OR REPLACE VIEW wiki_collab_count_view AS
  32 + SELECT author, count(*) from wiki GROUP BY author;
  33 + ''')
  34 +
  35 + def backwards(self, orm):
  36 + # Selecting trac database
  37 + connection = connections['trac']
  38 +
  39 + cursor = connection.cursor()
  40 + cursor.execute('''
  41 + DROP VIEW ticket_collab_count_view;
  42 + DROP VIEW wiki_collab_count_view;
  43 + ''')
  44 +
  45 + complete_apps = ['proxy']
  46 + symmetrical = True
src/proxy/models.py
@@ -4,7 +4,9 @@ import os @@ -4,7 +4,9 @@ import os
4 import urllib2 4 import urllib2
5 5
6 from django.conf import settings 6 from django.conf import settings
7 -from django.db import models 7 +from django.db import models, connections
  8 +from django.db.models.signals import post_save
  9 +from django.dispatch import receiver
8 10
9 from accounts.models import User 11 from accounts.models import User
10 from hitcounter.models import HitCounterModelMixin 12 from hitcounter.models import HitCounterModelMixin
@@ -81,6 +83,7 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -81,6 +83,7 @@ class Ticket(models.Model, HitCounterModelMixin):
81 collaborators = models.TextField(blank=True) 83 collaborators = models.TextField(blank=True)
82 created = models.DateTimeField(blank=True, null=True) 84 created = models.DateTimeField(blank=True, null=True)
83 modified = models.DateTimeField(blank=True, null=True) 85 modified = models.DateTimeField(blank=True, null=True)
  86 + modified_by = models.TextField(blank=True)
84 87
85 class Meta: 88 class Meta:
86 managed = False 89 managed = False
@@ -95,6 +98,12 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -95,6 +98,12 @@ class Ticket(models.Model, HitCounterModelMixin):
95 except User.DoesNotExist: 98 except User.DoesNotExist:
96 return None 99 return None
97 100
  101 + def get_modified_by(self):
  102 + try:
  103 + return User.objects.get(username=self.modified_by)
  104 + except User.DoesNotExist:
  105 + return None
  106 +
98 107
99 class Wiki(models.Model, HitCounterModelMixin): 108 class Wiki(models.Model, HitCounterModelMixin):
100 name = models.TextField(primary_key=True) 109 name = models.TextField(primary_key=True)
@@ -103,6 +112,7 @@ class Wiki(models.Model, HitCounterModelMixin): @@ -103,6 +112,7 @@ class Wiki(models.Model, HitCounterModelMixin):
103 collaborators = models.TextField(blank=True) 112 collaborators = models.TextField(blank=True)
104 created = models.DateTimeField(blank=True, null=True) 113 created = models.DateTimeField(blank=True, null=True)
105 modified = models.DateTimeField(blank=True, null=True) 114 modified = models.DateTimeField(blank=True, null=True)
  115 + modified_by = models.TextField(blank=True)
106 116
107 class Meta: 117 class Meta:
108 managed = False 118 managed = False
@@ -116,3 +126,54 @@ class Wiki(models.Model, HitCounterModelMixin): @@ -116,3 +126,54 @@ class Wiki(models.Model, HitCounterModelMixin):
116 return User.objects.get(username=self.author) 126 return User.objects.get(username=self.author)
117 except User.DoesNotExist: 127 except User.DoesNotExist:
118 return None 128 return None
  129 +
  130 + def get_modified_by(self):
  131 + try:
  132 + return User.objects.get(username=self.modified_by)
  133 + except User.DoesNotExist:
  134 + return None
  135 +
  136 +
  137 +class WikiCollabCount(models.Model):
  138 + author = models.TextField(primary_key=True)
  139 + count = models.IntegerField()
  140 +
  141 + class Meta:
  142 + managed = False
  143 + db_table = 'wiki_collab_count_view'
  144 +
  145 +
  146 +class TicketCollabCount(models.Model):
  147 + author = models.TextField(primary_key=True)
  148 + count = models.IntegerField()
  149 +
  150 + class Meta:
  151 + managed = False
  152 + db_table = 'ticket_collab_count_view'
  153 +
  154 +
  155 +@receiver(post_save, sender=User)
  156 +def change_session_attribute_email(sender, instance, **kwargs):
  157 + cursor = connections['trac'].cursor()
  158 +
  159 + cursor.execute(("UPDATE session_attribute SET value=%s "
  160 + "WHERE name='email' AND sid=%s"),
  161 + [instance.email, instance.username])
  162 + cursor.execute(("UPDATE session_attribute SET value=%s "
  163 + "WHERE name='name' AND sid=%s"),
  164 + [instance.get_full_name(), instance.username])
  165 +
  166 + cursor.execute(("INSERT INTO session_attribute "
  167 + "(sid, authenticated, name, value) "
  168 + "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "
  169 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  170 + "AND name='email')"),
  171 + [instance.username, instance.email, instance.username])
  172 +
  173 + cursor.execute(("INSERT INTO session_attribute "
  174 + "(sid, authenticated, name, value) "
  175 + "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "
  176 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  177 + "AND name='name')"),
  178 + [instance.username, instance.get_full_name(),
  179 + instance.username])
src/search/base_indexes.py
@@ -19,6 +19,8 @@ class BaseIndex(indexes.SearchIndex): @@ -19,6 +19,8 @@ class BaseIndex(indexes.SearchIndex):
19 icon_name = indexes.CharField(indexed=False) 19 icon_name = indexes.CharField(indexed=False)
20 fullname_and_username = indexes.CharField(null=True, stored=False) 20 fullname_and_username = indexes.CharField(null=True, stored=False)
21 hits = indexes.IntegerField(model_attr='hits') 21 hits = indexes.IntegerField(model_attr='hits')
  22 + modified_by = indexes.CharField(null=True)
  23 + modified_by_url = indexes.CharField(null=True)
22 24
23 def get_updated_field(self): 25 def get_updated_field(self):
24 return 'modified' 26 return 'modified'
@@ -30,33 +32,63 @@ class BaseIndex(indexes.SearchIndex): @@ -30,33 +32,63 @@ class BaseIndex(indexes.SearchIndex):
30 return math.log(obj.hits) 32 return math.log(obj.hits)
31 33
32 def prepare(self, obj): 34 def prepare(self, obj):
  35 + self.author_obj = None
  36 + if hasattr(obj, 'get_author'):
  37 + self.author_obj = obj.get_author()
  38 +
33 data = super(BaseIndex, self).prepare(obj) 39 data = super(BaseIndex, self).prepare(obj)
34 data['boost'] = self.get_boost(obj) 40 data['boost'] = self.get_boost(obj)
  41 +
35 return data 42 return data
36 43
37 def prepare_author(self, obj): 44 def prepare_author(self, obj):
38 - author = obj.get_author()  
39 - if author:  
40 - return author.username 45 + if self.author_obj:
  46 + return self.author_obj.username
  47 + return obj.author
  48 +
  49 + def prepare_author_url(self, obj):
  50 + if self.author_obj:
  51 + return self.author_obj.get_absolute_url()
  52 + return None
  53 +
  54 + def prepare_fullname(self, obj):
  55 + if hasattr(obj, 'modified_by'):
  56 + modified_by = obj.get_modified_by()
  57 + if modified_by:
  58 + return modified_by.get_full_name()
  59 + if self.author_obj:
  60 + return self.author_obj.get_full_name()
41 return obj.author 61 return obj.author
42 62
43 def prepare_fullname_and_username(self, obj): 63 def prepare_fullname_and_username(self, obj):
44 - author = obj.get_author()  
45 - if not author: 64 + if hasattr(obj, 'modified_by'):
  65 + modified_by = obj.get_modified_by()
  66 + if modified_by:
  67 + return u'{}\n{}'.format(
  68 + modified_by.get_full_name(),
  69 + modified_by.username,
  70 + )
  71 + if not self.author_obj:
46 return obj.author 72 return obj.author
47 return u'{}\n{}'.format( 73 return u'{}\n{}'.format(
48 - author.get_full_name(),  
49 - author.username, 74 + self.author_obj.get_full_name(),
  75 + self.author_obj.username,
50 ) 76 )
51 77
52 - def prepare_author_url(self, obj):  
53 - author = obj.get_author()  
54 - if author:  
55 - return author.get_absolute_url()  
56 - return None  
57 -  
58 - def prepare_fullname(self, obj):  
59 - author = obj.get_author()  
60 - if author:  
61 - return author.get_full_name() 78 + def prepare_modified_by(self, obj):
  79 + if hasattr(obj, 'modified_by'):
  80 + modified_by = obj.get_modified_by()
  81 + if modified_by:
  82 + return modified_by.get_full_name()
  83 + if self.author_obj:
  84 + return self.author_obj.get_full_name()
62 return obj.author 85 return obj.author
  86 +
  87 + def prepare_modified_by_url(self, obj):
  88 + if hasattr(obj, 'modified_by'):
  89 + modified_by = obj.get_modified_by()
  90 + if modified_by:
  91 + return modified_by.get_absolute_url()
  92 + if self.author_obj:
  93 + return self.author_obj.get_absolute_url()
  94 + return None
src/search/forms.py
@@ -17,6 +17,7 @@ class ColabSearchForm(SearchForm): @@ -17,6 +17,7 @@ class ColabSearchForm(SearchForm):
17 order = forms.CharField(widget=forms.HiddenInput(), required=False) 17 order = forms.CharField(widget=forms.HiddenInput(), required=False)
18 type = forms.CharField(required=False, label=_(u'Type')) 18 type = forms.CharField(required=False, label=_(u'Type'))
19 author = forms.CharField(required=False, label=_(u'Author')) 19 author = forms.CharField(required=False, label=_(u'Author'))
  20 + modified_by = forms.CharField(required=False, label=_(u'Modified by'))
20 # ticket status 21 # ticket status
21 tag = forms.CharField(required=False, label=_(u'Status')) 22 tag = forms.CharField(required=False, label=_(u'Status'))
22 # mailinglist tag 23 # mailinglist tag
@@ -122,6 +123,11 @@ class ColabSearchForm(SearchForm): @@ -122,6 +123,11 @@ class ColabSearchForm(SearchForm):
122 fullname_and_username__contains=self.cleaned_data['author'] 123 fullname_and_username__contains=self.cleaned_data['author']
123 ) 124 )
124 125
  126 + if self.cleaned_data['modified_by']:
  127 + sqs = sqs.filter(
  128 + fullname_and_username__contains=self.cleaned_data['modified_by']
  129 + )
  130 +
125 if self.cleaned_data['milestone']: 131 if self.cleaned_data['milestone']:
126 sqs = sqs.filter(milestone=self.cleaned_data['milestone']) 132 sqs = sqs.filter(milestone=self.cleaned_data['milestone'])
127 if self.cleaned_data['priority']: 133 if self.cleaned_data['priority']:
src/static/css/screen.css
@@ -413,3 +413,18 @@ span.highlighted { @@ -413,3 +413,18 @@ span.highlighted {
413 .vcard .label { 413 .vcard .label {
414 line-height: 2; 414 line-height: 2;
415 } 415 }
  416 +
  417 +/* Message link */
  418 +
  419 +.div-message-link {
  420 + display: inline !important;
  421 +}
  422 +
  423 +.message-link {
  424 + margin-left: 15px;
  425 +}
  426 +
  427 +.email-message .popover {
  428 + max-width: 350px;
  429 + width: 350px;
  430 +}
src/static/third-party/highcharts/js/highcharts.js 0 → 100644
@@ -0,0 +1,285 @@ @@ -0,0 +1,285 @@
  1 +/*
  2 + Highcharts JS v3.0.7 (2013-10-24)
  3 +
  4 + (c) 2009-2013 Torstein Hønsi
  5 +
  6 + License: www.highcharts.com/license
  7 +*/
  8 +(function(){function s(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function x(){var a,b=arguments.length,c={},d=function(a,b){var c,h;typeof a!=="object"&&(a={});for(h in b)b.hasOwnProperty(h)&&(c=b[h],a[h]=c&&typeof c==="object"&&Object.prototype.toString.call(c)!=="[object Array]"&&typeof c.nodeType!=="number"?d(a[h]||{},c):b[h]);return a};for(a=0;a<b;a++)c=d(c,arguments[a]);return c}function y(a,b){return parseInt(a,b||10)}function ea(a){return typeof a==="string"}function T(a){return typeof a===
  9 +"object"}function Ia(a){return Object.prototype.toString.call(a)==="[object Array]"}function ra(a){return typeof a==="number"}function ma(a){return R.log(a)/R.LN10}function fa(a){return R.pow(10,a)}function ga(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function u(a){return a!==v&&a!==null}function w(a,b,c){var d,e;if(ea(b))u(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(u(b)&&T(b))for(d in b)a.setAttribute(d,b[d]);return e}function ja(a){return Ia(a)?
  10 +a:[a]}function o(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++)if(c=a[b],typeof c!=="undefined"&&c!==null)return c}function I(a,b){if(sa&&b&&b.opacity!==v)b.filter="alpha(opacity="+b.opacity*100+")";s(a.style,b)}function U(a,b,c,d,e){a=z.createElement(a);b&&s(a,b);e&&I(a,{padding:0,border:S,margin:0});c&&I(a,c);d&&d.appendChild(a);return a}function ha(a,b){var c=function(){};c.prototype=new a;s(c.prototype,b);return c}function Aa(a,b,c,d){var e=L.lang,a=+a||0,f=b===-1?(a.toString().split(".")[1]||
  11 +"").length:isNaN(b=M(b))?2:b,b=c===void 0?e.decimalPoint:c,d=d===void 0?e.thousandsSep:d,e=a<0?"-":"",c=String(y(a=M(a).toFixed(f))),g=c.length>3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+M(a-c).toFixed(f).slice(2):"")}function Ba(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function mb(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);a.unshift(d);return c.apply(this,a)}}function Ca(a,b){for(var c="{",d=!1,
  12 +e,f,g,h,i,j=[];(c=a.indexOf(c))!==-1;){e=a.slice(0,c);if(d){f=e.split(":");g=f.shift().split(".");i=g.length;e=b;for(h=0;h<i;h++)e=e[g[h]];if(f.length)f=f.join(":"),g=/\.([0-9])/,h=L.lang,i=void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,e=Aa(e,i,h.decimalPoint,f.indexOf(",")>-1?h.thousandsSep:"")):e=Ya(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}j.push(a);return j.join("")}function nb(a){return R.pow(10,P(R.log(a)/R.LN10))}function ob(a,b,c,d){var e,c=o(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===
  13 +!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d<b.length;d++)if(a=b[d],e<=(b[d]+(b[d+1]||b[d]))/2)break;a*=c;return a}function Cb(a,b){var c=b||[[Db,[1,2,5,10,20,25,50,100,200,500]],[pb,[1,2,5,10,15,30]],[Za,[1,2,5,10,15,30]],[Qa,[1,2,3,4,6,8,12]],[ta,[1,2]],[$a,[1,2]],[Ra,[1,2,3,4,6]],[Da,null]],d=c[c.length-1],e=D[d[0]],f=d[1],g;for(g=0;g<c.length;g++)if(d=c[g],e=D[d[0]],f=d[1],c[g+1]&&a<=(e*f[f.length-1]+D[c[g+1][0]])/2)break;e===D[Da]&&a<5*e&&(f=[1,2,5]);c=ob(a/e,f,d[0]===Da?r(nb(a/e),1):
  14 +1);return{unitRange:e,count:c,unitName:d[0]}}function Eb(a,b,c,d){var e=[],f={},g=L.global.useUTC,h,i=new Date(b),j=a.unitRange,k=a.count;if(u(b)){j>=D[pb]&&(i.setMilliseconds(0),i.setSeconds(j>=D[Za]?0:k*P(i.getSeconds()/k)));if(j>=D[Za])i[Fb](j>=D[Qa]?0:k*P(i[qb]()/k));if(j>=D[Qa])i[Gb](j>=D[ta]?0:k*P(i[rb]()/k));if(j>=D[ta])i[sb](j>=D[Ra]?1:k*P(i[Sa]()/k));j>=D[Ra]&&(i[Hb](j>=D[Da]?0:k*P(i[ab]()/k)),h=i[bb]());j>=D[Da]&&(h-=h%k,i[Ib](h));if(j===D[$a])i[sb](i[Sa]()-i[tb]()+o(d,1));b=1;h=i[bb]();
  15 +for(var d=i.getTime(),l=i[ab](),m=i[Sa](),p=g?0:(864E5+i.getTimezoneOffset()*6E4)%864E5;d<c;)e.push(d),j===D[Da]?d=cb(h+b*k,0):j===D[Ra]?d=cb(h,l+b*k):!g&&(j===D[ta]||j===D[$a])?d=cb(h,l,m+b*k*(j===D[ta]?1:7)):d+=j*k,b++;e.push(d);n(ub(e,function(a){return j<=D[Qa]&&a%D[ta]===p}),function(a){f[a]=ta})}e.info=s(a,{higherRanks:f,totalRange:j*k});return e}function Jb(){this.symbol=this.color=0}function Kb(a,b){var c=a.length,d,e;for(e=0;e<c;e++)a[e].ss_i=e;a.sort(function(a,c){d=b(a,c);return d===0?
  16 +a.ss_i-c.ss_i:d});for(e=0;e<c;e++)delete a[e].ss_i}function Ja(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function ua(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Ka(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Ta(a){db||(db=U(Ea));a&&db.appendChild(a);db.innerHTML=""}function ka(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;else N.console&&console.log(c)}function ia(a){return parseFloat(a.toPrecision(14))}
  17 +function La(a,b){Fa=o(a,b.animation)}function Lb(){var a=L.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";cb=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,o(c,1),o(g,0),o(h,0),o(i,0))).getTime()};qb=b+"Minutes";rb=b+"Hours";tb=b+"Day";Sa=b+"Date";ab=b+"Month";bb=b+"FullYear";Fb=c+"Minutes";Gb=c+"Hours";sb=c+"Date";Hb=c+"Month";Ib=c+"FullYear"}function va(){}function Ma(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function vb(a,b){this.axis=a;if(b)this.options=
  18 +b,this.id=b.id}function Mb(a,b,c,d,e,f){var g=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=null;this.points={};this.stack=e;this.percent=f==="percent";this.alignOptions={align:b.align||(g?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(g?"middle":c?"bottom":"top"),y:o(b.y,g?4:c?14:-6),x:o(b.x,g?c?-6:6:0)};this.textAlign=b.textAlign||(g?c?"right":"left":"center")}function eb(){this.init.apply(this,arguments)}function wb(){this.init.apply(this,arguments)}
  19 +function xb(a,b){this.init(a,b)}function fb(a,b){this.init(a,b)}function yb(){this.init.apply(this,arguments)}var v,z=document,N=window,R=Math,t=R.round,P=R.floor,wa=R.ceil,r=R.max,J=R.min,M=R.abs,V=R.cos,ba=R.sin,xa=R.PI,Ua=xa*2/360,na=navigator.userAgent,Nb=N.opera,sa=/msie/i.test(na)&&!Nb,gb=z.documentMode===8,hb=/AppleWebKit/.test(na),ib=/Firefox/.test(na),Ob=/(Mobile|Android|Windows Phone)/.test(na),ya="http://www.w3.org/2000/svg",W=!!z.createElementNS&&!!z.createElementNS(ya,"svg").createSVGRect,
  20 +Ub=ib&&parseInt(na.split("Firefox/")[1],10)<4,ca=!W&&!sa&&!!z.createElement("canvas").getContext,Va,jb=z.documentElement.ontouchstart!==v,Pb={},zb=0,db,L,Ya,Fa,Ab,D,oa=function(){},Ga=[],Ea="div",S="none",Qb="rgba(192,192,192,"+(W?1.0E-4:0.002)+")",Db="millisecond",pb="second",Za="minute",Qa="hour",ta="day",$a="week",Ra="month",Da="year",Rb="stroke-width",cb,qb,rb,tb,Sa,ab,bb,Fb,Gb,sb,Hb,Ib,X={};N.Highcharts=N.Highcharts?ka(16,!0):{};Ya=function(a,b,c){if(!u(b)||isNaN(b))return"Invalid date";var a=
  21 +o(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b),e,f=d[rb](),g=d[tb](),h=d[Sa](),i=d[ab](),j=d[bb](),k=L.lang,l=k.weekdays,d=s({a:l[g].substr(0,3),A:l[g],d:Ba(h),e:h,b:k.shortMonths[i],B:k.months[i],m:Ba(i+1),y:j.toString().substr(2,2),Y:j,H:Ba(f),I:Ba(f%12||12),l:f%12||12,M:Ba(d[qb]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:Ba(d.getSeconds()),L:Ba(t(b%1E3),3)},Highcharts.dateFormats);for(e in d)for(;a.indexOf("%"+e)!==-1;)a=a.replace("%"+e,typeof d[e]==="function"?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+
  22 +a.substr(1):a};Jb.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};D=function(){for(var a=0,b=arguments,c=b.length,d={};a<c;a++)d[b[a++]]=b[a];return d}(Db,1,pb,1E3,Za,6E4,Qa,36E5,ta,864E5,$a,6048E5,Ra,26784E5,Da,31556952E3);Ab={init:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&
  23 +(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length<a;)d=[].concat(b).splice(b.length-f,f),e&&(d[f-6]=d[f-2],d[f-5]=d[f-1]),b=b.concat(d);h&&(b=b.concat(h),c=c.concat(i));return[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;)d=parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}};
  24 +(function(a){N.HighchartsAdapter=N.HighchartsAdapter||a&&{init:function(b){var c=a.fx,d=c.step,e,f=a.Tween,g=f&&f.propHooks;e=a.cssHooks.opacity;a.extend(a.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});a.each(["cur","_default","width","height","opacity"],function(a,b){var e=d,k,l;b==="cur"?e=c.prototype:b==="_default"&&f&&(e=g[b],b="set");(k=e[b])&&(e[b]=function(c){c=a?c:this;if(c.prop!=="align")return l=c.elem,l.attr?l.attr(c.prop,b==="cur"?v:c.now):k.apply(this,arguments)})});
  25 +mb(e,"get",function(a,b,c){return b.attr?b.opacity||0:a.call(this,b,c)});e=function(a){var c=a.elem,d;if(!a.started)d=b.init(c,c.d,c.toD),a.start=d[0],a.end=d[1],a.started=!0;c.attr("d",b.step(a.start,a.end,a.pos,c.toD))};f?g.d={set:e}:d.d=e;this.each=Array.prototype.forEach?function(a,b){return Array.prototype.forEach.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===!1)return c};a.fn.highcharts=function(){var a="Chart",b=arguments,c,d;ea(b[0])&&(a=b[0],b=Array.prototype.slice.call(b,
  26 +1));c=b[0];if(c!==v)c.chart=c.chart||{},c.chart.renderTo=this[0],new Highcharts[a](c,b[1]),d=this;c===v&&(d=Ga[w(this[0],"data-highcharts-chart")]);return d}},getScript:a.getScript,inArray:a.inArray,adapterRun:function(b,c){return a(b)[c]()},grep:a.grep,map:function(a,c){for(var d=[],e=0,f=a.length;e<f;e++)d[e]=c.call(a[e],a[e],e,a);return d},offset:function(b){return a(b).offset()},addEvent:function(b,c,d){a(b).bind(c,d)},removeEvent:function(b,c,d){var e=z.removeEventListener?"removeEventListener":
  27 +"detachEvent";z[e]&&b&&!b[e]&&(b[e]=function(){});a(b).unbind(c,d)},fireEvent:function(b,c,d,e){var f=a.Event(c),g="detached"+c,h;!sa&&d&&(delete d.layerX,delete d.layerY);s(f,d);b[c]&&(b[g]=b[c],b[c]=null);a.each(["preventDefault","stopPropagation"],function(a,b){var c=f[b];f[b]=function(){try{c.call(f)}catch(a){b==="preventDefault"&&(h=!0)}}});a(b).trigger(f);b[g]&&(b[c]=b[g],b[g]=null);e&&!f.isDefaultPrevented()&&!h&&e(f)},washMouseEvent:function(a){var c=a.originalEvent||a;if(c.pageX===v)c.pageX=
  28 +a.pageX,c.pageY=a.pageY;return c},animate:function(b,c,d){var e=a(b);if(!b.style)b.style={};if(c.d)b.toD=c.d,c.d=1;e.stop();c.opacity!==v&&b.attr&&(c.opacity+="px");e.animate(c,d)},stop:function(b){a(b).stop()}}})(N.jQuery);var Y=N.HighchartsAdapter,G=Y||{};Y&&Y.init.call(Y,Ab);var kb=G.adapterRun,Vb=G.getScript,pa=G.inArray,n=G.each,ub=G.grep,Wb=G.offset,Na=G.map,K=G.addEvent,$=G.removeEvent,A=G.fireEvent,Xb=G.washMouseEvent,Bb=G.animate,Wa=G.stop,G={enabled:!0,x:0,y:15,style:{color:"#666",cursor:"default",
  29 +fontSize:"11px",lineHeight:"14px"}};L={colors:"#2f7ed8,#0d233a,#8bbc21,#910000,#1aadce,#492970,#f28f43,#77a1e5,#c42525,#a6c96a".split(","),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),decimalPoint:".",
  30 +numericSymbols:"k,M,G,T,P,E".split(","),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/3.0.7/modules/canvas-tools.js",VMLRadialGradientURL:"http://code.highcharts.com/3.0.7/gfx/vml-radial-gradient.png"},chart:{borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
  31 +fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",align:"center",margin:15,style:{color:"#274b6d",fontSize:"16px"}},subtitle:{text:"",align:"center",style:{color:"#4d759e"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},lineWidth:2,marker:{enabled:!0,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{enabled:!0},select:{fillColor:"#FFFFFF",
  32 +lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:x(G,{align:"center",enabled:!1,formatter:function(){return this.y===null?"":Aa(this.y,-1)},verticalAlign:"bottom",y:0}),cropThreshold:300,pointRange:0,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:!0}},labels:{style:{position:"absolute",color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderWidth:1,borderColor:"#909090",borderRadius:5,navigation:{activeColor:"#274b6d",
  33 +inactiveColor:"#CCC"},shadow:!1,itemStyle:{cursor:"pointer",color:"#274b6d",fontSize:"12px"},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"1em"},style:{position:"absolute",backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:!0,animation:W,
  34 +backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:1,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>',shadow:!0,snap:Ob?25:10,style:{color:"#333333",cursor:"default",
  35 +fontSize:"12px",padding:"8px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var Z=L.plotOptions,Y=Z.line;Lb();var Yb=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,Zb=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,$b=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,
  36 +qa=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Na(a.stops,function(a){return qa(a[1])}):(c=Yb.exec(a))?b=[y(c[1]),y(c[2]),y(c[3]),parseFloat(c[4],10)]:(c=Zb.exec(a))?b=[y(c[1],16),y(c[2],16),y(c[3],16),1]:(c=$b.exec(a))&&(b=[y(c[1]),y(c[2]),y(c[3]),1])})(a);return{get:function(c){var f;d?(f=x(a),f.stops=[].concat(f.stops),n(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a;return f},brighten:function(a){if(d)n(d,
  37 +function(b){b.brighten(a)});else if(ra(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=y(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this}}};va.prototype={init:function(a,b){this.element=b==="span"?U(b):z.createElementNS(ya,b);this.renderer=a;this.attrSetters={}},opacity:1,animate:function(a,b,c){b=o(b,Fa,!0);Wa(this);if(b){b=x(b);if(c)b.complete=c;Bb(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName.toLowerCase(),
  38 +i=this.renderer,j,k=this.attrSetters,l=this.shadows,m,p,q=this;ea(a)&&u(b)&&(c=a,a={},a[c]=b);if(ea(a))c=a,h==="circle"?c={x:"cx",y:"cy"}[c]||c:c==="strokeWidth"&&(c="stroke-width"),q=w(g,c)||this[c]||0,c!=="d"&&c!=="visibility"&&c!=="fill"&&(q=parseFloat(q));else{for(c in a)if(j=!1,d=a[c],e=k[c]&&k[c].call(this,d,c),e!==!1){e!==v&&(d=e);if(c==="d")d&&d.join&&(d=d.join(" ")),/(NaN| {2}|^$)/.test(d)&&(d="M 0 0");else if(c==="x"&&h==="text")for(e=0;e<g.childNodes.length;e++)f=g.childNodes[e],w(f,"x")===
  39 +w(g,"x")&&w(f,"x",d);else if(this.rotation&&(c==="x"||c==="y"))p=!0;else if(c==="fill")d=i.color(d,g,c);else if(h==="circle"&&(c==="x"||c==="y"))c={x:"cx",y:"cy"}[c]||c;else if(h==="rect"&&c==="r")w(g,{rx:d,ry:d}),j=!0;else if(c==="translateX"||c==="translateY"||c==="rotation"||c==="verticalAlign"||c==="scaleX"||c==="scaleY")j=p=!0;else if(c==="stroke")d=i.color(d,g,c);else if(c==="dashstyle")if(c="stroke-dasharray",d=d&&d.toLowerCase(),d==="solid")d=S;else{if(d){d=d.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot",
  40 +"3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(e=d.length;e--;)d[e]=y(d[e])*o(a["stroke-width"],this["stroke-width"]);d=d.join(",")}}else if(c==="width")d=y(d);else if(c==="align")c="text-anchor",d={left:"start",center:"middle",right:"end"}[d];else if(c==="title")e=g.getElementsByTagName("title")[0],e||(e=z.createElementNS(ya,"title"),g.appendChild(e)),e.textContent=d;c==="strokeWidth"&&
  41 +(c="stroke-width");if(c==="stroke-width"||c==="stroke"){this[c]=d;if(this.stroke&&this["stroke-width"])w(g,"stroke",this.stroke),w(g,"stroke-width",this["stroke-width"]),this.hasStroke=!0;else if(c==="stroke-width"&&d===0&&this.hasStroke)g.removeAttribute("stroke"),this.hasStroke=!1;j=!0}this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(m||(this.symbolAttr(a),m=!0),j=!0);if(l&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c))for(e=l.length;e--;)w(l[e],
  42 +c,c==="height"?r(d-(l[e].cutHeight||0),0):d);if((c==="width"||c==="height")&&h==="rect"&&d<0)d=0;this[c]=d;c==="text"?(d!==this.textStr&&delete this.bBox,this.textStr=d,this.added&&i.buildText(this)):j||w(g,c,d)}p&&this.updateTransform()}return q},addClass:function(a){var b=this.element,c=w(b,"class")||"";c.indexOf(a)===-1&&w(b,"class",c+" "+a);return this},symbolAttr:function(a){var b=this;n("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=o(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,
  43 +b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":S)},crisp:function(a,b,c,d,e){var f,g={},h={},i,a=a||this.strokeWidth||this.attr&&this.attr("stroke-width")||0;i=t(a)%2/2;h.x=P(b||this.x||0)+i;h.y=P(c||this.y||0)+i;h.width=P((d||this.width||0)-2*i);h.height=P((e||this.height||0)-2*i);h.strokeWidth=a;for(f in h)this[f]!==h[f]&&(this[f]=g[f]=h[f]);return g},css:function(a){var b=this.element,c=this.textWidth=a&&a.width&&b.nodeName.toLowerCase()===
  44 +"text"&&y(a.width),d,e="",f=function(a,b){return"-"+b.toLowerCase()};if(a&&a.color)a.fill=a.color;this.styles=a=s(this.styles,a);c&&delete a.width;if(sa&&!W)I(this.element,a);else{for(d in a)e+=d.replace(/([A-Z])/g,f)+":"+a[d]+";";w(b,"style",e)}c&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=this,d=c.element;jb&&a==="click"?(d.ontouchstart=function(a){c.touchEventFired=Date.now();a.preventDefault();b.call(d,a)},d.onclick=function(a){(na.indexOf("Android")===-1||Date.now()-
  45 +(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=a;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},htmlCss:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width)delete a.width,this.textWidth=b,this.updateTransform();this.styles=s(this.styles,a);I(this.element,a);return this},htmlGetBBox:function(){var a=
  46 +this.element,b=this.bBox;if(!b){if(a.nodeName==="text")a.style.position="absolute";b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,f=this.y||0,g=this.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=g&&g!=="left",j=this.shadows;I(b,{marginLeft:c,marginTop:d});j&&n(j,function(a){I(a,{marginLeft:c+1,marginTop:d+1})});
  47 +this.inverted&&n(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName==="SPAN"){var k,l,j=this.rotation,m;k=0;var p=1,q=0,aa;m=y(this.textWidth);var B=this.xCorr||0,O=this.yCorr||0,Sb=[j,g,b.innerHTML,this.textWidth].join(",");if(Sb!==this.cTT){u(j)&&(k=j*Ua,p=V(k),q=ba(k),this.setSpanRotation(j,q,p));k=o(this.elemWidth,b.offsetWidth);l=o(this.elemHeight,b.offsetHeight);if(k>m&&/[ \-]/.test(b.textContent||b.innerText))I(b,{width:m+"px",display:"block",whiteSpace:"normal"}),k=m;m=a.fontMetrics(b.style.fontSize).b;
  48 +B=p<0&&-k;O=q<0&&-l;aa=p*q<0;B+=q*m*(aa?1-h:h);O-=p*m*(j?aa?h:1-h:1);i&&(B-=k*h*(p<0?-1:1),j&&(O-=l*h*(q<0?-1:1)),I(b,{textAlign:g}));this.xCorr=B;this.yCorr=O}I(b,{left:e+B+"px",top:f+O+"px"});if(hb)l=b.offsetHeight;this.cTT=Sb}}else this.alignOnAdd=!0},setSpanRotation:function(a){var b={};b[sa?"-ms-transform":hb?"-webkit-transform":ib?"MozTransform":Nb?"-o-transform":""]=b.transform="rotate("+a+"deg)";I(this.element,b)},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=
  49 +this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation;e&&(a+=this.attr("width"),b+=this.attr("height"));a=["translate("+a+","+b+")"];e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(this.x||0)+" "+(this.y||0)+")");(u(c)||u(d))&&a.push("scale("+o(c,1)+" "+o(d,1)+")");a.length&&w(this.element,"transform",a.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions=
  50 +a,this.alignByTranslate=b,!c||ea(c))this.alignTo=d=c||"renderer",ga(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=o(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||0);g=(c.y||0)+(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=t(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=t(g);this[this.placed?"animate":"attr"](h);this.placed=
  51 +!0;this.alignAttr=h;return this},getBBox:function(){var a=this.bBox,b=this.renderer,c,d=this.rotation;c=this.element;var e=this.styles,f=d*Ua;if(!a){if(c.namespaceURI===ya||b.forExport){try{a=c.getBBox?s({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(g){}if(!a||a.width<0)a={width:0,height:0}}else a=this.htmlGetBBox();if(b.isSVG){b=a.width;c=a.height;if(sa&&e&&e.fontSize==="11px"&&c.toPrecision(3)==="22.7")a.height=c=14;if(d)a.width=M(c*ba(f))+M(b*V(f)),a.height=M(c*V(f))+M(b*ba(f))}this.bBox=
  52 +a}return a},show:function(){return this.attr({visibility:"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.hide()}})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=w(f,"zIndex"),h;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);if(g)c.handleZ=!0,g=y(g);if(c.handleZ)for(c=0;c<e.length;c++)if(a=
  53 +e[c],b=w(a,"zIndex"),a!==f&&(y(b)>g||!u(g)&&u(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;A(this,"add");return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName==="SPAN"&&a.parentGroup,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null;Wa(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();
  54 +a.stops=null}a.safeRemoveChild(b);for(c&&n(c,function(b){a.safeRemoveChild(b)});d&&d.div.childNodes.length===0;)b=d.parentGroup,a.safeRemoveChild(d.div),delete d.div,d=b;a.alignTo&&ga(a.renderer.alignedObjects,a);for(e in a)delete a[e];return null},shadow:function(a,b,c){var d=[],e,f,g=this.element,h,i,j,k;if(a){i=o(a.width,3);j=(a.opacity||0.15)/i;k=this.parentInverted?"(-1,-1)":"("+o(a.offsetX,1)+", "+o(a.offsetY,1)+")";for(e=1;e<=i;e++){f=g.cloneNode(0);h=i*2+1-2*e;w(f,{isShadow:"true",stroke:a.color||
  55 +"black","stroke-opacity":j*e,"stroke-width":h,transform:"translate"+k,fill:S});if(c)w(f,"height",r(w(f,"height")-h,0)),f.cutHeight=h;b?b.element.appendChild(f):g.parentNode.insertBefore(f,g);d.push(f)}this.shadows=d}return this}};var za=function(){this.init.apply(this,arguments)};za.prototype={Element:va,init:function(a,b,c,d){var e=location,f,g;f=this.createElement("svg").attr({version:"1.1"});g=f.element;a.appendChild(g);a.innerHTML.indexOf("xmlns")===-1&&w(g,"xmlns",ya);this.isSVG=!0;this.box=
  56 +g;this.boxWrapper=f;this.alignedObjects=[];this.url=(ib||hb)&&z.getElementsByTagName("base").length?e.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(z.createTextNode("Created with Highcharts 3.0.7"));this.defs=this.createElement("defs").add();this.forExport=d;this.gradients={};this.setSize(b,c,!1);var h;if(ib&&a.getBoundingClientRect)this.subPixelFix=b=function(){I(a,{left:0,top:0});h=a.getBoundingClientRect();I(a,
  57 +{left:wa(h.left)-h.left+"px",top:wa(h.top)-h.top+"px"})},b(),K(N,"resize",b)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Ka(this.gradients||{});this.gradients=null;if(a)this.defs=a.destroy();this.subPixelFix&&$(N,"resize",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},buildText:function(a){for(var b=
  58 +a.element,c=this,d=c.forExport,e=o(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g),f=b.childNodes,g=/style="([^"]+)"/,h=/href="(http[^"]+)"/,i=w(b,"x"),j=a.styles,k=a.textWidth,l=j&&j.lineHeight,m=f.length;m--;)b.removeChild(f[m]);k&&!a.added&&this.box.appendChild(b);e[e.length-1]===""&&e.pop();n(e,function(e,f){var m,o=0,
  59 +e=e.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");m=e.split("|||");n(m,function(e){if(e!==""||m.length===1){var p={},n=z.createElementNS(ya,"tspan"),r;g.test(e)&&(r=e.match(g)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),w(n,"style",r));h.test(e)&&!d&&(w(n,"onclick",'location.href="'+e.match(h)[1]+'"'),I(n,{cursor:"pointer"}));e=(e.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">");if(e!==" "&&(n.appendChild(z.createTextNode(e)),o?p.dx=0:p.x=i,w(n,p),!o&&f&&
  60 +(!W&&d&&I(n,{display:"block"}),w(n,"dy",l||c.fontMetrics(/px$/.test(n.style.fontSize)?n.style.fontSize:j.fontSize).h,hb&&n.offsetHeight)),b.appendChild(n),o++,k))for(var e=e.replace(/([^\^])-/g,"$1- ").split(" "),u,t,p=a._clipHeight,E=[],v=y(l||16),s=1;e.length||E.length;)delete a.bBox,u=a.getBBox(),t=u.width,!W&&c.forExport&&(t=c.measureSpanWidth(n.firstChild.data,a.styles)),u=t>k,!u||e.length===1?(e=E,E=[],e.length&&(s++,p&&s*v>p?(e=["..."],a.attr("title",a.textStr)):(n=z.createElementNS(ya,"tspan"),
  61 +w(n,{dy:v,x:i}),r&&w(n,"style",r),b.appendChild(n),t>k&&(k=t)))):(n.removeChild(n.firstChild),E.unshift(e.pop())),e.length&&n.appendChild(z.createTextNode(e.join(" ").replace(/- /g,"-")))}})})},button:function(a,b,c,d,e,f,g,h,i){var j=this.label(a,b,c,i,null,null,null,null,"button"),k=0,l,m,p,q,n,o,a={x1:0,y1:0,x2:0,y2:1},e=x({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);p=e.style;delete e.style;f=x(e,{stroke:"#68A",
  62 +fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);q=f.style;delete f.style;g=x(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);n=g.style;delete g.style;h=x(e,{style:{color:"#CCC"}},h);o=h.style;delete h.style;K(j.element,sa?"mouseover":"mouseenter",function(){k!==3&&j.attr(f).css(q)});K(j.element,sa?"mouseout":"mouseleave",function(){k!==3&&(l=[e,f,g][k],m=[p,q,n][k],j.attr(l).css(m))});j.setState=function(a){(j.state=k=a)?a===2?j.attr(g).css(n):a===3&&j.attr(h).css(o):
  63 +j.attr(e).css(p)};return j.on("click",function(){k!==3&&d.call(j)}).attr(e).css(s({cursor:"default"},p))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=t(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=t(a[2])+b%2/2);return a},path:function(a){var b={fill:S};Ia(a)?b.d=a:T(a)&&s(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=T(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(T(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol("arc",
  64 +a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0});a.r=c;return a},rect:function(a,b,c,d,e,f){e=T(a)?a.r:e;e=this.createElement("rect").attr({rx:e,ry:e,fill:S});return e.attr(T(a)?a:e.crisp(f,a,b,r(c,0),r(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[o(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return u(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,
  65 +c,d,e){var f={preserveAspectRatio:S};arguments.length>1&&s(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(t(b),t(c),d,e,f),i=/^url\((.*?)\)$/,j,k;if(h)g=this.path(h),s(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&s(g,f);else if(i.test(a))k=function(a,b){a.element&&(a.attr({width:b[0],
  66 +height:b[1]}),a.alignByTranslate||a.translate(t((d-b[0])/2),t((e-b[1])/2)))},j=a.match(i)[1],a=Pb[j],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),U("img",{onload:function(){k(g,Pb[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",
  67 +a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=V(f),j=ba(f),k=V(g),g=ba(g),e=e.end-f<xa?0:1;return["M",a+c*i,b+c*j,"A",c,c,0,e,1,a+c*k,b+c*g,h?"M":"L",a+d*k,b+d*g,"A",d,d,0,e,0,a+d*i,b+d*j,h?"":"Z"]}},clipRect:function(a,b,c,d){var e="highcharts-"+zb++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),
  68 +a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;return a},color:function(a,b,c){var d=this,e,f=/^rgba/,g,h,i,j,k,l,m,p=[];a&&a.linearGradient?g="linearGradient":a&&a.radialGradient&&(g="radialGradient");if(g){c=a[g];h=d.gradients;j=a.stops;b=b.radialReference;Ia(c)&&(a[g]=c={x1:c[0],y1:c[1],x2:c[2],y2:c[3],gradientUnits:"userSpaceOnUse"});g==="radialGradient"&&b&&!u(c.gradientUnits)&&(c=x(c,{cx:b[0]-b[2]/2+c.cx*b[2],cy:b[1]-b[2]/2+c.cy*b[2],r:c.r*b[2],gradientUnits:"userSpaceOnUse"}));for(m in c)m!==
  69 +"id"&&p.push(m,c[m]);for(m in j)p.push(j[m]);p=p.join(",");h[p]?a=h[p].id:(c.id=a="highcharts-"+zb++,h[p]=i=d.createElement(g).attr(c).add(d.defs),i.stops=[],n(j,function(a){f.test(a[1])?(e=qa(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1);a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i);i.stops.push(a)}));return"url("+d.url+"#"+a+")"}else return f.test(a)?(e=qa(a),w(b,c+"-opacity",e.get("a")),e.get("rgb")):(b.removeAttribute(c+"-opacity"),a)},text:function(a,
  70 +b,c,d){var e=L.chart.style,f=ca||!W&&this.forExport;if(d&&!this.forExport)return this.html(a,b,c);b=t(o(b,0));c=t(o(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({fontFamily:e.fontFamily,fontSize:e.fontSize});f&&a.css({position:"absolute"});a.x=b;a.y=c;return a},html:function(a,b,c){var d=L.chart.style,e=this.createElement("span"),f=e.attrSetters,g=e.element,h=e.renderer;f.text=function(a){a!==g.innerHTML&&delete this.bBox;g.innerHTML=a;return!1};f.x=f.y=f.align=function(a,b){b===
  71 +"align"&&(b="textAlign");e[b]=a;e.htmlUpdateTransform();return!1};e.attr({text:a,x:t(b),y:t(c)}).css({position:"absolute",whiteSpace:"nowrap",fontFamily:d.fontFamily,fontSize:d.fontSize});e.css=e.htmlCss;if(h.isSVG)e.add=function(a){var b,c=h.box.parentNode,d=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)d.push(a),a=a.parentGroup;n(d.reverse(),function(a){var d;b=a.div=a.div||U(Ea,{className:w(a.element,"class")},{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c);
  72 +d=b.style;s(a.attrSetters,{translateX:function(a){d.left=a+"px"},translateY:function(a){d.top=a+"px"},visibility:function(a,b){d[b]=a}})})}}else b=c;b.appendChild(g);e.added=!0;e.alignOnAdd&&e.htmlUpdateTransform();return e};return e},fontMetrics:function(a){var a=y(a||11),a=a<24?a+4:t(a*1.2),b=t(a*0.8);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h,i){function j(){var a,b;a=o.element.style;O=(Oa===void 0||Ha===void 0||q.styles.textAlign)&&o.getBBox();q.width=(Oa||O.width||0)+2*da+lb;q.height=(Ha||
  73 +O.height||0)+2*da;w=da+p.fontMetrics(a&&a.fontSize).b;if(y){if(!B)a=t(-r*da),b=h?-w:0,q.box=B=d?p.symbol(d,a,b,q.width,q.height,Xa):p.rect(a,b,q.width,q.height,0,Xa[Rb]),B.add(q);B.isImg||B.attr(x({width:q.width,height:q.height},Xa));Xa=null}}function k(){var a=q.styles,a=a&&a.textAlign,b=lb+da*(1-r),c;c=h?0:w;if(u(Oa)&&(a==="center"||a==="right"))b+={center:0.5,right:1}[a]*(Oa-O.width);(b!==o.x||c!==o.y)&&o.attr({x:b,y:c});o.x=b;o.y=c}function l(a,b){B?B.attr(a,b):Xa[a]=b}function m(){o.add(q);q.attr({text:a,
  74 +x:b,y:c});B&&u(e)&&q.attr({anchorX:e,anchorY:f})}var p=this,q=p.g(i),o=p.text("",0,0,g).attr({zIndex:1}),B,O,r=0,da=3,lb=0,Oa,Ha,E,H,C=0,Xa={},w,g=q.attrSetters,y;K(q,"add",m);g.width=function(a){Oa=a;return!1};g.height=function(a){Ha=a;return!1};g.padding=function(a){u(a)&&a!==da&&(da=a,k());return!1};g.paddingLeft=function(a){u(a)&&a!==lb&&(lb=a,k());return!1};g.align=function(a){r={left:0,center:0.5,right:1}[a];return!1};g.text=function(a,b){o.attr(b,a);j();k();return!1};g[Rb]=function(a,b){y=
  75 +!0;C=a%2/2;l(b,a);return!1};g.stroke=g.fill=g.r=function(a,b){b==="fill"&&(y=!0);l(b,a);return!1};g.anchorX=function(a,b){e=a;l(b,a+C-E);return!1};g.anchorY=function(a,b){f=a;l(b,a-H);return!1};g.x=function(a){q.x=a;a-=r*((Oa||O.width)+da);E=t(a);q.attr("translateX",E);return!1};g.y=function(a){H=q.y=t(a);q.attr("translateY",H);return!1};var z=q.css;return s(q,{css:function(a){if(a){var b={},a=x(a);n("fontSize,fontWeight,fontFamily,color,lineHeight,width,textDecoration,textShadow".split(","),function(c){a[c]!==
  76 +v&&(b[c]=a[c],delete a[c])});o.css(b)}return z.call(q,a)},getBBox:function(){return{width:O.width+2*da,height:O.height+2*da,x:O.x-da,y:O.y-da}},shadow:function(a){B&&B.shadow(a);return q},destroy:function(){$(q,"add",m);$(q.element,"mouseenter");$(q.element,"mouseleave");o&&(o=o.destroy());B&&(B=B.destroy());va.prototype.destroy.call(q);q=p=j=k=l=m=null}})}};Va=za;var F;if(!W&&!ca){Highcharts.VMLElement=F={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],
  77 +e=b===Ea;(b==="shape"||e)&&d.push("left:0;top:0;width:1px;height:1px;");d.push("visibility: ",e?"hidden":"visible");c.push(' style="',d.join(""),'"/>');if(b)c=e||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element=U(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();A(this,"add");return this},
  78 +updateTransform:va.prototype.htmlUpdateTransform,setSpanRotation:function(a,b,c){I(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",c,", M12=",-b,", M21=",b,", M22=",c,", sizingMethod='auto expand')"].join(""):S})},pathToVML:function(a){for(var b=a.length,c=[],d;b--;)if(ra(a[b]))c[b]=t(a[b]*10)-5;else if(a[b]==="Z")c[b]="x";else if(c[b]=a[b],a.isArc&&(a[b]==="wa"||a[b]==="at"))d=a[b]==="wa"?1:-1,c[b+5]===c[b+7]&&(c[b+7]-=d),c[b+6]===c[b+8]&&(c[b+8]-=d);return c.join(" ")||"x"},
  79 +attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,k,l=this.shadows,m,p=this.attrSetters,q=this;ea(a)&&u(b)&&(c=a,a={},a[c]=b);if(ea(a))c=a,q=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c];else for(c in a)if(d=a[c],m=!1,e=p[c]&&p[c].call(this,d,c),e!==!1&&d!==null){e!==v&&(d=e);if(j&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k||(this.symbolAttr(a),k=!0),m=!0;else if(c==="d"){d=d||[];this.d=d.join(" ");f.path=
  80 +d=this.pathToVML(d);if(l)for(e=l.length;e--;)l[e].path=l[e].cutOff?this.cutOffPath(d,l[e].cutOff):d;m=!0}else if(c==="visibility"){if(l)for(e=l.length;e--;)l[e].style[c]=d;h==="DIV"&&(d=d==="hidden"?"-999em":0,gb||(g[c]=d?"visible":"hidden"),c="top");g[c]=d;m=!0}else if(c==="zIndex")d&&(g[c]=d),m=!0;else if(pa(c,["x","y","width","height"])!==-1)this[c]=d,c==="x"||c==="y"?c={x:"left",y:"top"}[c]:d=r(0,d),this.updateClipping?(this[c]=d,this.updateClipping()):g[c]=d,m=!0;else if(c==="class"&&h==="DIV")f.className=
  81 +d;else if(c==="stroke")d=i.color(d,f,c),c="strokecolor";else if(c==="stroke-width"||c==="strokeWidth")f.stroked=d?!0:!1,c="strokeweight",this[c]=d,ra(d)&&(d+="px");else if(c==="dashstyle")(f.getElementsByTagName("stroke")[0]||U(i.prepVML(["<stroke/>"]),null,null,f))[c]=d||"solid",this.dashstyle=d,m=!0;else if(c==="fill")if(h==="SPAN")g.color=d;else{if(h!=="IMG")f.filled=d!==S?!0:!1,d=i.color(d,f,c,this),c="fillcolor"}else if(c==="opacity")m=!0;else if(h==="shape"&&c==="rotation")this[c]=f.style[c]=
  82 +d,f.style.left=-t(ba(d*Ua)+1)+"px",f.style.top=t(V(d*Ua))+"px";else if(c==="translateX"||c==="translateY"||c==="rotation")this[c]=d,this.updateTransform(),m=!0;else if(c==="text")this.bBox=null,f.innerHTML=d,m=!0;m||(gb?f[c]=d:w(f,c,d))}return q},clip:function(a){var b=this,c;a?(c=a.members,ga(c,b),c.push(b),b.destroyClip=function(){ga(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:gb?"inherit":"rect(auto)"});return b.css(a)},css:va.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&
  83 +Ta(a)},destroy:function(){this.destroyClip&&this.destroyClip();return va.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=N.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=y(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,m,p,q;k&&typeof k.value!=="string"&&(k="x");m=k;if(a){p=o(a.width,3);q=(a.opacity||
  84 +0.15)/p;for(e=1;e<=3;e++){l=p*2+1-2*e;c&&(m=this.cutOffPath(k.value,l+0.5));j=['<shape isShadow="true" strokeweight="',l,'" filled="false" path="',m,'" coordsize="10 10" style="',f.style.cssText,'" />'];h=U(g.prepVML(j),null,{left:y(i.left)+o(a.offsetX,1),top:y(i.top)+o(a.offsetY,1)});if(c)h.cutOff=l+1;j=['<stroke color="',a.color||"black",'" opacity="',q*e,'"/>'];U(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this}};F=ha(va,F);
  85 +var la={Element:F,isIE8:na.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(Ea);e=d.element;e.style.position="relative";a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=d;this.setSize(b,c,!1);if(!z.namespaces.hcv){z.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{z.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){z.styleSheets[0].cssText+=
  86 +"hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=T(a);return s(e,{members:[],left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+t(a?e:d)+"px,"+t(a?f:
  87 +b)+"px,"+t(a?b:f)+"px,"+t(a?d:e)+"px)"};!a&&gb&&c==="DIV"&&s(d,{width:b+"px",height:f+"px"});return d},updateClipping:function(){n(e.members,function(a){a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=S;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,l,m=a.linearGradient||a.radialGradient,p,q,o,B,O,r="",a=a.stops,u,t=[],v=function(){h=['<fill colors="'+t.join(",")+'" opacity="',o,'" o:opacity2="',q,'" type="',i,'" ',r,'focus="100%" method="any" />'];
  88 +U(e.prepVML(h),null,null,b)};p=a[0];u=a[a.length-1];p[0]>0&&a.unshift([0,p[1]]);u[0]<1&&a.push([1,u[1]]);n(a,function(a,b){g.test(a[1])?(f=qa(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1);t.push(a[0]*100+"% "+k);b?(o=l,B=k):(q=l,O=k)});if(c==="fill")if(i==="gradient")c=m.x1||m[0]||0,a=m.y1||m[1]||0,p=m.x2||m[2]||0,m=m.y2||m[3]||0,r='angle="'+(90-R.atan((m-a)/(p-c))*180/xa)+'"',v();else{var j=m.r,s=j*2,E=j*2,H=m.cx,C=m.cy,x=b.radialReference,w,j=function(){x&&(w=d.getBBox(),H+=(x[0]-w.x)/w.width-
  89 +0.5,C+=(x[1]-w.y)/w.height-0.5,s*=x[2]/w.width,E*=x[2]/w.height);r='src="'+L.global.VMLRadialGradientURL+'" size="'+s+","+E+'" origin="0.5,0.5" position="'+H+","+C+'" color2="'+O+'" ';v()};d.added?j():K(d,"add",j);j=B}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=qa(a),h=["<",c,' opacity="',f.get("a"),'"/>'],U(this.prepVML(h),null,null,b),j=f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1,j[0].type="solid";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join("");b?
  90 +(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","<hcv:");return a},text:za.prototype.html,path:function(a){var b={coordsize:"10 10"};Ia(a)?b.d=a:T(a)&&s(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,c){var d=this.symbol("circle");if(T(a))c=a.r,b=a.y,a=a.x;d.isCircle=
  91 +!0;d.r=c;return d.attr({x:a,y:b})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement(Ea).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.attr({x:b,y:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){var g=this.symbol("rect");g.r=T(a)?a.r:e;return g.attr(T(a)?a:g.crisp(f,a,b,r(c,0),r(d,0)))},invertChild:function(a,b){var c=b.style;I(a,{flip:"x",left:y(c.width)-1,top:y(c.height)-1,rotation:-90})},
  92 +symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=V(f),i=ba(f),j=V(g),k=ba(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&(c=d=2*e.r);e&&e.isCircle&&(a-=c/2,b-=d/2);return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){var f=a+c,g=b+d,h;!u(e)||!e.r?f=za.prototype.symbols.square.apply(0,
  93 +arguments):(h=J(e.r,c,d),f=["M",a+h,b,"L",f-h,b,"wa",f-2*h,b,f,b+2*h,f-h,b,f,b+h,"L",f,g-h,"wa",f-2*h,g-2*h,f,g,f,g-h,f-h,g,"L",a+h,g,"wa",a,g-2*h,a+2*h,g,a+h,g,a,g-h,"L",a,b+h,"wa",a,b,a+2*h,b+2*h,a,b+h,a+h,b,"x","e"]);return f}}};Highcharts.VMLRenderer=F=function(){this.init.apply(this,arguments)};F.prototype=x(za.prototype,la);Va=F}za.prototype.measureSpanWidth=function(a,b){var c=z.createElement("span"),d=z.createTextNode(a);c.appendChild(d);I(c,b);this.box.appendChild(c);return c.offsetWidth};
  94 +var Tb;if(ca)Highcharts.CanVGRenderer=F=function(){ya="http://www.w3.org/1999/xhtml"},F.prototype.symbols={},Tb=function(){function a(){var a=b.length,d;for(d=0;d<a;d++)b[d]();b=[]}var b=[];return{push:function(c,d){b.length===0&&Vb(d,a);b.push(c)}}}(),Va=F;Ma.prototype={addLabel:function(){var a=this.axis,b=a.options,c=a.chart,d=a.horiz,e=a.categories,f=a.names,g=this.pos,h=b.labels,i=a.tickPositions,d=d&&e&&!h.step&&!h.staggerLines&&!h.rotation&&c.plotWidth/i.length||!d&&(c.margin[3]||c.chartWidth*
  95 +0.33),j=g===i[0],k=g===i[i.length-1],l,f=e?o(e[g],f[g],g):g,e=this.label,m=i.info;a.isDatetimeAxis&&m&&(l=b.dateTimeLabelFormats[m.higherRanks[g]||m.unitName]);this.isFirst=j;this.isLast=k;b=a.labelFormatter.call({axis:a,chart:c,isFirst:j,isLast:k,dateTimeLabelFormat:l,value:a.isLog?ia(fa(f)):f});g=d&&{width:r(1,t(d-2*(h.padding||10)))+"px"};g=s(g,h.style);if(u(e))e&&e.attr({text:b}).css(g);else{l={align:a.labelAlign};if(ra(h.rotation))l.rotation=h.rotation;if(d&&h.ellipsis)l._clipHeight=a.len/i.length;
  96 +this.label=u(b)&&h.enabled?c.renderer.text(b,0,0,h.useHTML).attr(l).css(g).add(a.labelGroup):null}},getLabelSize:function(){var a=this.label,b=this.axis;return a?(this.labelBBox=a.getBBox())[b.horiz?"height":"width"]:0},getLabelSides:function(){var a=this.axis,b=this.labelBBox.width,a=b*{left:0,center:0.5,right:1}[a.labelAlign]-a.options.labels.x;return[-a,b-a]},handleOverflow:function(a,b){var c=!0,d=this.axis,e=d.chart,f=this.isFirst,g=this.isLast,h=b.x,i=d.reversed,j=d.tickPositions;if(f||g){var k=
  97 +this.getLabelSides(),l=k[0],k=k[1],e=e.plotLeft,m=e+d.len,j=(d=d.ticks[j[a+(f?1:-1)]])&&d.label.xy&&d.label.xy.x+d.getLabelSides()[f?0:1];f&&!i||g&&i?h+l<e&&(h=e-l,d&&h+k>j&&(c=!1)):h+k>m&&(h=m-k,d&&h+l<j&&(c=!1));b.x=h}return c},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):
  98 +g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,l=i.staggerLines,m=i.chart.renderer.fontMetrics(e.style.fontSize).b,p=e.rotation,a=a+e.x-(f&&d?f*j*(k?-1:1):0),b=b+e.y-(f&&!d?f*j*(k?1:-1):0);p&&i.side===2&&(b-=m-m*V(p*Ua));!u(e.y)&&!p&&(b+=m-c.getBBox().height/2);l&&(b+=g/(h||1)%l*(i.labelOffset/l));return{x:a,y:b}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,
  99 +b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,j=this.pos,k=e.labels,l=this.gridLine,m=h?h+"Grid":"grid",p=h?h+"Tick":"tick",q=e[m+"LineWidth"],n=e[m+"LineColor"],B=e[m+"LineDashStyle"],r=e[p+"Length"],m=e[p+"Width"]||0,u=e[p+"Color"],t=e[p+"Position"],p=this.mark,s=k.step,w=!0,x=d.tickmarkOffset,E=this.getPosition(g,j,x,b),H=E.x,E=E.y,C=g&&H===d.pos+d.len||!g&&E===d.pos?-1:1,y=d.staggerLines;this.isActive=!0;if(q){j=d.getPlotLinePath(j+x,q*C,b,!0);if(l===v){l=
  100 +{stroke:n,"stroke-width":q};if(B)l.dashstyle=B;if(!h)l.zIndex=1;if(b)l.opacity=0;this.gridLine=l=q?f.path(j).attr(l).add(d.gridGroup):null}if(!b&&l&&j)l[this.isNew?"attr":"animate"]({d:j,opacity:c})}if(m&&r)t==="inside"&&(r=-r),d.opposite&&(r=-r),b=this.getMarkPath(H,E,r,m*C,g,f),p?p.animate({d:b,opacity:c}):this.mark=f.path(b).attr({stroke:u,"stroke-width":m,opacity:c}).add(d.axisGroup);if(i&&!isNaN(H))i.xy=E=this.getLabelPosition(H,E,i,g,k,x,a,s),this.isFirst&&!this.isLast&&!o(e.showFirstLabel,
  101 +1)||this.isLast&&!this.isFirst&&!o(e.showLastLabel,1)?w=!1:!y&&g&&k.overflow==="justify"&&!this.handleOverflow(a,E)&&(w=!1),s&&a%s&&(w=!1),w&&!isNaN(E.y)?(E.opacity=c,i[this.isNew?"attr":"animate"](E),this.isNew=!1):i.attr("y",-9999)},destroy:function(){Ka(this,this.axis)}};vb.prototype={render:function(){var a=this,b=a.axis,c=b.horiz,d=(b.pointRange||0)/2,e=a.options,f=e.label,g=a.label,h=e.width,i=e.to,j=e.from,k=u(j)&&u(i),l=e.value,m=e.dashStyle,p=a.svgElem,q=[],n,B=e.color,O=e.zIndex,t=e.events,
  102 +v=b.chart.renderer;b.isLog&&(j=ma(j),i=ma(i),l=ma(l));if(h){if(q=b.getPlotLinePath(l,h),d={stroke:B,"stroke-width":h},m)d.dashstyle=m}else if(k){if(j=r(j,b.min-d),i=J(i,b.max+d),q=b.getPlotBandPath(j,i,e),d={fill:B},e.borderWidth)d.stroke=e.borderColor,d["stroke-width"]=e.borderWidth}else return;if(u(O))d.zIndex=O;if(p)if(q)p.animate({d:q},null,p.onGetPath);else{if(p.hide(),p.onGetPath=function(){p.show()},g)a.label=g=g.destroy()}else if(q&&q.length&&(a.svgElem=p=v.path(q).attr(d).add(),t))for(n in e=
  103 +function(b){p.on(b,function(c){t[b].apply(a,[c])})},t)e(n);if(f&&u(f.text)&&q&&q.length&&b.width>0&&b.height>0){f=x({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f);if(!g)a.label=g=v.text(f.text,0,0,f.useHTML).attr({align:f.textAlign||f.align,rotation:f.rotation,zIndex:O}).css(f.style).add();b=[q[1],q[4],o(q[6],q[1])];q=[q[2],q[5],o(q[7],q[2])];c=Ja(b);k=Ja(q);g.align(f,!1,{x:c,y:k,width:ua(b)-c,height:ua(q)-k});g.show()}else g&&g.hide();return a},
  104 +destroy:function(){ga(this.axis.plotLinesAndBands,this);delete this.axis;Ka(this)}};Mb.prototype={destroy:function(){Ka(this,this.axis)},render:function(a){var b=this.options,c=b.format,c=c?Ca(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,0,0,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,
  105 +g=c.translate(this.percent?100:this.total,0,0,0,1),c=c.translate(0),c=M(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e.attr({visibility:this.options.crop===!1||d.isInsidePlot(f.x,f.y)?W?"inherit":"visible":"hidden"})}};eb.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",
  106 +month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#C0C0C0",labels:G,lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#4d759e",fontWeight:"bold"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,
  107 +gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return Aa(this.total,-1)},style:G.style}},defaultLeftAxisOptions:{labels:{x:-8,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:8,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{x:0,y:14},title:{rotation:0}},defaultTopAxisOptions:{labels:{x:0,y:-5},
  108 +title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.xOrY=(this.isXAxis=c)?"x":"y";this.opposite=b.opposite;this.side=this.horiz?this.opposite?0:2:this.opposite?1:3;this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.names=[];this.isLog=e==="logarithmic";
  109 +this.isDatetimeAxis=e==="datetime";this.isLinked=u(d.linkedTo);this.tickmarkOffset=this.categories&&d.tickmarkPlacement==="between"?0.5:0;this.ticks={};this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stackExtremes={};this.min=this.max=null;var f,d=this.options.events;pa(this,a.axes)===-1&&(a.axes.push(this),a[c?"xAxis":"yAxis"].push(this));
  110 +this.series=this.series||[];if(a.inverted&&c&&this.reversed===v)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)K(this,f,d[f]);if(this.isLog)this.val2lin=ma,this.lin2val=fa},setOptions:function(a){this.options=x(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],x(L[this.isXAxis?"xAxis":"yAxis"],a))},update:function(a,
  111 +b){var c=this.chart,a=c.options[this.xOrY+"Axis"][this.options.index]=x(this.userOptions,a);this.destroy(!0);this._addedPlotLB=this.userMin=this.userMax=v;this.init(c,s(a,{events:v}));c.isDirtyBox=!0;o(b,!0)&&c.redraw()},remove:function(a){var b=this.chart,c=this.xOrY+"Axis";n(this.series,function(a){a.remove(!1)});ga(b.axes,this);ga(b[c],this);b.options[c].splice(this.options.index,1);n(b[c],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=!0;o(a,!0)&&b.redraw()},defaultLabelFormatter:function(){var a=
  112 +this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=L.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ca(h,this);else if(c)g=b;else if(d)g=Ya(d,b);else if(f&&a>=1E3)for(;f--&&g===v;)c=Math.pow(1E3,f+1),a>=c&&e[f]!==null&&(g=Aa(b/c,-1)+e[f]);g===v&&(g=b>=1E3?Aa(b,0):Aa(b,-1));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=null;a.stackExtremes={};a.buildStacks();n(a.series,function(c){if(c.visible||
  113 +!b.options.chart.ignoreHiddenSeries){var d;d=c.options.threshold;var e;a.hasVisibleSeries=!0;a.isLog&&d<=0&&(d=null);if(a.isXAxis){if(d=c.xData,d.length)a.dataMin=J(o(a.dataMin,d[0]),Ja(d)),a.dataMax=r(o(a.dataMax,d[0]),ua(d))}else{c.getExtremes();e=c.dataMax;c=c.dataMin;if(u(c)&&u(e))a.dataMin=J(o(a.dataMin,c),c),a.dataMax=r(o(a.dataMax,e),e);if(u(d))if(a.dataMin>=d)a.dataMin=d,a.ignoreMinPadding=!0;else if(a.dataMax<d)a.dataMax=d,a.ignoreMaxPadding=!0}}})},translate:function(a,b,c,d,e,f){var g=
  114 +this.len,h=1,i=0,j=d?this.oldTransA:this.transA,d=d?this.oldMin:this.min,k=this.minPixelPadding,e=(this.options.ordinal||this.isLog&&e)&&this.lin2val;if(!j)j=this.transA;c&&(h*=-1,i=g);this.reversed&&(h*=-1,i-=h*g);b?(a=a*h+i,a-=k,a=a/j+d,e&&(a=this.lin2val(a))):(e&&(a=this.val2lin(a)),f==="between"&&(f=0.5),a=h*(a-d)*j+i+h*k+(ra(f)?j*f*this.pointRange:0));return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-
  115 +(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d){var e=this.chart,f=this.left,g=this.top,h,i,j,a=this.translate(a,null,null,c),k=c&&e.oldChartHeight||e.chartHeight,l=c&&e.oldChartWidth||e.chartWidth,m;h=this.transB;c=i=t(a+h);h=j=t(k-a-h);if(isNaN(a))m=!0;else if(this.horiz){if(h=g,j=k-this.bottom,c<f||c>f+this.width)m=!0}else if(c=f,i=l-this.right,h<g||h>g+this.height)m=!0;return m&&!d?null:e.renderer.crispLine(["M",c,h,"L",i,j],b||0)},getPlotBandPath:function(a,b){var c=
  116 +this.getPlotLinePath(b),d=this.getPlotLinePath(a);d&&c?d.push(c[4],c[5],c[1],c[2]):d=null;return d},getLinearTickPositions:function(a,b,c){for(var d,b=ia(P(b/a)*a),c=ia(wa(c/a)*a),e=[];b<=c;){e.push(b);b=ia(b+a);if(b===d)break;d=b}return e},getLogTickPositions:function(a,b,c,d){var e=this.options,f=this.len,g=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=t(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=P(b),h,i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];f<
  117 +c+1&&!l;f++){i=e.length;for(h=0;h<i&&!l;h++)j=ma(fa(f)*e[h]),j>b&&(!d||k<=c)&&g.push(k),k>c&&(l=!0),k=j}else if(b=fa(b),c=fa(c),a=e[d?"minorTickInterval":"tickInterval"],a=o(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=ob(a,null,nb(a)),g=Na(this.getLinearTickPositions(a,b,c),ma),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,
  118 +d=[],e;if(this.isLog){e=b.length;for(a=1;a<e;a++)d=d.concat(this.getLogTickPositions(c,b[a-1],b[a],!0))}else if(this.isDatetimeAxis&&a.minorTickInterval==="auto")d=d.concat(Eb(Cb(c),this.min,this.max,a.startOfWeek)),d[0]<this.min&&d.shift();else for(b=this.min+(b[0]-this.min)%c;b<=this.max;b+=c)d.push(b);return d},adjustForMinRange:function(){var a=this.options,b=this.min,c=this.max,d,e=this.dataMax-this.dataMin>=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===v&&!this.isLog)u(a.min)||u(a.max)?
  119 +this.minRange=null:(n(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===v||h<f)f=h}),this.minRange=J(f*5,this.dataMax-this.dataMin));if(c-b<this.minRange){var k=this.minRange;d=(k-c+b)/2;d=[b-d,o(a.min,b-d)];if(e)d[2]=this.dataMin;b=ua(d);c=[b+k,o(a.max,b+k)];if(e)c[2]=this.dataMax;c=Ja(c);c-b<k&&(d[0]=c-k,d[1]=o(a.min,c-k),b=ua(d))}this.min=b;this.max=c},setAxisTranslation:function(a){var b=this.max-this.min,c=0,d,e=0,f=0,g=this.linkedParent,h=this.transA;
  120 +if(this.isXAxis)g?(e=g.minPointOffset,f=g.pointRangePadding):n(this.series,function(a){var g=a.pointRange,h=a.options.pointPlacement,l=a.closestPointRange;g>b&&(g=0);c=r(c,g);e=r(e,ea(h)?0:g/2);f=r(f,h==="on"?0:g);!a.noSharedTooltip&&u(l)&&(d=u(d)?J(d,l):l)}),g=this.ordinalSlope&&d?this.ordinalSlope/d:1,this.minPointOffset=e*=g,this.pointRangePadding=f*=g,this.pointRange=J(c,b),this.closestPointRange=d;if(a)this.oldTransA=h;this.translationSlope=this.transA=h=this.len/(b+f||1);this.transB=this.horiz?
  121 +this.left:this.bottom;this.minPixelPadding=h*e},setTickPositions:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,m=d.minTickInterval,p=d.tickPixelInterval,q,aa=b.categories;h?(b.linkedParent=c[g?"xAxis":"yAxis"][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=o(c.min,c.dataMin),b.max=o(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ka(11,1)):(b.min=o(b.userMin,d.min,
  122 +b.dataMin),b.max=o(b.userMax,d.max,b.dataMax));if(e)!a&&J(b.min,o(b.dataMin,b.min))<=0&&ka(10,1),b.min=ia(ma(b.min)),b.max=ia(ma(b.max));if(b.range&&(b.userMin=b.min=r(b.min,b.max-b.range),b.userMax=b.max,a))b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!aa&&!b.usePercentage&&!h&&u(b.min)&&u(b.max)&&(c=b.max-b.min)){if(!u(d.min)&&!u(b.userMin)&&k&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*k;if(!u(d.max)&&!u(b.userMax)&&j&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*j}b.min===
  123 +b.max||b.min===void 0||b.max===void 0?b.tickInterval=1:h&&!l&&p===b.linkedParent.options.tickPixelInterval?b.tickInterval=b.linkedParent.tickInterval:(b.tickInterval=o(l,aa?1:(b.max-b.min)*p/r(b.len,p)),!u(l)&&b.len<p&&!this.isRadial&&(q=!0,b.tickInterval/=4));g&&!a&&n(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);
  124 +if(b.pointRange)b.tickInterval=r(b.pointRange,b.tickInterval);if(!l&&b.tickInterval<m)b.tickInterval=m;if(!f&&!e&&!l)b.tickInterval=ob(b.tickInterval,null,nb(b.tickInterval),d);b.minorTickInterval=d.minorTickInterval==="auto"&&b.tickInterval?b.tickInterval/5:d.minorTickInterval;b.tickPositions=a=d.tickPositions?[].concat(d.tickPositions):i&&i.apply(b,[b.min,b.max]);if(!a)!b.ordinalPositions&&(b.max-b.min)/b.tickInterval>r(2*b.len,200)&&ka(19,!0),a=f?(b.getNonLinearTimeTicks||Eb)(Cb(b.tickInterval,
  125 +d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):e?b.getLogTickPositions(b.tickInterval,b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),q&&a.splice(1,a.length-2),b.tickPositions=a;if(!h)e=a[0],f=a[a.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&a.shift(),d.endOnTick?b.max=f:b.max+h<f&&a.pop(),a.length===1&&(b.min-=0.001,b.max+=0.001)},setMaxTicks:function(){var a=this.chart,b=a.maxTicks||{},c=this.tickPositions,d=this._maxTicksKey=
  126 +[this.xOrY,this.pos,this.len].join("-");if(!this.isLinked&&!this.isDatetimeAxis&&c&&c.length>(b[d]||0)&&this.options.alignTicks!==!1)b[d]=c.length;a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1){var d=this.tickAmount,e=b.length;this.tickAmount=a=c[a];if(e<a){for(;b.length<a;)b.push(ia(b[b.length-1]+this.tickInterval));this.transA*=(e-1)/(a-
  127 +1);this.max=b[b.length-1]}if(u(d)&&a!==d)this.isDirty=!0}},setScale:function(){var a=this.stacks,b,c,d,e;this.oldMin=this.min;this.oldMax=this.max;this.oldAxisLength=this.len;this.setAxisSize();e=this.len!==this.oldAxisLength;n(this.series,function(a){if(a.isDirtyData||a.isDirty||a.xAxis.isDirty)d=!0});if(e||d||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax){if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].total=null,a[b][c].cum=0;this.forceRedraw=
  128 +!1;this.getSeriesExtremes();this.setTickPositions();this.oldUserMin=this.userMin;this.oldUserMax=this.userMax;if(!this.isDirty)this.isDirty=e||this.min!==this.oldMin||this.max!==this.oldMax}else if(!this.isXAxis){if(this.oldStacks)a=this.stacks=this.oldStacks;for(b in a)for(c in a[b])a[b][c].cum=a[b][c].total}this.setMaxTicks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=o(c,!0),e=s(e,{min:a,max:b});A(f,"setExtremes",e,function(){f.userMin=a;f.userMax=b;f.eventArgs=e;f.isDirtyExtremes=
  129 +!0;c&&g.redraw(d)})},zoom:function(a,b){this.allowZoomOutside||(u(this.dataMin)&&a<=this.dataMin&&(a=v),u(this.dataMax)&&b>=this.dataMax&&(b=v));this.displayBtn=a!==v||b!==v;this.setExtremes(a,b,!1,v,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=b.offsetRight||0,e=this.horiz,f,g;this.left=g=o(b.left,a.plotLeft+c);this.top=f=o(b.top,a.plotTop);this.width=c=o(b.width,a.plotWidth-c+d);this.height=b=o(b.height,a.plotHeight);this.bottom=a.chartHeight-
  130 +b-f;this.right=a.chartWidth-c-g;this.len=r(e?c:b,0);this.pos=e?g:f},getExtremes:function(){var a=this.isLog;return{min:a?ia(fa(this.min)):this.min,max:a?ia(fa(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?fa(this.min):this.min,b=b?fa(this.max):this.max;c>a||a===null?a=c:b<a&&(a=b);return this.translate(a,0,1,0,1)},addPlotBand:function(a){this.addPlotBandOrLine(a,"plotBands")},addPlotLine:function(a){this.addPlotBandOrLine(a,
  131 +"plotLines")},addPlotBandOrLine:function(a,b){var c=(new vb(this,a)).render(),d=this.userOptions;c&&(b&&(d[b]=d[b]||[],d[b].push(a)),this.plotLinesAndBands.push(c));return c},autoLabelAlign:function(a){a=(o(a,0)-this.side*90+720)%360;return a>15&&a<165?"right":a>195&&a<345?"left":"center"},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,j,k=0,l,m=0,p=d.title,q=d.labels,aa=0,B=b.axisOffset,t=b.clipOffset,
  132 +s=[-1,1,1,-1][h],w,x=1,y=o(q.maxStaggerLines,5),Ha,E,H,C;a.hasData=j=a.hasVisibleSeries||u(a.min)&&u(a.max)&&!!e;a.showAxis=b=j||o(d.showEmpty,!0);a.staggerLines=a.horiz&&q.staggerLines;if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:q.zIndex||7}).add();if(j||a.isLinked){a.labelAlign=o(q.align||a.autoLabelAlign(q.rotation));n(e,function(b){f[b]?f[b].addLabel():f[b]=new Ma(a,
  133 +b)});if(a.horiz&&!a.staggerLines&&y&&!q.rotation){for(w=a.reversed?[].concat(e).reverse():e;x<y;){j=[];Ha=!1;for(q=0;q<w.length;q++)E=w[q],H=(H=f[E].label&&f[E].label.getBBox())?H.width:0,C=q%x,H&&(E=a.translate(E),j[C]!==v&&E<j[C]&&(Ha=!0),j[C]=E+H);if(Ha)x++;else break}if(x>1)a.staggerLines=x}n(e,function(b){if(h===0||h===2||{1:"left",3:"right"}[h]===a.labelAlign)aa=r(f[b].getLabelSize(),aa)});if(a.staggerLines)aa*=a.staggerLines,a.labelOffset=aa}else for(w in f)f[w].destroy(),delete f[w];if(p&&
  134 +p.text&&p.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(p.text,0,0,p.useHTML).attr({zIndex:7,rotation:p.rotation||0,align:p.textAlign||{low:"left",middle:"center",high:"right"}[p.align]}).css(p.style).add(a.axisGroup),a.axisTitle.isNew=!0;if(b)k=a.axisTitle.getBBox()[g?"height":"width"],m=o(p.margin,g?5:10),l=p.offset;a.axisTitle[b?"show":"hide"]()}a.offset=s*o(d.offset,B[h]);a.axisTitleMargin=o(l,aa+m+(h!==2&&aa&&s*d.labels[g?"y":"x"]));B[h]=r(B[h],a.axisTitleMargin+k+s*a.offset);t[i]=r(t[i],
  135 +P(d.lineWidth/2)*2)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;c&&(a*=-1);return b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=y(e.style.fontSize||12),d={low:f+(a?0:d),
  136 +middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,g=a.tickPositions,h=a.axisTitle,i=a.stacks,j=a.ticks,k=a.minorTicks,l=a.alternateBands,m=d.stackLabels,p=d.alternateGridColor,q=a.tickmarkOffset,o=d.lineWidth,B,r=b.hasRendered&&u(a.oldMin)&&!isNaN(a.oldMin);B=a.hasData;
  137 +var t=a.showAxis,s,w;n([j,k,l],function(a){for(var b in a)a[b].isActive=!1});if(B||f)if(a.minorTickInterval&&!a.categories&&n(a.getMinorTickPositions(),function(b){k[b]||(k[b]=new Ma(a,b,"minor"));r&&k[b].isNew&&k[b].render(null,!0);k[b].render(null,!1,1)}),g.length&&(n(g.slice(1).concat([g[0]]),function(b,c){c=c===g.length-1?0:c+1;if(!f||b>=a.min&&b<=a.max)j[b]||(j[b]=new Ma(a,b)),r&&j[b].isNew&&j[b].render(c,!0),j[b].render(c,!1,1)}),q&&a.min===0&&(j[-1]||(j[-1]=new Ma(a,-1,null,!0)),j[-1].render(-1))),
  138 +p&&n(g,function(b,c){if(c%2===0&&b<a.max)l[b]||(l[b]=new vb(a)),s=b+q,w=g[c+1]!==v?g[c+1]+q:a.max,l[b].options={from:e?fa(s):s,to:e?fa(w):w,color:p},l[b].render(),l[b].isActive=!0}),!a._addedPlotLB)n((d.plotLines||[]).concat(d.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0;n([j,k,l],function(a){var c,d,e=[],f=Fa?Fa.duration||500:0,g=function(){for(d=e.length;d--;)a[e[d]]&&!a[e[d]].isActive&&(a[e[d]].destroy(),delete a[e[d]])};for(c in a)if(!a[c].isActive)a[c].render(c,!1,0),
  139 +a[c].isActive=!1,e.push(c);a===l||!b.hasRendered||!f?g():f&&setTimeout(g,f)});if(o)B=a.getLinePath(o),a.axisLine?a.axisLine.animate({d:B}):a.axisLine=c.path(B).attr({stroke:d.lineColor,"stroke-width":o,zIndex:7}).add(a.axisGroup),a.axisLine[t?"show":"hide"]();if(h&&t)h[h.isNew?"attr":"animate"](a.getTitlePosition()),h.isNew=!1;if(m&&m.enabled){var x,y,d=a.stackTotalGroup;if(!d)a.stackTotalGroup=d=c.g("stack-labels").attr({visibility:"visible",zIndex:6}).add();d.translate(b.plotLeft,b.plotTop);for(x in i)for(y in c=
  140 +i[x],c)c[y].render(d)}a.isDirty=!1},removePlotBandOrLine:function(a){for(var b=this.plotLinesAndBands,c=this.options,d=this.userOptions,e=b.length;e--;)b[e].id===a&&b[e].destroy();n([c.plotLines||[],d.plotLines||[],c.plotBands||[],d.plotBands||[]],function(b){for(e=b.length;e--;)b[e].id===a&&ga(b,b[e])})},setTitle:function(a,b){this.update({title:a},b)},redraw:function(){var a=this.chart.pointer;a.reset&&a.reset(!0);this.render();n(this.plotLinesAndBands,function(a){a.render()});n(this.series,function(a){a.isDirty=
  141 +!0})},buildStacks:function(){var a=this.series,b=a.length;if(!this.isXAxis){for(;b--;)a[b].setStackedPoints();if(this.usePercentage)for(b=0;b<a.length;b++)a[b].setPercentStacks()}},setCategories:function(a,b){this.update({categories:a},b)},destroy:function(a){var b=this,c=b.stacks,d,e=b.plotLinesAndBands;a||$(b);for(d in c)Ka(c[d]),c[d]=null;n([b.ticks,b.minorTicks,b.alternateBands],function(a){Ka(a)});for(a=e.length;a--;)e[a].destroy();n("stackTotalGroup,axisLine,axisGroup,gridGroup,labelGroup,axisTitle".split(","),
  142 +function(a){b[a]&&(b[a]=b[a].destroy())})}};wb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=y(d.padding);this.chart=a;this.options=b;this.crosshairs=[];this.now={x:0,y:0};this.isHidden=!0;this.label=a.renderer.label("",0,0,b.shape,null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-999});ca||this.label.shadow(b.shadow);this.shared=b.shared},destroy:function(){n(this.crosshairs,
  143 +function(a){a&&a.destroy()});if(this.label)this.label=this.label.destroy();clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden;s(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:g?(2*f.anchorX+c)/3:c,anchorY:g?(f.anchorY+d)/2:d});e.label.attr(f);if(g&&(M(a-f.x)>1||M(b-f.y)>1))clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(){var a=this,b;clearTimeout(this.hideTimer);
  144 +if(!this.isHidden)b=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut();a.isHidden=!0},o(this.options.hideDelay,500)),b&&n(b,function(a){a.setState()}),this.chart.hoverPoints=null},hideCrosshairs:function(){n(this.crosshairs,function(a){a&&a.hide()})},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,i,a=ja(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===v&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(n(a,function(a){i=
  145 +a.series.yAxis;g+=a.plotX;h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g:h]);return Na(c,t)},getPosition:function(a,b,c){var d=this.chart,e=d.plotLeft,f=d.plotTop,g=d.plotWidth,h=d.plotHeight,i=o(this.options.distance,12),j=c.plotX,c=c.plotY,d=j+e+(d.inverted?i:-a-i),k=c-b+f+15,l;d<7&&(d=e+r(j,0)+i);d+a>e+g&&(d-=d+a-(e+g),k=c-b+f-i,l=!0);k<f+5&&(k=f+5,l&&c>=k&&c<=k+b&&(k=c+
  146 +f+i));k+b>f+h&&(k=r(f,f+h-b-i));return{x:d,y:k}},defaultFormatter:function(a){var b=this.points||ja(this),c=b[0].series,d;d=[c.tooltipHeaderFormatter(b[0])];n(b,function(a){c=a.series;d.push(c.tooltipFormatter&&c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))});d.push(a.options.footerFormat||"");return d.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h={},i,j=[];i=e.formatter||this.defaultFormatter;var h=c.hoverPoints,k,l=e.crosshairs,
  147 +m=this.shared;clearTimeout(this.hideTimer);this.followPointer=ja(a)[0].series.tooltipOptions.followPointer;g=this.getAnchor(a,b);f=g[0];g=g[1];m&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,h&&n(h,function(a){a.setState()}),n(a,function(a){a.setState("hover");j.push(a.getLabelConfig())}),h={x:a[0].category,y:a[0].y},h.points=j,a=a[0]):h=a.getLabelConfig();i=i.call(h,this);h=a.series;i===!1?this.hide():(this.isHidden&&(Wa(d),d.attr("opacity",1).show()),d.attr({text:i}),k=e.borderColor||
  148 +a.color||h.color||"#606060",d.attr({stroke:k}),this.updatePosition({plotX:f,plotY:g}),this.isHidden=!1);if(l){l=ja(l);for(d=l.length;d--;)if(m=a.series,e=m[d?"yAxis":"xAxis"],l[d]&&e)if(h=d?o(a.stackY,a.y):a.x,e.isLog&&(h=ma(h)),d===1&&m.modifyValue&&(h=m.modifyValue(h)),e=e.getPlotLinePath(h,1),this.crosshairs[d])this.crosshairs[d].attr({d:e,visibility:"visible"});else{h={"stroke-width":l[d].width||1,stroke:l[d].color||"#C0C0C0",zIndex:l[d].zIndex||2};if(l[d].dashStyle)h.dashstyle=l[d].dashStyle;
  149 +this.crosshairs[d]=c.renderer.path(e).attr(h).add()}}A(c,"tooltipRefresh",{text:i,x:f+c.plotLeft,y:g+c.plotTop,borderColor:k})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(t(c.x),t(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)}};xb.prototype={init:function(a,b){var c=b.chart,d=c.events,e=ca?"":c.zoomType,c=a.inverted,f;this.options=b;this.chart=a;this.zoomX=f=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=
  150 +f&&!c||e&&c;this.zoomVert=e&&!c||f&&c;this.runChartClick=d&&!!d.click;this.pinchDown=[];this.lastValidTouch={};if(b.tooltip.enabled)a.tooltip=new wb(a,b.tooltip);this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||N.event;if(!a.target)a.target=a.srcElement;a=Xb(a);d=a.touches?a.touches.item(0):a;if(!b)this.chartPosition=b=Wb(this.chart.container);d.pageX===v?(c=r(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top);return s(a,{chartX:t(c),chartY:t(d)})},getCoordinates:function(a){var b=
  151 +{xAxis:[],yAxis:[]};n(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e,f=b.hoverPoint,g=b.hoverSeries,h,i,j=b.chartWidth,k=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!g||!g.noSharedTooltip)){e=[];h=c.length;for(i=0;i<h;i++)if(c[i].visible&&
  152 +c[i].options.enableMouseTracking!==!1&&!c[i].noSharedTooltip&&c[i].tooltipPoints.length&&(b=c[i].tooltipPoints[k])&&b.series)b._dist=M(k-b.clientX),j=J(j,b._dist),e.push(b);for(h=e.length;h--;)e[h]._dist>j&&e.splice(h,1);if(e.length&&e[0].clientX!==this.hoverX)d.refresh(e,a),this.hoverX=e[0].clientX}if(g&&g.tracker){if((b=g.tooltipPoints[k])&&b!==f)b.onMouseOver(a)}else d&&d.followPointer&&!d.isHidden&&(a=d.getAnchor([{}],a),d.updatePosition({plotX:a[0],plotY:a[1]}))},reset:function(a){var b=this.chart,
  153 +c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,b=e&&e.shared?b.hoverPoints:d;(a=a&&e&&b)&&ja(b)[0].plotX===v&&(a=!1);if(a)e.refresh(b);else{if(d)d.onMouseOut();if(c)c.onMouseOut();e&&(e.hide(),e.hideCrosshairs());this.hoverX=null}},scaleGroups:function(a,b){var c=this.chart,d;n(c.series,function(e){d=a||e.getPlotBox();e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))});c.clipRect.attr(b||
  154 +c.clipBox)},pinchTranslate:function(a,b,c,d,e,f,g,h){a&&this.pinchTranslateDirection(!0,c,d,e,f,g,h);b&&this.pinchTranslateDirection(!1,c,d,e,f,g,h)},pinchTranslateDirection:function(a,b,c,d,e,f,g,h){var i=this.chart,j=a?"x":"y",k=a?"X":"Y",l="chart"+k,m=a?"width":"height",p=i["plot"+(a?"Left":"Top")],q,o,n=h||1,r=i.inverted,t=i.bounds[a?"h":"v"],u=b.length===1,s=b[0][l],v=c[0][l],w=!u&&b[1][l],x=!u&&c[1][l],y,c=function(){!u&&M(s-w)>20&&(n=h||M(v-x)/M(s-w));o=(p-v)/n+s;q=i["plot"+(a?"Width":"Height")]/
  155 +n};c();b=o;b<t.min?(b=t.min,y=!0):b+q>t.max&&(b=t.max-q,y=!0);y?(v-=0.8*(v-g[j][0]),u||(x-=0.8*(x-g[j][1])),c()):g[j]=[v,x];r||(f[j]=o-p,f[m]=q);f=r?1/n:n;e[m]=q;e[j]=b;d[r?a?"scaleY":"scaleX":"scale"+k]=n;d["translate"+k]=f*p+(v-f*s)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=c.tooltip&&c.tooltip.options.followTouchMove,f=a.touches,g=f.length,h=b.lastValidTouch,i=b.zoomHor||b.pinchHor,j=b.zoomVert||b.pinchVert,k=i||j,l=b.selectionMarker,m={},p=g===1&&(b.inClass(a.target,"highcharts-tracker")&&
  156 +c.runTrackerClick||c.runChartClick),q={};(k||e)&&!p&&a.preventDefault();Na(f,function(a){return b.normalize(a)});if(a.type==="touchstart")n(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&&d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],n(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=J(e,f),e=r(e,f);b.min=J(a.pos,g-d);b.max=r(a.pos+a.len,e+d)}});else if(d.length){if(!l)b.selectionMarker=
  157 +l=s({destroy:oa},c.plotBox);b.pinchTranslate(i,j,d,f,m,l,q,h);b.hasPinched=k;b.scaleGroups(m,q);!k&&e&&g===1&&this.runPointActions(b.normalize(a))}},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,g=this.zoomVert,h=b.plotLeft,i=b.plotTop,j=b.plotWidth,k=b.plotHeight,l,m=this.mouseDownX,p=this.mouseDownY;d<
  158 +h?d=h:d>h+j&&(d=h+j);e<i?e=i:e>i+k&&(e=i+k);this.hasDragged=Math.sqrt(Math.pow(m-d,2)+Math.pow(p-e,2));if(this.hasDragged>10){l=b.isInsidePlot(m-h,p-i);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!this.selectionMarker)this.selectionMarker=b.renderer.rect(h,i,f?1:j,g?1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();this.selectionMarker&&f&&(d-=m,this.selectionMarker.attr({width:M(d),x:(d>0?0:d)+m}));this.selectionMarker&&g&&(d=e-p,this.selectionMarker.attr({height:M(d),
  159 +y:(d>0?0:d)+p}));l&&!this.selectionMarker&&c.panning&&b.pan(a,c.panning)}},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var d={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},e=this.selectionMarker,f=e.x,g=e.y,h;if(this.hasDragged||c)n(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.toValue(b?f:g),b=a.toValue(b?f+e.width:g+e.height);!isNaN(c)&&!isNaN(b)&&(d[a.xOrY+"Axis"].push({axis:a,min:J(c,b),max:r(c,b)}),h=!0)}}),h&&A(b,"selection",d,function(a){b.zoom(s(a,
  160 +c?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();c&&this.scaleGroups()}if(b)I(b.container,{cursor:b._cursor}),b.cancelClick=this.hasDragged>10,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){this.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=this.normalize(a,c);
  161 +c&&d&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){this.reset();this.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart,a=this.normalize(a);a.returnValue=!1;b.mouseIsDown==="mousedown"&&this.drag(a);(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=
  162 +w(a,"class"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf("highcharts-container")!==-1)return!1;a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries;if(b&&!b.options.stickyTracking&&!this.inClass(a.toElement||a.relatedTarget,"highcharts-tooltip"))b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,f=b.inverted,g,h,i,a=this.normalize(a);a.cancelBubble=!0;if(!b.cancelClick)c&&this.inClass(a.target,"highcharts-tracker")?(g=this.chartPosition,
  163 +h=c.plotX,i=c.plotY,s(c,{pageX:g.left+d+(f?b.plotWidth-i:h),pageY:g.top+e+(f?b.plotHeight-h:i)}),A(c.series,"click",s(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(s(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&A(b,"click",a))},onContainerTouchStart:function(a){var b=this.chart;a.touches.length===1?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)?(this.runPointActions(a),this.pinch(a)):this.reset()):a.touches.length===2&&this.pinch(a)},onContainerTouchMove:function(a){(a.touches.length===
  164 +1||a.touches.length===2)&&this.pinch(a)},onDocumentTouchEnd:function(a){this.drop(a)},setDOMEvents:function(){var a=this,b=a.chart.container,c;this._events=c=[[b,"onmousedown","onContainerMouseDown"],[b,"onmousemove","onContainerMouseMove"],[b,"onclick","onContainerClick"],[b,"mouseleave","onContainerMouseLeave"],[z,"mousemove","onDocumentMouseMove"],[z,"mouseup","onDocumentMouseUp"]];jb&&c.push([b,"ontouchstart","onContainerTouchStart"],[b,"ontouchmove","onContainerTouchMove"],[z,"touchend","onDocumentTouchEnd"]);
  165 +n(c,function(b){a["_"+b[2]]=function(c){a[b[2]](c)};b[1].indexOf("on")===0?b[0][b[1]]=a["_"+b[2]]:K(b[0],b[1],a["_"+b[2]])})},destroy:function(){var a=this;n(a._events,function(b){b[1].indexOf("on")===0?b[0][b[1]]=null:$(b[0],b[1],a["_"+b[2]])});delete a._events;clearInterval(a.tooltipTimeout)}};fb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=o(b.padding,8),f=b.itemMarginTop||0;this.options=b;if(b.enabled)c.baseline=y(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=x(d,b.itemHiddenStyle),
  166 +c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.render(),K(c.chart,"endResize",function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.color:g,g=a.options&&a.options.marker,i={stroke:h,fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(j in g=a.convertAttribs(g),
  167 +g)d=g[j],d!==v&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;n(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Ta(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},
  168 +positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,n(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,I(f,{left:b.translateX+e.legendItemWidth+f.x-20+"px",top:g+"px",display:g>c-6&&g<c+d-6?"":S}))})},renderTitle:function(){var a=this.padding,b=this.options.title,c=0;if(b.text){if(!this.title)this.title=this.chart.renderer.label(b.text,a-3,a-4,null,null,null,null,null,"legend-title").attr({zIndex:1}).css(b.style).add(this.group);
  169 +a=this.title.getBBox();c=a.height;this.offsetWidth=a.width;this.contentGroup.attr({translateY:c})}this.titleHeight=c},renderItem:function(a){var C;var b=this,c=b.chart,d=c.renderer,e=b.options,f=e.layout==="horizontal",g=e.symbolWidth,h=e.symbolPadding,i=b.itemStyle,j=b.itemHiddenStyle,k=b.padding,l=f?o(e.itemDistance,8):0,m=!e.rtl,p=e.width,q=e.itemMarginBottom||0,n=b.itemMarginTop,B=b.initialItemX,t=a.legendItem,u=a.series||a,s=u.options,v=s.showCheckbox,w=e.useHTML;if(!t&&(a.legendGroup=d.g("legend-item").attr({zIndex:1}).add(b.scrollGroup),
  170 +u.drawLegendSymbol(b,a),a.legendItem=t=d.text(e.labelFormat?Ca(e.labelFormat,a):e.labelFormatter.call(a),m?g+h:-h,b.baseline,w).css(x(a.visible?i:j)).attr({align:m?"left":"right",zIndex:2}).add(a.legendGroup),(w?t:a.legendGroup).on("mouseover",function(){a.setState("hover");t.css(b.options.itemHoverStyle)}).on("mouseout",function(){t.css(a.visible?i:j);a.setState()}).on("click",function(b){var c=function(){a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):
  171 +A(a,"legendItemClick",b,c)}),b.colorizeItem(a,a.visible),s&&v))a.checkbox=U("input",{type:"checkbox",checked:a.selected,defaultChecked:a.selected},e.itemCheckboxStyle,c.container),K(a.checkbox,"click",function(b){A(a,"checkboxClick",{checked:b.target.checked},function(){a.select()})});d=t.getBBox();C=a.legendItemWidth=e.itemWidth||g+h+d.width+l+(v?20:0),e=C;b.itemHeight=g=d.height;if(f&&b.itemX-B+e>(p||c.chartWidth-2*k-B))b.itemX=B,b.itemY+=n+b.lastLineHeight+q,b.lastLineHeight=0;b.maxItemWidth=r(b.maxItemWidth,
  172 +e);b.lastItemY=n+b.itemY+q;b.lastLineHeight=r(g,b.lastLineHeight);a._legendItemPos=[b.itemX,b.itemY];f?b.itemX+=e:(b.itemY+=n+g+q,b.lastLineHeight=g);b.offsetWidth=p||r((f?b.itemX-B-l:e)+k,b.offsetWidth)},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,m=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),
  173 +a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=[];n(b.series,function(a){var b=a.options;if(o(b.showInLegend,b.linkedTo===v?v:!1,!0))e=e.concat(a.legendItems||(b.legendType==="point"?a.data:a))});Kb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;n(e,function(b){a.renderItem(b)});g=j.width||a.offsetWidth;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);if(l||
  174 +m){g+=k;h+=k;if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp(null,null,null,g,h)),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:m||S}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=h;n(e,function(b){a.positionItem(b)});f&&d.align(s({width:g,height:h},j),!0,"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,
  175 +f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h=this.clipRect,i=e.navigation,j=o(i.animation,!0),k=i.arrowSize||12,l=this.nav;e.layout==="horizontal"&&(f/=2);g&&(f=J(f,g));if(a>f&&!e.useHTML){this.clipHeight=c=f-20-this.titleHeight;this.pageCount=wa(a/c);this.currentPage=o(this.currentPage,1);this.fullHeight=a;if(!h)h=b.clipRect=d.clipRect(0,0,9999,0),b.contentGroup.clip(h);h.attr({height:c});if(!l)this.nav=l=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",
  176 +0,0,k,k).on("click",function(){b.scroll(-1,j)}).add(l),this.pager=d.text("",15,10).css(i.style).add(l),this.down=d.symbol("triangle-down",0,0,k,k).on("click",function(){b.scroll(1,j)}).add(l);b.scroll(0);a=f}else if(l)h.attr({height:c.chartHeight}),l.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pageCount,d=this.currentPage+a,e=this.clipHeight,f=this.options.navigation,g=f.activeColor,h=f.inactiveColor,f=this.pager,i=this.padding;d>c&&(d=
  177 +c);if(d>0)b!==v&&La(b,this.chart),this.nav.attr({translateX:i,translateY:e+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:d===1?h:g}).css({cursor:d===1?"default":"pointer"}),f.attr({text:d+"/"+this.pageCount}),this.down.attr({x:18+this.pager.getBBox().width,fill:d===c?h:g}).css({cursor:d===c?"default":"pointer"}),e=-J(e*(d-1),this.fullHeight-e+i)+1,this.scrollGroup.animate({translateY:e}),f.attr({text:d+"/"+c}),this.currentPage=d,this.positionCheckboxes(e)}};/Trident\/7\.0/.test(na)&&
  178 +mb(fb.prototype,"positionItem",function(a,b){var c=this,d=function(){a.call(c,b)};c.chart.renderer.forExport?d():setTimeout(d)});yb.prototype={init:function(a,b){var c,d=a.series;a.series=null;c=x(L,a);c.series=a.series=d;d=c.chart;this.margin=this.splashArray("margin",d);this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}};this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=Ga.length;Ga.push(f);
  179 +d.reflow!==!1&&K(f,"load",function(){f.initReflow()});if(e)for(g in e)K(f,g,e[g]);f.xAxis=[];f.yAxis=[];f.animation=ca?!1:o(d.animation,!0);f.pointCount=0;f.counters=new Jb;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=X[a.type||b.type||b.defaultSeriesType])||ka(17,!0);b=new b;b.init(this,a);return b},addSeries:function(a,b,c){var d,e=this;a&&(b=o(b,!0),A(e,"addSeries",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;e.linkSeries();b&&e.redraw(c)}));return d},addAxis:function(a,
  180 +b,c,d){var e=b?"xAxis":"yAxis",f=this.options;new eb(this,x(a,{index:this[e].length,isX:b}));f[e]=ja(f[e]||{});f[e].push(a);o(c,!0)&&this.redraw(d)},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&n(this.axes,function(a){a.adjustTickAmount()});this.maxTicks=null},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.isDirtyBox,
  181 +j=c.length,k=j,l=this.renderer,m=l.isHidden(),p=[];La(a,this);m&&this.cloneRenderTo();for(this.layOutTitles();k--;)if(a=c[k],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(k=j;k--;)if(a=c[k],a.options.stacking)a.isDirty=!0;n(c,function(a){a.isDirty&&a.options.legendType==="point"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(this.hasCartesianSeries){if(!this.isResizing)this.maxTicks=null,n(b,function(a){a.setScale()});this.adjustTickAmounts();
  182 +this.getMargins();n(b,function(a){a.isDirty&&(i=!0)});n(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,p.push(function(){A(a,"afterSetExtremes",s(a.eventArgs,a.getExtremes()));delete a.eventArgs});(i||g)&&a.redraw()})}i&&this.drawChartBox();n(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.reset&&d.reset(!0);l.draw();A(this,"redraw");m&&this.cloneRenderTo(!0);n(p,function(a){a.call()})},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;
  183 +if(!c)this.loadingDiv=c=U(Ea,{className:"highcharts-loading"},s(d.style,{zIndex:10,display:S}),this.container),this.loadingSpan=U("span",null,d.labelStyle,c);this.loadingSpan.innerHTML=a||b.lang.loading;if(!this.loadingShown)I(c,{opacity:0,display:"",left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px"}),Bb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&Bb(b,
  184 +{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){I(b,{display:S})}});this.loadingShown=!1},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;d<b.length;d++)if(b[d].options.id===a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++){e=c[d].points||[];for(b=0;b<e.length;b++)if(e[b].id===a)return e[b]}return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis=ja(b.xAxis||{}),b=b.yAxis=ja(b.yAxis||{});n(c,function(a,b){a.index=
  185 +b;a.isX=!0});n(b,function(a,b){a.index=b});c=c.concat(b);n(c,function(b){new eb(a,b)});a.adjustTickAmounts()},getSelectedPoints:function(){var a=[];n(this.series,function(b){a=a.concat(ub(b.points||[],function(a){return a.selected}))});return a},getSelectedSeries:function(){return ub(this.series,function(a){return a.selected})},getStacks:function(){var a=this;n(a.yAxis,function(a){if(a.stacks&&a.hasVisibleSeries)a.oldStacks=a.stacks});n(a.series,function(b){if(b.options.stacking&&(b.visible===!0||
  186 +a.options.chart.ignoreHiddenSeries===!1))b.stackKey=b.type+o(b.options.stack,"")})},showResetZoom:function(){var a=this,b=L.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,f=c.relativeTo==="chart"?null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).add().align(c.position,!1,f)},zoomOut:function(){var a=this;A(a,"selection",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var b,
  187 +c=this.pointer,d=!1,e;!a||a.resetSelection?n(this.axes,function(a){b=a.zoom()}):n(a.xAxis.concat(a.yAxis),function(a){var e=a.axis,h=e.isXAxis;if(c[h?"zoomX":"zoomY"]||c[h?"pinchX":"pinchY"])b=e.zoom(a.min,a.max),e.displayBtn&&(d=!0)});e=this.resetZoomButton;if(d&&!e)this.showResetZoom();else if(!d&&T(e))this.resetZoomButton=e.destroy();b&&this.redraw(o(this.options.chart.animation,a&&a.animation,this.pointCount<100))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&n(d,function(a){a.setState()});
  188 +n(b==="xy"?[1,0]:[1],function(b){var d=a[b?"chartX":"chartY"],h=c[b?"xAxis":"yAxis"][0],i=c[b?"mouseDownX":"mouseDownY"],j=(h.pointRange||0)/2,k=h.getExtremes(),l=h.toValue(i-d,!0)+j,i=h.toValue(i+c[b?"plotWidth":"plotHeight"]-d,!0)-j;h.series.length&&l>J(k.dataMin,k.min)&&i<r(k.dataMax,k.max)&&(h.setExtremes(l,i,!1,!1,{trigger:"pan"}),e=!0);c[b?"mouseDownX":"mouseDownY"]=d});e&&c.redraw(!1);I(c.container,{cursor:"move"})},setTitle:function(a,b){var f;var c=this,d=c.options,e;e=d.title=x(d.title,
  189 +a);f=d.subtitle=x(d.subtitle,b),d=f;n([["title",a,e],["subtitle",b,d]],function(a){var b=a[0],d=c[b],e=a[1],a=a[2];d&&e&&(c[b]=d=d.destroy());a&&a.text&&!d&&(c[b]=c.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add())});c.layOutTitles()},layOutTitles:function(){var a=0,b=this.title,c=this.subtitle,d=this.options,e=d.title,d=d.subtitle,f=this.spacingBox.width-44;if(b&&(b.css({width:(e.width||f)+"px"}).align(s({y:15},e),!1,"spacingBox"),
  190 +!e.floating&&!e.verticalAlign))a=b.getBBox().height,a>=18&&a<=25&&(a=15);c&&(c.css({width:(d.width||f)+"px"}).align(s({y:a+e.margin},d),!1,"spacingBox"),!d.floating&&!d.verticalAlign&&(a=wa(a+c.getBBox().height)));this.titleOffset=a},getChartSize:function(){var a=this.options.chart,b=this.renderToClone||this.renderTo;this.containerWidth=kb(b,"width");this.containerHeight=kb(b,"height");this.chartWidth=r(0,a.width||this.containerWidth||600);this.chartHeight=r(0,o(a.height,this.containerHeight>19?this.containerHeight:
  191 +400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ta(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),I(b,{position:"absolute",top:"-9999px",display:"block"}),z.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+zb++;if(ea(a))this.renderTo=a=z.getElementById(a);
  192 +a||ka(13,!0);c=y(w(a,"data-highcharts-chart"));!isNaN(c)&&Ga[c]&&Ga[c].destroy();w(a,"data-highcharts-chart",this.index);a.innerHTML="";a.offsetWidth||this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=U(Ea,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},s({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||
  193 +a);this._cursor=a.style.cursor;this.renderer=b.forExport?new za(a,c,d,!0):new Va(a,c,d);ca&&this.renderer.create(this,a,c,d)},getMargins:function(){var a=this.spacing,b,c=this.legend,d=this.margin,e=this.options.legend,f=o(e.margin,10),g=e.x,h=e.y,i=e.align,j=e.verticalAlign,k=this.titleOffset;this.resetMargins();b=this.axisOffset;if(k&&!u(d[0]))this.plotTop=r(this.plotTop,k+this.options.title.margin+a[0]);if(c.display&&!e.floating)if(i==="right"){if(!u(d[1]))this.marginRight=r(this.marginRight,c.legendWidth-
  194 +g+f+a[1])}else if(i==="left"){if(!u(d[3]))this.plotLeft=r(this.plotLeft,c.legendWidth+g+f+a[3])}else if(j==="top"){if(!u(d[0]))this.plotTop=r(this.plotTop,c.legendHeight+h+f+a[0])}else if(j==="bottom"&&!u(d[2]))this.marginBottom=r(this.marginBottom,c.legendHeight-h+f+a[2]);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);this.hasCartesianSeries&&n(this.axes,function(a){a.getOffset()});u(d[3])||(this.plotLeft+=b[3]);u(d[0])||
  195 +(this.plotTop+=b[0]);u(d[2])||(this.marginBottom+=b[2]);u(d[1])||(this.marginRight+=b[1]);this.setChartSize()},initReflow:function(){function a(a){var g=c.width||kb(d,"width"),h=c.height||kb(d,"height"),a=a?a.target:N;if(!b.hasUserSize&&g&&h&&(a===N||a===z)){if(g!==b.containerWidth||h!==b.containerHeight)clearTimeout(e),b.reflowTimeout=e=setTimeout(function(){if(b.container)b.setSize(g,h,!1),b.hasUserSize=null},100);b.containerWidth=g;b.containerHeight=h}}var b=this,c=b.options.chart,d=b.renderTo,
  196 +e;b.reflow=a;K(N,"resize",a);K(b,"destroy",function(){$(N,"resize",a)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&A(d,"endResize",null,function(){d.isResizing-=1})};La(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(u(a))d.chartWidth=e=r(0,t(a)),d.hasUserSize=!!e;if(u(b))d.chartHeight=f=r(0,t(b));I(d.container,{width:e+"px",height:f+"px"});d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;n(d.axes,function(a){a.isDirty=!0;a.setScale()});
  197 +n(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.getMargins();d.redraw(c);d.oldChartHeight=null;A(d,"resize");Fa===!1?g():setTimeout(g,Fa&&Fa.duration||500)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset,i,j,k,l;this.plotLeft=i=t(this.plotLeft);this.plotTop=j=t(this.plotTop);this.plotWidth=k=r(0,t(d-i-this.marginRight));this.plotHeight=l=r(0,t(e-j-this.marginBottom));
  198 +this.plotSizeX=b?l:k;this.plotSizeY=b?k:l;this.plotBorderWidth=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]};this.plotBox=c.plotBox={x:i,y:j,width:k,height:l};d=2*P(this.plotBorderWidth/2);b=wa(r(d,h[3])/2);c=wa(r(d,h[0])/2);this.clipBox={x:b,y:c,width:P(this.plotSizeX-r(d,h[1])/2-b),height:P(this.plotSizeY-r(d,h[2])/2-c)};a||n(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this.spacing,b=this.margin;
  199 +this.plotTop=o(b[0],a[0]);this.marginRight=o(b[1],a[1]);this.marginBottom=o(b[2],a[2]);this.plotLeft=o(b[3],a[3]);this.axisOffset=[0,0,0,0];this.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,m=a.plotBorderWidth||0,p,q=this.plotLeft,o=this.plotTop,n=this.plotWidth,
  200 +r=this.plotHeight,t=this.plotBox,u=this.clipRect,s=this.clipBox;p=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp(null,null,null,c-p,d-p));else{e={fill:j||S};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(p/2,p/2,c-p,d-p,a.borderRadius,i).attr(e).add().shadow(a.shadow)}if(k)f?f.animate(t):this.plotBackground=b.rect(q,o,n,r,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(t):this.plotBGImage=b.image(l,q,o,n,r).add();u?u.animate({width:s.width,height:s.height}):
  201 +this.clipRect=b.clipRect(s);if(m)g?g.animate(g.crisp(null,q,o,n,r)):this.plotBorder=b.rect(q,o,n,r,0,-m).attr({stroke:a.plotBorderColor,"stroke-width":m,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;n(["inverted","angular","polar"],function(g){c=X[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=X[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;
  202 +n(b,function(a){a.linkedSeries.length=0});n(b,function(b){var d=b.options.linkedTo;if(ea(d)&&(d=d===":previous"?a.series[b.index-1]:a.get(d)))d.linkedSeries.push(b),b.linkedParent=d})},render:function(){var a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,f=d.credits,g;a.setTitle();a.legend=new fb(a,d.legend);a.getStacks();n(b,function(a){a.setScale()});a.getMargins();a.maxTicks=null;n(b,function(a){a.setTickPositions(!0);a.setMaxTicks()});a.adjustTickAmounts();a.getMargins();a.drawChartBox();
  203 +a.hasCartesianSeries&&n(b,function(a){a.render()});if(!a.seriesGroup)a.seriesGroup=c.g("series-group").attr({zIndex:3}).add();n(a.series,function(a){a.translate();a.setTooltipPoints();a.render()});e.items&&n(e.items,function(b){var d=s(e.style,b.style),f=y(d.left)+a.plotLeft,g=y(d.top)+a.plotTop+12;delete d.left;delete d.top;c.text(b.html,f,g).attr({zIndex:2}).css(d).add()});if(f.enabled&&!a.credits)g=f.href,a.credits=c.text(f.text,0,0).on("click",function(){if(g)location.href=g}).attr({align:f.position.align,
  204 +zIndex:8}).css(f.style).add().align(f.position);a.hasRendered=!0},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;A(a,"destroy");Ga[a.index]=v;a.renderTo.removeAttribute("data-highcharts-chart");$(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();n("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=
  205 +a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML="",$(d),f&&Ta(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!W&&N==N.top&&z.readyState!=="complete"||ca&&!N.canvg?(ca?Tb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):z.attachEvent("onreadystatechange",function(){z.detachEvent("onreadystatechange",a.firstRender);z.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender())a.getContainer(),
  206 +A(a,"init"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),n(b.series||[],function(b){a.initSeries(b)}),a.linkSeries(),A(a,"beforeRender"),a.pointer=new xb(a,b),a.render(),a.renderer.draw(),c&&c.apply(a,[a]),n(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),A(a,"load")},splashArray:function(a,b){var c=b[a],c=T(c)?c:[c,c,c,c];return[o(b[a+"Top"],c[0]),o(b[a+"Right"],c[1]),o(b[a+"Bottom"],c[2]),o(b[a+"Left"],c[3])]}};yb.prototype.callbacks=[];var Pa=function(){};Pa.prototype=
  207 +{init:function(a,b,c){this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.pointValKey,a=Pa.prototype.optionsToObject.call(this,a);s(this,a);this.options=this.options?s(this.options,a):a;if(d)this.y=this[d];if(this.x===v&&c)this.x=b===v?c.autoIncrement():b;return this},
  208 +optionsToObject:function(a){var b={},c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if(typeof a==="number"||a===null)b[d[0]]=a;else if(Ia(a)){if(a.length>e){c=typeof a[0];if(c==="string")b.name=a[0];else if(c==="number")b.x=a[0];f++}for(;g<e;)b[d[g++]]=a[f++]}else if(typeof a==="object"){b=a;if(a.dataLabels)c._hasPointLabels=!0;if(a.marker)c._hasPointMarkers=!0}return b},destroy:function(){var a=this.series.chart,b=a.hoverPoints,c;a.pointCount--;if(b&&(this.setState(),ga(b,this),!b.length))a.hoverPoints=
  209 +null;if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)$(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var a="graphic,dataLabel,dataLabelUpper,group,connector,shadowGroup".split(","),b,c=6;c--;)b=a[c],this[b]&&(this[b]=this[b].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||
  210 +this.stackTotal}},select:function(a,b){var c=this,d=c.series,e=d.chart,a=o(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=c.options.selected=a;d.options.data[pa(c,d.data)]=c.options;c.setState(a&&"select");b||n(e.getSelectedPoints(),function(a){if(a.selected&&a!==c)a.selected=a.options.selected=!1,d.options.data[pa(a,d.data)]=a.options,a.setState(""),a.firePointEvent("unselect")})})},onMouseOver:function(a){var b=this.series,c=b.chart,d=c.tooltip,e=c.hoverPoint;
  211 +if(e&&e!==this)e.onMouseOut();this.firePointEvent("mouseOver");d&&(!d.shared||b.noSharedTooltip)&&d.refresh(this,a);this.setState("hover");c.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;if(!b||pa(this,b)===-1)this.firePointEvent("mouseOut"),this.setState(),a.hoverPoint=null},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=o(c.valueDecimals,""),e=c.valuePrefix||"",f=c.valueSuffix||"";n(b.pointArrayMap||["y"],function(b){b="{point."+b;if(e||f)a=
  212 +a.replace(b+"}",e+b+"}"+f);a=a.replace(b+"}",b+":,."+d+"f}")});return Ca(a,{point:this,series:this.series})},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g,h=e.data,i=e.chart,j=e.options,b=o(b,!0);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);if(T(a)&&(e.getAttribs(),f))a&&a.marker&&a.marker.symbol?d.graphic=f.destroy():f.attr(d.pointAttr[d.state||""]);g=pa(d,h);e.xData[g]=d.x;e.yData[g]=e.toYData?e.toYData(d):d.y;e.zData[g]=d.z;j.data[g]=d.options;e.isDirty=e.isDirtyData=
  213 +!0;if(!e.fixedBox&&e.hasCartesianSeries)i.isDirtyBox=!0;j.legendType==="point"&&i.legend.destroyItem(d);b&&i.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.points,f=d.chart,g,h=d.data;La(b,f);a=o(a,!0);c.firePointEvent("remove",null,function(){g=pa(c,h);h.length===e.length&&e.splice(g,1);h.splice(g,1);d.options.data.splice(g,1);d.xData.splice(g,1);d.yData.splice(g,1);d.zData.splice(g,1);c.destroy();d.isDirty=!0;d.isDirtyData=!0;a&&f.redraw()})},firePointEvent:function(a,b,c){var d=this,
  214 +e=this.series.options;(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();a==="click"&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});A(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=x(this.series.options.point,this.options).events,b;this.events=a;for(b in a)K(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a){var b=this.plotX,c=this.plotY,d=this.series,e=d.options.states,f=Z[d.type].marker&&
  215 +d.options.marker,g=f&&!f.enabled,h=f&&f.states[a],i=h&&h.enabled===!1,j=d.stateMarkerGraphic,k=this.marker||{},l=d.chart,m=this.pointAttr,a=a||"";if(!(a===this.state||this.selected&&a!=="select"||e[a]&&e[a].enabled===!1||a&&(i||g&&!h.enabled)||a&&k.states&&k.states[a]&&k.states[a].enabled===!1)){if(this.graphic)e=f&&this.graphic.symbolName&&m[a].r,this.graphic.attr(x(m[a],e?{x:b-e,y:c-e,width:2*e,height:2*e}:{}));else{if(a&&h)e=h.radius,k=k.symbol||d.symbol,j&&j.currentSymbol!==k&&(j=j.destroy()),
  216 +j?j.attr({x:b-e,y:c-e}):(d.stateMarkerGraphic=j=l.renderer.symbol(k,b-e,c-e,2*e,2*e).attr(m[a]).add(d.markerGroup),j.currentSymbol=k);if(j)j[a&&l.isInsidePlot(b,c)?"show":"hide"]()}this.state=a}}};var Q=function(){};Q.prototype={isCartesian:!0,type:"line",pointClass:Pa,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},colorCounter:0,init:function(a,b){var c,d,e=a.series;this.chart=a;this.options=b=this.setOptions(b);this.linkedSeries=
  217 +[];this.bindAxes();s(this,{name:b.name,state:"",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0});if(ca)b.animation=!1;d=b.events;for(c in d)K(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;this.getColor();this.getSymbol();this.setData(b.data,!1);if(this.isCartesian)a.hasCartesianSeries=!0;e.push(this);this._i=e.length-1;Kb(e,function(a,b){return o(a.options.index,a._i)-o(b.options.index,a._i)});n(e,function(a,b){a.index=
  218 +b;a.name=a.name||"Series "+(b+1)})},bindAxes:function(){var a=this,b=a.options,c=a.chart,d;a.isCartesian&&n(["xAxis","yAxis"],function(e){n(c[e],function(c){d=c.options;if(b[e]===d.index||b[e]!==v&&b[e]===d.id||b[e]===v&&d.index===0)c.series.push(a),a[e]=c,c.isDirty=!0});a[e]||ka(18,!0)})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=o(b,a.pointStart,0);this.pointInterval=o(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},getSegments:function(){var a=
  219 +-1,b=[],c,d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)d[c].y===null&&d.splice(c,1);d.length&&(b=[d])}else n(d,function(c,g){c.y===null?(g>a+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=c[this.type];this.userOptions=a;a=x(d,c.series,a);this.tooltipOptions=x(b.tooltip,a.tooltip);d.marker===null&&delete a.marker;return a},getColor:function(){var a=this.options,b=this.userOptions,
  220 +c=this.chart.options.colors,d=this.chart.counters,e;e=a.color||Z[this.type].color;if(!e&&!a.colorByPoint)u(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a];this.color=e;d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol;if(!this.symbol)u(a._symbolIndex)?a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++),this.symbol=d[a];if(/^url/.test(this.symbol))b.radius=0;c.wrapSymbol(d.length)},
  221 +drawLegendSymbol:function(a){var b=this.options,c=b.marker,d=a.options,e;e=d.symbolWidth;var f=this.chart.renderer,g=this.legendGroup,a=a.baseline-t(f.fontMetrics(d.itemStyle.fontSize).b*0.3);if(b.lineWidth){d={"stroke-width":b.lineWidth};if(b.dashStyle)d.dashstyle=b.dashStyle;this.legendLine=f.path(["M",0,a,"L",e,a]).attr(d).add(g)}if(c&&c.enabled)b=c.radius,this.legendSymbol=e=f.symbol(this.symbol,e/2-b,a-b,2*b,2*b).add(g),e.isMarker=!0},addPoint:function(a,b,c,d){var e=this.options,f=this.data,
  222 +g=this.graph,h=this.area,i=this.chart,j=this.xData,k=this.yData,l=this.zData,m=this.xAxis&&this.xAxis.names,p=g&&g.shift||0,q=e.data,r;La(d,i);c&&n([g,h,this.graphNeg,this.areaNeg],function(a){if(a)a.shift=p+1});if(h)h.isArea=!0;b=o(b,!0);d={series:this};this.pointClass.prototype.applyOptions.apply(d,[a]);g=d.x;h=j.length;if(this.requireSorting&&g<j[h-1])for(r=!0;h&&j[h-1]>g;)h--;j.splice(h,0,g);k.splice(h,0,this.toYData?this.toYData(d):d.y);l.splice(h,0,d.z);if(m)m[g]=d.name;q.splice(h,0,a);r&&(this.data.splice(h,
  223 +0,null),this.processData());e.legendType==="point"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),j.shift(),k.shift(),l.shift(),q.shift()));this.isDirtyData=this.isDirty=!0;b&&(this.getAttribs(),i.redraw())},setData:function(a,b){var c=this.points,d=this.options,e=this.chart,f=null,g=this.xAxis,h=g&&g.names,i;this.xIncrement=null;this.pointRange=g&&g.categories?1:d.pointRange;this.colorCounter=0;var j=[],k=[],l=[],m=a?a.length:[];i=o(d.turboThreshold,1E3);var p=this.pointArrayMap,
  224 +p=p&&p.length,q=!!this.toYData;if(i&&m>i){for(i=0;f===null&&i<m;)f=a[i],i++;if(ra(f)){h=o(d.pointStart,0);d=o(d.pointInterval,1);for(i=0;i<m;i++)j[i]=h,k[i]=a[i],h+=d;this.xIncrement=h}else if(Ia(f))if(p)for(i=0;i<m;i++)d=a[i],j[i]=d[0],k[i]=d.slice(1,p+1);else for(i=0;i<m;i++)d=a[i],j[i]=d[0],k[i]=d[1];else ka(12)}else for(i=0;i<m;i++)if(a[i]!==v&&(d={series:this},this.pointClass.prototype.applyOptions.apply(d,[a[i]]),j[i]=d.x,k[i]=q?this.toYData(d):d.y,l[i]=d.z,h&&d.name))h[d.x]=d.name;ea(k[0])&&
  225 +ka(14,!0);this.data=[];this.options.data=a;this.xData=j;this.yData=k;this.zData=l;for(i=c&&c.length||0;i--;)c[i]&&c[i].destroy&&c[i].destroy();if(g)g.minRange=g.userMinRange;this.isDirty=this.isDirtyData=e.isDirtyBox=!0;o(b,!0)&&e.redraw(!1)},remove:function(a,b){var c=this,d=c.chart,a=o(a,!0);if(!c.isRemoving)c.isRemoving=!0,A(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=!0;d.linkSeries();a&&d.redraw(b)});c.isRemoving=!1},processData:function(a){var b=this.xData,c=this.yData,
  226 +d=b.length,e;e=0;var f,g,h=this.xAxis,i=this.options,j=i.cropThreshold,k=this.isCartesian;if(k&&!this.isDirty&&!h.isDirty&&!this.yAxis.isDirty&&!a)return!1;if(k&&this.sorted&&(!j||d>j||this.forceCrop))if(a=h.min,h=h.max,b[d-1]<a||b[0]>h)b=[],c=[];else if(b[0]<a||b[d-1]>h)e=this.cropData(this.xData,this.yData,a,h),b=e.xData,c=e.yData,e=e.start,f=!0;for(h=b.length-1;h>=0;h--)d=b[h]-b[h-1],d>0&&(g===v||d<g)?g=d:d<0&&this.requireSorting&&ka(15);this.cropped=f;this.cropStart=e;this.processedXData=b;this.processedYData=
  227 +c;if(i.pointRange===null)this.pointRange=g||1;this.closestPointRange=g},cropData:function(a,b,c,d){var e=a.length,f=0,g=e,h=o(this.cropShoulder,1),i;for(i=0;i<e;i++)if(a[i]>=c){f=r(0,i-h);break}for(;i<e;i++)if(a[i]>d){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],m;if(!b&&!j)b=[],b.length=
  228 +a.length,b=this.data=b;for(m=0;m<g;m++)i=h+m,j?l[m]=(new f).init(this,[d[m]].concat(ja(e[m]))):(b[i]?k=b[i]:a[i]!==v&&(b[i]=k=(new f).init(this,a[i],d[m])),l[m]=k);if(b&&(g!==(c=b.length)||j))for(m=0;m<c;m++)if(m===h&&!j&&(m+=g),b[m])b[m].destroyElements(),b[m].plotX=v;this.data=b;this.points=l},setStackedPoints:function(){if(this.options.stacking&&!(this.visible!==!0&&this.chart.options.chart.ignoreHiddenSeries!==!1)){var a=this.processedXData,b=this.processedYData,c=[],d=b.length,e=this.options,
  229 +f=e.threshold,g=e.stack,e=e.stacking,h=this.stackKey,i="-"+h,j=this.negStacks,k=this.yAxis,l=k.stacks,m=k.oldStacks,p,q,o,n,t;for(o=0;o<d;o++){n=a[o];t=b[o];q=(p=j&&t<f)?i:h;l[q]||(l[q]={});if(!l[q][n])m[q]&&m[q][n]?(l[q][n]=m[q][n],l[q][n].total=null):l[q][n]=new Mb(k,k.options.stackLabels,p,n,g,e);q=l[q][n];q.points[this.index]=[q.cum||0];e==="percent"?(p=p?h:i,j&&l[p]&&l[p][n]?(p=l[p][n],q.total=p.total=r(p.total,q.total)+M(t)||0):q.total+=M(t)||0):q.total+=t||0;q.cum=(q.cum||0)+(t||0);q.points[this.index].push(q.cum);
  230 +c[o]=q.cum}if(e==="percent")k.usePercentage=!0;this.stackedYData=c;k.oldStacks={}}},setPercentStacks:function(){var a=this,b=a.stackKey,c=a.yAxis.stacks;n([b,"-"+b],function(b){var d;for(var e=a.xData.length,f,g;e--;)if(f=a.xData[e],d=(g=c[b]&&c[b][f])&&g.points[a.index],f=d)g=g.total?100/g.total:0,f[0]=ia(f[0]*g),f[1]=ia(f[1]*g),a.stackedYData[e]=f[1]})},getExtremes:function(){var a=this.yAxis,b=this.processedXData,c=this.stackedYData||this.processedYData,d=c.length,e=[],f=0,g=this.xAxis.getExtremes(),
  231 +h=g.min,g=g.max,i,j,k,l;for(l=0;l<d;l++)if(j=b[l],k=c[l],i=k!==null&&k!==v&&(!a.isLog||k.length||k>0),j=this.getExtremesFromAll||this.cropped||(b[l+1]||j)>=h&&(b[l-1]||j)<=g,i&&j)if(i=k.length)for(;i--;)k[i]!==null&&(e[f++]=k[i]);else e[f++]=k;this.dataMin=o(void 0,Ja(e));this.dataMax=o(void 0,ua(e))},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,
  232 +i=a.pointPlacement,j=i==="between"||ra(i),k=a.threshold,a=0;a<g;a++){var l=f[a],m=l.x,p=l.y,q=l.low,n=e.stacks[(this.negStacks&&p<k?"-":"")+this.stackKey];if(e.isLog&&p<=0)l.y=p=null;l.plotX=c.translate(m,0,0,0,1,i,this.type==="flags");if(b&&this.visible&&n&&n[m])n=n[m],p=n.points[this.index],q=p[0],p=p[1],q===0&&(q=o(k,e.min)),e.isLog&&q<=0&&(q=null),l.total=l.stackTotal=n.total,l.percentage=b==="percent"&&l.y/n.total*100,l.stackY=p,n.setOffset(this.pointXOffset||0,this.barW||0);l.yBottom=u(q)?e.translate(q,
  233 +0,1,0,1):null;h&&(p=this.modifyValue(p,l));l.plotY=typeof p==="number"&&p!==Infinity?e.translate(p,0,1,0,1):v;l.clientX=j?c.translate(m,0,0,0,1):l.plotX;l.negative=l.y<(k||0);l.category=d&&d[l.x]!==v?d[l.x]:l.x}this.getSegments()},setTooltipPoints:function(a){var b=[],c,d,e=this.xAxis,f=e&&e.getExtremes(),g=e?e.tooltipLen||e.len:this.chart.plotSizeX,h,i,j=[];if(this.options.enableMouseTracking!==!1){if(a)this.tooltipPoints=null;n(this.segments||this.points,function(a){b=b.concat(a)});e&&e.reversed&&
  234 +(b=b.reverse());this.orderTooltipPoints&&this.orderTooltipPoints(b);a=b.length;for(i=0;i<a;i++)if(e=b[i],c=e.x,c>=f.min&&c<=f.max){h=b[i+1];c=d===v?0:d+1;for(d=b[i+1]?J(r(0,P((e.clientX+(h?h.wrappedClientX||h.clientX:g))/2)),g):g;c>=0&&c<=d;)j[c++]=e}this.tooltipPoints=j}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat,d=b.dateTimeLabelFormats,e=this.xAxis,f=e&&e.options.type==="datetime",b=b.headerFormat,e=e&&e.closestPointRange,g;if(f&&!c)if(e)for(g in D){if(D[g]>=
  235 +e){c=d[g];break}}else c=d.day;f&&c&&ra(a.key)&&(b=b.replace("{point.key}","{point.key:"+c+"}"));return Ca(b,{point:a,series:this})},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&A(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();this&&a.events.mouseOut&&A(this,"mouseOut");c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&
  236 +c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this,c=b.chart,d=c.renderer,e;e=b.options.animation;var f=c.clipBox,g=c.inverted,h;if(e&&!T(e))e=Z[b.type].animation;h="_sharedClip"+e.duration+e.easing;if(a)a=c[h],e=c[h+"m"],a||(c[h]=a=d.clipRect(s(f,{width:0})),c[h+"m"]=e=d.clipRect(-99,g?-c.plotLeft:-c.plotTop,99,g?c.chartWidth:c.chartHeight)),b.group.clip(a),b.markerGroup.clip(e),b.sharedClipKey=h;else{if(a=c[h])a.animate({width:c.plotSizeX},e),c[h+"m"].animate({width:c.plotSizeX+
  237 +99},e);b.animate=null;b.animationTimeout=setTimeout(function(){b.afterAnimate()},e.duration)}},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group;c&&this.options.clip!==!1&&(c.clip(a.clipRect),this.markerGroup.clip());setTimeout(function(){b&&a[b]&&(a[b]=a[b].destroy(),a[b+"m"]=a[b+"m"].destroy())},100)},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,m,n=this.markerGroup;if(l.enabled||this._hasPointMarkers)for(f=b.length;f--;)if(g=
  238 +b[f],d=P(g.plotX),e=g.plotY,k=g.graphic,i=g.marker||{},a=l.enabled&&i.enabled===v||i.enabled,m=c.isInsidePlot(t(d),e,c.inverted),a&&e!==v&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""],h=a.r,i=o(i.symbol,this.symbol),j=i.indexOf("url")===0,k)k.attr({visibility:m?W?"inherit":"visible":"hidden"}).animate(s({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(m&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(n)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,
  239 +b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=o(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=Z[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h={stroke:g,fill:g},i=a.points||[],j=[],k,l=a.pointAttrToOptions,m=b.negativeColor,p=c.lineColor,q;b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||qa(e.color||g).brighten(e.brightness).get();j[""]=a.convertAttribs(c,
  240 +h);n(["hover","select"],function(b){j[b]=a.convertAttribs(d[b],j[""])});a.pointAttr=j;for(g=i.length;g--;){h=i[g];if((c=h.options&&h.options.marker||h.options)&&c.enabled===!1)c.radius=0;if(h.negative&&m)h.color=h.fillColor=m;f=b.colorByPoint||h.color;if(h.options)for(q in l)u(c[l[q]])&&(f=!0);if(f){c=c||{};k=[];d=c.states||{};f=d.hover=d.hover||{};if(!b.marker)f.color=qa(f.color||h.color).brighten(f.brightness||e.brightness).get();k[""]=a.convertAttribs(s({color:h.color,fillColor:h.color,lineColor:p===
  241 +null?h.color:v},c),j[""]);k.hover=a.convertAttribs(d.hover,j.hover,k[""]);k.select=a.convertAttribs(d.select,j.select,k[""])}else k=j;h.pointAttr=k}},update:function(a,b){var c=this.chart,d=this.type,e=X[d].prototype,f,a=x(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(f in e)e.hasOwnProperty(f)&&(this[f]=v);s(this,X[a.type||d].prototype);this.init(c,a);o(b,!0)&&c.redraw(!1)},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(na),
  242 +d,e,f=a.data||[],g,h,i;A(a,"destroy");$(a);n(["xAxis","yAxis"],function(b){if(i=a[b])ga(i.series,a),i.isDirty=i.forceRedraw=!0,i.stacks={}});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);n("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","),function(b){a[b]&&(d=c&&b==="group"?"hide":"destroy",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;ga(b.series,
  243 +a);for(h in a)delete a[h]},drawDataLabels:function(){var a=this,b=a.options,c=b.cursor,d=b.dataLabels,b=a.points,e,f,g,h;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(d),h=a.plotGroup("dataLabelsGroup","data-labels",a.visible?"visible":"hidden",d.zIndex||6),f=d,n(b,function(b){var j,k=b.dataLabel,l,m,n=b.connector,q=!0;e=b.options&&b.options.dataLabels;j=o(e&&e.enabled,f.enabled);if(k&&!j)b.dataLabel=k.destroy();else if(j){d=x(f,e);j=d.rotation;l=b.getLabelConfig();g=d.format?
  244 +Ca(d.format,l):d.formatter.call(l,d);d.style.color=o(d.color,d.style.color,a.color,"black");if(k)if(u(g))k.attr({text:g}),q=!1;else{if(b.dataLabel=k=k.destroy(),n)b.connector=n.destroy()}else if(u(g)){k={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:j,padding:d.padding,zIndex:1};for(m in k)k[m]===v&&delete k[m];k=b.dataLabel=a.chart.renderer[j?"text":"label"](g,0,-999,null,null,null,d.useHTML).attr(k).css(s(d.style,c&&{cursor:c})).add(h).shadow(d.shadow)}k&&
  245 +a.alignDataLabel(b,k,d,null,q)}})},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=o(a.plotX,-999),i=o(a.plotY,-999),j=b.getBBox();if(a=this.visible&&f.isInsidePlot(a.plotX,a.plotY,g))d=s({x:g?f.plotWidth-i:h,y:t(g?f.plotHeight-h:i),width:0,height:0},d),s(c,{width:j.width,height:j.height}),c.rotation?(g={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](g)):(b.align(c,null,d),g=b.alignAttr,o(c.overflow,"justify")==="justify"?this.justifyDataLabel(b,c,
  246 +g,j,d,e):o(c.crop,!0)&&(a=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)));a||b.attr({y:-999})},justifyDataLabel:function(a,b,c,d,e,f){var g=this.chart,h=b.align,i=b.verticalAlign,j,k;j=c.x;if(j<0)h==="right"?b.align="left":b.x=-j,k=!0;j=c.x+d.width;if(j>g.plotWidth)h==="left"?b.align="right":b.x=g.plotWidth-j,k=!0;j=c.y;if(j<0)i==="bottom"?b.verticalAlign="top":b.y=-j,k=!0;j=c.y+d.height;if(j>g.plotHeight)i==="top"?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0;if(k)a.placed=
  247 +!f,a.align(b,null,e)},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;n(a,function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];n(a.segments,function(e){c=a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=
  248 +d;return a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color]],d=b.lineWidth,e=b.dashStyle,f=b.linecap!=="square",g=this.getGraphPath(),h=b.negativeColor;h&&c.push(["graphNeg",h]);n(c,function(c,h){var k=c[0],l=a[k];if(l)Wa(l),l.animate({d:g});else if(d&&g.length)l={stroke:c[1],"stroke-width":d,zIndex:1},e?l.dashstyle=e:f&&(l["stroke-linecap"]=l["stroke-linejoin"]="round"),a[k]=a.chart.renderer.path(g).attr(l).add(a.group).shadow(!h&&b.shadow)})},clipNeg:function(){var a=
  249 +this.options,b=this.chart,c=b.renderer,d=a.negativeColor||a.negativeFillColor,e,f=this.graph,g=this.area,h=this.posClip,i=this.negClip;e=b.chartWidth;var j=b.chartHeight,k=r(e,j),l=this.yAxis;if(d&&(f||g)){d=t(l.toPixels(a.threshold||0,!0));a={x:0,y:0,width:k,height:d};k={x:0,y:d,width:k,height:k};if(b.inverted)a.height=k.y=b.plotWidth-d,c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:j},k={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e});l.reversed?(b=k,e=a):(b=a,e=k);h?(h.animate(b),
  250 +i.animate(e)):(this.posClip=h=c.clipRect(b),this.negClip=i=c.clipRect(e),f&&this.graphNeg&&(f.clip(h),this.graphNeg.clip(i)),g&&(g.clip(h),this.areaNeg.clip(i)))}},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};n(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)K(c,"resize",a),K(b,"destroy",function(){$(c,"resize",a)}),a(),b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,
  251 +zIndex:d||0.1}).add(e));f[g?"attr":"animate"](this.getPlotBox());return f},getPlotBox:function(){return{translateX:this.xAxis?this.xAxis.left:this.chart.plotLeft,translateY:this.yAxis?this.yAxis.top:this.chart.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this.chart,b,c=this.options,d=c.animation&&!!this.animate&&a.renderer.isSVG,e=this.visible?"visible":"hidden",f=c.zIndex,g=this.hasRendered,h=a.seriesGroup;b=this.plotGroup("group","series",e,f,h);this.markerGroup=this.plotGroup("markerGroup",
  252 +"markers",e,f,h);d&&this.animate(!0);this.getAttribs();b.inverted=this.isCartesian?a.inverted:!1;this.drawGraph&&(this.drawGraph(),this.clipNeg());this.drawDataLabels();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();a.inverted&&this.invertGroups();c.clip!==!1&&!this.sharedClipKey&&!g&&b.clip(a.clipRect);d?this.animate():g||this.afterAnimate();this.isDirty=this.isDirtyData=!1;this.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,
  253 +e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:o(d&&d.left,a.plotLeft),translateY:o(e&&e.top,a.plotTop)}));this.translate();this.setTooltipPoints(!0);this.render();b&&A(this,"updatedData")},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth,a=a||"";if(this.state!==a)this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&&(a={"stroke-width":b},c.attr(a),d&&d.attr(a)))},setVisible:function(a,
  254 +b){var c=this,d=c.chart,e=c.legendItem,f,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===v?!h:a)?"show":"hide";n(["group","dataLabelsGroup","markerGroup","tracker"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c)c.onMouseOut();e&&d.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&&n(d.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});n(c.linkedSeries,function(b){b.setVisible(a,!1)});if(g)d.isDirtyBox=!0;b!==!1&&d.redraw();A(c,
  255 +f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===v?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;A(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,l=k&&{cursor:k},k=a.singlePoints,m,p=function(){if(f.hoverSeries!==a)a.onMouseOver()};if(e&&!c)for(m=
  256 +e+1;m--;)d[m]==="M"&&d.splice(m+1,0,d[m+1]-i,d[m+2],"L"),(m&&d[m]==="M"||m===e)&&d.splice(m,0,"L",d[m-2]+i,d[m-1]);for(m=0;m<k.length;m++)e=k[m],d.push("M",e.plotX-i,e.plotY,"L",e.plotX+i,e.plotY);j?j.attr({d:d}):(a.tracker=h.path(d).attr({"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:Qb,fill:c?Qb:S,"stroke-width":b.lineWidth+(c?0:2*i),zIndex:2}).add(a.group),n([a.tracker,a.markerGroup],function(a){a.addClass("highcharts-tracker").on("mouseover",p).on("mouseout",function(a){g.onTrackerMouseOut(a)}).css(l);
  257 +if(jb)a.on("touchstart",p)}))}};G=ha(Q);X.line=G;Z.area=x(Y,{threshold:0});G=ha(Q,{type:"area",getSegments:function(){var a=[],b=[],c=[],d=this.xAxis,e=this.yAxis,f=e.stacks[this.stackKey],g={},h,i,j=this.points,k=this.options.connectNulls,l,m,p;if(this.options.stacking&&!this.cropped){for(m=0;m<j.length;m++)g[j[m].x]=j[m];for(p in f)f[p].total!==null&&c.push(+p);c.sort(function(a,b){return a-b});n(c,function(a){if(!k||g[a]&&g[a].y!==null)g[a]?b.push(g[a]):(h=d.translate(a),l=f[a].percent?f[a].total?
  258 +f[a].cum*100/f[a].total:0:f[a].cum,i=e.toPixels(l,!0),b.push({y:null,plotX:h,clientX:h,plotY:i,yBottom:i,onMouseOver:oa}))});b.length&&a.push(b)}else Q.prototype.getSegments.call(this),a=this.segments;this.segments=a},getSegmentPath:function(a){var b=Q.prototype.getSegmentPath.call(this,a),c=[].concat(b),d,e=this.options;d=b.length;var f=this.yAxis.getThreshold(e.threshold),g;d===3&&c.push("L",b[1],b[2]);if(e.stacking&&!this.closedStacks)for(d=a.length-1;d>=0;d--)g=o(a[d].yBottom,f),d<a.length-1&&
  259 +e.step&&c.push(a[d+1].plotX,g),c.push(a[d].plotX,g);else this.closeSegment(c,a,f);this.areaPath=this.areaPath.concat(c);return b},closeSegment:function(a,b,c){a.push("L",b[b.length-1].plotX,c,"L",b[0].plotX,c)},drawGraph:function(){this.areaPath=[];Q.prototype.drawGraph.apply(this);var a=this,b=this.areaPath,c=this.options,d=c.negativeColor,e=c.negativeFillColor,f=[["area",this.color,c.fillColor]];(d||e)&&f.push(["areaNeg",d,e]);n(f,function(d){var e=d[0],f=a[e];f?f.animate({d:b}):a[e]=a.chart.renderer.path(b).attr({fill:o(d[2],
  260 +qa(d[1]).setOpacity(o(c.fillOpacity,0.75)).get()),zIndex:0}).add(a.group)})},drawLegendSymbol:function(a,b){b.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,a.options.symbolWidth,12,2).attr({zIndex:3}).add(b.legendGroup)}});X.area=G;Z.spline=x(Y);F=ha(Q,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,i,j,k;if(f&&g){a=f.plotY;j=g.plotX;var g=g.plotY,l;h=(1.5*d+f.plotX)/2.5;i=(1.5*e+a)/2.5;j=(1.5*d+j)/2.5;k=(1.5*e+g)/2.5;l=(k-i)*(j-d)/(j-h)+e-k;i+=l;
  261 +k+=l;i>a&&i>e?(i=r(a,e),k=2*e-i):i<a&&i<e&&(i=J(a,e),k=2*e-i);k>g&&k>e?(k=r(g,e),i=2*e-k):k<g&&k<e&&(k=J(g,e),i=2*e-k);b.rightContX=j;b.rightContY=k}c?(b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=["M",d,e];return b}});X.spline=F;Z.areaspline=x(Z.area);la=G.prototype;F=ha(F,{type:"areaspline",closedStacks:!0,getSegmentPath:la.getSegmentPath,closeSegment:la.closeSegment,drawGraph:la.drawGraph,drawLegendSymbol:la.drawLegendSymbol});X.areaspline=
  262 +F;Z.column=x(Y,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:0.1,shadow:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},stickyTracking:!1,threshold:0});F=ha(Q,{type:"column",pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},cropShoulder:0,trackerGroups:["group",
  263 +"dataLabelsGroup"],negStacks:!0,init:function(){Q.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&n(b.series,function(b){if(b.type===a.type)b.isDirty=!0})},getColumnMetrics:function(){var a=this,b=a.options,c=a.xAxis,d=a.yAxis,e=c.reversed,f,g={},h,i=0;b.grouping===!1?i=1:n(a.chart.series,function(b){var c=b.options,e=b.yAxis;if(b.type===a.type&&b.visible&&d.len===e.len&&d.pos===e.pos)c.stacking?(f=b.stackKey,g[f]===v&&(g[f]=i++),h=g[f]):c.grouping!==!1&&(h=i++),b.columnIndex=
  264 +h});var c=J(M(c.transA)*(c.ordinalSlope||b.pointRange||c.closestPointRange||1),c.len),j=c*b.groupPadding,k=(c-2*j)/i,l=b.pointWidth,b=u(l)?(k-l)/2:k*b.pointPadding,l=o(l,k-2*b);return a.columnMetrics={width:l,offset:b+(j+((e?i-(a.columnIndex||0):a.columnIndex)||0)*k-c/2)*(e?-1:1)}},translate:function(){var a=this.chart,b=this.options,c=b.borderWidth,d=this.yAxis,e=this.translatedThreshold=d.getThreshold(b.threshold),f=o(b.minPointLength,5),b=this.getColumnMetrics(),g=b.width,h=this.barW=wa(r(g,1+
  265 +2*c)),i=this.pointXOffset=b.offset,j=-(c%2?0.5:0),k=c%2?0.5:1;a.renderer.isVML&&a.inverted&&(k+=1);Q.prototype.translate.apply(this);n(this.points,function(a){var b=o(a.yBottom,e),c=J(r(-999-b,a.plotY),d.len+999+b),n=a.plotX+i,u=h,s=J(c,b),v,c=r(c,b)-s;M(c)<f&&f&&(c=f,s=t(M(s-e)>f?b-f:e-(d.translate(a.y,0,1,0,1)<=e?f:0)));a.barX=n;a.pointWidth=g;b=M(n)<0.5;u=t(n+u)+j;n=t(n)+j;u-=n;v=M(s)<0.5;c=t(s+c)+k;s=t(s)+k;c-=s;b&&(n+=1,u-=1);v&&(s-=1,c+=1);a.shapeType="rect";a.shapeArgs={x:n,y:s,width:u,height:c}})},
  266 +getSymbol:oa,drawLegendSymbol:G.prototype.drawLegendSymbol,drawGraph:oa,drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d;n(a.points,function(e){var f=e.plotY,g=e.graphic;if(f!==v&&!isNaN(f)&&e.y!==null)d=e.shapeArgs,g?(Wa(g),g.animate(x(d))):e.graphic=c[e.shapeType](d).attr(e.pointAttr[e.selected?"select":""]).add(a.group).shadow(b.shadow,null,b.stacking&&!b.borderRadius);else if(g)e.graphic=g.destroy()})},drawTracker:function(){var a=this,b=a.chart,c=b.pointer,d=a.options.cursor,
  267 +e=d&&{cursor:d},f=function(c){var d=c.target,e;if(b.hoverSeries!==a)a.onMouseOver();for(;d&&!e;)e=d.point,d=d.parentNode;if(e!==v&&e!==b.hoverPoint)e.onMouseOver(c)};n(a.points,function(a){if(a.graphic)a.graphic.element.point=a;if(a.dataLabel)a.dataLabel.element.point=a});if(!a._hasTracking)n(a.trackerGroups,function(b){if(a[b]&&(a[b].addClass("highcharts-tracker").on("mouseover",f).on("mouseout",function(a){c.onTrackerMouseOut(a)}).css(e),jb))a[b].on("touchstart",f)}),a._hasTracking=!0},alignDataLabel:function(a,
  268 +b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>o(this.translatedThreshold,f.plotSizeY),j=o(c.inside,!!this.options.stacking);if(h&&(d=x(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j))g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=o(c.align,!g||j?"center":i?"right":"left");c.verticalAlign=o(c.verticalAlign,g||j?"middle":i?"top":"bottom");Q.prototype.alignDataLabel.call(this,a,b,c,d,e)},animate:function(a){var b=
  269 +this.yAxis,c=this.options,d=this.chart.inverted,e={};if(W)a?(e.scaleY=0.001,a=J(b.pos+b.len,r(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?"translateX":"translateY"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null)},remove:function(){var a=this,b=a.chart;b.hasRendered&&n(b.series,function(b){if(b.type===a.type)b.isDirty=!0});Q.prototype.remove.apply(a,arguments)}});X.column=F;Z.bar=x(Z.column);la=ha(F,{type:"bar",inverted:!0});
  270 +X.bar=la;Z.scatter=x(Y,{lineWidth:0,tooltip:{headerFormat:'<span style="font-size: 10px; color:{series.color}">{series.name}</span><br/>',pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>",followPointer:!0},stickyTracking:!1});la=ha(Q,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["markerGroup"],takeOrdinalPosition:!1,drawTracker:F.prototype.drawTracker,setTooltipPoints:oa});X.scatter=la;Z.pie=x(Y,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,
  271 +colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});Y={type:"pie",isCartesian:!1,pointClass:ha(Pa,{init:function(){Pa.prototype.init.apply(this,arguments);var a=this,b;if(a.y<0)a.y=null;s(a,{visible:a.visible!==!1,name:o(a.name,"Slice")});b=function(b){a.slice(b.type==="select")};
  272 +K(a,"select",b);K(a,"unselect",b);return a},setVisible:function(a){var b=this,c=b.series,d=c.chart,e;b.visible=b.options.visible=a=a===v?!b.visible:a;c.options.data[pa(b,c.data)]=b.options;e=a?"show":"hide";n(["graphic","dataLabel","connector","shadowGroup"],function(a){if(b[a])b[a][e]()});b.legendItem&&d.legend.colorizeItem(b,a);if(!c.isDirty&&c.options.ignoreHiddenPoint)c.isDirty=!0,d.redraw()},slice:function(a,b,c){var d=this.series;La(c,d.chart);o(b,!0);this.sliced=this.options.sliced=a=u(a)?
  273 +a:!this.sliced;d.options.data[pa(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:oa,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)n(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/
  274 +2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null},setData:function(a,b){Q.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();o(b,!0)&&this.chart.redraw()},generatePoints:function(){var a,b=0,c,d,e,f=this.options.ignoreHiddenPoint;Q.prototype.generatePoints.call(this);c=this.points;d=c.length;for(a=0;a<d;a++)e=c[a],b+=f&&!e.visible?0:e.y;this.total=b;for(a=0;a<d;a++)e=c[a],e.percentage=b>0?e.y/b*100:0,e.total=b},getCenter:function(){var a=
  275 +this.options,b=this.chart,c=2*(a.slicedOffset||0),d,e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[o(b[0],"50%"),o(b[1],"50%"),a.size||"100%",a.innerSize||0],g=J(e,f),h;return Na(a,function(a,b){h=/%$/.test(a);d=b<2||b===2&&h;return(h?[e,f,g,g][b]*y(a)/100:a)+(d?c:0)})},translate:function(a){this.generatePoints();var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,h,i=c.startAngle||0,j=this.startAngleRad=xa/180*(i-90),i=(this.endAngleRad=xa/180*((c.endAngle||i+360)-90))-j,k=this.points,
  276 +l=c.dataLabels.distance,c=c.ignoreHiddenPoint,m,n=k.length,o;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=R.asin((b-a[1])/(a[2]/2+l));return a[0]+(c?-1:1)*V(h)*(a[2]/2+l)};for(m=0;m<n;m++){o=k[m];f=j+b*i;if(!c||o.visible)b+=o.percentage/100;g=j+b*i;o.shapeType="arc";o.shapeArgs={x:a[0],y:a[1],r:a[2]/2,innerR:a[3]/2,start:t(f*1E3)/1E3,end:t(g*1E3)/1E3};h=(g+f)/2;h>0.75*i&&(h-=2*xa);o.slicedTranslation={translateX:t(V(h)*d),translateY:t(ba(h)*d)};f=V(h)*a[2]/2;g=ba(h)*a[2]/2;o.tooltipPos=
  277 +[a[0]+f*0.7,a[1]+g*0.7];o.half=h<-xa/2||h>xa/2?1:0;o.angle=h;e=J(e,l/2);o.labelPos=[a[0]+f+V(h)*l,a[1]+g+ba(h)*l,a[0]+f+V(h)*e,a[1]+g+ba(h)*e,a[0]+f,a[1]+g,l<0?"center":o.half?"right":"left",h]}},setTooltipPoints:oa,drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,g;if(e&&!a.shadowGroup)a.shadowGroup=b.g("shadow").add(a.group);n(a.points,function(h){d=h.graphic;g=h.shapeArgs;f=h.shadowGroup;if(e&&!f)f=h.shadowGroup=b.g("shadow").add(a.shadowGroup);c=h.sliced?
  278 +h.slicedTranslation:{translateX:0,translateY:0};f&&f.attr(c);d?d.animate(s(g,c)):h.graphic=d=b.arc(g).setRadialReference(a.center).attr(h.pointAttr[h.selected?"select":""]).attr({"stroke-linejoin":"round"}).attr(c).add(a.group).shadow(e,f);h.visible===!1&&h.setVisible(!1)})},sortByAngle:function(a,b){a.sort(function(a,d){return a.angle!==void 0&&(d.angle-a.angle)*b})},drawDataLabels:function(){var a=this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=o(e.connectorPadding,10),g=o(e.connectorWidth,1),
  279 +h=d.plotWidth,d=d.plotHeight,i,j,k=o(e.softConnector,!0),l=e.distance,m=a.center,p=m[2]/2,q=m[1],u=l>0,s,v,w,x,y=[[],[]],z,A,E,H,C,D=[0,0,0,0],J=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){Q.prototype.drawDataLabels.apply(a);n(b,function(a){a.dataLabel&&y[a.half].push(a)});for(H=0;!x&&b[H];)x=b[H]&&b[H].dataLabel&&(b[H].dataLabel.getBBox().height||21),H++;for(H=2;H--;){var b=[],I=[],G=y[H],K=G.length,F;a.sortByAngle(G,H-0.5);if(l>0){for(C=q-p-l;C<=q+p+l;C+=x)b.push(C);
  280 +v=b.length;if(K>v){c=[].concat(G);c.sort(J);for(C=K;C--;)c[C].rank=C;for(C=K;C--;)G[C].rank>=v&&G.splice(C,1);K=G.length}for(C=0;C<K;C++){c=G[C];w=c.labelPos;c=9999;var N,L;for(L=0;L<v;L++)N=M(b[L]-w[1]),N<c&&(c=N,F=L);if(F<C&&b[C]!==null)F=C;else for(v<K-C+F&&b[C]!==null&&(F=v-K+C);b[F]===null;)F++;I.push({i:F,y:b[F]});b[F]=null}I.sort(J)}for(C=0;C<K;C++){c=G[C];w=c.labelPos;s=c.dataLabel;E=c.visible===!1?"hidden":"visible";c=w[1];if(l>0){if(v=I.pop(),F=v.i,A=v.y,c>A&&b[F+1]!==null||c<A&&b[F-1]!==
  281 +null)A=c}else A=c;z=e.justify?m[0]+(H?-1:1)*(p+l):a.getX(F===0||F===b.length-1?c:A,H);s._attr={visibility:E,align:w[6]};s._pos={x:z+e.x+({left:f,right:-f}[w[6]]||0),y:A+e.y-10};s.connX=z;s.connY=A;if(this.options.size===null)v=s.width,z-v<f?D[3]=r(t(v-z+f),D[3]):z+v>h-f&&(D[1]=r(t(z+v-h+f),D[1])),A-x/2<0?D[0]=r(t(-A+x/2),D[0]):A+x/2>d&&(D[2]=r(t(A+x/2-d),D[2]))}}if(ua(D)===0||this.verifyDataLabelOverflow(D))this.placeDataLabels(),u&&g&&n(this.points,function(b){i=b.connector;w=b.labelPos;if((s=b.dataLabel)&&
  282 +s._pos)E=s._attr.visibility,z=s.connX,A=s.connY,j=k?["M",z+(w[6]==="left"?5:-5),A,"C",z,A,2*w[2]-w[4],2*w[3]-w[5],w[2],w[3],"L",w[4],w[5]]:["M",z+(w[6]==="left"?5:-5),A,"L",w[2],w[3],"L",w[4],w[5]],i?(i.animate({d:j}),i.attr("visibility",E)):b.connector=i=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:E}).add(a.group);else if(i)b.connector=i.destroy()})}},verifyDataLabelOverflow:function(a){var b=this.center,c=this.options,d=c.center,e=c=c.minSize||
  283 +80,f;d[0]!==null?e=r(b[2]-r(a[1],a[3]),c):(e=r(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2);d[1]!==null?e=r(J(e,b[2]-r(a[0],a[2])),c):(e=r(J(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2);e<b[2]?(b[2]=e,this.translate(b),n(this.points,function(a){if(a.dataLabel)a.dataLabel._pos=null}),this.drawDataLabels()):f=!0;return f},placeDataLabels:function(){n(this.points,function(a){var a=a.dataLabel,b;if(a)(b=a._pos)?(a.attr(a._attr),a[a.moved?"animate":"attr"](b),a.moved=!0):a&&a.attr({y:-999})})},alignDataLabel:oa,
  284 +drawTracker:F.prototype.drawTracker,drawLegendSymbol:G.prototype.drawLegendSymbol,getSymbol:oa};Y=ha(Q,Y);X.pie=Y;s(Highcharts,{Axis:eb,Chart:yb,Color:qa,Legend:fb,Pointer:xb,Point:Pa,Tick:Ma,Tooltip:wb,Renderer:Va,Series:Q,SVGElement:va,SVGRenderer:za,arrayMin:Ja,arrayMax:ua,charts:Ga,dateFormat:Ya,format:Ca,pathAnim:Ab,getOptions:function(){return L},hasBidiBug:Ub,isTouchDevice:Ob,numberFormat:Aa,seriesTypes:X,setOptions:function(a){L=x(L,a);Lb();return L},addEvent:K,removeEvent:$,createElement:U,
  285 +discardElement:Ta,css:I,each:n,extend:s,map:Na,merge:x,pick:o,splat:ja,extendClass:ha,pInt:y,wrap:mb,svg:W,canvas:ca,vml:!W&&!ca,product:"Highcharts",version:"3.0.7"})})();
src/super_archives/management/commands/import_emails.py
@@ -11,7 +11,10 @@ from optparse import make_option @@ -11,7 +11,10 @@ from optparse import make_option
11 11
12 from django.db import transaction 12 from django.db import transaction
13 from django.template.defaultfilters import slugify 13 from django.template.defaultfilters import slugify
  14 +from super_archives.utils.email import colab_send_email
14 from django.core.management.base import BaseCommand, CommandError 15 from django.core.management.base import BaseCommand, CommandError
  16 +from django.template.loader import render_to_string
  17 +from django.utils.translation import ugettext as _
15 18
16 from super_archives.models import MailingList, Message, \ 19 from super_archives.models import MailingList, Message, \
17 Thread, EmailAddress 20 Thread, EmailAddress
@@ -196,6 +199,21 @@ class Command(BaseCommand, object): @@ -196,6 +199,21 @@ class Command(BaseCommand, object):
196 email_addr.save() 199 email_addr.save()
197 200
198 subject = email_msg.get_subject() 201 subject = email_msg.get_subject()
  202 + if not subject:
  203 + colab_send_email(
  204 + subject=_(
  205 + u"[Colab] Warning - Email sent with a blank subject."
  206 + ),
  207 + message=render_to_string(
  208 + u'superarchives/emails/email_blank_subject.txt',
  209 + {
  210 + 'email_body': email_msg.get_body(),
  211 + 'mailinglist': mailinglist.name,
  212 + 'user': email_addr.get_full_name()
  213 + }
  214 + ),
  215 + to=email_addr.address
  216 + )
199 217
200 email = Message.all_objects.create( 218 email = Message.all_objects.create(
201 message_id=email_msg.get('Message-ID'), 219 message_id=email_msg.get('Message-ID'),
src/super_archives/models.py
@@ -326,18 +326,27 @@ class Message(models.Model): @@ -326,18 +326,27 @@ class Message(models.Model):
326 326
327 @property 327 @property
328 def author(self): 328 def author(self):
329 - from_address = self.from_address  
330 - if from_address.user:  
331 - return from_address.user.username 329 + return self.fullname
  330 +
  331 + @property
  332 + def author_url(self):
  333 + if self.from_address.user_id:
  334 + return self.from_address.user.get_absolute_url()
332 return None 335 return None
333 336
  337 + # An alias for author
334 @property 338 @property
335 - def fullname(self):  
336 - return self.from_address.get_full_name() 339 + def modified_by(self):
  340 + return self.author
337 341
  342 + # An alias for author_url
338 @property 343 @property
339 - def author_url(self):  
340 - return self.from_address.user.get_absolute_url() 344 + def modified_by_url(self):
  345 + return self.author_url
  346 +
  347 + @property
  348 + def fullname(self):
  349 + return self.from_address.get_full_name()
341 350
342 @property 351 @property
343 def icon_name(self): 352 def icon_name(self):
src/super_archives/search_indexes.py
@@ -50,17 +50,34 @@ class ThreadIndex(BaseIndex, indexes.Indexable): @@ -50,17 +50,34 @@ class ThreadIndex(BaseIndex, indexes.Indexable):
50 ) 50 )
51 51
52 def prepare_author(self, obj): 52 def prepare_author(self, obj):
53 - return obj.latest_message.author 53 + first_message = obj.message_set.first()
  54 + return first_message.from_address.get_full_name()
54 55
55 def prepare_author_url(self, obj): 56 def prepare_author_url(self, obj):
56 first_message = obj.message_set.first() 57 first_message = obj.message_set.first()
57 - if first_message.from_address.user:  
58 - return first_message.from_address.user.get_absolute_url() 58 + return first_message.author_url
  59 +
  60 + def prepare_modified_by(self, obj):
  61 + modified_by = obj.latest_message.modified_by
  62 + if modified_by:
  63 + return modified_by
  64 + return obj.message_set.first().author
  65 +
  66 + def prepare_modified_by_url(self, obj):
  67 + modified_by_url = obj.latest_message.modified_by_url
  68 + if modified_by_url:
  69 + return modified_by_url
59 return None 70 return None
60 71
61 def prepare_created(self, obj): 72 def prepare_created(self, obj):
62 return obj.message_set.first().received_time 73 return obj.message_set.first().received_time
63 74
  75 + def prepare_fullname(self, obj):
  76 + fullname = obj.latest_message.from_address.get_full_name()
  77 + if not fullname:
  78 + fullname = obj.message_set.first().from_address.get_full_name()
  79 + return fullname
  80 +
64 def prepare_icon_name(self, obj): 81 def prepare_icon_name(self, obj):
65 return u'envelope' 82 return u'envelope'
66 83
src/super_archives/templates/message-preview.html
@@ -28,33 +28,41 @@ @@ -28,33 +28,41 @@
28 {% highlight result.description with query max_length "150" %} 28 {% highlight result.description with query max_length "150" %}
29 {% else %} 29 {% else %}
30 {% if result.latest_description %} 30 {% if result.latest_description %}
31 - {{ result.latest_description|escape|truncatechars:150 }} 31 + {{ result.latest_description|striptags|escape|truncatechars:150 }}
32 {% elif result.description %} 32 {% elif result.description %}
33 - {{ result.description|escape|truncatechars:150 }} 33 + {{ result.description|striptags|escape|truncatechars:150 }}
34 {% endif %} 34 {% endif %}
35 {% endif %} 35 {% endif %}
36 </span> 36 </span>
37 {% endif %} 37 {% endif %}
38 38
39 -{% if result.fullname or result.modified %} 39 +{% if result.fullname or result.modified or result.modified_by %}
40 <div class="quiet"> 40 <div class="quiet">
41 - {% if result.fullname %} 41 + {% if result.modified_by %}
42 <span class="pull-left">{% trans "by" %} 42 <span class="pull-left">{% trans "by" %}
43 - {% if result.fullname and result.author_url %}  
44 - <a href="{{ result.author_url }}">  
45 - {% if query %}  
46 - {% highlight result.fullname with query %}  
47 - {% else %}  
48 - {{ result.fullname }}  
49 - {% endif %} 43 + {% if result.modified_by_url %}
  44 + <a href="{{ result.modified_by_url }}">
  45 + {% else %}
  46 + <span>
  47 + {% endif %}
  48 +
  49 + {% if query %}
  50 + {% highlight result.modified_by with query %}
  51 + {% else %}
  52 + {{ result.modified_by }}
  53 + {% endif %}
  54 +
  55 + {% if result.modified_by_url %}
50 </a> 56 </a>
51 {% else %} 57 {% else %}
52 - <span>{{ result.fullname }}</span> 58 + </span>
53 {% endif %} 59 {% endif %}
54 </span> 60 </span>
  61 + {% else %}
  62 + <span class="pull-left">{% trans "by" %} {% trans "Anonymous" %}</span>
55 {% endif %} 63 {% endif %}
56 {% if result.modified %} 64 {% if result.modified %}
57 - <span class="pull-right">{{ result.modified|localtime|timesince }} {% trans "ago" %}</span> 65 + <span class="pull-right">{{ result.modified|localtime|timesince }} {% trans "ago" %}</span>
58 {% endif %} 66 {% endif %}
59 </div> 67 </div>
60 {% endif %} 68 {% endif %}
src/super_archives/templates/message-thread.html
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 3
4 {% trans "Anonymous" as anonymous %} 4 {% trans "Anonymous" as anonymous %}
5 5
  6 +{% block title %}{{ first_msg.subject_clean }}{% endblock %}
  7 +
6 {% block head_js %} 8 {% block head_js %}
7 9
8 <script> 10 <script>
@@ -98,6 +100,8 @@ @@ -98,6 +100,8 @@
98 {% if user.is_active %} 100 {% if user.is_active %}
99 $('.reply.btn', this).on('click', focus_reply); 101 $('.reply.btn', this).on('click', focus_reply);
100 {% endif %} 102 {% endif %}
  103 +
  104 + $('.message-link').popover({'placement': 'right'});
101 }); 105 });
102 106
103 </script> 107 </script>
src/super_archives/templates/superarchives/emails/email_blank_subject.txt 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +{% load i18n %}
  2 +{% trans 'Hello' %} {{ user }},
  3 +{% blocktrans with body=email_body mailinglist=mailinglist %}
  4 +You've sent an email to {{ mailinglist }} with a blank subject and the following content:
  5 +
  6 +"{{ body }}"
  7 +
  8 +Please, fill the subject in every email you send it.
  9 +
  10 +Thank you.
  11 +{% endblocktrans %}
src/super_archives/templates/superarchives/includes/message.html
@@ -13,6 +13,13 @@ @@ -13,6 +13,13 @@
13 {% if userprofile.get_absolute_url %} 13 {% if userprofile.get_absolute_url %}
14 </a> 14 </a>
15 {% endif %} 15 {% endif %}
  16 + {% if email.id %}
  17 + <div class="hidden-xs hidden-sm div-message-link" title="{% trans 'Link to this message' %}">
  18 + <button class="btn btn-default message-link" data-toggle="popover" data-content="<input type='text' value='{{ request.get_host }}{{ request.path }}#msg-{{ email.id }}' class='form-control' />" data-title="{% trans 'Link to this message' %}" data-html="true" data-container="body">
  19 + <span class="glyphicon glyphicon-link"></span>
  20 + </button>
  21 + </div>
  22 + {% endif %}
16 </div> 23 </div>
17 24
18 {% if not reply %} 25 {% if not reply %}
src/super_archives/templates/superarchives/thread-dashboard.html
@@ -2,12 +2,12 @@ @@ -2,12 +2,12 @@
2 {% load i18n %} 2 {% load i18n %}
3 3
4 {% block main-content %} 4 {% block main-content %}
5 - <h2>{% trans 'Discussions'|title %}</h2> 5 + <h2>{% trans 'Groups'|title %}</h2>
6 <hr/> 6 <hr/>
7 7
8 - {% for listname, latest, most_relevant in lists %} 8 + {% for listname, description, latest, most_relevant in lists %}
9 {% if latest or most_relevant %} 9 {% if latest or most_relevant %}
10 - <h3 class="text-center"><b>{{ listname|title }}</b></h3> 10 + <h3 class="text-center"><b>{{ listname|title }} {% if description %} ({{ description }}){% endif %}</b></h3>
11 <hr/> 11 <hr/>
12 12
13 <div class="row"> 13 <div class="row">
src/super_archives/views.py
@@ -20,6 +20,7 @@ from django.shortcuts import render, redirect, get_object_or_404 @@ -20,6 +20,7 @@ from django.shortcuts import render, redirect, get_object_or_404
20 20
21 from haystack.query import SearchQuerySet 21 from haystack.query import SearchQuerySet
22 22
  23 +from accounts.utils import mailman
23 from .utils.email import send_verification_email 24 from .utils.email import send_verification_email
24 from .models import MailingList, Thread, EmailAddress, \ 25 from .models import MailingList, Thread, EmailAddress, \
25 EmailAddressValidation, Message 26 EmailAddressValidation, Message
@@ -74,6 +75,7 @@ class ThreadView(View): @@ -74,6 +75,7 @@ class ThreadView(View):
74 raise http.Http404 75 raise http.Http404
75 76
76 data = { 77 data = {
  78 + 'in_reply_to': thread.message_set.last().message_id,
77 'email_from': request.user.email, 79 'email_from': request.user.email,
78 'name_from': request.user.get_full_name(), 80 'name_from': request.user.get_full_name(),
79 'subject': thread.message_set.first().subject_clean, 81 'subject': thread.message_set.first().subject_clean,
@@ -93,10 +95,12 @@ class ThreadView(View): @@ -93,10 +95,12 @@ class ThreadView(View):
93 error_msg = _('Timeout trying to connect to Mailman API') 95 error_msg = _('Timeout trying to connect to Mailman API')
94 96
95 if resp and resp.status_code == 200: 97 if resp and resp.status_code == 200:
96 - messages.success(request, _("Your message was sent. It may take "  
97 - "some minutes before it's delivered. "  
98 - "Why don't you breath some fresh air "  
99 - "in the meanwhile?")) 98 + messages.success(request, _(
  99 + "Your message was sent to this topic. "
  100 + "It may take some minutes before it's delivered by email "
  101 + "to the group. Why don't you breath some fresh air in the "
  102 + "meanwhile?"
  103 + ))
100 else: 104 else:
101 if not error_msg: 105 if not error_msg:
102 if resp is not None: 106 if resp is not None:
@@ -117,13 +121,17 @@ class ThreadDashboardView(View): @@ -117,13 +121,17 @@ class ThreadDashboardView(View):
117 def get(self, request): 121 def get(self, request):
118 MAX = 6 122 MAX = 6
119 context = {} 123 context = {}
  124 + all_lists = mailman.all_lists(description=True)
120 125
121 context['lists'] = [] 126 context['lists'] = []
122 lists = MailingList.objects.filter() 127 lists = MailingList.objects.filter()
123 for list_ in MailingList.objects.order_by('name'): 128 for list_ in MailingList.objects.order_by('name'):
124 context['lists'].append(( 129 context['lists'].append((
125 list_.name, 130 list_.name,
126 - list_.thread_set.filter(spam=False)[:MAX], 131 + mailman.get_list_description(list_.name, all_lists),
  132 + list_.thread_set.filter(spam=False).order_by(
  133 + '-latest_message__received_time'
  134 + )[:MAX],
127 SearchQuerySet().filter(type='thread', tag=list_.name)[:MAX], 135 SearchQuerySet().filter(type='thread', tag=list_.name)[:MAX],
128 )) 136 ))
129 137
src/templates/base.html
@@ -5,6 +5,12 @@ @@ -5,6 +5,12 @@
5 {% block head %} 5 {% block head %}
6 <meta charset="UTF-8" /> 6 <meta charset="UTF-8" />
7 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  8 + {% block metarobots %}
  9 + {% if ROBOTS_NOINDEX %}
  10 + <meta name="robots" content="noindex, nofollow" />
  11 + {% endif %}
  12 + {% endblock %}
  13 +
8 <title>Colab - {% block title %}Colab{% endblock %}</title> 14 <title>Colab - {% block title %}Colab{% endblock %}</title>
9 15
10 <link rel="shortcut icon" type="image/x-icon" href="{{ STATIC_URL }}img/interlegis.ico"> 16 <link rel="shortcut icon" type="image/x-icon" href="{{ STATIC_URL }}img/interlegis.ico">
@@ -22,6 +28,7 @@ @@ -22,6 +28,7 @@
22 <link rel="stylesheet" href="{{ STATIC_URL }}css/screen.css" 28 <link rel="stylesheet" href="{{ STATIC_URL }}css/screen.css"
23 type="text/css" media="screen" /> 29 type="text/css" media="screen" />
24 30
  31 + <!-- JQuery 2+ won't work for IE < 9 -->
25 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery-2.0.3.min.js"></script> 32 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery-2.0.3.min.js"></script>
26 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery.debouncedresize.js"></script> 33 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery.debouncedresize.js"></script>
27 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery.cookie.js"></script> 34 <script type="text/javascript" src="{{ STATIC_URL }}third-party/jquery.cookie.js"></script>
@@ -69,7 +76,7 @@ @@ -69,7 +76,7 @@
69 <div class="collapse navbar-collapse navbar-main"> 76 <div class="collapse navbar-collapse navbar-main">
70 <ul class="nav navbar-nav"> 77 <ul class="nav navbar-nav">
71 <li> 78 <li>
72 - <a href="{% url 'thread_list' %}">{% trans "Discussions" %}</a> 79 + <a href="{% url 'thread_list' %}">{% trans "Groups" %}</a>
73 </li> 80 </li>
74 <li> 81 <li>
75 <a href="{% url "feedzilla_index" %}">{% trans "Planet" %}</a> 82 <a href="{% url "feedzilla_index" %}">{% trans "Planet" %}</a>
@@ -78,13 +85,13 @@ @@ -78,13 +85,13 @@
78 <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Contribute" %} <b class="caret"></b></a> 85 <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Contribute" %} <b class="caret"></b></a>
79 <ul class="dropdown-menu"> 86 <ul class="dropdown-menu">
80 <li><a href="/wiki">Wiki</a></li> 87 <li><a href="/wiki">Wiki</a></li>
  88 + <li><a href="/timeline">{% trans "Timeline" %}</a></li>
  89 + <li><a href="/roadmap">{% trans "Roadmap" %}</a></li>
81 {% if user.is_active %} 90 {% if user.is_active %}
82 <li><a href="/newticket">{% trans "New Ticket" %}</a></li> 91 <li><a href="/newticket">{% trans "New Ticket" %}</a></li>
83 {% endif %} 92 {% endif %}
84 - <li><a href="/timeline">{% trans "Timeline" %}</a></li>  
85 - <li><a href="/roadmap">{% trans "Roadmap" %}</a></li>  
86 - <li><a href="/browser">{% trans "Browse Source" %}</a></li>  
87 <li><a href="/report">{% trans "View Tickets" %}</a></li> 93 <li><a href="/report">{% trans "View Tickets" %}</a></li>
  94 + <li><a href="/browser">{% trans "Browse Source" %}</a></li>
88 </ul> 95 </ul>
89 </li> 96 </li>
90 <li class="hidden-lg hidden-md"> 97 <li class="hidden-lg hidden-md">
@@ -95,7 +102,8 @@ @@ -95,7 +102,8 @@
95 <ul class="nav navbar-nav navbar-right"> 102 <ul class="nav navbar-nav navbar-right">
96 {% if not user.is_authenticated %} 103 {% if not user.is_authenticated %}
97 <li><a href="{% url 'signup' %}">{% trans "Register" %}</a></li> 104 <li><a href="{% url 'signup' %}">{% trans "Register" %}</a></li>
98 - <li>{% browserid_login text='Login' %}</li> 105 + {% trans 'Login' as login_text %}
  106 + <li>{% browserid_login text=login_text %}</li>
99 {% else %} 107 {% else %}
100 <li id="user-menu" class="dropdown"> 108 <li id="user-menu" class="dropdown">
101 <a href="#" class="dropdown-toggle user" data-toggle="dropdown">{% gravatar user.email 40 %} <b class="caret"></b>&nbsp;&nbsp;</a> 109 <a href="#" class="dropdown-toggle user" data-toggle="dropdown">{% gravatar user.email 40 %} <b class="caret"></b>&nbsp;&nbsp;</a>
@@ -109,7 +117,8 @@ @@ -109,7 +117,8 @@
109 </div> 117 </div>
110 <div> 118 <div>
111 <a class="btn btn-info pull-left" href="{% url 'user_profile' user.username %}">{% trans "My Profile" %}</a> 119 <a class="btn btn-info pull-left" href="{% url 'user_profile' user.username %}">{% trans "My Profile" %}</a>
112 - {% browserid_logout text='Logout' link_class='btn btn-default pull-right' %} 120 + {% trans 'Logout' as logout_text %}
  121 + {% browserid_logout text=logout_text link_class='btn btn-default pull-right' %}
113 </div> 122 </div>
114 </div> 123 </div>
115 </li> 124 </li>
@@ -161,16 +170,17 @@ @@ -161,16 +170,17 @@
161 <div class="row">&nbsp;</div> 170 <div class="row">&nbsp;</div>
162 171
163 {% block footer %} 172 {% block footer %}
164 - <p class="col-lg-12 text-center">{% trans "Last email imported at" %} {{ last_imported_message.received_time|date:'DATETIME_FORMAT' }}</p>  
165 - <div class="row">  
166 - </div>  
167 <div class="row"> 173 <div class="row">
168 - <p class="col-lg-12 text-center">  
169 - {% trans "The contents of this site is published under license" %}  
170 - <a href="http://creativecommons.org/licenses/by-nc-sa/2.0/br/">  
171 - {% trans "Creative Commons - attribution, non-commercial" %}  
172 - </a>  
173 - </p> 174 + <p class="col-lg-12 text-center">
  175 + <a href="{% url 'opendata' %}"><img src="{{ STATIC_URL }}img/opendata3.png"/></a>
  176 + </p>
  177 + <p class="col-lg-12 text-center">{% trans "Last email imported at" %} {{ last_imported_message.received_time|date:'DATETIME_FORMAT' }}</p>
  178 + <p class="col-lg-12 text-center">
  179 + {% trans "The contents of this site is published under license" %}
  180 + <a href="http://creativecommons.org/licenses/by-nc-sa/2.0/br/">
  181 + {% trans "Creative Commons - attribution, non-commercial" %}
  182 + </a>
  183 + </p>
174 </div> 184 </div>
175 {% endblock %} 185 {% endblock %}
176 186
src/templates/home.html
@@ -2,7 +2,9 @@ @@ -2,7 +2,9 @@
2 {% load i18n %} 2 {% load i18n %}
3 3
4 {% block head_js %} 4 {% block head_js %}
5 - {% include "pizza-chart.html" with chart_data=type_count chart_div="collabs" chart_height=330 %} 5 + {% trans "Contributions" as collabs_name %}
  6 +
  7 + {% include "pizza-chart.html" with chart_data=type_count chart_div="collabs" chart_height=330 name=collabs_name %}
6 {% endblock %} 8 {% endblock %}
7 9
8 {% block header %} 10 {% block header %}
src/templates/open-data.html 0 → 100644
@@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
  1 +{% extends "base.html" %}
  2 +{% load i18n %}
  3 +
  4 +{% block main-content %}
  5 + <div class="col-lg-12">
  6 + <h2>{% trans "OpenData - Communities Interlegis" %}</h2>
  7 + <p>{% trans "If you are interested in any other data that is not provided by this API, please contact us via the ticketing system (you must be registered in order to create a ticket)." %}</p>
  8 +
  9 + <h3>{% trans "Retrieving data via API" %}</h3>
  10 + <p>{% trans "Colab API works through HTTP/REST, always returning JSON objects." %}</p>
  11 + <p>
  12 + {% trans "The base API URL is" %}:
  13 + {% url 'api_v1_top_level' api_name='v1' as BASE_API_URL %}
  14 + <a href="{{ BASE_API_URL }}">{{ BASE_API_URL }}</a>
  15 + </p>
  16 +
  17 + <ul class="list-unstyled">
  18 + <li>
  19 + <p>{% trans "Each model listed below has a resource_uri field available, which is the object's data URI." %}</p>
  20 + <p>{% trans "The following list contains the available models to retrieve data and its fields available for filtering" %}:</p>
  21 + <ul>
  22 + <li>
  23 + <strong><a href="{{ BASE_API_URL }}user/">user</a></strong>:
  24 + {% trans "Fields" %}: <i>username, email, institution, role, first_name, last_name and bio</i>
  25 + <p><strong>{% trans "The email field is not shown for user's privacy, but you can use it to filter" %}</strong></p>
  26 + <ul>
  27 + <li><i>username</i> - {% trans "The user's username" %}</li>
  28 + <li><i>email</i> - {% trans "The user's email address" %}</li>
  29 + <li><i>institution</i> - {% trans "What is the user's institution" %}</li>
  30 + <li><i>role</i> - {% trans "What is the user's role" %}</li>
  31 + <li><i>first_name</i> - {% trans "The user's first name" %}</li>
  32 + <li><i>last_name</i> - {% trans "The user's last name" %}</li>
  33 + <li><i>bio</i> - {% trans "A mini bio of the user" %}</li>
  34 + </ul>
  35 + <br />
  36 + </li>
  37 + <li>
  38 + <strong><a href="{{ BASE_API_URL }}emailaddress/">emailaddress</a></strong>:
  39 + {% trans "Fields" %}: <i>user, address and real_name</i>
  40 + <p><strong>{% trans "The address field is not shown for user's privacy, but you can use it to filter" %}</strong></p>
  41 + <ul>
  42 + <li><i>user</i> - {% trans "It has a relationshop with the user described above" %}</li>
  43 + <li><i>address</i> - {% trans "An email address" %}</li>
  44 + <li><i>real_name</i> - {% trans "The user's real name" %}</li>
  45 + </ul>
  46 + <br />
  47 + </li>
  48 + <li>
  49 + <strong><a href="{{ BASE_API_URL }}message/">message</a></strong>:
  50 + {% trans "Fields" %}: <i>from_address, body, id, received_time and subject</i>
  51 + <ul>
  52 + <li><i>from_address</i> - {% trans "It has a relationship with the emailaddress described above" %}</li>
  53 + <li><i>body</i> - {% trans "The message's body" %}</li>
  54 + <li><i>subject</i> - {% trans "The message's subject" %}</li>
  55 + <li><i>id</i> - {% trans "The message's id" %}</li>
  56 + <li><i>received_time</i> - {% trans "The message's received time" %}</li>
  57 + </ul>
  58 + <br />
  59 + </li>
  60 + <li>
  61 + <strong><a href="{{ BASE_API_URL }}revision/">revision</a></strong>:
  62 + {% trans "Fields" %}: <i>author, created, key, message and repository_name</i>
  63 + <ul>
  64 + <li><i>author</i> - {% trans "The revision's author username" %}</li>
  65 + <li><i>created</i> - {% trans "When the revision's were created" %}</li>
  66 + <li><i>key</i> - {% trans "The revision's key" %}</li>
  67 + <li><i>message</i> - {% trans "The revision's message" %}</li>
  68 + <li><i>repository_name</i> - {% trans "The revision's repository name" %}</li>
  69 + </ul>
  70 + <br />
  71 + </li>
  72 + <li>
  73 + <strong><a href="{{ BASE_API_URL }}ticket/">ticket</a></strong>:
  74 + {% trans "Fields" %}: <i>author, component, created, description, id, keywords, milestone, modified, modified_by, priority, reporter, severity, status, summary and version</i>
  75 + <ul>
  76 + <li><i>author</i> - {% trans "The ticket's author username" %}</li>
  77 + <li><i>component</i> - {% trans "The ticket's component" %}</li>
  78 + <li><i>created</i> - {% trans "When the ticket's were created" %}</li>
  79 + <li><i>description</i> - {% trans "The ticket's description" %}</li>
  80 + <li><i>id</i> - {% trans "The ticket's id" %}</li>
  81 + <li><i>keywords</i> - {% trans "The ticket's keywords" %}</li>
  82 + <li><i>milestone</i> - {% trans "The ticket's milestone" %}</li>
  83 + <li><i>modified</i> - {% trans "The time of the last modification" %}</li>
  84 + <li><i>modified_by</i> - {% trans "The username of the last user who modified the ticket" %}</li>
  85 + <li><i>priority</i> - {% trans "The ticket's priority" %}</li>
  86 + <li><i>severity</i> - {% trans "The ticket's severity" %}</li>
  87 + <li><i>status</i> - {% trans "The ticket's status" %}</li>
  88 + <li><i>summary</i> - {% trans "The ticket's summary" %}</li>
  89 + <li><i>version</i> - {% trans "The ticket's version" %}</li>
  90 + </ul>
  91 + <br />
  92 + </li>
  93 + <li>
  94 + <strong><a href="{{ BASE_API_URL }}wiki/">wiki</a></strong>:
  95 + {% trans "Fields" %}: <i>author, created, modified, modified_by, name and wiki_text</i>
  96 + <ul>
  97 + <li><i>author</i> - {% trans "The wiki's author username" %}</li>
  98 + <li><i>created</i> - {% trans "When the wiki's were created" %}</li>
  99 + <li><i>modified</i> - {% trans "The time of the last modification" %}</li>
  100 + <li><i>modified_by</i> - {% trans "The username of the last user who modified the wiki" %}</li>
  101 + <li><i>name</i> - {% trans "The wiki's name" %}</li>
  102 + <li><i>wiki_text</i> - {% trans "the wiki's content" %}</li>
  103 + </ul>
  104 + </li>
  105 + </ul>
  106 + </li>
  107 + </ul>
  108 + <ul class="list-unstyled">
  109 + <li><h3>{% trans 'Parameters' %}:</h3></li>
  110 + <li class="divider"></li>
  111 + <li>
  112 + <h4><i>limit</i> - {% trans "Results per page" %}</h4>
  113 + {% trans "Number of results to be displayed per page." %}
  114 + <i>{% trans "Default: 20" %}</i>.
  115 + </li>
  116 + <li class="divider"></li>
  117 + <li>
  118 + <h4><i>offset</i> - {% trans "Starts of n element" %}</h4>
  119 + {% trans "Where n is the index of the first result to appear in the page." %}
  120 + <i>{% trans "Default: 0" %}</i>.
  121 + </li>
  122 + <li class="divider"><h3>{% trans "Filtering" %}:</h3></li>
  123 + <li>
  124 + <h4><i>fieldname</i> - {% trans "The field name" %}</h4>
  125 + {% trans "If you are looking for a specific wiki, and you know the wiki's name, you can filter it as below" %}
  126 + <p><i>...{{ BASE_API_URL }}wiki/?name={% trans "WikiName" %}</i></p>
  127 + <p>{% trans "Where &quot;name&quot; is the fieldname and &quot;WikiName&quot; is the value you want to filter." %}</p>
  128 + <h4>{% trans "Usage" %}</h4>
  129 + <p>{% trans "You can also filter using Django lookup fields with the double underscores, just as below" %}</p>
  130 + <p><i>...{{ BASE_API_URL }}wiki/?wiki_text__startswith={% trans "Wiki" %}</i></p>
  131 + <p><i>...{{ BASE_API_URL }}ticket/?author__endswith={% trans "test" %}</i></p>
  132 + <p><i>...{{ BASE_API_URL }}message/?body__contains={% trans "test" %}</i></p>
  133 + <h4>{% trans "Usage with relationships" %}</h4>
  134 + <p>{% trans "You can use related fields to filter too. So, you can filter by any field of emailaddress using the 'from_address' field of message, which has a relation to emailaddress. You will achieve the related fields by using double underscore and the field's name. See the example below" %}</p>
  135 + <p><i>...{{ BASE_API_URL }}message/?from_address__real_name__contains=Name</i></p>
  136 + <p>{% trans "So, real_name is a field of emailaddress, and you had access to this field by a message field called from_address and using double underscore to say you want to use a field of that relationship" %}</p>
  137 + <p><strong>{% trans "Note: email filters must be exact. Which means that __contains, __startswith, __endswith and others won't work" %}</strong></p>
  138 + <p>{% trans "Another example of usage with relations. Used to retrieve all messages of a given user, using the username or the email field" %}</p>
  139 + <p><i>...{{ BASE_API_URL }}message/?from_address__user__username=username</i></p>
  140 + <p><i>...{{ BASE_API_URL }}message/?from_address__user__email=usermailexample@host.com</i></p>
  141 + </li>
  142 + </ul>
  143 + </div>
  144 +{% endblock %}
src/templates/pizza-chart.html
1 {% load i18n %} 1 {% load i18n %}
2 2
3 - <!--Load the AJAX API-->  
4 - <script type="text/javascript" src="https://www.google.com/jsapi"></script>  
5 - <script type="text/javascript">  
6 -  
7 - // Load the Visualization API and the piechart package.  
8 - google.load('visualization', '1.0', {'packages':['corechart']});  
9 -  
10 - // Set a callback to run when the Google Visualization API is loaded.  
11 - google.setOnLoadCallback(drawChart);  
12 -  
13 - // Callback that creates and populates a data table,  
14 - // instantiates the pie chart, passes in the data and  
15 - // draws it.  
16 - function drawChart() { 3 +<script src="{{ STATIC_URL }}third-party/highcharts/js/highcharts.js"></script>
  4 +<script>
  5 +$(function () {
  6 + $('#{{ chart_div }}').highcharts({
  7 + chart: {
  8 + type: 'pie',
  9 + height: {{ chart_height }},
  10 + },
17 11
18 - // Create the data table.  
19 - var data = new google.visualization.DataTable();  
20 - data.addColumn('string', 'Topping');  
21 - data.addColumn('number', 'Slices');  
22 - data.addRows([  
23 - {% for key, value in chart_data.items %}  
24 - ['{{ key }}', {{ value }} ],  
25 - {% empty %}  
26 - ['{% trans "Willing to help" %}', 100],  
27 - {% endfor %}  
28 - ]);  
29 -  
30 - // Set chart options  
31 - var options = {  
32 - height: '{{ chart_height }}',  
33 - legend: {  
34 - position: 'bottom',  
35 - alignment: 'center',  
36 - },  
37 - chartArea: {  
38 - height: "85%",  
39 - width: "95%",  
40 - top: 10, 12 + // Add selectpoint and legends to the chart
  13 + plotOptions: {
  14 + pie: {
  15 + allowPointSelect: true,
  16 + cursor: 'pointer',
  17 + dataLabels: {
  18 + enabled: false
41 }, 19 },
42 - }; 20 + showInLegend: true,
  21 + }
  22 + },
43 23
44 - // Instantiate and draw our chart, passing in some options.  
45 - var chart = new google.visualization.PieChart(document.getElementById('{{ chart_div }}'));  
46 - chart.draw(data, options); 24 + // Removes highcharts watermark
  25 + credits: {
  26 + enabled: false
  27 + },
47 28
48 - $(window).on("debouncedresize", function( event ) {  
49 - chart.draw(data, options);  
50 - });  
51 - }  
52 - </script> 29 + title: {
  30 + text: {% if chart_title %}'{{ chart_title }}'{% else %}''{% endif %}
  31 + },
  32 +
  33 + series: [{
  34 + data: [
  35 + {% for option, value in chart_data.items %}
  36 + ['{{ option }}', {{ value }}],
  37 + {% endfor %}
  38 + ],
  39 + name: '{{ name }}'
  40 + }]
  41 + });
  42 +});
  43 +</script>