[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:
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user