org settings: Add save/discard widget for realm authentication methods.

Along with this, we refactored settings_org.populate_auth_methods to use
HTML function after rendering all auth methods rows rather than appending
each row individually, which actually is a good practice.

Also in this commit, to compare `current_val` and `changed_val` in
`check_property_changed` function of the property
`realm_authentication_methods`, which are objects, and we found here
https://stackoverflow.com/a/1144249 that there is no easy way to do so. So
I followed this approach,

```js
 JSON.stringify(obj1) === JSON.stringify(obj2)
```

but before converting them to string we want the same order of keys, so we
used `sort_object_by_key` to sort `current_val` by keys and
`get_auth_method_table_data` always return `changed_val` having keys
sorted.

Since these refactor were closely related we kept them as a single commit
here.

Fixes: #11954.
This commit is contained in:
Pragati Agrawal 2019-04-06 12:13:34 +05:30 committed by Tim Abbott
parent c634d22de9
commit 4df971c3c2
6 changed files with 55 additions and 66 deletions

View File

@ -387,6 +387,8 @@ casper.then(function () {
casper.click("li[data-section='auth-methods']"); casper.click("li[data-section='auth-methods']");
casper.waitUntilVisible(".method_row[data-method='Google'] input[type='checkbox'] + span", function () { casper.waitUntilVisible(".method_row[data-method='Google'] input[type='checkbox'] + span", function () {
casper.click(".method_row[data-method='Google'] input[type='checkbox'] + span"); casper.click(".method_row[data-method='Google'] input[type='checkbox'] + span");
casper.test.assertSelectorHasText('#org-submit-auth_settings', "Save");
casper.click('#org-submit-auth_settings');
}); });
}); });

View File

@ -85,24 +85,7 @@ run_test('unloaded', () => {
settings_org.populate_auth_methods(); settings_org.populate_auth_methods();
}); });
function simulate_auth_methods() { function simulate_tip_box() {
$('#admin_auth_methods_table').set_find_results(
'tr.method_row',
$.create('admin-tr-stub')
);
var controls = $.create('auth-methods-controls-stub');
$(".organization-box [data-name='auth-methods']").set_find_results(
'input, button, select, checked',
controls
);
controls.attr = function (name, val) {
assert.equal(name, 'disabled');
assert.equal(val, true);
};
var non_editables = $.create('auth-methods-not-edit-stub'); var non_editables = $.create('auth-methods-not-edit-stub');
$('.organization-box').set_find_results( $('.organization-box').set_find_results(
'.settings-section:not(.can-edit)', '.settings-section:not(.can-edit)',
@ -734,13 +717,12 @@ run_test('set_up', () => {
name: "Zoom", name: "Zoom",
}, },
}; };
simulate_auth_methods(); simulate_tip_box();
$('#id_realm_create_stream_policy').change = set_callback('realm_create_stream_policy'); $('#id_realm_create_stream_policy').change = set_callback('realm_create_stream_policy');
$('#id_realm_video_chat_provider').change = set_callback('realm_video_chat_provider'); $('#id_realm_video_chat_provider').change = set_callback('realm_video_chat_provider');
$("#id_realm_org_join_restrictions").change = set_callback('change_org_join_restrictions'); $("#id_realm_org_join_restrictions").change = set_callback('change_org_join_restrictions');
$('#submit-add-realm-domain').click = set_callback('add_realm_domain'); $('#submit-add-realm-domain').click = set_callback('add_realm_domain');
$('#admin_auth_methods_table').change = set_callback('admin_auth_methods_table');
$('.notifications-stream-disable').click = set_callback('disable_notifications_stream'); $('.notifications-stream-disable').click = set_callback('disable_notifications_stream');
$('.signup-notifications-stream-disable').click = set_callback('disable_signup_notifications_stream'); $('.signup-notifications-stream-disable').click = set_callback('disable_signup_notifications_stream');

View File

@ -441,14 +441,12 @@ run_test('bankruptcy_modal', () => {
run_test('admin_auth_methods_list', () => { run_test('admin_auth_methods_list', () => {
var args = { var args = {
method: {
method: "Email", method: "Email",
enabled: false, enabled: false,
},
}; };
var html = ''; var html = '';
html += '<tbody id="admin_auth_methods_table">'; html += '<tbody>';
html += render('admin_auth_methods_list', args); html += render('admin_auth_methods_list', args);
html += '</tbody>'; html += '</tbody>';

View File

@ -304,7 +304,6 @@ exports.populate_realm_domains = function (realm_domains) {
realm_domains_table_body.append(templates.render("admin-realm-domains-list", {realm_domain: realm_domain})); realm_domains_table_body.append(templates.render("admin-realm-domains-list", {realm_domain: realm_domain}));
}); });
}; };
function sort_object_by_key(obj) { function sort_object_by_key(obj) {
var keys = _.keys(obj).sort(); var keys = _.keys(obj).sort();
var new_obj = {}; var new_obj = {};
@ -313,24 +312,21 @@ function sort_object_by_key(obj) {
}); });
return new_obj; return new_obj;
} }
exports.populate_auth_methods = function (auth_methods) { exports.populate_auth_methods = function (auth_methods) {
if (!meta.loaded) { if (!meta.loaded) {
return; return;
} }
var auth_methods_table = $("#id_realm_authentication_methods").expectOne();
var auth_methods_table = $("#admin_auth_methods_table").expectOne();
auth_methods_table.find('tr.method_row').remove();
auth_methods = sort_object_by_key(auth_methods); auth_methods = sort_object_by_key(auth_methods);
var rendered_auth_method_rows = "";
_.each(auth_methods, function (value, auth_method) { _.each(auth_methods, function (value, auth_method) {
auth_methods_table.append(templates.render('admin_auth_methods_list', { rendered_auth_method_rows += templates.render('admin_auth_methods_list', {
method: {
method: auth_method, method: auth_method,
enabled: value, enabled: value,
is_admin: page_params.is_admin, is_admin: page_params.is_admin,
},
}));
}); });
});
auth_methods_table.html(rendered_auth_method_rows);
}; };
function insert_tip_box() { function insert_tip_box() {
@ -344,7 +340,6 @@ function insert_tip_box() {
.prepend(tip_box); .prepend(tip_box);
} }
exports.render_notifications_stream_ui = function (stream_id, elem) { exports.render_notifications_stream_ui = function (stream_id, elem) {
var name = stream_data.maybe_get_stream_name(stream_id); var name = stream_data.maybe_get_stream_name(stream_id);
@ -453,6 +448,9 @@ function discard_property_element_changes(elem) {
elem.prop('checked', property_value); elem.prop('checked', property_value);
} else if (typeof property_value === 'string' || typeof property_value === 'number') { } else if (typeof property_value === 'string' || typeof property_value === 'number') {
elem.val(property_value); elem.val(property_value);
} else if (typeof property_value === 'object' &&
property_name === 'realm_authentication_methods') {
exports.populate_auth_methods(property_value);
} else { } else {
blueslip.error('Element refers to unknown property ' + property_name); blueslip.error('Element refers to unknown property ' + property_name);
} }
@ -605,12 +603,20 @@ exports.build_page = function () {
set_message_content_in_email_notifications_visiblity(); set_message_content_in_email_notifications_visiblity();
set_digest_emails_weekday_visibility(); set_digest_emails_weekday_visibility();
function get_auth_method_table_data() {
var new_auth_methods = {};
var auth_method_rows = $("#id_realm_authentication_methods").find('tr.method_row');
_.each(auth_method_rows, function (method_row) {
new_auth_methods[$(method_row).data('method')] = $(method_row).find('input').prop('checked');
});
return new_auth_methods;
}
function check_property_changed(elem) { function check_property_changed(elem) {
elem = $(elem); elem = $(elem);
var property_name = exports.extract_property_name(elem); var property_name = exports.extract_property_name(elem);
var changed_val; var changed_val;
var current_val = get_property_value(property_name); var current_val = get_property_value(property_name);
if (typeof current_val === 'boolean') { if (typeof current_val === 'boolean') {
changed_val = elem.prop('checked'); changed_val = elem.prop('checked');
} else if (typeof current_val === 'string') { } else if (typeof current_val === 'string') {
@ -618,6 +624,12 @@ exports.build_page = function () {
} else if (typeof current_val === 'number') { } else if (typeof current_val === 'number') {
current_val = current_val.toString(); current_val = current_val.toString();
changed_val = elem.val().trim(); changed_val = elem.val().trim();
} else if (typeof current_val === 'object') {
// Currently we only deal with realm_authentication_methods object
current_val = sort_object_by_key(current_val);
current_val = JSON.stringify(current_val);
changed_val = get_auth_method_table_data();
changed_val = JSON.stringify(changed_val);
} else { } else {
blueslip.error('Element refers to unknown property ' + property_name); blueslip.error('Element refers to unknown property ' + property_name);
} }
@ -775,6 +787,9 @@ exports.build_page = function () {
data.invite_required = true; data.invite_required = true;
data.invite_by_admins_only = false; data.invite_by_admins_only = false;
} }
} else if (subsection === 'auth_settings') {
data = {};
data.authentication_methods = JSON.stringify(get_auth_method_table_data());
} }
return data; return data;
} }
@ -865,19 +880,6 @@ exports.build_page = function () {
e.stopPropagation(); e.stopPropagation();
}); });
$('#admin_auth_methods_table').change(function () {
var new_auth_methods = {};
_.each($("#admin_auth_methods_table").find('tr.method_row'), function (method_row) {
new_auth_methods[$(method_row).data('method')] = $(method_row).find('input').prop('checked');
});
settings_ui.do_settings_change(channel.patch, '/json/realm',
{authentication_methods: JSON.stringify(new_auth_methods)},
$('#admin-realm-authentication-methods-status').expectOne()
);
});
function fade_status_element(elem) { function fade_status_element(elem) {
setTimeout(function () { setTimeout(function () {
elem.fadeOut(500); elem.fadeOut(500);

View File

@ -1,4 +1,3 @@
{{#with method}}
<tr class="method_row" data-method="{{method}}"> <tr class="method_row" data-method="{{method}}">
<td> <td>
<span class="method">{{method}}</span> <span class="method">{{method}}</span>
@ -10,4 +9,3 @@
</label> </label>
</td> </td>
</tr> </tr>
{{/with}}

View File

@ -1,16 +1,23 @@
<div id="admin-auth-settings" class="settings-section" data-name="auth-methods"> <div id="organization-auth-settings" class="settings-section" data-name="auth-methods">
<form class="form-horizontal admin-realm-form org-authentications-form"> <form class="form-horizontal admin-realm-form org-authentications-form">
<div class="admin-table-wrapper"> <div id="org-auth_settings" class="admin-table-wrapper org-subsection-parent">
<h3 class="inline-block">{{t "Authentication methods" }}</h3> <div class ="subsection-header">
<div class="alert-notification" id="admin-realm-authentication-methods-status"></div> <h3>{{t "Authentication methods" }}</h3>
<p>{{#tr this}}Configure the authentication methods for your organization.{{/tr}}</p> {{ partial "settings-save-discard-widget" "section_name" "auth_settings" }}
<table class="table table-condensed table-striped"> </div>
<div>
<p>{{t "Configure the authentication methods for your organization."}}</p>
<table id="id_realm_authentication_methods"
class="table table-condensed table-striped prop-element">
<thead> <thead>
<th>{{t "Method" }}</th> <th>{{t "Method" }}</th>
<th>{{t "Enabled" }}</th> <th>{{t "Enabled" }}</th>
</thead> </thead>
<tbody id="admin_auth_methods_table" class=" admin_auth_methods_table"></tbody> <tbody>
</tbody>
</table> </table>
</div> </div>
</div>
</form> </form>
</div> </div>