From c1f33a7cdbe45c02110378121dc029f0f7b16f89 Mon Sep 17 00:00:00 2001 From: Foram Date: Wed, 2 Dec 2020 16:27:03 +0530 Subject: [PATCH] [WIP] Modified the code for attachment_preview. --- attachment_preview/__manifest__.py | 3 +- attachment_preview/models/ir_attachment.py | 15 +- .../static/src/js/attachment_preview.js | 462 +++++++++--------- .../static/src/js/viewerjs_tweaks.js | 1 + .../static/src/xml/attachment_preview.xml | 9 +- .../tests/test_attachment_preview.py | 5 +- 6 files changed, 248 insertions(+), 247 deletions(-) diff --git a/attachment_preview/__manifest__.py b/attachment_preview/__manifest__.py index b2610136..96761e74 100644 --- a/attachment_preview/__manifest__.py +++ b/attachment_preview/__manifest__.py @@ -3,8 +3,9 @@ { "name": "Preview attachments", - "version": "12.0.1.0.0", + "version": "14.0.1.0.0", "author": "Therp BV," "Onestein," "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/knowledge", "license": "AGPL-3", "summary": "Preview attachments supported by Viewer.js", "category": "Knowledge Management", diff --git a/attachment_preview/models/ir_attachment.py b/attachment_preview/models/ir_attachment.py index 425c357b..80e3fc8d 100644 --- a/attachment_preview/models/ir_attachment.py +++ b/attachment_preview/models/ir_attachment.py @@ -25,14 +25,16 @@ class IrAttachment(models.Model): # unnecessarily. if filename_field: for this in ( - self.env[model].with_context(bin_size=True).browse(ids_to_browse) + self.env[model].with_context( + bin_size=True).browse(ids_to_browse) ): if not this.id: result[this.id] = False continue extension = "" if this[filename_field]: - filename, extension = os.path.splitext(this[filename_field]) + filename, extension = os.path.splitext( + this[filename_field]) if this[binary_field] and extension: result[this.id] = extension _logger.debug( @@ -61,13 +63,16 @@ class IrAttachment(models.Model): ) else: mimetype = magic.from_buffer(this[binary_field], mime=True) - _logger.debug("Magic determined mimetype %s from buffer", mimetype) + _logger.debug( + "Magic determined mimetype %s from buffer", mimetype) except ImportError: (mimetype, encoding) = mimetypes.guess_type( "data:;base64," + this[binary_field], strict=False ) - _logger.debug("Mimetypes guessed type %s from buffer", mimetype) - extension = mimetypes.guess_extension(mimetype.split(";")[0], strict=False) + _logger.debug( + "Mimetypes guessed type %s from buffer", mimetype) + extension = mimetypes.guess_extension( + mimetype.split(";")[0], strict=False) result[this.id] = extension for _id in result: result[_id] = (result[_id] or "").lstrip(".").lower() diff --git a/attachment_preview/static/src/js/attachment_preview.js b/attachment_preview/static/src/js/attachment_preview.js index 64cb1b8b..87e563f1 100644 --- a/attachment_preview/static/src/js/attachment_preview.js +++ b/attachment_preview/static/src/js/attachment_preview.js @@ -2,26 +2,24 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function require ) { "use strict"; - const useStore = require("mail/static/src/component_hooks/use_store/use_store.js"); - const {Component} = owl; - const {useRef} = owl.hooks; const components = { Attachment: require("mail/static/src/components/attachment/attachment.js"), Chatter: require("mail/static/src/components/chatter/chatter.js"), - AttachmentBox: require("mail/static/src/components/attachment_box/attachment_box.js"), + ChatterContainer: require("mail/static/src/components/chatter_container/chatter_container.js"), }; const {patch} = require("web.utils"); var rpc = require("web.rpc"); var basic_fields = require("web.basic_fields"); var FormRenderer = require("web.FormRenderer"); var Widget = require("web.Widget"); + var core = require("web.core"); + var _t = core._t; const attachment = patch( components.Attachment, - "/attachment_preview/static/src/js/attachment_preview.js", + "mail/static/src/components/attachment/attachment.js", { - previewableAttachments: null, - events: _.extend({}, components.Attachment.prototype.events, { + events: _.extend({}, components.Chatter.prototype.events, { "click .o_attachment_preview": "_onPreviewAttachment", }), canPreview: function (extension) { @@ -79,99 +77,15 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function } }, - _openAttachmentBox() { - this.getPreviewableAttachments().done( - function (atts) { - this.previewableAttachments = atts; - this.updatePreviewButtons(atts); - this.attachmentPreviewWidget.setAttachments(atts); - }.bind(this) - ); - }, - - getPreviewableAttachments: function () { - var self = this; - var deferred = $.Deferred(); - - var $items = $(this); - var attachments = _.object( - $items.map(function () { - return parseInt($(this).attr("data-id"), 10); - }), - $items.map(function () { - return { - url: $(this).attr("data-url"), - extension: $(this).attr("data-extension"), - title: $(this).attr("data-original-title"), - }; - }) - ); - - rpc.query({ - model: "ir.attachment", - method: "get_attachment_extension", - args: [ - _.map(_.keys(attachments), function (id) { - return parseInt(id, 10); - }), - ], - }).then( - function (extensions) { - var reviewableAttachments = _.map( - _.keys( - _.pick(extensions, function (extension, id) { - return self.canPreview(extension); - }) - ), - function (id) { - return { - id: id, - url: attachments[id].url, - extension: extensions[id], - title: attachments[id].title, - previewUrl: self.getUrl( - id, - attachments[id].url, - extensions[id], - id + " - " + attachments[id].title - ), - }; - } - ); - deferred.resolve(reviewableAttachments); - }, - function () { - deferred.reject(); - } - ); - return deferred.promise(); - }, - - _update: function () { - var self = this; - self._openAttachmentBox(); - self.getPreviewableAttachments().done(function (atts) { - self.updatePreviewButtons(self.previewableAttachments); - self.previewableAttachments = atts; - self.attachmentPreviewWidget.setAttachments(atts); - }); - }, - - patched() { - this._update(); - }, _onPreviewAttachment(event) { event.preventDefault(); var self = this, $target = $(event.currentTarget), split_screen = $target.attr("data-target") !== "new", attachment_id = parseInt($target.attr("data-id"), 10), - attachment_url = this.attachmentUrl, - attachment_extension = $(event.currentTarget).attr( - "data-extension" - ), - attachment_title = $target.attr("data-original-title"); - + attachment_extension = "pdf", + attachment_title = $target.attr("data-original-title"), + attachment_url = this.attachmentUrl; if (attachment_extension) { this.showPreview( attachment_id, @@ -196,141 +110,12 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function }); } }, - - getPreviewableAttachments: function () { - var self = this; - var deferred = $.Deferred(); - - var $items = $(this).find(".o_attachment_preview"); - var attachments = _.object( - $items.map(function () { - return parseInt($(this).attr("data-id"), 10); - }), - $items.map(function () { - return { - url: $(this).attr("data-url"), - extension: $(this).attr("data-extension"), - title: $(this).attr("data-original-title"), - }; - }) - ); - - rpc.query({ - model: "ir.attachment", - method: "get_attachment_extension", - args: [ - _.map(_.keys(attachments), function (id) { - return parseInt(id, 10); - }), - ], - }).then( - function (extensions) { - var reviewableAttachments = _.map( - _.keys( - _.pick(extensions, function (extension, id) { - return self.canPreview(extension); - }) - ), - function (id) { - return { - id: id, - url: attachments[id].url, - extension: extensions[id], - title: attachments[id].title, - previewUrl: self.getUrl( - id, - attachments[id].url, - extensions[id], - id + " - " + attachments[id].title - ), - }; - } - ); - deferred.resolve(reviewableAttachments); - }, - function () { - deferred.reject(); - } - ); - return deferred.promise(); - }, - - updatePreviewButtons: function (previewableAttachments) { - $(this) - .find(".o_attachment_preview") - .each(function () { - var $this = $(this); - var id = $this.attr("data-id"); - var att = _.findWhere(previewableAttachments, {id: id}); - if (att) { - $this.attr("data-extension", att.extension); - } else { - $this.remove(); - } - }); - }, } ); - basic_fields.FieldBinaryFile.include(attachment); - basic_fields.FieldBinaryFile.include({ - events: _.extend({}, basic_fields.FieldBinaryFile.prototype.events, { - "click .fa-search": "_onPreview", - }), - - _renderReadonly: function () { - var self = this; - this._super.apply(this, arguments); - - if (this.recordData.id) { - this._getBinaryExtension().done(function (extension) { - if (self.canPreview(extension)) { - self._renderPreviewButton(extension); - } - }); - } - }, - - _renderPreviewButton: function (extension) { - this.$previewBtn = $(""); - this.$previewBtn.addClass("fa fa-search mr-2"); - this.$previewBtn.attr("href", "javascript:void(0)"); - this.$previewBtn.attr( - "title", - _.str.sprintf(_t("Preview %s"), this.field.string) - ); - this.$previewBtn.attr("data-extension", extension); - this.$el.find(".fa-download").before(this.$previewBtn); - }, - - _getBinaryExtension: function () { - return this._rpc({ - model: "ir.attachment", - method: "get_binary_extension", - args: [this.model, this.recordData.id, this.name, this.attrs.filename], - }); - }, - - _onPreview: function (event) { - this.showPreview( - null, - _.str.sprintf( - "/web/content?model=%s&field=%s&id=%d", - this.model, - this.name, - this.recordData.id - ), - $(event.currentTarget).attr("data-extension"), - _.str.sprintf(_t("Preview %s"), this.field.string), - false - ); - event.stopPropagation(); - }, - }); var AttachmentPreviewWidget = Widget.extend({ template: "attachment_preview.AttachmentPreviewWidget", activeIndex: 0, - attachments: null, events: { "click .attachment_preview_close": "_onCloseClick", @@ -403,6 +188,9 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function this.activeIndex + 1, this.attachments.length ); + this.$overlay = $(this).find(".attachment_preview_overlay"); + this.$iframe = $(this).find(".attachment_preview_iframe"); + this.$current = $(this).find(".attachment_preview_current"); this.$current.html(value); }, @@ -417,10 +205,219 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function }, setAttachments: function (attachments) { - this.attachments = attachments; - this.activeIndex = 0; - this.updatePaginator(); - this.loadPreview(); + if (attachments) { + this.attachments = attachments; + this.activeIndex = 0; + this.updatePaginator(); + this.loadPreview(); + } + }, + }); + + const chatter = patch( + components.Chatter, + "mail/static/src/components/chatter/chatter.js", + { + canPreview: function (extension) { + return ( + $.inArray(extension, [ + "odt", + "odp", + "ods", + "fodt", + "pdf", + "ott", + "fodp", + "otp", + "fods", + "ots", + ]) > -1 + ); + }, + + getUrl: function ( + attachment_id, + attachment_url, + attachment_extension, + attachment_title + ) { + return ( + (window.location.origin || "") + + "/attachment_preview/static/lib/ViewerJS/index.html" + + "?type=" + + encodeURIComponent(attachment_extension) + + "&title=" + + encodeURIComponent(attachment_title) + + "#" + + attachment_url.replace(window.location.origin, "") + ); + }, + + showPreview( + attachment_id, + attachment_url, + attachment_extension, + attachment_title, + split_screen + ) { + var url = this.getUrl( + attachment_id, + attachment_url, + attachment_extension, + attachment_title + ); + if (split_screen) { + this.trigger("onAttachmentPreview", {url: url}); + } else { + window.open(url); + } + }, + + _update() { + var self = this; + self.getPreviewableAttachments().done( + function (atts) { + this.updatePreviewButtons(this.previewableAttachments); + if (!this.attachmentPreviewWidget) { + this.attachmentPreviewWidget = new AttachmentPreviewWidget( + this + ); + this.attachmentPreviewWidget.setAttachments(atts); + } + this.props.previewableAttachments = atts; + this.attachmentPreviewWidget.setAttachments(atts); + }.bind(this) + ); + }, + + getPreviewableAttachments: function () { + var self = this; + var deferred = $.Deferred(); + var $items = $(".o_attachment_preview"); + var attachments = _.object( + $items.map(function () { + return parseInt($(this).attr("data-id"), 10); + }), + $items.map(function () { + return { + url: $(this).attr("data-url"), + extension: $(this).attr("data-extension"), + title: $(this).attr("data-original-title"), + }; + }) + ); + + rpc.query({ + model: "ir.attachment", + method: "get_attachment_extension", + args: [ + _.map(_.keys(attachments), function (id) { + return parseInt(id, 10); + }), + ], + }).then( + function (extensions) { + var reviewableAttachments = _.map( + _.keys( + _.pick(extensions, function (extension) { + return self.canPreview(extension); + }) + ), + function (id) { + return { + id: id, + url: attachments[id].url, + extension: extensions[id], + title: attachments[id].title, + previewUrl: self.getUrl( + id, + attachments[id].url, + extensions[id], + id + " - " + attachments[id].title + ), + }; + } + ); + deferred.resolve(reviewableAttachments); + }, + function () { + deferred.reject(); + } + ); + return deferred.promise(); + }, + + updatePreviewButtons: function (previewableAttachments) { + $(this) + .find(".o_attachment_preview") + .each(function () { + var $this = $(this); + var att = _.findWhere(previewableAttachments, { + id: $this.attr("data-id"), + }); + if (att) { + $this.attr("data-extension", att.extension); + } else { + $this.remove(); + } + }); + }, + } + ); + + basic_fields.FieldBinaryFile.include(components.Chatter); + basic_fields.FieldBinaryFile.include({ + events: _.extend({}, basic_fields.FieldBinaryFile.prototype.events, { + "click .fa-search": "_onPreview", + }), + + _renderReadonly: function () { + var self = this; + this._super.apply(this, arguments); + + if (this.recordData.id) { + this._getBinaryExtension().done(function (extension) { + if (self.canPreview(extension)) { + self._renderPreviewButton(extension); + } + }); + } + }, + + _renderPreviewButton: function (extension) { + this.$previewBtn = $(""); + this.$previewBtn.addClass("fa fa-search mr-2"); + this.$previewBtn.attr("href"); + this.$previewBtn.attr( + "title", + _.str.sprintf(_t("Preview %s"), this.field.string) + ); + this.$previewBtn.attr("data-extension", extension); + this.$el.find(".fa-download").before(this.$previewBtn); + }, + + _getBinaryExtension: function () { + return this._rpc({ + model: "ir.attachment", + method: "get_binary_extension", + args: [this.model, this.recordData.id, this.name, this.attrs.filename], + }); + }, + + _onPreview: function (event) { + this.showPreview( + null, + _.str.sprintf( + "/web/content?model=%s&field=%s&id=%d", + this.model, + this.name, + this.recordData.id + ), + $(event.currentTarget).attr("data-extension"), + _.str.sprintf(_t("Preview %s"), this.field.string), + false + ); + event.stopPropagation(); }, }); @@ -428,7 +425,6 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function custom_events: _.extend({}, FormRenderer.prototype.custom_events, { onAttachmentPreview: "_onAttachmentPreview", }), - attachmentPreviewWidget: null, init: function () { @@ -452,13 +448,8 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function }, showAttachmentPreviewWidget: function () { - // Debugger; this.$el.addClass("attachment_preview"); - - this.attachmentPreviewWidget.setAttachments( - this.attachments - // This._chatterContainerComponent.Component.components.Chatter.props.chatterLocalId.previewableAttachments - ); + this.attachmentPreviewWidget.setAttachments(this.previewableAttachments); this.attachmentPreviewWidget.show(); }, @@ -467,13 +458,14 @@ odoo.define("/attachment_preview/static/src/js/attachment_preview.js", function return this._super.apply(this, arguments); }, - _onAttachmentPreview: function (event) { + _onAttachmentPreview: function () { this.showAttachmentPreviewWidget(); }, }); return { attachment, + chatter, AttachmentPreviewWidget: AttachmentPreviewWidget, }; }); diff --git a/attachment_preview/static/src/js/viewerjs_tweaks.js b/attachment_preview/static/src/js/viewerjs_tweaks.js index ad745646..21d209cb 100644 --- a/attachment_preview/static/src/js/viewerjs_tweaks.js +++ b/attachment_preview/static/src/js/viewerjs_tweaks.js @@ -4,6 +4,7 @@ // This file contains tweaks for viewerjs itself and is not meant to be run in // OpenERP's context (function (original_Viewer) { + "use strict"; window.Viewer = function (plugin, parameters) { if (!plugin) { // eslint-disable-next-line no-alert diff --git a/attachment_preview/static/src/xml/attachment_preview.xml b/attachment_preview/static/src/xml/attachment_preview.xml index 82404336..95bf9b7e 100644 --- a/attachment_preview/static/src/xml/attachment_preview.xml +++ b/attachment_preview/static/src/xml/attachment_preview.xml @@ -9,9 +9,10 @@
@@ -20,7 +21,9 @@ class="ml4 o_attachment_preview o_attachment_preview_new_tab" data-target="new" t-att-data-id="attachment.id" - t-att-data-url="attachment.url" + t-att-data-url="attachmentUrl" + t-on-click="_onPreviewAttachment" + t-att-data-original-title="attachment.name" t-attf-title="Open preview {{attachment.name}} in a new tab" > diff --git a/attachment_preview/tests/test_attachment_preview.py b/attachment_preview/tests/test_attachment_preview.py index bbd023da..68cb1676 100644 --- a/attachment_preview/tests/test_attachment_preview.py +++ b/attachment_preview/tests/test_attachment_preview.py @@ -12,14 +12,12 @@ class TestAttachmentPreview(TransactionCase): { "datas": base64.b64encode(b"from this, to that."), "name": "doc.txt", - "datas_fname": "doc.txt", } ) attachment2 = self.env["ir.attachment"].create( { "datas": base64.b64encode(b"Png"), "name": "image.png", - "datas_fname": "image.png", } ) res = self.env["ir.attachment"].get_attachment_extension(attachment.id) @@ -37,7 +35,8 @@ class TestAttachmentPreview(TransactionCase): self.assertTrue(res2) module = ( - self.env["ir.module.module"].search([]).filtered(lambda m: m.icon_image)[0] + self.env["ir.module.module"].search( + []).filtered(lambda m: m.icon_image)[0] ) res3 = self.env["ir.attachment"].get_binary_extension( "ir.module.module", module.id, "icon_image"