Skip to content
This repository was archived by the owner on Jul 14, 2025. It is now read-only.

Commit ec8a785

Browse files
FIX: Ensure assign plugin respects prioritize_full_name_in_ux site setting (#632)
* WIP * more messing around * undos, notes to self * WIP notes * completed logic and added tests for existing code and implemented code * fixed failing tests * fixed failing tests * added suggested changes * added suggested changes * fix merge * fix linting issues * possible flaky test * removed comment * further user name display changes * implemented suggested change * fixed bug in small action post when assigning or unassigning * fixed breaking tests * refactored test --------- Co-authored-by: Juan David Martinez <[email protected]>
1 parent 3b1ffef commit ec8a785

File tree

10 files changed

+313
-17
lines changed

10 files changed

+313
-17
lines changed

assets/javascripts/discourse/components/assigned-to-post.gjs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ import DMenu from "float-kit/components/d-menu";
99

1010
export default class AssignedToPost extends Component {
1111
@service taskActions;
12+
@service siteSettings;
13+
14+
get nameOrUsername() {
15+
if (this.siteSettings.prioritize_full_name_in_ux) {
16+
return this.args.assignedToUser.name || this.args.assignedToUser.username;
17+
} else {
18+
return this.args.assignedToUser.username;
19+
}
20+
}
1221

1322
@action
1423
unassign() {
@@ -33,7 +42,7 @@ export default class AssignedToPost extends Component {
3342

3443
<a href={{@href}} class="assigned-to-username">
3544
{{#if @assignedToUser}}
36-
{{@assignedToUser.username}}
45+
{{this.nameOrUsername}}
3746
{{else}}
3847
{{@assignedToGroup.name}}
3948
{{/if}}

assets/javascripts/discourse/components/topic-level-assign-menu.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ export default {
7272
const content = [];
7373

7474
if (this.topic.isAssigned()) {
75-
content.push(unassignFromTopicButton(this.topic));
75+
content.push(
76+
unassignFromTopicButton(
77+
this.topic,
78+
this.siteSettings.prioritize_full_name_in_ux
79+
)
80+
);
7681
}
7782

7883
if (this.topic.hasAssignedPosts()) {
@@ -131,9 +136,14 @@ function reassignToSelfButton() {
131136
};
132137
}
133138

134-
function unassignFromTopicButton(topic) {
135-
const username =
139+
function unassignFromTopicButton(topic, prioritize_full_name_in_ux) {
140+
let username =
136141
topic.assigned_to_user?.username || topic.assigned_to_group?.name;
142+
143+
if (topic.assigned_to_user && prioritize_full_name_in_ux) {
144+
username = topic.assigned_to_user?.name || topic.assigned_to_user?.username;
145+
}
146+
137147
const icon = topic.assigned_to_user
138148
? avatarHtml(topic.assigned_to_user, "small")
139149
: iconHTML("user-xmark");

assets/javascripts/discourse/initializers/extend-for-assigns.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const DEPENDENT_KEYS = [
3030
"topic.assigned_to_group",
3131
"currentUser.can_assign",
3232
"topic.assigned_to_user.username",
33+
"topic.assigned_to_user.name",
3334
];
3435

3536
function defaultTitle(topic) {
@@ -481,7 +482,11 @@ function initialize(api) {
481482
}
482483

483484
const icon = iconHTML(assignee.username ? "user-plus" : "group-plus");
484-
const name = assignee.username || assignee.name;
485+
const name =
486+
siteSettings.prioritize_full_name_in_ux || !assignee.username
487+
? assignee.name || assignee.username
488+
: assignee.username;
489+
485490
const tagName = params.tagName || "a";
486491
const href =
487492
tagName === "a"
@@ -553,13 +558,18 @@ function initialize(api) {
553558
)}</span>`;
554559
};
555560

561+
let displayedName = "";
556562
if (assignedToUser) {
563+
displayedName = this.siteSettings.prioritize_full_name_in_ux
564+
? assignedToUser.name || assignedToUser.username
565+
: assignedToUser.username;
566+
557567
assigneeElements.push(
558568
h(
559569
"span.assignee",
560570
new RawHtml({
561571
html: assignedHtml(
562-
assignedToUser.username,
572+
displayedName,
563573
assignedToUserPath(assignedToUser),
564574
"user"
565575
),
@@ -581,10 +591,17 @@ function initialize(api) {
581591
)
582592
);
583593
}
594+
584595
if (indirectlyAssignedTo) {
585596
Object.keys(indirectlyAssignedTo).map((postId) => {
586597
const assignee = indirectlyAssignedTo[postId].assigned_to;
587598
const postNumber = indirectlyAssignedTo[postId].post_number;
599+
600+
displayedName =
601+
this.siteSettings.prioritize_full_name_in_ux || !assignee.username
602+
? assignee.name || assignee.username
603+
: assignee.username;
604+
588605
assigneeElements.push(
589606
h("span.assignee", [
590607
h(
@@ -597,13 +614,14 @@ function initialize(api) {
597614
},
598615
i18n("discourse_assign.assign_post_to_multiple", {
599616
post_number: postNumber,
600-
username: assignee.username || assignee.name,
617+
username: displayedName,
601618
})
602619
),
603620
])
604621
);
605622
});
606623
}
624+
607625
if (!isEmpty(assigneeElements)) {
608626
return h("p.assigned-to", [
609627
assignedToUser ? iconNode("user-plus") : iconNode("group-plus"),

assets/javascripts/discourse/models/assignment.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class Assignment extends EmberObject {
1717
static fromPost(post) {
1818
const assignment = new Assignment();
1919
assignment.username = post.assigned_to.username;
20+
assignment.name = post.assigned_to.name;
2021
assignment.groupName = post.assigned_to.name;
2122
assignment.status = post.assignment_status;
2223
assignment.note = post.assignment_note;
@@ -31,6 +32,7 @@ export class Assignment extends EmberObject {
3132
// and models from server, that's why we have to call it "group_name" now
3233
@tracked group_name;
3334
@tracked username;
35+
@tracked name;
3436
@tracked status;
3537
@tracked note;
3638
targetId;

config/locales/client.en.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ en:
100100
assignable_levels:
101101
title: "Who can assign this group"
102102
user:
103-
notification_level_when_assigned:
103+
notification_level_when_assigned:
104104
label: "When assigned"
105105
watch_topic: "Watch topic"
106106
track_topic: "Track topic"

lib/assigner.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,7 @@ def unassign(silent: false, deactivate: false)
405405
if SiteSetting.unassign_creates_tracking_post && !silent
406406
post_type = SiteSetting.assigns_public ? Post.types[:small_action] : Post.types[:whisper]
407407

408-
custom_fields = {
409-
"action_code_who" => assigned_to.is_a?(User) ? assigned_to.username : assigned_to.name,
410-
}
408+
custom_fields = small_action_username_or_name(assigned_to)
411409

412410
if post_target?
413411
custom_fields.merge!("action_code_path" => "/p/#{@target.id}")
@@ -493,10 +491,20 @@ def queue_notification(assignment)
493491
Jobs.enqueue(:assign_notification, assignment_id: assignment.id)
494492
end
495493

494+
def small_action_username_or_name(assign_to)
495+
if (assign_to.is_a?(User) && SiteSetting.prioritize_full_name_in_ux) ||
496+
!assign_to.try(:username)
497+
custom_fields = { "action_code_who" => assign_to.name || assign_to.username }
498+
else
499+
custom_fields = {
500+
"action_code_who" => assign_to.is_a?(User) ? assign_to.username : assign_to.name,
501+
}
502+
end
503+
custom_fields
504+
end
505+
496506
def add_small_action_post(action_code, assign_to, text)
497-
custom_fields = {
498-
"action_code_who" => assign_to.is_a?(User) ? assign_to.username : assign_to.name,
499-
}
507+
custom_fields = small_action_username_or_name(assign_to)
500508

501509
if post_target?
502510
custom_fields.merge!(

spec/serializers/topic_view_serializer_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
it "includes assigned user in serializer" do
2020
Assigner.new(topic, user).assign(user)
2121
serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian)
22+
expect(serializer.as_json[:topic_view][:assigned_to_user][:name]).to eq(user.name)
2223
expect(serializer.as_json[:topic_view][:assigned_to_user][:username]).to eq(user.username)
2324
expect(serializer.as_json[:topic_view][:assigned_to_group]).to be nil
2425
end

spec/system/assign_post_spec.rb

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# frozen_string_literal: true
2+
3+
describe "Assign | Assigning posts", type: :system do
4+
let(:topic_page) { PageObjects::Pages::Topic.new }
5+
let(:assign_modal) { PageObjects::Modals::Assign.new }
6+
fab!(:staff_user) { Fabricate(:user, groups: [Group[:staff]]) }
7+
fab!(:admin)
8+
fab!(:topic)
9+
fab!(:post1) { Fabricate(:post, topic: topic) }
10+
fab!(:post2) { Fabricate(:post, topic: topic) }
11+
12+
before do
13+
SiteSetting.assign_enabled = true
14+
SiteSetting.prioritize_full_name_in_ux = false
15+
16+
# The system tests in this file are flaky and auth token related so turning this on
17+
SiteSetting.verbose_auth_token_logging = true
18+
19+
sign_in(admin)
20+
end
21+
22+
def assign_post(post, assignee)
23+
topic_page.click_assign_post(post)
24+
assign_modal.assignee = assignee
25+
assign_modal.confirm
26+
end
27+
28+
describe "with open topic" do
29+
before { SiteSetting.prioritize_full_name_in_ux = false }
30+
31+
it "can assign and unassign" do
32+
visit "/t/#{topic.id}"
33+
assign_post(post2, staff_user)
34+
35+
expect(assign_modal).to be_closed
36+
37+
expect(topic_page).to have_assigned_post(user: staff_user, at_post: 3)
38+
39+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(staff_user.username)
40+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(staff_user.username)
41+
42+
visit "/t/#{topic.id}"
43+
44+
topic_page.click_unassign_post(post2)
45+
46+
expect(topic_page).to have_unassigned_from_post(user: staff_user, at_post: 4)
47+
expect(page).to have_no_css("#topic .assigned-to")
48+
end
49+
50+
it "can submit modal form with shortcuts" do
51+
visit "/t/#{topic.id}"
52+
53+
topic_page.click_assign_post(post2)
54+
assign_modal.assignee = staff_user
55+
56+
find("body").send_keys(:tab)
57+
find("body").send_keys(:control, :enter)
58+
59+
expect(assign_modal).to be_closed
60+
expect(topic_page).to have_assigned_post(user: staff_user, at_post: 3)
61+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(staff_user.username)
62+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(staff_user.username)
63+
end
64+
65+
context "when prioritize_full_name_in_ux setting is enabled" do
66+
before { SiteSetting.prioritize_full_name_in_ux = true }
67+
68+
it "shows the user's name after assign" do
69+
visit "/t/#{topic.id}"
70+
71+
assign_post(post2, staff_user)
72+
73+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(staff_user.name)
74+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(staff_user.name)
75+
end
76+
77+
it "show the user's username if there is no name" do
78+
visit "/t/#{topic.id}"
79+
staff_user.name = nil
80+
staff_user.save
81+
staff_user.reload
82+
83+
assign_post(post2, staff_user)
84+
85+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(staff_user.username)
86+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(staff_user.username)
87+
end
88+
end
89+
90+
context "when assigns are not public" do
91+
before { SiteSetting.assigns_public = false }
92+
93+
it "assigned small action post has 'private-assign' in class attribute" do
94+
visit "/t/#{topic.id}"
95+
96+
assign_post(post2, staff_user)
97+
98+
expect(assign_modal).to be_closed
99+
expect(topic_page).to have_assigned_post(
100+
user: staff_user,
101+
at_post: 3,
102+
class_attribute: ".private-assign",
103+
)
104+
end
105+
end
106+
107+
context "when unassign_on_close is set to true" do
108+
before { SiteSetting.unassign_on_close = true }
109+
110+
it "unassigns the topic on close" do
111+
visit "/t/#{topic.id}"
112+
113+
assign_post(post2, staff_user)
114+
115+
expect(assign_modal).to be_closed
116+
expect(topic_page).to have_assigned_post(user: staff_user, at_post: 3)
117+
118+
find(".timeline-controls .toggle-admin-menu").click
119+
find(".topic-admin-close").click
120+
121+
expect(find("#post_4")).to have_content(
122+
I18n.t("js.action_codes.closed.enabled", when: "just now"),
123+
)
124+
expect(page).to have_no_css("#post_5")
125+
expect(page).to have_no_css("#topic .assigned-to")
126+
end
127+
128+
it "can assign the previous assignee" do
129+
visit "/t/#{topic.id}"
130+
131+
assign_post(post2, staff_user)
132+
133+
expect(assign_modal).to be_closed
134+
expect(topic_page).to have_assigned_post(user: staff_user, at_post: 3)
135+
136+
find(".timeline-controls .toggle-admin-menu").click
137+
find(".topic-admin-close").click
138+
139+
expect(find("#post_4")).to have_content(
140+
I18n.t("js.action_codes.closed.enabled", when: "just now"),
141+
)
142+
expect(page).to have_no_css("#post_5")
143+
expect(page).to have_no_css("#topic .assigned-to")
144+
145+
assign_post(post2, staff_user)
146+
147+
expect(page).to have_no_css("#post_5")
148+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(staff_user.username)
149+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(staff_user.username)
150+
end
151+
152+
context "when reassign_on_open is set to true" do
153+
before { SiteSetting.reassign_on_open = true }
154+
155+
it "reassigns the topic on open" do
156+
visit "/t/#{topic.id}"
157+
158+
assign_post(post2, staff_user)
159+
expect(assign_modal).to be_closed
160+
expect(topic_page).to have_assigned_post(user: staff_user, at_post: 3)
161+
162+
find(".timeline-controls .toggle-admin-menu").click
163+
find(".topic-admin-close").click
164+
165+
expect(find("#post_4")).to have_content(
166+
I18n.t("js.action_codes.closed.enabled", when: "just now"),
167+
)
168+
expect(page).to have_no_css("#post_5")
169+
expect(page).to have_no_css("#topic .assigned-to")
170+
171+
find(".timeline-controls .toggle-admin-menu").click
172+
find(".topic-admin-open").click
173+
174+
expect(find("#post_5")).to have_content(
175+
I18n.t("js.action_codes.closed.disabled", when: "just now"),
176+
)
177+
expect(page).to have_no_css("#post_6")
178+
expect(topic_page.find_post_assign(post1.post_number)).to have_content(
179+
staff_user.username,
180+
)
181+
expect(topic_page.find_post_assign(post2.post_number)).to have_content(
182+
staff_user.username,
183+
)
184+
end
185+
end
186+
end
187+
end
188+
end

0 commit comments

Comments
 (0)