FEATURE: display warning when sharing a topic in a restricted category (#14820)

* FEATURE: display warning when sharing a topic in a restricted category

If a topic belongs to a category that is not readable by everyone, display a text warning of "Only visible to members of groups: [group_a], [group_b]"

* DEV: Adding a new category means we need to bump this value

* DEV: pass category to showModal
This commit is contained in:
jbrw 2021-11-16 11:49:41 -05:00 committed by GitHub
parent b6677fb126
commit e306d84c56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 449 additions and 4 deletions

View File

@ -76,7 +76,7 @@ export default Component.extend({
shareModal() { shareModal() {
const { topic } = this.composer; const { topic } = this.composer;
const controller = showModal("share-topic"); const controller = showModal("share-topic", { model: topic.category });
controller.setProperties({ controller.setProperties({
allowInvites: allowInvites:
topic.details.can_invite_to && topic.details.can_invite_to &&

View File

@ -9,13 +9,29 @@ import showModal from "discourse/lib/show-modal";
import { bufferedProperty } from "discourse/mixins/buffered-content"; import { bufferedProperty } from "discourse/mixins/buffered-content";
import ModalFunctionality from "discourse/mixins/modal-functionality"; import ModalFunctionality from "discourse/mixins/modal-functionality";
import I18n from "I18n"; import I18n from "I18n";
import Category from "discourse/models/category";
export default Controller.extend( export default Controller.extend(
ModalFunctionality, ModalFunctionality,
bufferedProperty("invite"), bufferedProperty("invite"),
{ {
topic: null,
restrictedGroups: null,
onShow() { onShow() {
this.set("showNotifyUsers", false); this.set("showNotifyUsers", false);
if (this.model && this.model.read_restricted) {
Category.reloadBySlugPath(this.model.slug).then((result) => {
this.setProperties({
restrictedGroups: result.category.group_permissions.map(
(g) => g.group_name
),
});
});
} else {
this.setProperties({ restrictedGroups: null });
}
}, },
@discourseComputed("topic.shareUrl") @discourseComputed("topic.shareUrl")
@ -39,6 +55,21 @@ export default Controller.extend(
); );
}, },
@discourseComputed("restrictedGroups")
hasRestrictedGroups(groups) {
return !!groups;
},
@discourseComputed("restrictedGroups")
restrictedGroupsCount(groups) {
return groups.length;
},
@discourseComputed("restrictedGroups")
restrictedGroupsDisplayText(groups) {
return groups.join(", ");
},
@action @action
onChangeUsers(usernames) { onChangeUsers(usernames) {
this.set("users", usernames.uniq()); this.set("users", usernames.uniq());

View File

@ -23,7 +23,9 @@ export default {
}, },
title: "topic.share.help", title: "topic.share.help",
action() { action() {
const controller = showModal("share-topic"); const controller = showModal("share-topic", {
model: this.topic.category,
});
controller.setProperties({ controller.setProperties({
allowInvites: this.canInviteTo && !this.inviteDisabled, allowInvites: this.canInviteTo && !this.inviteDisabled,
topic: this.topic, topic: this.topic,

View File

@ -12,6 +12,13 @@
{{copy-button selector="input.invite-link"}} {{copy-button selector="input.invite-link"}}
</div> </div>
</div> </div>
{{#if hasRestrictedGroups}}
<div class="link-share-restricted-groups">
{{i18n "topic.share.restricted_groups" count=restrictedGroupsCount}}
{{restrictedGroupsDisplayText}}
</div>
{{/if}}
<div class="link-share-actions"> <div class="link-share-actions">
<div class="sources"> <div class="sources">
{{#each sources as |s|}} {{#each sources as |s|}}

View File

@ -48,6 +48,23 @@ acceptance("Share and Invite modal", function (needs) {
assert.ok(exists("#share-link"), "it shows the share modal"); assert.ok(exists("#share-link"), "it shows the share modal");
}); });
test("Share topic in a restricted category", async function (assert) {
await visit("/t/topic-in-restricted-group/2481");
assert.ok(
exists("#topic-footer-button-share-and-invite"),
"the button exists"
);
await click("#topic-footer-button-share-and-invite");
assert.ok(exists(".share-topic-modal"), "it shows the modal");
assert.ok(
exists(".link-share-restricted-groups"),
"it shows restricted warning"
);
});
}); });
acceptance("Share and Invite modal - mobile", function (needs) { acceptance("Share and Invite modal - mobile", function (needs) {

View File

@ -48,5 +48,18 @@ export default {
slug: "testing", slug: "testing",
can_edit: true can_edit: true
} }
},
"/c/2481/show.json": {
category: {
id: 2481,
name: "restricted-group",
color: "e9dd00",
text_color: "000000",
slug: "restricted-group",
read_restricted: true,
permission: null,
group_permissions: [{ permission_type: 1, group_name: "moderators" }],
} }
},
}; };

View File

@ -438,6 +438,23 @@ export default {
default_view: "latest", default_view: "latest",
subcategory_list_style: "boxes", subcategory_list_style: "boxes",
}, },
{
id: 2481,
name: "Restricted Group",
color: "0E78BD",
text_color: "FFFFFF",
slug: "restricted-group",
topic_count: 137,
post_count: 1142,
description: "A restricted group",
topic_url: "/t/category-definition-for-restricted-group/11",
read_restricted: true,
permission: 1,
notification_level: null,
show_subcategory_list: true,
default_view: "latest",
subcategory_list_style: "boxes",
},
], ],
post_action_types: [ post_action_types: [
{ {

View File

@ -5855,4 +5855,347 @@ export default {
}, },
}, },
}, },
"/t/2481/1.json": {
post_stream: {
posts: [
{
id: 2441,
name: "",
username: "group_moderator",
avatar_template: "/images/avatar.png",
created_at: "2020-07-24T17:48:55.419Z",
cooked:
"<p>Here is my new topic. I am a group category moderator!</p>",
post_number: 1,
post_type: 1,
updated_at: "2020-07-24T17:48:55.419Z",
reply_count: 0,
reply_to_post_number: null,
quote_count: 0,
incoming_link_count: 0,
reads: 2,
readers_count: 1,
score: 0,
yours: true,
topic_id: 2481,
topic_slug: "topic-in-restricted-group",
display_username: "",
primary_group_name: "group_moderators",
flair_name: "group_moderators",
flair_url: "cheese",
flair_bg_color: "ff0",
flair_color: "",
version: 1,
can_edit: true,
can_delete: false,
can_recover: false,
can_wiki: false,
read: true,
user_title: "a title",
title_is_group: false,
bookmarked: false,
bookmarks: [],
actions_summary: [
{
id: 3,
can_act: true,
},
{
id: 4,
can_act: true,
},
{
id: 8,
can_act: true,
},
{
id: 7,
can_act: true,
},
],
moderator: false,
admin: false,
staff: false,
group_moderator: true,
user_id: 3,
hidden: false,
trust_level: 1,
deleted_at: null,
user_deleted: false,
edit_reason: null,
can_view_edit_history: true,
wiki: false,
reviewable_id: 0,
reviewable_score_count: 0,
reviewable_score_pending_count: 0,
},
{
id: 2442,
name: "",
username: "normal_user",
avatar_template: "/images/avatar.png",
created_at: "2020-07-24T17:50:01.263Z",
cooked: "<p>A fascinating topic worthy of discussion.</p>",
post_number: 2,
post_type: 1,
updated_at: "2020-07-24T17:50:01.263Z",
reply_count: 0,
reply_to_post_number: null,
quote_count: 0,
incoming_link_count: 0,
reads: 2,
readers_count: 1,
score: 0,
yours: false,
topic_id: 2481,
topic_slug: "topic-in-restricted-group",
display_username: "",
primary_group_name: null,
flair_name: null,
flair_url: null,
flair_bg_color: null,
flair_color: null,
version: 1,
can_edit: false,
can_delete: false,
can_recover: false,
can_wiki: false,
read: true,
user_title: null,
bookmarked: false,
bookmarks: [],
actions_summary: [
{
id: 2,
can_act: true,
},
{
id: 3,
can_act: true,
},
{
id: 4,
can_act: true,
},
{
id: 8,
can_act: true,
},
{
id: 6,
can_act: true,
},
{
id: 7,
can_act: true,
},
],
moderator: false,
admin: false,
staff: false,
user_id: 2,
hidden: false,
trust_level: 1,
deleted_at: null,
user_deleted: false,
edit_reason: null,
can_view_edit_history: true,
wiki: false,
reviewable_id: 0,
reviewable_score_count: 0,
reviewable_score_pending_count: 0,
},
{
id: 2443,
name: "",
username: "group_moderator",
avatar_template: "/images/avatar.png",
created_at: "2020-07-24T17:50:17.274Z",
cooked: '<aside class="onebox allowlistedgeneric" data-onebox-src="https://example.com/57350945"><header class="source"><a href="https://example.com/57350945" target="_blank" rel="noopener">XYZ News Site</a> </header> <article class="onebox-body"> <div class="aspect-image" style="--aspect-ratio:690/388;"><img src="/assets/logo.png" class="thumbnail d-lazyload" width="690" height="388"></div> <h3><a href="https://example.com/57350945" target="_blank" rel="noopener">News Headline</a></h3> <p>Article summary</p> </article> <div class="onebox-metadata"> </div> <div style="clear: both"></div> </aside>',
post_number: 3,
post_type: 1,
updated_at: "2020-07-24T17:50:17.274Z",
reply_count: 0,
reply_to_post_number: null,
quote_count: 0,
incoming_link_count: 0,
reads: 2,
readers_count: 1,
score: 0,
yours: true,
topic_id: 2481,
topic_slug: "topic-in-restricted-group",
display_username: "",
primary_group_name: "group_moderators",
flair_url: "cheese",
flair_bg_color: "ff0",
flair_color: "",
version: 1,
can_edit: true,
can_delete: true,
can_recover: false,
can_wiki: false,
read: true,
user_title: "a title",
title_is_group: false,
bookmarked: false,
bookmarks: [],
actions_summary: [
{
id: 3,
can_act: true,
},
{
id: 4,
can_act: true,
},
{
id: 8,
can_act: true,
},
{
id: 7,
can_act: true,
},
],
moderator: false,
admin: false,
staff: false,
group_moderator: true,
user_id: 3,
hidden: false,
trust_level: 1,
deleted_at: null,
user_deleted: false,
edit_reason: null,
can_view_edit_history: true,
wiki: false,
reviewable_id: 0,
reviewable_score_count: 0,
reviewable_score_pending_count: 0,
},
],
stream: [2441, 2442, 2443],
},
timeline_lookup: [[1, 0]],
id: 2481,
title: "A Topic in a Restricted Group",
fancy_title: "A Topic in a Restricted Group",
posts_count: 3,
created_at: "2020-07-24T17:48:54.986Z",
views: 2,
reply_count: 0,
like_count: 0,
last_posted_at: "2020-07-24T17:50:17.274Z",
visible: true,
closed: false,
archived: false,
has_summary: false,
archetype: "regular",
slug: "topic-in-restricted-group",
category_id: 2481,
word_count: 22,
deleted_at: null,
user_id: 3,
featured_link: null,
pinned_globally: false,
pinned_at: null,
pinned_until: null,
image_url: null,
draft: null,
draft_key: "topic_2481",
draft_sequence: 1,
posted: true,
unpinned: null,
pinned: false,
current_post_number: 3,
highest_post_number: 3,
last_read_post_number: 3,
last_read_post_id: 43,
deleted_by: null,
actions_summary: [
{
id: 4,
count: 0,
hidden: false,
can_act: true,
},
{
id: 8,
count: 0,
hidden: false,
can_act: true,
},
{
id: 7,
count: 0,
hidden: false,
can_act: true,
},
],
chunk_size: 20,
bookmarked: false,
bookmarks: [],
topic_timer: null,
message_bus_last_id: 4,
participant_count: 2,
show_read_indicator: false,
thumbnails: null,
details: {
notification_level: 3,
notifications_reason_id: 1,
can_delete: true,
can_edit: true,
can_create_post: true,
can_move_posts: true,
can_reply_as_new_topic: true,
can_flag_topic: true,
can_review_topic: true,
can_close_topic: true,
can_archive_topic: true,
can_toggle_topic_visibility: true,
can_split_merge_topic: true,
can_edit_staff_notes: true,
can_pin_unpin_topic: true,
can_moderate_category: true,
participants: [
{
id: 3,
username: "group_moderator",
name: "",
avatar_template: "/images/avatar.png",
post_count: 2,
primary_group_name: "group_moderators",
flar_name: "group_moderators",
flair_url: "cheese",
flair_color: "",
flair_bg_color: "ff0",
},
{
id: 2,
username: "normal_user",
name: "",
avatar_template: "/images/avatar.png",
post_count: 1,
primary_group_name: null,
flair_name: null,
flair_url: null,
flair_color: null,
flair_bg_color: null,
},
],
created_by: {
id: 3,
username: "group_moderator",
name: "",
avatar_template: "/images/avatar.png",
},
last_poster: {
id: 3,
username: "group_moderator",
name: "",
avatar_template: "/images/avatar.png",
},
},
},
}; };

View File

@ -281,6 +281,9 @@ export function applyDefaultHandlers(pretender) {
pretender.get("/t/2480.json", () => pretender.get("/t/2480.json", () =>
response(fixturesByUrl["/t/2480/1.json"]) response(fixturesByUrl["/t/2480/1.json"])
); );
pretender.get("/t/2481.json", () =>
response(fixturesByUrl["/t/2481/1.json"])
);
pretender.get("/t/id_for/:slug", () => { pretender.get("/t/id_for/:slug", () => {
return response({ return response({
@ -344,6 +347,10 @@ export function applyDefaultHandlers(pretender) {
response(fixturesByUrl["/c/1/show.json"]) response(fixturesByUrl["/c/1/show.json"])
); );
pretender.get("/c/restricted-group/find_by_slug.json", () =>
response(fixturesByUrl["/c/2481/show.json"])
);
pretender.put("/categories/:category_id", (request) => { pretender.put("/categories/:category_id", (request) => {
const category = parsePostData(request.requestBody); const category = parsePostData(request.requestBody);
category.id = parseInt(request.params.category_id, 10); category.id = parseInt(request.params.category_id, 10);

View File

@ -107,7 +107,7 @@ discourseModule(
assert.strictEqual( assert.strictEqual(
this.subject.rows().length, this.subject.rows().length,
21, 22,
"all categories are visible" "all categories are visible"
); );

View File

@ -13,6 +13,11 @@
} }
} }
.link-share-restricted-groups {
margin-top: 0.5em;
color: var(--danger-medium);
}
.link-share-actions { .link-share-actions {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;

View File

@ -2825,6 +2825,9 @@ en:
help: "share a link to this topic" help: "share a link to this topic"
instructions: "Share a link to this topic:" instructions: "Share a link to this topic:"
copied: "Topic link copied." copied: "Topic link copied."
restricted_groups:
one: "Only visible to members of group:"
other: "Only visible to members of groups:"
notify_users: notify_users:
title: "Notify" title: "Notify"
instructions: "Notify the following users about this topic:" instructions: "Notify the following users about this topic:"