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:
parent
700dfe551b
commit
a4ce90e855
|
@ -15,10 +15,13 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
taskActions: service(),
|
taskActions: service(),
|
||||||
autofocus: not("capabilities.touch"),
|
autofocus: not("capabilities.touch"),
|
||||||
assigneeName: or("model.username", "model.group_name"),
|
assigneeName: or("model.username", "model.group_name"),
|
||||||
|
assigneeError: false,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.allowedGroups = [];
|
|
||||||
|
this.set("allowedGroups", []);
|
||||||
|
this.set("assigneeError", false);
|
||||||
|
|
||||||
ajax("/assign/suggestions").then((data) => {
|
ajax("/assign/suggestions").then((data) => {
|
||||||
if (this.isDestroying || this.isDestroyed) {
|
if (this.isDestroying || this.isDestroyed) {
|
||||||
|
@ -77,6 +80,11 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
return this.bulkAction(this.model.username);
|
return this.bulkAction(this.model.username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.assigneeName) {
|
||||||
|
this.set("assigneeError", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let path = "/assign/assign";
|
let path = "/assign/assign";
|
||||||
|
|
||||||
if (isEmpty(this.get("model.username"))) {
|
if (isEmpty(this.get("model.username"))) {
|
||||||
|
@ -136,6 +144,7 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
},
|
},
|
||||||
|
|
||||||
setGroupOrUser(name) {
|
setGroupOrUser(name) {
|
||||||
|
this.set("assigneeError", false);
|
||||||
if (this.allowedGroupsForAssignment.includes(name)) {
|
if (this.allowedGroupsForAssignment.includes(name)) {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
"model.username": null,
|
"model.username": null,
|
||||||
|
|
|
@ -924,10 +924,7 @@ export default {
|
||||||
actions: {
|
actions: {
|
||||||
showReAssign() {
|
showReAssign() {
|
||||||
this.set("assignUser.isBulkAction", true);
|
this.set("assignUser.isBulkAction", true);
|
||||||
this.set("assignUser.model", {
|
this.set("assignUser.model", { username: "" });
|
||||||
username: "",
|
|
||||||
description: "discourse_assign.assign_bulk_modal.description",
|
|
||||||
});
|
|
||||||
this.send("changeBulkTemplate", "modal/assign-user");
|
this.send("changeBulkTemplate", "modal/assign-user");
|
||||||
},
|
},
|
||||||
unassignTopics() {
|
unassignTopics() {
|
||||||
|
|
|
@ -29,10 +29,6 @@ export default Service.extend({
|
||||||
this.i18nSuffix(options.targetType) +
|
this.i18nSuffix(options.targetType) +
|
||||||
`.${options.isAssigned ? "reassign_title" : "title"}`,
|
`.${options.isAssigned ? "reassign_title" : "title"}`,
|
||||||
model: {
|
model: {
|
||||||
description:
|
|
||||||
`discourse_assign.${options.isAssigned ? "reassign" : "assign"}` +
|
|
||||||
this.i18nSuffix(options.targetType) +
|
|
||||||
".description",
|
|
||||||
reassign: options.isAssigned,
|
reassign: options.isAssigned,
|
||||||
username: target.assigned_to_user?.username,
|
username: target.assigned_to_user?.username,
|
||||||
group_name: target.assigned_to_group?.name,
|
group_name: target.assigned_to_group?.name,
|
||||||
|
|
|
@ -1,31 +1,32 @@
|
||||||
{{#d-modal-body class="assign"}}
|
{{#d-modal-body class="assign"}}
|
||||||
<div>
|
<div>
|
||||||
<p>{{i18n model.description}}</p>
|
<div class="control-group {{if this.assigneeError "assignee-error"}}">
|
||||||
{{email-group-user-chooser
|
<label>{{i18n "discourse_assign.assign_modal.assignee_label"}}</label>
|
||||||
autocomplete="off"
|
{{email-group-user-chooser
|
||||||
value=assigneeName
|
autocomplete="off"
|
||||||
onChange=(action "assignUsername")
|
value=assigneeName
|
||||||
autofocus="autofocus"
|
onChange=(action "assignUsername")
|
||||||
showUserStatus=true
|
autofocus="autofocus"
|
||||||
options=(hash
|
showUserStatus=true
|
||||||
mobilePlacementStrategy="absolute"
|
caretIcon="search"
|
||||||
filterPlaceholder=placeholderKey
|
options=(hash
|
||||||
includeGroups=true
|
mobilePlacementStrategy="absolute"
|
||||||
customSearchOptions=(hash assignableGroups=true)
|
filterPlaceholder=placeholderKey
|
||||||
groupMembersOf=allowedGroups
|
includeGroups=true
|
||||||
maximum=1
|
customSearchOptions=(hash assignableGroups=true defaultSearchResults=this.assignSuggestions)
|
||||||
autofocus=autofocus
|
groupMembersOf=allowedGroups
|
||||||
tabindex=1
|
maximum=1
|
||||||
)
|
autofocus=autofocus
|
||||||
}}
|
tabindex=1
|
||||||
<div class="assign-suggestions">
|
)
|
||||||
{{#each assignSuggestions as |user|}}
|
}}
|
||||||
<a href {{action "assignUser" user.username }}>
|
{{#if this.assigneeError}}
|
||||||
{{avatar user imageSize="small"}}
|
<span class="error-label">
|
||||||
{{decorate-username-selector user.username}}
|
{{d-icon "exclamation-triangle"}} {{i18n "discourse_assign.assign_modal.choose_assignee"}}
|
||||||
</a>
|
</span>
|
||||||
{{/each}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if this.statusEnabled}}
|
{{#if this.statusEnabled}}
|
||||||
<div class="control-group assign-status">
|
<div class="control-group assign-status">
|
||||||
<label>{{i18n "discourse_assign.assign_modal.status_label"}}</label>
|
<label>{{i18n "discourse_assign.assign_modal.status_label"}}</label>
|
||||||
|
@ -37,8 +38,11 @@
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="control-group assign-status">
|
<div class="control-group assign-status">
|
||||||
<label>{{i18n "discourse_assign.assign_modal.note_label"}}</label>
|
<label>
|
||||||
|
{{i18n "discourse_assign.assign_modal.note_label"}} <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")}}
|
{{textarea id="assign-modal-note" value=model.note key-down=(action "handleTextAreaKeydown")}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,4 +56,5 @@
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
disabled=disabled
|
disabled=disabled
|
||||||
}}
|
}}
|
||||||
|
<DModalCancel @close={{route-action "closeModal"}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,37 +66,37 @@
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assign.modal-body .email-group-user-chooser {
|
.assign-user-modal {
|
||||||
display: block;
|
.modal-inner-container {
|
||||||
width: 300px;
|
width: 400px;
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assign-user-modal p {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assign-suggestions {
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
margin-right: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.groups {
|
label {
|
||||||
margin-top: 5px;
|
font-weight: bold;
|
||||||
a {
|
|
||||||
margin-right: 5px;
|
.label-optional {
|
||||||
|
color: var(--primary-medium);
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.on-holiday {
|
.email-group-user-chooser {
|
||||||
position: absolute;
|
width: 100%;
|
||||||
margin-left: -18px;
|
|
||||||
margin-top: 14px;
|
.caret-icon {
|
||||||
color: var(--primary-medium);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,19 +50,17 @@ en:
|
||||||
help: "Edit assignment details"
|
help: "Edit assignment details"
|
||||||
reassign_modal:
|
reassign_modal:
|
||||||
title: "Reassign Topic"
|
title: "Reassign Topic"
|
||||||
description: "Enter the name of the user you'd like to Reassign this topic"
|
|
||||||
assign_modal:
|
assign_modal:
|
||||||
title: "Assign Topic"
|
title: "Assign Topic"
|
||||||
reassign_title: "Reassign Topic"
|
reassign_title: "Reassign Topic"
|
||||||
description: "Enter the name of the user you'd like to assign this topic"
|
|
||||||
assign: "Assign"
|
assign: "Assign"
|
||||||
|
assignee_label: Assignee
|
||||||
|
choose_assignee: Choose a user to assign.
|
||||||
note_label: Note
|
note_label: Note
|
||||||
|
optional_label: "(optional)"
|
||||||
status_label: Status
|
status_label: Status
|
||||||
assign_post_modal:
|
assign_post_modal:
|
||||||
title: "Assign Post"
|
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:
|
claim:
|
||||||
title: "claim"
|
title: "claim"
|
||||||
help: "Assign topic to yourself"
|
help: "Assign topic to yourself"
|
||||||
|
|
|
@ -46,8 +46,6 @@ acceptance("Discourse Assign | Assign mobile", function (needs) {
|
||||||
assert.ok(menu.rowByValue("assign").exists());
|
assert.ok(menu.rowByValue("assign").exists());
|
||||||
await menu.selectRowByValue("assign");
|
await menu.selectRowByValue("assign");
|
||||||
assert.ok(exists(".assign.modal-body"), "assign modal opens");
|
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");
|
await click("#topic-footer-button-assign");
|
||||||
|
|
||||||
assert.ok(exists(".assign.modal-body"), "assign modal opens");
|
assert.ok(exists(".assign.modal-body"), "assign modal opens");
|
||||||
|
|
||||||
await click(".assign-suggestions .avatar");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ discourseModule("Unit | Service | task-actions", function () {
|
||||||
assert.deepEqual(modalCall[1], {
|
assert.deepEqual(modalCall[1], {
|
||||||
title: "discourse_assign.assign_modal.title",
|
title: "discourse_assign.assign_modal.title",
|
||||||
model: {
|
model: {
|
||||||
description: "discourse_assign.assign_modal.description",
|
|
||||||
reassign: false,
|
reassign: false,
|
||||||
username: "tomtom",
|
username: "tomtom",
|
||||||
group_name: "cats",
|
group_name: "cats",
|
||||||
|
|
Loading…
Reference in New Issue