DEV: Post-release cleanup (#163)
Included: * DEV: Post-release cleanup * DEV: Tests cleanup * DEV: Import cleanup * DEV: Drop a compatibility fix * DEV: Use index_by * DEV: Use ember imports * DEV: Use discourseDebounce * DEV: Use @action * DEV: Use the optional chaining operator * DEV: Fix an invalid test * DEV: Use `discourseModule` * DEV: Add .prettierrc * DEV: Sync up the version number
This commit is contained in:
parent
954e908e24
commit
195dcc92cb
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -98,21 +98,13 @@ module DiscourseAssign
|
|||
|
||||
Topic.preload_custom_fields(topics, TopicList.preloaded_custom_fields)
|
||||
|
||||
# TODO Drop AvatarLookup after Discourse 2.6.0 release
|
||||
lookup_columns = defined?(UserLookup) ? UserLookup.lookup_columns : AvatarLookup.lookup_columns
|
||||
|
||||
users = User
|
||||
.where("users.id IN (SELECT value::int FROM topic_custom_fields WHERE name = 'assigned_to_id' AND topic_id IN (?))", topics.map(&:id))
|
||||
.joins('join user_emails on user_emails.user_id = users.id AND user_emails.primary')
|
||||
.select(lookup_columns)
|
||||
.select(UserLookup.lookup_columns)
|
||||
.to_a
|
||||
|
||||
# TODO Drop after Discourse 2.6.0 release
|
||||
if User.respond_to?(:allowed_user_custom_fields)
|
||||
User.preload_custom_fields(users, User.allowed_user_custom_fields(guardian))
|
||||
else
|
||||
User.preload_custom_fields(users, User.whitelisted_user_custom_fields(guardian))
|
||||
end
|
||||
User.preload_custom_fields(users, User.allowed_user_custom_fields(guardian))
|
||||
|
||||
users = users.to_h { |u| [u.id, u] }
|
||||
topics.each do |t|
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import { action } from "@ember/object";
|
||||
|
||||
export default {
|
||||
shouldRender(args, component) {
|
||||
return component.currentUser && component.currentUser.can_assign;
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChangeAssigned(value) {
|
||||
if (this.onChangeSearchedTermField) {
|
||||
this.onChangeSearchedTermField("assigned", "updateInRegex", value);
|
||||
} else {
|
||||
this.set("searchedTerms.assigned", value);
|
||||
}
|
||||
},
|
||||
@action
|
||||
onChangeAssigned(value) {
|
||||
if (this.onChangeSearchedTermField) {
|
||||
this.onChangeSearchedTermField("assigned", "updateInRegex", value);
|
||||
} else {
|
||||
this.set("searchedTerms.assigned", value);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { action } from "@ember/object";
|
||||
|
||||
export default {
|
||||
actions: {
|
||||
onChangeSetting(value) {
|
||||
this.set(
|
||||
"category.custom_fields.enable_unassigned_filter",
|
||||
value ? "true" : "false"
|
||||
);
|
||||
},
|
||||
@action
|
||||
onChangeSetting(value) {
|
||||
this.set(
|
||||
"category.custom_fields.enable_unassigned_filter",
|
||||
value ? "true" : "false"
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { inject as controller } from "@ember/controller";
|
||||
import { not } from "@ember/object/computed";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
export default Controller.extend({
|
||||
topicBulkActions: controller(),
|
||||
assignSuggestions: null,
|
||||
allowedGroups: null,
|
||||
taskActions: Ember.inject.service(),
|
||||
taskActions: service(),
|
||||
autofocus: not("capabilities.touch"),
|
||||
|
||||
init() {
|
||||
|
@ -33,50 +36,50 @@ export default Ember.Controller.extend({
|
|||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
assignUser(user) {
|
||||
if (this.isBulkAction) {
|
||||
this.bulkAction(user.username);
|
||||
return;
|
||||
}
|
||||
this.setProperties({
|
||||
"model.username": user.username,
|
||||
"model.allowedGroups": this.taskActions.allowedGroups,
|
||||
});
|
||||
this.send("assign");
|
||||
},
|
||||
@action
|
||||
assignUser(user) {
|
||||
if (this.isBulkAction) {
|
||||
this.bulkAction(user.username);
|
||||
return;
|
||||
}
|
||||
this.setProperties({
|
||||
"model.username": user.username,
|
||||
"model.allowedGroups": this.taskActions.allowedGroups,
|
||||
});
|
||||
this.send("assign");
|
||||
},
|
||||
|
||||
assign() {
|
||||
if (this.isBulkAction) {
|
||||
this.bulkAction(this.model.username);
|
||||
return;
|
||||
}
|
||||
let path = "/assign/assign";
|
||||
@action
|
||||
assign() {
|
||||
if (this.isBulkAction) {
|
||||
this.bulkAction(this.model.username);
|
||||
return;
|
||||
}
|
||||
let path = "/assign/assign";
|
||||
|
||||
if (Ember.isEmpty(this.get("model.username"))) {
|
||||
path = "/assign/unassign";
|
||||
this.set("model.assigned_to_user", null);
|
||||
}
|
||||
if (isEmpty(this.get("model.username"))) {
|
||||
path = "/assign/unassign";
|
||||
this.set("model.assigned_to_user", null);
|
||||
}
|
||||
|
||||
this.send("closeModal");
|
||||
this.send("closeModal");
|
||||
|
||||
return ajax(path, {
|
||||
type: "PUT",
|
||||
data: {
|
||||
username: this.get("model.username"),
|
||||
topic_id: this.get("model.topic.id"),
|
||||
},
|
||||
return ajax(path, {
|
||||
type: "PUT",
|
||||
data: {
|
||||
username: this.get("model.username"),
|
||||
topic_id: this.get("model.topic.id"),
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
if (this.get("model.onSuccess")) {
|
||||
this.get("model.onSuccess")();
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (this.get("model.onSuccess")) {
|
||||
this.get("model.onSuccess")();
|
||||
}
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
|
||||
updateUsername(selected) {
|
||||
this.set("model.username", selected.firstObject);
|
||||
},
|
||||
updateUsername(selected) {
|
||||
this.set("model.username", selected.firstObject);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import UserTopicsList from "discourse/controllers/user-topics-list";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import debounce from "discourse/plugins/discourse-assign/lib/debounce";
|
||||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
import { INPUT_DELAY } from "discourse-common/config/environment";
|
||||
import { inject as controller } from "@ember/controller";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default UserTopicsList.extend({
|
||||
user: Ember.inject.controller(),
|
||||
taskActions: Ember.inject.service(),
|
||||
user: controller(),
|
||||
taskActions: service(),
|
||||
order: "",
|
||||
ascending: false,
|
||||
search: "",
|
||||
|
@ -43,33 +46,43 @@ export default UserTopicsList.extend({
|
|||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
unassign(topic) {
|
||||
this.taskActions
|
||||
.unassign(topic.get("id"))
|
||||
.then(() => this.send("changeAssigned"));
|
||||
},
|
||||
reassign(topic) {
|
||||
const controller = this.taskActions.assign(topic);
|
||||
controller.set("model.onSuccess", () => this.send("changeAssigned"));
|
||||
},
|
||||
changeSort(sortBy) {
|
||||
if (sortBy === this.order) {
|
||||
this.toggleProperty("ascending");
|
||||
this.refreshModel();
|
||||
} else {
|
||||
this.setProperties({ order: sortBy, ascending: false });
|
||||
this.refreshModel();
|
||||
}
|
||||
},
|
||||
onChangeFilter(value) {
|
||||
debounce(this, this._setSearchTerm, value, INPUT_DELAY * 2);
|
||||
},
|
||||
toggleBulkSelect() {
|
||||
this.toggleProperty("bulkSelectEnabled");
|
||||
},
|
||||
refresh() {
|
||||
@action
|
||||
unassign(topic) {
|
||||
this.taskActions
|
||||
.unassign(topic.get("id"))
|
||||
.then(() => this.send("changeAssigned"));
|
||||
},
|
||||
|
||||
@action
|
||||
reassign(topic) {
|
||||
this.taskActions
|
||||
.assign(topic)
|
||||
.set("model.onSuccess", () => this.send("changeAssigned"));
|
||||
},
|
||||
|
||||
@action
|
||||
changeSort(sortBy) {
|
||||
if (sortBy === this.order) {
|
||||
this.toggleProperty("ascending");
|
||||
this.refreshModel();
|
||||
},
|
||||
} else {
|
||||
this.setProperties({ order: sortBy, ascending: false });
|
||||
this.refreshModel();
|
||||
}
|
||||
},
|
||||
|
||||
@action
|
||||
onChangeFilter(value) {
|
||||
discourseDebounce(this, this._setSearchTerm, value, INPUT_DELAY * 2);
|
||||
},
|
||||
|
||||
@action
|
||||
toggleBulkSelect() {
|
||||
this.toggleProperty("bulkSelectEnabled");
|
||||
},
|
||||
|
||||
@action
|
||||
refresh() {
|
||||
this.refreshModel();
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import Controller, { inject as controller } from "@ember/controller";
|
|||
import { action } from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import debounce from "discourse/plugins/discourse-assign/lib/debounce";
|
||||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
import { INPUT_DELAY } from "discourse-common/config/environment";
|
||||
|
||||
export default Controller.extend({
|
||||
|
@ -86,6 +86,6 @@ export default Controller.extend({
|
|||
|
||||
@action
|
||||
onChangeFilterName(value) {
|
||||
debounce(this, this._setFilter, value, INPUT_DELAY * 2);
|
||||
discourseDebounce(this, this._setFilter, value, INPUT_DELAY * 2);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import UserTopicsList from "discourse/controllers/user-topics-list";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import debounce from "discourse/plugins/discourse-assign/lib/debounce";
|
||||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
import { INPUT_DELAY } from "discourse-common/config/environment";
|
||||
import { inject as controller } from "@ember/controller";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default UserTopicsList.extend({
|
||||
user: Ember.inject.controller(),
|
||||
taskActions: Ember.inject.service(),
|
||||
user: controller(),
|
||||
taskActions: service(),
|
||||
queryParams: ["order", "ascending", "search"],
|
||||
order: "",
|
||||
ascending: false,
|
||||
|
@ -38,27 +41,33 @@ export default UserTopicsList.extend({
|
|||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
unassign(topic) {
|
||||
this.taskActions
|
||||
.unassign(topic.get("id"))
|
||||
.then(() => this.send("changeAssigned"));
|
||||
},
|
||||
reassign(topic) {
|
||||
const controller = this.taskActions.assign(topic);
|
||||
controller.set("model.onSuccess", () => this.send("changeAssigned"));
|
||||
},
|
||||
changeSort(sortBy) {
|
||||
if (sortBy === this.order) {
|
||||
this.toggleProperty("ascending");
|
||||
this.refreshModel();
|
||||
} else {
|
||||
this.setProperties({ order: sortBy, ascending: false });
|
||||
this.refreshModel();
|
||||
}
|
||||
},
|
||||
onChangeFilter(value) {
|
||||
debounce(this, this._setSearchTerm, value, INPUT_DELAY * 2);
|
||||
},
|
||||
@action
|
||||
unassign(topic) {
|
||||
this.taskActions
|
||||
.unassign(topic.get("id"))
|
||||
.then(() => this.send("changeAssigned"));
|
||||
},
|
||||
|
||||
@action
|
||||
reassign(topic) {
|
||||
this.taskActions
|
||||
.assign(topic)
|
||||
.set("model.onSuccess", () => this.send("changeAssigned"));
|
||||
},
|
||||
|
||||
@action
|
||||
changeSort(sortBy) {
|
||||
if (sortBy === this.order) {
|
||||
this.toggleProperty("ascending");
|
||||
this.refreshModel();
|
||||
} else {
|
||||
this.setProperties({ order: sortBy, ascending: false });
|
||||
this.refreshModel();
|
||||
}
|
||||
},
|
||||
|
||||
@action
|
||||
onChangeFilter(value) {
|
||||
discourseDebounce(this, this._setSearchTerm, value, INPUT_DELAY * 2);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import TopicButtonAction, {
|
|||
} from "discourse/controllers/topic-bulk-actions";
|
||||
import { inject } from "@ember/controller";
|
||||
import I18n from "I18n";
|
||||
import { get } from "@ember/object";
|
||||
|
||||
function titleForState(user) {
|
||||
if (user) {
|
||||
|
@ -308,11 +309,11 @@ function initialize(api) {
|
|||
if (dec.attrs.post_number === 1) {
|
||||
const postModel = dec.getModel();
|
||||
if (postModel) {
|
||||
const assignedToUser = Ember.get(postModel, "topic.assigned_to_user");
|
||||
const assignedToUser = get(postModel, "topic.assigned_to_user");
|
||||
if (assignedToUser) {
|
||||
return dec.widget.attach("assigned-to", {
|
||||
assignedToUser,
|
||||
href: Ember.get(postModel, "topic.assignedToUserPath"),
|
||||
href: get(postModel, "topic.assignedToUserPath"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
import Category from "discourse/models/category";
|
||||
import { computed } from "@ember/object";
|
||||
|
||||
export default {
|
||||
name: "extend-category-for-assign",
|
||||
|
||||
before: "inject-discourse-objects",
|
||||
|
||||
initialize() {
|
||||
Category.reopen({
|
||||
enable_unassigned_filter: Ember.computed(
|
||||
enable_unassigned_filter: computed(
|
||||
"custom_fields.enable_unassigned_filter",
|
||||
{
|
||||
get() {
|
||||
if (this && this.custom_fields) {
|
||||
return this.custom_fields.enable_unassigned_filter === "true";
|
||||
}
|
||||
return false;
|
||||
return this?.custom_fields?.enable_unassigned_filter === "true";
|
||||
},
|
||||
}
|
||||
),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
model() {
|
||||
|
@ -25,9 +26,8 @@ export default DiscourseRoute.extend({
|
|||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
changeAssigned() {
|
||||
this.refresh();
|
||||
},
|
||||
@action
|
||||
changeAssigned() {
|
||||
this.refresh();
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import I18n from "I18n";
|
||||
import UserTopicListRoute from "discourse/routes/user-topic-list";
|
||||
import cookie from "discourse/lib/cookie";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default UserTopicListRoute.extend({
|
||||
userActionType: 16,
|
||||
|
@ -42,9 +43,8 @@ export default UserTopicListRoute.extend({
|
|||
controller.set("model", model);
|
||||
},
|
||||
|
||||
actions: {
|
||||
changeAssigned() {
|
||||
this.refresh();
|
||||
},
|
||||
@action
|
||||
changeAssigned() {
|
||||
this.refresh();
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import I18n from "I18n";
|
||||
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default DropdownSelectBoxComponent.extend({
|
||||
classNames: ["assign-actions-dropdown"],
|
||||
|
@ -27,16 +28,15 @@ export default DropdownSelectBoxComponent.extend({
|
|||
];
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelect(id) {
|
||||
switch (id) {
|
||||
case "unassign":
|
||||
this.unassign(this.topic, this.user);
|
||||
break;
|
||||
case "reassign":
|
||||
this.reassign(this.topic, this.user);
|
||||
break;
|
||||
}
|
||||
},
|
||||
@action
|
||||
onSelect(id) {
|
||||
switch (id) {
|
||||
case "unassign":
|
||||
this.unassign(this.topic, this.user);
|
||||
break;
|
||||
case "reassign":
|
||||
this.reassign(this.topic, this.user);
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
export default Ember.Component.extend({
|
||||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["assigned-to-user"],
|
||||
});
|
||||
|
|
|
@ -1,27 +1,6 @@
|
|||
import {
|
||||
ListItemDefaults,
|
||||
default as TopicListItem,
|
||||
} from "discourse/components/topic-list-item";
|
||||
import TopicListItem from "discourse/components/topic-list-item";
|
||||
import { equal } from "@ember/object/computed";
|
||||
|
||||
// This is a backward compatible fix so that this change:
|
||||
// https://github.com/discourse/discourse/pull/8589
|
||||
// in discourse core doesn't break this plugin.
|
||||
let assignedTopicListItem = null;
|
||||
|
||||
if (ListItemDefaults) {
|
||||
assignedTopicListItem = Ember.Component.extend(ListItemDefaults, {
|
||||
isPrivateMessage: Ember.computed.equal(
|
||||
"topic.archetype",
|
||||
"private_message"
|
||||
),
|
||||
});
|
||||
} else {
|
||||
assignedTopicListItem = TopicListItem.extend({
|
||||
isPrivateMessage: Ember.computed.equal(
|
||||
"topic.archetype",
|
||||
"private_message"
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
export default assignedTopicListItem;
|
||||
export default TopicListItem.extend({
|
||||
isPrivateMessage: equal("topic.archetype", "private_message"),
|
||||
});
|
||||
|
|
|
@ -1,52 +1,55 @@
|
|||
import Component from "@ember/component";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
claiming: false,
|
||||
unassigning: false,
|
||||
|
||||
actions: {
|
||||
unassign() {
|
||||
this.set("unassigning", true);
|
||||
return ajax("/assign/unassign", {
|
||||
type: "PUT",
|
||||
data: { topic_id: this.get("topic.id") },
|
||||
})
|
||||
.then(() => {
|
||||
this.set("topic.assigned_to_user", null);
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
this.set("unassigning", false);
|
||||
});
|
||||
},
|
||||
@action
|
||||
unassign() {
|
||||
this.set("unassigning", true);
|
||||
|
||||
claim() {
|
||||
this.set("claiming", true);
|
||||
|
||||
let topic = this.topic;
|
||||
ajax(`/assign/claim/${topic.id}`, {
|
||||
method: "PUT",
|
||||
return ajax("/assign/unassign", {
|
||||
type: "PUT",
|
||||
data: { topic_id: this.get("topic.id") },
|
||||
})
|
||||
.then(() => {
|
||||
this.set("topic.assigned_to_user", null);
|
||||
})
|
||||
.then(() => {
|
||||
this.set("topic.assigned_to_user", this.currentUser);
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.jqXHR && e.jqXHR.responseJSON) {
|
||||
let json = e.jqXHR.responseJSON;
|
||||
if (json && json.extras) {
|
||||
this.set("topic.assigned_to_user", json.extras.assigned_to);
|
||||
}
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => {
|
||||
this.set("unassigning", false);
|
||||
});
|
||||
},
|
||||
|
||||
@action
|
||||
claim() {
|
||||
this.set("claiming", true);
|
||||
|
||||
let topic = this.topic;
|
||||
ajax(`/assign/claim/${topic.id}`, {
|
||||
method: "PUT",
|
||||
})
|
||||
.then(() => {
|
||||
this.set("topic.assigned_to_user", this.currentUser);
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.jqXHR && e.jqXHR.responseJSON) {
|
||||
let json = e.jqXHR.responseJSON;
|
||||
if (json && json.extras) {
|
||||
this.set("topic.assigned_to_user", json.extras.assigned_to);
|
||||
}
|
||||
return popupAjaxError(e);
|
||||
})
|
||||
.finally(() => {
|
||||
if (this.isDestroying || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
this.set("claiming", false);
|
||||
});
|
||||
},
|
||||
}
|
||||
return popupAjaxError(e);
|
||||
})
|
||||
.finally(() => {
|
||||
if (this.isDestroying || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
this.set("claiming", false);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import Component from "@ember/component";
|
||||
import { set } from "@ember/object";
|
||||
|
||||
function assignIfEqual(topic, data) {
|
||||
if (topic && topic.id === data.topic_id) {
|
||||
Ember.set(topic, "assigned_to_user", data.assigned_to);
|
||||
set(topic, "assigned_to_user", data.assigned_to);
|
||||
}
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
export default Component.extend({
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
this.messageBus.subscribe("/staff/topic-assignment", (data) => {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
export default Ember.Component.extend({
|
||||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
});
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Component from "@ember/component";
|
||||
import I18n from "I18n";
|
||||
import { or } from "@ember/object/computed";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
export default Component.extend({
|
||||
selectedFrequency: or(
|
||||
"user.custom_fields.remind_assigns_frequency",
|
||||
"siteSettings.remind_assigns_frequency"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Service from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default Ember.Service.extend({
|
||||
export default Service.extend({
|
||||
unassign(topicId) {
|
||||
return ajax("/assign/unassign", {
|
||||
type: "PUT",
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { debounce } from "@ember/runloop";
|
||||
|
||||
// TODO: Remove this file and use discouseDebounce after the 2.7 release.
|
||||
let debounceFunction = debounce;
|
||||
|
||||
try {
|
||||
debounceFunction = require("discourse-common/lib/debounce").default;
|
||||
} catch (_) {}
|
||||
|
||||
export default debounceFunction;
|
|
@ -87,12 +87,6 @@ class PendingAssignsReminder
|
|||
|
||||
def update_last_reminded(user)
|
||||
update_last_reminded = { REMINDED_AT => DateTime.now }
|
||||
# New API in Discouse that's better under concurrency
|
||||
if user.respond_to?(:upsert_custom_fields)
|
||||
user.upsert_custom_fields(update_last_reminded)
|
||||
else
|
||||
user.custom_fields.merge!(update_last_reminded)
|
||||
user.save_custom_fields
|
||||
end
|
||||
user.upsert_custom_fields(update_last_reminded)
|
||||
end
|
||||
end
|
||||
|
|
113
plugin.rb
113
plugin.rb
|
@ -2,7 +2,7 @@
|
|||
|
||||
# name: discourse-assign
|
||||
# about: Assign users to topics
|
||||
# version: 0.1
|
||||
# version: 1.0.0
|
||||
# authors: Sam Saffron
|
||||
# url: https://github.com/discourse/discourse-assign
|
||||
|
||||
|
@ -11,8 +11,8 @@ enabled_site_setting :assign_enabled
|
|||
register_asset 'stylesheets/assigns.scss'
|
||||
register_asset 'stylesheets/mobile/assigns.scss', :mobile
|
||||
|
||||
register_svg_icon "user-plus" if respond_to?(:register_svg_icon)
|
||||
register_svg_icon "user-times" if respond_to?(:register_svg_icon)
|
||||
register_svg_icon "user-plus"
|
||||
register_svg_icon "user-times"
|
||||
|
||||
load File.expand_path('../lib/discourse_assign/engine.rb', __FILE__)
|
||||
load File.expand_path('../lib/discourse_assign/helpers.rb', __FILE__)
|
||||
|
@ -128,25 +128,19 @@ after_initialize do
|
|||
end
|
||||
|
||||
TopicList.preloaded_custom_fields << TopicAssigner::ASSIGNED_TO_ID
|
||||
Site.preloaded_category_custom_fields << "enable_unassigned_filter" if Site.respond_to? :preloaded_category_custom_fields
|
||||
Search.preloaded_topic_custom_fields << TopicAssigner::ASSIGNED_TO_ID if Search.respond_to? :preloaded_topic_custom_fields
|
||||
Site.preloaded_category_custom_fields << "enable_unassigned_filter"
|
||||
Search.preloaded_topic_custom_fields << TopicAssigner::ASSIGNED_TO_ID
|
||||
|
||||
if defined? BookmarkQuery
|
||||
if BookmarkQuery.respond_to?(:preloaded_custom_fields) && BookmarkQuery.respond_to?(:on_preload)
|
||||
BookmarkQuery.preloaded_custom_fields << TopicAssigner::ASSIGNED_TO_ID
|
||||
BookmarkQuery.on_preload do |bookmarks, bookmark_query|
|
||||
if SiteSetting.assign_enabled?
|
||||
assigned_user_ids = bookmarks.map(&:topic).map { |topic| topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID] }.compact.uniq
|
||||
assigned_users = {}
|
||||
User.where(id: assigned_user_ids).each do |user|
|
||||
assigned_users[user.id] = user
|
||||
end
|
||||
bookmarks.each do |bookmark|
|
||||
bookmark.topic.preload_assigned_to_user(
|
||||
assigned_users[bookmark.topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]]
|
||||
)
|
||||
end
|
||||
end
|
||||
BookmarkQuery.preloaded_custom_fields << TopicAssigner::ASSIGNED_TO_ID
|
||||
BookmarkQuery.on_preload do |bookmarks, bookmark_query|
|
||||
if SiteSetting.assign_enabled?
|
||||
assigned_user_ids = bookmarks.map(&:topic).map { |topic| topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID] }.compact.uniq
|
||||
assigned_users = User.where(id: assigned_user_ids).index_by(&:id)
|
||||
|
||||
bookmarks.each do |bookmark|
|
||||
bookmark.topic.preload_assigned_to_user(
|
||||
assigned_users[bookmark.topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -156,47 +150,40 @@ after_initialize do
|
|||
can_assign = topic_list.current_user && topic_list.current_user.can_assign?
|
||||
allowed_access = SiteSetting.assigns_public || can_assign
|
||||
|
||||
# TODO Drop AvatarLookup after Discourse 2.6.0 release
|
||||
lookup_columns = defined?(UserLookup) ? UserLookup.lookup_columns : AvatarLookup.lookup_columns
|
||||
|
||||
if allowed_access && topics.length > 0
|
||||
users = User.where("users.id in (
|
||||
users = User
|
||||
.where(<<~SQL, topic_ids: topics.map(&:id))
|
||||
users.id in (
|
||||
SELECT value::int
|
||||
FROM topic_custom_fields
|
||||
WHERE name = 'assigned_to_id' AND topic_id IN (?)
|
||||
)", topics.map(&:id))
|
||||
.select(lookup_columns)
|
||||
WHERE name = 'assigned_to_id' AND topic_id IN (:topic_ids)
|
||||
)
|
||||
SQL
|
||||
.select(UserLookup.lookup_columns)
|
||||
|
||||
if !defined?(UserLookup) # Remove after Discourse 2.6.0
|
||||
users = users.joins('join user_emails on user_emails.user_id = users.id AND user_emails.primary')
|
||||
end
|
||||
|
||||
map = {}
|
||||
users.each { |u| map[u.id] = u }
|
||||
users_map = users.index_by(&:id)
|
||||
|
||||
topics.each do |t|
|
||||
if id = t.custom_fields[TopicAssigner::ASSIGNED_TO_ID]
|
||||
t.preload_assigned_to_user(map[id.to_i])
|
||||
t.preload_assigned_to_user(users_map[id.to_i])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Search.respond_to?(:on_preload)
|
||||
Search.on_preload do |results, search|
|
||||
if SiteSetting.assign_enabled?
|
||||
can_assign = search.guardian&.can_assign?
|
||||
allowed_access = SiteSetting.assigns_public || can_assign
|
||||
Search.on_preload do |results, search|
|
||||
if SiteSetting.assign_enabled?
|
||||
can_assign = search.guardian&.can_assign?
|
||||
allowed_access = SiteSetting.assigns_public || can_assign
|
||||
|
||||
if allowed_access && results.posts.length > 0
|
||||
assigned_user_ids = results.posts.map(&:topic).map { |topic| topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID] }.compact.uniq
|
||||
assigned_users = User.where(id: assigned_user_ids).index_by(&:id)
|
||||
results.posts.each do |post|
|
||||
post.topic.preload_assigned_to_user(
|
||||
assigned_users[post.topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]]
|
||||
)
|
||||
end
|
||||
if allowed_access && results.posts.length > 0
|
||||
assigned_user_ids = results.posts.map(&:topic).map { |topic| topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID] }.compact.uniq
|
||||
assigned_users = User.where(id: assigned_user_ids).index_by(&:id)
|
||||
results.posts.each do |post|
|
||||
post.topic.preload_assigned_to_user(
|
||||
assigned_users[post.topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -206,9 +193,7 @@ after_initialize do
|
|||
TopicQuery.add_custom_filter(:assigned) do |results, topic_query|
|
||||
if topic_query.guardian.can_assign? || SiteSetting.assigns_public
|
||||
username = topic_query.options[:assigned]
|
||||
|
||||
user_id = topic_query.guardian.user.id if username == "me"
|
||||
|
||||
special = ["*", "nobody"].include?(username)
|
||||
|
||||
if username.present? && !special
|
||||
|
@ -216,14 +201,12 @@ after_initialize do
|
|||
end
|
||||
|
||||
if user_id || special
|
||||
|
||||
if username == "nobody"
|
||||
results = results.joins("LEFT JOIN topic_custom_fields tc_assign ON
|
||||
topics.id = tc_assign.topic_id AND
|
||||
tc_assign.name = 'assigned_to_id'")
|
||||
.where("tc_assign.name IS NULL")
|
||||
else
|
||||
|
||||
if username == "*"
|
||||
filter = "AND tc_assign.value IS NOT NULL"
|
||||
else
|
||||
|
@ -393,24 +376,20 @@ after_initialize do
|
|||
end
|
||||
end
|
||||
|
||||
if defined? register_permitted_bulk_action_parameter
|
||||
register_permitted_bulk_action_parameter :username
|
||||
register_permitted_bulk_action_parameter :username
|
||||
|
||||
add_to_class(:user_bookmark_serializer, :assigned_to_user_id) do
|
||||
id = topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]
|
||||
# a bit messy but race conditions can give us an array here, avoid
|
||||
id && id.to_i rescue nil
|
||||
end
|
||||
|
||||
if defined? UserBookmarkSerializer
|
||||
add_to_class(:user_bookmark_serializer, :assigned_to_user_id) do
|
||||
id = topic.custom_fields[TopicAssigner::ASSIGNED_TO_ID]
|
||||
# a bit messy but race conditions can give us an array here, avoid
|
||||
id && id.to_i rescue nil
|
||||
end
|
||||
add_to_serializer(:user_bookmark, :assigned_to_user, false) do
|
||||
topic.assigned_to_user
|
||||
end
|
||||
|
||||
add_to_serializer(:user_bookmark, :assigned_to_user, false) do
|
||||
topic.assigned_to_user
|
||||
end
|
||||
|
||||
add_to_serializer(:user_bookmark, 'include_assigned_to_user?') do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && topic.assigned_to_user
|
||||
end
|
||||
add_to_serializer(:user_bookmark, 'include_assigned_to_user?') do
|
||||
(SiteSetting.assigns_public || scope.can_assign?) && topic.assigned_to_user
|
||||
end
|
||||
|
||||
add_to_serializer(:current_user, :can_assign) do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { default as AssignedTopics } from "../fixtures/assigned-group-assignments-fixtures";
|
||||
import { default as GroupMembers } from "../fixtures/group-members-fixtures";
|
||||
import { acceptance, count } from "discourse/tests/helpers/qunit-helpers";
|
||||
import AssignedTopics from "../fixtures/assigned-group-assignments-fixtures";
|
||||
import GroupMembers from "../fixtures/group-members-fixtures";
|
||||
|
||||
acceptance("GroupAssignments", function (needs) {
|
||||
needs.user();
|
||||
|
@ -20,12 +20,12 @@ acceptance("GroupAssignments", function (needs) {
|
|||
test("Group Assignments Everyone", async (assert) => {
|
||||
await visit("/g/discourse/assigned");
|
||||
assert.equal(currentPath(), "group.assigned.show");
|
||||
assert.ok(find(".topic-list-item").length === 1);
|
||||
assert.equal(count(".topic-list-item"), 1);
|
||||
});
|
||||
|
||||
test("Group Assignments Ahmedgagan", async (assert) => {
|
||||
await visit("/g/discourse/assigned/ahmedgagan6");
|
||||
assert.equal(currentPath(), "group.assigned.show");
|
||||
assert.ok(find(".topic-list-item").length === 1);
|
||||
assert.equal(count(".topic-list-item"), 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import {
|
||||
acceptance,
|
||||
queryAll,
|
||||
query,
|
||||
updateCurrentUser,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { default as AssignedTopics } from "../fixtures/assigned-topics-fixtures";
|
||||
|
||||
const USER_MENU = "#current-user.header-dropdown-toggle";
|
||||
import AssignedTopics from "../fixtures/assigned-topics-fixtures";
|
||||
|
||||
acceptance("Quick access assignments panel", function (needs) {
|
||||
needs.user();
|
||||
|
@ -21,22 +19,15 @@ acceptance("Quick access assignments panel", function (needs) {
|
|||
updateCurrentUser({ can_assign: true });
|
||||
|
||||
await visit("/");
|
||||
await click(USER_MENU);
|
||||
await click("#current-user.header-dropdown-toggle");
|
||||
|
||||
// TODO: Remove when 2.7 gets released
|
||||
let quickAccessAssignmentsTab = ".widget-button.assigned";
|
||||
|
||||
if (queryAll(quickAccessAssignmentsTab).length === 0) {
|
||||
quickAccessAssignmentsTab = ".widget-link.assigned";
|
||||
}
|
||||
|
||||
await click(quickAccessAssignmentsTab);
|
||||
const assignment = find(".quick-access-panel li a")[0];
|
||||
await click(".widget-button.assigned");
|
||||
const assignment = query(".quick-access-panel li a");
|
||||
|
||||
assert.ok(assignment.innerText.includes("Greetings!"));
|
||||
assert.ok(assignment.href.includes("/t/greetings/10/5"));
|
||||
|
||||
await click(quickAccessAssignmentsTab);
|
||||
await click(".widget-button.assigned");
|
||||
assert.equal(
|
||||
currentPath(),
|
||||
"user.userActivity.assigned",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { default as AssignedTopics } from "../fixtures/assigned-topics-fixtures";
|
||||
import { acceptance, count } from "discourse/tests/helpers/qunit-helpers";
|
||||
import AssignedTopics from "../fixtures/assigned-topics-fixtures";
|
||||
|
||||
acceptance("UnAssign/Re-assign from the topics list", function (needs) {
|
||||
needs.user();
|
||||
|
@ -17,7 +17,7 @@ acceptance("UnAssign/Re-assign from the topics list", function (needs) {
|
|||
await visit("/u/eviltrout/activity/assigned");
|
||||
await options.expand();
|
||||
|
||||
assert.equal(find("li[data-value='unassign']").length, 1);
|
||||
assert.equal(find("li[data-value='reassign']").length, 1);
|
||||
assert.equal(count("li[data-value='unassign']"), 1);
|
||||
assert.equal(count("li[data-value='reassign']"), 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,46 +1,34 @@
|
|||
import componentTest from "discourse/tests/helpers/component-test";
|
||||
import componentTest, {
|
||||
setupRenderingTest,
|
||||
} from "discourse/tests/helpers/component-test";
|
||||
import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
moduleForComponent("group-assigned-filter", { integration: true });
|
||||
discourseModule(
|
||||
"Integration | Component | group-assigned-filter",
|
||||
function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
componentTest("display username", {
|
||||
template: "{{group-assigned-filter show-avatar=true filter=filter}}",
|
||||
componentTest("displays username and name", {
|
||||
template: "{{group-assigned-filter show-avatar=true filter=filter}}",
|
||||
|
||||
beforeEach() {
|
||||
this.siteSettings.prioritize_username_in_ux = true;
|
||||
this.set("filter", {
|
||||
id: 2,
|
||||
username: "Ahmed",
|
||||
name: "Ahmed Gagan",
|
||||
avatar_template: "/letter_avatar_proxy/v4/letter/a/8c91f0/{size}.png",
|
||||
title: "trust_level_0",
|
||||
last_posted_at: "2020-06-22T10:15:54.532Z",
|
||||
last_seen_at: "2020-07-07T11:55:59.437Z",
|
||||
added_at: "2020-06-22T09:55:31.692Z",
|
||||
timezone: "Asia/Calcutta",
|
||||
beforeEach() {
|
||||
this.set("filter", {
|
||||
id: 2,
|
||||
username: "Ahmed",
|
||||
name: "Ahmed Gagan",
|
||||
avatar_template: "/letter_avatar_proxy/v4/letter/a/8c91f0/{size}.png",
|
||||
title: "trust_level_0",
|
||||
last_posted_at: "2020-06-22T10:15:54.532Z",
|
||||
last_seen_at: "2020-07-07T11:55:59.437Z",
|
||||
added_at: "2020-06-22T09:55:31.692Z",
|
||||
timezone: "Asia/Calcutta",
|
||||
});
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
assert.equal(query(".assign-username").innerText, "Ahmed");
|
||||
assert.equal(query(".assign-name").innerText, "Ahmed Gagan");
|
||||
},
|
||||
});
|
||||
},
|
||||
async test(assert) {
|
||||
assert.ok(find("li")[0].innerText.trim(), "Ahmed");
|
||||
},
|
||||
});
|
||||
componentTest("display name", {
|
||||
template: "{{group-assigned-filter show-avatar=true filter=filter}}",
|
||||
|
||||
beforeEach() {
|
||||
this.siteSettings.prioritize_username_in_ux = true;
|
||||
this.set("filter", {
|
||||
id: 2,
|
||||
username: "Ahmed",
|
||||
name: "Ahmed Gagan",
|
||||
avatar_template: "/letter_avatar_proxy/v4/letter/a/8c91f0/{size}.png",
|
||||
title: "trust_level_0",
|
||||
last_posted_at: "2020-06-22T10:15:54.532Z",
|
||||
last_seen_at: "2020-07-07T11:55:59.437Z",
|
||||
added_at: "2020-06-22T09:55:31.692Z",
|
||||
timezone: "Asia/Calcutta",
|
||||
});
|
||||
},
|
||||
async test(assert) {
|
||||
assert.ok(find("li")[0].innerText.trim(), "Ahmed Gagan");
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue