diff options
| author | jpr-odoo <jpr@openerp.com> | 2019-02-19 06:41:37 +0000 |
|---|---|---|
| committer | Simon Lejeune <sle@openerp.com> | 2019-08-01 13:34:58 +0000 |
| commit | 8bf1486da56d3afe459eb97e5e2f100b63c54b90 (patch) | |
| tree | b25f78378ebd7d7c5ec164692e3fc0c47634158d | |
| parent | 1a33056557be7b5696854d3056ea79204f36eae4 (diff) | |
[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>
| -rw-r--r-- | addons/mrp/models/mrp_routing.py | 8 | ||||
| -rw-r--r-- | addons/mrp/models/mrp_workorder.py | 4 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp.js | 126 | ||||
| -rw-r--r-- | addons/mrp/static/src/scss/mrp_fields.scss | 8 | ||||
| -rw-r--r-- | addons/mrp/static/tests/mrp_tests.js | 47 | ||||
| -rw-r--r-- | addons/mrp/views/mrp_routing_views.xml | 6 | ||||
| -rw-r--r-- | addons/mrp/views/mrp_templates.xml | 1 | ||||
| -rw-r--r-- | addons/mrp/views/mrp_workorder_views.xml | 6 |
8 files changed, 201 insertions, 5 deletions
diff --git a/addons/mrp/models/mrp_routing.py b/addons/mrp/models/mrp_routing.py index f697df1cb3d..85f60bbb82b 100644 --- a/addons/mrp/models/mrp_routing.py +++ b/addons/mrp/models/mrp_routing.py @@ -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', diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 667ccc32fa5..58903a3aec5 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -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)]) diff --git a/addons/mrp/static/src/js/mrp.js b/addons/mrp/static/src/js/mrp.js index 8843d9ab3cd..22abd2b0d91 100644 --- a/addons/mrp/static/src/js/mrp.js +++ b/addons/mrp/static/src/js/mrp.js @@ -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; }); diff --git a/addons/mrp/static/src/scss/mrp_fields.scss b/addons/mrp/static/src/scss/mrp_fields.scss new file mode 100644 index 00000000000..606e32f4d94 --- /dev/null +++ b/addons/mrp/static/src/scss/mrp_fields.scss @@ -0,0 +1,8 @@ +.o_field_widget.o_embed_url_viewer{ + width: 100% !important; + iframe { + width: 100%; + height: 30rem; + border: none; + } +}
\ No newline at end of file diff --git a/addons/mrp/static/tests/mrp_tests.js b/addons/mrp/static/tests/mrp_tests.js index c8a38be42c3..31d85ee0ff8 100644 --- a/addons/mrp/static/tests/mrp_tests.js +++ b/addons/mrp/static/tests/mrp_tests.js @@ -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(); + }); }); }); diff --git a/addons/mrp/views/mrp_routing_views.xml b/addons/mrp/views/mrp_routing_views.xml index 44be561285b..a9f3fdfcefe 100644 --- a/addons/mrp/views/mrp_routing_views.xml +++ b/addons/mrp/views/mrp_routing_views.xml @@ -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> diff --git a/addons/mrp/views/mrp_templates.xml b/addons/mrp/views/mrp_templates.xml index f51f0427e19..59604b0183c 100644 --- a/addons/mrp/views/mrp_templates.xml +++ b/addons/mrp/views/mrp_templates.xml @@ -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> diff --git a/addons/mrp/views/mrp_workorder_views.xml b/addons/mrp/views/mrp_workorder_views.xml index 64b2bdf2ea0..21f08de5eda 100644 --- a/addons/mrp/views/mrp_workorder_views.xml +++ b/addons/mrp/views/mrp_workorder_views.xml @@ -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> |
