diff --git a/templates/zephyr/index.html b/templates/zephyr/index.html index 0e981e22c5..936ef7d817 100644 --- a/templates/zephyr/index.html +++ b/templates/zephyr/index.html @@ -15,6 +15,10 @@ {% rawjstemplate "subscription" %} + + @@ -52,6 +56,7 @@ + {% if debug %} @@ -132,6 +137,12 @@ var people_list = [ Feedback +
  • + + + Invite users to Humbug + +
  • @@ -238,5 +249,6 @@ var people_list = [ {% include "zephyr/keyboard_shortcuts.html" %} {% include "zephyr/markdown_help.html" %} + {% include "zephyr/invite_user.html" %} {% endblock %} diff --git a/templates/zephyr/invite_user.html b/templates/zephyr/invite_user.html new file mode 100644 index 0000000000..e5cfdd145b --- /dev/null +++ b/templates/zephyr/invite_user.html @@ -0,0 +1,30 @@ + diff --git a/tools/jslint/check-all.js b/tools/jslint/check-all.js index 7ef5ad8f24..cc0fcf3490 100644 --- a/tools/jslint/check-all.js +++ b/tools/jslint/check-all.js @@ -48,6 +48,9 @@ var globals = // hashchange.js + ' hashchange' + // invite.js + + ' invite' + // ui.js + ' ui' diff --git a/zephyr/jstemplates/invite_subscription.html b/zephyr/jstemplates/invite_subscription.html new file mode 100644 index 0000000000..873375ef17 --- /dev/null +++ b/zephyr/jstemplates/invite_subscription.html @@ -0,0 +1,11 @@ +{{! Client-side Mustache template for rendering subscriptions in the "invite user" form.}} +Check all | +Uncheck all +
    + {{#each subscriptions}} + + {{/each}} +
    + diff --git a/zephyr/static-access-control/4nrjx8cwce2bka8r/js/invite.js b/zephyr/static-access-control/4nrjx8cwce2bka8r/js/invite.js new file mode 120000 index 0000000000..d6a751c2cf --- /dev/null +++ b/zephyr/static-access-control/4nrjx8cwce2bka8r/js/invite.js @@ -0,0 +1 @@ +../../../static/js/invite.js \ No newline at end of file diff --git a/zephyr/static/js/invite.js b/zephyr/static/js/invite.js new file mode 100644 index 0000000000..0f9f7c6681 --- /dev/null +++ b/zephyr/static/js/invite.js @@ -0,0 +1,76 @@ +var invite = (function () { + +var exports = {}; + +function update_subscription_checkboxes() { + // TODO: If we were more clever, we would only do this if the + // stream list has actually changed; that way, the settings of the + // checkboxes are saved from invocation to invocation (which is + // nice if I want to invite a bunch of people at once) + $('#streams_to_add').html(templates.invite_subscription({subscriptions: stream_list})); +} + +exports.initialize = function () { + var invite_status = $('#invite_status'); + var invitee_emails = $("#invitee_emails"); + var invitee_emails_group = invitee_emails.closest('.control-group'); + + $('#invite-user').on('show', update_subscription_checkboxes); + invitee_emails.focus(); + invitee_emails.autosize(); + $("#invite_user_form").ajaxForm({ + dataType: 'json', + clearForm: true, + beforeSubmit: function(arr, $form, options) { + invite_status.hide() + .removeClass('alert-error alert-warning alert-success'); + invitee_emails_group.removeClass('warning error'); + // The array of form data takes the following form: + // [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] + // TODO: You could alternatively parse the textarea here, and return errors to + // the user if they don't match certain constraints (i.e. not real email addresses, + // aren't in the right domain, etc.) + // + // OR, you could just let the server do it. Probably my temptation. + return true; + }, + success: function (resp, statusText, xhr, form) { + invite_status.text('Users invited successfully.') + .addClass('alert-success') + .show(); + }, + error: function (xhr, error_type, xhn) { + var arr = $.parseJSON(xhr.responseText); + if (arr.errors === undefined) { + // There was a fatal error, no partial processing occurred. + invite_status.text(arr.msg) + .addClass('alert-error') + .show(); + } else { + // Some users were not invited. + var error_list = $('