From c56f7912efac1d256009d8aa2fb6539b71e9fbfa Mon Sep 17 00:00:00 2001 From: aignatov-bio Date: Mon, 19 Oct 2020 15:23:34 +0200 Subject: [PATCH 1/6] Update file preview --- .../javascripts/my_modules/repositories.js | 1 - app/assets/javascripts/my_modules/results.js | 1 - app/assets/javascripts/protocols/index.js | 2 - app/assets/javascripts/protocols/steps.js.erb | 7 +- .../repositories/repository_datatable.js | 3 - .../javascripts/results/result_assets.js | 3 - .../javascripts/sitewide/drag_n_drop.js | 1 - .../javascripts/sitewide/file_preview.js | 465 ++---------------- .../javascripts/sitewide/image_editor.js | 407 +++++++++++++++ .../javascripts/sitewide/marvinjs_editor.js | 1 - .../sitewide/repository_row_info_modal.js | 1 - app/controllers/assets_controller.rb | 27 +- app/views/layouts/application.html.erb | 2 +- app/views/my_modules/archive.html.erb | 2 - .../_repository_row_info_modal.html.erb | 1 - .../shared/file_preview/_content.html.erb | 24 + app/views/shared/file_preview/_modal.html.erb | 13 + 17 files changed, 503 insertions(+), 458 deletions(-) create mode 100644 app/assets/javascripts/sitewide/image_editor.js create mode 100644 app/views/shared/file_preview/_content.html.erb create mode 100644 app/views/shared/file_preview/_modal.html.erb diff --git a/app/assets/javascripts/my_modules/repositories.js b/app/assets/javascripts/my_modules/repositories.js index 897553a4d..b3640dc38 100644 --- a/app/assets/javascripts/my_modules/repositories.js +++ b/app/assets/javascripts/my_modules/repositories.js @@ -186,7 +186,6 @@ var MyModuleRepositories = (function() { drawCallback: function() { FULL_VIEW_TABLE.columns.adjust(); - FilePreviewModal.init(); renderFullViewRepositoryName( tableContainer.attr('data-repository-name'), tableContainer.attr('data-repository-snapshot-created'), diff --git a/app/assets/javascripts/my_modules/results.js b/app/assets/javascripts/my_modules/results.js index 0483d0a49..dd7aa01e3 100644 --- a/app/assets/javascripts/my_modules/results.js +++ b/app/assets/javascripts/my_modules/results.js @@ -118,7 +118,6 @@ ResultAssets.applyEditResultAssetCallback(); applyCreateWopiFileCallback(); toggleResultEditButtons(true); - FilePreviewModal.init(); Comments.init(); ResultAssets.initNewResultAsset(); expandResult($(this)); diff --git a/app/assets/javascripts/protocols/index.js b/app/assets/javascripts/protocols/index.js index dcd29c0c1..99986c960 100644 --- a/app/assets/javascripts/protocols/index.js +++ b/app/assets/javascripts/protocols/index.js @@ -220,8 +220,6 @@ function initProtocolPreviewModal() { modal.modal("show"); ProtocolRepositoryHeader.init(); initHandsOnTable(modalBody); - FilePreviewModal.init({ readOnly: true }); - }, error: function (error) { // TODO } diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index 0d191e8c8..d69fe3ca1 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -79,7 +79,6 @@ setTimeout(function() { initStepsComments(); - FilePreviewModal.init(); SmartAnnotation.preventPropagation('.atwho-user-popover'); TinyMCE.destroyAll(); DragNDropSteps.clearFiles(); @@ -107,7 +106,6 @@ toggleButtons(false); initializeCheckboxSorting(); animateSpinner(null, false); - FilePreviewModal.init(); DragNDropSteps.clearFiles(); if (tinyMCE.editors.step_description_textarea) tinyMCE.editors.step_description_textarea.remove(); TinyMCE.init('#step_description_textarea'); @@ -183,8 +181,6 @@ initCallBacks(); initHandsOnTable($new_step); toggleButtons(true); - FilePreviewModal.init(); - TinyMCE.destroyAll(); SmartAnnotation.preventPropagation('.atwho-user-popover'); // Show the edited step @@ -345,6 +341,7 @@ $(`.asset[data-asset-id=${assetId}]`).replaceWith(data.html); FilePreviewModal.init(); $(`.asset[data-asset-id=${assetId}]`).closest('.attachments').trigger('reorder'); + }, error: function (data) { console.log(data); @@ -592,7 +589,6 @@ }); animateSpinner(null, false); DragNDropSteps.clearFiles(); - FilePreviewModal.init(); if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); }, error: function(xhr) { @@ -697,7 +693,6 @@ initCallBacks(); initHandsOnTable($(document)); expandAllSteps(); - FilePreviewModal.init(); TinyMCE.highlight(); SmartAnnotation.preventPropagation('.atwho-user-popover'); newStepHandler(); diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index c05fc64c9..52daf7973 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -118,7 +118,6 @@ var RepositoryDatatable = (function(global) { currentMode = 'viewMode'; // Table specific stuff TABLE.button(0).enable(true); - FilePreviewModal.init(); $(TABLE_WRAPPER_ID).find('tr').removeClass('blocked'); updateButtons(); disableCheckboxToggleOnCheckboxPreview(); @@ -502,7 +501,6 @@ var RepositoryDatatable = (function(global) { animateSpinner(this, false); changeToViewMode(); updateDataTableSelectAllCtrl(); - FilePreviewModal.init(); // Prevent row toggling when selecting user smart annotation link SmartAnnotation.preventPropagation('.atwho-user-popover'); @@ -549,7 +547,6 @@ var RepositoryDatatable = (function(global) { }, fnInitComplete: function() { disableCheckboxToggleOnAssetDownload(); - FilePreviewModal.init(); initHeaderTooltip(); disableCheckboxToggleOnCheckboxPreview(); diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index d8b92a117..35477a682 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -50,7 +50,6 @@ $form.remove(); applyEditResultAssetCallback(); Results.toggleResultEditButtons(true); - FilePreviewModal.init(); }); Results.toggleResultEditButtons(false); @@ -71,7 +70,6 @@ Results.toggleResultEditButtons(true); Results.expandResult($newResult); - FilePreviewModal.init(); Comments.init(); initNewResultAsset(); }).on('ajax:error', function(e, xhr) { @@ -97,5 +95,4 @@ ResultAssets.initNewResultAsset(); ResultAssets.applyEditResultAssetCallback(); - FilePreviewModal.init(); }(window)); diff --git a/app/assets/javascripts/sitewide/drag_n_drop.js b/app/assets/javascripts/sitewide/drag_n_drop.js index fbfeb2f77..66682e94d 100644 --- a/app/assets/javascripts/sitewide/drag_n_drop.js +++ b/app/assets/javascripts/sitewide/drag_n_drop.js @@ -435,7 +435,6 @@ initFormSubmitLinks($(this)); ResultAssets.applyEditResultAssetCallback(); Results.toggleResultEditButtons(true); - FilePreviewModal.init(); Comments.init(); ResultAssets.initNewResultAsset(); Results.expandResult($(this)); diff --git a/app/assets/javascripts/sitewide/file_preview.js b/app/assets/javascripts/sitewide/file_preview.js index d31b942d8..e4ba247ea 100644 --- a/app/assets/javascripts/sitewide/file_preview.js +++ b/app/assets/javascripts/sitewide/file_preview.js @@ -8,439 +8,47 @@ var FilePreviewModal = (function() { 'use strict'; - var readOnly = false; + //var readOnly = false; function initPreviewModal(options = {}) { - var name; - var url; - var downloadUrl; - readOnly = options.readOnly; - - $('.file-preview-link').off('click'); - $('.file-preview-link').click(function(e) { - if ($(e.target.offsetParent).hasClass('change-preview-type')) return; + $(document).on('click', '.file-preview-link', function(e) { e.preventDefault(); - name = $(this).find('.attachment-label').text(); - url = $(this).data('preview-url'); - downloadUrl = $(this).attr('href'); - openPreviewModal(name, url, downloadUrl); - return true; - }); + $.get($(this).data('preview-url'), function(result) { + $('#filePreviewModal .modal-content').html(result.html); + $('#filePreviewModal').modal('show'); + }) + }) + //var name; + //var url; + //var downloadUrl; + //readOnly = options.readOnly; - $('#filePreviewModal').find('.preview-close').click(function() { - $('#filePreviewModal').find('.file-preview-container').html(''); - $('#filePreviewModal').modal('hide'); - if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); - }); + //return false; + // + //$('.file-preview-link').off('click'); + //$('.file-preview-link').click(function(e) { + // if ($(e.target.offsetParent).hasClass('change-preview-type')) return; + // e.preventDefault(); + // name = $(this).find('.attachment-label').text(); + // url = $(this).data('preview-url'); + // downloadUrl = $(this).attr('href'); + // openPreviewModal(name, url, downloadUrl); + // return true; + //}); + // + //$('#filePreviewModal').find('.preview-close').click(function() { + // $('#filePreviewModal').find('.file-preview-container').html(''); + // $('#filePreviewModal').modal('hide'); + // if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); + //}); } // Adding rotation icon - function updateFabricControls() { - fabric.Object.prototype.drawBorders = function(ctx, styleOverride = {}) { - var wh = this._calculateCurrentDimensions(); - var strokeWidth = 1 / this.borderScaleFactor; - var width = wh.x + strokeWidth; - var height = wh.y + strokeWidth; - var drawRotatingPoint = typeof styleOverride.hasRotatingPoint !== 'undefined' - ? styleOverride.hasRotatingPoint : this.hasRotatingPoint; - var hasControls = typeof styleOverride.hasControls !== 'undefined' - ? styleOverride.hasControls : this.hasControls; - var rotatingPointOffset = typeof styleOverride.rotatingPointOffset !== 'undefined' - ? styleOverride.rotatingPointOffset : this.rotatingPointOffset; - var rotateHeight = -height / 2; - ctx.save(); - ctx.strokeStyle = styleOverride.borderColor || this.borderColor; - this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null); - ctx.strokeRect( - -width / 2, - -height / 2, - width, - height - ); - if (drawRotatingPoint && this.isControlVisible('mtr') && hasControls) { - ctx.beginPath(); - ctx.moveTo(0, rotateHeight); - ctx.lineTo(0, rotateHeight - rotatingPointOffset + 10); - ctx.stroke(); - } - ctx.restore(); - return this; - }; - fabric.Object.prototype.drawControls = function(ctx) { - var rotationImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAHEklEQVRoge2bYYgdVxXHf/8lhGUJYQ1hKSFIiDXUEoq+e1lClLgfRLSGfNGSVvxgVIyiIqGWEhfpp6IBayiSBJQiQo3YKEQqsQSpmkopYWYJIUSIEkrYhhiWEEIoyxLe3w8zb53Mm/fezNvdlhf7h8feeTv3zvnPPffcc885T8b8P2Hs/RbgvcYHhB90rFurgWOIY8A4sNN2S9JHbG+VtBEYt70E3AFuSvoXcDH/3E7SpL1WcqnKaMUQ1wFjSZosNRkshrgR2A60gKdsR0mTALaRxID2InBR0ingHHA1SZOFIblVootwDHEn8ITtDZJ+naTJxUGDxBAngN2290uaAbaxMu1p274u6S3gN8DfkjS5vYLxltFFOLTCG5KmyQT+h+1n0rn0fFXnXG132n4mJ7qFVbYLtm9KOg8cJSO+InW/j3AMcQr4T+meS8DTSZqc7XwRWmFM0hbbX5U0S7ZW1xpt4DhwwvaVdC69N8wg5dmoUsOdwNEY4nTnC0m7gBNNyNpeaXsM+BbwS0n76jyzCuUZ3gK8UxY0NyrnbT8taQx4yfb2vP1+4AbwLHAySZNGMz1Q4I4FBaYl/QH4M/BwsW+dWVplPAT8HPhhaIWNTTo2taRTnUbhRdRpt4EFYD7/e8/2OmBS0pacQFNZNgKHJC0BP6nbaaBKrwCLwHXgNeBV4Jrtd4EloJ2/jPXABBnhL9h+XNJ2mhnBO7YPSDpdx4J3Ebb9jqTltdvLSRggwAXgmKTXkjS5U1fyGOI4sAf4PjANbK7Tz/ZVSV8Hzg0i3aVGHULlv+V2nwcfk/RKkibzdYQtIkmTReBsDDEB9gHfAeIgL03SNuAQ8G+yZdMTPY1WQ4PTBi5LegI4PgzZIpI0uQW8DOwHzkjqa4ltjwGfBb40aOyh1nDFW75r+2A6l54c1LcpYoibbf8I+BqwobPMAIrt/PqW7U+kc+m1XuPV2kfLW02Fmm+QNBtDbDWjMxhJmixI+rGkl4vLrNzOrzcBB0Mr9OQ1kHC/9VO8B3gUOBFaYXfuY68akjS5YXsWqPTpS7Luk7Sz1z1dgpXXbsP9dlrSMWCmn2DDIJ1Lb9k+BLxd/l9RxYEdwN78iNuFoYzWAM/q42S+d8+3PCwkXQBO5ufm4vdFOdYDn6TgJBXRRbhqO+p1T5/2Y8ALMcStg0g0QZIm7wK/I9t+llGx1HaTncm7UCa8SLbFDEQN//kR2zvqjNUESZpclHSm+F2F5Z4kI92F+wjbvg0kgx5aM1wzD1xpyKcuftt5XgcVmvbpqo73Lex0Lm3HEA8AB4CHbY/12/f6tBckvUjmS68FLgJXc7+7Fyq3yMog3igghvgSmTPSz8B+KJ1L74uFjXJc+p9Fzav6AB8udxplwm+XnSDb97U7IeIiRpaw7eVjZ/EYWzrSbij3G1nCRTQJK40s4Txl02lT1QbulvuNLGHb22rc05WtGFnCkj5WMlDLRqvgL3Sdi9cse7iWyI+fM/3CUcD18h4MI0qY7HCy7GX18ATnqjqOqko/VbyoMlqS/l7VceQIh1Z4DHi83z2SbgNvVv1vpAjHECck7Sc72PTcc22/RYXBghEjTLZ2nwTGywGKwvWSpDfIEm5dGMpo5Xnk7wEztr8t6fJa1mXkz9xk+0VJ23u4kR1cAc70yio2nuG8vOE54AfAp/Kg3aNDcGjyzIeA5/PKhL7ZENt/IjsvV6IR4RjiBtuHbX+D/yW8dtk+Elph1cM5+TM3A4dtfwWq/ebCer4l6UQ/basdAMgfPAt8E5gohXPaki6TRUou5TmiFSEPs24lywN/jsHLbxGYTdLkZ/1uqjXDeVbvObKSgwnoUqsxstKIU7a/G1qh6+DdBKEVNtn+MnAK2Mtgsm3bfwFeGTR2rRkOrfAZSa9SL297F7hANjNnm5QbhVZYL2mP7UP5eq2VLgWuArXSpbUIxxB3AH8lK0uqhbzSbh44C/wRuCZpOSGe39ZJiE8Bnwf22t4OTPTLTZfadyQdAJonxPshhvgkcIQ8TlRTmM7W0Za0YHs+z/AtkS2nSWXlT1vI1bZXlLRH+7akI0ma1C55aLIPn3ZWnfe87am6ZHMBx4ApSVMdgYvod92nfYesWO14Aw7NwrT5sWyP7V+RzXTtba3JCxqUsZR0A3jW9smmBWpDxaVjiDPAYTLy44MEXS3YvicpAV5I0uT3w4wxlC9t+xxwEPipCuUI/TygvN9K2m1JvyCzxqeHkRtWmHnIVXyarKBkD1n50WrP9E3biaSjtl9P59LVKy4dFrnLOaOsqGUPPdZ3gzXbJjvtvEmWOHt9zcqHV4IY4iRZWeIu4ItAy3aT0sBF4JKkU7bPSbqapMnNVROQNUym5eq+EXiErCrgo2QqP0n2E4B7+dZyEyj+BODWe/4TgAcZoxbxWDE+IPyg47+vLtaj5o1LZgAAAABJRU5ErkJggg=='; - var rotate = new Image(); - var rotateLeft; - var rotateTop; - var wh = this._calculateCurrentDimensions(); - var width = wh.x; - var height = wh.y; - var scaleOffset = this.cornerSize; - var left = -(width + scaleOffset) / 2; - var top = -(height + scaleOffset) / 2; - var methodName = this.transparentCorners ? 'stroke' : 'fill'; - - if (!this.hasControls) { - return this; - } - ctx.save(); - ctx.strokeStyle = this.cornerColor; - ctx.fillStyle = this.cornerColor; - if (!this.transparentCorners) { - ctx.strokeStyle = this.cornerStrokeColor; - } - this._setLineDash(ctx, this.cornerDashArray, null); - - // top-left - this._drawControl( - 'tl', - ctx, - methodName, - left, - top - ); - - // top-right - this._drawControl( - 'tr', - ctx, - methodName, - left + width, - top - ); - - // bottom-left - this._drawControl( - 'bl', - ctx, - methodName, - left, - top + height - ); - - // bottom-right - this._drawControl( - 'br', - ctx, - methodName, - left + width, - top + height - ); - - if (!this.get('lockUniScaling')) { - // middle-top - this._drawControl( - 'mt', - ctx, - methodName, - left + width / 2, - top - ); - - // middle-bottom - this._drawControl( - 'mb', - ctx, - methodName, - left + width / 2, - top + height - ); - - // middle-right - this._drawControl( - 'mr', - ctx, - methodName, - left + width, - top + height / 2 - ); - - // middle-left - this._drawControl( - 'ml', - ctx, - methodName, - left, - top + height / 2 - ); - } - // middle-top-rotate - if (this.hasRotatingPoint) { - rotate.src = rotationImage; - rotateLeft = left + width / 2 - 6; - rotateTop = top - this.rotatingPointOffset - 6; - ctx.drawImage(rotate, rotateLeft, rotateTop, 32, 32); - } - ctx.restore(); - - return this; - }; - } - - function preInitImageEditor(data) { - $.ajax({ - url: data['download-url'], - type: 'get', - success: function(responseData) { - var fileUrl = responseData; - initImageEditor(data, fileUrl); - } - }); - } - - function initImageEditor(data, fileUrl) { - var imageEditor; - var ps; - var blackTheme = { - 'common.bi.image': '', - 'common.bisize.width': '0', - 'common.bisize.height': '0', - 'common.backgroundImage': 'none', - 'common.backgroundColor': '#1e1e1e', - 'common.border': '0px', - - // header - 'header.backgroundImage': 'none', - 'header.backgroundColor': 'transparent', - 'header.border': '0px', - - // load button - 'loadButton.backgroundColor': '#fff', - 'loadButton.border': '1px solid #ddd', - 'loadButton.color': '#222', - 'loadButton.fontFamily': '\'Noto Sans\', sans-serif', - 'loadButton.fontSize': '12px', - - // download button - 'downloadButton.backgroundColor': '#fdba3b', - 'downloadButton.border': '1px solid #fdba3b', - 'downloadButton.color': '#fff', - 'downloadButton.fontFamily': '\'Noto Sans\', sans-serif', - 'downloadButton.fontSize': '12px', - - // main icons - 'menu.normalIcon.path': '/images/icon-d.svg', - 'menu.normalIcon.name': 'icon-d', - 'menu.activeIcon.path': '/images/icon-b.svg', - 'menu.activeIcon.name': 'icon-b', - 'menu.disabledIcon.path': '/images/icon-a.svg', - 'menu.disabledIcon.name': 'icon-a', - 'menu.hoverIcon.path': '/images/icon-c.svg', - 'menu.hoverIcon.name': 'icon-c', - 'menu.iconSize.width': '24px', - 'menu.iconSize.height': '24px', - - // submenu primary color - 'submenu.backgroundColor': '#1e1e1e', - 'submenu.partition.color': '#3c3c3c', - - // submenu icons - 'submenu.normalIcon.path': '/images/icon-d.svg', - 'submenu.normalIcon.name': 'icon-d', - 'submenu.activeIcon.path': '/images/icon-c.svg', - 'submenu.activeIcon.name': 'icon-c', - 'submenu.iconSize.width': '32px', - 'submenu.iconSize.height': '32px', - - // submenu labels - 'submenu.normalLabel.color': '#8a8a8a', - 'submenu.normalLabel.fontWeight': 'lighter', - 'submenu.activeLabel.color': '#fff', - 'submenu.activeLabel.fontWeight': 'lighter', - - // checkbox style - 'checkbox.border': '0px', - 'checkbox.backgroundColor': '#fff', - - // range style - 'range.pointer.color': '#fff', - 'range.bar.color': '#666', - 'range.subbar.color': '#d1d1d1', - - 'range.disabledPointer.color': '#414141', - 'range.disabledBar.color': '#282828', - 'range.disabledSubbar.color': '#414141', - - 'range.value.color': '#fff', - 'range.value.fontWeight': 'lighter', - 'range.value.fontSize': '11px', - 'range.value.border': '1px solid #353535', - 'range.value.backgroundColor': '#151515', - 'range.title.color': '#fff', - 'range.title.fontWeight': 'lighter', - - // colorpicker style - 'colorpicker.button.border': '1px solid #1e1e1e', - 'colorpicker.title.color': '#fff' - }; - - animateSpinner(null, true); - imageEditor = new tui.ImageEditor('#tui-image-editor', { - includeUI: { - loadImage: { - path: fileUrl, - name: data.filename - }, - theme: blackTheme, - initMenu: 'draw', - menuBarPosition: 'bottom' - }, - cssMaxWidth: 700, - cssMaxHeight: 500, - selectionStyle: { - cornerSize: 20, - rotatingPointOffset: 70, - borderColor: '#333', - cornerColor: '#333', - cornerStyle: 'circle', - borderScaleFactor: 3 - - }, - usageStatistics: false - }); - - imageEditor.on('image_loaded', () => { - $('.file-save-link').css('display', ''); - animateSpinner(null, false); - }); - - ps = new PerfectScrollbar($('.tui-image-editor-wrap')[0], { wheelSpeed: 0.5 }); - $('#tui-image-editor .tui-image-editor').on('mousewheel', (e) => { - var imageOriginalSize = { - width: imageEditor._graphics.canvasImage.width, - height: imageEditor._graphics.canvasImage.height - }; - var wDelta = e.originalEvent.wheelDelta || e.originalEvent.deltaY; - var imageEditorWindow = e.currentTarget; - var scrollContainer = $('.tui-image-editor-wrap'); - var initWidth = imageEditorWindow.style.width; - var initHeight = imageEditorWindow.style.height; - - var scrollContainerInitial = { - top: scrollContainer.scrollTop(), - left: scrollContainer.scrollLeft(), - height: scrollContainer[0].scrollHeight, - width: scrollContainer[0].scrollWidth - }; - - var mousePosition = { - top: e.clientY - (imageEditorWindow.offsetTop - scrollContainerInitial.top), - left: e.clientX - $(imageEditorWindow).offset().left - }; - - - var newWidth; - var newHeight; - var offsetY; - var offsetX; - if (wDelta > 0) { - newWidth = parseInt(initWidth, 10) * 1.1; - newHeight = parseInt(initHeight, 10) * 1.1; - if (newWidth > imageOriginalSize.width || newHeight > imageOriginalSize.height) { - newWidth = imageOriginalSize.width; - newHeight = imageOriginalSize.height; - } - } else { - newWidth = parseInt(initWidth, 10) * 0.9; - newHeight = parseInt(initHeight, 10) * 0.9; - if (parseInt(imageEditorWindow.dataset.minWidth, 10) * 0.5 > parseInt(newWidth, 10)) { - newWidth = parseInt(imageEditorWindow.dataset.minWidth, 10) * 0.5; - newHeight = parseInt(imageEditorWindow.dataset.minHeight, 10) * 0.5; - } - } - imageEditorWindow.style.width = newWidth + 'px'; - imageEditorWindow.style.height = newHeight + 'px'; - $(imageEditorWindow).find('canvas, .tui-image-editor-canvas-container') - .css('max-width', imageEditorWindow.style.width) - .css('max-height', imageEditorWindow.style.height); - if (imageEditorWindow.dataset.minHeight === undefined) { - imageEditorWindow.dataset.minHeight = initHeight; - imageEditorWindow.dataset.minWidth = initWidth; - } - - offsetY = (scrollContainer[0].scrollHeight - scrollContainerInitial.height) - * (mousePosition.top / scrollContainerInitial.height); - offsetX = (scrollContainer[0].scrollWidth - scrollContainerInitial.width) - * (mousePosition.left / scrollContainerInitial.width); - - scrollContainer.scrollTop(scrollContainerInitial.top + offsetY); - scrollContainer.scrollLeft(scrollContainerInitial.left + offsetX); - - ps.update(); - - e.preventDefault(); - e.stopPropagation(); - }); - $('.tui-image-editor-wrap')[0].onwheel = function() { return false; }; - $('.tui-image-editor-wrap').css('height', 'calc(100% - 150px)'); - - $('#fileEditModal').find('.file-name').text('Editing: ' + data.filename); - $('#fileEditModal').modal('show'); - - $('.tui-image-editor-header').hide(); - - $('.file-save-link').css('display', 'none'); - $('.file-save-link').off().click(function(ev) { - var imageBlob; - var imageDataURL; - var imageParams; - var dataUpload = new FormData(); - var blobArray; - var bytePosition; - - ev.preventDefault(); - ev.stopPropagation(); - - if (data['mime-type'] === 'image/png') { - imageParams = { format: 'png' }; - } else { - imageParams = { format: 'jpeg', quality: (data.quality / 100) }; - } - - imageDataURL = imageEditor.toDataURL(imageParams); - imageDataURL = atob(imageDataURL.split(',')[1]); - - blobArray = new Uint8Array(imageDataURL.length); - - for (bytePosition = 0; bytePosition < imageDataURL.length; bytePosition += 1) { - blobArray[bytePosition] = imageDataURL.charCodeAt(bytePosition); - } - - imageBlob = new Blob([blobArray]); - - function closeEditor() { - animateSpinner(null, false); - imageEditor.destroy(); - imageEditor = {}; - $('#tui-image-editor').html(''); - $('#fileEditModal').modal('hide'); - } - - dataUpload.append('image', imageBlob); - animateSpinner(null, true); - $.ajax({ - type: 'POST', - url: '/files/' + data.id + '/update_image', - data: dataUpload, - contentType: false, - processData: false, - success: function(res) { - $('#modal_link' + data.id).parent().html(res.html); - initPreviewModal(); - } - }).done(function() { - closeEditor(); - - }); - if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); - }); - - window.onresize = function() { - imageEditor.ui.resizeEditor(); - }; - } function openPreviewModal(name, url, downloadUrl) { + + /* var modal = $('#filePreviewModal'); updateFabricControls(); $.ajax({ @@ -480,7 +88,7 @@ var FilePreviewModal = (function() { ev.preventDefault(); ev.stopPropagation(); modal.modal('hide'); - preInitImageEditor(data); + //preInitImageEditor(data); }); } else { modal.find('.file-edit-link').css('display', 'none'); @@ -504,7 +112,7 @@ var FilePreviewModal = (function() { error: function() { // TODO } - }); + });*/ } function clearPrevieModal() { @@ -545,7 +153,8 @@ var FilePreviewModal = (function() { } return Object.freeze({ - init: initPreviewModal, - imageEditor: initImageEditor + init: initPreviewModal }); -}(window)); +}()); + +FilePreviewModal.init(); diff --git a/app/assets/javascripts/sitewide/image_editor.js b/app/assets/javascripts/sitewide/image_editor.js new file mode 100644 index 000000000..7dfea2fa8 --- /dev/null +++ b/app/assets/javascripts/sitewide/image_editor.js @@ -0,0 +1,407 @@ +var ImageEditorModal = (function() { + function updateFabricControls() { + fabric.Object.prototype.drawBorders = function(ctx, styleOverride = {}) { + var wh = this._calculateCurrentDimensions(); + var strokeWidth = 1 / this.borderScaleFactor; + var width = wh.x + strokeWidth; + var height = wh.y + strokeWidth; + var drawRotatingPoint = typeof styleOverride.hasRotatingPoint !== 'undefined' + ? styleOverride.hasRotatingPoint : this.hasRotatingPoint; + var hasControls = typeof styleOverride.hasControls !== 'undefined' + ? styleOverride.hasControls : this.hasControls; + var rotatingPointOffset = typeof styleOverride.rotatingPointOffset !== 'undefined' + ? styleOverride.rotatingPointOffset : this.rotatingPointOffset; + var rotateHeight = -height / 2; + ctx.save(); + ctx.strokeStyle = styleOverride.borderColor || this.borderColor; + this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null); + ctx.strokeRect( + -width / 2, + -height / 2, + width, + height + ); + if (drawRotatingPoint && this.isControlVisible('mtr') && hasControls) { + ctx.beginPath(); + ctx.moveTo(0, rotateHeight); + ctx.lineTo(0, rotateHeight - rotatingPointOffset + 10); + ctx.stroke(); + } + ctx.restore(); + return this; + }; + + fabric.Object.prototype.drawControls = function(ctx) { + var rotationImage = 'data:image/png;base64,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'; + var rotate = new Image(); + var rotateLeft; + var rotateTop; + var wh = this._calculateCurrentDimensions(); + var width = wh.x; + var height = wh.y; + var scaleOffset = this.cornerSize; + var left = -(width + scaleOffset) / 2; + var top = -(height + scaleOffset) / 2; + var methodName = this.transparentCorners ? 'stroke' : 'fill'; + + if (!this.hasControls) { + return this; + } + ctx.save(); + ctx.strokeStyle = this.cornerColor; + ctx.fillStyle = this.cornerColor; + if (!this.transparentCorners) { + ctx.strokeStyle = this.cornerStrokeColor; + } + this._setLineDash(ctx, this.cornerDashArray, null); + + // top-left + this._drawControl( + 'tl', + ctx, + methodName, + left, + top + ); + + // top-right + this._drawControl( + 'tr', + ctx, + methodName, + left + width, + top + ); + + // bottom-left + this._drawControl( + 'bl', + ctx, + methodName, + left, + top + height + ); + + // bottom-right + this._drawControl( + 'br', + ctx, + methodName, + left + width, + top + height + ); + + if (!this.get('lockUniScaling')) { + // middle-top + this._drawControl( + 'mt', + ctx, + methodName, + left + width / 2, + top + ); + + // middle-bottom + this._drawControl( + 'mb', + ctx, + methodName, + left + width / 2, + top + height + ); + + // middle-right + this._drawControl( + 'mr', + ctx, + methodName, + left + width, + top + height / 2 + ); + + // middle-left + this._drawControl( + 'ml', + ctx, + methodName, + left, + top + height / 2 + ); + } + // middle-top-rotate + if (this.hasRotatingPoint) { + rotate.src = rotationImage; + rotateLeft = left + width / 2 - 6; + rotateTop = top - this.rotatingPointOffset - 6; + ctx.drawImage(rotate, rotateLeft, rotateTop, 32, 32); + } + ctx.restore(); + + return this; + }; + } + + function preInitImageEditor(data) { + $.ajax({ + url: data['download-url'], + type: 'get', + success: function(responseData) { + var fileUrl = responseData; + initImageEditor(data, fileUrl); + } + }); + } + + function initImageEditor(data, fileUrl) { + var imageEditor; + var ps; + var blackTheme = { + 'common.bi.image': '', + 'common.bisize.width': '0', + 'common.bisize.height': '0', + 'common.backgroundImage': 'none', + 'common.backgroundColor': '#1e1e1e', + 'common.border': '0px', + + // header + 'header.backgroundImage': 'none', + 'header.backgroundColor': 'transparent', + 'header.border': '0px', + + // load button + 'loadButton.backgroundColor': '#fff', + 'loadButton.border': '1px solid #ddd', + 'loadButton.color': '#222', + 'loadButton.fontFamily': '\'Noto Sans\', sans-serif', + 'loadButton.fontSize': '12px', + + // download button + 'downloadButton.backgroundColor': '#fdba3b', + 'downloadButton.border': '1px solid #fdba3b', + 'downloadButton.color': '#fff', + 'downloadButton.fontFamily': '\'Noto Sans\', sans-serif', + 'downloadButton.fontSize': '12px', + + // main icons + 'menu.normalIcon.path': '/images/icon-d.svg', + 'menu.normalIcon.name': 'icon-d', + 'menu.activeIcon.path': '/images/icon-b.svg', + 'menu.activeIcon.name': 'icon-b', + 'menu.disabledIcon.path': '/images/icon-a.svg', + 'menu.disabledIcon.name': 'icon-a', + 'menu.hoverIcon.path': '/images/icon-c.svg', + 'menu.hoverIcon.name': 'icon-c', + 'menu.iconSize.width': '24px', + 'menu.iconSize.height': '24px', + + // submenu primary color + 'submenu.backgroundColor': '#1e1e1e', + 'submenu.partition.color': '#3c3c3c', + + // submenu icons + 'submenu.normalIcon.path': '/images/icon-d.svg', + 'submenu.normalIcon.name': 'icon-d', + 'submenu.activeIcon.path': '/images/icon-c.svg', + 'submenu.activeIcon.name': 'icon-c', + 'submenu.iconSize.width': '32px', + 'submenu.iconSize.height': '32px', + + // submenu labels + 'submenu.normalLabel.color': '#8a8a8a', + 'submenu.normalLabel.fontWeight': 'lighter', + 'submenu.activeLabel.color': '#fff', + 'submenu.activeLabel.fontWeight': 'lighter', + + // checkbox style + 'checkbox.border': '0px', + 'checkbox.backgroundColor': '#fff', + + // range style + 'range.pointer.color': '#fff', + 'range.bar.color': '#666', + 'range.subbar.color': '#d1d1d1', + + 'range.disabledPointer.color': '#414141', + 'range.disabledBar.color': '#282828', + 'range.disabledSubbar.color': '#414141', + + 'range.value.color': '#fff', + 'range.value.fontWeight': 'lighter', + 'range.value.fontSize': '11px', + 'range.value.border': '1px solid #353535', + 'range.value.backgroundColor': '#151515', + 'range.title.color': '#fff', + 'range.title.fontWeight': 'lighter', + + // colorpicker style + 'colorpicker.button.border': '1px solid #1e1e1e', + 'colorpicker.title.color': '#fff' + }; + + animateSpinner(null, true); + imageEditor = new tui.ImageEditor('#tui-image-editor', { + includeUI: { + loadImage: { + path: fileUrl, + name: data.filename + }, + theme: blackTheme, + initMenu: 'draw', + menuBarPosition: 'bottom' + }, + cssMaxWidth: 700, + cssMaxHeight: 500, + selectionStyle: { + cornerSize: 20, + rotatingPointOffset: 70, + borderColor: '#333', + cornerColor: '#333', + cornerStyle: 'circle', + borderScaleFactor: 3 + + }, + usageStatistics: false + }); + + imageEditor.on('image_loaded', () => { + $('.file-save-link').css('display', ''); + animateSpinner(null, false); + }); + + ps = new PerfectScrollbar($('.tui-image-editor-wrap')[0], { wheelSpeed: 0.5 }); + $('#tui-image-editor .tui-image-editor').on('mousewheel', (e) => { + var imageOriginalSize = { + width: imageEditor._graphics.canvasImage.width, + height: imageEditor._graphics.canvasImage.height + }; + var wDelta = e.originalEvent.wheelDelta || e.originalEvent.deltaY; + var imageEditorWindow = e.currentTarget; + var scrollContainer = $('.tui-image-editor-wrap'); + var initWidth = imageEditorWindow.style.width; + var initHeight = imageEditorWindow.style.height; + + var scrollContainerInitial = { + top: scrollContainer.scrollTop(), + left: scrollContainer.scrollLeft(), + height: scrollContainer[0].scrollHeight, + width: scrollContainer[0].scrollWidth + }; + + var mousePosition = { + top: e.clientY - (imageEditorWindow.offsetTop - scrollContainerInitial.top), + left: e.clientX - $(imageEditorWindow).offset().left + }; + + + var newWidth; + var newHeight; + var offsetY; + var offsetX; + if (wDelta > 0) { + newWidth = parseInt(initWidth, 10) * 1.1; + newHeight = parseInt(initHeight, 10) * 1.1; + if (newWidth > imageOriginalSize.width || newHeight > imageOriginalSize.height) { + newWidth = imageOriginalSize.width; + newHeight = imageOriginalSize.height; + } + } else { + newWidth = parseInt(initWidth, 10) * 0.9; + newHeight = parseInt(initHeight, 10) * 0.9; + if (parseInt(imageEditorWindow.dataset.minWidth, 10) * 0.5 > parseInt(newWidth, 10)) { + newWidth = parseInt(imageEditorWindow.dataset.minWidth, 10) * 0.5; + newHeight = parseInt(imageEditorWindow.dataset.minHeight, 10) * 0.5; + } + } + imageEditorWindow.style.width = newWidth + 'px'; + imageEditorWindow.style.height = newHeight + 'px'; + $(imageEditorWindow).find('canvas, .tui-image-editor-canvas-container') + .css('max-width', imageEditorWindow.style.width) + .css('max-height', imageEditorWindow.style.height); + if (imageEditorWindow.dataset.minHeight === undefined) { + imageEditorWindow.dataset.minHeight = initHeight; + imageEditorWindow.dataset.minWidth = initWidth; + } + + offsetY = (scrollContainer[0].scrollHeight - scrollContainerInitial.height) + * (mousePosition.top / scrollContainerInitial.height); + offsetX = (scrollContainer[0].scrollWidth - scrollContainerInitial.width) + * (mousePosition.left / scrollContainerInitial.width); + + scrollContainer.scrollTop(scrollContainerInitial.top + offsetY); + scrollContainer.scrollLeft(scrollContainerInitial.left + offsetX); + + ps.update(); + + e.preventDefault(); + e.stopPropagation(); + }); + $('.tui-image-editor-wrap')[0].onwheel = function() { return false; }; + $('.tui-image-editor-wrap').css('height', 'calc(100% - 150px)'); + + $('#fileEditModal').find('.file-name').text('Editing: ' + data.filename); + $('#fileEditModal').modal('show'); + + $('.tui-image-editor-header').hide(); + + $('.file-save-link').css('display', 'none'); + $('.file-save-link').off().click(function(ev) { + var imageBlob; + var imageDataURL; + var imageParams; + var dataUpload = new FormData(); + var blobArray; + var bytePosition; + + ev.preventDefault(); + ev.stopPropagation(); + + if (data['mime-type'] === 'image/png') { + imageParams = { format: 'png' }; + } else { + imageParams = { format: 'jpeg', quality: (data.quality / 100) }; + } + + imageDataURL = imageEditor.toDataURL(imageParams); + imageDataURL = atob(imageDataURL.split(',')[1]); + + blobArray = new Uint8Array(imageDataURL.length); + + for (bytePosition = 0; bytePosition < imageDataURL.length; bytePosition += 1) { + blobArray[bytePosition] = imageDataURL.charCodeAt(bytePosition); + } + + imageBlob = new Blob([blobArray]); + + function closeEditor() { + animateSpinner(null, false); + imageEditor.destroy(); + imageEditor = {}; + $('#tui-image-editor').html(''); + $('#fileEditModal').modal('hide'); + } + + dataUpload.append('image', imageBlob); + animateSpinner(null, true); + $.ajax({ + type: 'POST', + url: '/files/' + data.id + '/update_image', + data: dataUpload, + contentType: false, + processData: false, + success: function(res) { + $('#modal_link' + data.id).parent().html(res.html); + initPreviewModal(); + } + }).done(function() { + closeEditor(); + + }); + if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); + }); + + window.onresize = function() { + imageEditor.ui.resizeEditor(); + }; + } + +}()); diff --git a/app/assets/javascripts/sitewide/marvinjs_editor.js b/app/assets/javascripts/sitewide/marvinjs_editor.js index 5467d72d6..052591750 100644 --- a/app/assets/javascripts/sitewide/marvinjs_editor.js +++ b/app/assets/javascripts/sitewide/marvinjs_editor.js @@ -166,7 +166,6 @@ var MarvinJsEditorApi = (function() { TinyMCE.updateImages(config.editor); } $(marvinJsModal).modal('hide'); - FilePreviewModal.init(); config.button.dataset.inProgress = false; }).error((response) => { if (response.status === 403) { diff --git a/app/assets/javascripts/sitewide/repository_row_info_modal.js b/app/assets/javascripts/sitewide/repository_row_info_modal.js index af74b1da7..a4d5364fc 100644 --- a/app/assets/javascripts/sitewide/repository_row_info_modal.js +++ b/app/assets/javascripts/sitewide/repository_row_info_modal.js @@ -16,7 +16,6 @@ $(this).find('.modal-body #repository_row-info-table').DataTable().destroy(); $(this).remove(); }); - FilePreviewModal.init(); $('#repository_row-info-table').DataTable({ dom: 'RBltpi', stateSave: false, diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index b562f976e..2f0b27951 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -19,6 +19,25 @@ class AssetsController < ApplicationController before_action :check_edit_permission, only: %i(edit toggle_view_mode) def file_preview + can_edit = if @assoc.class == Step + can_manage_protocol_in_module?(@protocol) || can_manage_protocol_in_repository?(@protocol) + elsif @assoc.class == Result + can_manage_module?(@my_module) + elsif @assoc.class == RepositoryCell && !@repository.is_a?(RepositorySnapshot) + can_manage_repository_rows?(@repository) + end + + render json: {html: render_to_string( + { + partial: "shared/file_preview/content.html.erb", + locals: { + asset: @asset, + can_edit: can_edit + } + } + )} + + return true file_type = @asset.file.metadata[:asset_type] || (@asset.previewable? ? 'previewable' : false) response_json = { 'id' => @asset.id, @@ -28,13 +47,7 @@ class AssetsController < ApplicationController 'download-url' => asset_file_url_path(@asset) } - can_edit = if @assoc.class == Step - can_manage_protocol_in_module?(@protocol) || can_manage_protocol_in_repository?(@protocol) - elsif @assoc.class == Result - can_manage_module?(@my_module) - elsif @assoc.class == RepositoryCell && !@repository.is_a?(RepositorySnapshot) - can_manage_repository_rows?(@repository) - end + if response_json['type'] == 'previewable' if ['image/jpeg', 'image/pjpeg'].include? @asset.file.content_type response_json['quality'] = @asset.file_image_quality || 80 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f83f49d62..e01e1f280 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -46,7 +46,7 @@ <%= render "shared/about_modal" %> - <%= render "shared/file_preview_modal.html.erb" %> + <%= render "shared/file_preview/modal.html.erb" %> <%= render "shared/file_edit_modal.html.erb" %> <%= render "shared/marvinjs_modal.html.erb" %> <%= render "shared/navigation" %> diff --git a/app/views/my_modules/archive.html.erb b/app/views/my_modules/archive.html.erb index 5b5bed9bd..1ccad0796 100644 --- a/app/views/my_modules/archive.html.erb +++ b/app/views/my_modules/archive.html.erb @@ -17,5 +17,3 @@ <% end %> - - diff --git a/app/views/repositories/_repository_row_info_modal.html.erb b/app/views/repositories/_repository_row_info_modal.html.erb index ce9ed0173..4745c5fc6 100644 --- a/app/views/repositories/_repository_row_info_modal.html.erb +++ b/app/views/repositories/_repository_row_info_modal.html.erb @@ -93,7 +93,6 @@ <% end %> <% end %> - diff --git a/app/views/shared/file_preview/_content.html.erb b/app/views/shared/file_preview/_content.html.erb new file mode 100644 index 000000000..0e8c337dc --- /dev/null +++ b/app/views/shared/file_preview/_content.html.erb @@ -0,0 +1,24 @@ + + + diff --git a/app/views/shared/file_preview/_modal.html.erb b/app/views/shared/file_preview/_modal.html.erb new file mode 100644 index 000000000..380010df0 --- /dev/null +++ b/app/views/shared/file_preview/_modal.html.erb @@ -0,0 +1,13 @@ + From d99e279ecc5608dfc3e3eab1023945a5b86336b1 Mon Sep 17 00:00:00 2001 From: aignatov-bio Date: Thu, 22 Oct 2020 13:41:17 +0200 Subject: [PATCH 2/6] Add gallery to file preview --- app/assets/javascripts/protocols/index.js | 1 + .../repositories/repository_datatable.js | 7 - .../javascripts/sitewide/file_preview.js | 158 ++---------------- .../javascripts/sitewide/image_editor.js | 45 +++-- .../javascripts/sitewide/marvinjs_editor.js | 15 +- .../stylesheets/shared/file_preview.scss | 141 ++++++++++++++++ .../shared_styles/elements/buttons.scss | 3 +- app/assets/stylesheets/steps.scss | 6 + app/assets/stylesheets/themes/scinote.scss | 133 --------------- app/controllers/assets_controller.rb | 140 ++++------------ app/permissions/asset.rb | 33 ++++ app/views/assets/_asset.html.erb | 7 +- app/views/assets/_asset_thumbnail.html.erb | 7 +- .../assets/wopi/_file_wopi_controls.html.erb | 22 +-- .../shared/file_preview/_content.html.erb | 96 ++++++++++- .../shared/file_preview/_file_icon.html.erb | 4 + app/views/steps/attachments/_list.html.erb | 2 +- config/locales/en.yml | 3 + 18 files changed, 385 insertions(+), 438 deletions(-) create mode 100644 app/assets/stylesheets/shared/file_preview.scss create mode 100644 app/permissions/asset.rb create mode 100644 app/views/shared/file_preview/_file_icon.html.erb diff --git a/app/assets/javascripts/protocols/index.js b/app/assets/javascripts/protocols/index.js index 99986c960..8453ff040 100644 --- a/app/assets/javascripts/protocols/index.js +++ b/app/assets/javascripts/protocols/index.js @@ -220,6 +220,7 @@ function initProtocolPreviewModal() { modal.modal("show"); ProtocolRepositoryHeader.init(); initHandsOnTable(modalBody); + }, error: function (error) { // TODO } diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 52daf7973..d0698f9fe 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -361,12 +361,6 @@ var RepositoryDatatable = (function(global) { }); } - function disableCheckboxToggleOnAssetDownload() { - $('.file-preview-link').on('click', function(ev) { - ev.stopPropagation(); - }); - } - // Adjust columns width in table header function adjustTableHeader() { TABLE.columns.adjust(); @@ -546,7 +540,6 @@ var RepositoryDatatable = (function(global) { }); }, fnInitComplete: function() { - disableCheckboxToggleOnAssetDownload(); initHeaderTooltip(); disableCheckboxToggleOnCheckboxPreview(); diff --git a/app/assets/javascripts/sitewide/file_preview.js b/app/assets/javascripts/sitewide/file_preview.js index e4ba247ea..20280be98 100644 --- a/app/assets/javascripts/sitewide/file_preview.js +++ b/app/assets/javascripts/sitewide/file_preview.js @@ -1,155 +1,31 @@ /* eslint no-underscore-dangle: ["error", { "allowAfterThis": true }]*/ /* eslint no-use-before-define: ["error", { "functions": false }]*/ /* eslint-disable no-underscore-dangle */ -/* global Uint8Array fabric tui animateSpinner Assets ActiveStoragePreviews - PerfectScrollbar MarvinJsEditor refreshProtocolStatusBar */ - - var FilePreviewModal = (function() { 'use strict'; - //var readOnly = false; - - function initPreviewModal(options = {}) { + function initPreviewModal() { $(document).on('click', '.file-preview-link', function(e) { + var params = {}; + var galleryViewId = $(this).data('gallery-view-id'); e.preventDefault(); - $.get($(this).data('preview-url'), function(result) { + e.stopPropagation(); + params.gallery = $(`.file-preview-link[data-gallery-view-id=${galleryViewId}]`) + .toArray().sort((a, b) => $(a).closest('.step-asset').css('order') - $(b).closest('.step-asset').css('order')) + .map(i => i.dataset.id); + $.get($(this).data('preview-url'), params, function(result) { $('#filePreviewModal .modal-content').html(result.html); $('#filePreviewModal').modal('show'); - }) - }) - //var name; - //var url; - //var downloadUrl; - //readOnly = options.readOnly; - - //return false; - // - //$('.file-preview-link').off('click'); - //$('.file-preview-link').click(function(e) { - // if ($(e.target.offsetParent).hasClass('change-preview-type')) return; - // e.preventDefault(); - // name = $(this).find('.attachment-label').text(); - // url = $(this).data('preview-url'); - // downloadUrl = $(this).attr('href'); - // openPreviewModal(name, url, downloadUrl); - // return true; - //}); - // - //$('#filePreviewModal').find('.preview-close').click(function() { - // $('#filePreviewModal').find('.file-preview-container').html(''); - // $('#filePreviewModal').modal('hide'); - // if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); - //}); - } - - // Adding rotation icon - - - function openPreviewModal(name, url, downloadUrl) { - - /* - var modal = $('#filePreviewModal'); - updateFabricControls(); - $.ajax({ - url: url, - type: 'GET', - dataType: 'json', - success: function(data) { - var link = modal.find('.file-download-link'); - clearPrevieModal(); - if (Object.prototype.hasOwnProperty.call(data, 'wopi-controls')) { - modal.find('.file-wopi-controls').html(data['wopi-controls']); - } - link.attr('href', downloadUrl); - link.attr('data-no-turbolink', true); - link.attr('data-status', 'asset-present'); - if (data.type === 'previewable') { - animateSpinner('.file-preview-container', false); - if (data['wopi-preview-url']) { - modal.find('.file-preview-container') - .html(``); - } else { - modal.find('.file-preview-container') - .append($('') - .css('opacity', 0) - .attr('src', data['large-preview-url']) - .attr('alt', name) - .on('error', ActiveStoragePreviews.reCheckPreview) - .on('load', ActiveStoragePreviews.showPreview) - .click(function(ev) { - ev.stopPropagation(); - })); - } - if (!readOnly && data.editable) { - modal.find('.file-edit-link').css('display', ''); - modal.find('.file-edit-link').off().click(function(ev) { - $.post('/files/' + data.id + '/start_edit_image'); - ev.preventDefault(); - ev.stopPropagation(); - modal.modal('hide'); - //preInitImageEditor(data); - }); - } else { - modal.find('.file-edit-link').css('display', 'none'); - } - } else if (data.type === 'marvinjs') { - openMarvinEditModal(data, modal); - } else { - modal.find('.file-edit-link').css('display', 'none'); - modal.find('.file-preview-container').html(data['preview-icon']); - } - if (readOnly) { - modal.find('#wopi_file_edit_button').remove(); - } - modal.find('.file-name').text(name); - modal.modal(); - modal.find('a[disabled=disabled]').click(function(ev) { - ev.preventDefault(); - }); - $('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1); - }, - error: function() { - // TODO - } - });*/ - } - - function clearPrevieModal() { - var modal = $('#filePreviewModal'); - modal.find('.file-preview-container').empty(); - modal.find('.file-wopi-controls').empty(); - modal.find('.file-edit-link').css('display', 'none'); - } - - function openMarvinEditModal(data, modal) { - modal.find('.file-preview-container') - .append($('') - .css('opacity', 0) - .attr('src', data['large-preview-url']) - .attr('alt', data.name) - .on('error', ActiveStoragePreviews.reCheckPreview) - .on('load', ActiveStoragePreviews.showPreview) - .click(function(ev) { - ev.stopPropagation(); - })); - if (!readOnly && data.editable) { - modal.find('.file-edit-link').css('display', ''); - modal.find('.file-edit-link').off().click(function(ev) { - ev.preventDefault(); - ev.stopPropagation(); - modal.modal('hide'); - $.post(data['update-url'] + '/start_editing'); - MarvinJsEditor.open({ - mode: 'edit', - data: data.description, - name: data.name, - marvinUrl: data['update-url'] - }); }); - } else { - modal.find('.file-edit-link').css('display', 'none'); - } + }); + + $(document).on('click', '#filePreviewModal .gallery-switcher', function(e) { + e.preventDefault(); + e.stopPropagation(); + $.get($(this).attr('href'), { gallery: $(this).data('gallery-elements') }, function(result) { + $('#filePreviewModal .modal-content').html(result.html); + }); + }); } return Object.freeze({ diff --git a/app/assets/javascripts/sitewide/image_editor.js b/app/assets/javascripts/sitewide/image_editor.js index 7dfea2fa8..3be16555e 100644 --- a/app/assets/javascripts/sitewide/image_editor.js +++ b/app/assets/javascripts/sitewide/image_editor.js @@ -1,3 +1,6 @@ +/* global animateSpinner fabric PerfectScrollbar refreshProtocolStatusBar tui Uint8Array*/ +/* eslint-disable no-underscore-dangle */ + var ImageEditorModal = (function() { function updateFabricControls() { fabric.Object.prototype.drawBorders = function(ctx, styleOverride = {}) { @@ -141,17 +144,6 @@ var ImageEditorModal = (function() { }; } - function preInitImageEditor(data) { - $.ajax({ - url: data['download-url'], - type: 'get', - success: function(responseData) { - var fileUrl = responseData; - initImageEditor(data, fileUrl); - } - }); - } - function initImageEditor(data, fileUrl) { var imageEditor; var ps; @@ -389,12 +381,10 @@ var ImageEditorModal = (function() { contentType: false, processData: false, success: function(res) { - $('#modal_link' + data.id).parent().html(res.html); - initPreviewModal(); + $(`.step-asset[data-asset-id=${data.id}]`).replaceWith(res.html); + $(`.step-asset[data-asset-id=${data.id}]`).closest('.attachments').trigger('reorder'); + closeEditor(); } - }).done(function() { - closeEditor(); - }); if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar(); }); @@ -404,4 +394,27 @@ var ImageEditorModal = (function() { }; } + function preInitImageEditor() { + $(document).on('click', '.image-edit-button', function() { + var editButton = $(this); + updateFabricControls(); + $.get(editButton.data('image-url'), function(responseData) { + var fileUrl = responseData; + var data = { + id: editButton.data('image-id'), + quality: editButton.data('image-quality'), + filename: editButton.data('image-name'), + 'mime-type': editButton.data('image-mime-type') + }; + $('#filePreviewModal').modal('hide'); + $.post(editButton.data('start-edit-url')); + initImageEditor(data, fileUrl); + }); + }); + } + + return Object.freeze({ + init: preInitImageEditor + }); }()); +ImageEditorModal.init(); diff --git a/app/assets/javascripts/sitewide/marvinjs_editor.js b/app/assets/javascripts/sitewide/marvinjs_editor.js index 052591750..1bf2f63d3 100644 --- a/app/assets/javascripts/sitewide/marvinjs_editor.js +++ b/app/assets/javascripts/sitewide/marvinjs_editor.js @@ -1,5 +1,4 @@ -/* global TinyMCE, ChemicalizeMarvinJs, MarvinJSUtil, I18n, FilePreviewModal, tinymce */ -/* global Results, Comments */ +/* global TinyMCE, ChemicalizeMarvinJs, MarvinJSUtil, I18n, tinymce, HelperModule */ /* eslint-disable no-param-reassign */ /* eslint-disable wrap-iife */ /* eslint-disable no-use-before-define */ @@ -318,7 +317,17 @@ var MarvinJsEditorApi = (function() { })(); // Initialization - +$(document).on('click', '.marvinjs-edit-button', function() { + var editButton = $(this); + $.post(editButton.data('sketch-start-edit-url')); + $('#filePreviewModal').modal('hide'); + MarvinJsEditor.open({ + mode: 'edit', + data: editButton.data('sketch-description'), + name: editButton.data('sketch-name'), + marvinUrl: editButton.data('update-url') + }); +}); $(document).on('turbolinks:load', function() { MarvinJsEditor = MarvinJsEditorApi(); diff --git a/app/assets/stylesheets/shared/file_preview.scss b/app/assets/stylesheets/shared/file_preview.scss new file mode 100644 index 000000000..3e042b78c --- /dev/null +++ b/app/assets/stylesheets/shared/file_preview.scss @@ -0,0 +1,141 @@ +// scss-lint:disable ImportantRule PropertyUnits NestingDepth SelectorDepth + +// Image preview modal +.modal-file-preview { + background: transparent; + font-size: $font-size-base; + padding: 0 !important; + + .modal-dialog { + background: inherit; + height: 100%; + margin: 0; + padding: 0; + width: 100%; + } + + .modal-content { + background: inherit; + border: 0; + border-radius: 0; + height: auto; + min-height: 100%; + } + + .file-preview-container { + align-items: center; + display: flex; + height: 100%; + justify-content: center; + text-align: center; + width: 100%; + + &.processing { + background-image: url("/images/medium/processing.gif"); + background-position: center; + background-repeat: no-repeat; + } + + .wopi-file-preview { + height: 100%; + width: 100%; + } + + } + + img { + background: url(asset-path("custom/checkerboard-pattern.png")); + height: auto; + max-width: 100%; + + @media (max-height: 520px) { + height: 80%; + max-width: 100%; + } + } + + .modal-header { + align-items: center; + background: $color-white; + display: flex; + height: 4em; + padding: 0 1em; + + .file-name { + font-weight: bold; + margin-right: auto; + } + } + + .modal-body { + align-items: center; + background: transparent; + display: flex; + height: calc(100vh - 8em); + justify-content: center; + overflow: hidden; + padding: 0; + width: 100%; + } + + .modal-footer { + background: $color-white; + height: 4em; + padding: 0 1em; + + .gallery { + align-items: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + height: 100%; + padding: 0 1em; + width: 100%; + + img { + max-height: 2em; + max-width: 2em; + } + + + .file-counter { + font-weight: bold; + grid-column-start: 2; + margin: 0 auto; + } + + .gallery-switcher { + align-items: center; + color: $color-black; + display: flex; + + &:hover { + text-decoration: none; + } + + .file-name { + display: inline-block; + max-width: 16em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + + .fa-angle-right, + .fa-angle-left { + margin: 0 .5em; + } + + &.previous-asset { + grid-column-start: 1; + margin-right: auto; + } + + &.next-asset { + grid-column-start: 3; + margin-left: auto; + } + } + } + } +} diff --git a/app/assets/stylesheets/shared_styles/elements/buttons.scss b/app/assets/stylesheets/shared_styles/elements/buttons.scss index 18f996c98..a3058c2f3 100644 --- a/app/assets/stylesheets/shared_styles/elements/buttons.scss +++ b/app/assets/stylesheets/shared_styles/elements/buttons.scss @@ -16,7 +16,8 @@ transition: .3s; user-select: none; - .fas { + .fas, + img { color: inherit; margin-right: 5px; } diff --git a/app/assets/stylesheets/steps.scss b/app/assets/stylesheets/steps.scss index f93f2a66b..4a6fac336 100644 --- a/app/assets/stylesheets/steps.scss +++ b/app/assets/stylesheets/steps.scss @@ -183,6 +183,12 @@ text-align: center; width: 100%; + &.processing { + background-image: url("/images/medium/processing.gif"); + background-position: center; + background-repeat: no-repeat; + } + img { max-height: 100%; max-width: 100%; diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index 1bc515b94..0be53aa44 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -1458,139 +1458,6 @@ ul.content-activities { } } - -// Image preview modal -.modal-file-preview { - background: transparent; - font-size: $font-size-large; - padding-right: 0 !important; - z-index: 1060; - - .preview-close { - background: transparent; - border: 0; - color: $color-white; - display: inline-block; - float: right; - } - - .file-wopi-controls { - display: inline-block; - - .btn { - margin: 0 15px; - } - } - - .modal-dialog { - height: 100%; - margin: 0; - padding: 0; - width: auto; - } - - .modal-content { - background: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - color: $color-white; - height: 100%; - width: auto; - - .modal-body { - width: 100%; - } - } - - .file-preview-container { - align-items: center; - color: $gray-dark; - display: -moz-flex; - display: -webkit-flex; - display: flex; - height: 100%; - justify-content: center; - text-align: center; - width: 100%; - - &.processing { - background-image: url("/images/medium/processing.gif"); - background-position: center; - background-repeat: no-repeat; - } - - .file-name { - color: $color-black; - margin: 30px 0; - } - - .wopi-file-preview { - border: 0; - height: 100%; - width: 100%; - } - } - - img { - background: url(asset-path("custom/checkerboard-pattern.png")); - height: auto; - max-width: 100%; - - @media (max-height: 520px) { - height: 80%; - max-width: 100%; - } - } - - .modal-header { - background: $color-black; - border: 0; - height: 60px; - line-height: 40px; - text-align: center; - - .file-name { - float: left; - } - } - - .modal-body { - align-items: center; - display: -moz-flex; - display: -webkit-flex; - display: flex; - height: calc(100% - 120px); - justify-content: center; - overflow: hidden; - padding: 0; - } - - .modal-footer { - background: $color-black; - border: 0; - bottom: 0; - height: 60px; - position: absolute; - text-align: center; - width: 100%; - } - - .file-download-link { - color: $color-white; - display: inline-block; - float: right; - margin-right: 20px; - } - - .file-edit-link { - color: $color-white; - display: inline-block; - float: right; - margin-right: 20px; - } -} - // Disable textarea resizing throughout application // (will be done via autosize JS plugin) textarea { diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 2f0b27951..cc34c19f0 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -14,100 +14,21 @@ class AssetsController < ApplicationController include FileIconsHelper include MyModulesHelper + helper_method :wopi_file_edit_button_status + before_action :load_vars, except: :create_wopi_file before_action :check_read_permission, except: :edit before_action :check_edit_permission, only: %i(edit toggle_view_mode) def file_preview - can_edit = if @assoc.class == Step - can_manage_protocol_in_module?(@protocol) || can_manage_protocol_in_repository?(@protocol) - elsif @assoc.class == Result - can_manage_module?(@my_module) - elsif @assoc.class == RepositoryCell && !@repository.is_a?(RepositorySnapshot) - can_manage_repository_rows?(@repository) - end - - render json: {html: render_to_string( - { - partial: "shared/file_preview/content.html.erb", - locals: { - asset: @asset, - can_edit: can_edit - } + render json: { html: render_to_string( + partial: 'shared/file_preview/content.html.erb', + locals: { + asset: @asset, + can_edit: can_manage_asset?(@asset), + gallery: params[:gallery] } - )} - - return true - file_type = @asset.file.metadata[:asset_type] || (@asset.previewable? ? 'previewable' : false) - response_json = { - 'id' => @asset.id, - 'type' => file_type, - 'filename' => truncate(escape_input(@asset.file_name), - length: Constants::FILENAME_TRUNCATION_LENGTH), - 'download-url' => asset_file_url_path(@asset) - } - - - if response_json['type'] == 'previewable' - if ['image/jpeg', 'image/pjpeg'].include? @asset.file.content_type - response_json['quality'] = @asset.file_image_quality || 80 - end - response_json.merge!( - 'editable' => @asset.editable_image? && can_edit, - 'mime-type' => @asset.file.content_type, - 'large-preview-url' => rails_representation_url(@asset.large_preview) - ) - elsif response_json['type'] == 'marvinjs' - response_json.merge!( - 'editable' => can_edit, - 'large-preview-url' => rails_representation_url(@asset.large_preview), - 'update-url' => marvin_js_asset_path(@asset.id), - 'description' => @asset.file.metadata[:description], - 'name' => @asset.file.metadata[:name] - ) - else - - response_json['preview-icon'] = render_to_string(partial: 'shared/file_preview_icon.html.erb', - locals: { asset: @asset }) - end - - if wopi_enabled? && wopi_file?(@asset) - edit_supported, title = wopi_file_edit_button_status - response_json['wopi-preview-url'] = @asset.get_action_url(current_user, 'embedview') - response_json['wopi-controls'] = render_to_string( - partial: 'assets/wopi/file_wopi_controls.html.erb', - locals: { - asset: @asset, - can_edit: can_edit, - edit_supported: edit_supported, - title: title - } - ) - end - respond_to do |format| - format.json do - render json: response_json - end - end - end - - # Check whether the wopi file can be edited and return appropriate response - def wopi_file_edit_button_status - file_ext = @asset.file_name.split('.').last - if Constants::WOPI_EDITABLE_FORMATS.include?(file_ext) - edit_supported = true - title = '' - else - edit_supported = false - title = if Constants::FILE_TEXT_FORMATS.include?(file_ext) - I18n.t('assets.wopi_supported_text_formats_title') - elsif Constants::FILE_TABLE_FORMATS.include?(file_ext) - I18n.t('assets.wopi_supported_table_formats_title') - else - I18n.t('assets.wopi_supported_presentation_formats_title') - end - end - return edit_supported, title + ) } end def toggle_view_mode @@ -139,7 +60,7 @@ class AssetsController < ApplicationController tkn = current_user.get_wopi_token @token = tkn.token @ttl = (tkn.ttl * 1000).to_s - @asset.step&.protocol&.update(updated_at: Time.now) + @asset.step&.protocol&.update(updated_at: Time.zone.now) create_wopi_file_activity(current_user, true) @@ -173,7 +94,7 @@ class AssetsController < ApplicationController @asset.team.release_space(orig_file_size) # Post process file here @asset.post_process_file(@asset.team) - @asset.step&.protocol&.update(updated_at: Time.now) + @asset.step&.protocol&.update(updated_at: Time.zone.now) render_html = if @asset.step || @asset.result render_to_string( @@ -183,7 +104,7 @@ class AssetsController < ApplicationController ) else render_to_string( - partial: 'shared/asset_link', + partial: 'assets/asset_link.html.erb', locals: { asset: @asset, display_image_tag: true }, formats: :html ) @@ -222,7 +143,7 @@ class AssetsController < ApplicationController render_403 && return unless can_manage_protocol_in_module?(step.protocol) || can_manage_protocol_in_repository?(step.protocol) step_asset = StepAsset.create!(step: step, asset: asset) - step.protocol&.update(updated_at: Time.now) + step.protocol&.update(updated_at: Time.zone.now) edit_url = edit_asset_url(step_asset.asset_id) elsif params[:element_type] == 'Result' @@ -270,25 +191,30 @@ class AssetsController < ApplicationController end def check_read_permission - if @assoc.class == Step - render_403 && return unless can_read_protocol_in_module?(@protocol) || - can_read_protocol_in_repository?(@protocol) - elsif @assoc.class == Result - render_403 and return unless can_read_experiment?(@my_module.experiment) - elsif @assoc.class == RepositoryCell - render_403 and return unless can_read_repository?(@repository) - end + render_403 unless can_read_asset?(@asset) end def check_edit_permission - if @assoc.class == Step - render_403 && return unless can_manage_protocol_in_module?(@protocol) || - can_manage_protocol_in_repository?(@protocol) - elsif @assoc.class == Result - render_403 and return unless can_manage_module?(@my_module) - elsif @assoc.class == RepositoryCell - render_403 and return unless can_manage_repository_rows?(@repository) + render_403 unless can_manage_asset?(@asset) + end + + # Check whether the wopi file can be edited and return appropriate response + def wopi_file_edit_button_status(asset) + file_ext = asset.file_name.split('.').last + if Constants::WOPI_EDITABLE_FORMATS.include?(file_ext) + edit_supported = true + title = '' + else + edit_supported = false + title = if Constants::FILE_TEXT_FORMATS.include?(file_ext) + I18n.t('assets.wopi_supported_text_formats_title') + elsif Constants::FILE_TABLE_FORMATS.include?(file_ext) + I18n.t('assets.wopi_supported_table_formats_title') + else + I18n.t('assets.wopi_supported_presentation_formats_title') + end end + return edit_supported, title end def append_wd_params(url) diff --git a/app/permissions/asset.rb b/app/permissions/asset.rb new file mode 100644 index 000000000..6cea35793 --- /dev/null +++ b/app/permissions/asset.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +Canaid::Permissions.register_for(Asset) do + can :read_asset do |user, asset| + object ||= asset.step + object ||= asset.result + object ||= asset.repository_cell + + if object.class == Step + protocol = object.protocol + can_read_protocol_in_module?(user, protocol) || can_read_protocol_in_repository?(user, protocol) + elsif object.class == Result + can_read_experiment?(user, object.my_module.experiment) + elsif object.class == RepositoryCell + can_read_repository?(user, object.repository_column.repository) + end + end + + can :manage_asset do |user, asset| + object ||= asset.step + object ||= asset.result + object ||= asset.repository_cell + + if object.class == Step + protocol = object.protocol + can_manage_protocol_in_module?(user, protocol) || can_manage_protocol_in_repository?(user, protocol) + elsif object.class == Result + can_manage_experiment?(user, object.my_module.experiment) + elsif object.class == RepositoryCell && !object.repository_column.repository.is_a?(RepositorySnapshot) + can_manage_repository?(user, object.repository_column.repository) + end + end +end diff --git a/app/views/assets/_asset.html.erb b/app/views/assets/_asset.html.erb index 8feef8c14..67ab3f91b 100644 --- a/app/views/assets/_asset.html.erb +++ b/app/views/assets/_asset.html.erb @@ -1,7 +1,8 @@ +<% gallery_view_id = nil unless defined? gallery_view_id %> <% if asset.inline? %> - <%= render partial: 'assets/asset_inline.html.erb', locals: { asset: asset } %> + <%= render partial: 'assets/asset_inline.html.erb', locals: { asset: asset, gallery_view_id: gallery_view_id } %> <% elsif asset.list? %> - <%= render partial: 'assets/asset_list.html.erb', locals: { asset: asset } %> + <%= render partial: 'assets/asset_list.html.erb', locals: { asset: asset, gallery_view_id: gallery_view_id } %> <% else %> - <%= render partial: 'assets/asset_thumbnail.html.erb', locals: { edit_page: false, asset: asset } %> + <%= render partial: 'assets/asset_thumbnail.html.erb', locals: { asset: asset, gallery_view_id: gallery_view_id } %> <% end %> diff --git a/app/views/assets/_asset_thumbnail.html.erb b/app/views/assets/_asset_thumbnail.html.erb index b41997fa4..4be1a891c 100644 --- a/app/views/assets/_asset_thumbnail.html.erb +++ b/app/views/assets/_asset_thumbnail.html.erb @@ -7,7 +7,12 @@ <%= link_to rails_blob_path(asset.file, disposition: 'attachment'), class: "file-preview-link", id: "modal_link#{asset.id}", - data: { no_turbolink: true, id: true, 'preview-url': asset_file_preview_path(asset)} do %> + data: { + no_turbolink: true, + id: asset.id, + gallery_view_id: gallery_view_id, + preview_url: asset_file_preview_path(asset) + } do %>
diff --git a/app/views/assets/wopi/_file_wopi_controls.html.erb b/app/views/assets/wopi/_file_wopi_controls.html.erb index 836c91b72..f86e59554 100644 --- a/app/views/assets/wopi/_file_wopi_controls.html.erb +++ b/app/views/assets/wopi/_file_wopi_controls.html.erb @@ -1,28 +1,18 @@ -<%= link_to view_asset_url(id: asset), - id: 'wopi_file_view_button', - class: 'btn btn-default btn-sm', - target: '_blank', - style: 'display: inline-block' do %> - <%= file_application_icon(asset) %> - <%= wopi_button_text(asset, 'view') %> -<% end %> -<% if can_edit && edit_supported %> +<% if edit_supported %> <%= link_to edit_asset_url(id: asset), id: 'wopi_file_edit_button', - class: 'btn btn-default btn-sm', - target: '_blank', - style: 'display: inline-block' do %> + class: 'btn btn-light', + target: '_blank' do %> <%= file_application_icon(asset) %> <%= wopi_button_text(asset, 'edit') %> <% end %> -<% elsif can_edit %> +<% else %> <%= link_to edit_asset_url(id: asset), id: 'wopi_file_edit_button', - class: 'btn btn-default btn-sm', + class: 'btn btn-light', target: '_blank', title: title, - disabled: true, - style: 'display: inline-block' do %> + disabled: true do %> <%= file_application_icon(asset) %> <%= wopi_button_text(asset, 'edit') %> <% end %> diff --git a/app/views/shared/file_preview/_content.html.erb b/app/views/shared/file_preview/_content.html.erb index 0e8c337dc..109a628e9 100644 --- a/app/views/shared/file_preview/_content.html.erb +++ b/app/views/shared/file_preview/_content.html.erb @@ -1,24 +1,102 @@ diff --git a/app/views/shared/file_preview/_file_icon.html.erb b/app/views/shared/file_preview/_file_icon.html.erb new file mode 100644 index 000000000..337f8969e --- /dev/null +++ b/app/views/shared/file_preview/_file_icon.html.erb @@ -0,0 +1,4 @@ +
+ +

+
diff --git a/app/views/steps/attachments/_list.html.erb b/app/views/steps/attachments/_list.html.erb index bf6197811..5d0b71461 100644 --- a/app/views/steps/attachments/_list.html.erb +++ b/app/views/steps/attachments/_list.html.erb @@ -41,7 +41,7 @@
<% assets.each_with_index do |asset, i| %> - <%= render partial: 'assets/asset.html.erb', locals: { asset: asset } %> + <%= render partial: 'assets/asset.html.erb', locals: { asset: asset, gallery_view_id: step.id } %> <% end %>

diff --git a/config/locales/en.yml b/config/locales/en.yml index 7f553010a..523ad9e7d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2283,6 +2283,9 @@ en: errors: forbidden: 'You do not have permission to add files.' not_found: 'Element not found.' + file_preview: + edit_in_scinote: "Edit in SciNote" + edit_in_marvinjs: "Edit in Marvin JS" atwho: no_results: projects: "Projects with this name were not found" From 131d487e6900962162bf4e413af2ced8ed0422fd Mon Sep 17 00:00:00 2001 From: aignatov-bio Date: Mon, 26 Oct 2020 17:16:31 +0100 Subject: [PATCH 3/6] Add file preview to list view --- app/assets/javascripts/sitewide/file_preview.js | 2 +- app/assets/javascripts/sitewide/image_editor.js | 4 ++-- app/controllers/assets_controller.rb | 9 ++++++++- app/views/assets/_asset_inline.html.erb | 7 ++++++- app/views/assets/_asset_list.html.erb | 7 ++++++- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/sitewide/file_preview.js b/app/assets/javascripts/sitewide/file_preview.js index 20280be98..715bcb6d0 100644 --- a/app/assets/javascripts/sitewide/file_preview.js +++ b/app/assets/javascripts/sitewide/file_preview.js @@ -11,7 +11,7 @@ var FilePreviewModal = (function() { e.preventDefault(); e.stopPropagation(); params.gallery = $(`.file-preview-link[data-gallery-view-id=${galleryViewId}]`) - .toArray().sort((a, b) => $(a).closest('.step-asset').css('order') - $(b).closest('.step-asset').css('order')) + .toArray().sort((a, b) => $(a).closest('.asset').css('order') - $(b).closest('.asset').css('order')) .map(i => i.dataset.id); $.get($(this).data('preview-url'), params, function(result) { $('#filePreviewModal .modal-content').html(result.html); diff --git a/app/assets/javascripts/sitewide/image_editor.js b/app/assets/javascripts/sitewide/image_editor.js index 3be16555e..209b73844 100644 --- a/app/assets/javascripts/sitewide/image_editor.js +++ b/app/assets/javascripts/sitewide/image_editor.js @@ -381,8 +381,8 @@ var ImageEditorModal = (function() { contentType: false, processData: false, success: function(res) { - $(`.step-asset[data-asset-id=${data.id}]`).replaceWith(res.html); - $(`.step-asset[data-asset-id=${data.id}]`).closest('.attachments').trigger('reorder'); + $(`.asset[data-asset-id=${data.id}]`).replaceWith(res.html); + $(`.asset[data-asset-id=${data.id}]`).closest('.attachments').trigger('reorder'); closeEditor(); } }); diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index cc34c19f0..15a65ca60 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -34,7 +34,14 @@ class AssetsController < ApplicationController def toggle_view_mode @asset.view_mode = toggle_view_mode_params[:view_mode] if @asset.save(touch: false) - html = render_to_string(partial: 'assets/asset.html.erb', locals: { asset: @asset }) + if @assoc.class == Step + gallery_view_id = @assoc.id + end + + html = render_to_string(partial: 'assets/asset.html.erb', locals: { + asset: @asset, + gallery_view_id: gallery_view_id + }) respond_to do |format| format.json do render json: { html: html }, status: :ok diff --git a/app/views/assets/_asset_inline.html.erb b/app/views/assets/_asset_inline.html.erb index 35415b5a2..9db49bb4f 100644 --- a/app/views/assets/_asset_inline.html.erb +++ b/app/views/assets/_asset_inline.html.erb @@ -9,7 +9,12 @@ <%= link_to rails_blob_path(asset.file, disposition: 'attachment'), class: "file-preview-link file-name", id: "modal_link#{asset.id}", - data: { no_turbolink: true, id: true, 'preview-url': asset_file_preview_path(asset)} do %> + data: { + no_turbolink: true, + id: asset.id, + gallery_view_id: gallery_view_id, + preview_url: asset_file_preview_path(asset) + } do %> <%= asset.file_name %> <% end %>