diff options
| author | Ankita Raval <anr@odoo.com> | 2019-12-10 13:15:08 +0000 |
|---|---|---|
| committer | svs-odoo <svs@odoo.com> | 2020-03-04 10:12:46 +0000 |
| commit | 65513ef3f92d82806d03bd5fe55c7f9af4f1484d (patch) | |
| tree | bb8b71b6d1c19713abd5e81729459672ae0f2131 | |
| parent | a56a4f8aeeebf946745b09b0b1a649293b806546 (diff) | |
[IMP] mrp: mrp_document
Purpose:
Modernizes and facilitates files upload in manufacturing app.
In this Commit:
- Show the image in Kanban.
- Allow to access a preview of the file when clicking on it in the
Kanban view.
- Add a 'Edit', 'Delete' and 'Download' in kanban card dropdown menu.
- Add Upload button in control panel to upload document which will
create new record of `mrp.document` and also add a testcase for it.
task-1960733
closes odoo/odoo#42168
Related: odoo/enterprise#8977
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
| -rw-r--r-- | addons/mrp/__init__.py | 1 | ||||
| -rw-r--r-- | addons/mrp/__manifest__.py | 2 | ||||
| -rw-r--r-- | addons/mrp/controller/__init__.py | 4 | ||||
| -rw-r--r-- | addons/mrp/controller/main.py | 36 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_document_kanban_view.js | 20 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_documents_controller_mixin.js | 126 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_documents_document_viewer.js | 19 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_documents_kanban_controller.js | 37 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_documents_kanban_record.js | 50 | ||||
| -rw-r--r-- | addons/mrp/static/src/js/mrp_documents_kanban_renderer.js | 27 | ||||
| -rw-r--r-- | addons/mrp/static/src/scss/mrp_document_kanban_view.scss | 3 | ||||
| -rw-r--r-- | addons/mrp/static/src/xml/mrp_document_template.xml | 10 | ||||
| -rw-r--r-- | addons/mrp/static/tests/mrp_document_kanban_tests.js | 172 | ||||
| -rw-r--r-- | addons/mrp/views/ir_attachment_view.xml | 53 | ||||
| -rw-r--r-- | addons/mrp/views/mrp_templates.xml | 8 |
15 files changed, 556 insertions, 12 deletions
diff --git a/addons/mrp/__init__.py b/addons/mrp/__init__.py index 7a2198e463d..616729a420d 100644 --- a/addons/mrp/__init__.py +++ b/addons/mrp/__init__.py @@ -4,6 +4,7 @@ from . import models from . import wizard from . import report +from . import controller from odoo import api, SUPERUSER_ID diff --git a/addons/mrp/__manifest__.py b/addons/mrp/__manifest__.py index 09f62e9d37c..f664c4883e2 100644 --- a/addons/mrp/__manifest__.py +++ b/addons/mrp/__manifest__.py @@ -40,7 +40,7 @@ 'report/report_stock_rule.xml', 'report/mrp_zebra_production_templates.xml', ], - 'qweb': ['static/src/xml/mrp.xml'], + 'qweb': ['static/src/xml/*.xml'], 'demo': [ 'data/mrp_demo.xml', ], diff --git a/addons/mrp/controller/__init__.py b/addons/mrp/controller/__init__.py new file mode 100644 index 00000000000..5d4b25db9c0 --- /dev/null +++ b/addons/mrp/controller/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import main diff --git a/addons/mrp/controller/main.py b/addons/mrp/controller/main.py new file mode 100644 index 00000000000..0c8b40f0621 --- /dev/null +++ b/addons/mrp/controller/main.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import base64 +import json +import logging + +from odoo import http +from odoo.http import request +from odoo.tools.mimetypes import neuter_mimetype +from odoo.tools.translate import _ + +logger = logging.getLogger(__name__) + + +class MrpDocumentRoute(http.Controller): + + @http.route('/mrp/upload_attachment', type='http', methods=['POST'], auth="user") + def upload_document(self, ufile, **kwargs): + files = request.httprequest.files.getlist('ufile') + result = {'success': _("All files uploaded")} + for ufile in files: + try: + mimetype = neuter_mimetype(ufile.content_type, http.request.env.user) + request.env['mrp.document'].create({ + 'name': ufile.filename, + 'res_model': kwargs.get('res_model'), + 'res_id': kwargs.get('res_id'), + 'mimetype': mimetype, + 'datas': base64.encodebytes(ufile.read()), + }) + except Exception as e: + logger.exception("Fail to upload document %s" % ufile.filename) + result = {'error': str(e)} + + return json.dumps(result) diff --git a/addons/mrp/static/src/js/mrp_document_kanban_view.js b/addons/mrp/static/src/js/mrp_document_kanban_view.js new file mode 100644 index 00000000000..e4e936637b1 --- /dev/null +++ b/addons/mrp/static/src/js/mrp_document_kanban_view.js @@ -0,0 +1,20 @@ +odoo.define('mrp.MrpDocumentsKanbanView', function (require) { +"use strict"; + +const KanbanView = require('web.KanbanView'); +const MrpDocumentsKanbanController = require('mrp.MrpDocumentsKanbanController'); +const MrpDocumentsKanbanRenderer = require('mrp.MrpDocumentsKanbanRenderer'); +const viewRegistry = require('web.view_registry'); + +const MrpDocumentsKanbanView = KanbanView.extend({ + config: Object.assign({}, KanbanView.prototype.config, { + Controller: MrpDocumentsKanbanController, + Renderer: MrpDocumentsKanbanRenderer, + }), +}); + +viewRegistry.add('mrp_documents_kanban', MrpDocumentsKanbanView); + +return MrpDocumentsKanbanView; + +}); diff --git a/addons/mrp/static/src/js/mrp_documents_controller_mixin.js b/addons/mrp/static/src/js/mrp_documents_controller_mixin.js new file mode 100644 index 00000000000..9bcaf3d6cf3 --- /dev/null +++ b/addons/mrp/static/src/js/mrp_documents_controller_mixin.js @@ -0,0 +1,126 @@ +odoo.define('mrp.controllerMixin', function (require) { +'use strict'; + +const { _t, qweb } = require('web.core'); +const fileUploadMixin = require('web.fileUploadMixin'); +const DocumentViewer = require('mrp.MrpDocumentViewer'); + +const MrpDocumentsControllerMixin = Object.assign({}, fileUploadMixin, { + events: { + 'click .o_mrp_documents_kanban_upload': '_onClickMrpDocumentsUpload', + }, + custom_events: Object.assign({}, fileUploadMixin.custom_events, { + kanban_image_clicked: '_onKanbanPreview', + upload_file: '_onUploadFile', + }), + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Called right after the reload of the view. + */ + async reload() { + await this._renderFileUploads(); + }, + + /** + * @override + * @param {jQueryElement} $node + */ + renderButtons($node) { + this.$buttons = $(qweb.render('MrpDocumentsKanbanView.buttons')); + this.$buttons.appendTo($node); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _getFileUploadRoute() { + return '/mrp/upload_attachment'; + }, + + /** + * @override + * @param {integer} param0.recordId + */ + _makeFileUploadFormDataKeys() { + const context = this.model.get(this.handle, { raw: true }).getContext(); + return { + res_id: context.default_res_id, + res_model: context.default_res_model, + }; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + */ + _onClickMrpDocumentsUpload() { + const $uploadInput = $('<input>', { + type: 'file', + name: 'files[]', + multiple: 'multiple' + }); + $uploadInput.on('change', async ev => { + await this._uploadFiles(ev.target.files); + $uploadInput.remove(); + }); + $uploadInput.click(); + }, + + /** + * Handles custom event to display the document viewer. + * + * @private + * @param {OdooEvent} ev + * @param {integer} ev.data.recordID + * @param {Array<Object>} ev.data.recordList + */ + _onKanbanPreview(ev) { + ev.stopPropagation(); + const documents = ev.data.recordList; + const documentID = ev.data.recordID; + const documentViewer = new DocumentViewer(this, documents, documentID); + documentViewer.appendTo(this.$('.o_mrp_documents_kanban_view')); + }, + + /** + * Specially created to call `_uploadFiles` method from tests. + * + * @private + * @param {OdooEvent} ev + */ + async _onUploadFile(ev) { + await this._uploadFiles(ev.data.files); + }, + + /** + * @override + * @param {Object} param0 + * @param {XMLHttpRequest} param0.xhr + */ + _onUploadLoad({ xhr }) { + const result = xhr.status === 200 + ? JSON.parse(xhr.response) + : { + error: _.str.sprintf(_t("status code: %s </br> message: %s"), xhr.status, xhr.response) + }; + if (result.error) { + this.do_notify(_t("Error"), result.error, true); + } + fileUploadMixin._onUploadLoad.apply(this, arguments); + }, +}); + +return MrpDocumentsControllerMixin; + +}); diff --git a/addons/mrp/static/src/js/mrp_documents_document_viewer.js b/addons/mrp/static/src/js/mrp_documents_document_viewer.js new file mode 100644 index 00000000000..c0d7f3e8c8d --- /dev/null +++ b/addons/mrp/static/src/js/mrp_documents_document_viewer.js @@ -0,0 +1,19 @@ +odoo.define('mrp.MrpDocumentViewer', function (require) { +"use strict"; + +const DocumentViewer = require('mail.DocumentViewer'); + +/** + * This file defines the DocumentViewer for the MRP Documents Kanban view. + */ +const MrpDocumentsDocumentViewer = DocumentViewer.extend({ + init(parent, attachments, activeAttachmentID) { + this._super(...arguments); + this.modelName = 'mrp.document'; + }, +}); + +return MrpDocumentsDocumentViewer; + +}); + diff --git a/addons/mrp/static/src/js/mrp_documents_kanban_controller.js b/addons/mrp/static/src/js/mrp_documents_kanban_controller.js new file mode 100644 index 00000000000..9a123dfb970 --- /dev/null +++ b/addons/mrp/static/src/js/mrp_documents_kanban_controller.js @@ -0,0 +1,37 @@ +odoo.define('mrp.MrpDocumentsKanbanController', function (require) { +"use strict"; + +/** + * This file defines the Controller for the MRP Documents Kanban view, which is an + * override of the KanbanController. + */ + +const MrpDocumentsControllerMixin = require('mrp.controllerMixin'); + +const KanbanController = require('web.KanbanController'); + +const MrpDocumentsKanbanController = KanbanController.extend(MrpDocumentsControllerMixin, { + events: Object.assign({}, KanbanController.prototype.events, MrpDocumentsControllerMixin.events), + custom_events: Object.assign({}, KanbanController.prototype.custom_events, MrpDocumentsControllerMixin.custom_events), + + /** + * @override + */ + init() { + this._super(...arguments); + MrpDocumentsControllerMixin.init.apply(this, arguments); + }, + /** + * Override to update the records selection. + * + * @override + */ + async reload() { + await this._super(...arguments); + await MrpDocumentsControllerMixin.reload.apply(this, arguments); + }, +}); + +return MrpDocumentsKanbanController; + +}); diff --git a/addons/mrp/static/src/js/mrp_documents_kanban_record.js b/addons/mrp/static/src/js/mrp_documents_kanban_record.js new file mode 100644 index 00000000000..445588341ee --- /dev/null +++ b/addons/mrp/static/src/js/mrp_documents_kanban_record.js @@ -0,0 +1,50 @@ +odoo.define('mrp.MrpDocumentsKanbanRecord', function (require) { +"use strict"; + +/** + * This file defines the KanbanRecord for the MRP Documents Kanban view. + */ + +const KanbanRecord = require('web.KanbanRecord'); + +const MrpDocumentsKanbanRecord = KanbanRecord.extend({ + events: Object.assign({}, KanbanRecord.prototype.events, { + 'click .o_mrp_download': '_onDownload', + 'click .o_kanban_previewer': '_onImageClicked', + }), + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Handles the click on the download link to save the attachment locally. + * + * @private + * @param {MouseEvent} ev + */ + _onDownload(ev) { + ev.preventDefault(); + window.location = `/web/content/${this.modelName}/${this.id}/datas?download=true`; + }, + + /** + * Handles the click on the preview image. Triggers up `_onKanbanPreview` to + * display `DocumentViewer`. + * + * @private + * @param {MouseEvent} ev + */ + _onImageClicked(ev) { + ev.preventDefault(); + ev.stopPropagation(); + this.trigger_up('kanban_image_clicked', { + recordList: [this.recordData], + recordID: this.recordData.id + }); + }, +}); + +return MrpDocumentsKanbanRecord; + +}); diff --git a/addons/mrp/static/src/js/mrp_documents_kanban_renderer.js b/addons/mrp/static/src/js/mrp_documents_kanban_renderer.js new file mode 100644 index 00000000000..79ffffe7aee --- /dev/null +++ b/addons/mrp/static/src/js/mrp_documents_kanban_renderer.js @@ -0,0 +1,27 @@ +odoo.define('mrp.MrpDocumentsKanbanRenderer', function (require) { +"use strict"; + +/** + * This file defines the Renderer for the MRP Documents Kanban view, which is an + * override of the KanbanRenderer. + */ + +const KanbanRenderer = require('web.KanbanRenderer'); +const MrpDocumentsKanbanRecord = require('mrp.MrpDocumentsKanbanRecord'); + +const MrpDocumentsKanbanRenderer = KanbanRenderer.extend({ + config: Object.assign({}, KanbanRenderer.prototype.config, { + KanbanRecord: MrpDocumentsKanbanRecord, + }), + /** + * @override + */ + async start() { + this.$el.addClass('o_mrp_documents_kanban_view'); + await this._super(...arguments); + }, +}); + +return MrpDocumentsKanbanRenderer; + +}); diff --git a/addons/mrp/static/src/scss/mrp_document_kanban_view.scss b/addons/mrp/static/src/scss/mrp_document_kanban_view.scss new file mode 100644 index 00000000000..536ef77d028 --- /dev/null +++ b/addons/mrp/static/src/scss/mrp_document_kanban_view.scss @@ -0,0 +1,3 @@ +.o_kanban_previewer:hover { + cursor: zoom-in; +} diff --git a/addons/mrp/static/src/xml/mrp_document_template.xml b/addons/mrp/static/src/xml/mrp_document_template.xml new file mode 100644 index 00000000000..23ea08d860e --- /dev/null +++ b/addons/mrp/static/src/xml/mrp_document_template.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates xml:space="preserve"> + +<div t-name="MrpDocumentsKanbanView.buttons"> + <button type="button" t-attf-class="btn btn-primary o_mrp_documents_kanban_upload"> + Upload + </button> +</div> +</templates> + diff --git a/addons/mrp/static/tests/mrp_document_kanban_tests.js b/addons/mrp/static/tests/mrp_document_kanban_tests.js new file mode 100644 index 00000000000..366bb1bd1da --- /dev/null +++ b/addons/mrp/static/tests/mrp_document_kanban_tests.js @@ -0,0 +1,172 @@ +odoo.define('mrp.document_kanban_tests', function (require) { +"use strict"; + +const MrpDocumentsKanbanView = require('mrp.MrpDocumentsKanbanView'); +const MrpDocumentsKanbanController = require('mrp.MrpDocumentsKanbanController'); +const testUtils = require('web.test_utils'); + +const createView = testUtils.createView; + +QUnit.module('Views', {}, function () { + +QUnit.module('MrpDocumentsKanbanView', { + beforeEach: function () { + this.ORIGINAL_CREATE_XHR = MrpDocumentsKanbanController.prototype._createXHR; + this.patchDocumentXHR = (mockedXHRs, customSend) => { + MrpDocumentsKanbanController.prototype._createXhr = () => { + const xhr = { + upload: new window.EventTarget(), + open() { }, + send(data) { customSend && customSend(data); }, + }; + mockedXHRs.push(xhr); + return xhr; + }; + }; + this.data = { + 'mrp.document': { + fields: { + name: {string: "Name", type: 'char', default: ' '}, + priority: {string: 'priority', type: 'selection', + selection: [['0', 'Normal'], ['1', 'Low'], ['2', 'High'], ['3', 'Very High']]}, + }, + records: [ + {id: 1, name: 'test1', priority: 2}, + {id: 4, name: 'test2', priority: 1}, + {id: 3, name: 'test3', priority: 3}, + ], + }, + }; + }, + afterEach() { + MrpDocumentsKanbanController.prototype._createXHR = this.ORIGINAL_CREATE_XHR; + }, +}, function () { + QUnit.test('MRP documents kanban basic rendering', async function (assert) { + assert.expect(6); + + const kanban = await createView({ + View: MrpDocumentsKanbanView, + model: 'mrp.document', + data: this.data, + arch: '<kanban><templates><t t-name="kanban-box">' + + '<div>' + + '<field name="name"/>' + + '</div>' + + '</t></templates></kanban>', + }); + + assert.ok(kanban, "kanban is created"); + assert.ok(kanban.$buttons.find('.o_mrp_documents_kanban_upload'), + "should have upload button in kanban buttons"); + assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3, + "should have 3 records in the renderer"); + // check view layout + assert.hasClass(kanban.$('.o_kanban_view'), 'o_mrp_documents_kanban_view', + "should have classname 'o_mrp_documents_kanban_view'"); + // check control panel buttons + assert.containsN(kanban, '.o_cp_buttons .btn-primary', 1, + "should have only 1 primary button i.e. Upload button"); + assert.strictEqual(kanban.$('.o_cp_buttons .btn-primary:first').text().trim(), 'Upload', + "should have a primary 'Upload' button"); + + kanban.destroy(); + }); + + QUnit.test('mrp: upload multiple files', async function (assert) { + assert.expect(4); + + const file1 = await testUtils.file.createFile({ + name: 'text1.txt', + content: 'hello, world', + contentType: 'text/plain', + }); + const file2 = await testUtils.file.createFile({ + name: 'text2.txt', + content: 'hello, world', + contentType: 'text/plain', + }); + const file3 = await testUtils.file.createFile({ + name: 'text3.txt', + content: 'hello, world', + contentType: 'text/plain', + }); + + const mockedXHRs = []; + this.patchDocumentXHR(mockedXHRs, data => assert.step('xhrSend')); + + const kanban = await createView({ + View: MrpDocumentsKanbanView, + model: 'mrp.document', + data: this.data, + arch: '<kanban><templates><t t-name="kanban-box">' + + '<div>' + + '<field name="name"/>' + + '</div>' + + '</t></templates></kanban>', + }); + + kanban.trigger_up('upload_file', {files: [file1]}); + await testUtils.nextTick(); + assert.verifySteps(['xhrSend']); + + kanban.trigger_up('upload_file', {files: [file2, file3]}); + await testUtils.nextTick(); + assert.verifySteps(['xhrSend']); + + kanban.destroy(); + }); + + QUnit.test('mrp: upload progress bars', async function (assert) { + assert.expect(4); + + const file1 = await testUtils.file.createFile({ + name: 'text1.txt', + content: 'hello, world', + contentType: 'text/plain', + }); + + const mockedXHRs = []; + this.patchDocumentXHR(mockedXHRs, data => assert.step('xhrSend')); + + const kanban = await createView({ + View: MrpDocumentsKanbanView, + model: 'mrp.document', + data: this.data, + arch: '<kanban><templates><t t-name="kanban-box">' + + '<div>' + + '<field name="name"/>' + + '</div>' + + '</t></templates></kanban>', + }); + + kanban.trigger_up('upload_file', {files: [file1]}); + await testUtils.nextTick(); + assert.verifySteps(['xhrSend']); + + const progressEvent = new Event('progress', { bubbles: true }); + progressEvent.loaded = 250000000; + progressEvent.total = 500000000; + progressEvent.lengthComputable = true; + mockedXHRs[0].upload.dispatchEvent(progressEvent); + assert.strictEqual( + kanban.$('.o_file_upload_progress_text_left').text(), + "Uploading... (50%)", + "the current upload progress should be at 50%" + ); + + progressEvent.loaded = 350000000; + mockedXHRs[0].upload.dispatchEvent(progressEvent); + assert.strictEqual( + kanban.$('.o_file_upload_progress_text_right').text(), + "(350/500Mb)", + "the current upload progress should be at (350/500Mb)" + ); + + kanban.destroy(); + }); +}); + +}); + +}); diff --git a/addons/mrp/views/ir_attachment_view.xml b/addons/mrp/views/ir_attachment_view.xml index b187ebb8196..6e144e98465 100644 --- a/addons/mrp/views/ir_attachment_view.xml +++ b/addons/mrp/views/ir_attachment_view.xml @@ -5,7 +5,7 @@ <field name="name">mrp.document kanban.mrp</field> <field name="model">mrp.document</field> <field name="arch" type="xml"> - <kanban> + <kanban js_class="mrp_documents_kanban" create="false"> <field name="ir_attachment_id"/> <field name="mimetype"/> <field name="type"/> @@ -16,11 +16,13 @@ <t t-name="kanban-box"> <div class="oe_kanban_global_area o_kanban_attachment oe_kanban_global_click"> <div class="o_kanban_image"> - <div class="o_kanban_image_wrapper"> + <t t-set="binaryPreviewable" + t-value="new RegExp('(image|video|application/pdf|text)').test(record.mimetype.value) && record.type.raw_value === 'binary'"/> + <div t-attf-class="o_kanban_image_wrapper #{(webimage or binaryPreviewable) ? 'o_kanban_previewer' : ''}"> <t t-set="webimage" t-value="new RegExp('image.*(gif|jpeg|jpg|png)').test(record.mimetype.value)"/> <div t-if="record.type.raw_value == 'url'" class="o_url_image fa fa-link fa-3x text-muted" aria-label="Image is a link"/> <img t-elif="webimage" t-attf-src="/web/image/#{record.ir_attachment_id.raw_value}" width="100" height="100" alt="Document" class="o_attachment_image"/> - <div t-else="!webimage" class="o_image o_image_thumbnail" t-att-data-mimetype="record.mimetype.value"/> + <div t-else="" class="o_image o_image_thumbnail" t-att-data-mimetype="record.mimetype.value"/> </div> </div> <div class="o_kanban_details"> @@ -29,7 +31,6 @@ <field name="name" class="o_text_overflow"/> </div> <div class="o_kanban_record_body"> - <field name="name" attrs="{'invisible':[('type','=','url')]}"/> <field name="url" widget="url" attrs="{'invisible':[('type','=','binary')]}"/> </div> <div class="o_kanban_record_bottom"> @@ -40,6 +41,16 @@ <img t-att-src="kanban_image('res.users', 'image_128', record.create_uid.raw_value)" t-att-data-member_id="record.create_uid.raw_value" t-att-alt="record.create_uid.raw_value" class="oe_kanban_avatar"/> </div> </div> + <div class="o_dropdown_kanban dropdown" tabindex="-1"> + <a class="dropdown-toggle o-no-caret btn" data-toggle="dropdown" href="#" role="button" aria-label="Dropdown menu" title="Dropdown menu"> + <span class="fa fa-ellipsis-v"/> + </a> + <div class="dropdown-menu" role="menu" aria-labelledby="dLabel"> + <a t-if="widget.editable" type="edit" class="dropdown-item">Edit</a> + <a t-if="widget.deletable" type="delete" class="dropdown-item">Delete</a> + <a class="dropdown-item o_mrp_download">Download</a> + </div> + </div> </div> </div> </div> @@ -49,16 +60,36 @@ </field> </record> - <record id="view_document_form" model="ir.ui.view"> + <record id="view_mrp_document_form" model="ir.ui.view"> <field name="name">mrp.document.form</field> <field name="model">mrp.document</field> - <field name="inherit_id" ref="base.view_attachment_form"/> - <field name="mode">primary</field> <field name="arch" type="xml"> - <xpath expr="//field[@name='mimetype']" position="after"> - <field name="priority" widget="priority"/> - <field name="company_id" groups="base.group_multi_company"/> - </xpath> + <form string="Attachments"> + <sheet> + <label for="name" class="oe_edit_only"/> + <h1> + <field name="name"/> + </h1> + <group> + <group> + <field name="type"/> + <field name="datas" filename="name" attrs="{'invisible':[('type','=','url')]}"/> + <field name="url" widget="url" attrs="{'invisible':[('type','=','binary')]}"/> + </group> + <group string="Attached To" groups="base.group_no_one"> + <field name="res_name"/> + <field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/> + </group> + <group string="History" groups="base.group_no_one" attrs="{'invisible':[('create_date','=',False)]}"> + <label for="create_uid" string="Creation"/> + <div name="creation_div"> + <field name="create_uid" readonly="1" class="oe_inline"/> on + <field name="create_date" readonly="1" class="oe_inline"/> + </div> + </group> + </group> + </sheet> + </form> </field> </record> </odoo> diff --git a/addons/mrp/views/mrp_templates.xml b/addons/mrp/views/mrp_templates.xml index 9f2b80215ce..24b891d49bd 100644 --- a/addons/mrp/views/mrp_templates.xml +++ b/addons/mrp/views/mrp_templates.xml @@ -6,6 +6,12 @@ <script type="text/javascript" src="/mrp/static/src/js/mrp.js"></script> <script type="text/javascript" src="/mrp/static/src/js/mrp_bom_report.js"></script> <script type="text/javascript" src="/mrp/static/src/js/mrp_workorder_popover.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_documents_controller_mixin.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_documents_document_viewer.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_documents_kanban_controller.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_documents_kanban_record.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_documents_kanban_renderer.js"></script> + <script type="text/javascript" src="/mrp/static/src/js/mrp_document_kanban_view.js"></script> </xpath> </template> @@ -14,12 +20,14 @@ <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" /> <link rel="stylesheet" type="text/scss" href="/mrp/static/src/scss/mrp_gantt.scss" /> + <link rel="stylesheet" type="text/scss" href="/mrp/static/src/scss/mrp_document_kanban_view.scss" /> </xpath> </template> <template id="qunit_suite" inherit_id="web.qunit_suite"> <xpath expr="//script[last()]" position="after"> <script type="text/javascript" src="/mrp/static/tests/mrp_tests.js"/> + <script type="text/javascript" src="/mrp/static/tests/mrp_document_kanban_tests.js"/> </xpath> </template> |
