UX: Improve assign modal design (#403)

Implements a new design that improves the user experience:

- add a clear cancel button
- add an indication the note is optional
- change the plus icon to a search icon
- show an error when the user tries to assign without choosing an assignee
- move suggestions to default search results
- focus search input when modal is displayed
This commit is contained in:
Bianca Nenciu 2022-12-21 14:49:24 +02:00 committed by GitHub
parent 700dfe551b
commit a4ce90e855
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 71 additions and 71 deletions

View File

@ -15,10 +15,13 @@ export default Controller.extend(ModalFunctionality, {
taskActions: service(),
autofocus: not("capabilities.touch"),
assigneeName: or("model.username", "model.group_name"),
assigneeError: false,
init() {
this._super(...arguments);
this.allowedGroups = [];
this.set("allowedGroups", []);
this.set("assigneeError", false);
ajax("/assign/suggestions").then((data) => {
if (this.isDestroying || this.isDestroyed) {
@ -77,6 +80,11 @@ export default Controller.extend(ModalFunctionality, {
return this.bulkAction(this.model.username);
}
if (!this.assigneeName) {
this.set("assigneeError", true);
return;
}
let path = "/assign/assign";
if (isEmpty(this.get("model.username"))) {
@ -136,6 +144,7 @@ export default Controller.extend(ModalFunctionality, {
},
setGroupOrUser(name) {
this.set("assigneeError", false);
if (this.allowedGroupsForAssignment.includes(name)) {
this.setProperties({
"model.username": null,

View File

@ -924,10 +924,7 @@ export default {
actions: {
showReAssign() {
this.set("assignUser.isBulkAction", true);
this.set("assignUser.model", {
username: "",
description: "discourse_assign.assign_bulk_modal.description",
});
this.set("assignUser.model", { username: "" });
this.send("changeBulkTemplate", "modal/assign-user");
},
unassignTopics() {

View File

@ -29,10 +29,6 @@ export default Service.extend({
this.i18nSuffix(options.targetType) +
`.${options.isAssigned ? "reassign_title" : "title"}`,
model: {
description:
`discourse_assign.${options.isAssigned ? "reassign" : "assign"}` +
this.i18nSuffix(options.targetType) +
".description",
reassign: options.isAssigned,
username: target.assigned_to_user?.username,
group_name: target.assigned_to_group?.name,

View File

@ -1,31 +1,32 @@
{{#d-modal-body class="assign"}}
<div>
<p>{{i18n model.description}}</p>
{{email-group-user-chooser
autocomplete="off"
value=assigneeName
onChange=(action "assignUsername")
autofocus="autofocus"
showUserStatus=true
options=(hash
mobilePlacementStrategy="absolute"
filterPlaceholder=placeholderKey
includeGroups=true
customSearchOptions=(hash assignableGroups=true)
groupMembersOf=allowedGroups
maximum=1
autofocus=autofocus
tabindex=1
)
}}
<div class="assign-suggestions">
{{#each assignSuggestions as |user|}}
<a href {{action "assignUser" user.username }}>
{{avatar user imageSize="small"}}
{{decorate-username-selector user.username}}
</a>
{{/each}}
<div class="control-group {{if this.assigneeError "assignee-error"}}">
<label>{{i18n "discourse_assign.assign_modal.assignee_label"}}</label>
{{email-group-user-chooser
autocomplete="off"
value=assigneeName
onChange=(action "assignUsername")
autofocus="autofocus"
showUserStatus=true
caretIcon="search"
options=(hash
mobilePlacementStrategy="absolute"
filterPlaceholder=placeholderKey
includeGroups=true
customSearchOptions=(hash assignableGroups=true defaultSearchResults=this.assignSuggestions)
groupMembersOf=allowedGroups
maximum=1
autofocus=autofocus
tabindex=1
)
}}
{{#if this.assigneeError}}
<span class="error-label">
{{d-icon "exclamation-triangle"}} {{i18n "discourse_assign.assign_modal.choose_assignee"}}
</span>
{{/if}}
</div>
{{#if this.statusEnabled}}
<div class="control-group assign-status">
<label>{{i18n "discourse_assign.assign_modal.status_label"}}</label>
@ -37,8 +38,11 @@
}}
</div>
{{/if}}
<div class="control-group assign-status">
<label>{{i18n "discourse_assign.assign_modal.note_label"}}</label>
<label>
{{i18n "discourse_assign.assign_modal.note_label"}}&nbsp;<span class="label-optional">{{i18n "discourse_assign.assign_modal.optional_label"}}</span>
</label>
{{textarea id="assign-modal-note" value=model.note key-down=(action "handleTextAreaKeydown")}}
</div>
</div>
@ -52,4 +56,5 @@
class="btn-primary"
disabled=disabled
}}
<DModalCancel @close={{route-action "closeModal"}} />
</div>

View File

@ -66,37 +66,37 @@
margin-left: 5px;
}
.assign.modal-body .email-group-user-chooser {
display: block;
width: 300px;
margin-top: 5px;
}
.assign-user-modal p {
margin-top: 0;
}
.assign-suggestions {
margin-top: 15px;
margin-bottom: 15px;
img {
margin-right: 5px;
cursor: pointer;
.assign-user-modal {
.modal-inner-container {
width: 400px;
}
.groups {
margin-top: 5px;
a {
margin-right: 5px;
label {
font-weight: bold;
.label-optional {
color: var(--primary-medium);
font-weight: normal;
}
}
.on-holiday {
position: absolute;
margin-left: -18px;
margin-top: 14px;
color: var(--primary-medium);
.email-group-user-chooser {
width: 100%;
.caret-icon {
color: var(--primary-medium);
}
}
.control-group.assignee-error {
.select-kit-header {
border-color: var(--danger);
}
.error-label {
color: var(--danger);
font-size: var(--font-down-1);
}
}
}

View File

@ -50,19 +50,17 @@ en:
help: "Edit assignment details"
reassign_modal:
title: "Reassign Topic"
description: "Enter the name of the user you'd like to Reassign this topic"
assign_modal:
title: "Assign Topic"
reassign_title: "Reassign Topic"
description: "Enter the name of the user you'd like to assign this topic"
assign: "Assign"
assignee_label: Assignee
choose_assignee: Choose a user to assign.
note_label: Note
optional_label: "(optional)"
status_label: Status
assign_post_modal:
title: "Assign Post"
description: "Enter the name of the user you'd like to assign this post"
assign_bulk_modal:
description: "Enter the name of the user you'd like to assign these topics"
claim:
title: "claim"
help: "Assign topic to yourself"

View File

@ -46,8 +46,6 @@ acceptance("Discourse Assign | Assign mobile", function (needs) {
assert.ok(menu.rowByValue("assign").exists());
await menu.selectRowByValue("assign");
assert.ok(exists(".assign.modal-body"), "assign modal opens");
await click(".assign-suggestions .avatar");
});
});
@ -102,8 +100,6 @@ acceptance("Discourse Assign | Assign desktop", function (needs) {
await click("#topic-footer-button-assign");
assert.ok(exists(".assign.modal-body"), "assign modal opens");
await click(".assign-suggestions .avatar");
});
});

View File

@ -21,7 +21,6 @@ discourseModule("Unit | Service | task-actions", function () {
assert.deepEqual(modalCall[1], {
title: "discourse_assign.assign_modal.title",
model: {
description: "discourse_assign.assign_modal.description",
reassign: false,
username: "tomtom",
group_name: "cats",