39
39
var privacy_spinner;
40
40
var link_branch_link;
42
// The set of subscriber CSS IDs as a JSON struct.
45
// A boolean telling us whether advanced subscription features are to be
47
// XXX 2011-01-14 gmb bug=702859:
48
// We need to expose feature flags via the API to avoid this kind of
50
var use_advanced_subscriptions = false;
51
var subscription_labels = Y.lp.bugs.subscriber.subscription_labels;
54
* An object representing the bugtask subscribers portlet.
56
* Since the portlet loads via XHR and inline subscribing
57
* depends on that portlet being loaded, setup a custom
58
* event object, to provide a hook for initializing subscription
59
* link callbacks after custom events.
61
var PortletTarget = function() {};
62
Y.augment(PortletTarget, Y.Event.Target);
63
namespace.portlet = new PortletTarget();
65
function setup_portlet_handlers() {
66
namespace.portlet.subscribe('bugs:portletloaded', function() {
67
load_subscriber_ids();
69
namespace.portlet.subscribe('bugs:dupeportletloaded', function() {
70
setup_unsubscribe_icon_handlers();
73
* If the subscribers portlet fails to load, clear any
74
* click handlers, so the normal subscribe page can be reached.
76
namespace.portlet.subscribe('bugs:portletloadfailed', function(handlers) {
77
if (Y.Lang.isArray(handlers)) {
78
var click_handler = handlers[0];
79
click_handler.detach();
82
/* If the dupe subscribers portlet fails to load,
83
* be sure to try to handle any unsub icons that may
86
namespace.portlet.subscribe(
87
'bugs:dupeportletloadfailed',
89
setup_unsubscribe_icon_handlers();
92
/* If loading the subscriber IDs JSON has succeeded, set up the
93
* subscription link handlers and load the subscribers from dupes.
95
namespace.portlet.subscribe(
96
'bugs:portletsubscriberidsloaded',
98
setup_subscription_link_handlers();
99
load_subscribers_from_duplicates();
102
/* If loading the subscriber IDs JSON fails we still need to load the
103
* subscribers from duplicates but we don't set up the subscription link
106
namespace.portlet.subscribe(
107
'bugs:portletsubscriberidsfailed',
109
load_subscribers_from_duplicates();
113
* Subscribing someone else requires loading a grayed out
114
* username into the DOM until the subscribe action completes.
115
* There are a couple XHR requests in check_can_be_unsubscribed
116
* before the subscribe work can be done, so fire a custom event
117
* bugs:nameloaded and do the work here when the event fires.
119
namespace.portlet.subscribe('bugs:nameloaded', function(subscription) {
120
var error_handler = new LP.client.ErrorHandler();
121
error_handler.clearProgressUI = function() {
122
var temp_link = Y.one('#temp-username');
124
var temp_parent = temp_link.get('parentNode');
125
temp_parent.removeChild(temp_link);
128
error_handler.showError = function(error_msg) {
129
Y.lp.app.errors.display_error(
130
Y.one('.menu-link-addsubscriber'), error_msg);
135
success: function() {
136
var temp_link = Y.one('#temp-username');
137
var temp_spinner = Y.one('#temp-name-spinner');
138
temp_link.removeChild(temp_spinner);
139
var anim = Y.lazr.anim.green_flash({ node: temp_link });
140
anim.on('end', function() {
141
add_user_name_link(subscription);
142
var temp_parent = temp_link.get('parentNode');
143
temp_parent.removeChild(temp_link);
147
failure: error_handler.getFailureHandler()
150
person: LP.client.get_absolute_uri(
151
subscription.get('person').get('escaped_uri')),
152
suppress_notify: false
155
lp_client.named_post(bug_repr.self_link, 'subscribe', config);
159
42
namespace.setup_bugtask_index = function() {
160
setup_portlet_handlers();
43
Y.lp.bugs.bugtask_index.portlets.setup_portlet_handlers();
162
46
* Check the page for links related to overlay forms and request the HTML
163
47
* for these forms.
278
* Initialize click handler for the subscribe someone else link.
280
* @method setup_subscribe_someone_else_handler
281
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
283
function setup_subscribe_someone_else_handler(subscription) {
285
header: 'Subscribe someone else',
286
step_title: 'Search',
287
picker_activator: '.menu-link-addsubscriber'
290
config.save = function(result) {
291
subscribe_someone_else(result, subscription);
293
var picker = Y.lp.app.picker.create('ValidPersonOrTeam', config);
298
* Handle the advanced_subscription_overlay's form submissions.
300
* @method handle_advanced_subscription_overlay
301
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
302
* @param form_data {Object} The data from the submitted form.
304
function handle_advanced_subscription_overlay(subscription, form_data) {
305
var link = subscription.get('link');
306
var link_parent = link.get('parentNode');
307
if (link_parent.hasClass('subscribed-false') &&
308
link_parent.hasClass('dup-subscribed-false')) {
309
// The user isn't subscribed, so subscribe them.
311
'bug_notification_level',
312
form_data['field.bug_notification_level']);
313
subscribe_current_user(subscription);
315
form_data['field.subscription'] == 'update-subscription') {
316
// The user is already subscribed and wants to update their
318
setup_client_and_bug();
319
var person_name = subscription.get('person').get('name');
320
var subscription_url =
321
lp_bug_entry.get('self_link') + '/+subscription/' +
325
success: function(lp_subscription) {
326
subscription.enable_spinner('Updating subscription...');
328
'bug_notification_level',
329
form_data['field.bug_notification_level'][0])
332
success: function(e) {
333
subscription.disable_spinner(
334
'Edit subscription');
335
var anim = Y.lazr.anim.green_flash({
340
failure: function(e) {
341
subscription.disable_spinner(
342
'Edit subscription');
343
var anim = Y.lazr.anim.red_flash({
350
lp_subscription.lp_save(save_config);
354
lp_client.get(subscription_url, config);
356
// The user is already subscribed and wants to unsubscribe.
357
unsubscribe_current_user(subscription);
363
* Create and return a FormOverlay for advanced subscription
366
* @method setup_advanced_subscription_overlay
367
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
369
function setup_advanced_subscription_overlay(subscription) {
370
var subscription_overlay = new Y.lazr.FormOverlay({
371
headerContent: '<h2>Subscribe to bug</h2>',
373
Y.Node.create(submit_button_html),
375
Y.Node.create(cancel_button_html),
379
subscription_overlay.set(
380
'form_submit_callback', function(form_data) {
381
handle_advanced_subscription_overlay(subscription, form_data);
382
subscription_overlay.hide();
385
var subscription_link_url = subscription.get(
386
'link').get('href') + '/++form++';
387
subscription_overlay.loadFormContentAndRender(
388
subscription_link_url);
389
subscription_overlay.render('#privacy-form-container');
390
return subscription_overlay
395
* Initialize callbacks for subscribe/unsubscribe links.
397
* @method setup_subscription_link_handlers
399
function setup_subscription_link_handlers() {
400
if (LP.client.links.me === undefined) {
404
setup_client_and_bug();
405
var subscription = new Y.lp.bugs.subscriber.Subscription({
406
link: Y.one('.menu-link-subscription'),
407
spinner: Y.one('#sub-unsub-spinner'),
408
subscriber: new Y.lp.bugs.subscriber.Subscriber({
409
uri: LP.client.links.me,
410
subscriber_ids: subscriber_ids
414
var is_direct = subscription.get(
415
'link').get('parentNode').hasClass('subscribed-true');
416
var has_dupes = subscription.get(
417
'link').get('parentNode').hasClass('dup-subscribed-true');
418
subscription.set('is_direct', is_direct);
419
subscription.set('has_dupes', has_dupes);
421
if (subscription.is_node()) {
422
subscription.get('link').on('click', function(e) {
424
subscription.set('can_be_unsubscribed', true);
425
subscription.set('person', subscription.get('subscriber'));
426
subscription.set('is_team', false);
427
var parent = e.target.get('parentNode');
428
if (namespace.use_advanced_subscriptions) {
429
var subscription_overlay =
430
setup_advanced_subscription_overlay(subscription);
431
subscription_overlay.show();
433
// Look for the false conditions of subscription, which
434
// is_direct_subscription, etc. don't report correctly,
435
// to make sure we only use subscribe_current_user for
437
if (parent.hasClass('subscribed-false') &&
438
parent.hasClass('dup-subscribed-false')) {
439
subscribe_current_user(subscription);
442
unsubscribe_current_user(subscription);
446
subscription.get('link').addClass('js-action');
449
setup_subscribe_someone_else_handler(subscription);
453
* Set click handlers for unsubscribe remove icons.
455
* @method setup_unsubscribe_icon_handlers
456
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
458
function setup_unsubscribe_icon_handlers() {
459
var subscription = new Y.lp.bugs.subscriber.Subscription({
460
link: Y.one('.menu-link-subscription'),
461
spinner: Y.one('#sub-unsub-spinner'),
462
subscriber: new Y.lp.bugs.subscriber.Subscriber({
463
uri: LP.client.links.me,
464
subscriber_ids: subscriber_ids
468
Y.on('click', function(e) {
470
unsubscribe_user_via_icon(e.target, subscription);
475
162
* Create the lp client and bug entry if we haven't done so already.
477
164
* @method setup_client_and_bug
850
537
Y.fire('lp:branch-linked', bug_branch_node);
854
* Traverse the DOM of a given remove icon to find
855
* the user's link. Returns a URI of the form "/~username".
857
* @method get_user_uri_from_icon
858
* @param icon {Node} The node representing a remove icon.
859
* @return user_uri {String} The user's uri, without the hostname.
861
function get_user_uri_from_icon(icon) {
862
var parent_div = icon.get('parentNode').get('parentNode');
863
// This should be parent_div.firstChild, but because of #text
864
// and cross-browser issues, using the YUI query syntax is
866
var user_uri = parent_div.one('a').getAttribute('href');
868
// Strip the domain off. We just want a path.
869
var host_start = user_uri.indexOf('//');
870
if (host_start != -1) {
871
var host_end = user_uri.indexOf('/', host_start+2);
872
return user_uri.substring(host_end, user_uri.length);
880
* Build the HTML for a user link for the subscribers list.
882
* @method build_user_link_html
883
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
884
* @return html {String} The HTML used for creating a subscriber link.
886
function build_user_link_html(subscription) {
887
var name = subscription.get('person').get('name');
888
var css_name = subscription.get('person').get('css_name');
889
var full_name = subscription.get('person').get('full_display_name');
890
// Be paranoid about display_name, since timeouts or other errors
891
// could mean display_name wasn't set on initialization.
892
if (subscription.get('person').get('display_name') === '') {
893
subscription.get('person').set_display_name();
895
var display_name = subscription.get('person').get('display_name');
899
display_name: display_name,
903
if (subscription.is_current_user_subscribing()) {
904
terms.subscribed_by = 'themselves';
906
terms.subscribed_by = 'by ' + full_name;
909
var html = Y.Node.create('<div><a></a></div>');
910
html.addClass(terms.css_name);
912
if (subscription.is_direct_subscription()) {
913
html.set('id', 'direct-' + terms.css_name);
915
html.set('id', 'dupe-' + terms.css_name);
919
.set('href', '/~' + terms.name)
920
.set('name', terms.full_name)
921
.set('title', 'Subscribed ' + terms.subscribed_by);
924
if (subscription.is_team()) {
925
span = '<span class="sprite team"></span>';
927
span = '<span class="sprite person"></span>';
931
.appendChild(Y.Node.create(span))
932
.appendChild(document.createTextNode(terms.display_name));
934
// Add remove icon if the current user can unsubscribe the subscriber.
935
if (subscription.can_be_unsubscribed_by_user()) {
936
var icon_html = Y.Node.create(
937
'<a href="+subscribe">' +
938
'<img class="unsub-icon" src="/@@/remove" alt="Remove" /></a>');
940
.set('id', 'unsubscribe-' + terms.css_name)
941
.set('title', 'Unsubscribe ' + terms.full_name);
943
.set('id', 'unsubscribe-icon-' + terms.css_name);
944
html.appendChild(icon_html);
951
* Used to remove the user's name from the subscriber's list.
953
* @method remove_user_name_link
954
* @param user_node {Node} Node representing the user name link.
956
function remove_user_name_link(user_node) {
957
var parent = user_node.get('parentNode');
958
parent.removeChild(user_node);
962
* Returns the next node in alphabetical order after the subscriber
963
* node now being added. No node is returned to append to end of list.
965
* The name can appear in one of two different lists. 1) The list of
966
* subscribers that can be unsubscribed by the current user, and
967
* 2) the list of subscribers that cannont be unsubscribed.
969
* @method get_next_subscriber_node
970
* @param subscription_link {Node} The sub/unsub link.
971
* @return {Node} The node appearing next in the subscriber list or
972
* undefined if no node is next.
974
function get_next_subscriber_node(subscription) {
975
var full_name = subscription.get('person').get('full_display_name');
976
var can_be_unsubscribed = subscription.can_be_unsubscribed_by_user();
977
var nodes_by_name = {};
978
var unsubscribables = [];
979
var not_unsubscribables = [];
981
// Use the list of subscribers pulled from the DOM to have sortable
982
// lists of unsubscribable vs. not unsubscribale person links.
983
var all_subscribers = Y.all('#subscribers-links div');
984
if (all_subscribers.size() > 0) {
985
all_subscribers.each(function(sub_link) {
986
if (sub_link.getAttribute('id') != 'temp-username') {
987
// User's displayname is found via the link's "name"
989
var sub_link_name = sub_link.one('a').getAttribute('name');
990
nodes_by_name[sub_link_name] = sub_link;
991
if (sub_link.one('img.unsub-icon')) {
992
unsubscribables.push(sub_link_name);
994
not_unsubscribables.push(sub_link_name);
999
// Add the current subscription.
1000
if (can_be_unsubscribed) {
1001
unsubscribables.push(full_name);
1003
not_unsubscribables.push(full_name);
1005
unsubscribables.sort();
1006
not_unsubscribables.sort();
1008
// If there is no all_subscribers, then we're dealing with
1009
// the printed None, so return.
1014
if ((!unsubscribables && !not_unsubscribables) ||
1015
// If A) neither list exists, B) the user belongs in the second
1016
// list but the second list doesn't exist, or C) user belongs in the
1017
// first list and the second doesn't exist, return no node to append.
1018
(!can_be_unsubscribed && !not_unsubscribables) ||
1019
(can_be_unsubscribed && unsubscribables && !not_unsubscribables)) {
1022
// If the user belongs in the first list, and the first list
1023
// doesn't exist, but the second one does, return the first node
1024
// in the second list.
1025
can_be_unsubscribed && !unsubscribables && not_unsubscribables) {
1026
return nodes_by_name[not_unsubscribables[0]];
1027
} else if (can_be_unsubscribed) {
1028
// If the user belongs in the first list, loop the list for position.
1029
for (i=0; i<unsubscribables.length; i++) {
1030
if (unsubscribables[i] == full_name) {
1031
if (i+1 < unsubscribables.length) {
1032
return nodes_by_name[unsubscribables[i+1]];
1033
// If the current link should go at the end of the first
1034
// list and we're at the end of that list, return the
1035
// first node of the second list. Due to earlier checks
1036
// we can be sure this list exists.
1037
} else if (i+1 >= unsubscribables.length) {
1038
return nodes_by_name[not_unsubscribables[0]];
1042
} else if (!can_be_unsubscribed) {
1043
// If user belongs in the second list, loop the list for position.
1044
for (i=0; i<not_unsubscribables.length; i++) {
1045
if (not_unsubscribables[i] == full_name) {
1046
if (i+1 < not_unsubscribables.length) {
1047
return nodes_by_name[not_unsubscribables[i+1]];
1057
* Add the user name to the subscriber's list.
1059
* @method add_user_name_link
1061
function add_user_name_link(subscription) {
1062
var person = subscription.get('person');
1063
var link_node = build_user_link_html(subscription);
1064
var subscribers = Y.one('#subscribers-links');
1065
if (subscription.is_current_user_subscribing()) {
1066
// If this is the current user, then top post the name and be done.
1067
subscribers.insertBefore(link_node, subscribers.get('firstChild'));
1069
var next = get_next_subscriber_node(subscription);
1071
subscribers.insertBefore(link_node, next);
1073
// Handle the case of the displayed "None".
1074
var none_subscribers = Y.one('#none-subscribers');
1075
if (none_subscribers) {
1076
var none_parent = none_subscribers.get('parentNode');
1077
none_parent.removeChild(none_subscribers);
1079
subscribers.appendChild(link_node);
1083
// Set the click handler if adding a remove icon.
1084
if (subscription.can_be_unsubscribed_by_user()) {
1086
Y.one('#unsubscribe-icon-' + person.get('css_name'));
1087
remove_icon.on('click', function(e) {
1089
unsubscribe_user_via_icon(e.target, subscription);
1095
* Add a grayed out, temporary user name when subscribing
1098
* @method add_temp_user_name
1099
* @param subscription_link {Node} The sub/unsub link.
1101
function add_temp_user_name(subscription) {
1102
// Be paranoid about display_name, since timeouts or other errors
1103
// could mean display_name wasn't set on initialization.
1104
if (subscription.get('person').get('display_name') === '') {
1105
subscription.get('person').set_display_name();
1107
var display_name = subscription.get('person').get('display_name');
1109
if (subscription.is_team()) {
1110
img_src = '/@@/teamgray';
1112
img_src = '/@@/persongray';
1115
// The <span>...</span> below must *not* be <span/>. On FF (maybe
1116
// others, but at least on FF 3.0.11) will then not notice any
1117
// following sibling nodes, like the spinner image.
1118
var link_node = Y.Node.create([
1119
'<div id="temp-username"> ',
1120
' <img alt="" width="14" height="14" />',
1121
' <span>Other Display Name</span>',
1122
' <img id="temp-name-spinner" src="/@@/spinner" alt="" ',
1123
' style="position:absolute;right:8px" /></div>'].join(''));
1124
link_node.one('img').set('src', img_src);
1125
link_node.replaceChild(
1126
document.createTextNode(display_name),
1127
link_node.one('span'));
1129
var subscribers = Y.one('#subscribers-links');
1130
var next = get_next_subscriber_node(subscription);
1132
subscribers.insertBefore(link_node, next);
1134
// Handle the case of the displayed "None".
1135
var none_subscribers = Y.one('#none-subscribers');
1136
if (none_subscribers) {
1137
var none_parent = none_subscribers.get('parentNode');
1138
none_parent.removeChild(none_subscribers);
1140
subscribers.appendChild(link_node);
1143
// Fire a custom event to know it's safe to begin
1144
// any actual subscribing work.
1145
namespace.portlet.fire('bugs:nameloaded', subscription);
1149
* Add the "None" div to the subscribers list if
1150
* there aren't any subscribers left.
1152
* @method set_none_for_empty_subscribers
1154
function set_none_for_empty_subscribers() {
1155
var subscriber_list = Y.one('#subscribers-links');
1156
// Assume if subscriber_list has no child divs
1157
// then the list of subscribers is empty.
1158
if (!Y.Lang.isValue(subscriber_list.one('div')) &&
1159
!Y.Lang.isValue(Y.one('#none-subscribers'))) {
1160
var none_div = Y.Node.create('<div id="none-subscribers">None</div>');
1161
subscriber_list.appendChild(none_div);
1164
// Clear the empty duplicate subscribers list if it exists.
1165
var dup_list = Y.one('#subscribers-from-duplicates');
1166
if (Y.Lang.isValue(dup_list) &&
1167
!Y.Lang.isValue(dup_list.one('div'))) {
1168
var parent = dup_list.get('parentNode');
1169
parent.removeChild(dup_list);
1174
* Set the class on subscription link's parentNode.
1176
* This is used to reset the class used by the
1177
* click handler to know which link was clicked.
1179
* @method set_subscription_link_parent_class
1180
* @param subscription_link {Node} The sub/unsub link.
1181
* @param subscribed {Boolean} The sub/unsub'ed flag for the class.
1182
* @param dupe_subscribed {Boolean} The sub/unsub'ed flag for dupes
1185
function set_subscription_link_parent_class(
1186
user_link, subscribed, dupe_subscribed) {
1188
var parent = user_link.get('parentNode');
1190
parent.removeClass('subscribed-false');
1191
parent.addClass('subscribed-true');
1193
parent.removeClass('subscribed-true');
1194
parent.addClass('subscribed-false');
1197
if (dupe_subscribed) {
1198
parent.removeClass('dup-subscribed-false');
1199
parent.addClass('dup-subscribed-true');
1201
parent.removeClass('dup-subscribed-true');
1202
parent.addClass('dup-subscribed-false');
1207
* Unsubscribe a user from this bugtask when a remove icon is clicked.
1209
* @method unsubscribe_user_via_icon
1210
* @param icon {Node} The remove icon that was clicked.
1211
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
1213
function unsubscribe_user_via_icon(icon, subscription) {
1214
icon.set('src', '/@@/spinner');
1215
var icon_parent = icon.get('parentNode');
1217
var user_uri = get_user_uri_from_icon(icon);
1218
var person = new Y.lp.bugs.subscriber.Subscriber({
1220
subscriber_ids: subscriber_ids
1222
subscription.set('person', person);
1224
// Determine if this is a dupe.
1226
var icon_parent_div = icon_parent.get('parentNode');
1227
var dupe_id = 'dupe-' + person.get('css_name');
1228
if (icon_parent_div.get('id') == dupe_id) {
1234
var error_handler = new LP.client.ErrorHandler();
1235
error_handler.clearProgressUI = function () {
1236
icon.set('src', '/@@/remove');
1237
// Grab the icon again to reset to click handler.
1238
var unsubscribe_icon = Y.one(
1239
'#unsubscribe-icon-' + person.get('css_name'));
1240
unsubscribe_icon.on('click', function(e) {
1242
unsubscribe_user_via_icon(e.target, subscription);
1246
error_handler.showError = function (error_msg) {
1247
var flash_node = Y.one('.' + person.get('css_name'));
1248
Y.lp.app.errors.display_error(flash_node, error_msg);
1252
var subscription_link = subscription.get('link');
1255
success: function(client) {
1256
icon_parent.removeChild(icon);
1257
var anim = Y.lazr.anim.green_flash({ node: icon_parent_div });
1258
anim.on('end', function(e) {
1259
remove_user_name_link(icon_parent_div);
1260
set_none_for_empty_subscribers();
1261
var person_link = Y.one('.' + person.get('css_name'));
1262
if (Y.Lang.isNull(person_link) &&
1263
subscription.is_current_user_subscribing()) {
1264
// Current user has been completely unsubscribed.
1265
subscription.disable_spinner(
1266
subscription_labels.SUBSCRIBE);
1267
set_subscription_link_parent_class(
1268
subscription_link, false, false);
1269
subscription.set('is_direct', false);
1270
subscription.set('has_dupes', false);
1273
// A direct subscription remains.
1274
set_subscription_link_parent_class(
1275
subscription_link, true, false);
1276
subscription.set('is_direct', true);
1277
subscription.set('has_dupes', false);
1279
// A dupe subscription remains.
1280
set_subscription_link_parent_class(
1281
subscription_link, false, true);
1282
subscription.set('is_direct', false);
1283
subscription.set('has_dupes', true);
1290
failure: error_handler.getFailureHandler()
1294
if (!subscription.is_current_user_subscribing()) {
1295
config.parameters = {
1296
person: LP.client.get_absolute_uri(user_uri)
1301
lp_client.named_post(
1302
bug_repr.self_link, 'unsubscribeFromDupes', config);
1304
lp_client.named_post(bug_repr.self_link, 'unsubscribe', config);
1309
* Subscribe the current user via the LP API.
1311
* @method subscribe_current_user
1312
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
1314
function subscribe_current_user(subscription) {
1315
subscription.enable_spinner('Subscribing...');
1316
var subscription_link = subscription.get('link');
1317
var subscriber = subscription.get('subscriber');
1318
var bug_notification_level = subscription.get('bug_notification_level');
1320
var error_handler = new LP.client.ErrorHandler();
1321
error_handler.clearProgressUI = function () {
1322
subscription.disable_spinner();
1324
error_handler.showError = function (error_msg) {
1325
Y.lp.app.errors.display_error(subscription_link, error_msg);
1330
success: function(client) {
1331
if (namespace.use_advanced_subscriptions) {
1332
subscription.disable_spinner(
1333
subscription_labels.EDIT);
1335
subscription.disable_spinner(
1336
subscription_labels.UNSUBSCRIBE);
1339
if (subscription.has_duplicate_subscriptions()) {
1340
set_subscription_link_parent_class(
1341
subscription_link, true, true);
1343
set_subscription_link_parent_class(
1344
subscription_link, true, false);
1347
// Handle the case where the subscriber's list displays
1349
var empty_subscribers = Y.one("#none-subscribers");
1350
if (empty_subscribers) {
1351
var parent = empty_subscribers.get('parentNode');
1352
parent.removeChild(empty_subscribers);
1355
add_user_name_link(subscription);
1357
var flash_node = Y.one('.' + subscriber.get('css_name'));
1358
var anim = Y.lazr.anim.green_flash({ node: flash_node });
1362
failure: error_handler.getFailureHandler()
1366
person: LP.client.get_absolute_uri(subscriber.get('escaped_uri')),
1367
suppress_notify: false,
1368
level: bug_notification_level
1371
lp_client.named_post(bug_repr.self_link, 'subscribe', config);
1375
* Unsubscribe the current user via the LP API.
1377
* @method unsubscribe_current_user
1378
* @param subscription {Object} A Y.lp.bugs.subscriber.Subscription object.
1380
function unsubscribe_current_user(subscription) {
1381
subscription.enable_spinner('Unsubscribing...');
1382
var subscription_link = subscription.get('link');
1383
var subscriber = subscription.get('subscriber');
1385
var error_handler = new LP.client.ErrorHandler();
1386
error_handler.clearProgressUI = function () {
1387
subscription.disable_spinner();
1389
error_handler.showError = function (error_msg) {
1390
Y.lp.app.errors.display_error(subscription_link, error_msg);
1395
success: function(client) {
1396
if (subscription.is_direct_subscription() &&
1397
subscription.has_duplicate_subscriptions()) {
1398
// Don't change the 'Unsubscribe' text if
1399
// dupe subscriptions remain.
1400
subscription.disable_spinner();
1401
set_subscription_link_parent_class(
1402
subscription_link, false, true);
1403
subscription.set('is_direct', false);
1404
} else if (subscription.is_direct_subscription() &&
1405
!subscription.has_duplicate_subscriptions()) {
1406
// Only unsub'ing a direct subscriber here.
1407
subscription.disable_spinner(
1408
subscription_labels.SUBSCRIBE);
1409
set_subscription_link_parent_class(
1410
subscription_link, false, false);
1411
subscription.set('is_direct', false);
1413
// Only unsub'ing dupes here.
1414
subscription.disable_spinner(
1415
subscription_labels.SUBSCRIBE);
1416
set_subscription_link_parent_class(
1417
subscription_link, false, false);
1418
subscription.set('has_dupes', false);
1421
var flash_node = Y.one('.' + subscriber.get('css_name'));
1422
var anim = Y.lazr.anim.green_flash({ node: flash_node });
1423
anim.on('end', function(e) {
1424
remove_user_name_link(flash_node);
1425
set_none_for_empty_subscribers();
1430
failure: error_handler.getFailureHandler()
1433
if (subscription.is_direct_subscription()) {
1434
lp_client.named_post(bug_repr.self_link, 'unsubscribe', config);
1436
lp_client.named_post(
1437
bug_repr.self_link, 'unsubscribeFromDupes', config);
1443
542
* Set up a bug task table row.