From 47bdecdc4f5551ee6a8250ef0ae9622243a9cf09 Mon Sep 17 00:00:00 2001 From: Steve Howell Date: Wed, 5 Apr 2017 17:28:57 -0700 Subject: [PATCH] Extract settings_account.js. This code handles the settings pane for "Your account," which has email/name/password/avatar/etc. --- .eslintrc.json | 1 + static/js/settings.js | 176 +------------------------------ static/js/settings_account.js | 192 ++++++++++++++++++++++++++++++++++ static/js/user_events.js | 2 +- zproject/settings.py | 1 + 5 files changed, 196 insertions(+), 176 deletions(-) create mode 100644 static/js/settings_account.js diff --git a/.eslintrc.json b/.eslintrc.json index 4f59653b43..4fe5d44e03 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,7 @@ "stream_color": false, "people": false, "navigate": false, + "settings_account": false, "settings": false, "resize": false, "loading": false, diff --git a/static/js/settings.js b/static/js/settings.js index b5f61029d9..856605ef7b 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -139,14 +139,6 @@ function render_bots() { } } -exports.update_email = function (new_email) { - var email_input = $('#email_value'); - - if (email_input) { - email_input.text(new_email); - } -}; - exports.generate_zuliprc_uri = function (email, api_key) { var data = settings.generate_zuliprc_content(email, api_key); @@ -246,13 +238,13 @@ function _setup_page() { }); $(".settings-box").html(settings_tab); - $("#account-settings-status").hide(); $("#notify-settings-status").hide(); $("#display-settings-status").hide(); $("#ui-settings-status").hide(); alert_words_ui.set_up_alert_words(); attachments_ui.set_up_attachments(); + settings_account.set_up(); $("#api_key_value").text(""); $("#get_api_key_box").hide(); @@ -263,13 +255,6 @@ function _setup_page() { exports.launch_page(tab); } - function clear_password_change() { - // Clear the password boxes so that passwords don't linger in the DOM - // for an XSS attacker to find. - $('#old_password, #new_password, #confirm_password').val(''); - } - - clear_password_change(); $('#api_key_button').click(function () { if (page_params.password_auth_enabled !== false) { @@ -281,30 +266,6 @@ function _setup_page() { $("#api_key_button_box").hide(); }); - $('#pw_change_link').on('click', function (e) { - e.preventDefault(); - $('#pw_change_link').hide(); - $('#pw_change_controls').show(); - if (page_params.password_auth_enabled !== false) { - // zxcvbn.js is pretty big, and is only needed on password - // change, so load it asynchronously. - var zxcvbn_path = '/static/min/zxcvbn.js'; - if (page_params.development_environment) { - // Usually the Django templates handle this path stuff - // for us, but in this case we need to hardcode it. - zxcvbn_path = '/static/node_modules/zxcvbn/dist/zxcvbn.js'; - } - $.getScript(zxcvbn_path, function () { - $('#pw_strength .bar').removeClass("fade"); - }); - } - }); - - $('#new_password').on('change keyup', function () { - var field = $('#new_password'); - password_quality(field.val(), $('#pw_strength .bar'), field); - }); - if (!page_params.show_digest_email) { $("#other_notifications").hide(); } @@ -312,57 +273,6 @@ function _setup_page() { $('.new-bot-ui').hide(); } - function settings_change_error(message, xhr) { - // Scroll to the top so the error message is visible. - // We would scroll anyway if we end up submitting the form. - message_viewport.scrollTop(0); - ui_report.error(message, xhr, $('#account-settings-status').expectOne()); - } - - function settings_change_success(message) { - // Scroll to the top so the error message is visible. - // We would scroll anyway if we end up submitting the form. - message_viewport.scrollTop(0); - ui_report.success(message, $('#account-settings-status').expectOne()); - } - - $("form.your-account-settings").ajaxForm({ - dataType: 'json', // This seems to be ignored. We still get back an xhr. - beforeSubmit: function () { - if (page_params.password_auth_enabled !== false) { - // FIXME: Check that the two password fields match - // FIXME: Use the same jQuery validation plugin as the signup form? - var field = $('#new_password'); - var new_pw = $('#new_password').val(); - if (new_pw !== '') { - var password_ok = password_quality(new_pw, undefined, field); - if (password_ok === undefined) { - // zxcvbn.js didn't load, for whatever reason. - settings_change_error( - 'An internal error occurred; try reloading the page. ' + - 'Sorry for the trouble!'); - return false; - } else if (!password_ok) { - settings_change_error('New password is too weak'); - return false; - } - } - } - return true; - }, - success: function () { - settings_change_success("Updated settings!"); - }, - error: function (xhr) { - settings_change_error("Error changing settings", xhr); - }, - complete: function () { - // Whether successful or not, clear the password boxes. - // TODO: Clear these earlier, while the request is still pending. - clear_password_change(); - }, - }); - function update_notification_settings_success(resp, statusText, xhr) { var result = JSON.parse(xhr.responseText); var notify_settings_status = $('#notify-settings-status').expectOne(); @@ -597,63 +507,12 @@ function _setup_page() { }); }); - $('#change_email_button').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - $('#change_email_modal').modal('hide'); - - var data = {}; - data.email = $('.email_change_container').find("input[name='email']").val(); - - channel.patch({ - url: '/json/settings/change', - data: data, - success: function (data) { - if ('account_email' in data) { - settings_change_success(data.account_email); - } else { - settings_change_error(i18n.t("Error changing settings: No new data supplied.")); - } - }, - error: function (xhr) { - settings_change_error("Error changing settings", xhr); - }, - }); - }); - $('#default_language').on('click', function (e) { e.preventDefault(); e.stopPropagation(); $('#default_language_modal').show().attr('aria-hidden', false); }); - $('#change_email').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - $('#change_email_modal').modal('show'); - var email = $('#email_value').text(); - $('.email_change_container').find("input[name='email']").val(email); - }); - - $("#user_deactivate_account_button").on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - $("#deactivate_self_modal").modal("show"); - }); - - $("#do_deactivate_self_button").on('click',function () { - $("#deactivate_self_modal").modal("hide"); - channel.del({ - url: '/json/users/me', - success: function () { - window.location.href = "/login"; - }, - error: function (xhr) { - ui_report.error(i18n.t("Error deactivating account"), xhr, $('#account-settings-status').expectOne()); - }, - }); - }); - $("#get_api_key_box").hide(); $("#show_api_key_box").hide(); $("#get_api_key_box form").ajaxForm({ @@ -675,39 +534,6 @@ function _setup_page() { }, }); - function upload_avatar(file_input) { - var form_data = new FormData(); - - form_data.append('csrfmiddlewaretoken', csrf_token); - jQuery.each(file_input[0].files, function (i, file) { - form_data.append('file-'+i, file); - }); - - var spinner = $("#upload_avatar_spinner").expectOne(); - loading.make_indicator(spinner, {text: 'Uploading avatar.'}); - - channel.put({ - url: '/json/users/me/avatar', - data: form_data, - cache: false, - processData: false, - contentType: false, - success: function (data) { - loading.destroy_indicator($("#upload_avatar_spinner")); - $("#user-settings-avatar").expectOne().attr("src", data.avatar_url); - $("#user_avatar_delete_button").show(); - }, - }); - - } - - avatar.build_user_avatar_widget(upload_avatar); - - if (page_params.name_changes_disabled) { - $(".name_change_container").hide(); - } - - // TODO: render bots xxxx render_bots(); $(document).on('zulip.bot_data_changed', render_bots); diff --git a/static/js/settings_account.js b/static/js/settings_account.js new file mode 100644 index 0000000000..ebcb5881ff --- /dev/null +++ b/static/js/settings_account.js @@ -0,0 +1,192 @@ +var settings_account = (function () { + +var exports = {}; + +exports.update_email = function (new_email) { + var email_input = $('#email_value'); + + if (email_input) { + email_input.text(new_email); + } +}; + +function settings_change_error(message, xhr) { + // Scroll to the top so the error message is visible. + // We would scroll anyway if we end up submitting the form. + message_viewport.scrollTop(0); + ui_report.error(message, xhr, $('#account-settings-status').expectOne()); +} + +function settings_change_success(message) { + // Scroll to the top so the error message is visible. + // We would scroll anyway if we end up submitting the form. + message_viewport.scrollTop(0); + ui_report.success(message, $('#account-settings-status').expectOne()); +} + + +exports.set_up = function () { + $("#account-settings-status").hide(); + + function clear_password_change() { + // Clear the password boxes so that passwords don't linger in the DOM + // for an XSS attacker to find. + $('#old_password, #new_password, #confirm_password').val(''); + } + + clear_password_change(); + + $('#pw_change_link').on('click', function (e) { + e.preventDefault(); + $('#pw_change_link').hide(); + $('#pw_change_controls').show(); + if (page_params.password_auth_enabled !== false) { + // zxcvbn.js is pretty big, and is only needed on password + // change, so load it asynchronously. + var zxcvbn_path = '/static/min/zxcvbn.js'; + if (page_params.development_environment) { + // Usually the Django templates handle this path stuff + // for us, but in this case we need to hardcode it. + zxcvbn_path = '/static/node_modules/zxcvbn/dist/zxcvbn.js'; + } + $.getScript(zxcvbn_path, function () { + $('#pw_strength .bar').removeClass("fade"); + }); + } + }); + + $('#new_password').on('change keyup', function () { + var field = $('#new_password'); + password_quality(field.val(), $('#pw_strength .bar'), field); + }); + + $("form.your-account-settings").ajaxForm({ + dataType: 'json', // This seems to be ignored. We still get back an xhr. + beforeSubmit: function () { + if (page_params.password_auth_enabled !== false) { + // FIXME: Check that the two password fields match + // FIXME: Use the same jQuery validation plugin as the signup form? + var field = $('#new_password'); + var new_pw = $('#new_password').val(); + if (new_pw !== '') { + var password_ok = password_quality(new_pw, undefined, field); + if (password_ok === undefined) { + // zxcvbn.js didn't load, for whatever reason. + settings_change_error( + 'An internal error occurred; try reloading the page. ' + + 'Sorry for the trouble!'); + return false; + } else if (!password_ok) { + settings_change_error('New password is too weak'); + return false; + } + } + } + return true; + }, + success: function () { + settings_change_success("Updated settings!"); + }, + error: function (xhr) { + settings_change_error("Error changing settings", xhr); + }, + complete: function () { + // Whether successful or not, clear the password boxes. + // TODO: Clear these earlier, while the request is still pending. + clear_password_change(); + }, + }); + + $('#change_email_button').on('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + $('#change_email_modal').modal('hide'); + + var data = {}; + data.email = $('.email_change_container').find("input[name='email']").val(); + + channel.patch({ + url: '/json/settings/change', + data: data, + success: function (data) { + if ('account_email' in data) { + settings_change_success(data.account_email); + } else { + settings_change_error(i18n.t("Error changing settings: No new data supplied.")); + } + }, + error: function (xhr) { + settings_change_error("Error changing settings", xhr); + }, + }); + }); + + $('#change_email').on('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + $('#change_email_modal').modal('show'); + var email = $('#email_value').text(); + $('.email_change_container').find("input[name='email']").val(email); + }); + + $("#user_deactivate_account_button").on('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + $("#deactivate_self_modal").modal("show"); + }); + + $("#do_deactivate_self_button").on('click',function () { + $("#deactivate_self_modal").modal("hide"); + channel.del({ + url: '/json/users/me', + success: function () { + window.location.href = "/login"; + }, + error: function (xhr) { + ui_report.error(i18n.t("Error deactivating account"), xhr, $('#account-settings-status').expectOne()); + }, + }); + }); + + + function upload_avatar(file_input) { + var form_data = new FormData(); + + form_data.append('csrfmiddlewaretoken', csrf_token); + jQuery.each(file_input[0].files, function (i, file) { + form_data.append('file-'+i, file); + }); + + var spinner = $("#upload_avatar_spinner").expectOne(); + loading.make_indicator(spinner, {text: 'Uploading avatar.'}); + + channel.put({ + url: '/json/users/me/avatar', + data: form_data, + cache: false, + processData: false, + contentType: false, + success: function (data) { + loading.destroy_indicator($("#upload_avatar_spinner")); + $("#user-settings-avatar").expectOne().attr("src", data.avatar_url); + $("#user_avatar_delete_button").show(); + }, + }); + + } + + avatar.build_user_avatar_widget(upload_avatar); + + if (page_params.name_changes_disabled) { + $(".name_change_container").hide(); + } + +}; + + +return exports; +}()); + +if (typeof module !== 'undefined') { + module.exports = settings_account; +} diff --git a/static/js/user_events.js b/static/js/user_events.js index a95d877175..2884ac90e0 100644 --- a/static/js/user_events.js +++ b/static/js/user_events.js @@ -24,7 +24,7 @@ exports.update_person = function update(person) { compose.update_email(user_id, new_email); if (people.is_my_user_id(person.user_id)) { - settings.update_email(new_email); + settings_account.update_email(new_email); } people.update_email(user_id, new_email); diff --git a/zproject/settings.py b/zproject/settings.py index b1ea04a99d..e56a8a2310 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -905,6 +905,7 @@ JS_SPECS = { 'js/upload_widget.js', 'js/avatar.js', 'js/realm_icon.js', + 'js/settings_account.js', 'js/settings.js', 'js/admin.js', 'js/tab_bar.js',