DEV: APIs for plugin to add custom reviewable confirm modal (#12246)
This commit is contained in:
parent
4c1e02d412
commit
4adce0d844
|
@ -12,6 +12,14 @@ import showModal from "discourse/lib/show-modal";
|
||||||
|
|
||||||
let _components = {};
|
let _components = {};
|
||||||
|
|
||||||
|
const pluginReviewableParams = {};
|
||||||
|
|
||||||
|
export function addPluginReviewableParam(reviewableType, param) {
|
||||||
|
pluginReviewableParams[reviewableType]
|
||||||
|
? pluginReviewableParams[reviewableType].push(param)
|
||||||
|
: (pluginReviewableParams[reviewableType] = [param]);
|
||||||
|
}
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
adminTools: optionalService(),
|
adminTools: optionalService(),
|
||||||
tagName: "",
|
tagName: "",
|
||||||
|
@ -106,14 +114,23 @@ export default Component.extend({
|
||||||
let performAction = () => {
|
let performAction = () => {
|
||||||
let version = reviewable.get("version");
|
let version = reviewable.get("version");
|
||||||
this.set("updating", true);
|
this.set("updating", true);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
send_email: reviewable.sendEmail,
|
||||||
|
reject_reason: reviewable.rejectReason,
|
||||||
|
};
|
||||||
|
|
||||||
|
(pluginReviewableParams[reviewable.type] || []).forEach((param) => {
|
||||||
|
if (reviewable[param]) {
|
||||||
|
data[param] = reviewable[param];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return ajax(
|
return ajax(
|
||||||
`/review/${reviewable.id}/perform/${action.id}?version=${version}`,
|
`/review/${reviewable.id}/perform/${action.id}?version=${version}`,
|
||||||
{
|
{
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
data: {
|
data,
|
||||||
send_email: reviewable.sendEmail,
|
|
||||||
reject_reason: reviewable.rejectReason,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
@ -227,6 +244,7 @@ export default Component.extend({
|
||||||
|
|
||||||
let msg = action.get("confirm_message");
|
let msg = action.get("confirm_message");
|
||||||
let requireRejectReason = action.get("require_reject_reason");
|
let requireRejectReason = action.get("require_reject_reason");
|
||||||
|
let customModal = action.get("custom_modal");
|
||||||
if (msg) {
|
if (msg) {
|
||||||
bootbox.confirm(msg, (answer) => {
|
bootbox.confirm(msg, (answer) => {
|
||||||
if (answer) {
|
if (answer) {
|
||||||
|
@ -241,6 +259,14 @@ export default Component.extend({
|
||||||
performConfirmed: this._performConfirmed.bind(this),
|
performConfirmed: this._performConfirmed.bind(this),
|
||||||
action,
|
action,
|
||||||
});
|
});
|
||||||
|
} else if (customModal) {
|
||||||
|
showModal(customModal, {
|
||||||
|
title: `review.${customModal}.title`,
|
||||||
|
model: this.reviewable,
|
||||||
|
}).setProperties({
|
||||||
|
performConfirmed: this._performConfirmed.bind(this),
|
||||||
|
action,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return this._performConfirmed(action);
|
return this._performConfirmed(action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import { addGTMPageChangedCallback } from "discourse/lib/page-tracker";
|
||||||
import { addGlobalNotice } from "discourse/components/global-notice";
|
import { addGlobalNotice } from "discourse/components/global-notice";
|
||||||
import { addNavItem } from "discourse/models/nav-item";
|
import { addNavItem } from "discourse/models/nav-item";
|
||||||
import { addPluginOutletDecorator } from "discourse/components/plugin-connector";
|
import { addPluginOutletDecorator } from "discourse/components/plugin-connector";
|
||||||
|
import { addPluginReviewableParam } from "discourse/components/reviewable-item";
|
||||||
import { addPopupMenuOptionsCallback } from "discourse/controllers/composer";
|
import { addPopupMenuOptionsCallback } from "discourse/controllers/composer";
|
||||||
import { addPostClassesCallback } from "discourse/widgets/post";
|
import { addPostClassesCallback } from "discourse/widgets/post";
|
||||||
import { addPostSmallActionIcon } from "discourse/widgets/post-small-action";
|
import { addPostSmallActionIcon } from "discourse/widgets/post-small-action";
|
||||||
|
@ -1222,6 +1223,9 @@ class PluginApi {
|
||||||
addSaveableUserOptionField(fieldName) {
|
addSaveableUserOptionField(fieldName) {
|
||||||
addSaveableUserOptionField(fieldName);
|
addSaveableUserOptionField(fieldName);
|
||||||
}
|
}
|
||||||
|
addPluginReviewableParam(reviewableType, param) {
|
||||||
|
addPluginReviewableParam(reviewableType, param);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the default category background and text colors in the
|
* Change the default category background and text colors in the
|
||||||
|
|
|
@ -192,6 +192,11 @@ class ReviewablesController < ApplicationController
|
||||||
|
|
||||||
args.merge!(reject_reason: params[:reject_reason], send_email: params[:send_email] != "false") if reviewable.type == 'ReviewableUser'
|
args.merge!(reject_reason: params[:reject_reason], send_email: params[:send_email] != "false") if reviewable.type == 'ReviewableUser'
|
||||||
|
|
||||||
|
plugin_params = DiscoursePluginRegistry.reviewable_params.select do |reviewable_param|
|
||||||
|
reviewable.type == reviewable_param[:type].to_s.classify
|
||||||
|
end
|
||||||
|
args.merge!(params.slice(*plugin_params.map { |pp| pp[:param] }).permit!)
|
||||||
|
|
||||||
result = reviewable.perform(current_user, params[:action_id].to_sym, args)
|
result = reviewable.perform(current_user, params[:action_id].to_sym, args)
|
||||||
rescue Reviewable::InvalidAction => e
|
rescue Reviewable::InvalidAction => e
|
||||||
# Consider InvalidAction an InvalidAccess
|
# Consider InvalidAction an InvalidAccess
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ReviewableActionSerializer < ApplicationSerializer
|
class ReviewableActionSerializer < ApplicationSerializer
|
||||||
attributes :id, :icon, :button_class, :label, :confirm_message, :description, :client_action, :require_reject_reason
|
attributes :id, :icon, :button_class, :label, :confirm_message, :description, :client_action, :require_reject_reason, :custom_modal
|
||||||
|
|
||||||
def label
|
def label
|
||||||
I18n.t(object.label)
|
I18n.t(object.label)
|
||||||
|
@ -30,4 +30,8 @@ class ReviewableActionSerializer < ApplicationSerializer
|
||||||
def include_require_reject_reason?
|
def include_require_reject_reason?
|
||||||
object.require_reject_reason.present?
|
object.require_reject_reason.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include_custom_modal?
|
||||||
|
object.custom_modal.present?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -84,6 +84,7 @@ class DiscoursePluginRegistry
|
||||||
define_filtered_register :user_api_key_scope_mappings
|
define_filtered_register :user_api_key_scope_mappings
|
||||||
|
|
||||||
define_filtered_register :permitted_bulk_action_parameters
|
define_filtered_register :permitted_bulk_action_parameters
|
||||||
|
define_filtered_register :reviewable_params
|
||||||
|
|
||||||
def self.register_auth_provider(auth_provider)
|
def self.register_auth_provider(auth_provider)
|
||||||
self.auth_providers << auth_provider
|
self.auth_providers << auth_provider
|
||||||
|
|
|
@ -877,6 +877,13 @@ class Plugin::Instance
|
||||||
DiscoursePluginRegistry.demon_processes << demon_class
|
DiscoursePluginRegistry.demon_processes << demon_class
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_permitted_reviewable_param(type, param)
|
||||||
|
DiscoursePluginRegistry.register_reviewable_param({
|
||||||
|
type: type,
|
||||||
|
param: param
|
||||||
|
}, self)
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def self.js_path
|
def self.js_path
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Reviewable < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
class Action < Item
|
class Action < Item
|
||||||
attr_accessor :icon, :button_class, :label, :description, :confirm_message, :client_action, :require_reject_reason
|
attr_accessor :icon, :button_class, :label, :description, :confirm_message, :client_action, :require_reject_reason, :custom_modal
|
||||||
|
|
||||||
def initialize(id, icon = nil, button_class = nil, label = nil)
|
def initialize(id, icon = nil, button_class = nil, label = nil)
|
||||||
super(id)
|
super(id)
|
||||||
|
|
|
@ -432,6 +432,48 @@ describe ReviewablesController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "with reviewable params added via plugin API" do
|
||||||
|
class ::ReviewablePhony < Reviewable
|
||||||
|
def build_actions(actions, guardian, _args)
|
||||||
|
return [] unless pending?
|
||||||
|
|
||||||
|
actions.add(:approve_phony) do |action|
|
||||||
|
action.label = "js.phony.review.approve"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_approve_phony(performed_by, args)
|
||||||
|
puts args.inspect
|
||||||
|
MessageBus.publish("/phony-reviewable-test", { args: args }, user_ids: [1])
|
||||||
|
create_result(:success, :approved)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
plugin = Plugin::Instance.new
|
||||||
|
plugin.add_permitted_reviewable_param(:reviewable_phony, :fake_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
DiscoursePluginRegistry.reset!
|
||||||
|
end
|
||||||
|
|
||||||
|
fab!(:reviewable_phony) { Fabricate(:reviewable, type: "ReviewablePhony") }
|
||||||
|
|
||||||
|
it "passes the added param into the reviewable class' perform method" do
|
||||||
|
MessageBus.expects(:publish)
|
||||||
|
.with("/phony-reviewable-test", { args: {
|
||||||
|
version: reviewable_phony.version,
|
||||||
|
"fake_id" => "2" }
|
||||||
|
},
|
||||||
|
{ user_ids: [1] })
|
||||||
|
.once
|
||||||
|
|
||||||
|
put "/review/#{reviewable_phony.id}/perform/approve_phony.json?version=#{reviewable_phony.version}", params: { fake_id: 2 }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "#topics" do
|
context "#topics" do
|
||||||
fab!(:post0) { Fabricate(:post) }
|
fab!(:post0) { Fabricate(:post) }
|
||||||
fab!(:post1) { Fabricate(:post, topic: post0.topic) }
|
fab!(:post1) { Fabricate(:post, topic: post0.topic) }
|
||||||
|
|
Loading…
Reference in New Issue