FIX: Use a default hashtag icon color for user with no permission (#21825)

One user can create a post or chat message with a hashtag they
have permission to use, but then when other users look at that
post they will see an empty space next to the hashtag because they
do not have the permission to load the colors in CSS classes for
the related category.

This fixes the issue by adding a default color with a special
CSS class if the user doesn't have permission to see the linked
channel/category on the hashtag.
This commit is contained in:
Martin Brennan 2023-06-07 10:15:39 +10:00 committed by GitHub
parent af74cf5c77
commit 69eecf92d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 4 deletions

View File

@ -31,6 +31,10 @@ export default class CategoryHashtagType extends HashtagTypeBase {
} }
generateIconHTML(hashtag) { generateIconHTML(hashtag) {
return `<span class="hashtag-category-badge hashtag-color--${this.type}-${hashtag.id}"></span>`; const hashtagId = parseInt(hashtag.id, 10);
const colorCssClass = !this.preloadedData.mapBy("id").includes(hashtagId)
? "hashtag-missing"
: `hashtag-color--${this.type}-${hashtag.id}`;
return `<span class="hashtag-category-badge ${colorCssClass}"></span>`;
} }
} }

View File

@ -25,6 +25,10 @@ a.hashtag {
.d-icon { .d-icon {
font-size: var(--font-down-1); font-size: var(--font-down-1);
margin: 0 0.2em 0 0.1em; margin: 0 0.2em 0 0.1em;
&.hashtag-missing {
color: var(--primary-medium);
}
} }
img.emoji { img.emoji {
@ -43,6 +47,10 @@ a.hashtag {
height: 9px; height: 9px;
margin-right: 5px; margin-right: 5px;
display: inline-block; display: inline-block;
&.hashtag-missing {
background-color: var(--primary-medium);
}
} }
} }

View File

@ -25,8 +25,12 @@ export default class ChannelHashtagType extends HashtagTypeBase {
} }
generateIconHTML(hashtag) { generateIconHTML(hashtag) {
const hashtagId = parseInt(hashtag.id, 10);
const colorCssClass = !this.preloadedData.mapBy("id").includes(hashtagId)
? "hashtag-missing"
: `hashtag-color--${this.type}-${hashtag.id}`;
return iconHTML(hashtag.icon, { return iconHTML(hashtag.icon, {
class: `hashtag-color--${this.type}-${hashtag.id}`, class: colorCssClass,
}); });
} }
} }

View File

@ -80,4 +80,44 @@ describe "Using #hashtag autocompletion to search for and lookup channels",
<a class=\"hashtag-cooked\" href=\"#{tag.url}\" data-type=\"tag\" data-slug=\"razed\" data-id="#{tag.id}"><svg class=\"fa d-icon d-icon-tag svg-icon hashtag-color--tag-#{tag.id} svg-string\" xmlns=\"http://www.w3.org/2000/svg\"><use href=\"#tag\"></use></svg><span>razed</span></a> <a class=\"hashtag-cooked\" href=\"#{tag.url}\" data-type=\"tag\" data-slug=\"razed\" data-id="#{tag.id}"><svg class=\"fa d-icon d-icon-tag svg-icon hashtag-color--tag-#{tag.id} svg-string\" xmlns=\"http://www.w3.org/2000/svg\"><use href=\"#tag\"></use></svg><span>razed</span></a>
HTML HTML
end end
context "when a user cannot access the category for a cooked channel hashtag" do
fab!(:admin) { Fabricate(:admin) }
fab!(:manager_group) { Fabricate(:group, name: "Managers") }
fab!(:private_category) do
Fabricate(:private_category, name: "Management", slug: "management", group: manager_group)
end
fab!(:admin_group_user) { Fabricate(:group_user, user: admin, group: manager_group) }
fab!(:management_channel) do
Fabricate(:chat_channel, chatable: private_category, slug: "management")
end
fab!(:post_with_private_category) do
Fabricate(
:post,
topic: topic,
raw: "this is a secret #management::channel channel",
user: admin,
)
end
fab!(:message_with_private_channel) do
Fabricate(
:chat_message,
chat_channel: channel1,
user: admin,
message: "this is a secret #management channel",
)
end
before { management_channel.add(admin) }
it "shows a default color and css class for the channel icon in a post" do
topic_page.visit_topic(topic, post_number: post_with_private_category.post_number)
expect(page).to have_css(".hashtag-cooked .hashtag-missing")
end
it "shows a default color and css class for the channel icon in a channel" do
chat_page.visit_channel(channel1)
expect(page).to have_css(".hashtag-cooked .hashtag-missing")
end
end
end end

View File

@ -93,4 +93,21 @@ describe "Using #hashtag autocompletion to search for and lookup categories and
<a class=\"hashtag-cooked\" href=\"#{tag.url}\" data-type=\"tag\" data-slug=\"cooltag\" data-id=\"#{tag.id}\"><svg class=\"fa d-icon d-icon-tag svg-icon hashtag-color--tag-#{tag.id} svg-string\" xmlns=\"http://www.w3.org/2000/svg\"><use href=\"#tag\"></use></svg><span>cooltag</span></a> <a class=\"hashtag-cooked\" href=\"#{tag.url}\" data-type=\"tag\" data-slug=\"cooltag\" data-id=\"#{tag.id}\"><svg class=\"fa d-icon d-icon-tag svg-icon hashtag-color--tag-#{tag.id} svg-string\" xmlns=\"http://www.w3.org/2000/svg\"><use href=\"#tag\"></use></svg><span>cooltag</span></a>
HTML HTML
end end
context "when a user cannot access the category for a hashtag cooked in another post" do
fab!(:admin) { Fabricate(:admin) }
fab!(:manager_group) { Fabricate(:group, name: "Managers") }
fab!(:private_category) do
Fabricate(:private_category, name: "Management", slug: "management", group: manager_group)
end
fab!(:admin_group_user) { Fabricate(:group_user, user: admin, group: manager_group) }
fab!(:post_with_private_category) do
Fabricate(:post, topic: topic, raw: "this is a secret #management category", user: admin)
end
it "shows a default color and css class for the category icon square" do
topic_page.visit_topic(topic, post_number: post_with_private_category.post_number)
expect(page).to have_css(".hashtag-cooked .hashtag-missing")
end
end
end end

View File

@ -8,8 +8,10 @@ module PageObjects
@fast_edit_component = PageObjects::Components::FastEditor.new @fast_edit_component = PageObjects::Components::FastEditor.new
end end
def visit_topic(topic) def visit_topic(topic, post_number: nil)
page.visit "/t/#{topic.id}" url = "/t/#{topic.id}"
url += "/#{post_number}" if post_number
page.visit url
self self
end end