Commit 21973244d51d342ce40ab7c20ea8b46fb5d4334d
Committed by
Gust
1 parent
19615e85
Exists in
master
and in
39 other branches
Remove haystack search from dashboard an profile
-Generalizes a structure for proxies to define its collaboration models -Remove haystack search from profile and search pages in pro of the colab own database
Showing
10 changed files
with
169 additions
and
71 deletions
Show diff stats
colab/accounts/views.py
| 1 | 1 | #!/usr/bin/env python |
| 2 | 2 | # encoding: utf-8 |
| 3 | +import importlib | |
| 4 | +import inspect | |
| 3 | 5 | |
| 4 | 6 | from collections import OrderedDict |
| 5 | 7 | |
| ... | ... | @@ -15,6 +17,7 @@ from django.shortcuts import render, redirect, get_object_or_404 |
| 15 | 17 | from django.core.urlresolvers import reverse |
| 16 | 18 | from django.core.exceptions import PermissionDenied |
| 17 | 19 | from django.views.generic import DetailView, UpdateView, TemplateView |
| 20 | +from django.apps import apps | |
| 18 | 21 | |
| 19 | 22 | from conversejs import xmpp |
| 20 | 23 | from conversejs.models import XMPPAccount |
| ... | ... | @@ -22,7 +25,7 @@ from haystack.query import SearchQuerySet |
| 22 | 25 | |
| 23 | 26 | from colab.super_archives.models import (EmailAddress, Message, |
| 24 | 27 | EmailAddressValidation) |
| 25 | -from colab.search.utils import trans | |
| 28 | +from colab.search.utils import trans, getCollaborationData | |
| 26 | 29 | # from proxy.trac.models import WikiCollabCount, TicketCollabCount |
| 27 | 30 | from .forms import (UserCreationForm, UserForm, ListsForm, |
| 28 | 31 | UserUpdateForm, ChangeXMPPPasswordForm) |
| ... | ... | @@ -71,48 +74,19 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): |
| 71 | 74 | |
| 72 | 75 | count_types = OrderedDict() |
| 73 | 76 | |
| 74 | - fields_or_lookup = ( | |
| 75 | - {'collaborators__contains': user.username}, | |
| 76 | - {'fullname_and_username__contains': user.username}, | |
| 77 | - ) | |
| 77 | + # TODO: remove when mailman becomes a proxied plugin | |
| 78 | + messages = Message.objects.filter(from_address__user__pk=user.pk) | |
| 79 | + count_types[trans('thread')] = messages.count() | |
| 78 | 80 | |
| 79 | - counter_class = {} | |
| 80 | - # { | |
| 81 | - # 'wiki': WikiCollabCount, | |
| 82 | - # 'ticket': TicketCollabCount, | |
| 83 | - # } | |
| 81 | + collaborations, count_types_extras = getCollaborationData(user) | |
| 82 | + collaborations.extend(messages) | |
| 84 | 83 | |
| 85 | - types = ['thread'] | |
| 86 | - # types.extend(['ticket', 'wiki', 'changeset', 'attachment']) | |
| 84 | + collaborations = sorted(collaborations, key=lambda elem : elem.modified, reverse=True) | |
| 87 | 85 | |
| 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() | |
| 86 | + count_types.update(count_types_extras) | |
| 105 | 87 | |
| 106 | 88 | 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] | |
| 89 | + context['results'] = collaborations[:10] | |
| 116 | 90 | |
| 117 | 91 | email_pks = [addr.pk for addr in user.emails.iterator()] |
| 118 | 92 | query = Message.objects.filter(from_address__in=email_pks) |
| ... | ... | @@ -127,7 +101,6 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): |
| 127 | 101 | context.update(kwargs) |
| 128 | 102 | return super(UserProfileDetailView, self).get_context_data(**context) |
| 129 | 103 | |
| 130 | - | |
| 131 | 104 | def signup(request): |
| 132 | 105 | BROWSERID_ENABLED = getattr(settings, 'BROWSERID_ENABLED', False) |
| 133 | 106 | ... | ... |
colab/home/views.py
| 1 | - | |
| 2 | 1 | from collections import OrderedDict |
| 3 | 2 | |
| 4 | 3 | from django.conf import settings |
| ... | ... | @@ -8,53 +7,49 @@ from django.http import HttpResponse, Http404 |
| 8 | 7 | |
| 9 | 8 | from haystack.query import SearchQuerySet |
| 10 | 9 | |
| 10 | +<<<<<<< HEAD | |
| 11 | 11 | # from proxy.trac.models import WikiCollabCount, TicketCollabCount |
| 12 | 12 | from colab.search.utils import trans |
| 13 | 13 | from colab.super_archives.models import Thread |
| 14 | +======= | |
| 15 | +from colab.search.utils import trans, getCollaborationData | |
| 16 | +from colab.super_archives.models import Thread, Message | |
| 17 | +from colab.search.preview_block import PreviewBlock | |
| 18 | +from colab.accounts.models import User | |
| 19 | +>>>>>>> Remove haystack search from dashboard an profile | |
| 14 | 20 | |
| 15 | 21 | |
| 16 | 22 | def dashboard(request): |
| 17 | 23 | """Dashboard page""" |
| 24 | + | |
| 18 | 25 | 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) | |
| 26 | + highest_score_threads = Thread.highest_score.all()[:6] | |
| 27 | + | |
| 28 | + hottest_threads = [] | |
| 29 | + for thread in highest_score_threads: | |
| 30 | + hottest_threads.append(thread.latest_message) | |
| 31 | + | |
| 32 | + latest_results, count_types = getCollaborationData() | |
| 33 | + threads = Thread.objects.all() | |
| 34 | + messages = [] | |
| 35 | + for t in threads: | |
| 36 | + messages.append(t.latest_message) | |
| 37 | + | |
| 38 | + latest_results.extend(messages) | |
| 39 | + latest_results = sorted(latest_results, | |
| 40 | + key=lambda elem : elem.modified, reverse=True) | |
| 43 | 41 | |
| 44 | 42 | for key in count_types.keys(): |
| 45 | 43 | count_types[trans(key)] = count_types.pop(key) |
| 46 | 44 | |
| 47 | 45 | context = { |
| 48 | 46 | 'hottest_threads': hottest_threads[:6], |
| 49 | - 'latest_threads': latest_threads, | |
| 47 | + 'latest_threads': latest_threads[:6], | |
| 50 | 48 | 'type_count': count_types, |
| 51 | - 'latest_results': SearchQuerySet().all().order_by( | |
| 52 | - '-modified', '-created' | |
| 53 | - )[:6], | |
| 49 | + 'latest_results': latest_results[:6], | |
| 54 | 50 | } |
| 55 | 51 | return render(request, 'home.html', context) |
| 56 | 52 | |
| 57 | - | |
| 58 | 53 | def robots(request): |
| 59 | 54 | if getattr(settings, 'ROBOTS_NOINDEX', False): |
| 60 | 55 | return HttpResponse('User-agent: *\nDisallow: /', | ... | ... |
colab/proxy/gitlab/apps.py
| ... | ... | @@ -3,8 +3,36 @@ from django.utils.translation import ugettext_lazy as _ |
| 3 | 3 | |
| 4 | 4 | from ..utils.apps import ColabProxiedAppConfig |
| 5 | 5 | |
| 6 | - | |
| 7 | 6 | class ProxyGitlabAppConfig(ColabProxiedAppConfig): |
| 7 | + ''' | |
| 8 | + You can define a collaboration_models list to tell colab which | |
| 9 | + models and what values should be displayed as collaborations. | |
| 10 | + | |
| 11 | + See the example bellow: | |
| 12 | + | |
| 13 | + Field model refers to the model to be displayed. | |
| 14 | + Field model_verbose is the human name to be displayed in charts. | |
| 15 | + Field collaborator_username tells which user(username) is associated with this collaboration. | |
| 16 | + | |
| 17 | + The value of the hashes maps the attribute or method of the model to be put in those positions. | |
| 18 | + | |
| 19 | + collaboration_models = [ | |
| 20 | + { | |
| 21 | + 'model' : 'User', | |
| 22 | + 'model_verbose' : 'User', | |
| 23 | + 'tag' : '', | |
| 24 | + 'title' : 'username', | |
| 25 | + 'description' : 'get_full_name', | |
| 26 | + 'fullname' : '', | |
| 27 | + 'modified' : 'modified', | |
| 28 | + 'modified_by' : '', | |
| 29 | + 'modified_by_url' : '', | |
| 30 | + 'url' : '', | |
| 31 | + 'type' : '', | |
| 32 | + 'collaborator_username' : 'username', | |
| 33 | + }, | |
| 34 | + ] | |
| 35 | + ''' | |
| 8 | 36 | name = 'colab.proxy.gitlab' |
| 9 | 37 | verbose_name = 'Gitlab Proxy' |
| 10 | 38 | |
| ... | ... | @@ -23,3 +51,5 @@ class ProxyGitlabAppConfig(ColabProxiedAppConfig): |
| 23 | 51 | |
| 24 | 52 | ), |
| 25 | 53 | } |
| 54 | + | |
| 55 | + collaboration_models = [] | ... | ... |
colab/proxy/jenkins/apps.py
colab/proxy/noosfero/apps.py
colab/proxy/redmine/apps.py
colab/proxy/trac/apps.py
| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | +class PreviewBlock(): | |
| 2 | + tag = None | |
| 3 | + title = None | |
| 4 | + description = None | |
| 5 | + fullname = None | |
| 6 | + modified = None | |
| 7 | + modified_by = None | |
| 8 | + url = None | |
| 9 | + type = None | |
| 10 | + modified_by_url = None | |
| 11 | + collaborator_username = None | |
| 12 | + | |
| 13 | + def __init__(self, **kwargs): | |
| 14 | + for key, value in kwargs.items(): | |
| 15 | + setattr(self, key, value) | ... | ... |
colab/search/templates/search/search-message-preview.html
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 | 7 | from django.utils.translation import ugettext as _ |
| 8 | +from django.apps import apps | |
| 9 | +from django.conf import settings | |
| 10 | +from colab.super_archives.models import Thread, Message | |
| 11 | +from colab.search.preview_block import PreviewBlock | |
| 3 | 12 | |
| 4 | 13 | |
| 5 | 14 | def trans(key): |
| ... | ... | @@ -11,4 +20,73 @@ def trans(key): |
| 11 | 20 | 'attachment': _('Attachments'), |
| 12 | 21 | } |
| 13 | 22 | |
| 23 | + app_names = settings.PROXIED_APPS.keys() | |
| 24 | + | |
| 25 | + for app_name in app_names: | |
| 26 | + collaboration_models = apps.get_app_config(app_name).collaboration_models | |
| 27 | + | |
| 28 | + for collaboration in collaboration_models: | |
| 29 | + module = importlib.import_module('colab.proxy.{}.models'.format(app_name)) | |
| 30 | + elements = eval("module." + collaboration['model']).objects.all() | |
| 31 | + translations[ collaboration['model'].lower() ] = collaboration['model_verbose'] | |
| 32 | + | |
| 14 | 33 | return translations.get(key, key) |
| 34 | + | |
| 35 | +def getCollaborationData(filter_by_user = None): | |
| 36 | + | |
| 37 | + latest_results = [] | |
| 38 | + count_types = cache.get('home_chart') | |
| 39 | + populate_count_types = False | |
| 40 | + | |
| 41 | + if count_types is None: | |
| 42 | + populate_count_types = True | |
| 43 | + count_types = OrderedDict() | |
| 44 | + count_types['thread'] = Thread.objects.count() | |
| 45 | + | |
| 46 | + app_names = settings.PROXIED_APPS.keys() | |
| 47 | + | |
| 48 | + for app_name in app_names: | |
| 49 | + collaboration_models = apps.get_app_config(app_name).collaboration_models | |
| 50 | + | |
| 51 | + for collaboration in collaboration_models: | |
| 52 | + module = importlib.import_module('colab.proxy.{}.models'.format(app_name)) | |
| 53 | + elements = eval("module." + collaboration['model']).objects | |
| 54 | + | |
| 55 | + if filter_by_user: | |
| 56 | + dic = {} | |
| 57 | + dic[collaboration['collaborator_username']] = filter_by_user | |
| 58 | + elements = elements.filter(**dic) | |
| 59 | + else: | |
| 60 | + elements = elements.all() | |
| 61 | + | |
| 62 | + latest_results.extend(parsePreviewBlock(elements, collaboration)) | |
| 63 | + | |
| 64 | + if populate_count_types: | |
| 65 | + count_types[ collaboration['model'].lower() ] = elements.count() | |
| 66 | + | |
| 67 | + if populate_count_types: | |
| 68 | + cache.set('home_chart', count_types) | |
| 69 | + | |
| 70 | + for key in count_types.keys(): | |
| 71 | + count_types[trans(key)] = count_types.pop(key) | |
| 72 | + | |
| 73 | + return latest_results, count_types | |
| 74 | + | |
| 75 | +def parsePreviewBlock(elements, collaboration): | |
| 76 | + results = [] | |
| 77 | + for element in elements: | |
| 78 | + previewblock = PreviewBlock() | |
| 79 | + attributes = collaboration.keys() | |
| 80 | + | |
| 81 | + for keyname in attributes: | |
| 82 | + if keyname == 'model' or keyname == 'model_verbose' or len(collaboration[keyname].strip()) == 0: | |
| 83 | + continue | |
| 84 | + value = getattr(element, collaboration[keyname]) | |
| 85 | + if(inspect.ismethod(value)): | |
| 86 | + setattr(previewblock, keyname, value() ) | |
| 87 | + else: | |
| 88 | + setattr(previewblock, keyname, value ) | |
| 89 | + | |
| 90 | + results.append(previewblock) | |
| 91 | + | |
| 92 | + return results | |
| 15 | 93 | \ No newline at end of file | ... | ... |