From d4aece75a5dd0c6956c32b3c75032973cffffb3d Mon Sep 17 00:00:00 2001 From: Jason Michalski Date: Fri, 17 Jan 2014 14:18:53 -0500 Subject: [PATCH] Add JS to for the inline subscribe button Add javascript to handle the button clicks and update the status based on the subscribe and unsubscribe events from the server. (imported from commit 6b9c0b40d9084e3d8b64bed701ebc786bef6d432) --- static/js/custom_markdown.js | 122 ++++++++++++++++++ static/styles/zulip.css | 4 + .../tests/frontend/tests/04-subscriptions.js | 50 +++++++ zproject/settings.py | 3 +- 4 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 static/js/custom_markdown.js diff --git a/static/js/custom_markdown.js b/static/js/custom_markdown.js new file mode 100644 index 0000000000..fd7f7b28fc --- /dev/null +++ b/static/js/custom_markdown.js @@ -0,0 +1,122 @@ +var custom_markdown = (function () { + +var exports = {}; + +(function () { + // Javascript for bugdown.StreamSubscribeButton + + // A map of stream names to ids to select inline subscribe node without + // needing to escape the CSS selectors. + var inline_subscribe_id_map = {}; + + function add_sub(stream_name, $status_message) { + channel.post({ + url: '/json/subscriptions/add', + data: { + subscriptions: JSON.stringify([{'name': stream_name}]) + } + }).then( + function (data) { + if (!$.isEmptyObject(data.already_subscribed)) { + // Display the canonical stream capitalization. + var true_stream_name = data.already_subscribed[page_params.email][0]; + ui.report_success("Already subscribed to " + true_stream_name, + $status_message); + } + }, function (xhr) { + ui.report_error("Error adding subscription", xhr, $status_message); + } + ); + } + + function remove_sub(stream_name, $status_message) { + channel.post({ + url: '/json/subscriptions/remove', + data: { + subscriptions: JSON.stringify([stream_name]) + } + }).then( + function (data) { + $status_message.hide(); + }, function (xhr) { + ui.report_error("Error removing subscription", xhr, $status_message); + } + ); + } + + function display_subscribe($button, stream_name) { + $button.text('Subscribe to ' + stream_data.canonicalized_name(stream_name)) + .removeClass('green-button') + .addClass('gray-button'); + } + + function display_unsubscribe($button, stream_name) { + $button.text('Unsubscribe from ' + stream_data.canonicalized_name(stream_name)) + .removeClass('gray-button') + .addClass('green-button'); + } + + function update_button_display($button, stream_name) { + if (stream_data.is_subscribed(stream_name)) { + display_unsubscribe($button, stream_name); + } else { + display_subscribe($button, stream_name); + } + } + + $(function () { + $('#main_div').delegate('.inline-subscribe-button', 'click', function (e) { + var $button = $(e.target); + var stream_name = $button.closest('.inline-subscribe').data('stream-name'); + var $status_message = $button.siblings('.inline-subscribe-error'); + e.preventDefault(); + e.stopPropagation(); + + if (stream_data.is_subscribed(stream_name)) { + remove_sub(stream_name, $status_message); + } else { + add_sub(stream_name, $status_message); + } + }); + }); + + $(document).on('message_rendered.zulip', function (e) { + var $inline_subscribe, $button, stream_name, id; + $inline_subscribe = $(e.target).find('.inline-subscribe'); + if ($inline_subscribe.length === 0) { + return; + } + stream_name = $inline_subscribe.data('stream-name'); + $button = $inline_subscribe.find('.inline-subscribe-button'); + + if (inline_subscribe_id_map[stream_name]) { + id = inline_subscribe_id_map[stream_name]; + } else { + id = _.uniqueId('inline-subscribe-id-'); + inline_subscribe_id_map[stream_name] = id; + } + // Can not use data here, jQuery only stores into expando so our jQuery + // selectors will not be able to find it. + $inline_subscribe.attr('data-stream-ui-id', id); + + update_button_display($button, stream_name); + }); + + var sub_event_handler = function (e) { + var stream_name = e.sub.name; + var id = inline_subscribe_id_map[stream_name]; + var $button = $('#main_div'). + find('.inline-subscribe[data-stream-ui-id="'+ id + '"] .inline-subscribe-button'); + update_button_display($button, stream_name); + }; + $(document).on('subscription_add_done.zulip', sub_event_handler); + $(document).on('subscription_remove_done.zulip', sub_event_handler); +}()); + + +return exports; + +}()); +if (typeof module !== 'undefined') { + module.exports = custom_markdown; +} diff --git a/static/styles/zulip.css b/static/styles/zulip.css index 50eafea350..54c513a30c 100644 --- a/static/styles/zulip.css +++ b/static/styles/zulip.css @@ -3732,3 +3732,7 @@ li.show-more-topics a { .user-list-filter { width: 80%; } + +.inline-subscribe-error { + margin-left: 5px; +} diff --git a/zerver/tests/frontend/tests/04-subscriptions.js b/zerver/tests/frontend/tests/04-subscriptions.js index ddf296bae1..9ae3b59ad0 100644 --- a/zerver/tests/frontend/tests/04-subscriptions.js +++ b/zerver/tests/frontend/tests/04-subscriptions.js @@ -42,6 +42,56 @@ casper.then(function () { casper.test.assertTextExists('Error adding subscription', "Can't subscribe to an empty stream name"); }); +// Test the inline subscribe and unsubscribe in messages +casper.then(function () { + casper.click('a[href^="#"]'); + casper.test.assertUrlMatch(/^http:\/\/[^\/]+\/#$/, 'URL suggests we are on home page'); +}); + +// Test an inline subscribe button for an unsubscribed stream +common.send_message('stream', { + stream: 'Verona', + subject: 'Inline subscribe', + content: "!_stream_subscribe_button(inline stream)" +}); + +var new_stream_button = '.inline-subscribe[data-stream-name="inline stream"] .inline-subscribe-button'; + +casper.waitUntilVisible(new_stream_button, function () { + casper.test.assertSelectorHasText(new_stream_button, + 'Subscribe to inline stream', + 'New inline subscribe button starts as subscribe'); + casper.click(new_stream_button); +}); + +casper.waitUntilVisible('.narrow-filter[data-name="inline stream"]', function () { + casper.test.assertSelectorHasText(new_stream_button, + 'Unsubscribe from inline stream', + 'New inline subscribe button becomes unsubscribe'); + casper.click(new_stream_button); +}); + +casper.waitWhileVisible('.narrow-filter[data-name="inline stream"]', function () { + casper.test.assertSelectorHasText(new_stream_button, + 'Subscribe to inline stream', + 'New inline subscribe returns to subscribe on unsubscribe'); +}); + +// Test an inline subscribe button for an subscribed stream +common.send_message('stream', { + stream: 'Verona', + subject: 'Inline subscribe', + content: "!_stream_subscribe_button(Denmark)" +}); + +var existing_stream_button = '.inline-subscribe[data-stream-name="Denmark"] .inline-subscribe-button'; + +casper.waitUntilVisible(new_stream_button, function () { + casper.test.assertSelectorHasText(existing_stream_button, + 'Unsubscribe from denmark', + 'Existing subscribe button starts as unsubscribe'); +}); + common.then_log_out(); casper.run(function () { diff --git a/zproject/settings.py b/zproject/settings.py index 6832e7a99d..8bddf96e75 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -556,7 +556,8 @@ JS_SPECS = { 'js/settings.js', 'js/tab_bar.js', 'js/emoji.js', - 'js/referral.js' + 'js/referral.js', + 'js/custom_markdown.js', ], 'output_filename': 'min/app.js' },