~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/answers/browser/questiontarget.py

[r=adeuring][bug=823945] Provide a javascript answer contacts portlet
 which allows users to be removed as contacts

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
    'QuestionCollectionOpenCountView',
18
18
    'QuestionCollectionAnswersMenu',
19
19
    'QuestionTargetFacetMixin',
 
20
    'QuestionTargetPortletAnswerContactsWithDetails',
20
21
    'QuestionTargetTraversalMixin',
21
22
    'QuestionTargetAnswersMenu',
22
23
    'UserSupportLanguagesMixin',
23
24
    ]
24
25
 
25
26
from operator import attrgetter
 
27
from simplejson import dumps
26
28
from urllib import urlencode
27
29
 
 
30
from lazr.restful.interfaces import (
 
31
    IJSONRequestCache,
 
32
    IWebServiceClientRequest,
 
33
    )
 
34
 
28
35
from z3c.ptcompat import ViewPageTemplateFile
29
36
from zope.app.form.browser import DropdownWidget
30
37
from zope.component import (
42
49
    SimpleTerm,
43
50
    SimpleVocabulary,
44
51
    )
 
52
from zope.traversing.browser import absoluteURL
45
53
 
46
54
from canonical.launchpad import _
47
55
from canonical.launchpad.helpers import (
60
68
from canonical.launchpad.webapp.batching import BatchNavigator
61
69
from canonical.launchpad.webapp.breadcrumb import Breadcrumb
62
70
from canonical.launchpad.webapp.menu import structured
 
71
from canonical.launchpad.webapp.publisher import LaunchpadView
63
72
from lp.answers.browser.faqcollection import FAQCollectionMenu
64
73
from lp.answers.enums import QuestionStatus
65
74
from lp.answers.interfaces.faqcollection import IFAQCollection
810
819
            response.addNotification(structured(msgid))
811
820
 
812
821
 
 
822
class QuestionTargetPortletAnswerContacts(LaunchpadView):
 
823
    """View sets up the required url data for the answer contacts portlet."""
 
824
 
 
825
    @cachedproperty
 
826
    def api_request(self):
 
827
        return IWebServiceClientRequest(self.request)
 
828
 
 
829
    def initialize(self):
 
830
        cache = IJSONRequestCache(self.request).objects
 
831
        context_url_data = {
 
832
            'web_link': canonical_url(self.context, rootsite='mainsite'),
 
833
            'self_link': absoluteURL(self.context, self.api_request),
 
834
            }
 
835
        cache[self.context.name + '_answer_portlet_url_data'] = (
 
836
            context_url_data)
 
837
 
 
838
 
 
839
class QuestionTargetPortletAnswerContactsWithDetails(LaunchpadView):
 
840
    """View returns JSON dump of answer contact details for questiontarget."""
 
841
 
 
842
    @cachedproperty
 
843
    def api_request(self):
 
844
        return IWebServiceClientRequest(self.request)
 
845
 
 
846
    def answercontact_data(self, questiontarget):
 
847
        """Get the answer contact data.
 
848
 
 
849
        This method is isolated from the answercontact_data_js so that query
 
850
        count testing can be done accurately and robustly.
 
851
        """
 
852
        data = []
 
853
        answer_contacts = list(questiontarget.direct_answer_contacts)
 
854
        for person in answer_contacts:
 
855
            can_edit = questiontarget.canUserAlterAnswerContact(
 
856
                person, self.user)
 
857
            if person.private and not can_edit:
 
858
                # Skip private teams user is not a member of.
 
859
                continue
 
860
 
 
861
            answer_contact = {
 
862
                'name': person.name,
 
863
                'display_name': person.displayname,
 
864
                'web_link': canonical_url(person, rootsite='mainsite'),
 
865
                'self_link': absoluteURL(person, self.api_request),
 
866
                'is_team': person.is_team,
 
867
                'can_edit': can_edit
 
868
                }
 
869
            record = {
 
870
                'subscriber': answer_contact,
 
871
                }
 
872
            data.append(record)
 
873
        return data
 
874
 
 
875
    @property
 
876
    def answercontact_data_js(self):
 
877
        """Return subscriber_ids in a form suitable for JavaScript use."""
 
878
        questiontarget = IQuestionTarget(self.context)
 
879
        data = self.answercontact_data(questiontarget)
 
880
        return dumps(data)
 
881
 
 
882
    def render(self):
 
883
        """Override the default render() to return only JSON."""
 
884
        self.request.response.setHeader('content-type', 'application/json')
 
885
        return self.answercontact_data_js
 
886
 
 
887
 
813
888
class QuestionTargetFacetMixin:
814
889
    """Mixin for questiontarget facet definition."""
815
890