frontend: Add UI to create/edit private streams with public history.

This completes the effort of making this a user-facing feature.
This commit is contained in:
Eeshan Garg
2018-05-03 14:22:39 -02:30
committed by Tim Abbott
parent 3498fc4e74
commit 9c8865ba76
9 changed files with 110 additions and 36 deletions

View File

@@ -1251,12 +1251,14 @@ run_test('handlebars_bug', () => {
};
var html = render('subscription_stream_privacy_modal', args);
var stream_desc = $(html).find(".modal-body b");
assert.equal(stream_desc.text(), 'an invite-only stream');
var other_options = $(html).find("input[name=privacy]");
assert.equal(other_options[0].value, 'public');
assert.equal(other_options[1].value, 'invite-only');
assert.equal(other_options[2].value, 'invite-only-public-history');
var button = $(html).find("#change-stream-privacy-button");
assert(button.hasClass("btn-primary"));
assert.equal(button.text().trim(), "translated: Make stream public");
assert(button.hasClass("btn-danger"));
assert.equal(button.text().trim(), "translated: Change privacy");
}());

View File

@@ -97,7 +97,8 @@ var stream_name_error = (function () {
return self;
}());
function ajaxSubscribeForCreation(stream_name, description, principals, invite_only, announce) {
function ajaxSubscribeForCreation(stream_name, description, principals, invite_only,
announce, history_public_to_subscribers) {
// Subscribe yourself and possible other people to a new stream.
return channel.post({
url: "/json/users/me/subscriptions",
@@ -106,6 +107,7 @@ function ajaxSubscribeForCreation(stream_name, description, principals, invite_o
principals: JSON.stringify(principals),
invite_only: JSON.stringify(invite_only),
announce: JSON.stringify(announce),
history_public_to_subscribers: JSON.stringify(history_public_to_subscribers),
},
success: function () {
$("#create_stream_name").val("");
@@ -168,9 +170,23 @@ function get_principals() {
function create_stream() {
var stream_name = $.trim($("#create_stream_name").val());
var description = $.trim($("#create_stream_description").val());
var is_invite_only = $('#stream_creation_form input[name=privacy]:checked').val() === "invite-only";
var privacy_setting = $('#stream_creation_form input[name=privacy]:checked').val();
var principals = get_principals();
var invite_only;
var history_public_to_subscribers;
if (privacy_setting === 'invite-only') {
invite_only = true;
history_public_to_subscribers = false;
} else if (privacy_setting === 'invite-only-public-history') {
invite_only = true;
history_public_to_subscribers = true;
} else {
invite_only = false;
history_public_to_subscribers = true;
}
created_stream = stream_name;
var announce = (!!page_params.notifications_stream &&
@@ -182,8 +198,9 @@ function create_stream() {
stream_name,
description,
principals,
is_invite_only,
announce
invite_only,
announce,
history_public_to_subscribers
);
}

View File

@@ -343,11 +343,28 @@ function change_stream_privacy(e) {
var stream_id = $(e.target).data("stream-id");
var sub = stream_data.get_sub_by_id(stream_id);
var privacy_setting = $('#stream_privacy_modal input[name=privacy]:checked').val();
var invite_only;
var history_public_to_subscribers;
if (privacy_setting === 'invite-only') {
invite_only = true;
history_public_to_subscribers = false;
} else if (privacy_setting === 'invite-only-public-history') {
invite_only = true;
history_public_to_subscribers = true;
} else {
invite_only = false;
history_public_to_subscribers = true;
}
$(".stream_change_property_info").hide();
var data = {
stream_name: sub.name,
// toggle the privacy setting
is_private: !sub.invite_only,
is_private: JSON.stringify(invite_only),
history_public_to_subscribers: JSON.stringify(history_public_to_subscribers),
};
channel.patch({
@@ -358,7 +375,8 @@ function change_stream_privacy(e) {
var sub_row = $(".stream-row[data-stream-id='" + stream_id + "']");
// save new privacy settings.
sub.invite_only = !sub.invite_only;
sub.invite_only = invite_only;
sub.history_public_to_subscribers = history_public_to_subscribers;
redraw_privacy_related_stuff(sub_row, sub);
$("#stream_privacy_modal").remove();
@@ -488,8 +506,12 @@ exports.initialize = function () {
var stream_id = get_stream_id(e.target);
var stream = stream_data.get_sub_by_id(stream_id);
var template_data = {
is_private: stream.can_make_public,
stream_id: stream_id,
stream_name: stream.name,
is_public: !stream.invite_only,
is_private: stream.invite_only && !stream.history_public_to_subscribers,
is_private_with_public_history: (stream.invite_only &&
stream.history_public_to_subscribers),
};
var change_privacy_modal = templates.render("subscription_stream_privacy_modal", template_data);

View File

@@ -284,6 +284,7 @@ body.night-mode .subscriptions-container .left,
body.night-mode .subscriber-list-box,
body.night-mode .subscriber-list tr,
body.night-mode #subscription_overlay ul.grey-box li,
body.night-mode #stream_privacy_modal ul.grey-box li,
body.night-mode #settings_page .sidebar,
body.night-mode #settings_page .sidebar *,
body.night-mode table,

View File

@@ -952,23 +952,32 @@ form#add_new_subscription {
display: block;
}
#stream_privacy_modal ul.grey-box {
border-style: none;
}
#stream_privacy_modal ul.grey-box li,
#subscription_overlay ul.grey-box li {
border-bottom: 1px solid hsl(0, 0%, 86%);
padding: 5px 0px;
}
#stream_privacy_modal ul.grey-box li input[type=checkbox],
#subscription_overlay ul.grey-box li input[type=checkbox] {
margin-top: 0px;
}
#stream_privacy_modal ul.grey-box li:last-of-type,
#subscription_overlay ul.grey-box li:last-of-type {
border-bottom: none;
}
#stream_privacy_modal ul.grey-box li .sp-replacer,
#subscription_overlay ul.grey-box li .sp-replacer {
box-shadow: none;
}
#stream_privacy_modal ul.grey-box li input[type=radio],
#subscription_overlay ul.grey-box li input[type=radio] {
margin-right: 5px;
}

View File

@@ -0,0 +1,26 @@
<ul class="grey-box">
<li>
<label class="radio">
<input type="radio" name="privacy" value="public" {{#if is_public}}checked{{/if}} />
{{#tr this}}
<b>Public:</b> anyone can join; anyone can view complete message history without joining
{{/tr}}
</label>
</li>
<li>
<label class="radio">
<input type="radio" name="privacy" value="invite-only" {{#if is_private}}checked{{/if}} />
{{#tr this}}
<b>Private:</b> must be invited by a member; new members can only see messages sent after they join; hidden from non-administrator users
{{/tr}}
</label>
</li>
<li>
<label class="radio">
<input type="radio" name="privacy" value="invite-only-public-history" {{#if is_private_with_public_history}}checked{{/if}} />
{{#tr this}}
<b>Private with history:</b> must be invited by a member; new members can view complete message history; hidden from non-administrator users
{{/tr}}
</label>
</li>
</ul>

View File

@@ -28,6 +28,7 @@
For more information on public/private streams, check out our <a target="_blank" href="https://zulip.readthedocs.io/en/latest/production/security-model.html?highlight=private#messages-and-history">docs</a>.
{{/tr}}
</div>
<ul class="grey-box">
<li>
<label class="radio">
@@ -45,7 +46,16 @@
{{/tr}}
</label>
</li>
<li>
<label class="radio">
<input type="radio" name="privacy" value="invite-only-public-history" />
{{#tr this}}
<b>Private with history:</b> must be invited by a member; new members can view complete message history; hidden from non-administrator users
{{/tr}}
</label>
</li>
</ul>
<div id="announce-new-stream">
<label class="checkbox">
<input type="checkbox" name="announce" value="announce" checked />

View File

@@ -1,33 +1,14 @@
<div id="stream_privacy_modal" class="modal modal-bg" tabindex="-1" role="dialog" aria-labelledby="stream_privacy_modal_label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close close-privacy-modal" aria-label="{{t 'Close' }}"><span aria-hidden="true">&times;</span></button>
<h3 id="stream_privacy_modal_label">{{t "Change stream privacy" }} <span class="email"></span></h3>
</div>
<div class="modal-body">
{{#if is_private}}
{{#tr this}}
This stream is currently <span class="fa fa-lock" aria-hidden="true"></span> <b>an invite-only stream</b>
which means only invited members can join and access its content. Making it public will make
it possible for anyone in your organization to join and access it.
{{/tr}}
{{else}}
{{#tr this}}
This stream is currently <span class="fa fa-globe" aria-hidden="true"></span> <b>a public stream</b>
which means anyone in the organization can join it. Making it private will mean that
only the invited members can join and access its content. Members of the stream can
invite others.
{{/tr}}
{{/if}}
<h3 id="stream_privacy_modal_label">{{t "Change stream permissions for #" }}{{ stream_name }}<span class="email"></span></h3>
</div>
{{ partial "stream_types" }}
<div class="modal-footer">
<button class="btn btn-default close-privacy-modal">{{t "Cancel" }}</button>
<button class="btn{{#if is_private}} btn-primary{{else}} btn-danger{{/if}}" id="change-stream-privacy-button"
<button class="btn btn-danger" id="change-stream-privacy-button"
tabindex="-1" data-stream-id="{{stream_id}}">
{{#if is_private}}
{{t "Make stream public"}}
{{else}}
{{t "Make stream invite-only"}}
{{/if}}
{{t "Change privacy"}}
</button>
</div>
</div>

View File

@@ -1,2 +1,8 @@
{{#if invite_only}}{{t 'This is an <span class="icon-vector-lock"></span> <b>invite-only stream</b>. Only people who have been invited can access its content, but&nbsp;any&nbsp;member&nbsp;of&nbsp;the&nbsp;stream can&nbsp;invite&nbsp;others.' }}
{{else}}{{t 'This is a <span class="icon-vector-globe"></span> <b>public stream</b>. Anybody in your organization can join.' }}{{/if}}
{{#if invite_only}}
{{t 'This is an <span class="icon-vector-lock"></span> <b>invite-only stream</b>. Only people who have been invited can access its content, but&nbsp;any&nbsp;member&nbsp;of&nbsp;the&nbsp;stream can&nbsp;invite&nbsp;others.' }}
{{#if history_public_to_subscribers}}{{t 'New members can view complete message history.' }}
{{else}}{{t 'New members can only see messages sent after they join.' }}
{{/if}}
{{else}}
{{t 'This is a <span class="icon-vector-globe"></span> <b>public stream</b>. Anybody in your organization can join.' }}
{{/if}}