311
311
add_subscription_overlay.on('cancel', clean_up);
315
* Modify the DOM to insert a link or two into the global actions portlet.
316
* If structural subscriptions already exist then a 'modify' link is
317
* added. Otherwise, just the 'add' link is put into the portlet.
319
* @method setup_subscription_links
320
* @param {String} overlay_id Id of the overlay element.
321
* @param {String} content_box_id Id of the element on the page where
322
* the overlay is anchored.
324
function setup_subscription_links(overlay_id, content_box_id) {
325
// Modify the menu-link-subscribe-to-bug-mail link to be visible.
326
var link = Y.one('.menu-link-subscribe_to_bug_mail');
327
if (!Y.Lang.isValue(link)) {
328
Y.fail('"Subscribe to bug mail" link not found.');
330
link.removeClass('invisible-link');
331
link.addClass('visible-link');
332
link.on('click', function(e) {
333
// Only proceed if the form content is already available.
334
if (add_subscription_overlay) {
336
// We always set up the overlay as a blank canvas, in case it was
338
clear_overlay(Y.one(content_box_id));
339
add_subscription_overlay.show();
342
link.addClass('js-action');
343
} // setup_subscription_links
346
315
* Reset the overlay form to initial values.
348
function clear_overlay(content_node) {
349
set_recipient(content_node, false, undefined);
317
function clear_overlay(content_node, no_recipient_picker) {
318
if (no_recipient_picker) {
319
set_recipient_label(content_node, undefined);
321
set_recipient(content_node, false, undefined);
350
323
content_node.one('[name="name"]').set('value', '');
352
325
content_node, LP.cache.statuses, LP.cache.statuses);
787
760
* the overlay will be anchored.
789
762
namespace.setup_bug_subscriptions = function(config) {
790
validate_config(config);
791
Y.on('domready', function() {
792
if (Y.Lang.isValue(config.lp_client)) {
793
// Tests can specify an lp_client if they want to.
794
namespace.lp_client = config.lp_client;
796
// Setup the Launchpad client.
763
// Return if pre-setup fails.
764
if (!pre_setup(config)) {
800
var overlay_id = setup_overlay(config.content_box, true);
801
var submit_button = Y.Node.create(
802
'<button type="submit" name="field.actions.create" ' +
803
'value="Save Changes" class="lazr-pos lazr-btn" ' +
805
// This is a bit of an odd approach, but it lets us retrofit code
806
// without a large refactoring. When edit_subscription_handler is
807
// called, context.filter_info will have the information about the
808
// filter that is being edited.
810
create_overlay(config.content_box, overlay_id, submit_button,
811
function (form_data) {
812
return edit_subscription_handler(context, form_data);});
813
fill_in_bug_subscriptions(config, context);
814
// We need to initialize the help links. They may have already been
815
// initialized except for the ones we added, so setupHelpTrigger
816
// is idempotent. Notice that this is old MochiKit code.
817
forEach(findHelpLinks(), setupHelpTrigger);
768
fill_in_bug_subscriptions(config);
822
772
* Set up a validator function for a form input field.
823
773
* @method add_input_validator
824
774
* @param {Object} overlay Overlay object.
877
* Sets the recipient label according to the filter on the overlay.
878
* Overlay must not have a recipient picker, but a simple recipient label.
880
function set_recipient_label(content_node, filter_info) {
881
var recipient_label = content_node.one('input[name="recipient"] + span'),
882
teams = LP.cache.administratedTeams;
883
if (filter_info !== undefined && filter_info.subscriber_is_team) {
885
for (i=0; i<teams.length; i++) {
886
if (teams[i].link === filter_info.subscriber_link){
887
recipient_label.set('text', teams[i].title);
892
recipient_label.set('text', 'Yourself');
897
* Sets filter statuses and importances on the overlay based on the filter
900
function set_filter_statuses_and_importances(content_node, filter) {
901
var is_lifecycle = filter.bug_notification_level==='Lifecycle',
902
statuses = filter.statuses,
903
importances = filter.importances;
905
statuses = LP.cache.statuses;
906
importances = LP.cache.importances;
908
// An absence of values is equivalent to all values.
909
if (statuses.length === 0) {
910
statuses = LP.cache.statuses;
912
if (importances.length === 0) {
913
importances = LP.cache.importances;
916
set_checkboxes(content_node, LP.cache.statuses, statuses);
918
content_node, LP.cache.importances, importances);
922
* Sets filter tags and tag matching options in the overlay based on the
925
function set_filter_tags(content_node, filter) {
926
var is_lifecycle = filter.bug_notification_level==='Lifecycle';
927
content_node.one('[name="tags"]').set(
928
'value', is_lifecycle ? '' : filter.tags.join(' '));
930
content_node, [MATCH_ALL, MATCH_ANY],
931
filter.find_all_tags ? MATCH_ALL : MATCH_ANY);
935
* Sets filter notification level radio/check boxes in the overlay
936
* according to the filter data.
938
function set_filter_notification_options(content_node, filter) {
939
var is_lifecycle = filter.bug_notification_level==='Lifecycle',
940
has_advanced_filters = !is_lifecycle && (
941
filter.statuses.length ||
942
filter.importances.length ||
943
filter.tags.length) > 0,
944
filters = has_advanced_filters ? [ADVANCED_FILTER] : [],
945
event = ADDED_OR_CHANGED;
946
// Chattiness: Lifecycle < Details < Discussion.
947
switch (filter.bug_notification_level) {
949
event = ADDED_OR_CLOSED;
953
filters.push(FILTER_COMMENTS);
956
// 'Discussion' case is the default and handled by the declared
957
// values in the code.
959
content_node, [ADDED_OR_CLOSED, ADDED_OR_CHANGED], event);
961
content_node, [FILTER_COMMENTS, ADVANCED_FILTER], filters);
962
handle_change(ADDED_OR_CHANGED, FILTER_WRAPPER, {duration: 0});
963
handle_change(ADVANCED_FILTER, ACCORDION_WRAPPER, {duration: 0});
967
* Loads all data from the filter into the overlay for editing.
969
function load_overlay_with_filter_data(content_node, filter_info) {
970
var filter = filter_info.filter;
971
set_recipient_label(content_node, filter_info);
972
content_node.one('[name="name"]').set('value',filter.description);
973
set_filter_statuses_and_importances(content_node, filter);
974
set_filter_tags(content_node, filter);
975
set_filter_notification_options(content_node, filter);
979
* Show an overlay for editing a subscription.
981
function show_edit_overlay(config, subscription, filter_info, filter_id) {
982
Y.one(config.content_box).empty();
983
var content_node = Y.one(config.content_box),
984
overlay_id = setup_overlay(config.content_box, true),
985
submit_button = Y.Node.create(
986
'<button type="submit" name="field.actions.create" ' +
987
'value="Save Changes" class="lazr-pos lazr-btn" ' +
990
clear_overlay(content_node, true);
993
filter_info: filter_info,
997
config.content_box, overlay_id, submit_button,
998
function (form_data) {
999
return edit_subscription_handler(context, form_data);});
1001
load_overlay_with_filter_data(content_node, filter_info);
1002
var title = subscription.target_title;
1003
Y.one('#structural-subscription-context-title')
1004
.set('text', title);
1005
Y.one('#subscription-overlay-title')
1006
.set('text', 'Edit subscription for '+title+' bugs');
1008
// We need to initialize the help links. They may have already been
1009
// initialized except for the ones we added, so setupHelpTrigger
1010
// is idempotent. Notice that this is old MochiKit code.
1011
forEach(findHelpLinks(), setupHelpTrigger);
1012
add_subscription_overlay.show();
927
1016
* Return an edit handler for the specified filter.
929
function make_edit_handler(subscription, filter_info, filter_id,
1018
function make_edit_handler(subscription, filter_info, filter_id, config) {
931
1019
// subscription is the filter's subscription.
932
1020
// filter_info is the filter's information (from subscription.filters).
933
1021
// filter_id is the numerical id for the filter, unique on the page.
934
1022
// config is the configuration object used for the entire assembly of the
936
// context is a way to communicate to the shared edit handler what filter
937
// should be updated.
938
1024
return function(e) {
939
// Only proceed if the form content is already available.
940
if (add_subscription_overlay) {
942
var content_node = Y.one(config.content_box),
943
teams = LP.cache.administratedTeams,
944
filter = filter_info.filter,
945
is_lifecycle = filter.bug_notification_level==='Lifecycle',
946
recipient_label = content_node.one(
947
'input[name="recipient"] + span'),
948
statuses = filter.statuses,
949
importances = filter.importances;
950
if (filter_info.subscriber_is_team) {
952
for (i=0; i<teams.length; i++) {
953
if (teams[i].link === filter_info.subscriber_link){
954
recipient_label.set('text', teams[i].title);
959
recipient_label.set('text', 'Yourself');
961
content_node.one('[name="name"]').set('value',filter.description);
963
statuses = LP.cache.statuses;
964
importances = LP.cache.importances;
966
// An absence of values is equivalent to all values.
967
if (statuses.length === 0) {
968
statuses = LP.cache.statuses;
970
if (importances.length === 0) {
971
importances = LP.cache.importances;
974
set_checkboxes(content_node, LP.cache.statuses, statuses);
976
content_node, LP.cache.importances, importances);
977
content_node.one('[name="tags"]').set(
978
'value', is_lifecycle ? '' : filter.tags.join(' '));
980
content_node, [MATCH_ALL, MATCH_ANY],
981
filter.find_all_tags ? MATCH_ALL : MATCH_ANY);
982
var has_advanced_filters = !is_lifecycle && (
983
filter.statuses.length ||
984
filter.importances.length ||
985
filter.tags.length) > 0,
986
filters = has_advanced_filters ? [ADVANCED_FILTER] : [],
987
event = ADDED_OR_CHANGED;
988
// Chattiness: Lifecycle < Details < Discussion.
989
switch (filter.bug_notification_level) {
991
event = ADDED_OR_CLOSED;
995
filters.push(FILTER_COMMENTS);
997
// case 'Discussion': This is already handled/the default.
998
// default: If we get here then it is a programmer error.
1001
content_node, [ADDED_OR_CLOSED, ADDED_OR_CHANGED], event);
1003
content_node, [FILTER_COMMENTS, ADVANCED_FILTER], filters);
1004
handle_change(ADDED_OR_CHANGED, FILTER_WRAPPER, {duration: 0});
1005
handle_change(ADVANCED_FILTER, ACCORDION_WRAPPER, {duration: 0});
1006
context.filter_info = filter_info;
1007
context.filter_id = filter_id;
1008
var title = subscription.target_title;
1009
Y.one('#structural-subscription-context-title')
1010
.set('text', title);
1011
Y.one('#subscription-overlay-title')
1012
.set('text', 'Edit subscription for '+title+' bugs');
1013
add_subscription_overlay.show();
1026
show_edit_overlay(config, subscription, filter_info, filter_id);
1289
1299
// Setup the Launchpad client.
1290
1300
setup_client();
1292
// Create the overlay.
1306
* Show the overlay for creating a new subscription.
1308
function show_add_overlay(config) {
1309
Y.one(config.content_box).empty();
1293
1310
var overlay_id = setup_overlay(config.content_box);
1294
// Create the subscription links on the page.
1295
setup_subscription_links(overlay_id, config.content_box);
1311
clear_overlay(Y.one(config.content_box), false);
1297
1313
var submit_button = Y.Node.create(
1298
1314
'<button type="submit" name="field.actions.create" ' +
1299
1315
'value="Create subscription" class="lazr-pos lazr-btn" '+
1300
1316
'>OK</button>');
1301
1318
create_overlay(config.content_box, overlay_id, submit_button,
1302
1319
save_subscription);
1303
1320
// We need to initialize the help links. They may have already been
1304
1321
// initialized except for the ones we added, so setupHelpTrigger
1305
1322
// is idempotent. Notice that this is old MochiKit code.
1306
1323
forEach(findHelpLinks(), setupHelpTrigger);
1324
add_subscription_overlay.show();
1327
namespace._show_add_overlay = show_add_overlay;
1330
* Modify a link to pop up a subscription overlay.
1332
* @method setup_subscription_link
1333
* @param {String} link_id Id of the link element.
1334
* @param {String} overlay_id Id of the overlay element.
1336
function setup_subscription_link(config, link_id) {
1337
// Modify the menu-link-subscribe-to-bug-mail link to be visible.
1338
var link = Y.one(link_id);
1339
if (!Y.Lang.isValue(link)) {
1340
Y.fail('Link to set as the pop-up link not found.');
1342
link.removeClass('invisible-link');
1343
link.addClass('visible-link');
1344
link.on('click', function(e) {
1346
show_add_overlay(config);
1348
link.addClass('js-action');
1349
} // setup_subscription_links
1352
* External entry point for configuring the structural subscription.
1354
* @param {Object} config Object literal of config name/value pairs.
1355
* config.content_box is the name of an element on the page where
1356
* the overlay will be anchored.
1358
namespace.setup = function(config) {
1359
// Return if pre-setup fails.
1360
if (!pre_setup(config)) {
1364
// Create the subscription links on the page.
1365
setup_subscription_link(config, '.menu-link-subscribe_to_bug_mail');
1309
1368
}, '0.1', {requires: [
1310
1369
'dom', 'node', 'lazr.anim', 'lazr.formoverlay', 'lazr.overlay',