1
# Copyright 2009 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
7
'BranchPortletSubscribersContent',
8
'BranchSubscriptionAddOtherView',
9
'BranchSubscriptionAddView',
10
'BranchSubscriptionEditOwnView',
11
'BranchSubscriptionEditView',
12
'BranchSubscriptionPrimaryContext',
16
from zope.interface import implements
18
from canonical.launchpad.webapp import (
22
from canonical.launchpad.webapp.authorization import check_permission
23
from canonical.launchpad.webapp.interfaces import IPrimaryContext
24
from canonical.launchpad.webapp.menu import structured
25
from canonical.lazr.utils import smartquote
26
from lp.app.browser.launchpadform import (
28
LaunchpadEditFormView,
31
from lp.code.enums import BranchSubscriptionNotificationLevel
32
from lp.code.interfaces.branchsubscription import IBranchSubscription
35
class BranchSubscriptionPrimaryContext:
36
"""The primary context is the subscription is that of the branch."""
38
implements(IPrimaryContext)
40
def __init__(self, branch_subscription):
41
self.context = IPrimaryContext(branch_subscription.branch).context
44
class BranchPortletSubscribersContent(LaunchpadView):
45
"""View for the contents for the subscribers portlet.
47
This view is strictly for use with ajax.
50
def subscriptions(self):
51
"""Return a decorated list of branch subscriptions."""
52
visible_subscriptions = [
53
subscription for subscription in self.context.subscriptions
54
if check_permission('launchpad.View', subscription.person)]
56
visible_subscriptions,
57
key=lambda subscription: subscription.person.displayname)
60
class _BranchSubscriptionView(LaunchpadFormView):
62
"""Contains the common functionality of the Add and Edit views."""
64
schema = IBranchSubscription
65
field_names = ['notification_level', 'max_diff_lines', 'review_level']
67
LEVELS_REQUIRING_LINES_SPECIFICATION = (
68
BranchSubscriptionNotificationLevel.DIFFSONLY,
69
BranchSubscriptionNotificationLevel.FULL)
72
def user_is_subscribed(self):
73
# Since it is technically possible to get to this page when
74
# the user is not subscribed by hacking the URL, we should
75
# handle the case nicely.
76
return self.context.getSubscription(self.user) is not None
80
return canonical_url(self.context)
84
def add_notification_message(self, initial,
85
notification_level, max_diff_lines,
87
if notification_level in self.LEVELS_REQUIRING_LINES_SPECIFICATION:
88
lines_message = '<li>%s</li>' % max_diff_lines.description
92
format_str = '%%s<ul><li>%%s</li>%s<li>%%s</li></ul>' % lines_message
93
message = structured(format_str, initial,
94
notification_level.description,
95
review_level.description)
96
self.request.response.addNotification(message)
98
def optional_max_diff_lines(self, notification_level, max_diff_lines):
99
if notification_level in self.LEVELS_REQUIRING_LINES_SPECIFICATION:
100
return max_diff_lines
105
class BranchSubscriptionAddView(_BranchSubscriptionView):
107
subscribing_self = True
109
page_title = label = "Subscribe to branch"
112
def subscribe(self, action, data):
113
# To catch the stale post problem, check that the user is not
114
# subscribed before continuing.
115
if self.context.hasSubscription(self.user):
116
self.request.response.addNotification(
117
'You are already subscribed to this branch.')
119
notification_level = data['notification_level']
120
max_diff_lines = self.optional_max_diff_lines(
121
notification_level, data['max_diff_lines'])
122
review_level = data['review_level']
124
self.context.subscribe(
125
self.user, notification_level, max_diff_lines, review_level,
128
self.add_notification_message(
129
'You have subscribed to this branch with: ',
130
notification_level, max_diff_lines, review_level)
133
class BranchSubscriptionEditOwnView(_BranchSubscriptionView):
137
return "Edit subscription to branch"
140
def page_title(self):
142
'Edit subscription to branch "%s"' % self.context.displayname)
145
def initial_values(self):
146
subscription = self.context.getSubscription(self.user)
147
if subscription is None:
148
# This is the case of URL hacking or stale page.
151
return {'notification_level': subscription.notification_level,
152
'max_diff_lines': subscription.max_diff_lines,
153
'review_level': subscription.review_level}
156
def change_details(self, action, data):
157
# Be proactive in the checking to catch the stale post problem.
158
if self.context.hasSubscription(self.user):
159
subscription = self.context.getSubscription(self.user)
160
subscription.notification_level = data['notification_level']
161
subscription.max_diff_lines = self.optional_max_diff_lines(
162
subscription.notification_level,
163
data['max_diff_lines'])
164
subscription.review_level = data['review_level']
166
self.add_notification_message(
167
'Subscription updated to: ',
168
subscription.notification_level,
169
subscription.max_diff_lines,
170
subscription.review_level)
172
self.request.response.addNotification(
173
'You are not subscribed to this branch.')
175
@action("Unsubscribe")
176
def unsubscribe(self, action, data):
177
# Be proactive in the checking to catch the stale post problem.
178
if self.context.hasSubscription(self.user):
179
self.context.unsubscribe(self.user, self.user)
180
self.request.response.addNotification(
181
"You have unsubscribed from this branch.")
183
self.request.response.addNotification(
184
'You are not subscribed to this branch.')
187
class BranchSubscriptionAddOtherView(_BranchSubscriptionView):
188
"""View used to subscribe someone other than the current user."""
191
'person', 'notification_level', 'max_diff_lines', 'review_level']
194
# Since we are subscribing other people, the current user
195
# is never considered subscribed.
196
user_is_subscribed = False
197
subscribing_self = False
199
page_title = label = "Subscribe to branch"
201
@action("Subscribe", name="subscribe_action")
202
def subscribe_action(self, action, data):
203
"""Subscribe the specified user to the branch.
205
The user must be a member of a team in order to subscribe that team to
206
the branch. Launchpad Admins are special and they can subscribe any
209
notification_level = data['notification_level']
210
max_diff_lines = self.optional_max_diff_lines(
211
notification_level, data['max_diff_lines'])
212
review_level = data['review_level']
213
person = data['person']
214
subscription = self.context.getSubscription(person)
215
if subscription is None:
216
self.context.subscribe(
217
person, notification_level, max_diff_lines, review_level,
220
self.add_notification_message(
221
'%s has been subscribed to this branch with: '
222
% person.displayname, notification_level, max_diff_lines,
225
self.add_notification_message(
226
'%s was already subscribed to this branch with: '
227
% person.displayname,
228
subscription.notification_level, subscription.max_diff_lines,
232
class BranchSubscriptionEditView(LaunchpadEditFormView):
233
"""The view for editing branch subscriptions.
235
Used when traversed to the branch subscription itself rather than
236
through the branch action item to edit the user's own subscription.
237
This is the only current way to edit a team branch subscription.
239
schema = IBranchSubscription
240
field_names = ['notification_level', 'max_diff_lines', 'review_level']
243
def page_title(self):
245
'Edit subscription to branch "%s"' % self.branch.displayname)
249
return "Edit subscription to branch for %s" % self.person.displayname
251
def initialize(self):
252
self.branch = self.context.branch
253
self.person = self.context.person
254
LaunchpadEditFormView.initialize(self)
256
@action("Change", name="change")
257
def change_action(self, action, data):
258
"""Update the branch subscription."""
259
self.updateContextFromData(data)
261
@action("Unsubscribe", name="unsubscribe")
262
def unsubscribe_action(self, action, data):
263
"""Unsubscribe the team from the branch."""
264
self.branch.unsubscribe(self.person, self.user)
265
self.request.response.addNotification(
266
"%s has been unsubscribed from this branch."
267
% self.person.displayname)
271
return canonical_url(self.branch)
273
cancel_url = next_url