The implementation previously generated a descriptor with an `initializer()`, and bound the function to the `this` context of the initializer. In native class syntax, the initializer of a descriptor is only called once, with a `this` context of the constructor, not the instance. This commit updates the implementation so that it generates the bound function on-demand using a getter. This is the same strategy employed by ember's built-in `@action` decorator. Unfortunately, this use of a getter means that the `@observes` decorator does not support being directly chained to `@debounce`. It throws the error "`observer must be provided a function or an observer definition`". The workaround is to put the observer on its own function, which then calls the debounced function. Given that we're aiming to reduce our usage of `@observes`, we've accepted the need for this workaround rather than spending the time to patch the implementation of `@observes`.
118 lines
2.6 KiB
JavaScript
118 lines
2.6 KiB
JavaScript
import Controller, { inject as controller } from "@ember/controller";
|
|
import discourseComputed, {
|
|
debounce,
|
|
observes,
|
|
} from "discourse-common/utils/decorators";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
|
|
|
export default Controller.extend({
|
|
application: controller(),
|
|
|
|
queryParams: ["order", "asc", "filter"],
|
|
|
|
order: "",
|
|
asc: null,
|
|
filter: null,
|
|
filterInput: null,
|
|
|
|
loading: false,
|
|
|
|
@observes("filterInput")
|
|
filterInputChanged() {
|
|
this._setFilter();
|
|
},
|
|
|
|
@debounce(500)
|
|
_setFilter() {
|
|
this.set("filter", this.filterInput);
|
|
},
|
|
|
|
@observes("order", "asc", "filter")
|
|
_filtersChanged() {
|
|
this.findRequesters(true);
|
|
},
|
|
|
|
findRequesters(refresh) {
|
|
if (this.loading) {
|
|
return;
|
|
}
|
|
|
|
const model = this.model;
|
|
if (!model) {
|
|
return;
|
|
}
|
|
|
|
if (!refresh && model.requesters.length >= model.user_count) {
|
|
this.set("application.showFooter", true);
|
|
return;
|
|
}
|
|
|
|
this.set("loading", true);
|
|
model.findRequesters(this.memberParams, refresh).finally(() => {
|
|
this.set(
|
|
"application.showFooter",
|
|
model.requesters.length >= model.user_count
|
|
);
|
|
this.set("loading", false);
|
|
});
|
|
},
|
|
|
|
@discourseComputed("order", "asc", "filter")
|
|
memberParams(order, asc, filter) {
|
|
return { order, asc, filter };
|
|
},
|
|
|
|
@discourseComputed("model.requesters.[]")
|
|
hasRequesters(requesters) {
|
|
return requesters && requesters.length > 0;
|
|
},
|
|
|
|
@discourseComputed
|
|
filterPlaceholder() {
|
|
if (this.currentUser && this.currentUser.admin) {
|
|
return "groups.members.filter_placeholder_admin";
|
|
} else {
|
|
return "groups.members.filter_placeholder";
|
|
}
|
|
},
|
|
|
|
handleRequest(data) {
|
|
ajax(`/groups/${this.get("model.id")}/handle_membership_request.json`, {
|
|
data,
|
|
type: "PUT",
|
|
}).catch(popupAjaxError);
|
|
},
|
|
|
|
actions: {
|
|
loadMore() {
|
|
this.findRequesters();
|
|
},
|
|
|
|
acceptRequest(user) {
|
|
this.handleRequest({ user_id: user.get("id"), accept: true });
|
|
user.setProperties({
|
|
request_accepted: true,
|
|
request_denied: false,
|
|
});
|
|
},
|
|
|
|
undoAcceptRequest(user) {
|
|
ajax("/groups/" + this.get("model.id") + "/members.json", {
|
|
type: "DELETE",
|
|
data: { user_id: user.get("id") },
|
|
}).then(() => {
|
|
user.set("request_undone", true);
|
|
});
|
|
},
|
|
|
|
denyRequest(user) {
|
|
this.handleRequest({ user_id: user.get("id") });
|
|
user.setProperties({
|
|
request_accepted: false,
|
|
request_denied: true,
|
|
});
|
|
},
|
|
},
|
|
});
|