FEATURE: Reassign workflow (#231)
Build a new workflow that adds a dropdown in place of the old assign button with the ability to Re-assign a new user / group to an assigned topic Re-assign yourself to an assigned topic Unassign a user / group from an assigned topic
This commit is contained in:
parent
0e4649d507
commit
98103586b2
|
@ -44,27 +44,11 @@ module DiscourseAssign
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign
|
def assign
|
||||||
target_id = params.require(:target_id)
|
reassign_or_assign_target(action: "assign")
|
||||||
target_type = params.require(:target_type)
|
end
|
||||||
username = params.permit(:username)['username']
|
|
||||||
group_name = params.permit(:group_name)['group_name']
|
|
||||||
|
|
||||||
assign_to = username.present? ? User.find_by(username_lower: username.downcase) : Group.where("LOWER(name) = ?", group_name.downcase).first
|
def reassign
|
||||||
|
reassign_or_assign_target(action: "reassign")
|
||||||
raise Discourse::NotFound unless assign_to
|
|
||||||
raise Discourse::NotFound if !Assignment.valid_type?(target_type)
|
|
||||||
target = target_type.constantize.where(id: target_id).first
|
|
||||||
raise Discourse::NotFound unless target
|
|
||||||
|
|
||||||
# perhaps?
|
|
||||||
#Scheduler::Defer.later "assign topic" do
|
|
||||||
assign = Assigner.new(target, current_user).assign(assign_to)
|
|
||||||
|
|
||||||
if assign[:success]
|
|
||||||
render json: success_json
|
|
||||||
else
|
|
||||||
render json: translate_failure(assign[:reason], assign_to), status: 400
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def assigned
|
def assigned
|
||||||
|
@ -185,5 +169,29 @@ module DiscourseAssign
|
||||||
def ensure_assign_allowed
|
def ensure_assign_allowed
|
||||||
raise Discourse::InvalidAccess.new unless current_user.can_assign?
|
raise Discourse::InvalidAccess.new unless current_user.can_assign?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reassign_or_assign_target(action:)
|
||||||
|
target_id = params.require(:target_id)
|
||||||
|
target_type = params.require(:target_type)
|
||||||
|
username = params.permit(:username)['username']
|
||||||
|
group_name = params.permit(:group_name)['group_name']
|
||||||
|
|
||||||
|
assign_to = username.present? ? User.find_by(username_lower: username.downcase) : Group.where("LOWER(name) = ?", group_name.downcase).first
|
||||||
|
|
||||||
|
raise Discourse::NotFound unless assign_to
|
||||||
|
raise Discourse::NotFound if !Assignment.valid_type?(target_type)
|
||||||
|
target = target_type.constantize.where(id: target_id).first
|
||||||
|
raise Discourse::NotFound unless target
|
||||||
|
|
||||||
|
# perhaps?
|
||||||
|
#Scheduler::Defer.later "assign topic" do
|
||||||
|
assign = Assigner.new(target, current_user).send(action, assign_to)
|
||||||
|
|
||||||
|
if assign[:success]
|
||||||
|
render json: success_json
|
||||||
|
else
|
||||||
|
render json: translate_failure(assign[:reason], assign_to), status: 400
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import { not, or } from "@ember/object/computed";
|
import { not, or } from "@ember/object/computed";
|
||||||
import { isEmpty } from "@ember/utils";
|
import { isEmpty } from "@ember/utils";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
topicBulkActions: controller(),
|
topicBulkActions: controller(),
|
||||||
|
@ -39,14 +38,43 @@ export default Controller.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("model.targetType")
|
reassignOrAssignTarget(assign_action) {
|
||||||
i18nSuffix(targetType) {
|
if (this.isBulkAction) {
|
||||||
switch (targetType) {
|
this.bulkAction(this.model.username);
|
||||||
case "Post":
|
return;
|
||||||
return "_post_modal";
|
|
||||||
case "Topic":
|
|
||||||
return "_modal";
|
|
||||||
}
|
}
|
||||||
|
let path = "/assign/" + assign_action;
|
||||||
|
|
||||||
|
if (isEmpty(this.get("model.username"))) {
|
||||||
|
this.model.target.set("assigned_to_user", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty(this.get("model.group_name"))) {
|
||||||
|
this.model.target.set("assigned_to_group", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
isEmpty(this.get("model.username")) &&
|
||||||
|
isEmpty(this.get("model.group_name"))
|
||||||
|
) {
|
||||||
|
path = "/assign/unassign";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.send("closeModal");
|
||||||
|
|
||||||
|
return ajax(path, {
|
||||||
|
type: "PUT",
|
||||||
|
data: {
|
||||||
|
username: this.get("model.username"),
|
||||||
|
group_name: this.get("model.group_name"),
|
||||||
|
target_id: this.get("model.target.id"),
|
||||||
|
target_type: this.get("model.targetType"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.get("model.onSuccess")?.();
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -77,48 +105,47 @@ export default Controller.extend({
|
||||||
|
|
||||||
@action
|
@action
|
||||||
assign() {
|
assign() {
|
||||||
|
this.reassignOrAssignTarget("assign");
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
reassign() {
|
||||||
|
this.reassignOrAssignTarget("reassign");
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
reassignUser(name) {
|
||||||
if (this.isBulkAction) {
|
if (this.isBulkAction) {
|
||||||
this.bulkAction(this.model.username);
|
this.bulkAction(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let path = "/assign/assign";
|
|
||||||
|
|
||||||
if (isEmpty(this.get("model.username"))) {
|
if (this.allowedGroupsForAssignment.includes(name)) {
|
||||||
this.model.target.set("assigned_to_user", null);
|
this.setProperties({
|
||||||
|
"model.username": null,
|
||||||
|
"model.group_name": name,
|
||||||
|
"model.allowedGroups": this.taskActions.allowedGroups,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setProperties({
|
||||||
|
"model.username": name,
|
||||||
|
"model.group_name": null,
|
||||||
|
"model.allowedGroups": this.taskActions.allowedGroups,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEmpty(this.get("model.group_name"))) {
|
if (name) {
|
||||||
this.model.target.set("assigned_to_group", null);
|
return this.reassign();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
isEmpty(this.get("model.username")) &&
|
|
||||||
isEmpty(this.get("model.group_name"))
|
|
||||||
) {
|
|
||||||
path = "/assign/unassign";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.send("closeModal");
|
|
||||||
|
|
||||||
return ajax(path, {
|
|
||||||
type: "PUT",
|
|
||||||
data: {
|
|
||||||
username: this.get("model.username"),
|
|
||||||
group_name: this.get("model.group_name"),
|
|
||||||
target_id: this.get("model.target.id"),
|
|
||||||
target_type: this.get("model.targetType"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
if (this.get("model.onSuccess")) {
|
|
||||||
this.get("model.onSuccess")();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(popupAjaxError);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@action
|
@action
|
||||||
assignUsername(selected) {
|
assignUsername(selected) {
|
||||||
this.assignUser(selected.firstObject);
|
this.assignUser(selected.firstObject);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
reassignUsername(selected) {
|
||||||
|
this.reassignUser(selected.firstObject);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,9 +14,17 @@ import TopicButtonAction, {
|
||||||
import { inject } from "@ember/controller";
|
import { inject } from "@ember/controller";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { isEmpty } from "@ember/utils";
|
import { isEmpty } from "@ember/utils";
|
||||||
|
import { registerTopicFooterDropdown } from "discourse/lib/register-topic-footer-dropdown";
|
||||||
|
|
||||||
const PLUGIN_ID = "discourse-assign";
|
const PLUGIN_ID = "discourse-assign";
|
||||||
|
|
||||||
|
const DEPENDENT_KEYS = [
|
||||||
|
"topic.assigned_to_user",
|
||||||
|
"topic.assigned_to_group",
|
||||||
|
"currentUser.can_assign",
|
||||||
|
"topic.assigned_to_user.username",
|
||||||
|
];
|
||||||
|
|
||||||
function titleForState(name) {
|
function titleForState(name) {
|
||||||
if (name) {
|
if (name) {
|
||||||
return I18n.t("discourse_assign.unassign.help", {
|
return I18n.t("discourse_assign.unassign.help", {
|
||||||
|
@ -27,14 +35,124 @@ function titleForState(name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defaultTitle(topic) {
|
||||||
|
return titleForState(
|
||||||
|
topic.get("topic.assigned_to_user.username") ||
|
||||||
|
topic.get("topic.assigned_to_group.name")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function includeIsAssignedOnTopic(api) {
|
||||||
|
api.modifyClass("model:topic", {
|
||||||
|
pluginId: PLUGIN_ID,
|
||||||
|
isAssigned() {
|
||||||
|
return this.assigned_to_user || this.assigned_to_group;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function registerTopicFooterButtons(api) {
|
function registerTopicFooterButtons(api) {
|
||||||
|
registerTopicFooterDropdown({
|
||||||
|
id: "reassign",
|
||||||
|
|
||||||
|
action(id) {
|
||||||
|
if (!this.get("currentUser.can_assign")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskActions = getOwner(this).lookup("service:task-actions");
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case "unassign": {
|
||||||
|
this.set("topic.assigned_to_user", null);
|
||||||
|
this.set("topic.assigned_to_group", null);
|
||||||
|
taskActions.unassign(this.topic.id).then(() => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "reassign-self": {
|
||||||
|
this.set("topic.assigned_to_user", null);
|
||||||
|
this.set("topic.assigned_to_group", null);
|
||||||
|
taskActions
|
||||||
|
.reassignUserToTopic(this.currentUser, this.topic)
|
||||||
|
.then(() => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "reassign": {
|
||||||
|
taskActions.reassign(this.topic).set("model.onSuccess", () => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
noneItem() {
|
||||||
|
const user = this.get("topic.assigned_to_user");
|
||||||
|
const group = this.get("topic.assigned_to_group");
|
||||||
|
const label = I18n.t("discourse_assign.unassign.title_w_ellipsis");
|
||||||
|
const groupLabel = I18n.t("discourse_assign.unassign.title");
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
name: htmlSafe(
|
||||||
|
`${renderAvatar(user, {
|
||||||
|
imageSize: "tiny",
|
||||||
|
ignoreTitle: true,
|
||||||
|
})}<span class="unassign-label">${label}</span>`
|
||||||
|
),
|
||||||
|
};
|
||||||
|
} else if (group) {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
name: htmlSafe(
|
||||||
|
`<span class="unassign-label">${groupLabel}</span> @${group.name}...`
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
|
classNames: ["reassign"],
|
||||||
|
content() {
|
||||||
|
const content = [
|
||||||
|
{ id: "unassign", name: I18n.t("discourse_assign.unassign.title") },
|
||||||
|
];
|
||||||
|
if (
|
||||||
|
this.topic.isAssigned() &&
|
||||||
|
this.get("topic.assigned_to_user")?.username !==
|
||||||
|
this.currentUser.username
|
||||||
|
) {
|
||||||
|
content.push({
|
||||||
|
id: "reassign-self",
|
||||||
|
name: I18n.t("discourse_assign.reassign.to_self"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
content.push({
|
||||||
|
id: "reassign",
|
||||||
|
name: I18n.t("discourse_assign.reassign.title_w_ellipsis"),
|
||||||
|
});
|
||||||
|
return content;
|
||||||
|
},
|
||||||
|
|
||||||
|
displayed() {
|
||||||
|
return !this.site.mobileView && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
api.registerTopicFooterButton({
|
api.registerTopicFooterButton({
|
||||||
id: "assign",
|
id: "assign",
|
||||||
icon() {
|
icon() {
|
||||||
const hasAssignement =
|
return this.topic.isAssigned()
|
||||||
this.get("topic.assigned_to_user") ||
|
|
||||||
this.get("topic.assigned_to_group");
|
|
||||||
return hasAssignement
|
|
||||||
? this.site.mobileView
|
? this.site.mobileView
|
||||||
? "user-times"
|
? "user-times"
|
||||||
: null
|
: null
|
||||||
|
@ -42,47 +160,13 @@ function registerTopicFooterButtons(api) {
|
||||||
},
|
},
|
||||||
priority: 250,
|
priority: 250,
|
||||||
translatedTitle() {
|
translatedTitle() {
|
||||||
return titleForState(
|
defaultTitle(this);
|
||||||
this.get("topic.assigned_to_user.username") ||
|
|
||||||
this.get("topic.assigned_to_group.name")
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
translatedAriaLabel() {
|
translatedAriaLabel() {
|
||||||
return titleForState(
|
defaultTitle(this);
|
||||||
this.get("topic.assigned_to_user.username") ||
|
|
||||||
this.get("topic.assigned_to_group.name")
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
translatedLabel() {
|
translatedLabel() {
|
||||||
const user = this.get("topic.assigned_to_user");
|
return I18n.t("discourse_assign.assign.title");
|
||||||
const group = this.get("topic.assigned_to_group");
|
|
||||||
const label = I18n.t("discourse_assign.unassign.title");
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
if (this.site.mobileView) {
|
|
||||||
return htmlSafe(
|
|
||||||
`<span class="unassign-label"><span class="text">${label}</span><span class="username">${
|
|
||||||
user.username
|
|
||||||
}</span></span>${renderAvatar(user, {
|
|
||||||
imageSize: "small",
|
|
||||||
ignoreTitle: true,
|
|
||||||
})}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return htmlSafe(
|
|
||||||
`${renderAvatar(user, {
|
|
||||||
imageSize: "tiny",
|
|
||||||
ignoreTitle: true,
|
|
||||||
})}<span class="unassign-label">${label}</span>`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (group) {
|
|
||||||
return htmlSafe(
|
|
||||||
`<span class="unassign-label">${label}</span> @${group.name}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return I18n.t("discourse_assign.assign.title");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
action() {
|
action() {
|
||||||
if (!this.get("currentUser.can_assign")) {
|
if (!this.get("currentUser.can_assign")) {
|
||||||
|
@ -90,20 +174,19 @@ function registerTopicFooterButtons(api) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskActions = getOwner(this).lookup("service:task-actions");
|
const taskActions = getOwner(this).lookup("service:task-actions");
|
||||||
const topic = this.topic;
|
|
||||||
|
|
||||||
if (topic.assigned_to_user || topic.assigned_to_group) {
|
if (this.topic.isAssigned()) {
|
||||||
this.set("topic.assigned_to_user", null);
|
this.set("topic.assigned_to_user", null);
|
||||||
this.set("topic.assigned_to_group", null);
|
this.set("topic.assigned_to_group", null);
|
||||||
taskActions.unassign(topic.id, "Topic").then(() => {
|
taskActions.unassign(this.topic.id, "Topic").then(() => {
|
||||||
this.appEvents.trigger("post-stream:refresh", {
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
id: topic.postStream.firstPostId,
|
id: this.topic.postStream.firstPostId,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskActions.assign(topic).set("model.onSuccess", () => {
|
taskActions.assign(this.topic).set("model.onSuccess", () => {
|
||||||
this.appEvents.trigger("post-stream:refresh", {
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
id: topic.postStream.firstPostId,
|
id: this.topic.postStream.firstPostId,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -112,14 +195,183 @@ function registerTopicFooterButtons(api) {
|
||||||
return this.site.mobileView;
|
return this.site.mobileView;
|
||||||
},
|
},
|
||||||
classNames: ["assign"],
|
classNames: ["assign"],
|
||||||
dependentKeys: [
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
"topic.assigned_to_user",
|
|
||||||
"topic.assigned_to_group",
|
|
||||||
"currentUser.can_assign",
|
|
||||||
"topic.assigned_to_user.username",
|
|
||||||
],
|
|
||||||
displayed() {
|
displayed() {
|
||||||
return this.currentUser && this.currentUser.can_assign;
|
return this.currentUser?.can_assign && !this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
api.registerTopicFooterButton({
|
||||||
|
id: "unassign-mobile-header",
|
||||||
|
translatedTitle() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedAriaLabel() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedLabel() {
|
||||||
|
const user = this.get("topic.assigned_to_user");
|
||||||
|
const group = this.get("topic.assigned_to_group");
|
||||||
|
const label = I18n.t("discourse_assign.assigned_to_w_ellipsis");
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class="unassign-label"><span class="text">${label}</span><span class="username">${
|
||||||
|
user.username
|
||||||
|
}</span></span>${renderAvatar(user, {
|
||||||
|
imageSize: "small",
|
||||||
|
ignoreTitle: true,
|
||||||
|
})}`
|
||||||
|
);
|
||||||
|
} else if (group) {
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class="unassign-label">${label}</span> @${group.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dropdown() {
|
||||||
|
return this.currentUser?.can_assign && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
classNames: ["assign"],
|
||||||
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
|
displayed() {
|
||||||
|
// only display the button in the mobile view
|
||||||
|
return this.site.mobileView;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
api.registerTopicFooterButton({
|
||||||
|
id: "unassign-mobile",
|
||||||
|
icon() {
|
||||||
|
return "user-times";
|
||||||
|
},
|
||||||
|
translatedTitle() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedAriaLabel() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedLabel() {
|
||||||
|
const label = I18n.t("discourse_assign.unassign.title");
|
||||||
|
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class="unassign-label"><span class="text">${label}</span></span>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
action() {
|
||||||
|
if (!this.get("currentUser.can_assign")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskActions = getOwner(this).lookup("service:task-actions");
|
||||||
|
|
||||||
|
this.set("topic.assigned_to_user", null);
|
||||||
|
this.set("topic.assigned_to_group", null);
|
||||||
|
taskActions.unassign(this.topic.id).then(() => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
dropdown() {
|
||||||
|
return this.currentUser?.can_assign && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
classNames: ["assign"],
|
||||||
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
|
displayed() {
|
||||||
|
// only display the button in the mobile view
|
||||||
|
return this.site.mobileView && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
api.registerTopicFooterButton({
|
||||||
|
id: "reassign-self-mobile",
|
||||||
|
icon() {
|
||||||
|
return "user-plus";
|
||||||
|
},
|
||||||
|
translatedTitle() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedAriaLabel() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedLabel() {
|
||||||
|
const label = I18n.t("discourse_assign.reassign.to_self");
|
||||||
|
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class="unassign-label"><span class="text">${label}</span></span>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
action() {
|
||||||
|
if (!this.get("currentUser.can_assign")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskActions = getOwner(this).lookup("service:task-actions");
|
||||||
|
|
||||||
|
this.set("topic.assigned_to_user", null);
|
||||||
|
this.set("topic.assigned_to_group", null);
|
||||||
|
taskActions.reassignUserToTopic(this.currentUser, this.topic).then(() => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
dropdown() {
|
||||||
|
return this.currentUser?.can_assign && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
classNames: ["assign"],
|
||||||
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
|
displayed() {
|
||||||
|
return (
|
||||||
|
// only display the button in the mobile view
|
||||||
|
this.site.mobileView &&
|
||||||
|
this.topic.isAssigned() &&
|
||||||
|
this.get("topic.assigned_to_user")?.username !==
|
||||||
|
this.currentUser.username
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
api.registerTopicFooterButton({
|
||||||
|
id: "reassign-mobile",
|
||||||
|
icon() {
|
||||||
|
return "user-plus";
|
||||||
|
},
|
||||||
|
translatedTitle() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedAriaLabel() {
|
||||||
|
defaultTitle(this);
|
||||||
|
},
|
||||||
|
translatedLabel() {
|
||||||
|
const label = I18n.t("discourse_assign.reassign.title_w_ellipsis");
|
||||||
|
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class="unassign-label"><span class="text">${label}</span></span>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
action() {
|
||||||
|
if (!this.get("currentUser.can_assign")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskActions = getOwner(this).lookup("service:task-actions");
|
||||||
|
|
||||||
|
taskActions.reassign(this.topic).set("model.onSuccess", () => {
|
||||||
|
this.appEvents.trigger("post-stream:refresh", {
|
||||||
|
id: this.topic.postStream.firstPostId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
dropdown() {
|
||||||
|
return this.currentUser?.can_assign && this.topic.isAssigned();
|
||||||
|
},
|
||||||
|
classNames: ["assign"],
|
||||||
|
dependentKeys: DEPENDENT_KEYS,
|
||||||
|
displayed() {
|
||||||
|
// only display the button in the mobile view
|
||||||
|
return this.site.mobileView;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -240,16 +492,19 @@ function initialize(api) {
|
||||||
api.addPostSmallActionIcon("unassigned_group", "group-times");
|
api.addPostSmallActionIcon("unassigned_group", "group-times");
|
||||||
api.addPostSmallActionIcon("unassigned_from_post", "user-times");
|
api.addPostSmallActionIcon("unassigned_from_post", "user-times");
|
||||||
api.addPostSmallActionIcon("unassigned_group_from_post", "group-times");
|
api.addPostSmallActionIcon("unassigned_group_from_post", "group-times");
|
||||||
|
|
||||||
api.includePostAttributes("assigned_to_user", "assigned_to_group");
|
api.includePostAttributes("assigned_to_user", "assigned_to_group");
|
||||||
|
api.addPostSmallActionIcon("reassigned", "user-plus");
|
||||||
|
api.addPostSmallActionIcon("reassigned_group", "group-plus");
|
||||||
|
|
||||||
api.addPostTransformCallback((transformed) => {
|
api.addPostTransformCallback((transformed) => {
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
"assigned",
|
"assigned",
|
||||||
"unassigned",
|
"unassigned",
|
||||||
|
"reassigned",
|
||||||
"assigned_group",
|
"assigned_group",
|
||||||
"unassigned_group",
|
"unassigned_group",
|
||||||
|
"reassigned_group",
|
||||||
"assigned_to_post",
|
"assigned_to_post",
|
||||||
"assigned_group_to_post",
|
"assigned_group_to_post",
|
||||||
"unassigned_from_post",
|
"unassigned_from_post",
|
||||||
|
@ -592,6 +847,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withPluginApi("0.13.0", (api) => includeIsAssignedOnTopic(api));
|
||||||
withPluginApi("0.11.0", (api) => initialize(api));
|
withPluginApi("0.11.0", (api) => initialize(api));
|
||||||
withPluginApi("0.8.28", (api) => registerTopicFooterButtons(api));
|
withPluginApi("0.8.28", (api) => registerTopicFooterButtons(api));
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,15 @@ import { ajax } from "discourse/lib/ajax";
|
||||||
import showModal from "discourse/lib/show-modal";
|
import showModal from "discourse/lib/show-modal";
|
||||||
|
|
||||||
export default Service.extend({
|
export default Service.extend({
|
||||||
|
i18nSuffix(targetType) {
|
||||||
|
switch (targetType) {
|
||||||
|
case "Post":
|
||||||
|
return "_post_modal";
|
||||||
|
case "Topic":
|
||||||
|
return "_modal";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
unassign(targetId, targetType = "Topic") {
|
unassign(targetId, targetType = "Topic") {
|
||||||
return ajax("/assign/unassign", {
|
return ajax("/assign/unassign", {
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
|
@ -15,22 +24,47 @@ export default Service.extend({
|
||||||
|
|
||||||
assign(target, targetType = "Topic") {
|
assign(target, targetType = "Topic") {
|
||||||
return showModal("assign-user", {
|
return showModal("assign-user", {
|
||||||
|
title: "discourse_assign.assign" + this.i18nSuffix(targetType) + ".title",
|
||||||
model: {
|
model: {
|
||||||
username: target.get("assigned_to_user.username"),
|
description:
|
||||||
group_name: target.get("assigned_to_group.name"),
|
"discourse_assign.assign" +
|
||||||
|
this.i18nSuffix(targetType) +
|
||||||
|
".description",
|
||||||
|
username: target.assigned_to_user?.username,
|
||||||
|
group_name: target.assigned_to_group?.name,
|
||||||
target,
|
target,
|
||||||
targetType,
|
targetType,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
assignUserToTopic(user, topic) {
|
reassignUserToTopic(user, target, targetType = "Topic") {
|
||||||
return ajax("/assign/assign", {
|
return ajax("/assign/reassign", {
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
data: {
|
data: {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
target_id: topic.id,
|
target_id: target.id,
|
||||||
target_type: "Topic",
|
target_type: targetType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
reassign(target, targetType = "Topic") {
|
||||||
|
return showModal("assign-user", {
|
||||||
|
title:
|
||||||
|
"discourse_assign.assign" +
|
||||||
|
this.i18nSuffix(targetType) +
|
||||||
|
".reassign_title",
|
||||||
|
model: {
|
||||||
|
description:
|
||||||
|
"discourse_assign.reassign" +
|
||||||
|
this.i18nSuffix(targetType) +
|
||||||
|
".description",
|
||||||
|
reassign: true,
|
||||||
|
username: target.assigned_to_user?.username,
|
||||||
|
group_name: target.assigned_to_group?.name,
|
||||||
|
target,
|
||||||
|
targetType,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{{#d-modal-body title=(concat "discourse_assign.assign" i18nSuffix ".title") class="assign"}}
|
{{#d-modal-body class="assign"}}
|
||||||
<div>
|
<div>
|
||||||
<p>{{i18n (concat "discourse_assign.assign" i18nSuffix ".description")}}</p>
|
<p>{{i18n model.description}}</p>
|
||||||
{{email-group-user-chooser
|
{{email-group-user-chooser
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
value=assigneeName
|
value=assigneeName
|
||||||
onChange=(action "assignUsername")
|
onChange=(action (if model.reassign "reassignUsername" "assignUsername"))
|
||||||
autofocus="autofocus"
|
autofocus="autofocus"
|
||||||
options=(hash
|
options=(hash
|
||||||
placementStrategy="absolute"
|
placementStrategy="absolute"
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
}}
|
}}
|
||||||
<div class="assign-suggestions">
|
<div class="assign-suggestions">
|
||||||
{{#each assignSuggestions as |user|}}
|
{{#each assignSuggestions as |user|}}
|
||||||
<a href {{action "assignUser" user.username }}>
|
<a href {{action (if model.reassign "reassignUser" "assignUser") user.username }}>
|
||||||
{{avatar user imageSize="small"}}
|
{{avatar user imageSize="small"}}
|
||||||
</a>
|
</a>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -29,9 +29,9 @@
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
{{d-button
|
{{d-button
|
||||||
label="discourse_assign.assign_modal.assign"
|
label= (if model.reassign "discourse_assign.reassign.title" "discourse_assign.assign_modal.assign")
|
||||||
icon=inviteIcon
|
icon=inviteIcon
|
||||||
action=(action "assign")
|
action=(action (if model.reassign "reassign" "assign"))
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
disabled=disabled
|
disabled=disabled
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -107,6 +107,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topic-footer-dropdown {
|
||||||
|
.avatar {
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Group assigns sidebar nav
|
// Group assigns sidebar nav
|
||||||
|
|
||||||
.group-assignments {
|
.group-assignments {
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select-kit-row[data-value="unassign-mobile-header"] {
|
||||||
|
background: rgba(var(--primary-low-rgb), 0.5);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.select-kit-row.assign {
|
.select-kit-row.assign {
|
||||||
.name {
|
.name {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -13,6 +13,8 @@ en:
|
||||||
unassigned_group: "unassigned %{who} %{when}"
|
unassigned_group: "unassigned %{who} %{when}"
|
||||||
unassigned_from_post: "unassigned %{who} from <a href='%{path}' data-auto-route='true'>post</a> %{when}"
|
unassigned_from_post: "unassigned %{who} from <a href='%{path}' data-auto-route='true'>post</a> %{when}"
|
||||||
unassigned_group_from_post: "unassigned %{who} from <a href='%{path}' data-auto-route='true'>post</a> %{when}"
|
unassigned_group_from_post: "unassigned %{who} from <a href='%{path}' data-auto-route='true'>post</a> %{when}"
|
||||||
|
reassigned: "Re-assigned %{who} %{when}"
|
||||||
|
reassigned_group: "Re-assigned %{who} %{when}"
|
||||||
discourse_assign:
|
discourse_assign:
|
||||||
add_unassigned_filter: "Add 'unassigned' filter to category"
|
add_unassigned_filter: "Add 'unassigned' filter to category"
|
||||||
cant_act: "You cannot act on flags that have been assigned to other users"
|
cant_act: "You cannot act on flags that have been assigned to other users"
|
||||||
|
@ -22,10 +24,12 @@ en:
|
||||||
assigned: "Assigned"
|
assigned: "Assigned"
|
||||||
group_everyone: "Everyone"
|
group_everyone: "Everyone"
|
||||||
assigned_to: "Assigned to"
|
assigned_to: "Assigned to"
|
||||||
|
assigned_to_w_ellipsis: "Assigned to..."
|
||||||
assign_notification: "<p><span>%{username}</span> %{description}</p>"
|
assign_notification: "<p><span>%{username}</span> %{description}</p>"
|
||||||
assign_group_notification: "<p><span>%{username}</span> %{description}</p>"
|
assign_group_notification: "<p><span>%{username}</span> %{description}</p>"
|
||||||
unassign:
|
unassign:
|
||||||
title: "Unassign"
|
title: "Unassign"
|
||||||
|
title_w_ellipsis: "Unassign..."
|
||||||
help: "Unassign %{username} from Topic"
|
help: "Unassign %{username} from Topic"
|
||||||
assign:
|
assign:
|
||||||
title: "Assign"
|
title: "Assign"
|
||||||
|
@ -37,9 +41,15 @@ en:
|
||||||
help: "Unassign %{username} from Post"
|
help: "Unassign %{username} from Post"
|
||||||
reassign:
|
reassign:
|
||||||
title: "Re-assign"
|
title: "Re-assign"
|
||||||
|
title_w_ellipsis: "Re-assign to..."
|
||||||
|
to_self: "Re-assign to me"
|
||||||
help: "Re-assign Topic to a different user"
|
help: "Re-assign Topic to a different user"
|
||||||
|
reassign_modal:
|
||||||
|
title: "Re-assign Topic"
|
||||||
|
description: "Enter the name of the user you'd like to Re-assign this topic"
|
||||||
assign_modal:
|
assign_modal:
|
||||||
title: "Assign Topic"
|
title: "Assign Topic"
|
||||||
|
reassign_title: "Re-assign Topic"
|
||||||
description: "Enter the name of the user you'd like to assign this topic"
|
description: "Enter the name of the user you'd like to assign this topic"
|
||||||
assign: "Assign"
|
assign: "Assign"
|
||||||
assign_post_modal:
|
assign_post_modal:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
DiscourseAssign::Engine.routes.draw do
|
DiscourseAssign::Engine.routes.draw do
|
||||||
put "/claim/:topic_id" => "assign#claim"
|
put "/claim/:topic_id" => "assign#claim"
|
||||||
put "/assign" => "assign#assign"
|
put "/assign" => "assign#assign"
|
||||||
|
put "/reassign" => "assign#reassign"
|
||||||
put "/unassign" => "assign#unassign"
|
put "/unassign" => "assign#unassign"
|
||||||
get "/suggestions" => "assign#suggestions"
|
get "/suggestions" => "assign#suggestions"
|
||||||
get "/assigned" => "assign#assigned"
|
get "/assigned" => "assign#assigned"
|
||||||
|
|
|
@ -180,7 +180,7 @@ class ::Assigner
|
||||||
topic.posts.where(post_number: 1).first
|
topic.posts.where(post_number: 1).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign(assign_to, silent: false)
|
def forbidden_reasons(assign_to:, type:)
|
||||||
forbidden_reason =
|
forbidden_reason =
|
||||||
case
|
case
|
||||||
when assign_to.is_a?(User) && !can_assignee_see_target?(assign_to)
|
when assign_to.is_a?(User) && !can_assignee_see_target?(assign_to)
|
||||||
|
@ -189,19 +189,18 @@ class ::Assigner
|
||||||
topic.private_message? ? :forbidden_group_assignee_not_pm_participant : :forbidden_group_assignee_cant_see_topic
|
topic.private_message? ? :forbidden_group_assignee_not_pm_participant : :forbidden_group_assignee_cant_see_topic
|
||||||
when !can_be_assigned?(assign_to)
|
when !can_be_assigned?(assign_to)
|
||||||
assign_to.is_a?(User) ? :forbidden_assign_to : :forbidden_group_assign_to
|
assign_to.is_a?(User) ? :forbidden_assign_to : :forbidden_group_assign_to
|
||||||
when topic.assignment&.assigned_to_id == assign_to.id
|
when topic.assignment&.assigned_to_id == assign_to.id && topic.assignment&.assigned_to_type == type
|
||||||
assign_to.is_a?(User) ? :already_assigned : :group_already_assigned
|
assign_to.is_a?(User) ? :already_assigned : :group_already_assigned
|
||||||
when Assignment.where(topic: topic).count >= ASSIGNMENTS_PER_TOPIC_LIMIT
|
when Assignment.where(topic: topic).count >= ASSIGNMENTS_PER_TOPIC_LIMIT
|
||||||
:too_many_assigns_for_topic
|
:too_many_assigns_for_topic
|
||||||
when !can_assign_to?(assign_to)
|
when !can_assign_to?(assign_to)
|
||||||
:too_many_assigns
|
:too_many_assigns
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return { success: false, reason: forbidden_reason } if forbidden_reason
|
def assign_or_reassign_target(assign_to:, type:, silent:, action_code:)
|
||||||
|
|
||||||
@target.assignment&.destroy!
|
@target.assignment&.destroy!
|
||||||
|
|
||||||
type = assign_to.is_a?(User) ? "User" : "Group"
|
|
||||||
assignment = @target.create_assignment!(assigned_to_id: assign_to.id, assigned_to_type: type, assigned_by_user_id: @assigned_by.id, topic_id: topic.id)
|
assignment = @target.create_assignment!(assigned_to_id: assign_to.id, assigned_to_type: type, assigned_by_user_id: @assigned_by.id, topic_id: topic.id)
|
||||||
|
|
||||||
first_post.publish_change_to_clients!(:revised, reload_topic: true)
|
first_post.publish_change_to_clients!(:revised, reload_topic: true)
|
||||||
|
@ -262,7 +261,7 @@ class ::Assigner
|
||||||
nil,
|
nil,
|
||||||
bump: false,
|
bump: false,
|
||||||
post_type: SiteSetting.assigns_public ? Post.types[:small_action] : Post.types[:whisper],
|
post_type: SiteSetting.assigns_public ? Post.types[:small_action] : Post.types[:whisper],
|
||||||
action_code: moderator_post_assign_action_code(assignment),
|
action_code: moderator_post_assign_action_code(assignment, action_code),
|
||||||
custom_fields: custom_fields
|
custom_fields: custom_fields
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -296,6 +295,26 @@ class ::Assigner
|
||||||
{ success: true }
|
{ success: true }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assign(assign_to, silent: false)
|
||||||
|
type = assign_to.is_a?(User) ? "User" : "Group"
|
||||||
|
|
||||||
|
forbidden_reason = forbidden_reasons(assign_to: assign_to, type: type)
|
||||||
|
return { success: false, reason: forbidden_reason } if forbidden_reason
|
||||||
|
|
||||||
|
action_code = { user: "assigned", group: "assigned_group" }
|
||||||
|
assign_or_reassign_target(assign_to: assign_to, type: type, silent: silent, action_code: action_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reassign(assign_to, silent: false)
|
||||||
|
type = assign_to.is_a?(User) ? "User" : "Group"
|
||||||
|
|
||||||
|
forbidden_reason = forbidden_reasons(assign_to: assign_to, type: type)
|
||||||
|
return { success: false, reason: forbidden_reason } if forbidden_reason
|
||||||
|
|
||||||
|
action_code = { user: "reassigned", group: "reassigned_group" }
|
||||||
|
assign_or_reassign_target(assign_to: assign_to, type: type, silent: silent, action_code: action_code)
|
||||||
|
end
|
||||||
|
|
||||||
def unassign(silent: false)
|
def unassign(silent: false)
|
||||||
if assignment = @target.assignment
|
if assignment = @target.assignment
|
||||||
assignment.destroy!
|
assignment.destroy!
|
||||||
|
@ -386,15 +405,15 @@ class ::Assigner
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def moderator_post_assign_action_code(assignment)
|
def moderator_post_assign_action_code(assignment, action_code)
|
||||||
suffix =
|
suffix =
|
||||||
if assignment.target.is_a?(Post)
|
if assignment.target.is_a?(Post)
|
||||||
"_to_post"
|
"_to_post"
|
||||||
elsif assignment.target.is_a?(Topic)
|
elsif assignment.target.is_a?(Topic)
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
return "assigned#{suffix}" if assignment.assigned_to_user?
|
return "#{action_code[:user]}#{suffix}" if assignment.assigned_to_user?
|
||||||
return "assigned_group#{suffix}" if assignment.assigned_to_group?
|
return "#{action_code[:group]}#{suffix}" if assignment.assigned_to_group?
|
||||||
end
|
end
|
||||||
|
|
||||||
def moderator_post_unassign_action_code(assignment)
|
def moderator_post_unassign_action_code(assignment)
|
||||||
|
|
|
@ -8,15 +8,9 @@ import {
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import { cloneJSON } from "discourse-common/lib/object";
|
import { cloneJSON } from "discourse-common/lib/object";
|
||||||
import topicFixtures from "discourse/tests/fixtures/topic";
|
import topicFixtures from "discourse/tests/fixtures/topic";
|
||||||
|
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||||
|
|
||||||
acceptance("Discourse Assign | Assigned topic", function (needs) {
|
function assignCurrentUserToTopic(needs) {
|
||||||
needs.user();
|
|
||||||
needs.settings({
|
|
||||||
assign_enabled: true,
|
|
||||||
tagging_enabled: true,
|
|
||||||
assigns_user_url_path: "/",
|
|
||||||
});
|
|
||||||
|
|
||||||
needs.pretender((server, helper) => {
|
needs.pretender((server, helper) => {
|
||||||
server.get("/t/44.json", () => {
|
server.get("/t/44.json", () => {
|
||||||
let topic = cloneJSON(topicFixtures["/t/28830/1.json"]);
|
let topic = cloneJSON(topicFixtures["/t/28830/1.json"]);
|
||||||
|
@ -42,6 +36,45 @@ acceptance("Discourse Assign | Assigned topic", function (needs) {
|
||||||
return helper.response(topic);
|
return helper.response(topic);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function assignNewUserToTopic(needs) {
|
||||||
|
needs.pretender((server, helper) => {
|
||||||
|
server.get("/t/44.json", () => {
|
||||||
|
let topic = cloneJSON(topicFixtures["/t/28830/1.json"]);
|
||||||
|
topic["assigned_to_user"] = {
|
||||||
|
username: "isaacjanzen",
|
||||||
|
name: "Isaac Janzen",
|
||||||
|
avatar_template:
|
||||||
|
"/letter_avatar/isaacjanzen/{size}/3_f9720745f5ce6dfc2b5641fca999d934.png",
|
||||||
|
};
|
||||||
|
topic["indirectly_assigned_to"] = {
|
||||||
|
2: {
|
||||||
|
name: "Developers",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return helper.response(topic);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.get("/t/45.json", () => {
|
||||||
|
let topic = cloneJSON(topicFixtures["/t/28830/1.json"]);
|
||||||
|
topic["assigned_to_group"] = {
|
||||||
|
name: "Developers",
|
||||||
|
};
|
||||||
|
return helper.response(topic);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptance("Discourse Assign | Assigned topic", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
needs.settings({
|
||||||
|
assign_enabled: true,
|
||||||
|
tagging_enabled: true,
|
||||||
|
assigns_user_url_path: "/",
|
||||||
|
});
|
||||||
|
|
||||||
|
assignCurrentUserToTopic(needs);
|
||||||
|
|
||||||
test("Shows user assignment info", async (assert) => {
|
test("Shows user assignment info", async (assert) => {
|
||||||
updateCurrentUser({ can_assign: true });
|
updateCurrentUser({ can_assign: true });
|
||||||
|
@ -59,8 +92,8 @@ acceptance("Discourse Assign | Assigned topic", function (needs) {
|
||||||
);
|
);
|
||||||
assert.ok(exists("#post_1 .assigned-to svg.d-icon-user-plus"));
|
assert.ok(exists("#post_1 .assigned-to svg.d-icon-user-plus"));
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists("#topic-footer-button-assign .unassign-label"),
|
exists("#topic-footer-dropdown-reassign"),
|
||||||
"shows unassign button at the bottom of the topic"
|
"shows reassign dropdown at the bottom of the topic"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,8 +113,76 @@ acceptance("Discourse Assign | Assigned topic", function (needs) {
|
||||||
);
|
);
|
||||||
assert.ok(exists("#post_1 .assigned-to svg.d-icon-group-plus"));
|
assert.ok(exists("#post_1 .assigned-to svg.d-icon-group-plus"));
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists("#topic-footer-button-assign .unassign-label"),
|
exists("#topic-footer-dropdown-reassign"),
|
||||||
"shows unassign button at the bottom of the topic"
|
"shows reassign dropdown at the bottom of the topic"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
acceptance("Discourse Assign | Re-assign topic", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
needs.settings({
|
||||||
|
assign_enabled: true,
|
||||||
|
tagging_enabled: true,
|
||||||
|
assigns_user_url_path: "/",
|
||||||
|
});
|
||||||
|
|
||||||
|
assignNewUserToTopic(needs);
|
||||||
|
|
||||||
|
test("Re-assign Footer dropdown contains reassign buttons", async (assert) => {
|
||||||
|
updateCurrentUser({ can_assign: true });
|
||||||
|
const menu = selectKit("#topic-footer-dropdown-reassign");
|
||||||
|
|
||||||
|
await visit("/t/assignment-topic/44");
|
||||||
|
await menu.expand();
|
||||||
|
|
||||||
|
assert.ok(menu.rowByValue("unassign").exists());
|
||||||
|
assert.ok(menu.rowByValue("reassign").exists());
|
||||||
|
assert.ok(menu.rowByValue("reassign-self").exists());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
acceptance("Discourse Assign | Re-assign topic | mobile", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
needs.mobileView();
|
||||||
|
needs.settings({
|
||||||
|
assign_enabled: true,
|
||||||
|
tagging_enabled: true,
|
||||||
|
assigns_user_url_path: "/",
|
||||||
|
});
|
||||||
|
|
||||||
|
assignNewUserToTopic(needs);
|
||||||
|
|
||||||
|
test("Mobile Footer dropdown contains reassign buttons", async (assert) => {
|
||||||
|
updateCurrentUser({ can_assign: true });
|
||||||
|
const menu = selectKit(".topic-footer-mobile-dropdown");
|
||||||
|
|
||||||
|
await visit("/t/assignment-topic/44");
|
||||||
|
await menu.expand();
|
||||||
|
|
||||||
|
assert.ok(menu.rowByValue("unassign-mobile").exists());
|
||||||
|
assert.ok(menu.rowByValue("reassign-mobile").exists());
|
||||||
|
assert.ok(menu.rowByValue("reassign-self-mobile").exists());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
acceptance("Discourse Assign | Re-assign topic conditionals", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
needs.settings({
|
||||||
|
assign_enabled: true,
|
||||||
|
tagging_enabled: true,
|
||||||
|
assigns_user_url_path: "/",
|
||||||
|
});
|
||||||
|
|
||||||
|
assignCurrentUserToTopic(needs);
|
||||||
|
|
||||||
|
test("Reassign Footer dropdown won't display reassign-to-self button when already assigned to current user", async (assert) => {
|
||||||
|
updateCurrentUser({ can_assign: true });
|
||||||
|
const menu = selectKit("#topic-footer-dropdown-reassign");
|
||||||
|
|
||||||
|
await visit("/t/assignment-topic/44");
|
||||||
|
await menu.expand();
|
||||||
|
|
||||||
|
assert.notOk(menu.rowByValue("reassign-self").exists());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue