[IMP] web: add messageIsHtml option for rainbowman

Before this commit, rainbowman message was displayed using
`t-raw` in template.
Now, the message is escaped by default and needs to be marked as
HTML to be displayed as well.

closes odoo/odoo#72392

Task-id: 2575435
Related: odoo/enterprise#19121
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Michael Mattiello (mcm)
2021-06-22 08:06:07 +00:00
parent 441baf578e
commit 9ecadd06ac
6 changed files with 41 additions and 6 deletions
@@ -35,6 +35,7 @@ var RainbowMan = Widget.extend({
fadeout: 'medium',
img_url: '/web/static/img/smile.svg',
message: _t('Well Done!'),
messageIsHtml: false,
});
this.delay = rainbowDelay[this.options.fadeout];
},
@@ -61,7 +62,16 @@ var RainbowMan = Widget.extend({
}, 600); // destroy only after fadeout animation is completed
}, this.delay);
}
this.$('.o_reward_msg_content').append(this.options.message);
let message = this.options.message;
if (!this.options.messageIsHtml) {
if (message instanceof jQuery) {
message = message.text();
} else if (message instanceof Element) {
message = message.textContent;
}
message = document.createTextNode(message);
}
this.$('.o_reward_msg_content').append(message);
return this._super.apply(this, arguments);
}
});
@@ -7,7 +7,5 @@ import { bus } from "web.core";
* isn't a parent of the current context. Like in the tour manager in website.
*/
bus.on("show-effect", this, (payload) => {
new RainbowMan({ message: payload.message, fadeout: payload.fadeout }).appendTo(
document.getElementsByTagName("body")[0]
);
new RainbowMan(payload).appendTo(document.getElementsByTagName("body")[0]);
});
@@ -54,6 +54,8 @@ export const effectService = {
* Can be a simple a string
* Can be a string representation of html (prefer component if you want interactions in the DOM)
* Can be a function returning a string (like _t)
* @param {boolean} [params.messageIsHtml]
* The message can be a string representation of html but it needs to be marked as well
* @param {"slow"|"medium"|"fast"|"no"} [params.fadeout="medium"]
* Delay for rainbowman to disappear
* 'fast' will make rainbowman dissapear quickly
@@ -72,6 +74,7 @@ export const effectService = {
fadeout: params.fadeout,
id: ++effectId,
message: convertRainBowMessage(params.message) || env._t("Well Done!"),
messageIsHtml: params.messageIsHtml || false,
Component: params.Component,
props: params.props,
});
@@ -35,7 +35,10 @@
<div class="o_reward_msg">
<div class="o_reward_msg_card">
<div class="o_reward_msg_content">
<t t-if="!props.Component" t-raw="props.message" />
<t t-if="!props.Component">
<t t-if="props.messageIsHtml" t-raw="props.message" />
<t t-else="" t-esc="props.message" />
</t>
<t t-else="" t-component="props.Component" t-props="props.props"/>
</div>
<div class="o_reward_shadow_container">
@@ -27,6 +27,7 @@ QUnit.module("RainbowMan", (hooks) => {
hooks.beforeEach(async () => {
rainbowManDefault = {
message: "<div>Congrats!</div>",
messageIsHtml: true,
fadeout: "nextTick",
};
target = getFixture();
@@ -72,4 +73,19 @@ QUnit.module("RainbowMan", (hooks) => {
assert.containsNone(target, ".o_reward");
parent.destroy();
});
QUnit.test("rendering a rainbowman with an escaped message", async function (assert) {
assert.expect(3);
const env = await makeTestEnv({ serviceRegistry });
const parent = await mount(Parent, { env, target });
env.services.effect.add("rainbowman", { ...rainbowManDefault, messageIsHtml: false });
await nextTick();
assert.containsOnce(parent.el, ".o_reward");
assert.containsOnce(parent.el, ".o_reward_rainbow");
assert.strictEqual(
parent.el.querySelector(".o_reward_msg_content").textContent,
"<div>Congrats!</div>"
);
parent.destroy();
});
});
@@ -432,7 +432,12 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
message = _t('<strong><b>Good job!</b> You went through all steps of this tour.</strong>');
}
const fadeout = this.tours[tour_name].fadeout;
core.bus.trigger('show-effect', {type: "rainbowman", message, fadeout});
core.bus.trigger('show-effect', {
type: "rainbowman",
message,
fadeout,
messageIsHtml: true,
});
}
this.tours[tour_name].current_step = 0;
local_storage.removeItem(get_step_key(tour_name));