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 | ... | ... |