上传修改后的主题
This commit is contained in:
@@ -0,0 +1,390 @@
|
||||
odoo.define('spiffy_theme_backend.spiffyDocumentViewer', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var SCROLL_ZOOM_STEP = 0.1;
|
||||
var ZOOM_STEP = 0.5;
|
||||
|
||||
var spiffyDocumentViewer = Widget.extend({
|
||||
template: "spiffyDocumentViewer",
|
||||
events: {
|
||||
'click .o_download_btn': '_onDownload',
|
||||
'click .o_viewer_img': '_onImageClicked',
|
||||
'click .o_viewer_video': '_onVideoClicked',
|
||||
'click .move_next': '_onNext',
|
||||
'click .move_previous': '_onPrevious',
|
||||
'click .o_rotate': '_onRotate',
|
||||
'click .o_zoom_in': '_onZoomIn',
|
||||
'click .o_zoom_out': '_onZoomOut',
|
||||
'click .o_zoom_reset': '_onZoomReset',
|
||||
'click .o_close_btn, .o_viewer_img_wrapper': '_onClose',
|
||||
'click .o_print_btn': '_onPrint',
|
||||
'DOMMouseScroll .o_viewer_content': '_onScroll', // Firefox
|
||||
'mousewheel .o_viewer_content': '_onScroll', // Chrome, Safari, IE
|
||||
'keydown': '_onKeydown',
|
||||
'keyup': '_onKeyUp',
|
||||
'mousedown .o_viewer_img': '_onStartDrag',
|
||||
'mousemove .o_viewer_content': '_onDrag',
|
||||
'mouseup .o_viewer_content': '_onEndDrag'
|
||||
},
|
||||
/**
|
||||
* The documentViewer takes an array of objects describing attachments in
|
||||
* argument, and the ID of an active attachment (the one to display first).
|
||||
* Documents that are not of type image or video are filtered out.
|
||||
*
|
||||
* @override
|
||||
* @param {Array<Object>} attachments list of attachments
|
||||
* @param {integer} activeAttachmentID
|
||||
*/
|
||||
init: function (parent, attachments, activeAttachmentID) {
|
||||
this._super.apply(this, arguments);
|
||||
this.attachment = _.filter(attachments, function (attachment) {
|
||||
var match = attachment.type === 'url' ? attachment.url.match("(youtu|.png|.jpg|.gif)") : attachment.mimetype.match("(image|video|application/pdf|text)");
|
||||
if (match) {
|
||||
attachment.fileType = match[1];
|
||||
if (match[1].match("(.png|.jpg|.gif)")) {
|
||||
attachment.fileType = 'image';
|
||||
}
|
||||
if (match[1] === 'youtu') {
|
||||
var youtube_array = attachment.url.split('/');
|
||||
var youtube_token = youtube_array[youtube_array.length-1];
|
||||
if (youtube_token.indexOf('watch') !== -1) {
|
||||
youtube_token = youtube_token.split('v=')[1];
|
||||
var amp = youtube_token.indexOf('&')
|
||||
if (amp !== -1){
|
||||
youtube_token = youtube_token.substring(0, amp);
|
||||
}
|
||||
}
|
||||
attachment.youtube = youtube_token;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.activeAttachment = _.findWhere(attachments, {id: activeAttachmentID});
|
||||
this.modelName = 'ir.attachment';
|
||||
this._reset();
|
||||
},
|
||||
/**
|
||||
* Open a modal displaying the active attachment
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.modal('show');
|
||||
this.$el.on('hidden.bs.modal', _.bind(this._onDestroy, this));
|
||||
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
|
||||
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
this.$el.modal('hide');
|
||||
this.$el.remove();
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_next: function () {
|
||||
var index = _.findIndex(this.attachment, this.activeAttachment);
|
||||
index = (index + 1) % this.attachment.length;
|
||||
this.activeAttachment = this.attachment[index];
|
||||
this._updateContent();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_previous: function () {
|
||||
var index = _.findIndex(this.attachment, this.activeAttachment);
|
||||
index = index === 0 ? this.attachment.length - 1 : index - 1;
|
||||
this.activeAttachment = this.attachment[index];
|
||||
this._updateContent();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_reset: function () {
|
||||
this.scale = 1;
|
||||
this.dragStartX = this.dragstopX = 0;
|
||||
this.dragStartY = this.dragstopY = 0;
|
||||
},
|
||||
/**
|
||||
* Render the active attachment
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_updateContent: function () {
|
||||
this.$('.o_viewer_content').html(QWeb.render('spiffyDocumentViewer.Content', {
|
||||
widget: this
|
||||
}));
|
||||
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
|
||||
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
|
||||
this._reset();
|
||||
},
|
||||
/**
|
||||
* Get CSS transform property based on scale and angle
|
||||
*
|
||||
* @private
|
||||
* @param {float} scale
|
||||
* @param {float} angle
|
||||
*/
|
||||
_getTransform: function(scale, angle) {
|
||||
return 'scale3d(' + scale + ', ' + scale + ', 1) rotate(' + angle + 'deg)';
|
||||
},
|
||||
/**
|
||||
* Rotate image clockwise by provided angle
|
||||
*
|
||||
* @private
|
||||
* @param {float} angle
|
||||
*/
|
||||
_rotate: function (angle) {
|
||||
this._reset();
|
||||
var new_angle = (this.angle || 0) + angle;
|
||||
this.$('.o_viewer_img').css('transform', this._getTransform(this.scale, new_angle));
|
||||
this.$('.o_viewer_img').css('max-width', new_angle % 180 !== 0 ? $(document).height() : '100%');
|
||||
this.$('.o_viewer_img').css('max-height', new_angle % 180 !== 0 ? $(document).width() : '100%');
|
||||
this.angle = new_angle;
|
||||
},
|
||||
/**
|
||||
* Zoom in/out image by provided scale
|
||||
*
|
||||
* @private
|
||||
* @param {integer} scale
|
||||
*/
|
||||
_zoom: function (scale) {
|
||||
if (scale > 0.5) {
|
||||
this.$('.o_viewer_img').css('transform', this._getTransform(scale, this.angle || 0));
|
||||
this.scale = scale;
|
||||
}
|
||||
this.$('.o_zoom_reset').add('.o_zoom_out').toggleClass('disabled', scale === 1);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onClose: function (e) {
|
||||
e.preventDefault();
|
||||
this.destroy();
|
||||
},
|
||||
/**
|
||||
* When popup close complete destroyed modal even DOM footprint too
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onDestroy: function () {
|
||||
this.destroy();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onDownload: function (e) {
|
||||
e.preventDefault();
|
||||
window.location = '/web/content/' + this.modelName + '/' + this.activeAttachment.id + '/' + 'datas' + '?download=true';
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onDrag: function (e) {
|
||||
e.preventDefault();
|
||||
if (this.enableDrag) {
|
||||
var $image = this.$('.o_viewer_img');
|
||||
var $zoomer = this.$('.o_viewer_zoomer');
|
||||
var top = $image.prop('offsetHeight') * this.scale > $zoomer.height() ? e.clientY - this.dragStartY : 0;
|
||||
var left = $image.prop('offsetWidth') * this.scale > $zoomer.width() ? e.clientX - this.dragStartX : 0;
|
||||
$zoomer.css("transform", "translate3d("+ left +"px, " + top + "px, 0)");
|
||||
$image.css('cursor', 'move');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onEndDrag: function (e) {
|
||||
e.preventDefault();
|
||||
if (this.enableDrag) {
|
||||
this.enableDrag = false;
|
||||
this.dragstopX = e.clientX - this.dragStartX;
|
||||
this.dragstopY = e.clientY - this.dragStartY;
|
||||
this.$('.o_viewer_img').css('cursor', '');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* On click of image do not close modal so stop event propagation
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onImageClicked: function (e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
/**
|
||||
* Remove loading indicator when image loaded
|
||||
* @private
|
||||
*/
|
||||
_onImageLoaded: function () {
|
||||
this.$('.o_loading_img').hide();
|
||||
},
|
||||
/**
|
||||
* Move next previous attachment on keyboard right left key
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} e
|
||||
*/
|
||||
_onKeydown: function (e){
|
||||
switch (e.which) {
|
||||
case $.ui.keyCode.RIGHT:
|
||||
e.preventDefault();
|
||||
this._next();
|
||||
break;
|
||||
case $.ui.keyCode.LEFT:
|
||||
e.preventDefault();
|
||||
this._previous();
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Close popup on ESCAPE keyup
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} e
|
||||
*/
|
||||
_onKeyUp: function (e) {
|
||||
switch (e.which) {
|
||||
case $.ui.keyCode.ESCAPE:
|
||||
e.preventDefault();
|
||||
this._onClose(e);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onNext: function (e) {
|
||||
e.preventDefault();
|
||||
this._next();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onPrevious: function (e) {
|
||||
e.preventDefault();
|
||||
this._previous();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onPrint: function (e) {
|
||||
e.preventDefault();
|
||||
var src = this.$('.o_viewer_img').prop('src');
|
||||
var script = QWeb.render('PrintImage', {
|
||||
src: src
|
||||
});
|
||||
var printWindow = window.open('about:blank', "_new");
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(script);
|
||||
printWindow.document.close();
|
||||
},
|
||||
/**
|
||||
* Zoom image on scroll
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onScroll: function (e) {
|
||||
var scale;
|
||||
if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
|
||||
scale = this.scale + SCROLL_ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
} else {
|
||||
scale = this.scale - SCROLL_ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onStartDrag: function (e) {
|
||||
e.preventDefault();
|
||||
this.enableDrag = true;
|
||||
this.dragStartX = e.clientX - (this.dragstopX || 0);
|
||||
this.dragStartY = e.clientY - (this.dragstopY || 0);
|
||||
},
|
||||
/**
|
||||
* On click of video do not close modal so stop event propagation
|
||||
* and provide play/pause the video instead of quitting it
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onVideoClicked: function (e) {
|
||||
e.stopPropagation();
|
||||
var videoElement = e.target;
|
||||
if (videoElement.paused) {
|
||||
videoElement.play();
|
||||
} else {
|
||||
videoElement.pause();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onRotate: function (e) {
|
||||
e.preventDefault();
|
||||
this._rotate(90);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomIn: function (e) {
|
||||
e.preventDefault();
|
||||
var scale = this.scale + ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomOut: function (e) {
|
||||
e.preventDefault();
|
||||
var scale = this.scale - ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomReset: function (e) {
|
||||
e.preventDefault();
|
||||
this.$('.o_viewer_zoomer').css("transform", "");
|
||||
this._zoom(1);
|
||||
},
|
||||
});
|
||||
return spiffyDocumentViewer;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#myModal{
|
||||
top:36px;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 1057;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
outline: 0;
|
||||
.modal-dialog{
|
||||
padding:0 !important;
|
||||
height: calc(100% - 100px);
|
||||
pointer-events: all;
|
||||
|
||||
.attch-modal-content {
|
||||
color: var(--biz-theme-body-text-color) !important;
|
||||
.attch-viewer-header{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.75) !important;
|
||||
color: #ced4da !important;
|
||||
width: 100% !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.image_filename_div{
|
||||
|
||||
}
|
||||
.download_clsoe_div{
|
||||
display: flex;
|
||||
a{
|
||||
color: #ced4da !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_viewer_zoomer{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
iframe, a, video{
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
.o_viewer_img{
|
||||
background-color: black;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
.o_viewer_toolbar{
|
||||
justify-content: center;
|
||||
bottom: 0;
|
||||
a{
|
||||
background-color: var(--AttachmentViewer_toolbarButton-background-color, #343a40);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.arrow{
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 40px;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.move_previous{
|
||||
left: 15px !important;
|
||||
}
|
||||
.move_next{
|
||||
right: 15px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="spiffyDocumentViewer.Content">
|
||||
<div class="o_viewer_content h-100">
|
||||
<t t-set="model" t-value="widget.modelName"/>
|
||||
<div class="attch-viewer-header">
|
||||
<div class="image_filename_div ms-2">
|
||||
<span class="o_image_caption">
|
||||
<i class="fa fa-picture-o mr8" t-if="widget.activeAttachment.fileType == 'image'" role="img" aria-label="Image" title="Image"/>
|
||||
<i class="fa fa-file-text mr8" t-if="widget.activeAttachment.fileType == 'application/pdf'" role="img" aria-label="PDF file" title="PDF file"/>
|
||||
<i class="fa fa-video-camera mr8" t-if="widget.activeAttachment.fileType == 'video'" role="img" aria-label="Video" title="Video"/>
|
||||
<span class="o_viewer_document_name" t-esc="widget.activeAttachment.name"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="download_clsoe_div">
|
||||
<a class="o_download_btn o_document_viewer_topbar_button btn" href="#" title="Download">
|
||||
<i class="fa fa-fw fa-download" role="img" aria-label="Download"/>
|
||||
<span class="d-none d-md-inline ml-2">Download</span>
|
||||
</a>
|
||||
<a role="button" href="#" class="o_close_btn o_document_viewer_topbar_button btn" title="Close">
|
||||
<i class="fa fa-fw fa-close" role="img" aria-label="Close"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_viewer_img_wrapper h-100">
|
||||
<div class="o_viewer_zoomer h-100">
|
||||
<t t-if="widget.activeAttachment.fileType === 'image'">
|
||||
<div class="o_loading_img text-center">
|
||||
<i class="fa fa-circle-o-notch fa-spin text-gray-light fa-3x fa-fw" role="img" aria-label="Loading" title="Loading"/>
|
||||
</div>
|
||||
<t t-set="unique" t-value="widget.activeAttachment.checksum ? widget.activeAttachment.checksum.slice(-8) : ''"/>
|
||||
<img class="o_viewer_img img-fluid" t-attf-src="/web/image/#{widget.activeAttachment.id}?unique=#{unique}&model=#{model}" alt="Viewer"/>
|
||||
</t>
|
||||
<iframe t-if="widget.activeAttachment.fileType == 'application/pdf'" class="o_viewer_pdf" t-attf-src="/web/static/lib/pdfjs/web/viewer.html?file=/web/content/#{widget.activeAttachment.id}?model%3D#{model}%26filename%3D#{window.encodeURIComponent(widget.activeAttachment.name)}" />
|
||||
<iframe t-if="(widget.activeAttachment.fileType || '').indexOf('text') !== -1" class="o_viewer_text" t-attf-src="/web/content/#{widget.activeAttachment.id}?model=#{model}" />
|
||||
<iframe t-if="widget.activeAttachment.fileType == 'youtu'" class="o_viewer_text" allow="autoplay; encrypted-media" width="560" height="315" t-attf-src="https://www.youtube.com/embed/#{widget.activeAttachment.youtube}"/>
|
||||
<video t-if="widget.activeAttachment.fileType == 'video'" class="o_viewer_video" controls="controls">
|
||||
<source t-attf-src="/web/image/#{widget.activeAttachment.id}?model=#{model}" t-att-data-type="widget.activeAttachment.mimetype"/>
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="widget.activeAttachment.fileType == 'image'" class="o_viewer_toolbar btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_in" data-toggle="tooltip" title="Zoom In"><i class="fa fa-fw fa-plus" role="img" aria-label="Zoom In"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_reset disabled" data-toggle="tooltip" title="Reset Zoom"><i class="fa fa-fw fa-search" role="img" aria-label="Reset Zoom"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_out disabled" data-toggle="tooltip" title="Zoom Out"><i class="fa fa-fw fa-minus" role="img" aria-label="Zoom Out"/></a>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_rotate" data-toggle="tooltip" title="Rotate"><i class="fa fa-fw fa-repeat" role="img" aria-label="Rotate"/></a>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_print_btn" data-toggle="tooltip" title="Print"><i class="fa fa-fw fa-print" role="img" aria-label="Print"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_download_btn" data-toggle="tooltip" title="Download"><i class="fa fa-fw fa-download" role="img" aria-label="Download"/></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
@param {mail.DocumentViewer} widget
|
||||
-->
|
||||
<t t-name="spiffyDocumentViewer">
|
||||
<div class="modal o_modal_fullscreen" id="myModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="attch-modal-content h-100">
|
||||
<t class="o_document_viewer_content_call" t-call="spiffyDocumentViewer.Content" />
|
||||
<t t-if="widget.attachment.length !== 1">
|
||||
<a class="arrow arrow-left move_previous" href="#">
|
||||
<span class="fa fa-chevron-left" role="img" aria-label="Previous" title="Previous"/>
|
||||
</a>
|
||||
<a class="arrow arrow-right move_next" href="#">
|
||||
<span class="fa fa-chevron-right" role="img" aria-label="Next" title="Next"/>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="PrintImage">
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function onload_img() {
|
||||
setTimeout('print_img()', 10);
|
||||
}
|
||||
function print_img() {
|
||||
window.print();
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onload_img()'>
|
||||
<img t-att-src='src' alt=""/>
|
||||
</body>
|
||||
</html>
|
||||
</t>
|
||||
</templates>
|
||||
Reference in New Issue
Block a user