# frozen_string_literal: true module ApplicationHelper include ActionView::Helpers::AssetTagHelper include ActionView::Helpers::UrlHelper include InputSanitizeHelper def module_page? controller_name == 'my_modules' || controller_name == 'my_module_repositories' end def experiment_page? controller_name == 'experiments' end def project_page? controller_name == 'projects' && action_name.in?(%w(show experiment_archive)) end def all_projects_page? controller_name == 'projects' && action_name.in?(%w(index archive)) end def display_tooltip(message, len = Constants::NAME_TRUNCATION_LENGTH) return '' unless message if message.strip.length > len sanitize_input("<div class='modal-tooltip'> \ #{truncate(message.strip, length: len)} \ <span class='modal-tooltiptext'> \ #{message.strip}</span></div>") else truncate(message.strip, length: len) end end def module_repository_page? controller_name == 'my_modules' && !@repository.nil? end def displayable_flash_type?(type) %w(success warning alert error notice).include?(type) end def flash_alert_class(type) case type when 'success' 'alert-success' when 'warning' 'alert-warning' when 'error', 'alert' 'alert-danger' else 'alert-info' end end def flash_icon_class(type) case type when 'error', 'warning' 'fa-exclamation-triangle' else 'fa-check-circle' end end def smart_annotation_notification(options = {}) title = options.fetch(:title) { :title_must_be_present } message = options.fetch(:message) { :message_must_be_present } new_text = options.fetch(:new_text) { :new_text_must_be_present } old_text = options[:old_text] || '' sa_user = /\[\@(.*?)~([0-9a-zA-Z]+)\]/ # fetch user ids from the previous text old_user_ids = [] old_text.gsub(sa_user) do |el| match = el.match(sa_user) old_user_ids << match[2].base62_decode end # fetch user ids from the new text new_user_ids = [] new_text.gsub(sa_user) do |el| match = el.match(sa_user) new_user_ids << match[2].base62_decode end # check if the user has been already mentioned annotated_users = [] new_user_ids.each do |el| annotated_users << el unless old_user_ids.include?(el) end # restrict the list of ids and generate notification annotated_users.uniq.each do |user_id| target_user = User.find_by_id(user_id) next unless target_user generate_annotation_notification(target_user, title, message) end end def generate_annotation_notification(target_user, title, message) notification = Notification.create( type_of: :assignment, title: sanitize_input(title), message: sanitize_input(message) ) UserNotification.create(notification: notification, user: target_user) if target_user.assignments_notification end def custom_link_open_new_tab(text) text.gsub(/\<a /, '<a target=_blank ') end def smart_annotation_parser(text, team = nil, base64_encoded_imgs = false, preview_repository = false) # sometimes happens that the "team" param gets wrong data: "{nil, []}" # so we have to check if the "team" param is kind of Team object team = nil unless team.is_a?(Team) new_text = smart_annotation_filter_resources(text, team, preview_repository: preview_repository) smart_annotation_filter_users(new_text, team, base64_encoded_imgs: base64_encoded_imgs) end # Check if text have smart annotations of resources # and outputs a link to resource def smart_annotation_filter_resources(text, team, preview_repository: false) user = if !defined?(current_user) && @user @user else current_user end team ||= defined?(current_team) ? current_team : nil SmartAnnotations::TagToHtml.new(user, team, text, preview_repository).html end # Check if text have smart annotations of users # and outputs a popover with user information def smart_annotation_filter_users(text, team, base64_encoded_imgs: false) sa_user = /\[\@(.*?)~([0-9a-zA-Z]+)\]/ new_text = text.gsub(sa_user) do |el| match = el.match(sa_user) user = User.find_by_id(match[2].base62_decode) next unless user popover_for_user_name(user, team, false, false, base64_encoded_imgs) end new_text end # Generate smart annotation link for one user object def popover_for_user_name(user, team = nil, skip_user_status = false, skip_avatar = false, base64_encoded_imgs = false) user_still_in_team = user.teams.include?(team) user_description = %(<div class='col-xs-4'> <img src='#{user_avatar_absolute_url(user, :thumb, base64_encoded_imgs)}' alt='thumb'></div><div class='col-xs-8'> <div class='row'><div class='col-xs-9 text-left'><h5> #{user.full_name}</h5></div><div class='col-xs-3 text-right'> <span class='fas fa-times' aria-hidden='true'></span> </div></div><div class='row'><div class='col-xs-12'> <p class='silver'>#{user.email}</p>) if user_still_in_team user_team_assignment = user.user_assignments.find_by(assignable: team) user_description += %(<p> #{I18n.t('atwho.users.popover_html', role: user_team_assignment.user_role.name.capitalize, team: user_team_assignment.assignable.name, time: I18n.l(user_team_assignment.created_at, format: :full_date))} </p></div></div></div>) else user_description += %(<p></p></div></div></div>) end user_name = user.full_name html = if skip_avatar '' else raw("<span class=\"global-avatar-container smart-annotation\">" \ "<img src='#{user_avatar_absolute_url(user, :icon_small, base64_encoded_imgs)}'" \ "alt='avatar' class='atwho-user-img-popover'" \ " ref='#{'missing-img' unless user.avatar.attached?}'></span>") end html = raw(html) + raw('<a onClick="$(this).popover(\'show\')" ' \ 'class="atwho-user-popover" data-container="body" ' \ 'data-html="true" tabindex="0" data-trigger="focus" ' \ 'data-placement="top" data-toggle="popover" data-content="') + raw(user_description) + raw('" >') + user_name + raw('</a>') html << " #{I18n.t('atwho.res.removed')}" unless skip_user_status || user_still_in_team html = '<span class="atwho-user-container">' + html + '</span>' html end # No more dirty hack def user_avatar_absolute_url(user, style, base64_encoded_imgs = false) avatar_link = user.avatar_variant(style) if user.avatar.attached? return user.convert_variant_to_base64(avatar_link) if base64_encoded_imgs avatar_link.processed.service_url(expires_in: Constants::URL_LONG_EXPIRE_TIME) elsif base64_encoded_imgs file_path = Rails.root.join('app', 'assets', *avatar_link.split('/')) encoded_data = File.open(file_path) do |file| Base64.strict_encode64(file.read) end "data:#{avatar_link.split('.').last};base64,#{encoded_data}" else avatar_link end rescue StandardError => e Rails.logger.error e.message 'icon_small/missing.png' end def wopi_enabled? ENV['WOPI_ENABLED'] == 'true' 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 end