DEV: Remove Category.findById from admin web hooks (#26605)

Include categories when fetching admin/web_hooks and make
'extras' more useful. 'extras' is the mechanism we use to provide
context for rest objects.

However, previously:

 * When you fetched many objects, extras was only set on the ResultSet,
   not on each object,

 * If you need derived data from extras, there wasn't a sensible place to
   put this code. Now, you can create an 'ExtrasClass' static field on
   your rest model and this class will be used for your extras data,
This commit is contained in:
Daniel Waterworth 2024-04-11 16:11:00 -05:00 committed by GitHub
parent 463eff2bbf
commit cead0cf684
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 72 additions and 15 deletions

View File

@ -1,13 +1,36 @@
import { tracked } from "@glimmer/tracking";
import { computed } from "@ember/object";
import { isEmpty } from "@ember/utils";
import { observes } from "@ember-decorators/object";
import Category from "discourse/models/category";
import Group from "discourse/models/group";
import RestModel from "discourse/models/rest";
import Site from "discourse/models/site";
import discourseComputed from "discourse-common/utils/decorators";
class WebHookExtras {
@tracked categories;
constructor(args) {
this.categories = args.categories;
this.content_types = args.content_types;
this.default_event_types = args.default_event_types;
this.delivery_statuses = args.delivery_statuses;
this.grouped_event_types = args.grouped_event_types;
}
get categoriesById() {
if (this.categories) {
return new Map(this.categories.map((c) => [c.id, c]));
}
}
findCategoryById(id) {
return this.categoriesById?.get(id);
}
}
export default class WebHook extends RestModel {
static ExtrasClass = WebHookExtras;
content_type = 1; // json
last_delivery_status = 1; // inactive
wildcard_web_hook = false;
@ -27,7 +50,9 @@ export default class WebHook extends RestModel {
@computed("category_ids")
get categories() {
return Category.findByIds(this.category_ids);
return (this.category_ids || []).map((id) =>
this.extras.findCategoryById(id)
);
}
set categories(value) {

View File

@ -126,7 +126,14 @@ export default class StoreService extends Service {
let hydrated = this._hydrateFindResults(result, type, findArgs, opts);
if (result.extras) {
hydrated.set("extras", result.extras);
let extras = result.extras;
const extrasClass = this._extrasClass(type);
if (extrasClass) {
extras = new extrasClass(extras);
}
hydrated.set("extras", extras);
}
if (adapter.cache) {
@ -260,12 +267,28 @@ export default class StoreService extends Service {
};
if (result.extras) {
createArgs.extras = result.extras;
let extras = result.extras;
const extrasClass = this._extrasClass(type);
if (extrasClass) {
extras = new extrasClass(extras);
}
createArgs.extras = extras;
for (const obj of content) {
obj.extras = extras;
}
}
return ResultSet.create(createArgs);
}
_extrasClass(type) {
const klass = this.register.lookupFactory("model:" + type) || RestModel;
return klass.class?.ExtrasClass;
}
_build(type, obj) {
const adapter = this.adapterFor(type);
obj.store = this;

View File

@ -16,6 +16,7 @@ acceptance("Admin - Webhooks", function (needs) {
total_rows_web_hooks: 0,
load_more_web_hooks: "/admin/api/web_hooks.json?limit=50&offset=50",
extras: {
categories: [],
content_types: [
{ id: 1, name: "application/json" },
{ id: 2, name: "application/x-www-form-urlencoded" },

View File

@ -15,15 +15,18 @@ class Admin::WebHooksController < Admin::AdminController
.includes(:categories)
.includes(:groups)
data = serialize_data(web_hooks, AdminWebHookSerializer, root: "web_hooks")
json = {
web_hooks: serialize_data(web_hooks, AdminWebHookSerializer),
extras: {
grouped_event_types: WebHookEventType.active_grouped,
default_event_types: WebHook.default_event_types,
content_types: WebHook.content_types.map { |name, id| { id: id, name: name } },
delivery_statuses:
WebHook.last_delivery_statuses.map { |name, id| { id: id, name: name.to_s } },
},
web_hooks: data.delete("web_hooks"),
extras:
data.merge(
grouped_event_types: WebHookEventType.active_grouped,
default_event_types: WebHook.default_event_types,
content_types: WebHook.content_types.map { |name, id| { id: id, name: name } },
delivery_statuses:
WebHook.last_delivery_statuses.map { |name, id| { id: id, name: name.to_s } },
),
total_rows_web_hooks: WebHook.count,
load_more_web_hooks:
admin_web_hooks_path(limit: limit, offset: offset + limit, format: :json),
@ -33,11 +36,16 @@ class Admin::WebHooksController < Admin::AdminController
end
def show
render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
data = serialize_data(@web_hook, AdminWebHookSerializer, root: "web_hook")
web_hook = data.delete("web_hook")
data = { "extras" => data, "web_hook" => web_hook }
render json: MultiJson.dump(data), status: 200
end
def edit
render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
data = serialize_data(@web_hook, AdminWebHookSerializer, root: "web_hook")
data["extras"] = { "categories" => data.delete(:categories) }
render json: MultiJson.dump(data), status: 200
end
def create

View File

@ -11,7 +11,7 @@ class AdminWebHookSerializer < ApplicationSerializer
:active,
:web_hook_event_types
has_many :categories, serializer: BasicCategorySerializer, embed: :ids, include: false
has_many :categories, serializer: BasicCategorySerializer, embed: :ids, include: true
has_many :tags,
key: :tag_names,
serializer: TagSerializer,