launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #05101
[Merge] lp:~stevenk/launchpad/private-bug-unsubscribe-confirm-2 into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/private-bug-unsubscribe-confirm-2 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #485126 in Launchpad itself: "Accidentally unsubscribing myself from a private bug makes the bug inaccessible"
https://bugs.launchpad.net/launchpad/+bug/485126
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/private-bug-unsubscribe-confirm-2/+merge/77091
Building on the work started in https://code.launchpad.net/~stevenk/launchpad/private-bug-unsubscribe-confirm/+merge/76326, this branch adds the private bug unsubscribe warning to the edit subscriptions overlay.
--
https://code.launchpad.net/~stevenk/launchpad/private-bug-unsubscribe-confirm-2/+merge/77091
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/private-bug-unsubscribe-confirm-2 into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bug.py'
--- lib/lp/bugs/browser/bug.py 2011-09-25 23:43:15 +0000
+++ lib/lp/bugs/browser/bug.py 2011-09-27 04:44:27 +0000
@@ -664,6 +664,7 @@
LaunchpadView.initialize(self)
cache = IJSONRequestCache(self.request).objects
self.extractBugSubscriptionDetails(self.user, self.context, cache)
+ cache['bug_is_private'] = self.context.private
if self.user:
cache['notifications_text'] = self.notifications_text
=== modified file 'lib/lp/bugs/javascript/bug_subscription_portlet.js'
--- lib/lp/bugs/javascript/bug_subscription_portlet.js 2011-09-21 04:24:04 +0000
+++ lib/lp/bugs/javascript/bug_subscription_portlet.js 2011-09-27 04:44:27 +0000
@@ -200,64 +200,102 @@
overlay.destroy();
link.replaceClass('spinner', 'edit');
};
+ // The on-click handler for make_action nodes.
+ var make_action_on_click = function (
+ e, method_name, css_class, parameters) {
+ var active_link = e.currentTarget;
+ active_link.replaceClass(css_class, 'spinner');
+ var handler = new Y.lp.client.ErrorHandler();
+ handler.showError = function(error_msg) {
+ Y.lp.app.errors.display_error(
+ active_link.get('parentNode'), error_msg);
+ };
+ handler.clearProgressUI = function () {
+ active_link.replaceClass('spinner', css_class);
+ };
+ var config = {
+ on: {
+ success: function(response) {
+ if (Y.Lang.isValue(response)) {
+ // This is a subscription. Update the cache.
+ LP.cache.subscription = response.getAttrs();
+ }
+ if (method_name === 'mute') {
+ // Special case: update main mute link.
+ mute_link.replaceClass(
+ UNMUTED_CLASS, MUTED_CLASS);
+ mute_link.set('text', 'Unmute bug mail');
+ Y.lp.anim.green_flash(
+ { node: mute_link.get('parentNode') }).run();
+ } else if (method_name === 'unsubscribe') {
+ // Special case: delete cache.
+ delete LP.cache.subscription;
+ if (!LP.cache.other_subscription_notifications) {
+ // Special case: hide mute link.
+ mute_div.addClass('hidden');
+ }
+ } else if (method_name === 'subscribe') {
+ // Special case: reveal mute link.
+ mute_div.removeClass('hidden');
+ }
+ active_link.replaceClass('spinner', css_class);
+ update_subscription_status();
+ clean_up();
+ },
+ failure: handler.getFailureHandler()
+ },
+ parameters: parameters
+ };
+ lp_client().named_post(
+ LP.cache.context.bug_link, method_name, config);
+ };
// The make_action function is the workhorse for creating all the
// JavaScript action links we need. Given the `text` that the link
// should display, the `class` name to show the appropriate sprite,
// the `method_name` to call on the server, and the `parameters` to
// send across, it returns a link node with the click handler properly
// set.
- // XXX StevenK 2011-09-26 bug=485126 We should expand the overlay here
- // and ask for confirmation if it's a private bug.
var make_action = function(text, css_class, method_name, parameters) {
result = make_link(text, css_class)
.addClass('js-action');
result.on('click', function (e) {
e.halt();
- var active_link = e.currentTarget;
- active_link.replaceClass(css_class, 'spinner');
- var handler = new Y.lp.client.ErrorHandler();
- handler.showError = function(error_msg) {
- Y.lp.app.errors.display_error(
- active_link.get('parentNode'), error_msg);
- };
- handler.clearProgressUI = function () {
- active_link.replaceClass('spinner', css_class);
- };
- var config = {
- on: {
- success: function(response) {
- if (Y.Lang.isValue(response)) {
- // This is a subscription. Update the cache.
- LP.cache.subscription = response.getAttrs();
- }
- if (method_name === 'mute') {
- // Special case: update main mute link.
- mute_link.replaceClass(
- UNMUTED_CLASS, MUTED_CLASS);
- mute_link.set('text', 'Unmute bug mail');
- Y.lp.anim.green_flash(
- { node: mute_link.get('parentNode') }).run();
- } else if (method_name === 'unsubscribe') {
- // Special case: delete cache.
- delete LP.cache.subscription;
- if (!LP.cache.other_subscription_notifications) {
- // Special case: hide mute link.
- mute_div.addClass('hidden');
- }
- } else if (method_name === 'subscribe') {
- // Special case: reveal mute link.
- mute_div.removeClass('hidden');
- }
- active_link.replaceClass('spinner', css_class);
- update_subscription_status();
- clean_up();
- },
- failure: handler.getFailureHandler()
- },
- parameters: parameters
- };
- lp_client().named_post(
- LP.cache.context.bug_link, method_name, config);
+ var method_call = function() {
+ make_action_on_click(e, method_name, css_class, parameters);
+ };
+ if (method_name === 'unsubscribe') {
+ var private_bug_warning_node = Y.Node.create(
+ ['<div class="private-bug-warning"><p>You will not ',
+ 'have access to this bug or any of its pages if you ',
+ 'unsubscribe. If you want to stop emails, choose the ',
+ '"Mute bug mail" option.</p>',
+ '<p>Do you really want to unsubscribe from this bug?',
+ '</p><div class="extra-form-buttons">',
+ '<button class="lazr-pos lazr-btn ok-btn" ',
+ 'type="submit"></button>',
+ '<button class="lazr-neg lazr-btn cancel-btn" ',
+ 'type="button"></button></div></div>'].join(''));
+ if (
+ Y.Lang.isBoolean(LP.cache.bug_is_private) &&
+ LP.cache.bug_is_private) {
+ var remove_div = Y.one('.remove-direct-subscription');
+ var ok_btn = private_bug_warning_node.one('.ok-btn');
+ ok_btn.on('click', function (internal_e) {
+ e.halt();
+ method_call();
+ });
+ var cancel_btn = private_bug_warning_node.one(
+ '.cancel-btn');
+ cancel_btn.on('click', function() {
+ private_bug_warning_node.remove();
+ });
+ remove_div.insert(private_bug_warning_node, 'after');
+ } else {
+ method_call();
+ }
+ } else {
+ method_call();
+ }
});
return result;
};
@@ -320,6 +358,7 @@
// has an existing direct subscription.
var unsubscribe_node = tag('div')
.setStyle('margin-top', '1.5em')
+ .addClass('remove-direct-subscription')
.append(make_action(
'Remove your direct subscription', 'remove',
'unsubscribe', {})
=== modified file 'lib/lp/bugs/javascript/tests/test_bug_subscription_portlet.js'
--- lib/lp/bugs/javascript/tests/test_bug_subscription_portlet.js 2011-06-21 05:37:38 +0000
+++ lib/lp/bugs/javascript/tests/test_bug_subscription_portlet.js 2011-09-27 04:44:27 +0000
@@ -553,6 +553,9 @@
this.link().simulate('click');
var overlay = Y.one('.pretty-overlay-window');
overlay.one('a.remove').simulate('click');
+ // There is no warning.
+ var warning = overlay.one('.private-bug-warning');
+ Y.Assert.isNull(warning);
// We got an appropriate call to the webservice.
Y.Assert.areEqual('named_post', module._lp_client.received[0][0]);
var args = module._lp_client.received[0][1];
@@ -570,6 +573,46 @@
this.status_node.get('text'));
},
+ test_unsubscribe_from_private_bug: function() {
+ this.init(LIFECYCLE, false);
+ window.LP.cache.bug_is_private = true;
+ this.link().simulate('click');
+ var overlay = Y.one('.pretty-overlay-window');
+ overlay.one('a.remove').simulate('click');
+ // The overlay now has a warning.
+ var warning = overlay.one('.private-bug-warning');
+ Y.Assert.isTrue(Y.Lang.isValue(warning));
+ // Find and click the OK button.
+ var ok_btn = warning.one('.ok-btn');
+ ok_btn.simulate('click');
+ // We got an appropriate call to the webservice.
+ Y.Assert.areEqual('named_post', module._lp_client.received[0][0]);
+ var args = module._lp_client.received[0][1];
+ Y.Assert.areEqual(this.bug_link, args[0]);
+ Y.Assert.areEqual('unsubscribe', args[1]);
+ Y.ObjectAssert.areEqual({}, args[2].parameters);
+ // The overlay has been destroyed, and the spinner is gone.
+ Y.Assert.isFalse(Y.Lang.isValue(Y.one('.pretty-overlay-window')));
+ Y.Assert.isFalse(this.link().hasClass('spinner'));
+ },
+
+ test_unsubscribe_from_private_bug_cancel: function() {
+ this.init(LIFECYCLE, false);
+ window.LP.cache.bug_is_private = true;
+ this.link().simulate('click');
+ var overlay = Y.one('.pretty-overlay-window');
+ overlay.one('a.remove').simulate('click');
+ // The overlay now has a warning.
+ var warning = overlay.one('.private-bug-warning');
+ Y.Assert.isTrue(Y.Lang.isValue(warning));
+ // Find and click the Cancel button.
+ var cancel_btn = warning.one('.cancel-btn');
+ cancel_btn.simulate('click');
+ // The warning is gone.
+ var warning = overlay.one('.private-bug-warning');
+ Y.Assert.isNull(warning);
+ },
+
test_unsubscribe_with_other: function() {
this.init(LIFECYCLE, true);
this.link().simulate('click');