mirror of
https://github.com/discourse/discourse.git
synced 2025-03-23 23:35:38 +08:00
DEV: Plugin API for customizing text in the composer conditionally
Co-authored-by: Isaac Janzen <issac.janzen@discourse.org>
This commit is contained in:
parent
3eb737c014
commit
bef5223672
@ -24,8 +24,15 @@ export default Component.extend({
|
||||
options: alias("model.replyOptions"),
|
||||
action: alias("model.action"),
|
||||
|
||||
@discourseComputed("options", "action")
|
||||
// Note we update when some other attributes like tag/category change to allow
|
||||
// text customizations to use those.
|
||||
@discourseComputed("options", "action", "model.tags", "model.category")
|
||||
actionTitle(opts, action) {
|
||||
let result = this.model.customizationFor("actionTitle");
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (TITLES[action]) {
|
||||
return I18n.t(TITLES[action]);
|
||||
}
|
||||
|
@ -240,13 +240,22 @@ export default Controller.extend({
|
||||
return SAVE_ICONS[modelAction];
|
||||
},
|
||||
|
||||
// Note we update when some other attributes like tag/category change to allow
|
||||
// text customizations to use those.
|
||||
@discourseComputed(
|
||||
"model.action",
|
||||
"isWhispering",
|
||||
"model.editConflict",
|
||||
"model.privateMessage"
|
||||
"model.privateMessage",
|
||||
"model.tags",
|
||||
"model.category"
|
||||
)
|
||||
saveLabel(modelAction, isWhispering, editConflict, privateMessage) {
|
||||
let result = this.model.customizationFor("saveLabel");
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (editConflict) {
|
||||
return "composer.overwrite_edit";
|
||||
} else if (isWhispering) {
|
||||
|
@ -37,7 +37,9 @@ import {
|
||||
registerIconRenderer,
|
||||
replaceIcon,
|
||||
} from "discourse-common/lib/icon-library";
|
||||
import Composer from "discourse/models/composer";
|
||||
import Composer, {
|
||||
registerCustomizationCallback,
|
||||
} from "discourse/models/composer";
|
||||
import DiscourseBanner from "discourse/components/discourse-banner";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import Sharing from "discourse/lib/sharing";
|
||||
@ -87,7 +89,7 @@ import { addSearchSuggestion } from "discourse/widgets/search-menu-results";
|
||||
import { CUSTOM_USER_SEARCH_OPTIONS } from "select-kit/components/user-chooser";
|
||||
|
||||
// If you add any methods to the API ensure you bump up this number
|
||||
const PLUGIN_API_VERSION = "0.12.3";
|
||||
const PLUGIN_API_VERSION = "0.12.5";
|
||||
|
||||
// This helper prevents us from applying the same `modifyClass` over and over in test mode.
|
||||
function canModify(klass, type, resolverName, changes) {
|
||||
@ -1471,6 +1473,28 @@ class PluginApi {
|
||||
{ ignoreMissing: true }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for customizing the composer text. By providing a callback. Callbacks should
|
||||
* return `null` or `undefined` if you don't need a customization based on the current state.
|
||||
*
|
||||
* ```
|
||||
* api.customizeComposerText({
|
||||
* actionTitle(model) {
|
||||
* if (model.hello) {
|
||||
* return "hello.world";
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* saveLabel(model) {
|
||||
* return "my.custom_save_label_key";
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*/
|
||||
customizeComposerText(callbacks) {
|
||||
registerCustomizationCallback(callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number
|
||||
|
@ -24,6 +24,15 @@ import { isEmpty } from "@ember/utils";
|
||||
import { propertyNotEqual } from "discourse/lib/computed";
|
||||
import { throwAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
let _customizations = [];
|
||||
export function registerCustomizationCallback(cb) {
|
||||
_customizations.push(cb);
|
||||
}
|
||||
|
||||
export function resetComposerCustomizations() {
|
||||
_customizations = [];
|
||||
}
|
||||
|
||||
// The actions the composer can take
|
||||
export const CREATE_TOPIC = "createTopic",
|
||||
CREATE_SHARED_DRAFT = "createSharedDraft",
|
||||
@ -1305,6 +1314,18 @@ const Composer = RestModel.extend({
|
||||
this.set("draftSaving", false);
|
||||
});
|
||||
},
|
||||
|
||||
customizationFor(type) {
|
||||
for (let i = 0; i < _customizations.length; i++) {
|
||||
let cb = _customizations[i][type];
|
||||
if (cb) {
|
||||
let result = cb(this);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Composer.reopenClass({
|
||||
|
@ -12,7 +12,8 @@ import { click, currentURL, fillIn, visit } from "@ember/test-helpers";
|
||||
import { skip, test } from "qunit";
|
||||
import Draft from "discourse/models/draft";
|
||||
import I18n from "I18n";
|
||||
import { NEW_TOPIC_KEY } from "discourse/models/composer";
|
||||
import { CREATE_TOPIC, NEW_TOPIC_KEY } from "discourse/models/composer";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { Promise } from "rsvp";
|
||||
import { run } from "@ember/runloop";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
@ -1008,3 +1009,51 @@ acceptance("Composer", function (needs) {
|
||||
assert.notOk(exists(".discard-draft-modal .save-draft"));
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Composer - Customizations", function (needs) {
|
||||
needs.user();
|
||||
needs.site({ can_tag_topics: true });
|
||||
|
||||
function customComposerAction(composer) {
|
||||
return (
|
||||
(composer.tags || []).indexOf("monkey") !== -1 &&
|
||||
composer.action === CREATE_TOPIC
|
||||
);
|
||||
}
|
||||
|
||||
needs.hooks.beforeEach(() => {
|
||||
withPluginApi("0.8.14", (api) => {
|
||||
api.customizeComposerText({
|
||||
actionTitle(model) {
|
||||
if (customComposerAction(model)) {
|
||||
return "custom text";
|
||||
}
|
||||
},
|
||||
|
||||
saveLabel(model) {
|
||||
if (customComposerAction(model)) {
|
||||
return "composer.emoji";
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("Supports text customization", async function (assert) {
|
||||
await visit("/");
|
||||
await click("#create-topic");
|
||||
assert.equal(query(".action-title").innerText, I18n.t("topic.create_long"));
|
||||
assert.equal(
|
||||
query(".save-or-cancel button").innerText,
|
||||
I18n.t("composer.create_topic")
|
||||
);
|
||||
const tags = selectKit(".mini-tag-chooser");
|
||||
await tags.expand();
|
||||
await tags.selectRowByValue("monkey");
|
||||
assert.equal(query(".action-title").innerText, "custom text");
|
||||
assert.equal(
|
||||
query(".save-or-cancel button").innerText,
|
||||
I18n.t("composer.emoji")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -37,6 +37,7 @@ import { resetUsernameDecorators } from "discourse/helpers/decorate-username-sel
|
||||
import { resetWidgetCleanCallbacks } from "discourse/components/mount-widget";
|
||||
import { resetUserSearchCache } from "discourse/lib/user-search";
|
||||
import { resetCardClickListenerSelector } from "discourse/mixins/card-contents-base";
|
||||
import { resetComposerCustomizations } from "discourse/models/composer";
|
||||
import sessionFixtures from "discourse/tests/fixtures/session-fixtures";
|
||||
import { setTopicList } from "discourse/lib/topic-list-tracker";
|
||||
import sinon from "sinon";
|
||||
@ -280,6 +281,7 @@ export function acceptance(name, optionsOrCallback) {
|
||||
resetCustomPostMessageCallbacks();
|
||||
resetUserSearchCache();
|
||||
resetCardClickListenerSelector();
|
||||
resetComposerCustomizations();
|
||||
resetPostMenuExtraButtons();
|
||||
clearNavItems();
|
||||
setTopicList(null);
|
||||
|
Loading…
x
Reference in New Issue
Block a user