launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03901
[Merge] lp:~danilo/launchpad/bug-772754-other-subscribers-actions into lp:launchpad
Данило Шеган has proposed merging lp:~danilo/launchpad/bug-772754-other-subscribers-actions into lp:launchpad with lp:~danilo/launchpad/bug-772754-other-subscribers-loading as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #772754 in Launchpad itself: "After better-bug-notification changes, list of bug subscribers is confusing"
https://bugs.launchpad.net/launchpad/+bug/772754
For more details, see:
https://code.launchpad.net/~danilo/launchpad/bug-772754-other-subscribers-actions/+merge/64187
= Bug 772754: Other subscribers list, part 6 =
NOT READY FOR REVIEW YET
This is part of ongoing work for providing the "other subscribers" list as indicated in mockup https://launchpadlibrarian.net/71552495/all-in-one.png attached to bug 772754 by Gary.
Provides subscribe-someone-else and unsubscribe actions that actually work with Launchpad. Tests missing.
== Tests ==
lp/bugs/javascript/tests/test_subscribers_list.html
== Demo and Q/A ==
N/A
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/bugs/browser/bugsubscription.py
lib/lp/bugs/javascript/bugtask_index_portlets.js
lib/lp/bugs/javascript/subscribers_list.js
lib/lp/bugs/templates/bugtask-index.pt
--
https://code.launchpad.net/~danilo/launchpad/bug-772754-other-subscribers-actions/+merge/64187
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~danilo/launchpad/bug-772754-other-subscribers-actions into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bugsubscription.py'
--- lib/lp/bugs/browser/bugsubscription.py 2011-06-10 13:58:29 +0000
+++ lib/lp/bugs/browser/bugsubscription.py 2011-06-10 13:58:31 +0000
@@ -16,7 +16,10 @@
import cgi
from lazr.delegates import delegates
-from lazr.restful.interfaces import IJSONRequestCache
+from lazr.restful.interfaces import (
+ IJSONRequestCache,
+ IWebServiceClientRequest,
+)
from simplejson import dumps
from zope import formlib
from zope.app.form import CustomWidgetFactory
@@ -27,6 +30,7 @@
SimpleVocabulary,
)
from zope.security.proxy import removeSecurityProxy
+from zope.traversing.browser import absoluteURL
from canonical.launchpad import _
from canonical.launchpad.webapp import (
@@ -590,6 +594,7 @@
"""Return subscriber_ids in a form suitable for JavaScript use."""
data = []
details = list(self.context.getDirectSubscribersWithDetails())
+ api_request = IWebServiceClientRequest(self.request)
for person, subscription in details:
if person == self.user:
# Skip the current user viewing the page.
@@ -599,6 +604,7 @@
'name': person.name,
'display_name': person.displayname,
'web_link': canonical_url(person, rootsite='mainsite'),
+ 'self_link': absoluteURL(person, api_request),
'is_team': person.is_team,
'can_edit': can_edit,
}
@@ -618,6 +624,7 @@
'name': person.name,
'display_name': person.displayname,
'web_link': canonical_url(person, rootsite='mainsite'),
+ 'self_link': absoluteURL(person, api_request),
'is_team': person.is_team,
'can_edit': False,
}
=== modified file 'lib/lp/bugs/javascript/bugtask_index_portlets.js'
--- lib/lp/bugs/javascript/bugtask_index_portlets.js 2011-06-10 13:58:29 +0000
+++ lib/lp/bugs/javascript/bugtask_index_portlets.js 2011-06-10 13:58:31 +0000
@@ -309,7 +309,6 @@
var subscription = get_subscribe_self_subscription();
- setup_subscribe_someone_else_handler(subscription);
}
function load_subscribers_from_duplicates() {
=== modified file 'lib/lp/bugs/javascript/subscribers_list.js'
--- lib/lp/bugs/javascript/subscribers_list.js 2011-06-10 13:58:29 +0000
+++ lib/lp/bugs/javascript/subscribers_list.js 2011-06-10 13:58:31 +0000
@@ -1,7 +1,23 @@
/* Copyright 2011 Canonical Ltd. This software is licensed under the
* GNU Affero General Public License version 3 (see the file LICENSE).
*
- * Functions for managing the subscribers list.
+ * Classes for managing the subscribers list.
+ *
+ * Two classes are provided:
+ *
+ * - SubscribersList: deals with node construction/removal for the
+ * list of subscribers, including activity indication and animations.
+ *
+ * Public methods to use:
+ * startActivity, stopActivity,
+ * addSubscriber, removeSubscriber, indicateSubscriberActivity,
+ * stopSubscriberActivity, addUnsubscribeAction
+ *
+ * - BugSubscribersLoader: loads subscribers from LP, allows subscribing
+ * someone else and sets unsubscribe actions where appropriate.
+ * Depends on the SubscribersList to do the actual node construction.
+ *
+ * No public methods are available: it all gets run from the constructor.
*
* @module bugs
* @submodule subscribers_list
@@ -135,6 +151,7 @@
*/
function BugSubscribersLoader(config) {
var sl = this.subscribers_list = new SubscribersList(config);
+
if (!Y.Lang.isValue(config.bug) ||
!Y.Lang.isString(config.bug.web_link)) {
Y.error(
@@ -142,6 +159,7 @@
}
this.bug = config.bug;
+ // Get BugSubscribersWithDetails portlet link to load subscribers from.
if (!Y.Lang.isString(config.subscribers_details_view)) {
Y.error(
"No config.subscribers_details_view specified to load " +
@@ -163,6 +181,12 @@
}
this._loadSubscribers();
+
+ // Check for CSS class for the link to subscribe someone else.
+ if (Y.Lang.isString(config.subscribe_someone_else_link)) {
+ this.subscribe_someone_else_link = config.subscribe_someone_else_link;
+ this._setupSubscribeSomeoneElse();
+ }
}
namespace.BugSubscribersLoader = BugSubscribersLoader;
@@ -266,21 +290,137 @@
* Return a function object that accepts SubscribersList and subscriber
* objects as parameters.
*
+ * Constructed function tries to unsubscribe subscriber from the
+ * this.bug, and indicates activity in the subscribers list.
+ *
* @method _getUnsubscribeCallback
*/
BugSubscribersLoader.prototype._getUnsubscribeCallback = function() {
+ var loader = this;
return function(subscribers_list, subscriber) {
- subscribers_list.indicateSubscriberActivity(subscriber);
- // Simulated unsubscribing action for prototyping the UI.
- setTimeout(function() {
+ function on_success() {
subscribers_list.stopSubscriberActivity(
subscriber, true, function() {
- subscribers_list.removeSubscriber(subscriber);
- });
- }, 2400);
+ subscribers_list.removeSubscriber(subscriber);
+ });
+ }
+ function on_failure() {
+ subscribers_list.stopSubscriberActivity(subscriber, false);
+ }
+
+ var config = {
+ on: { success: on_success,
+ failure: on_failure },
+ parameters: { person: subscriber.self_link }
+ };
+ subscribers_list.indicateSubscriberActivity(subscriber);
+ loader.lp_client.named_post(
+ loader.bug.self_link, 'unsubscribe', config);
};
};
+/**
+ * Set-up subscribe-someone-else link to pop-up a picker and subscribe
+ * the selected person/team.
+ *
+ * On `save' from the picker, fetch the actual person object via API
+ * and pass it into _subscribeSomeoneElse().
+ *
+ * @method _setupSubscribeSomeoneElse
+ */
+BugSubscribersLoader.prototype._setupSubscribeSomeoneElse = function() {
+ var loader = this;
+ var config = {
+ header: 'Subscribe someone else',
+ step_title: 'Search',
+ picker_activator: this.subscribe_someone_else_link
+ };
+ config.save = function(result) {
+ var person_uri = Y.lp.client.get_absolute_uri(result.api_uri);
+ loader.lp_client.get(person_uri, {
+ on: {
+ success: function(person) {
+ loader._subscribeSomeoneElse(person);
+ },
+ failure: function() {
+ // Failed to get person/team details, thus
+ // they have not been subscribed.
+ }
+ } });
+ };
+ var picker = Y.lp.app.picker.create('ValidPersonOrTeam', config);
+}
+
+/**
+ * Subscribe a person or a team to the bug.
+ *
+ * This is a callback for the subscribe someone else picker.
+ *
+ * @method _subscribeSomeoneElse
+ * @param person {Object} Representation of a person returned by the API.
+ */
+BugSubscribersLoader.prototype._subscribeSomeoneElse = function(person) {
+ var subscriber = person.getAttrs();
+ this.subscribers_list.addSubscriber(subscriber, 'Discussion');
+ this.subscribers_list.indicateSubscriberActivity(subscriber);
+
+ var loader = this;
+
+ function on_success() {
+ loader.subscribers_list.stopSubscriberActivity(subscriber, true);
+ loader._addUnsubscribeLinkIfTeamMember(subscriber);
+ }
+ function on_failure() {
+ loader.subscribers_list.stopSubscriberActivity(
+ subscriber, false, function() {
+ loader.subscribers_list.removeSubscriber(subscriber);
+ }
+ );
+ }
+ var config = {
+ on: { success: on_success,
+ failure: on_failure },
+ parameters: { person: subscriber.self_link } };
+ this.lp_client.named_post(this.bug.self_link, 'subscribe', config);
+}
+
+/**
+ * Add unsubscribe link for a team if the currently logged in user
+ * is member of the team.
+ *
+ * @method _addUnsubscribeLinkIfTeamMember
+ * @param team {Object} A person object as returned via API.
+ */
+BugSubscribersLoader.prototype
+._addUnsubscribeLinkIfTeamMember = function(team) {
+ if (Y.Lang.isString(LP.links.me) && team.is_team) {
+ var loader = this;
+ function on_success(members) {
+ var team_member = false;
+ var i;
+ for (i=0; i<members.entries.length; i++) {
+ if (members.entries[i].get('member_link') ===
+ Y.lp.client.get_absolute_uri(LP.links.me)) {
+ team_member = true;
+ break;
+ }
+ }
+ if (team_member === true) {
+ // Add unsubscribe action for the team member.
+ loader.subscribers_list.addUnsubscribeAction(
+ team, loader._getUnsubscribeCallback());
+ }
+ }
+
+ var config = {
+ on: { success: on_success }
+ };
+
+ var members_link = team.members_details_collection_link;
+ this.lp_client.get(members_link, config);
+ }
+}
+
/**
* Manages entire subscribers' list for a single bug.
@@ -893,4 +1033,5 @@
};
-}, "0.1", {"requires": ["node", "lazr.anim", "lp.client", "lp.names"]});
+}, "0.1", {"requires": ["node", "lazr.anim", "lp.app.picker", "lp.client",
+ "lp.names"]});
=== modified file 'lib/lp/bugs/templates/bugtask-index.pt'
--- lib/lp/bugs/templates/bugtask-index.pt 2011-06-10 13:58:29 +0000
+++ lib/lp/bugs/templates/bugtask-index.pt 2011-06-10 13:58:31 +0000
@@ -59,7 +59,8 @@
container_box: '#other-bug-subscribers',
bug: LP.cache.bug,
subscribers_details_view:
- '/+bug-portlet-subscribers-details'
+ '/+bug-portlet-subscribers-details',
+ subscribe_someone_else_link: '.menu-link-addsubscriber'
});
});
});
Follow ups