DEV: Remove reviewable action custom_modal and use new action-based modal API (#23258)

This removes the custom_modal implementation for the
reviewable items and uses the new modal patterns defined at
https://meta.discourse.org/t/converting-modals-from-legacy-controllers-to-new-dmodal-component-api/268057

Only one plugin (discourse category experts) was using this API,
that has been fixed up here https://github.com/discourse/discourse-category-experts/pull/117

Also adds `registerReviewableActionModal` to allow for plugins and
core to map a reviewable action ID to an actual
JS class for the modal and improves docs for plugin API functions
used by reviewable-item.
This commit is contained in:
Martin Brennan 2023-08-29 14:36:20 +10:00 committed by GitHub
parent 27ebbd2f8d
commit e562bb1f43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 17 deletions

View File

@ -15,6 +15,7 @@ import ExplainReviewableModal from "discourse/components/modal/explain-reviewabl
let _components = {};
const pluginReviewableParams = {};
const actionModalClassMap = {};
export function addPluginReviewableParam(reviewableType, param) {
pluginReviewableParams[reviewableType]
@ -22,6 +23,10 @@ export function addPluginReviewableParam(reviewableType, param) {
: (pluginReviewableParams[reviewableType] = [param]);
}
export function registerReviewableActionModal(actionName, modalClass) {
actionModalClassMap[actionName] = modalClass;
}
export default Component.extend({
adminTools: optionalService(),
dialog: service(),
@ -273,8 +278,11 @@ export default Component.extend({
}
const message = performableAction.get("confirm_message");
let requireRejectReason = performableAction.get("require_reject_reason");
let customModal = performableAction.get("custom_modal");
const requireRejectReason = performableAction.get(
"require_reject_reason"
);
const actionModalClass = actionModalClassMap[performableAction.id];
if (message) {
this.dialog.confirm({
message,
@ -288,13 +296,13 @@ export default Component.extend({
performConfirmed: this._performConfirmed,
action: performableAction,
});
} else if (customModal) {
showModal(customModal, {
title: `review.${customModal}.title`,
model: this.reviewable,
}).setProperties({
performConfirmed: this._performConfirmed,
action: performableAction,
} else if (actionModalClass) {
this.modal.show(actionModalClass, {
model: {
reviewable: this.reviewable,
performConfirmed: this._performConfirmed,
action: performableAction,
},
});
} else {
return this._performConfirmed(performableAction);

View File

@ -55,7 +55,10 @@ import { addGlobalNotice } from "discourse/components/global-notice";
import { addNavItem } from "discourse/models/nav-item";
import { addPluginDocumentTitleCounter } from "discourse/components/d-document";
import { addPluginOutletDecorator } from "discourse/components/plugin-connector";
import { addPluginReviewableParam } from "discourse/components/reviewable-item";
import {
addPluginReviewableParam,
registerReviewableActionModal,
} from "discourse/components/reviewable-item";
import {
addComposerSaveErrorCallback,
addPopupMenuOptionsCallback,
@ -130,7 +133,7 @@ import { _addBulkButton } from "discourse/components/modal/topic-bulk-actions";
// based on Semantic Versioning 2.0.0. Please update the changelog at
// docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version
// using the format described at https://keepachangelog.com/en/1.0.0/.
export const PLUGIN_API_VERSION = "1.9.0";
export const PLUGIN_API_VERSION = "1.10.0";
// This helper prevents us from applying the same `modifyClass` over and over in test mode.
function canModify(klass, type, resolverName, changes) {
@ -1648,10 +1651,44 @@ class PluginApi {
addSaveableUserOptionField(fieldName) {
addSaveableUserOptionField(fieldName);
}
/**
* Adds additional params to be sent to the reviewable/:id/perform/:action
* endpoint for a given reviewable type. This is so plugins can provide more
* complex reviewable actions that may depend on a custom modal.
*
* This is copied from the reviewable model instance when performing an action
* on the ReviewableItem component.
*
* ```
* api.addPluginReviewableParam("ReviewablePluginType", "some_param");
* ```
**/
addPluginReviewableParam(reviewableType, param) {
addPluginReviewableParam(reviewableType, param);
}
/**
* Registers a mapping between a JavaScript modal component class and a server-side reviewable
* action, which is registered via `actions.add` and `build_actions`.
*
* For more information about modal classes, which are special Ember components used with
* the DModal API, see:
*
* https://meta.discourse.org/t/using-the-dmodal-api-to-render-modal-windows-aka-popups-dialogs-in-discourse/268304.
*
* @param {String} reviewableAction - The action name, as registered in the server-side.
* @param {Class} modalClass - The actual JavaScript class of the modal.
*
* @example
* ```
* api.registerReviewableActionModal("approve_category_expert", ExpertGroupChooserModal);
* ```
**/
registerReviewableActionModal(reviewableType, modalClass) {
registerReviewableActionModal(reviewableType, modalClass);
}
/**
* Change the default category background and text colors in the
* category creation modal.

View File

@ -8,8 +8,7 @@ class ReviewableActionSerializer < ApplicationSerializer
:confirm_message,
:description,
:client_action,
:require_reject_reason,
:custom_modal
:require_reject_reason
def label
I18n.t(object.label)
@ -38,8 +37,4 @@ class ReviewableActionSerializer < ApplicationSerializer
def include_require_reject_reason?
object.require_reject_reason.present?
end
def include_custom_modal?
object.custom_modal.present?
end
end

View File

@ -7,6 +7,13 @@ in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.10.0] - 2023-08-25
### Added
- Adds `registerReviewableActionModal` which allows core and plugins to register a modal component class
which is used to show a modal for certain reviewable actions.
## [1.9.0] - 2023-08-09
### Added