Merge branch 'master' into rails-5.1

Conflicts:
	app/models/repository.rb
	app/models/repository_row.rb
	app/views/projects/index.html.erb
	app/views/shared/_secondary_navigation.html.erb
This commit is contained in:
Luka Murn 2017-07-06 15:12:15 +02:00
commit 9f60ece25f
26 changed files with 394 additions and 64 deletions

View file

@ -47,6 +47,7 @@
// Populate the errors container
$('#import-errors-container').html(data.responseJSON.html);
animateSpinner(null, false);
}
});
}

View file

@ -148,6 +148,7 @@ function dataTableInit() {
data = myData;
}
$.ajax({
async: false,
url: '/repositories/' + repositoryId + '/state_save',
data: {state: data},
dataType: 'json',

View file

@ -76,7 +76,14 @@
Comments.initialize();
initNewResultAsset();
}).on('ajax:error', function(e, xhr) {
$form.renderFormErrors('result', xhr.responseJSON, true, e);
var errors = xhr.responseJSON.errors;
var formInput = $form.find('#result_asset_attributes_file');
$('[data-status="error"]').remove();
$.each(errors, function(key, value) {
var message = '<span data-status="error" style="color: #a94442">';
message += value + '</span>';
formInput.after(message);
})
animateSpinner(null, false);
});
}

View file

@ -46,5 +46,6 @@ $('form#form-import')
// Populate the errors container
$('#import-errors-container').html(data.responseJSON.html);
animateSpinner(null, false);
}
});

View file

@ -583,6 +583,19 @@ a[data-toggle="tooltip"] {
background-color: $color-emperor;
opacity: 0.8;
}
}
.repositories-team {
padding: 10px 15px;
&.active {
color: $color-theme-primary;
}
}
.repository-search {
padding-left: 15px;
}
}

View file

@ -226,18 +226,33 @@ class RepositoriesController < ApplicationController
end
def import_records
import_records = repostiory_import_actions
status = import_records.import!
respond_to do |format|
format.json do
if status[:status] == :ok
flash[:success] = t('repositories.import_records.success_flash',
number_of_rows: status[:nr_of_added])
render json: {}, status: :ok
# Check if there exist mapping for repository record (it's mandatory)
if params[:mappings].value?('-1')
import_records = repostiory_import_actions
status = import_records.import!
if status[:status] == :ok
flash[:success] = t('repositories.import_records.success_flash',
number_of_rows: status[:nr_of_added])
render json: {}, status: :ok
else
flash[:alert] = t('repositories.import_records.error_flash',
message: status[:errors])
render json: {}, status: :unprocessable_entity
end
else
flash[:alert] = t('repositories.import_records.error_flash',
message: status[:errors])
render json: {}, status: :unprocessable_entity
render json: {
html: render_to_string(
partial: 'shared/flash_errors.html.erb',
locals: { error_title: t('repositories.import_records'\
'.error_message.errors_list_title'),
error: t('repositories.import_records.error_message'\
'.no_repository_name') }
)
},
status: :unprocessable_entity
end
end
end

View file

@ -17,6 +17,9 @@ class SearchController < ApplicationController
search_steps if @search_category == :steps
search_checklists if @search_category == :checklists
search_samples if @search_category == :samples
if @search_category == :repositories && params[:repository]
search_repository
end
search_assets if @search_category == :assets
search_tables if @search_category == :tables
search_comments if @search_category == :comments
@ -106,6 +109,39 @@ class SearchController < ApplicationController
whole_phrase: @search_whole_phrase).size
end
def count_by_repository
count_total = 0
search_results = Repository.search(current_user,
true,
@search_query,
Constants::SEARCH_NO_LIMIT,
nil,
match_case: @search_case,
whole_word: @search_whole_word,
whole_phrase: @search_whole_phrase)
@repository_search_count = {}
current_user.teams.includes(:repositories).each do |team|
team_results = {}
team_results[:count] = 0
team_results[:repositories] = {}
team.repositories.each do |repository|
repository_results = {}
repository_results[:id] = repository.id
repository_results[:count] = 0
search_results.each do |result|
if repository.id == result.id
count_total += result.counter
repository_results[:count] += result.counter
end
end
team_results[:repositories][repository.name] = repository_results
team_results[:count] += repository_results[:count]
end
@repository_search_count[team.name] = team_results
end
count_total
end
def count_search_results
@project_search_count = count_by_name Project
@experiment_search_count = count_by_name Experiment
@ -118,6 +154,7 @@ class SearchController < ApplicationController
@step_search_count = count_by_name Step
@checklist_search_count = count_by_name Checklist
@sample_search_count = count_by_name Sample
@repository_search_count_total = count_by_repository
@asset_search_count = count_by_name Asset
@table_search_count = count_by_name Table
@comment_search_count = count_by_name Comment
@ -133,6 +170,7 @@ class SearchController < ApplicationController
@search_results_count += @step_search_count
@search_results_count += @checklist_search_count
@search_results_count += @sample_search_count
@search_results_count += @repository_search_count_total
@search_results_count += @asset_search_count
@search_results_count += @table_search_count
@search_results_count += @comment_search_count
@ -210,6 +248,20 @@ class SearchController < ApplicationController
@search_count = @sample_search_count
end
def search_repository
@repository = Repository.find_by_id(params[:repository])
render_403 unless can_view_repository(@repository)
@repository_results = []
if @repository_search_count_total > 0
@repository_results =
RepositoryRow.search(@repository, @search_query, @search_page,
match_case: @search_case,
whole_word: @search_whole_word,
whole_phrase: @search_whole_phrase)
end
@search_count = @repository_search_count_total
end
def search_assets
@asset_results = []
@asset_results = search_by_name(Asset) if @asset_search_count > 0

View file

@ -225,7 +225,8 @@ module ApplicationHelper
user_name << ' ' + I18n.t('atwho.res.removed') if !user_still_in_team
raw("<img src='#{user_avatar_absolute_url(user, :icon_small)}'" \
"alt='avatar' class='atwho-user-img-popover'>") +
"alt='avatar' class='atwho-user-img-popover'" \
" ref='#{'missing-img' if missing_avatar(user, :icon_small)}'>") +
raw('<a onClick="$(this).popover(\'show\')" ' \
'class="atwho-user-popover" data-container="body" ' \
'data-html="true" tabindex="0" data-trigger="focus" ' \
@ -253,9 +254,14 @@ module ApplicationHelper
end
end
unless user.avatar(style) == '/images/icon_small/missing.png'
unless missing_avatar(user, style)
return user.avatar(style, timeout: Constants::URL_LONG_EXPIRE_TIME)
end
url_for(prefix + "/images/#{style}/missing.png")
end
def missing_avatar(user, style)
user.avatar(style) == '/images/icon_small/missing.png' ||
user.avatar(style) == '/images/thumb/missing.png'
end
end

View file

@ -100,11 +100,17 @@ module ReportsHelper
"<span class=\"label label-#{style}\">#{text}</span>".html_safe
end
def sanitize_report_pdf(text, tags = [], attributes = [])
ActionController::Base.helpers.sanitize(
text,
tags: Constants::WHITELISTED_TAGS + tags,
attributes: Constants::WHITELISTED_ATTRIBUTES + attributes
)
# Fixes issues with avatar images in reports
def fix_smart_annotation_image(html)
html_doc = Nokogiri::HTML(html)
html_doc.search('.atwho-user-popover').each do |el|
text = el.content
el.replace("<a href='#' style='margin-left: 5px'>#{text}</a>")
end
html_doc.search('[ref="missing-img"]').each do |el|
tag = wicked_pdf_image_tag('icon_small/missing.png')
el.replace(tag)
end
html_doc.to_s
end
end

View file

@ -1,10 +1,11 @@
class Repository < ApplicationRecord
include SearchableModel
belongs_to :team, optional: true
belongs_to :created_by,
foreign_key: :created_by_id,
class_name: 'User',
optional: true
has_many :repository_columns
has_many :repository_rows
has_many :repository_table_states,
inverse_of: :repository, dependent: :destroy
@ -18,6 +19,47 @@ class Repository < ApplicationRecord
validates :team, presence: true
validates :created_by, presence: true
def self.search(
user,
_include_archived,
query = nil,
page = 1,
current_team = nil,
options = {}
)
team_ids =
if current_team
current_team.id
else
Team.joins(:user_teams)
.where('user_teams.user_id = ?', user.id)
.distinct
.pluck(:id)
end
row_ids = RepositoryRow
.search(nil, query, Constants::SEARCH_NO_LIMIT, options)
.select(:id)
new_query = Repository
.select('repositories.*, COUNT(repository_rows.id) AS counter')
.joins(:team)
.joins('LEFT OUTER JOIN repository_rows ON ' \
'repositories.id = repository_rows.repository_id')
.where(team: team_ids)
.where('repository_rows.id IN (?)', row_ids)
.group('repositories.id')
# Show all results if needed
if page == Constants::SEARCH_NO_LIMIT
new_query
else
new_query
.limit(Constants::SEARCH_LIMIT)
.offset((page - 1) * Constants::SEARCH_LIMIT)
end
end
def open_spreadsheet(file)
filename = file.original_filename
file_path = file.path

View file

@ -1,4 +1,6 @@
class RepositoryRow < ApplicationRecord
include SearchableModel
belongs_to :repository, optional: true
belongs_to :created_by,
foreign_key: :created_by_id,
@ -19,4 +21,47 @@ class RepositoryRow < ApplicationRecord
presence: true,
length: { maximum: Constants::NAME_MAX_LENGTH }
validates :created_by, presence: true
def self.search(repository, query, page = 1, options)
new_query = distinct
.joins(:created_by)
.joins(
"LEFT OUTER JOIN (
SELECT repository_cells.repository_row_id,
repository_text_values.data AS text_value,
to_char(repository_date_values.data, 'DD.MM.YYYY HH24:MI')
AS date_value
FROM repository_cells
INNER JOIN repository_text_values
ON repository_text_values.id = repository_cells.value_id
FULL OUTER JOIN repository_date_values
ON repository_date_values.id = repository_cells.value_id
) AS values
ON values.repository_row_id = repository_rows.id"
)
.where_attributes_like(
['repository_rows.name', 'users.full_name',
'values.text_value', 'values.date_value'],
query, options
)
if repository
new_query = new_query
.preload(
:repository_columns,
:created_by,
repository_cells: :value
)
.where(repository: repository)
end
# Show all results if needed
if page == Constants::SEARCH_NO_LIMIT
new_query
else
new_query
.limit(Constants::SEARCH_LIMIT)
.offset((page - 1) * Constants::SEARCH_LIMIT)
end
end
end

View file

@ -62,8 +62,8 @@ class UserTeam < ApplicationRecord
end
# Also, make new owner author of all protocols that belong
# to the departing user.
p_ids = user.added_protocols.pluck(:id)
# to the departing user and belong to this team.
p_ids = user.added_protocols.where(team: team).pluck(:id)
Protocol.find(p_ids).each do |protocol|
protocol.record_timestamps = false
protocol.added_by = new_owner

View file

@ -59,7 +59,7 @@
<div class="form-group">
<!-- project archive button -->
<a class="btn btn-default pull-right" href="<%= url_for projects_archive_path %>" id="project-archive-btn" data-turbolinks="false" title="">
<a class="btn btn-default pull-right" href="<%= url_for projects_archive_path %>" id="project-archive-btn" data-turbolinks="false" title="<%= t'projects.index.archive' %>">
<span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span>
</a>

View file

@ -12,7 +12,7 @@
</li>
<li role="presentation" class="<%= "active" if @type == :archive %>">
<%= link_to protocols_path(team: @current_team, type: :archive) do %>
<span class="glyphicon glyphicon-briefcase"></span>
<span class="glyphicon glyphicon-briefcase" title="<%= t'protocols.index.navigation.archive' %>"></span>
<% end %>
</li>
</ul>

View file

@ -10,7 +10,9 @@
<body class="print-report-body">
<div class="print-report">
<% # Also whitelist <img> and <input type="checkbox"> tags %>
<%= sanitize_report_pdf(@html, ['img', 'input'], ['type', 'disabled', 'checked']) %>
<%= sanitize_input(fix_smart_annotation_image(@html),
['img', 'input'],
['type', 'disabled', 'checked']) %>
</div>
</body>
</html>

View file

@ -7,7 +7,7 @@
<%= t("repositories.modal_delete_record.notice") %>
</div>
<div class="modal-body">
<%= t("repositories.modal_delete_record.other_samples") %>
<%= t("repositories.modal_delete_record.other_records") %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" onclick="onClickDeleteRecord();">

View file

@ -43,7 +43,7 @@
<div class="row">
<div class="col-xs-12 col-sm-3 col-md-3" id="search-menu">
<ul class="nav nav-pills nav-stacked nav-stacked-arrow">
<ul class="nav nav-pills nav-stacked nav-stacked-arrow nav-search">
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :projects %>
@ -187,6 +187,7 @@
<%= t'Samples' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :assets %>
@ -226,6 +227,28 @@
<%= t'Comments' %>
</a>
</li>
<% @repository_search_count.each do |team, results| %>
<li class="repositories-team <%= 'active' if results[:count] > 0 %>">
<span class="fa fa-cubes"></span>
<%= t('Repositories_team', team: team) %>
</li>
<% results[:repositories].each do |repository, values| %>
<li role="presentation"
class="
<%= "active" if @search_category == :repositories && @repository.id == values[:id] %>
<%= "disabled" if values[:count] == 0 %> repository-search"
>
<a href="?<%= {category: 'repositories',
repository: values[:id], q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
<span class="badge pull-right"><%= values[:count] %></span>
<%= repository %>
</a>
</li>
<% end %>
<% end %>
</ul>
</div>
@ -272,6 +295,9 @@
<% if @search_category == :samples and @sample_search_count > 0 %>
<%= render 'search/results/samples', search_query: @search_query, results: @sample_results %>
<% end %>
<% if @search_category == :repositories and @repository_search_count_total > 0 %>
<%= render 'search/results/repositories', search_query: @search_query, results: @repository_results, repository: @repository %>
<% end %>
<% if @search_category == :assets and @asset_search_count > 0 %>
<%= render 'search/results/assets', search_query: @search_query, results: @asset_results %>
<% end %>

View file

@ -0,0 +1,51 @@
<% results.each do |repository_row| %>
<h5>
<span class="fa fa-cubes"></span>
<%=t "search.index.repositories.repository_row" %>
<%= highlight repository_row.name, search_query.strip.split(/\s+/) %>
</h5>
<p>
<% repository_row.repository_cells.each do |cell| %>
<span>
<%=t "search.index.repositories.custom_column", column: cell.repository_column.name %>
<%= highlight cell.value.data, search_query.strip.split(/\s+/) %>
</span>
<br>
<% end %>
<span>
<%=t "search.index.repositories.added_on" %>
<%=l repository_row.created_at, format: :full %>
</span>
<br>
<span>
<%=t "search.index.repositories.added_by" %>
<%= highlight repository_row.created_by.full_name, search_query.strip.split(/\s+/) %>
</span>
</p>
<p>
<span>
<%=t "search.index.modules" %>
<% if repository_row.my_modules.any? %>
<% repository_row.my_modules.each_with_index do |mod, i| %>
<%= render partial: "search/results/partials/my_module_text.html.erb",
locals: { my_module: mod, link_to_page: :repositories, repository: repository } %>
<% if i != repository_row.my_modules.count - 1 %>
,&nbsp;
<% end %>
<% end %>
<% else %>
<em><%=t "search.index.repositories.no_modules" %></em>
<% end %>
</span>
<br>
<span>
<%=t "search.index.team" %>
<%= render partial: "search/results/partials/team_text.html.erb",
locals: { team: repository.team } %>
</span>
</p>
<hr>
<% end %>

View file

@ -18,6 +18,10 @@
<%= route_to_other_team samples_my_module_path(my_module),
my_module.experiment.project.team,
text %>
<% when :repositories %>
<%= route_to_other_team repository_my_module_path(my_module, repository),
my_module.experiment.project.team,
text %>
<% when :protocols %>
<%= route_to_other_team protocols_my_module_path(my_module),
my_module.experiment.project.team,

View file

@ -0,0 +1,7 @@
<% if error.present? %>
<div class="alert alert-danger" role="alert">
<div><%= error_title %></div>
<br>
<%= error %>
</div>
<% end %>

View file

@ -9,7 +9,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<%= link_to(root_path, class: 'navbar-brand') do %>
<%= link_to(root_path, class: 'navbar-brand', title: t('nav.label.scinote')) do %>
<%
show_version = !Rails.env.production?
if ENV['NAVBAR_SHOW_VERSION'].present?
@ -32,33 +32,33 @@
<!-- links -->
<ul class="nav navbar-nav">
<li>
<a href="<%= projects_path %>">
<a title="<%= t('nav.label.projects') %>" href="<%= projects_path %>">
<span class="glyphicon glyphicon-home"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.projects') %></span>
</a>
</li>
<% if current_team %>
<li>
<a id="protocol-link" href="<%= protocols_path %>">
<a id="protocol-link" title="<%= t('nav.label.protocols') %>" href="<%= protocols_path %>">
<span class="glyphicon glyphicon-list-alt"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.protocols') %></span>
</a>
</li>
<li>
<a id="repositories-link" href="<%= team_repositories_path(current_team) %>">
<a id="repositories-link" title="<%= t('nav.label.repositories') %>" href="<%= team_repositories_path(current_team) %>">
<i class="fa fa-cubes" aria-hidden="true"></i>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.repositories') %></span>
</a>
</li>
<% else %>
<li class="disabled">
<a id="protocol-link" href="#">
<a id="protocol-link" title="<%= t('nav.label.protocols') %>" href="#">
<span class="glyphicon glyphicon-list-alt"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.protocols') %></span>
</a>
</li>
<li class="disabled">
<a id="repositories-link" href="#">
<a id="repositories-link" title="<%= t('nav.label.repositories') %>" href="#">
<span class="fa fa-cubes"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.repositories') %></span>
</a>
@ -73,7 +73,7 @@
</li>
<% end %>
<li>
<a class="btn-activity" href="<%= activities_path(format: :json) %>" role="button" data-remote="true">
<a class="btn-activity" title="<%= t('nav.label.activities') %>" href="<%= activities_path(format: :json) %>" role="button" data-remote="true">
<span class="glyphicon glyphicon-equalizer"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.activities') %></span>
</a>
@ -88,6 +88,7 @@
<li class="dropdown" id="team-switch">
<a href="#"
class="dropdown-toggle"
title="<%= t('nav.label.teams') %>"
data-toggle="dropdown"
role="button"
aria-haspopup="true"
@ -135,11 +136,13 @@
id="search-ico">
<a href="#"
class="dropdown-toggle"
title="<%= t('nav.label.search') %>"
data-toggle="dropdown"
role="button"
aria-haspopup="true"
aria-expanded="false">
<span class="glyphicon glyphicon-search"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.search') %></span>
</a>
<ul class="dropdown-menu search-dropdown">
<li>
@ -174,12 +177,14 @@
<a href="#"
id="notifications-dropdown"
class="dropdown-toggle"
title="<%= t('nav.label.notifications') %>"
data-toggle="dropdown"
role="button"
aria-haspopup="true"
aria-expanded="false"
data-href="<%= recent_notifications_url(current_user) %>">
<%= fa_icon 'bell'%>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.notifications') %></span>
<span id="count-notifications"
data-href="<%= unseen_notification_url(current_user) %>">
</span>
@ -205,11 +210,13 @@
<a href="#"
id="help-link"
class="dropdown-toggle"
title="<%= t('nav.label.info') %>"
data-toggle="dropdown"
role="button"
aria-haspopup="true"
aria-expanded="false">
<span class="glyphicon glyphicon-info-sign"></span>
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.info') %></span>
</a>
<ul class="dropdown-menu" data-hook="navigation-help-menu">
<li><%= link_to t('nav.help.support'),
@ -234,6 +241,7 @@
<li class="dropdown">
<a href="#"
class="dropdown-toggle"
title="<%= t('nav.label.account') %>"
data-toggle="dropdown"
role="button"
aria-haspopup="true"

View file

@ -101,7 +101,9 @@
<% end %>
<% if can_view_project_archive(@project) then %>
<li id="project-archive-nav-tab" data-turbolinks="false" class="<%= "active" if is_project_archive? %>">
<a href="<%= experiment_archive_project_url(@project) %>"><span class="glyphicon glyphicon-briefcase"></span></a>
<a href="<%= experiment_archive_project_url(@project) %>" title="<%=t "nav2.projects.archive" %>">
<span class="glyphicon glyphicon-briefcase"></span>
</a>
</li>
<% end %>
@ -136,7 +138,9 @@
<% end %>
<% if can_view_experiment_archive(@experiment) then %>
<li id="project-archive-nav-tab" data-turbolinks="false" class="<%= "active" if is_experiment_archive? %>">
<a href="<%= module_archive_experiment_url(@experiment) %>"><span class="glyphicon glyphicon-briefcase"></span></a>
<a href="<%= module_archive_experiment_url(@experiment) %>" title="<%=t "nav2.projects.archive" %>">
<span class="glyphicon glyphicon-briefcase"></span>
</a>
</li>
<% end %>

View file

@ -2,8 +2,8 @@
<div class="center-block center-block-narrow">
<h2>Sign up</h2>
<%= form_for(:user, as: resource_name, url: registration_path(resource_name)) do |f| %>
<div data-hook="sign-up-form-hook">
<%= form_for(:user, as: resource_name, url: registration_path(resource_name), html: { id: "sign-up-form" } ) do |f| %>
<div class="form-group">
<%= f.label :full_name %>
@ -44,7 +44,7 @@
<%= f.submit 'Sign up', class: 'btn btn-primary' %>
</div>
<% end %>
</div>
<%= render 'users/shared/links' %>
</div>

View file

@ -197,7 +197,7 @@ class Constants
#=============================================================================
# Application version
APP_VERSION = '1.11.0'.freeze
APP_VERSION = '1.12.1'.freeze
TEXT_EXTRACT_FILE_TYPES = [
'application/pdf',

View file

@ -75,11 +75,17 @@ en:
activities:
none: "No activities!"
label:
projects: "Projects"
scinote: "sciNote"
projects: "Home"
protocols: "Protocols"
calendar: "Calendar"
activities: "Activities"
repositories: "Repositories"
teams: "Teams"
search: "Search"
notifications: "Notifications"
info: "Info"
account: "Account"
sidebar:
title: "Navigation"
@ -91,6 +97,7 @@ en:
samples: "Samples"
activities: "Activity"
reports: "Reports"
archive: "Archive"
experiments:
canvas: "Overview"
modules:
@ -142,6 +149,12 @@ en:
added_on: "Added on: "
added_by: "Added by: "
custom_field: "%{cf}: "
repositories:
repository_row: "Repository item: "
added_on: "Added on: "
added_by: "Added by: "
custom_column: "%{column}: "
no_modules: "not assigned to any task"
comments:
project: "Project comment"
my_module: "Task comment"
@ -159,6 +172,7 @@ en:
projects:
index:
head_title: "Home"
archive: "Archive"
new: "New project"
visibility_private: "Project is private. Only invited users can see it."
visibility_public: "Project is public. Everybody from the team can see it."
@ -891,7 +905,7 @@ en:
add_new_record: "Add new item"
import_records:
import: 'Import'
success_flash: "%{number_of_rows} new record(s) successfully imported."
success_flash: "%{number_of_rows} new item(s) successfully imported."
error_flash: "Something went wrong: %{message}"
error_message:
temp_file_not_found: "This file could not be found. Your session might expire."
@ -899,6 +913,8 @@ en:
no_data_to_parse: "There's nothing to be parsed."
no_column_name: "Name column is required!"
duplicated_values: "Two or more columns have the same mapping."
errors_list_title: "Items were not imported because one or more errors were found:"
no_repository_name: "Item name is required!"
edit_record: "Edit"
delete_record: "Delete"
save_record: "Save"
@ -913,41 +929,41 @@ en:
view_all_records: "View all items"
view_assigned_records: "View assigned items"
modal_delete_record:
title: "Delete record"
notice: "Are you sure you want to delete the selected records?"
other_samples: "Only records created by you will be deleted."
delete: "Delete records"
title: "Delete items"
notice: "Are you sure you want to delete the selected item(s)?"
other_records: "Only items created by you will be deleted."
delete: "Delete item(s)"
modal_delete_column:
title: "Delete a column"
message: "Are you sure you wish to permanently delete selected column %{column}? This action is irreversible."
alert_heading: "Deleting a column has following consequences:"
alert_line_1: "you will lose information in this column for %{nr} records;"
alert_line_1: "you will lose information in this column for %{nr} item(s);"
alert_line_2: "the column will be deleted for all team members."
delete: "Delete column"
modal_parse:
title: 'Import records'
title: 'Import items'
modal_import:
title: 'Import records'
title: 'Import items'
notice: 'You may upload .csv file (comma separated) or tab separated file (.txt or .tdv) or Excel file (.xls, .xlsx). First row should include header names, followed by rows with sample data.'
upload: 'Upload file'
js:
permission_error: "You don't have permission to edit this record."
not_found_error: "This repository record does not exist."
permission_error: "You don't have permission to edit this item."
not_found_error: "This repository item does not exist."
column_added: "New column was sucessfully created."
empty_column_name: "Please enter column name."
create:
success_flash: "Successfully added record <strong>%{record}</strong> to repository <strong>%{repository}</strong>"
success_flash: "Successfully added item <strong>%{record}</strong> to repository <strong>%{repository}</strong>"
update:
success_flash: "Successfully updated record <strong>%{record}</strong> in repository <strong>%{repository}</strong>"
success_flash: "Successfully updated item <strong>%{record}</strong> in repository <strong>%{repository}</strong>"
destroy:
success_flash: "%{records_number} record(s) successfully deleted."
contains_other_records_flash: "%{records_number} record(s) successfully deleted. %{other_records_number} of the selected record(s) were created by other users and were not deleted."
no_records_selected_flash: "There were no selected records."
no_deleted_records_flash: "No records were deleted. %{other_records_number} of the selected records were created by other users and were not deleted."
assigned_records_flash: "Successfully assigned record(s) <strong>%{records}</strong> to task"
unassigned_records_flash: "Successfully unassigned record(s) <strong>%{records}</strong> from task"
no_records_assigned_flash: "No records were assigned to task"
no_records_unassigned_flash: "No records were unassigned from task"
success_flash: "%{records_number} item(s) successfully deleted."
contains_other_records_flash: "%{records_number} item(s) successfully deleted. %{other_records_number} of the selected item(s) were created by other users and were not deleted."
no_records_selected_flash: "There were no selected items."
no_deleted_records_flash: "No items were deleted. %{other_records_number} of the selected items were created by other users and were not deleted."
assigned_records_flash: "Successfully assigned item(s) <strong>%{records}</strong> to task"
unassigned_records_flash: "Successfully unassigned item(s) <strong>%{records}</strong> from task"
no_records_assigned_flash: "No items were assigned to task"
no_records_unassigned_flash: "No items were unassigned from task"
default_column: 'Name'
samples:
@ -1083,7 +1099,7 @@ en:
empty_file: "You've selected empty file. There's not much to import."
temp_file_failure: "We couldn't create temporary file. Please contact administrator."
no_file_selected: "You didn't select any file."
errors_list_title: "Samples were not imported because one or more errors was found:"
errors_list_title: "Samples were not imported because one or more errors were found:"
list_row: "Row %{row}"
list_error: "%{key}: %{val}"
import_samples:
@ -1139,8 +1155,8 @@ en:
uncomplete_module: "<i>%{user}</i> uncompleted task <strong>%{module}</strong>."
assign_sample: "<i>%{user}</i> assigned sample(s) <strong>%{samples}</strong> to task(s) <strong>%{tasks}</strong>"
unassign_sample: "<i>%{user}</i> unassigned sample(s) <strong>%{samples}</strong> from task(s) <strong>%{tasks}</strong>"
assign_repository_records: "<i>%{user}</i> assigned record(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository to task <strong>%{task}</strong>"
unassign_repository_records: "<i>%{user}</i> unassigned record(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository from task <strong>%{task}</strong>"
assign_repository_records: "<i>%{user}</i> assigned item(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository to task <strong>%{task}</strong>"
unassign_repository_records: "<i>%{user}</i> unassigned item(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository from task <strong>%{task}</strong>"
create_step: "<i>%{user}</i> created Step %{step} <strong>%{step_name}</strong>."
destroy_step: "<i>%{user}</i> deleted Step %{step} <strong>%{step_name}</strong>."
add_comment_to_step: "<i>%{user}</i> commented on Step %{step} <strong>%{step_name}</strong>."
@ -1412,6 +1428,7 @@ en:
navigation:
public: "Public protocols"
private: "Private protocols"
archive: "Archive"
public_description: "Public protocols are visible and can be used by everyone from the team."
private_description: "Private protocols are only visible to you."
create_new: "Create new"
@ -1677,7 +1694,7 @@ en:
sample_annotation_title: "%{user} mentioned you in Column: %{column} of Sample %{sample}"
sample_annotation_message_html: "Sample: %{sample} | Column: %{column}"
repository_annotation_title: "%{user} mentioned you in Column: %{column} of Record %{record} in Repository %{repository}"
repository_annotation_message_html: "Record: %{record} | Column: %{column}"
repository_annotation_message_html: "Item: %{record} | Column: %{column}"
protocol_step_annotation_message_html: "Protocol: %{protocol}"
email_title: "You've received a sciNote notification!"
assign_user_to_team: "<i>%{assigned_user}</i> was added as %{role} to team <strong>%{team}</strong> by <i>%{assigned_by_user}</i>."
@ -1780,6 +1797,7 @@ en:
Tables: "Tables"
Sample: "Sample"
Samples: "Samples"
Repositories_team: "Repositories - %{team}"
Reports: "Reports"
Comments: "Comments"
Step: "Step"

View file

@ -0,0 +1,21 @@
require File.expand_path('app/helpers/database_helper')
include DatabaseHelper
class AddSearchIndexesToRepositories < ActiveRecord::Migration[4.2]
def up
if db_adapter_is? 'PostgreSQL'
if index_exists?(:repository_rows, :name)
remove_index :repository_rows, :name
end
add_gin_index_without_tags :repository_rows, :name
add_gin_index_without_tags :repository_text_values, :data
end
end
def down
if db_adapter_is? 'PostgreSQL'
remove_index :repository_rows, :name
remove_index :repository_text_values, :data
end
end
end