mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-05 22:44:22 +08:00
Merge branch 'master' into ai-sci-3369-activity-for-edited-image-annotation
This commit is contained in:
commit
df344f4d03
19 changed files with 117 additions and 75 deletions
|
@ -452,16 +452,21 @@ function initRecentProtocols() {
|
|||
|
||||
// We use here ajax:success, because we want to check any change on this page
|
||||
$(document).on('ajax:success', () => {
|
||||
var steps = $('.step');
|
||||
var protocolDescription = $('#protocol_description_view').html();
|
||||
if (steps.length === 0 && protocolDescription.length === 0) {
|
||||
recentProtocolContainer.css('display', '');
|
||||
} else {
|
||||
recentProtocolContainer.css('display', 'none');
|
||||
}
|
||||
updateRecentProtocolsStatus();
|
||||
});
|
||||
}
|
||||
|
||||
function updateRecentProtocolsStatus() {
|
||||
var recentProtocolContainer = $('.my-module-recent-protocols');
|
||||
var steps = $('.step');
|
||||
var protocolDescription = $('#protocol_description_view').html();
|
||||
if (steps.length === 0 && protocolDescription.length === 0) {
|
||||
recentProtocolContainer.css('display', '');
|
||||
} else {
|
||||
recentProtocolContainer.css('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes page
|
||||
*/
|
||||
|
|
|
@ -504,10 +504,9 @@
|
|||
$('#new-step-main-tab a')
|
||||
.on('shown.bs.tab', function() {
|
||||
$('#step_name').focus();
|
||||
TinyMCE.init('#step_description_textarea');
|
||||
}).on('hidden.bs.tab', function() {
|
||||
tinyMCE.editors.step_description_textarea.remove();
|
||||
});
|
||||
TinyMCE.init('#step_description_textarea');
|
||||
})
|
||||
|
||||
TinyMCE.init('#step_description_textarea');
|
||||
});
|
||||
|
@ -538,7 +537,7 @@
|
|||
var nameValid = textValidator(ev, $nameInput, 1,
|
||||
<%= Constants::NAME_MAX_LENGTH %>);
|
||||
var $descrTextarea = $form.find("#step_description_textarea");
|
||||
var $tinyMCEInput = TinyMCE.getContent();
|
||||
var $tinyMCEInput = tinyMCE.editors.step_description_textarea.getContent();
|
||||
var descriptionValid = textValidator(ev, $descrTextarea, 0,
|
||||
<%= Constants::RICH_TEXT_MAX_LENGTH %>, false, $tinyMCEInput);
|
||||
var tableNamesValidArray = [];
|
||||
|
@ -579,7 +578,7 @@
|
|||
|
||||
animateSpinner(null, true);
|
||||
var data = DragNDropSteps.appendFilesToForm(ev);
|
||||
data.append('step[description]', TinyMCE.getContent());
|
||||
data.append('step[description]', $tinyMCEInput);
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
method: 'POST',
|
||||
|
@ -614,6 +613,7 @@
|
|||
FilePreviewModal.init();
|
||||
$.initTooltips();
|
||||
if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar();
|
||||
if (typeof updateRecentProtocolsStatus === 'function') updateRecentProtocolsStatus();
|
||||
},
|
||||
error: function(xhr) {
|
||||
if (xhr.responseJSON['assets.file']) {
|
||||
|
|
|
@ -45,7 +45,7 @@ function initializeHandsonTable(el) {
|
|||
formulas: true
|
||||
});
|
||||
el.handsontable("getInstance").loadData(data);
|
||||
el.handsontable("getInstance").sort(3, order);
|
||||
el.handsontable('getInstance').getPlugin('columnSorting').sort(3, order);
|
||||
|
||||
// "Hack" to disable user sorting rows by clicking on
|
||||
// header elements
|
||||
|
|
|
@ -85,6 +85,7 @@ function initInlineEditing(title) {
|
|||
if (inputString.disabled) {
|
||||
saveAllEditFields();
|
||||
editBlock.dataset.editMode = 1;
|
||||
$editBlock.closest('.inline_scroll_block').scrollTop(editBlock.offsetTop);
|
||||
inputString.disabled = false;
|
||||
$inputString.removeClass('hidden');
|
||||
$editBlock.find('.view-mode').addClass('hidden');
|
||||
|
|
|
@ -76,6 +76,7 @@ var Comments = (function() {
|
|||
$el.find('#message').val('');
|
||||
$el.find('.new-comment-button').removeClass('show');
|
||||
newButton.disable = false;
|
||||
$el.find('textarea').focus().blur();
|
||||
})
|
||||
.error((error) => {
|
||||
errorField.html(error.responseJSON.errors.message);
|
||||
|
|
|
@ -43,3 +43,22 @@
|
|||
.mce-top-part {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.mce-widget.mce-btn[aria-label="Restore last draft"] {
|
||||
background: $brand-primary;
|
||||
border-radius: 4px;
|
||||
transition: $md-transaction;
|
||||
|
||||
i {
|
||||
color: $color-white;
|
||||
transition: $md-transaction;
|
||||
}
|
||||
|
||||
&.mce-disabled {
|
||||
background: transparent;
|
||||
|
||||
i {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,6 +144,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Looks like PDF has some specail CSS rules, here is some hack
|
||||
&.report {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 100%;
|
||||
|
||||
.avatar-placehodler {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.content-placeholder {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-edit-mode="0"]:hover,
|
||||
&[data-edit-mode="1"] {
|
||||
.comment-right {
|
||||
|
@ -224,13 +239,16 @@
|
|||
|
||||
.new-comment-button {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin: 8px;
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
position: absolute;
|
||||
right: -36px;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
transition: $md-transaction;
|
||||
width: 26px;
|
||||
|
||||
&.show {
|
||||
right: 0;
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
border: solid 1px;
|
||||
border-color: $color-white;
|
||||
border-radius: 3px;
|
||||
float: left;
|
||||
margin-bottom: 10px;
|
||||
min-height: 100px;
|
||||
padding: 3px;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
border-color: $color-gainsboro;
|
||||
|
|
|
@ -196,16 +196,7 @@ module ApplicationHelper
|
|||
# No more dirty hack
|
||||
def user_avatar_absolute_url(user, style)
|
||||
begin
|
||||
unless missing_avatar(user, style)
|
||||
image = if user.avatar.options[:storage].to_sym == :s3
|
||||
URI.parse(user.avatar.url(style)).open.to_a.join
|
||||
else
|
||||
File.open(user.avatar.path(style)).to_a.join
|
||||
end
|
||||
encoded_data = Base64.strict_encode64(image)
|
||||
avatar_base64 = "data:#{user.avatar_content_type};base64,#{encoded_data}"
|
||||
return avatar_base64
|
||||
end
|
||||
return user.avatar_base64(style) unless missing_avatar(user, style)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error e.message
|
||||
end
|
||||
|
|
|
@ -97,21 +97,8 @@ module ReportsHelper
|
|||
end
|
||||
|
||||
# "Hack" to omit file preview URL because of WKHTML issues
|
||||
def report_image_asset_url(asset, type = :asset, klass = nil)
|
||||
prefix = ''
|
||||
if ENV['PAPERCLIP_STORAGE'].present? &&
|
||||
ENV['MAIL_SERVER_URL'].present? &&
|
||||
ENV['PAPERCLIP_STORAGE'] == 'filesystem'
|
||||
prefix = ENV['MAIL_SERVER_URL']
|
||||
end
|
||||
if !prefix.empty? &&
|
||||
!prefix.include?('http://') &&
|
||||
!prefix.include?('https://')
|
||||
prefix = "http://#{prefix}"
|
||||
end
|
||||
size = type == :tiny_mce_asset ? :large : :medium
|
||||
url = prefix + asset.url(size, timeout: Constants::URL_LONG_EXPIRE_TIME)
|
||||
image_tag(url, class: klass)
|
||||
def report_image_asset_url(asset, _type = :asset, klass = nil)
|
||||
image_tag(asset.generate_base64(:medium), class: klass)
|
||||
end
|
||||
|
||||
# "Hack" to load Glyphicons css directly from the CDN
|
||||
|
|
|
@ -493,6 +493,16 @@ class Asset < ApplicationRecord
|
|||
!locked? && %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES_EDITABLE)}} =~ file.content_type
|
||||
end
|
||||
|
||||
def generate_base64(style)
|
||||
image = if file.options[:storage].to_sym == :s3
|
||||
URI.parse(url(style)).open.to_a.join
|
||||
else
|
||||
File.open(file.path(style)).to_a.join
|
||||
end
|
||||
encoded_data = Base64.strict_encode64(image)
|
||||
"data:#{file_content_type};base64,#{encoded_data}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Checks if attachments is an image (in post processing imagemagick will
|
||||
|
|
|
@ -107,7 +107,7 @@ class TinyMceAsset < ApplicationRecord
|
|||
asset.destroy if asset && !asset.saved
|
||||
end
|
||||
|
||||
def self.update_old_tinymce(description, obj = nil)
|
||||
def self.update_old_tinymce(description, obj = nil, import = false)
|
||||
return description unless description
|
||||
|
||||
description.scan(/\[~tiny_mce_id:(\w+)\]/).flatten.each do |token|
|
||||
|
@ -115,7 +115,8 @@ class TinyMceAsset < ApplicationRecord
|
|||
new_format = "<img src=\"\" class=\"img-responsive\" data-mce-token=\"#{Base62.encode(token.to_i)}\"/>"
|
||||
|
||||
asset = find_by_id(token)
|
||||
unless asset
|
||||
# impor flag only for import from file cases, because we don't have image in DB
|
||||
unless asset || import
|
||||
# remove tag if asset deleted
|
||||
description.sub!(old_format, '')
|
||||
next
|
||||
|
|
|
@ -559,6 +559,22 @@ class User < ApplicationRecord
|
|||
.map { |i| { name: escape_input(i[:full_name]), id: i[:id] } }
|
||||
end
|
||||
|
||||
def avatar_base64(style)
|
||||
unless avatar.present?
|
||||
missing_link = File.open("#{Rails.root}/app/assets/images/#{style}/missing.png").to_a.join
|
||||
return "data:image/png;base64,#{Base64.strict_encode64(missing_link)}"
|
||||
end
|
||||
|
||||
avatar_uri = if avatar.options[:storage].to_sym == :s3
|
||||
URI.parse(avatar.url(style)).open.to_a.join
|
||||
else
|
||||
File.open(avatar.path(style)).to_a.join
|
||||
end
|
||||
|
||||
encoded_data = Base64.strict_encode64(avatar_uri)
|
||||
"data:#{avatar_content_type};base64,#{encoded_data}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def confirmation_required?
|
||||
|
|
|
@ -145,7 +145,7 @@ module ProtocolsImporter
|
|||
def populate_rte(object_json, object, team)
|
||||
return populate_rte_legacy(object_json) unless object_json['descriptionAssets']
|
||||
|
||||
description = TinyMceAsset.update_old_tinymce(object_json['description'])
|
||||
description = TinyMceAsset.update_old_tinymce(object_json['description'], nil, true)
|
||||
object_json['descriptionAssets'].values.each do |tiny_mce_img_json|
|
||||
tiny_mce_img = TinyMceAsset.new(
|
||||
object: object,
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
<%= render partial: "my_modules/protocols/protocol_status_bar.html.erb" %>
|
||||
</div>
|
||||
<%= render partial: "my_modules/protocols/protocol_buttons.html.erb" %>
|
||||
<%= render partial: "my_modules/recent_protocol_dropdown.html.erb", locals: {protocol: @my_module.protocol}%>
|
||||
<% if can_manage_protocol_in_module?(@protocol) %>
|
||||
<%= render partial: "my_modules/recent_protocol_dropdown.html.erb", locals: {protocol: @my_module.protocol}%>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
|
|
@ -18,22 +18,13 @@
|
|||
</div>
|
||||
<div class="report-element-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 comments-container">
|
||||
<div class="col-xs-12 comments-container simple">
|
||||
<% if comments.count == 0 %>
|
||||
<em><%=t "projects.reports.elements.result_comments.no_comments" %></em>
|
||||
<% else %>
|
||||
<ul class="no-style comments-list">
|
||||
<ul class="no-style content-comments">
|
||||
<% comments.each do |comment| %>
|
||||
<% comment_ts = comment.created_at %>
|
||||
<li class="comment" data-ts="<%= comment_ts.to_i %>">
|
||||
<span class="comment-prefix">
|
||||
<em><%=t "projects.reports.elements.result_comments.comment_prefix", user: comment.user.full_name, date: l(comment_ts, format: :full_date), time: l(comment_ts, format: :time) %></em>
|
||||
</span>
|
||||
<span class="comment-message">
|
||||
|
||||
<%= custom_auto_link(comment.message, team: current_team) %>
|
||||
</span>
|
||||
</li>
|
||||
<%= render partial: 'shared/comments/item.html.erb', locals: { comment: comment, readonly: true, report: true } %>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
|
|
@ -18,22 +18,13 @@
|
|||
</div>
|
||||
<div class="report-element-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 comments-container">
|
||||
<div class="col-xs-12 comments-container simple">
|
||||
<% if comments.count == 0 %>
|
||||
<em><%=t "projects.reports.elements.step_comments.no_comments" %></em>
|
||||
<% else %>
|
||||
<ul class="no-style comments-list">
|
||||
<ul class="no-style content-comments">
|
||||
<% comments.each do |comment| %>
|
||||
<% comment_ts = comment.created_at %>
|
||||
<li class="comment" data-ts="<%= comment_ts.to_i %>">
|
||||
<span class="comment-prefix">
|
||||
<em><%=t "projects.reports.elements.step_comments.comment_prefix", user: comment.user.full_name, date: l(comment_ts, format: :full_date), time: l(comment_ts, format: :time) %></em>
|
||||
</span>
|
||||
<span class="comment-message">
|
||||
|
||||
<%= custom_auto_link(comment.message, team: current_team) %>
|
||||
</span>
|
||||
</li>
|
||||
<%= render partial: 'shared/comments/item.html.erb', locals: { comment: comment, readonly: true, report: true } %>`
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="comments-container" data-object-id = <%= object.id %>>
|
||||
<% per_page = Constants::COMMENTS_SEARCH_LIMIT %>
|
||||
<div class="content-comments">
|
||||
<div class="content-comments inline_scroll_block">
|
||||
<% if comments.size == per_page %>
|
||||
<div class="comment-more text-center">
|
||||
<a class="btn btn-default btn-more-comments-new"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<% user_comment = comment.user == current_user %>
|
||||
<% report = false unless defined?(report) %>
|
||||
<% readonly = false unless defined?(readonly) %>
|
||||
<% edit_mode = (comment.user == current_user && !readonly) %>
|
||||
<div
|
||||
class="comment-container <%= user_comment ? 'comment-editable-field' : '' %>"
|
||||
class="comment-container <%= edit_mode ? 'comment-editable-field' : '' %> <%= report ? 'report' : '' %>"
|
||||
data-field-to-update="message"
|
||||
data-params-group="comment"
|
||||
data-path-to-update="<%= comment_action_url(comment) %>"
|
||||
|
@ -10,15 +12,19 @@
|
|||
error="false"
|
||||
>
|
||||
<div class="avatar-placehodler">
|
||||
<span class='global-avatar-container'>
|
||||
<%= image_tag avatar_path(comment.user, :icon_small), class: 'avatar' %>
|
||||
<span class='global-avatar-container'>
|
||||
<% if report %>
|
||||
<%= image_tag comment.user.avatar_base64(:icon_small), class: 'avatar' %>
|
||||
<% else %>
|
||||
<%= image_tag avatar_path(comment.user, :icon_small), class: 'avatar' %>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="content-placeholder">
|
||||
<div class="comment-name"><%= comment.user.full_name %></div>
|
||||
<div class="comment-right">
|
||||
<div class="comment-datetime"><%= l(comment.created_at, format: :full) %></div>
|
||||
<% if user_comment %>
|
||||
<% if edit_mode %>
|
||||
<div class="comment-actions">
|
||||
<div class="edit-buttons">
|
||||
<span class="save-button"><i class="fas fa-save"></i><%= t('general.save') %></span>
|
||||
|
@ -39,7 +45,7 @@
|
|||
</div>
|
||||
<div class="comment-message">
|
||||
<div class="view-mode"><%= custom_auto_link(comment.message, team: current_team, simple_format: true).html_safe %></div>
|
||||
<% if user_comment %>
|
||||
<% if edit_mode %>
|
||||
<%= text_area_tag 'message', comment.message, disabled: true, class: 'smart-text-area hidden' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue