17
17
'QuestionCollectionOpenCountView',
18
18
'QuestionCollectionAnswersMenu',
19
19
'QuestionTargetFacetMixin',
20
'QuestionTargetPortletAnswerContactsWithDetails',
20
21
'QuestionTargetTraversalMixin',
21
22
'QuestionTargetAnswersMenu',
22
23
'UserSupportLanguagesMixin',
25
26
from operator import attrgetter
27
from simplejson import dumps
26
28
from urllib import urlencode
30
from lazr.restful.interfaces import (
32
IWebServiceClientRequest,
28
35
from z3c.ptcompat import ViewPageTemplateFile
29
36
from zope.app.form.browser import DropdownWidget
30
37
from zope.component 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))
822
class QuestionTargetPortletAnswerContacts(LaunchpadView):
823
"""View sets up the required url data for the answer contacts portlet."""
826
def api_request(self):
827
return IWebServiceClientRequest(self.request)
829
def initialize(self):
830
cache = IJSONRequestCache(self.request).objects
832
'web_link': canonical_url(self.context, rootsite='mainsite'),
833
'self_link': absoluteURL(self.context, self.api_request),
835
cache[self.context.name + '_answer_portlet_url_data'] = (
839
class QuestionTargetPortletAnswerContactsWithDetails(LaunchpadView):
840
"""View returns JSON dump of answer contact details for questiontarget."""
843
def api_request(self):
844
return IWebServiceClientRequest(self.request)
846
def answercontact_data(self, questiontarget):
847
"""Get the answer contact data.
849
This method is isolated from the answercontact_data_js so that query
850
count testing can be done accurately and robustly.
853
answer_contacts = list(questiontarget.direct_answer_contacts)
854
for person in answer_contacts:
855
can_edit = questiontarget.canUserAlterAnswerContact(
857
if person.private and not can_edit:
858
# Skip private teams user is not a member of.
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,
870
'subscriber': answer_contact,
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)
883
"""Override the default render() to return only JSON."""
884
self.request.response.setHeader('content-type', 'application/json')
885
return self.answercontact_data_js
813
888
class QuestionTargetFacetMixin:
814
889
"""Mixin for questiontarget facet definition."""