[IMP] mrp: added support embedded google slide on work center

This commit adds new `embed_viewer` widget which will be used display URLs
via embedded iframes.  You can add any valid URL to display page via iframe,
although widget automatically converts raw google slide URL into embedded URL.

Task ID: 1909010

closes odoo/odoo#29404

Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>


Co-authored-by: pga-odoo <pga@odoo.com>
This commit is contained in:
jpr-odoo
2019-08-01 13:34:58 +00:00
committed by Simon Lejeune
co-authored by pga-odoo
parent 1a33056557
commit 8bf1486da5
8 changed files with 201 additions and 5 deletions
+7 -1
View File
@@ -50,7 +50,13 @@ class MrpRoutingWorkcenter(models.Model):
company_id = fields.Many2one(
'res.company', 'Company',
readonly=True, related='routing_id.company_id', store=True)
worksheet = fields.Binary('worksheet')
worksheet = fields.Binary('PDF', help="Upload your PDF file.")
worksheet_type = fields.Selection([
('pdf', 'PDF'), ('google_slide', 'Google Slide')],
string="Work Sheet", default="pdf",
help="Defines if you want to use a PDF or a Google Slide as work sheet."
)
worksheet_google_slide = fields.Char('Google Slide', help="Paste the url of your Google Slide. Make sure the access to the document is public.")
time_mode = fields.Selection([
('auto', 'Compute based on real time'),
('manual', 'Set duration manually')], string='Duration Computation',
+4
View File
@@ -88,6 +88,10 @@ class MrpWorkorder(models.Model):
'mrp.routing.workcenter', 'Operation') # Should be used differently as BoM can change in the meantime
worksheet = fields.Binary(
'Worksheet', related='operation_id.worksheet', readonly=True)
worksheet_type = fields.Selection(
'Worksheet Type', related='operation_id.worksheet_type', readonly=True)
worksheet_google_slide = fields.Char(
'Worksheet URL', related='operation_id.worksheet_google_slide', readonly=True)
move_raw_ids = fields.One2many(
'stock.move', 'workorder_id', 'Raw Moves',
domain=[('raw_material_production_id', '!=', False), ('production_id', '=', False)])
+125 -1
View File
@@ -3,6 +3,7 @@ odoo.define('mrp.mrp_state', function (require) {
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var fields = require('web.basic_fields');
var field_registry = require('web.field_registry');
var time = require('web.time');
@@ -125,8 +126,131 @@ var TimeCounter = AbstractField.extend({
},
});
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"/>').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');
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.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('bullet_state', SetBulletStatus)
.add('mrp_time_counter', TimeCounter);
.add('mrp_time_counter', TimeCounter)
.add('embed_viewer', FieldEmbedURLViewer);
return FieldEmbedURLViewer;
});
@@ -0,0 +1,8 @@
.o_field_widget.o_embed_url_viewer{
width: 100% !important;
iframe {
width: 100%;
height: 30rem;
border: none;
}
}
+47
View File
@@ -83,5 +83,52 @@ QUnit.module('mrp', {
form.destroy();
});
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('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();
});
});
});
+5 -1
View File
@@ -52,7 +52,11 @@
<field name="note"/>
</page>
<page string="Work Sheet">
<field name="worksheet" widget="pdf_viewer"/>
<group>
<field name="worksheet_type" widget="radio"/>
<field name="worksheet" widget="pdf_viewer" attrs="{'invisible': [('worksheet_type', '=', 'google_slide')]}"/>
<field name="worksheet_google_slide" placeholder="Google Slide Link" widget="embed_viewer" attrs="{'invisible': [('worksheet_type', '=', 'pdf')]}"/>
</group>
</page>
</notebook>
</sheet>
+1
View File
@@ -10,6 +10,7 @@
<template id="assets_common" name="mrp bom common assets" inherit_id="web.assets_common">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/mrp/static/src/scss/mrp_bom_report.scss" />
<link rel="stylesheet" type="text/scss" href="/mrp/static/src/scss/mrp_fields.scss" />
</xpath>
</template>
+4 -2
View File
@@ -138,8 +138,10 @@
</group>
</group>
<notebook>
<page string="Work Instruction" attrs="{'invisible': [('worksheet', '=', False)]}">
<field name="worksheet" widget="pdf_viewer"/>
<page string="Work Instruction" attrs="{'invisible': [('worksheet', '=', False),('worksheet_google_slide', '=', False)]}">
<field name="worksheet_type" invisible="1"/>
<field name="worksheet_google_slide" widget="embed_viewer" attrs="{'invisible': [('worksheet_type', '=', 'pdf')]}"/>
<field name="worksheet" widget="pdf_viewer" attrs="{'invisible': [('worksheet_type', '=', 'google_slide')]}"/>
</page>
<page string="Current Production">
<group>