FIX: Various assignment status issues (#536)

This commit is contained in:
Jarek Radosz 2023-12-08 11:48:34 +01:00 committed by GitHub
parent 9556df664c
commit 5888025dec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 100 additions and 96 deletions

View File

@ -36,7 +36,7 @@
@id="assign-status" @id="assign-status"
@content={{this.availableStatuses}} @content={{this.availableStatuses}}
@value={{this.status}} @value={{this.status}}
@onChange={{action (mut @model.status)}} @onChange={{fn (mut @model.status)}}
/> />
</div> </div>
{{/if}} {{/if}}

View File

@ -26,9 +26,7 @@ export default class AssignUserForm extends Component {
get status() { get status() {
return ( return (
this.args.model.status || this.args.model.status || this.siteSettings.assign_statuses.split("|")[0]
this.args.model.target.assignment_status ||
this.siteSettings.assign_statuses.split("|")[0]
); );
} }

View File

@ -1,8 +1,9 @@
import Component from "@glimmer/component"; import Component from "@glimmer/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { TrackedObject } from "@ember-compat/tracked-built-ins";
export default class AssignUser extends Component { export default class AssignUser extends Component {
model = {}; model = new TrackedObject({});
// `submit` property will be mutated by the `AssignUserForm` component // `submit` property will be mutated by the `AssignUserForm` component
formApi = { formApi = {
@ -14,6 +15,7 @@ export default class AssignUser extends Component {
return this.args.performAndRefresh({ return this.args.performAndRefresh({
type: "assign", type: "assign",
username: this.model.username, username: this.model.username,
status: this.model.status,
note: this.model.note, note: this.model.note,
}); });
} }

View File

@ -1,7 +1,7 @@
<DModal class="assign" @title={{this.title}} @closeModal={{@closeModal}}> <DModal class="assign" @title={{this.title}} @closeModal={{@closeModal}}>
<:body> <:body>
<AssignUserForm <AssignUserForm
@model={{@model}} @model={{this.model}}
@onSubmit={{this.onSubmit}} @onSubmit={{this.onSubmit}}
@formApi={{this.formApi}} @formApi={{this.formApi}}
/> />
@ -12,7 +12,7 @@
class="btn-primary" class="btn-primary"
@action={{this.formApi.submit}} @action={{this.formApi.submit}}
@label={{if @label={{if
@model.reassign this.model.reassign
"discourse_assign.reassign.title" "discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign" "discourse_assign.assign_modal.assign"
}} }}

View File

@ -1,11 +1,14 @@
import Component from "@glimmer/component"; import Component from "@glimmer/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import { TrackedObject } from "@ember-compat/tracked-built-ins";
import I18n from "I18n"; import I18n from "I18n";
export default class AssignUser extends Component { export default class AssignUser extends Component {
@service taskActions; @service taskActions;
model = new TrackedObject(this.args.model);
// `submit` property will be mutated by the `AssignUserForm` component // `submit` property will be mutated by the `AssignUserForm` component
formApi = { formApi = {
submit() {}, submit() {},
@ -14,7 +17,7 @@ export default class AssignUser extends Component {
get title() { get title() {
let i18nSuffix; let i18nSuffix;
switch (this.args.model.targetType) { switch (this.model.targetType) {
case "Post": case "Post":
i18nSuffix = "_post_modal"; i18nSuffix = "_post_modal";
break; break;
@ -25,7 +28,7 @@ export default class AssignUser extends Component {
return I18n.t( return I18n.t(
`discourse_assign.assign${i18nSuffix}.${ `discourse_assign.assign${i18nSuffix}.${
this.args.model.reassign ? "reassign_title" : "title" this.model.reassign ? "reassign_title" : "title"
}` }`
); );
} }
@ -33,6 +36,6 @@ export default class AssignUser extends Component {
@action @action
async onSubmit() { async onSubmit() {
this.args.closeModal(); this.args.closeModal();
await this.taskActions.assign(this.args.model); await this.taskActions.assign(this.model);
} }
} }

View File

@ -616,7 +616,6 @@ function initialize(api) {
topicAssignee, topicAssignee,
assignedToIndirectly.map((assigned) => ({ assignedToIndirectly.map((assigned) => ({
assignee: assigned.assigned_to, assignee: assigned.assigned_to,
status: assigned.assignment_status,
note: assigned.assignment_note, note: assigned.assignment_note,
})) }))
) )
@ -928,57 +927,23 @@ export default {
api.addUserSearchOption("assignableGroups"); api.addUserSearchOption("assignableGroups");
if (api.addBulkActionButton) { api.addBulkActionButton({
api.addBulkActionButton({ label: "topics.bulk.assign",
label: "topics.bulk.assign", icon: "user-plus",
icon: "user-plus", class: "btn-default assign-topics",
class: "btn-default assign-topics", action({ setComponent }) {
action({ setComponent }) { setComponent(BulkAssign);
setComponent(BulkAssign); },
}, });
});
api.addBulkActionButton({ api.addBulkActionButton({
label: "topics.bulk.unassign", label: "topics.bulk.unassign",
icon: "user-times", icon: "user-times",
class: "btn-default unassign-topics", class: "btn-default unassign-topics",
action({ performAndRefresh }) { action({ performAndRefresh }) {
performAndRefresh({ type: "unassign" }); performAndRefresh({ type: "unassign" });
}, },
}); });
} else {
// TODO: Remove this path after core 3.1.0.beta7 is released
const {
default: TopicButtonAction,
addBulkButton,
} = require("discourse/controllers/topic-bulk-actions");
TopicButtonAction.reopen({
actions: {
showReAssign() {
const controller = getOwner(this).lookup(
"controller:bulk-assign"
);
controller.set("model", { username: "", note: "" });
this.send("changeBulkTemplate", "modal/bulk-assign");
},
unassignTopics() {
this.performAndRefresh({ type: "unassign" });
},
},
});
addBulkButton("showReAssign", "assign", {
icon: "user-plus",
class: "btn-default assign-topics",
});
addBulkButton("unassignTopics", "unassign", {
icon: "user-times",
class: "btn-default unassign-topics",
});
}
}); });
}, },
}; };

View File

@ -66,13 +66,8 @@
margin-left: 5px; margin-left: 5px;
} }
.modal.assign { .d-modal.assign {
.modal-inner-container { .d-modal__body {
width: 400px;
}
.d-modal__body,
.modal-body {
overflow-y: unset; overflow-y: unset;
} }

View File

@ -223,14 +223,15 @@ class ::Assigner
def update_details(assign_to, note, status, skip_small_action_post: false) def update_details(assign_to, note, status, skip_small_action_post: false)
case case
when @target.assignment.note != note && @target.assignment.status != status && status.present? when note.present? && status.present? && @target.assignment.note != note &&
@target.assignment.status != status
small_action_text = <<~TEXT small_action_text = <<~TEXT
Status: #{@target.assignment.status} → #{status} Status: #{@target.assignment.status} → #{status}
#{note} #{note}
TEXT TEXT
change_type = "details" change_type = "details"
when @target.assignment.note != note when note.present? && @target.assignment.note != note
small_action_text = note small_action_text = note
change_type = "note" change_type = "note"
when @target.assignment.status != status when @target.assignment.status != status

View File

@ -645,7 +645,11 @@ after_initialize do
if @user.can_assign? if @user.can_assign?
assign_user = User.find_by_username(@operation[:username]) assign_user = User.find_by_username(@operation[:username])
topics.each do |topic| topics.each do |topic|
Assigner.new(topic, @user).assign(assign_user, note: @operation[:note]) Assigner.new(topic, @user).assign(
assign_user,
status: @operation[:status],
note: @operation[:note],
)
end end
end end
end end
@ -657,6 +661,7 @@ after_initialize do
end end
register_permitted_bulk_action_parameter :username register_permitted_bulk_action_parameter :username
register_permitted_bulk_action_parameter :status
register_permitted_bulk_action_parameter :note register_permitted_bulk_action_parameter :note
add_to_class(:user_bookmark_base_serializer, :assigned_to) do add_to_class(:user_bookmark_base_serializer, :assigned_to) do

View File

@ -44,7 +44,7 @@ acceptance("Discourse Assign | Assign mobile", function (needs) {
assert.true(menu.rowByValue("assign").exists()); assert.true(menu.rowByValue("assign").exists());
await menu.selectRowByValue("assign"); await menu.selectRowByValue("assign");
assert.dom(".assign.modal").exists("assign modal opens"); assert.dom(".assign.d-modal").exists("assign modal opens");
}); });
}); });
@ -86,12 +86,12 @@ acceptance("Discourse Assign | Assign desktop", function (needs) {
.exists("assign to post button exists"); .exists("assign to post button exists");
await click("#post_2 .extra-buttons .d-icon-user-plus"); await click("#post_2 .extra-buttons .d-icon-user-plus");
assert.dom(".assign.modal").exists("assign modal opens"); assert.dom(".assign.d-modal").exists("assign modal opens");
const menu = selectKit(".assign.modal .user-chooser"); const menu = selectKit(".assign.d-modal .user-chooser");
assert.true(menu.isExpanded(), "user selector is expanded"); assert.true(menu.isExpanded(), "user selector is expanded");
await click(".assign.modal .btn-primary"); await click(".assign.d-modal .btn-primary");
assert.dom(".error-label").includesText("Choose a user to assign"); assert.dom(".error-label").includesText("Choose a user to assign");
await menu.expand(); await menu.expand();
@ -108,16 +108,16 @@ acceptance("Discourse Assign | Assign desktop", function (needs) {
}); });
await fillIn("#assign-modal-note", "a note!"); await fillIn("#assign-modal-note", "a note!");
await click(".assign.modal .btn-primary"); await click(".assign.d-modal .btn-primary");
assert.dom(".assign.modal").doesNotExist("assign modal closes"); assert.dom(".assign.d-modal").doesNotExist("assign modal closes");
}); });
test("Footer dropdown contains button", async function (assert) { test("Footer dropdown contains button", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
await click("#topic-footer-button-assign"); await click("#topic-footer-button-assign");
assert.dom(".assign.modal").exists("assign modal opens"); assert.dom(".assign.d-modal").exists("assign modal opens");
}); });
}); });
@ -151,12 +151,35 @@ acceptance("Discourse Assign | Assign Status enabled", function (needs) {
}); });
test("Modal contains status dropdown", async function (assert) { test("Modal contains status dropdown", async function (assert) {
pretender.put("/assign/assign", ({ requestBody }) => {
const body = parsePostData(requestBody);
assert.strictEqual(body.target_type, "Topic");
assert.strictEqual(body.target_id, "280");
assert.strictEqual(body.username, "eviltrout");
assert.strictEqual(body.status, "In Progress");
return response({ success: true });
});
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
await click("#topic-footer-button-assign"); await click("#topic-footer-button-assign");
assert assert
.dom(".assign.modal #assign-status") .dom(".assign.d-modal #assign-status")
.exists("assign status dropdown exists"); .exists("assign status dropdown exists");
const statusDropdown = selectKit("#assign-status");
assert.strictEqual(statusDropdown.header().value(), "New");
await statusDropdown.expand();
await statusDropdown.selectRowByValue("In Progress");
assert.strictEqual(statusDropdown.header().value(), "In Progress");
const menu = selectKit(".assign.d-modal .user-chooser");
await menu.expand();
await menu.selectRowByIndex(0);
await click(".assign.d-modal .btn-primary");
}); });
}); });
@ -190,7 +213,7 @@ acceptance("Discourse Assign | Assign Status disabled", function (needs) {
await click("#topic-footer-button-assign"); await click("#topic-footer-button-assign");
assert assert
.dom(".assign.modal #assign-status") .dom(".assign.d-modal #assign-status")
.doesNotExist("assign status dropdown doesn't exists"); .doesNotExist("assign status dropdown doesn't exists");
}); });
}); });

View File

@ -13,7 +13,10 @@ acceptance("Discourse Assign | Bulk actions", function (needs) {
moderator: true, moderator: true,
can_assign: true, can_assign: true,
}); });
needs.settings({ assign_enabled: true }); needs.settings({
assign_enabled: true,
enable_assign_status: true,
});
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
server.get("/assign/suggestions", () => { server.get("/assign/suggestions", () => {
@ -35,6 +38,22 @@ acceptance("Discourse Assign | Bulk actions", function (needs) {
}); });
test("Assigning users to topics", async function (assert) { test("Assigning users to topics", async function (assert) {
pretender.put("/topics/bulk", ({ requestBody }) => {
const body = parsePostData(requestBody);
assert.deepEqual(body.operation, {
type: "assign",
username: "eviltrout",
status: "In Progress",
note: "a note!",
});
assert.deepEqual(body["topic_ids[]"], [
topic1.dataset.topicId,
topic2.dataset.topicId,
]);
return response({ success: true });
});
await visit("/latest"); await visit("/latest");
await click("button.bulk-select"); await click("button.bulk-select");
@ -61,22 +80,15 @@ acceptance("Discourse Assign | Bulk actions", function (needs) {
await menu.selectRowByIndex(0); await menu.selectRowByIndex(0);
assert.strictEqual(menu.header().value(), "eviltrout"); assert.strictEqual(menu.header().value(), "eviltrout");
pretender.put("/topics/bulk", ({ requestBody }) => {
const body = parsePostData(requestBody);
assert.deepEqual(body.operation, {
type: "assign",
username: "eviltrout",
note: "a note!",
});
assert.deepEqual(body["topic_ids[]"], [
topic1.dataset.topicId,
topic2.dataset.topicId,
]);
return response({ success: true });
});
await fillIn("#assign-modal-note", "a note!"); await fillIn("#assign-modal-note", "a note!");
const statusDropdown = selectKit("#assign-status");
assert.strictEqual(statusDropdown.header().value(), "New");
await statusDropdown.expand();
await statusDropdown.selectRowByValue("In Progress");
assert.strictEqual(statusDropdown.header().value(), "In Progress");
await click(".topic-bulk-actions-modal .btn-primary"); await click(".topic-bulk-actions-modal .btn-primary");
}); });
}); });