[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:
committed by
Simon Lejeune
co-authored by
pga-odoo
parent
1a33056557
commit
8bf1486da5
@@ -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',
|
||||
|
||||
@@ -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)])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user