Commit 21973244d51d342ce40ab7c20ea8b46fb5d4334d

Authored by Rodrigo Siqueira de Melo
Committed by Gust
1 parent 19615e85

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
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
... ... @@ -14,3 +14,5 @@ class ProxyJenkinsAppConfig(ColabProxiedAppConfig):
14 14 (_('Continuos Integration'), ''),
15 15 ),
16 16 }
  17 +
  18 + collaboration_models = []
... ...
colab/proxy/noosfero/apps.py
... ... @@ -19,3 +19,5 @@ class ProxyNoosferoAppConfig(ColabProxiedAppConfig):
19 19 (_('Control panel'), 'myprofile'),
20 20 ),
21 21 }
  22 +
  23 + collaboration_models = []
... ...
colab/proxy/redmine/apps.py
... ... @@ -5,3 +5,5 @@ from ..utils.apps import ColabProxiedAppConfig
5 5 class ProxyRedmineAppConfig(ColabProxiedAppConfig):
6 6 name = 'colab.proxy.redmine'
7 7 verbose_name = 'Redmine Proxy'
  8 +
  9 + collaboration_models = []
... ...
colab/proxy/trac/apps.py
... ... @@ -22,3 +22,5 @@ class ProxyTracAppConfig(ColabProxiedAppConfig):
22 22 (_('New Wiki Page'), 'wiki/WikiNewPage'),
23 23 ),
24 24 }
  25 +
  26 + collaboration_models = []
... ...
colab/search/preview_block.py 0 → 100644
... ... @@ -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
... ... @@ -11,7 +11,6 @@
11 11 <span class="subject">
12 12 <a href="{{ result.url }}#msg-{{ result.pk }}"
13 13 title="{% filter striptags|truncatewords:50 %}{{ result.description|escape }}{% endfilter %}">
14   - {{ result.title }}
15 14 </a>
16 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 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
... ...