Commit 5f62a7ac63ea3282a137553bc5800a93691f04d0
Exists in
master
and in
39 other branches
Merge branch 'master' of beta.softwarepublico.gov.br:softwarepublico/colab
Showing
18 changed files
with
299 additions
and
130 deletions
Show diff stats
colab/accounts/views.py
| 1 | -#!/usr/bin/env python | ||
| 2 | # encoding: utf-8 | 1 | # encoding: utf-8 |
| 3 | - | ||
| 4 | from collections import OrderedDict | 2 | from collections import OrderedDict |
| 5 | 3 | ||
| 6 | -from haystack.exceptions import SearchBackendError | ||
| 7 | - | ||
| 8 | from django.conf import settings | 4 | from django.conf import settings |
| 9 | from django.contrib import messages | 5 | from django.contrib import messages |
| 10 | from django.db import transaction | 6 | from django.db import transaction |
| @@ -18,15 +14,13 @@ from django.views.generic import DetailView, UpdateView, TemplateView | @@ -18,15 +14,13 @@ from django.views.generic import DetailView, UpdateView, TemplateView | ||
| 18 | 14 | ||
| 19 | from conversejs import xmpp | 15 | from conversejs import xmpp |
| 20 | from conversejs.models import XMPPAccount | 16 | from conversejs.models import XMPPAccount |
| 21 | -from haystack.query import SearchQuerySet | ||
| 22 | 17 | ||
| 23 | from colab.super_archives.models import (EmailAddress, Message, | 18 | from colab.super_archives.models import (EmailAddress, Message, |
| 24 | EmailAddressValidation) | 19 | EmailAddressValidation) |
| 25 | -from colab.search.utils import trans | ||
| 26 | -# from proxy.trac.models import WikiCollabCount, TicketCollabCount | 20 | +from colab.search.utils import get_collaboration_data |
| 21 | + | ||
| 27 | from .forms import (UserCreationForm, UserForm, ListsForm, | 22 | from .forms import (UserCreationForm, UserForm, ListsForm, |
| 28 | UserUpdateForm, ChangeXMPPPasswordForm) | 23 | UserUpdateForm, ChangeXMPPPasswordForm) |
| 29 | -# from .errors import XMPPChangePwdException | ||
| 30 | from .utils import mailman | 24 | from .utils import mailman |
| 31 | 25 | ||
| 32 | 26 | ||
| @@ -71,54 +65,21 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): | @@ -71,54 +65,21 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): | ||
| 71 | 65 | ||
| 72 | count_types = OrderedDict() | 66 | count_types = OrderedDict() |
| 73 | 67 | ||
| 74 | - fields_or_lookup = ( | ||
| 75 | - {'collaborators__contains': user.username}, | ||
| 76 | - {'fullname_and_username__contains': user.username}, | ||
| 77 | - ) | ||
| 78 | - | ||
| 79 | - counter_class = {} | ||
| 80 | - # { | ||
| 81 | - # 'wiki': WikiCollabCount, | ||
| 82 | - # 'ticket': TicketCollabCount, | ||
| 83 | - # } | 68 | + collaborations, count_types_extras = get_collaboration_data(user) |
| 84 | 69 | ||
| 85 | - types = ['thread'] | ||
| 86 | - # types.extend(['ticket', 'wiki', 'changeset', 'attachment']) | 70 | + collaborations.sort(key=lambda elem: elem.modified, reverse=True) |
| 87 | 71 | ||
| 88 | - messages = Message.objects.filter(from_address__user__pk=user.pk) | ||
| 89 | - for type in types: | ||
| 90 | - CounterClass = counter_class.get(type) | ||
| 91 | - if CounterClass: | ||
| 92 | - try: | ||
| 93 | - counter = CounterClass.objects.get(author=user.username) | ||
| 94 | - except CounterClass.DoesNotExist: | ||
| 95 | - count_types[trans(type)] = 0 | ||
| 96 | - else: | ||
| 97 | - count_types[trans(type)] = counter.count | ||
| 98 | - elif type == 'thread': | ||
| 99 | - count_types[trans(type)] = messages.count() | ||
| 100 | - else: | ||
| 101 | - sqs = SearchQuerySet() | ||
| 102 | - for filter_or in fields_or_lookup: | ||
| 103 | - sqs = sqs.filter_or(type=type, **filter_or) | ||
| 104 | - count_types[trans(type)] = sqs.count() | 72 | + count_types.update(count_types_extras) |
| 105 | 73 | ||
| 106 | context['type_count'] = count_types | 74 | context['type_count'] = count_types |
| 107 | - | ||
| 108 | - sqs = SearchQuerySet() | ||
| 109 | - for filter_or in fields_or_lookup: | ||
| 110 | - sqs = sqs.filter_or(**filter_or).exclude(type='thread') | ||
| 111 | - | ||
| 112 | - try: | ||
| 113 | - context['results'] = sqs.order_by('-modified', '-created')[:10] | ||
| 114 | - except SearchBackendError: | ||
| 115 | - context['results'] = sqs.order_by('-modified')[:10] | 75 | + context['results'] = collaborations[:10] |
| 116 | 76 | ||
| 117 | email_pks = [addr.pk for addr in user.emails.iterator()] | 77 | email_pks = [addr.pk for addr in user.emails.iterator()] |
| 118 | query = Message.objects.filter(from_address__in=email_pks) | 78 | query = Message.objects.filter(from_address__in=email_pks) |
| 119 | query = query.order_by('-received_time') | 79 | query = query.order_by('-received_time') |
| 120 | context['emails'] = query[:10] | 80 | context['emails'] = query[:10] |
| 121 | 81 | ||
| 82 | + messages = Message.objects.filter(from_address__user__pk=user.pk) | ||
| 122 | count_by = 'thread__mailinglist__name' | 83 | count_by = 'thread__mailinglist__name' |
| 123 | context['list_activity'] = dict(messages.values_list(count_by) | 84 | context['list_activity'] = dict(messages.values_list(count_by) |
| 124 | .annotate(Count(count_by)) | 85 | .annotate(Count(count_by)) |
colab/home/views.py
| 1 | - | ||
| 2 | -from collections import OrderedDict | ||
| 3 | - | ||
| 4 | from django.conf import settings | 1 | from django.conf import settings |
| 5 | -from django.core.cache import cache | ||
| 6 | from django.shortcuts import render | 2 | from django.shortcuts import render |
| 7 | from django.http import HttpResponse, Http404 | 3 | from django.http import HttpResponse, Http404 |
| 8 | 4 | ||
| 9 | -from haystack.query import SearchQuerySet | ||
| 10 | - | ||
| 11 | -# from proxy.trac.models import WikiCollabCount, TicketCollabCount | ||
| 12 | -from colab.search.utils import trans | 5 | +from colab.search.utils import get_collaboration_data |
| 13 | from colab.super_archives.models import Thread | 6 | from colab.super_archives.models import Thread |
| 14 | 7 | ||
| 15 | 8 | ||
| 16 | def dashboard(request): | 9 | def dashboard(request): |
| 17 | """Dashboard page""" | 10 | """Dashboard page""" |
| 11 | + | ||
| 12 | + highest_score_threads = Thread.highest_score.all()[:6] | ||
| 13 | + | ||
| 14 | + hottest_threads = [t.latest_message for t in highest_score_threads] | ||
| 15 | + | ||
| 18 | latest_threads = Thread.objects.all()[:6] | 16 | latest_threads = Thread.objects.all()[:6] |
| 19 | - hottest_threads = Thread.highest_score.from_haystack()[:6] | ||
| 20 | - | ||
| 21 | - count_types = cache.get('home_chart') | ||
| 22 | - if count_types is None: | ||
| 23 | - count_types = OrderedDict() | ||
| 24 | - count_types['thread'] = SearchQuerySet().filter( | ||
| 25 | - type='thread', | ||
| 26 | - ).count() | ||
| 27 | - # TODO: this section should be inside trac app and only use it here | ||
| 28 | - # if settings.TRAC_ENABLED: | ||
| 29 | - # for type in ['changeset', 'attachment']: | ||
| 30 | - # count_types[type] = SearchQuerySet().filter( | ||
| 31 | - # type=type, | ||
| 32 | - # ).count() | ||
| 33 | - | ||
| 34 | - # count_types['ticket'] = sum([ | ||
| 35 | - # ticket.count for ticket in TicketCollabCount.objects.all() | ||
| 36 | - # ]) | ||
| 37 | - | ||
| 38 | - # count_types['wiki'] = sum([ | ||
| 39 | - # wiki.count for wiki in WikiCollabCount.objects.all() | ||
| 40 | - # ]) | ||
| 41 | - | ||
| 42 | - cache.set('home_chart', count_types) | ||
| 43 | - | ||
| 44 | - for key in count_types.keys(): | ||
| 45 | - count_types[trans(key)] = count_types.pop(key) | 17 | + |
| 18 | + latest_results, count_types = get_collaboration_data() | ||
| 19 | + latest_results.sort(key=lambda elem: elem.modified, reverse=True) | ||
| 46 | 20 | ||
| 47 | context = { | 21 | context = { |
| 48 | 'hottest_threads': hottest_threads[:6], | 22 | 'hottest_threads': hottest_threads[:6], |
| 49 | 'latest_threads': latest_threads, | 23 | 'latest_threads': latest_threads, |
| 50 | 'type_count': count_types, | 24 | 'type_count': count_types, |
| 51 | - 'latest_results': SearchQuerySet().all().order_by( | ||
| 52 | - '-modified', '-created' | ||
| 53 | - )[:6], | 25 | + 'latest_results': latest_results[:6], |
| 54 | } | 26 | } |
| 55 | return render(request, 'home.html', context) | 27 | return render(request, 'home.html', context) |
| 56 | 28 |
colab/proxy/gitlab/data_api.py
| 1 | - | ||
| 2 | import json | 1 | import json |
| 3 | import urllib | 2 | import urllib |
| 4 | import urllib2 | 3 | import urllib2 |
| @@ -58,7 +57,7 @@ class GitlabDataAPI(ProxyDataAPI): | @@ -58,7 +57,7 @@ class GitlabDataAPI(ProxyDataAPI): | ||
| 58 | 57 | ||
| 59 | return projects | 58 | return projects |
| 60 | 59 | ||
| 61 | - def fetchData(self): | 60 | + def fetch_data(self): |
| 62 | data = self.fetchProjects() | 61 | data = self.fetchProjects() |
| 63 | 62 | ||
| 64 | for datum in data: | 63 | for datum in data: |
colab/proxy/gitlab/models.py
| 1 | from django.db import models | 1 | from django.db import models |
| 2 | +from django.utils.translation import ugettext_lazy as _ | ||
| 2 | 3 | ||
| 3 | 4 | ||
| 4 | class GitlabProject(models.Model): | 5 | class GitlabProject(models.Model): |
| @@ -10,3 +11,7 @@ class GitlabProject(models.Model): | @@ -10,3 +11,7 @@ class GitlabProject(models.Model): | ||
| 10 | name_with_namespace = models.TextField() | 11 | name_with_namespace = models.TextField() |
| 11 | created_at = models.DateTimeField(blank=True) | 12 | created_at = models.DateTimeField(blank=True) |
| 12 | last_activity_at = models.DateTimeField(blank=True) | 13 | last_activity_at = models.DateTimeField(blank=True) |
| 14 | + | ||
| 15 | + class Meta: | ||
| 16 | + verbose_name = _('Gitlab Project') | ||
| 17 | + verbose_name_plural = _('Gitlab Projects') |
colab/proxy/jenkins/data_api.py
colab/proxy/management/commands/import_proxy_data.py
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | 2 | ||
| 3 | import importlib | 3 | import importlib |
| 4 | +import inspect | ||
| 4 | 5 | ||
| 5 | from django.core.management.base import BaseCommand | 6 | from django.core.management.base import BaseCommand |
| 6 | from django.conf import settings | 7 | from django.conf import settings |
| 7 | 8 | ||
| 8 | -from colab.proxy.proxybase.proxy_data_api import ProxyDataAPI | 9 | +from colab.proxy.utils.proxy_data_api import ProxyDataAPI |
| 9 | 10 | ||
| 10 | 11 | ||
| 11 | class Command(BaseCommand): | 12 | class Command(BaseCommand): |
| @@ -20,7 +21,10 @@ class Command(BaseCommand): | @@ -20,7 +21,10 @@ class Command(BaseCommand): | ||
| 20 | 21 | ||
| 21 | for module_item_name in dir(module): | 22 | for module_item_name in dir(module): |
| 22 | module_item = getattr(module, module_item_name) | 23 | module_item = getattr(module, module_item_name) |
| 24 | + if not inspect.isclass(module_item): | ||
| 25 | + continue | ||
| 23 | if issubclass(module_item, ProxyDataAPI): | 26 | if issubclass(module_item, ProxyDataAPI): |
| 24 | if module_item != ProxyDataAPI: | 27 | if module_item != ProxyDataAPI: |
| 25 | api = module_item() | 28 | api = module_item() |
| 26 | - api.fetchData() | 29 | + api.fetch_data() |
| 30 | + break |
colab/proxy/noosfero/data_api.py
colab/proxy/redmine/data_api.py
colab/proxy/trac/data_api.py
colab/proxy/trac/models.py
| @@ -131,21 +131,3 @@ class Wiki(models.Model, HitCounterModelMixin): | @@ -131,21 +131,3 @@ class Wiki(models.Model, HitCounterModelMixin): | ||
| 131 | return User.objects.get(username=self.modified_by) | 131 | return User.objects.get(username=self.modified_by) |
| 132 | except User.DoesNotExist: | 132 | except User.DoesNotExist: |
| 133 | return None | 133 | return None |
| 134 | - | ||
| 135 | - | ||
| 136 | -class WikiCollabCount(models.Model): | ||
| 137 | - author = models.TextField(primary_key=True) | ||
| 138 | - count = models.IntegerField() | ||
| 139 | - | ||
| 140 | - class Meta: | ||
| 141 | - managed = False | ||
| 142 | - db_table = 'wiki_collab_count_view' | ||
| 143 | - | ||
| 144 | - | ||
| 145 | -class TicketCollabCount(models.Model): | ||
| 146 | - author = models.TextField(primary_key=True) | ||
| 147 | - count = models.IntegerField() | ||
| 148 | - | ||
| 149 | - class Meta: | ||
| 150 | - managed = False | ||
| 151 | - db_table = 'ticket_collab_count_view' |
| @@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
| 1 | +from django.db import models | ||
| 2 | +from django.conf import settings | ||
| 3 | +from colab.accounts.models import User | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class Collaboration(models.Model): | ||
| 7 | + ''' | ||
| 8 | + Class to define the fields of the collaboration block | ||
| 9 | + that are displayed at dashboard and profile pages. | ||
| 10 | + ''' | ||
| 11 | + | ||
| 12 | + tag = None | ||
| 13 | + title = None | ||
| 14 | + description = None | ||
| 15 | + url = None | ||
| 16 | + modified = None | ||
| 17 | + type = None | ||
| 18 | + | ||
| 19 | + user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, | ||
| 20 | + on_delete=models.SET_NULL) | ||
| 21 | + | ||
| 22 | + @property | ||
| 23 | + def modified_by(self): | ||
| 24 | + if self.user: | ||
| 25 | + return self.user.get_full_name() | ||
| 26 | + return None | ||
| 27 | + | ||
| 28 | + @property | ||
| 29 | + def modified_by_url(self): | ||
| 30 | + if self.user: | ||
| 31 | + return self.user.get_absolute_url() | ||
| 32 | + return None | ||
| 33 | + | ||
| 34 | + def update_user(self, user_name): | ||
| 35 | + try: | ||
| 36 | + self.user = User.objects.get(username=user_name) | ||
| 37 | + except User.DoesNotExist: | ||
| 38 | + self.user = None | ||
| 39 | + | ||
| 40 | + class Meta: | ||
| 41 | + abstract = True |
colab/proxy/utils/proxy_data_api.py
colab/search/templates/search/search-message-preview.html
| @@ -11,7 +11,6 @@ | @@ -11,7 +11,6 @@ | ||
| 11 | <span class="subject"> | 11 | <span class="subject"> |
| 12 | <a href="{{ result.url }}#msg-{{ result.pk }}" | 12 | <a href="{{ result.url }}#msg-{{ result.pk }}" |
| 13 | title="{% filter striptags|truncatewords:50 %}{{ result.description|escape }}{% endfilter %}"> | 13 | title="{% filter striptags|truncatewords:50 %}{{ result.description|escape }}{% endfilter %}"> |
| 14 | - {{ result.title }} | ||
| 15 | </a> | 14 | </a> |
| 16 | </span> | 15 | </span> |
| 17 | 16 |
colab/search/utils.py
| 1 | +import importlib | ||
| 2 | +import inspect | ||
| 1 | 3 | ||
| 4 | +from collections import OrderedDict | ||
| 5 | + | ||
| 6 | +from django.core.cache import cache | ||
| 2 | from django.utils.translation import ugettext as _ | 7 | from django.utils.translation import ugettext as _ |
| 8 | +from django.conf import settings | ||
| 9 | +from colab.super_archives.models import Thread, Message | ||
| 10 | +from colab.proxy.utils.models import Collaboration | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +def get_collaboration_data(filter_by_user=None): | ||
| 14 | + latest_results = [] | ||
| 15 | + count_types = cache.get('home_chart') | ||
| 16 | + populate_count_types = False | ||
| 17 | + | ||
| 18 | + if count_types is None: | ||
| 19 | + populate_count_types = True | ||
| 20 | + count_types = OrderedDict() | ||
| 21 | + count_types[_('Emails')] = Thread.objects.count() | ||
| 22 | + | ||
| 23 | + if filter_by_user: | ||
| 24 | + messages = Message.objects.filter(from_address__user__pk=filter_by_user.pk) | ||
| 25 | + else: | ||
| 26 | + latest_threads = Thread.objects.all()[:6] | ||
| 27 | + messages = [t.latest_message for t in latest_threads] | ||
| 28 | + | ||
| 29 | + latest_results.extend(messages) | ||
| 30 | + | ||
| 31 | + app_names = settings.PROXIED_APPS.keys() | ||
| 32 | + | ||
| 33 | + for app_name in app_names: | ||
| 34 | + module = importlib \ | ||
| 35 | + .import_module('colab.proxy.{}.models'.format(app_name)) | ||
| 36 | + | ||
| 37 | + for module_item_name in dir(module): | ||
| 38 | + module_item = getattr(module, module_item_name) | ||
| 39 | + if not inspect.isclass(module_item): | ||
| 40 | + continue | ||
| 41 | + if not issubclass(module_item, Collaboration): | ||
| 42 | + continue | ||
| 43 | + if module_item == Collaboration: | ||
| 44 | + continue | ||
| 45 | + | ||
| 46 | + queryset = module_item.objects | ||
| 47 | + | ||
| 48 | + if filter_by_user: | ||
| 49 | + elements = queryset.filter( | ||
| 50 | + user__username=filter_by_user) | ||
| 51 | + else: | ||
| 52 | + elements = queryset.all() | ||
| 53 | + | ||
| 54 | + latest_results.extend(elements) | ||
| 55 | + elements_count = elements.count() | ||
| 56 | + | ||
| 57 | + if elements_count > 1: | ||
| 58 | + verbose_name = module_item._meta.verbose_name_plural.title() | ||
| 59 | + else: | ||
| 60 | + verbose_name = module_item._meta.verbose_name.title() | ||
| 3 | 61 | ||
| 62 | + if populate_count_types: | ||
| 63 | + count_types[verbose_name] = elements_count | ||
| 4 | 64 | ||
| 5 | -def trans(key): | ||
| 6 | - translations = { | ||
| 7 | - 'wiki': _('Wiki'), | ||
| 8 | - 'thread': _('Emails'), | ||
| 9 | - 'changeset': _('Code'), | ||
| 10 | - 'ticket': _('Tickets'), | ||
| 11 | - 'attachment': _('Attachments'), | ||
| 12 | - } | 65 | + if populate_count_types: |
| 66 | + cache.set('home_chart', count_types, 30) | ||
| 13 | 67 | ||
| 14 | - return translations.get(key, key) | 68 | + return latest_results, count_types |
colab/settings.py
| @@ -321,8 +321,9 @@ if FEEDZILLA_ENABLED: | @@ -321,8 +321,9 @@ if FEEDZILLA_ENABLED: | ||
| 321 | 'common', | 321 | 'common', |
| 322 | ) | 322 | ) |
| 323 | 323 | ||
| 324 | -PROXIED_APPS = locals().get('PROXIED_APPS') or {} | ||
| 325 | BROWSERID_ENABLED = locals().get('BROWSERID_ENABLED') or False | 324 | BROWSERID_ENABLED = locals().get('BROWSERID_ENABLED') or False |
| 326 | 325 | ||
| 326 | +PROXIED_APPS = locals().get('PROXIED_APPS') or {} | ||
| 327 | + | ||
| 327 | for app_label in PROXIED_APPS.keys(): | 328 | for app_label in PROXIED_APPS.keys(): |
| 328 | INSTALLED_APPS += ('colab.proxy.{}'.format(app_label),) | 329 | INSTALLED_APPS += ('colab.proxy.{}'.format(app_label),) |
colab/super_archives/views.py
| @@ -17,13 +17,11 @@ from django.utils.decorators import method_decorator | @@ -17,13 +17,11 @@ from django.utils.decorators import method_decorator | ||
| 17 | from django.contrib.auth.decorators import login_required | 17 | from django.contrib.auth.decorators import login_required |
| 18 | from django.shortcuts import render, redirect, get_object_or_404 | 18 | from django.shortcuts import render, redirect, get_object_or_404 |
| 19 | 19 | ||
| 20 | -from haystack.query import SearchQuerySet | ||
| 21 | - | ||
| 22 | from colab.accounts.utils import mailman | 20 | from colab.accounts.utils import mailman |
| 23 | from colab.accounts.models import User | 21 | from colab.accounts.models import User |
| 24 | from .utils.email import send_verification_email | 22 | from .utils.email import send_verification_email |
| 25 | -from .models import MailingList, Thread, EmailAddress | ||
| 26 | -from .models import EmailAddressValidation, Message | 23 | +from .models import (MailingList, Thread, EmailAddress, |
| 24 | + EmailAddressValidation, Message) | ||
| 27 | 25 | ||
| 28 | 26 | ||
| 29 | class ThreadView(View): | 27 | class ThreadView(View): |
| @@ -110,8 +108,9 @@ class ThreadView(View): | @@ -110,8 +108,9 @@ class ThreadView(View): | ||
| 110 | elif resp.status_code == 404: | 108 | elif resp.status_code == 404: |
| 111 | error_msg = _('Mailing list does not exist') | 109 | error_msg = _('Mailing list does not exist') |
| 112 | else: | 110 | else: |
| 113 | - error_msg = _('Unknown error\ | ||
| 114 | - trying to connect to Mailman API') | 111 | + error_msg = \ |
| 112 | + _('Unknown error trying to connect to Mailman API') | ||
| 113 | + | ||
| 115 | messages.error(request, error_msg) | 114 | messages.error(request, error_msg) |
| 116 | 115 | ||
| 117 | return self.get(request, mailinglist, thread_token) | 116 | return self.get(request, mailinglist, thread_token) |
| @@ -126,7 +125,7 @@ class ThreadDashboardView(View): | @@ -126,7 +125,7 @@ class ThreadDashboardView(View): | ||
| 126 | all_lists = mailman.all_lists(description=True) | 125 | all_lists = mailman.all_lists(description=True) |
| 127 | 126 | ||
| 128 | context['lists'] = [] | 127 | context['lists'] = [] |
| 129 | - # lists = MailingList.objects.filter() | 128 | + |
| 130 | for list_ in MailingList.objects.order_by('name'): | 129 | for list_ in MailingList.objects.order_by('name'): |
| 131 | context['lists'].append(( | 130 | context['lists'].append(( |
| 132 | list_.name, | 131 | list_.name, |
| @@ -134,7 +133,8 @@ class ThreadDashboardView(View): | @@ -134,7 +133,8 @@ class ThreadDashboardView(View): | ||
| 134 | list_.thread_set.filter(spam=False).order_by( | 133 | list_.thread_set.filter(spam=False).order_by( |
| 135 | '-latest_message__received_time' | 134 | '-latest_message__received_time' |
| 136 | )[:MAX], | 135 | )[:MAX], |
| 137 | - SearchQuerySet().filter(type='thread', tag=list_.name)[:MAX], | 136 | + [t.latest_message for t in Thread.highest_score.filter( |
| 137 | + mailinglist__name=list_.name)[:MAX]], | ||
| 138 | len(mailman.list_users(list_.name)), | 138 | len(mailman.list_users(list_.name)), |
| 139 | )) | 139 | )) |
| 140 | 140 | ||
| @@ -171,6 +171,7 @@ class EmailView(View): | @@ -171,6 +171,7 @@ class EmailView(View): | ||
| 171 | email.user = email_val.user | 171 | email.user = email_val.user |
| 172 | email.save() | 172 | email.save() |
| 173 | email_val.delete() | 173 | email_val.delete() |
| 174 | + | ||
| 174 | user = User.objects.get(username=email.user.username) | 175 | user = User.objects.get(username=email.user.username) |
| 175 | user.is_active = True | 176 | user.is_active = True |
| 176 | user.save() | 177 | user.save() |
| @@ -0,0 +1,149 @@ | @@ -0,0 +1,149 @@ | ||
| 1 | +[ | ||
| 2 | +{ | ||
| 3 | + "fields": { | ||
| 4 | + "logo": "", | ||
| 5 | + "description": "", | ||
| 6 | + "last_imported_index": 0, | ||
| 7 | + "name": "ListA", | ||
| 8 | + "email": "listA@example.com" | ||
| 9 | + }, | ||
| 10 | + "model": "super_archives.mailinglist", | ||
| 11 | + "pk": 1 | ||
| 12 | +}, | ||
| 13 | +{ | ||
| 14 | + "fields": { | ||
| 15 | + "logo": "", | ||
| 16 | + "description": "", | ||
| 17 | + "last_imported_index": 0, | ||
| 18 | + "name": "ListB", | ||
| 19 | + "email": "listB@example.com" | ||
| 20 | + }, | ||
| 21 | + "model": "super_archives.mailinglist", | ||
| 22 | + "pk": 2 | ||
| 23 | +}, | ||
| 24 | +{ | ||
| 25 | + "fields": { | ||
| 26 | + "logo": "", | ||
| 27 | + "description": "", | ||
| 28 | + "last_imported_index": 0, | ||
| 29 | + "name": "ListC", | ||
| 30 | + "email": "listC@example.com" | ||
| 31 | + }, | ||
| 32 | + "model": "super_archives.mailinglist", | ||
| 33 | + "pk": 3 | ||
| 34 | +}, | ||
| 35 | +{ | ||
| 36 | + "fields": { | ||
| 37 | + "spam": false, | ||
| 38 | + "subject_token": "Thread_1_on_List_A", | ||
| 39 | + "mailinglist": 1, | ||
| 40 | + "score": 31, | ||
| 41 | + "latest_message": 3 | ||
| 42 | + }, | ||
| 43 | + "model": "super_archives.thread", | ||
| 44 | + "pk": 1 | ||
| 45 | +}, | ||
| 46 | +{ | ||
| 47 | + "fields": { | ||
| 48 | + "spam": false, | ||
| 49 | + "subject_token": "Thread_1_on_List_B", | ||
| 50 | + "mailinglist": 2, | ||
| 51 | + "score": 0, | ||
| 52 | + "latest_message": 4 | ||
| 53 | + }, | ||
| 54 | + "model": "super_archives.thread", | ||
| 55 | + "pk": 3 | ||
| 56 | +}, | ||
| 57 | +{ | ||
| 58 | + "fields": { | ||
| 59 | + "spam": false, | ||
| 60 | + "subject_token": "Thread_1_on_List_C", | ||
| 61 | + "mailinglist": 3, | ||
| 62 | + "score": 0, | ||
| 63 | + "latest_message": 5 | ||
| 64 | + }, | ||
| 65 | + "model": "super_archives.thread", | ||
| 66 | + "pk": 4 | ||
| 67 | +}, | ||
| 68 | +{ | ||
| 69 | + "fields": { | ||
| 70 | + "body": "This is a repply to Thread 1 on list A", | ||
| 71 | + "received_time": "2015-01-28T12:43:00.752Z", | ||
| 72 | + "from_address": 1, | ||
| 73 | + "thread": 1, | ||
| 74 | + "spam": false, | ||
| 75 | + "subject_clean": "Response to Thread 1A", | ||
| 76 | + "message_id": "loreipsum", | ||
| 77 | + "subject": "Response to Thread 1A" | ||
| 78 | + }, | ||
| 79 | + "model": "super_archives.message", | ||
| 80 | + "pk": 3 | ||
| 81 | +}, | ||
| 82 | +{ | ||
| 83 | + "fields": { | ||
| 84 | + "body": "", | ||
| 85 | + "received_time": "2015-01-28T12:57:22.180Z", | ||
| 86 | + "from_address": 1, | ||
| 87 | + "thread": 3, | ||
| 88 | + "spam": false, | ||
| 89 | + "subject_clean": "Message 1 on Thread 1B", | ||
| 90 | + "message_id": "", | ||
| 91 | + "subject": "Message 1 on Thread 1B" | ||
| 92 | + }, | ||
| 93 | + "model": "super_archives.message", | ||
| 94 | + "pk": 4 | ||
| 95 | +}, | ||
| 96 | +{ | ||
| 97 | + "fields": { | ||
| 98 | + "body": "", | ||
| 99 | + "received_time": "2015-01-28T13:02:12.903Z", | ||
| 100 | + "from_address": 1, | ||
| 101 | + "thread": 4, | ||
| 102 | + "spam": false, | ||
| 103 | + "subject_clean": "Message 1 on Thread 1C", | ||
| 104 | + "message_id": "", | ||
| 105 | + "subject": "Message 1 on Thread 1C" | ||
| 106 | + }, | ||
| 107 | + "model": "super_archives.message", | ||
| 108 | + "pk": 5 | ||
| 109 | +}, | ||
| 110 | +{ | ||
| 111 | + "fields": { | ||
| 112 | + "last_name": "Administrator", | ||
| 113 | + "webpage": "", | ||
| 114 | + "twitter": "", | ||
| 115 | + "is_staff": true, | ||
| 116 | + "user_permissions": [], | ||
| 117 | + "date_joined": "2015-01-28T12:34:58.770Z", | ||
| 118 | + "google_talk": "", | ||
| 119 | + "first_name": "Admin", | ||
| 120 | + "is_superuser": true, | ||
| 121 | + "last_login": "2015-01-28T12:35:39.621Z", | ||
| 122 | + "verification_hash": null, | ||
| 123 | + "role": "", | ||
| 124 | + "email": "admin@mail.com", | ||
| 125 | + "username": "admin", | ||
| 126 | + "bio": "", | ||
| 127 | + "needs_update": true, | ||
| 128 | + "is_active": true, | ||
| 129 | + "facebook": "", | ||
| 130 | + "groups": [], | ||
| 131 | + "password": "pbkdf2_sha256$12000$iiKCMnLZnFJw$UTx89LB8oYTiw9UqkcglzFLmIaZtbr+ZzF1cG3vfcyo=", | ||
| 132 | + "institution": "", | ||
| 133 | + "github": "", | ||
| 134 | + "modified": "2015-01-28T12:45:27.375Z" | ||
| 135 | + }, | ||
| 136 | + "model": "accounts.user", | ||
| 137 | + "pk": 1 | ||
| 138 | +}, | ||
| 139 | +{ | ||
| 140 | + "fields": { | ||
| 141 | + "real_name": "", | ||
| 142 | + "user": 1, | ||
| 143 | + "md5": "edb0e96701c209ab4b50211c856c50c4", | ||
| 144 | + "address": "admin@mail.com" | ||
| 145 | + }, | ||
| 146 | + "model": "super_archives.emailaddress", | ||
| 147 | + "pk": 1 | ||
| 148 | +} | ||
| 149 | +] |
vagrant/provision.sh