[FIX] mrp: convert the Google Slides viewer in Owl

closes odoo/odoo#102398

Task: 2991906
X-original-commit: ba593c742c62db9cf9b310eaf5e104802821dad3
Related: odoo/enterprise#32383
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
William Henrotin
2022-10-06 18:01:09 +02:00
parent 9dc5f5f60f
commit 8d30502e1b
4 changed files with 68 additions and 205 deletions
-128
View File
@@ -1,128 +0,0 @@
/** @odoo-module **/
import fields from 'web.basic_fields';
import field_registry from 'web.field_registry';
var FieldEmbedURLViewer = fields.FieldChar.extend({
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* @override
*/
init: function () {
this._super.apply(this, arguments);
this.page = 1;
this.srcDirty = false;
},
/**
* force to set 'src' for embed iframe viewer when its value has changed
*
* @override
*
*/
reset: function () {
this._super.apply(this, arguments);
this._updateIframePreview();
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Initializes and returns an iframe for the viewer
*
* @private
* @returns {jQueryElement}
*/
_prepareIframe: function () {
return $('<iframe>', {
class: 'o_embed_iframe d-none',
allowfullscreen: true,
});
},
/**
* @override
* @private
*/
_renderEdit: function () {
if (!this.$('iframe.o_embed_iframe').length) {
this.$input = this.$el;
this.setElement(this.$el.wrap('<div class="o_embed_url_viewer o_field_widget w-100"/>').parent());
this.$el.append(this._prepareIframe());
}
this._prepareInput(this.$input);
// Do not set iframe src if widget is invisible
if (!this.record.evalModifiers(this.attrs.modifiers).invisible) {
this._updateIframePreview();
} else {
this.srcDirty = true;
}
},
/**
* @override
* @private
*/
_renderReadonly: function () {
if (!this.$('iframe.o_embed_iframe').length) {
this.$el.addClass('o_embed_url_viewer w-100');
this.$el.append(this._prepareIframe());
}
this._updateIframePreview();
},
/**
* Set the associated src for embed iframe viewer
*
* @private
* @returns {string} source of the google slide
*/
_getEmbedSrc: function () {
var src = false;
if (this.value) {
// check given google slide url is valid or not
var googleRegExp = /(^https:\/\/docs.google.com).*(\/d\/e\/|\/d\/)([A-Za-z0-9-_]+)/;
var google = this.value.match(googleRegExp);
if (google && google[3]) {
src = 'https://docs.google.com/presentation' + google[2] + google[3] + '/preview?slide=' + this.page;
}
}
return src || this.value;
},
/**
* update iframe attrs
*
* @private
*/
_updateIframePreview: function () {
var $iframe = this.$('iframe.o_embed_iframe');
var src = this._getEmbedSrc();
$iframe.addClass('w-100 border-0').toggleClass('d-none', !src);
if (src) {
$iframe.attr('src', src);
} else {
$iframe.removeAttr('src');
}
},
/**
* Listen to modifiers updates to and only render iframe when it is necessary
*
* @override
*/
updateModifiersValue: function () {
this._super.apply(this, arguments);
if (!this.attrs.modifiersValue.invisible && this.srcDirty) {
this._updateIframePreview();
this.srcDirty = false;
}
},
});
field_registry.add('embed_viewer', FieldEmbedURLViewer);
export default FieldEmbedURLViewer;
@@ -0,0 +1,53 @@
/** @odoo-module **/
import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { CharField } from "@web/views/fields/char/char_field";
const { useState } = owl;
export class SlidesViewer extends CharField {
setup() {
super.setup();
this.notification = useService("notification");
this.page = 1 || this.props.page;
this.state = useState({
isValid: true,
});
}
get fileName() {
return this.state.fileName || this.props.value || "";
}
get url() {
var src = false;
if (this.props.value) {
// check given google slide url is valid or not
var googleRegExp = /(^https:\/\/docs.google.com).*(\/d\/e\/|\/d\/)([A-Za-z0-9-_]+)/;
var google = this.props.value.match(googleRegExp);
if (google && google[3]) {
src =
"https://docs.google.com/presentation" +
google[2] +
google[3] +
"/preview?slide=" +
this.page;
}
}
return src || this.props.value;
}
onLoadFailed() {
this.state.isValid = false;
this.notification.add(this.env._t("Could not display the selected spreadsheet"), {
type: "danger",
});
}
}
SlidesViewer.template = "mrp.SlidesViewer";
SlidesViewer.displayName = _lt("Google Slides Viewer");
registry.category("fields").add("embed_viewer", SlidesViewer);
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mrp.SlidesViewer" t-inherit="web.CharField">
<xpath expr="//input" position="after">
<iframe class="o_embed_iframe w-100"
alt="Slides viewer"
t-att-src="url"
t-att-name="props.name"
t-on-error="onLoadFailed"
/>
</xpath>
</t>
</templates>
-77
View File
@@ -1,77 +0,0 @@
/** @odoo-module **/
import FormView from 'web.FormView';
import testUtils from "web.test_utils";
var createView = testUtils.createView;
QUnit.module('mrp', {
beforeEach: function () {
this.data = {
partner: {
fields: {
state: {
string: "State",
type: "selection",
selection: [['waiting', 'Waiting'], ['chilling', 'Chilling']],
},
duration: {string: "Duration", type: "float"},
},
records: [{
id: 1,
state: 'waiting',
duration: 6000,
}],
onchanges: {},
},
};
},
}, function () {
QUnit.test("embed_viewer rendering in form view", async function (assert) {
assert.expect(8);
var data = {
foo: {
fields: { char_url: { string: "URL", type: "char" } },
records: [{ id: 1 }]
},
};
var form = await createView({
View: FormView,
model: 'foo',
data: data,
arch:
'<form>' +
'<field name="char_url" widget="embed_viewer"/>' +
'</form>',
res_id: 1,
mockRPC: function (route) {
if (route === ('http://example.com')) {
return Promise.resolve();
}
return this._super.apply(this, arguments);
}
});
assert.isNotVisible(form.$('iframe.o_embed_iframe'), "there should be an invisible iframe readonly mode");
assert.strictEqual(_.has(form.$('iframe.o_embed_iframe')[0].attributes, "src"), false,
"src attribute is not set if there are no values");
await testUtils.form.clickEdit(form);
assert.isNotVisible(form.$('iframe.o_embed_iframe'), "there should be an invisible iframe in edit mode");
await testUtils.fields.editAndTrigger(form.$('.o_field_char'), 'http://example.com', ['input', 'change', 'focusout']);
assert.strictEqual(form.$('iframe.o_embed_iframe').attr('data-src'), 'http://example.com',
"src should updated on the iframe");
assert.isVisible(form.$('iframe.o_embed_iframe'), "there should be a visible iframe in edit mode");
await testUtils.form.clickSave(form);
assert.isVisible(form.$('iframe.o_embed_iframe'), "there should be a visible iframe in readonly mode");
assert.strictEqual(form.$('iframe.o_embed_iframe').attr('data-src'), 'http://example.com',
"should have updated src in readonly mode");
// In readonly mode, we are not displaying the URL, only iframe will be there.
assert.strictEqual(form.$('.iframe.o_embed_iframe').siblings().length, 0,
"there shouldn't be any siblings of iframe in readonly mode");
form.destroy();
});
});