parse smart annotations in repository export [fixes SCI-2310]

This commit is contained in:
zmagod 2018-04-24 14:53:49 +02:00
parent 1e4a975304
commit 7d26ce561c
8 changed files with 236 additions and 10 deletions

View file

@ -11,12 +11,12 @@ module RepositoryZipExport
zip = ZipExport.create(user: current_user)
zip.generate_exportable_zip(
current_user,
to_csv(ordered_rows, params[:header_ids]),
to_csv(ordered_rows, params[:header_ids], current_user, repository.team),
:repositories
)
end
def self.to_csv(rows, column_ids)
def self.to_csv(rows, column_ids, user, team)
# Parse column names
csv_header = []
column_ids.each do |c_id|
@ -56,7 +56,11 @@ module RepositoryZipExport
else
cell = row.repository_cells
.find_by(repository_column_id: c_id)
cell ? cell.value.formatted : nil
if cell
SmartAnnotations::TagToText.new(
user, team, cell.value.formatted
).text
end
end
end
csv << csv_row

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
module SmartAnnotations
class Preview
class HtmlPreview
class << self
def html(name, type, object)
send("generate_#{type}_snippet", name, object)

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'smart_annotations/permision_eval'
require 'smart_annotations/preview'
require 'smart_annotations/html_preview'
module SmartAnnotations
class TagToHtml
@ -32,7 +32,7 @@ module SmartAnnotations
next unless object && SmartAnnotations::PermissionEval.check(user,
type,
object)
SmartAnnotations::Preview.html(nil, type, object)
SmartAnnotations::HtmlPreview.html(nil, type, object)
end
rescue ActiveRecord::RecordNotFound
next
@ -42,9 +42,9 @@ module SmartAnnotations
def repository_item(name, user, type, object)
if object && SmartAnnotations::PermissionEval.check(user, type, object)
return SmartAnnotations::Preview.html(nil, type, object)
return SmartAnnotations::HtmlPreview.html(nil, type, object)
end
SmartAnnotations::Preview.html(name, type, object)
SmartAnnotations::HtmlPreview.html(name, type, object)
end
def extract_values(element)

View file

@ -0,0 +1,78 @@
# frozen_string_literal: true
require 'smart_annotations/permision_eval'
require 'smart_annotations/text_preview'
module SmartAnnotations
class TagToText
attr_reader :text
def initialize(user, team, text)
parse_items_annotations(user, text)
parse_users_annotations(user, team, @text)
end
private
USER_REGEX = /\[\@(.*?)~([0-9a-zA-Z]+)\]/
ITEMS_REGEX = /\[\#(.*?)~(prj|exp|tsk|rep_item)~([0-9a-zA-Z]+)\]/
OBJECT_MAPPINGS = { prj: Project,
exp: Experiment,
tsk: MyModule,
rep_item: RepositoryRow }.freeze
def parse_items_annotations(user, text)
@text = text.gsub(ITEMS_REGEX) do |el|
value = extract_values(el)
type = value[:object_type]
begin
object = fetch_object(type, value[:object_id])
# handle repository_items edge case
if type == 'rep_item'
repository_item(value[:name], user, type, object)
else
next unless object && SmartAnnotations::PermissionEval.check(user,
type,
object)
SmartAnnotations::TextPreview.text(nil, type, object)
end
rescue ActiveRecord::RecordNotFound
next
end
end
end
def parse_users_annotations(user, team, text)
@text = text.gsub(USER_REGEX) do |el|
match = el.match(USER_REGEX)
user = User.find_by_id(match[2].base62_decode)
next unless user
next if UserTeam.where(user: user, team: team).empty?
user.full_name
end
end
def repository_item(name, user, type, object)
if object && SmartAnnotations::PermissionEval.check(user, type, object)
return SmartAnnotations::TextPreview.text(nil, type, object)
end
SmartAnnotations::TextPreview.text(name, type, object)
end
def extract_values(element)
match = element.match(ITEMS_REGEX)
{
name: match[1],
object_type: match[2],
object_id: match[3].base62_decode
}
end
def fetch_object(type, id)
klass = OBJECT_MAPPINGS.fetch(type.to_sym) do
raise ActiveRecord::RecordNotFound.new("#{type} does not exist")
end
klass.find_by_id(id)
end
end
end

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
module SmartAnnotations
class TextPreview
class << self
def text(name, type, object)
send("generate_#{type}_snippet", name, object)
end
private
ROUTES = Rails.application.routes.url_helpers
def generate_prj_snippet(_, object)
if object.archived?
return "#{object.name} #{I18n.t('atwho.res.archived')}"
end
object.name
end
def generate_exp_snippet(_, object)
if object.archived?
return "#{object.name} #{I18n.t('atwho.res.archived')}"
end
object.name
end
def generate_tsk_snippet(_, object)
if object.archived?
return "#{object.name} #{I18n.t('atwho.res.archived')}"
end
object.name
end
def generate_rep_item_snippet(name, object)
if object
return object.name
end
"#{name} #{I18n.t('atwho.res.deleted')}"
end
end
end
end

View file

@ -1,7 +1,7 @@
require 'rails_helper'
require 'smart_annotations/preview'
require 'smart_annotations/html_preview'
describe SmartAnnotations::Preview do
describe SmartAnnotations::HtmlPreview do
let(:subject) { described_class }
let(:user) { create :user }
let(:project) { create :project, name: 'my project' }

View file

@ -0,0 +1,58 @@
require 'rails_helper'
describe SmartAnnotations::TagToText do
let!(:user) { create :user }
let!(:team) { create :team }
let!(:user_team) { create :user_team, user: user, team: team, role: 2 }
let!(:project) { create :project, name: 'my project', team: team }
let!(:user_project) do
create :user_project, project: project, user: user, role: 0
end
let(:text) do
"My annotation of [#my project~prj~#{project.id.base62_encode}]"
end
let(:subject) { described_class.new(user, team, text) }
describe 'Parsed text' do
it 'returns a existing string with smart annotation' do
expect(subject.text).to eq("My annotation of #{project.name}")
end
end
describe '#extract_values/1' do
it 'returns a parsed hash of smart annotation' do
values = subject.send(:extract_values, '[#my project~prj~1]')
expect(values[:name]).to eq 'my project'
expect(values[:object_id]).to eq 1
expect(values[:object_type]).to eq 'prj'
end
end
describe '#fetch_object/2' do
it 'rises an error if type is not valid' do
expect {
subject.send(:fetch_object, 'banana', project.id)
}.to raise_error(ActiveRecord::RecordNotFound)
end
it 'returns the required object' do
expect(subject.send(:fetch_object, 'prj', project.id)).to eq project
end
end
describe '#parse_users_annotations/2' do
let!(:user_two) { create :user, email: 'test_user@asdf.com' }
let(:text) { "[@#{user.full_name}~#{user.id.base62_encode}]" }
it 'parses the user tokent to text format' do
expect(
subject.send(:parse_users_annotations, user, team, text)
).to eq user.full_name
end
it 'trims the user annotation if user is not member of a team' do
random_text = "Sec:[@#{user_two.full_name}~#{user_two.id.base62_encode}]"
expect(
subject.send(:parse_users_annotations, user, team, random_text)
).to eq "Sec:"
end
end
end

View file

@ -0,0 +1,43 @@
require 'rails_helper'
require 'smart_annotations/text_preview'
describe SmartAnnotations::TextPreview do
let(:subject) { described_class }
let(:user) { create :user }
let(:project) { create :project, name: 'my project' }
let(:experiment) do
create :experiment, name: 'my experiment',
project: project,
created_by: user,
last_modified_by: user
end
let(:task) { create :my_module, name: 'task', experiment: experiment }
describe 'Project annotations' do
it 'returns a text snippet' do
snippet = subject.text(nil, 'prj', project)
expect(snippet).to eq(project.name)
end
end
context 'Experiment annotations' do
it 'returns a text snippet' do
snippet = subject.text(nil, 'exp', experiment)
expect(snippet).to eq(experiment.name)
end
end
context 'MyModule annotations' do
it 'returns a text snippet' do
snippet = subject.text(nil, 'tsk', task)
expect(snippet).to eq(task.name)
end
end
context 'Repository item annotations with type rep_item' do
it 'returns a html snippet' do
snippet = subject.text('my item', 'rep_item', nil)
expect(snippet).to eq('my item (deleted)')
end
end
end