2017-06-06 23:35:29 +08:00
|
|
|
class RepositoryRowsController < ApplicationController
|
|
|
|
include InputSanitizeHelper
|
|
|
|
include ActionView::Helpers::TextHelper
|
|
|
|
include ApplicationHelper
|
|
|
|
|
2018-02-27 23:21:46 +08:00
|
|
|
before_action :load_info_modal_vars, only: :show
|
2017-06-06 23:35:29 +08:00
|
|
|
before_action :load_vars, only: %i(edit update)
|
2018-04-11 23:17:19 +08:00
|
|
|
before_action :load_repository,
|
2018-05-16 15:31:19 +08:00
|
|
|
only: %i(create
|
|
|
|
delete_records
|
|
|
|
index
|
|
|
|
copy_records
|
|
|
|
available_rows)
|
2017-06-06 23:35:29 +08:00
|
|
|
before_action :check_create_permissions, only: :create
|
2018-04-11 23:17:19 +08:00
|
|
|
before_action :check_manage_permissions,
|
|
|
|
only: %i(edit update delete_records copy_records)
|
2017-06-06 23:35:29 +08:00
|
|
|
|
2018-03-06 23:32:39 +08:00
|
|
|
def index
|
|
|
|
@draw = params[:draw].to_i
|
|
|
|
per_page = params[:length] == '-1' ? 100 : params[:length].to_i
|
|
|
|
page = (params[:start].to_i / per_page) + 1
|
|
|
|
records = RepositoryDatatableService.new(@repository,
|
|
|
|
params,
|
2018-03-09 00:36:10 +08:00
|
|
|
current_user)
|
|
|
|
@assigned_rows = records.assigned_rows
|
2018-03-06 23:32:39 +08:00
|
|
|
@repository_row_count = records.repository_rows.count
|
2018-03-09 21:22:00 +08:00
|
|
|
@columns_mappings = records.mappings
|
2018-03-06 23:32:39 +08:00
|
|
|
@repository_rows = records.repository_rows.page(page).per(per_page)
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def create
|
2017-06-07 19:36:39 +08:00
|
|
|
record = RepositoryRow.new(repository: @repository,
|
2017-06-06 23:35:29 +08:00
|
|
|
created_by: current_user,
|
|
|
|
last_modified_by: current_user)
|
|
|
|
errors = { default_fields: [],
|
2017-06-07 19:36:39 +08:00
|
|
|
repository_cells: [] }
|
2017-06-06 23:35:29 +08:00
|
|
|
|
|
|
|
record.transaction do
|
2018-04-13 23:21:17 +08:00
|
|
|
record.name = record_params[:repository_row_name] unless record_params[:repository_row_name].blank?
|
2017-07-26 17:22:26 +08:00
|
|
|
errors[:default_fields] = record.errors.messages unless record.save
|
2017-12-20 00:53:45 +08:00
|
|
|
if cell_params
|
|
|
|
cell_params.each do |key, value|
|
2018-04-16 20:10:49 +08:00
|
|
|
next if create_cell_value(record, key, value, errors).nil?
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
end
|
2017-06-22 23:26:11 +08:00
|
|
|
raise ActiveRecord::Rollback if errors[:repository_cells].any?
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
2017-06-22 23:26:11 +08:00
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
respond_to do |format|
|
|
|
|
format.json do
|
2017-06-14 19:09:23 +08:00
|
|
|
if errors[:default_fields].empty? && errors[:repository_cells].empty?
|
|
|
|
render json: { id: record.id,
|
|
|
|
flash: t('repositories.create.success_flash',
|
|
|
|
record: escape_input(record.name),
|
|
|
|
repository: escape_input(@repository.name)) },
|
|
|
|
status: :ok
|
|
|
|
else
|
|
|
|
render json: errors,
|
|
|
|
status: :bad_request
|
|
|
|
end
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-27 23:21:46 +08:00
|
|
|
def show
|
|
|
|
respond_to do |format|
|
|
|
|
format.json do
|
|
|
|
render json: {
|
|
|
|
html: render_to_string(
|
|
|
|
partial: 'repositories/repository_row_info_modal.html.erb'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def edit
|
|
|
|
json = {
|
|
|
|
repository_row: {
|
|
|
|
name: escape_input(@record.name),
|
2018-03-15 22:43:16 +08:00
|
|
|
repository_cells: {},
|
|
|
|
repository_column_items: fetch_columns_list_items
|
2017-06-06 23:35:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Add custom cells ids as key (easier lookup on js side)
|
|
|
|
@record.repository_cells.each do |cell|
|
2018-04-13 23:21:17 +08:00
|
|
|
if cell.value_type == 'RepositoryAssetValue'
|
2018-06-29 22:59:26 +08:00
|
|
|
cell_value = cell.value.asset
|
2018-04-13 23:21:17 +08:00
|
|
|
else
|
|
|
|
cell_value = escape_input(cell.value.data)
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
json[:repository_row][:repository_cells][cell.repository_column_id] = {
|
|
|
|
repository_cell_id: cell.id,
|
2018-07-03 21:25:37 +08:00
|
|
|
cell_column_id: cell.repository_column.id, # needed for mappings
|
2018-04-13 23:21:17 +08:00
|
|
|
value: cell_value,
|
2018-03-15 22:43:16 +08:00
|
|
|
type: cell.value_type,
|
|
|
|
list_items: fetch_list_items(cell)
|
2017-06-06 23:35:29 +08:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
respond_to do |format|
|
|
|
|
format.html
|
|
|
|
format.json { render json: json }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def update
|
|
|
|
errors = {
|
|
|
|
default_fields: [],
|
2017-06-07 19:36:39 +08:00
|
|
|
repository_cells: []
|
2017-06-06 23:35:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@record.transaction do
|
2018-04-13 23:21:17 +08:00
|
|
|
@record.name = record_params[:repository_row_name].blank? ? nil : record_params[:repository_row_name]
|
2017-07-26 17:22:26 +08:00
|
|
|
errors[:default_fields] = @record.errors.messages unless @record.save
|
2017-12-20 00:53:45 +08:00
|
|
|
if cell_params
|
|
|
|
cell_params.each do |key, value|
|
2017-06-06 23:35:29 +08:00
|
|
|
existing = @record.repository_cells.detect do |c|
|
|
|
|
c.repository_column_id == key.to_i
|
|
|
|
end
|
|
|
|
if existing
|
|
|
|
# Cell exists and new value present, so update value
|
2018-03-15 22:43:16 +08:00
|
|
|
if existing.value_type == 'RepositoryListValue'
|
|
|
|
item = RepositoryListItem.where(
|
|
|
|
repository_column: existing.repository_column
|
|
|
|
).find(value) unless value == '-1'
|
|
|
|
if item
|
2018-03-16 19:27:19 +08:00
|
|
|
existing.value.update_attribute(
|
|
|
|
:repository_list_item_id, item.id
|
|
|
|
)
|
2018-03-15 22:43:16 +08:00
|
|
|
else
|
|
|
|
existing.delete
|
|
|
|
end
|
2018-04-13 23:21:17 +08:00
|
|
|
elsif existing.value_type == 'RepositoryAssetValue'
|
2018-08-21 22:46:47 +08:00
|
|
|
existing.value.destroy && next if remove_file_columns_params.include?(key)
|
2018-04-13 23:21:17 +08:00
|
|
|
if existing.value.asset.update(file: value)
|
|
|
|
existing.value.asset.created_by = current_user
|
|
|
|
existing.value.asset.last_modified_by = current_user
|
|
|
|
existing.value.asset.post_process_file(current_team)
|
|
|
|
else
|
|
|
|
errors[:repository_cells] << {
|
|
|
|
"#{existing.repository_column_id}": { data: existing.value.asset.errors.messages[:file].first }
|
|
|
|
}
|
|
|
|
end
|
2017-06-14 19:09:23 +08:00
|
|
|
else
|
2018-08-07 17:47:26 +08:00
|
|
|
existing.value.destroy && next if value == ''
|
2018-03-15 22:43:16 +08:00
|
|
|
existing.value.data = value
|
|
|
|
if existing.value.save
|
|
|
|
record_annotation_notification(@record, existing)
|
|
|
|
else
|
|
|
|
errors[:repository_cells] << {
|
|
|
|
"#{existing.repository_column_id}":
|
|
|
|
existing.value.errors.messages
|
|
|
|
}
|
|
|
|
end
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
else
|
2018-08-07 17:47:26 +08:00
|
|
|
next if value == ''
|
2017-06-06 23:35:29 +08:00
|
|
|
# Looks like it is a new cell, so we need to create new value, cell
|
|
|
|
# will be created automatically
|
2018-04-16 20:10:49 +08:00
|
|
|
next if create_cell_value(@record, key, value, errors).nil?
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
@record.repository_cells.each { |c| c.value.destroy }
|
|
|
|
end
|
2017-06-22 23:29:17 +08:00
|
|
|
raise ActiveRecord::Rollback if errors[:repository_cells].any?
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
respond_to do |format|
|
|
|
|
format.json do
|
2017-06-14 19:09:23 +08:00
|
|
|
if errors[:default_fields].empty? && errors[:repository_cells].empty?
|
|
|
|
# Row sucessfully updated, so sending response to client
|
|
|
|
render json: {
|
|
|
|
id: @record.id,
|
|
|
|
flash: t(
|
|
|
|
'repositories.update.success_flash',
|
|
|
|
record: escape_input(@record.name),
|
|
|
|
repository: escape_input(@repository.name)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
status: :ok
|
|
|
|
else
|
|
|
|
# Errors
|
|
|
|
render json: errors,
|
|
|
|
status: :bad_request
|
|
|
|
end
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-16 20:10:49 +08:00
|
|
|
def create_cell_value(record, key, value, errors)
|
|
|
|
column = @repository.repository_columns.detect do |c|
|
|
|
|
c.id == key.to_i
|
|
|
|
end
|
2018-07-03 21:25:37 +08:00
|
|
|
|
2018-05-21 20:46:30 +08:00
|
|
|
save_successful = false
|
2018-04-16 20:10:49 +08:00
|
|
|
if column.data_type == 'RepositoryListValue'
|
|
|
|
return if value == '-1'
|
2018-05-21 20:46:30 +08:00
|
|
|
# check if item exists else revert the transaction
|
2018-04-16 20:10:49 +08:00
|
|
|
list_item = RepositoryListItem.where(repository_column: column)
|
|
|
|
.find(value)
|
|
|
|
cell_value = RepositoryListValue.new(
|
|
|
|
repository_list_item_id: list_item.id,
|
|
|
|
created_by: current_user,
|
|
|
|
last_modified_by: current_user,
|
|
|
|
repository_cell_attributes: {
|
|
|
|
repository_row: record,
|
|
|
|
repository_column: column
|
|
|
|
}
|
|
|
|
)
|
2018-05-21 20:46:30 +08:00
|
|
|
save_successful = list_item && cell_value.save
|
2018-04-16 20:10:49 +08:00
|
|
|
elsif column.data_type == 'RepositoryAssetValue'
|
2018-05-21 20:46:30 +08:00
|
|
|
return if value.blank?
|
2018-04-16 20:10:49 +08:00
|
|
|
asset = Asset.new(file: value,
|
|
|
|
created_by: current_user,
|
|
|
|
last_modified_by: current_user,
|
|
|
|
team: current_team)
|
|
|
|
if asset.save
|
|
|
|
asset.post_process_file(current_team)
|
|
|
|
else
|
|
|
|
errors[:repository_cells] << {
|
|
|
|
"#{column.id}": { data: asset.errors.messages[:file].first }
|
|
|
|
}
|
|
|
|
end
|
|
|
|
cell_value = RepositoryAssetValue.new(
|
|
|
|
asset: asset,
|
|
|
|
created_by: current_user,
|
|
|
|
last_modified_by: current_user,
|
|
|
|
repository_cell_attributes: {
|
|
|
|
repository_row: record,
|
|
|
|
repository_column: column
|
|
|
|
}
|
|
|
|
)
|
2018-05-21 20:46:30 +08:00
|
|
|
save_successful = cell_value.save
|
2018-04-16 20:10:49 +08:00
|
|
|
else
|
|
|
|
cell_value = RepositoryTextValue.new(
|
|
|
|
data: value,
|
|
|
|
created_by: current_user,
|
|
|
|
last_modified_by: current_user,
|
|
|
|
repository_cell_attributes: {
|
|
|
|
repository_row: record,
|
|
|
|
repository_column: column
|
|
|
|
}
|
|
|
|
)
|
2018-05-21 20:46:30 +08:00
|
|
|
if (save_successful = cell_value.save)
|
|
|
|
record_annotation_notification(record,
|
|
|
|
cell_value.repository_cell)
|
|
|
|
end
|
2018-04-16 20:10:49 +08:00
|
|
|
end
|
2018-05-21 20:46:30 +08:00
|
|
|
|
|
|
|
unless save_successful
|
2018-04-16 20:10:49 +08:00
|
|
|
errors[:repository_cells] << {
|
|
|
|
"#{column.id}": cell_value.errors.messages
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def delete_records
|
|
|
|
deleted_count = 0
|
2017-12-20 00:53:45 +08:00
|
|
|
if selected_params
|
|
|
|
selected_params.each do |row_id|
|
2017-06-06 23:35:29 +08:00
|
|
|
row = @repository.repository_rows.find_by_id(row_id)
|
2018-04-03 02:48:44 +08:00
|
|
|
if row && can_manage_repository_rows?(@repository.team)
|
2017-06-06 23:35:29 +08:00
|
|
|
row.destroy && deleted_count += 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if deleted_count.zero?
|
2017-06-16 23:12:04 +08:00
|
|
|
flash = t('repositories.destroy.no_deleted_records_flash',
|
2017-12-20 00:53:45 +08:00
|
|
|
other_records_number: selected_params.count)
|
|
|
|
elsif deleted_count != selected_params.count
|
|
|
|
not_deleted_count = selected_params.count - deleted_count
|
2017-06-06 23:35:29 +08:00
|
|
|
flash = t('repositories.destroy.contains_other_records_flash',
|
|
|
|
records_number: deleted_count,
|
|
|
|
other_records_number: not_deleted_count)
|
|
|
|
else
|
|
|
|
flash = t('repositories.destroy.success_flash',
|
|
|
|
records_number: deleted_count)
|
|
|
|
end
|
|
|
|
respond_to do |format|
|
2017-06-16 23:12:04 +08:00
|
|
|
color = deleted_count.zero? ? 'info' : 'success'
|
|
|
|
format.json { render json: { flash: flash, color: color }, status: :ok }
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
else
|
|
|
|
respond_to do |format|
|
|
|
|
format.json do
|
|
|
|
render json: {
|
|
|
|
flash: t('repositories.destroy.no_records_selected_flash')
|
|
|
|
}, status: :bad_request
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-11 23:17:19 +08:00
|
|
|
def copy_records
|
2018-04-13 17:47:33 +08:00
|
|
|
duplicate_service = RepositoryActions::DuplicateRows.new(
|
|
|
|
current_user, @repository, params[:selected_rows]
|
|
|
|
)
|
2018-04-11 23:17:19 +08:00
|
|
|
duplicate_service.call
|
|
|
|
render json: {
|
|
|
|
flash: t('repositories.copy_records_report',
|
|
|
|
number: duplicate_service.number_of_duplicated_items)
|
|
|
|
}, status: :ok
|
|
|
|
end
|
|
|
|
|
2018-05-16 15:31:19 +08:00
|
|
|
def available_rows
|
|
|
|
if @repository.repository_rows.empty?
|
|
|
|
no_items_string =
|
|
|
|
"#{t('projects.reports.new.save_PDF_to_inventory_modal.no_items')} " \
|
|
|
|
"#{link_to(t('projects.reports.new.save_PDF_to_inventory_modal.here'),
|
|
|
|
repository_path(@repository),
|
|
|
|
data: { 'no-turbolink' => true })}"
|
|
|
|
render json: { no_items: no_items_string },
|
|
|
|
status: :ok
|
|
|
|
else
|
|
|
|
render json: { results: load_available_rows(search_params[:q]) },
|
|
|
|
status: :ok
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
private
|
|
|
|
|
2018-05-16 15:31:19 +08:00
|
|
|
include StringUtility
|
|
|
|
AvailableRepositoryRow = Struct.new(:id, :name, :has_file_attached)
|
|
|
|
|
2018-02-27 23:21:46 +08:00
|
|
|
def load_info_modal_vars
|
2018-03-02 21:14:27 +08:00
|
|
|
@repository_row = RepositoryRow.eager_load(:created_by, repository: [:team])
|
2018-03-02 21:16:31 +08:00
|
|
|
.find_by_id(params[:id])
|
2018-03-02 21:14:27 +08:00
|
|
|
@assigned_modules = MyModuleRepositoryRow.eager_load(
|
|
|
|
my_module: [{ experiment: :project }]
|
|
|
|
).where(repository_row: @repository_row)
|
|
|
|
render_404 and return unless @repository_row
|
|
|
|
render_403 unless can_read_team?(@repository_row.repository.team)
|
2018-02-27 23:21:46 +08:00
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def load_vars
|
|
|
|
@repository = Repository.eager_load(:repository_columns)
|
|
|
|
.find_by_id(params[:repository_id])
|
|
|
|
@record = RepositoryRow.eager_load(:repository_columns)
|
|
|
|
.find_by_id(params[:id])
|
|
|
|
render_404 unless @repository && @record
|
|
|
|
end
|
|
|
|
|
|
|
|
def load_repository
|
|
|
|
@repository = Repository.find_by_id(params[:repository_id])
|
|
|
|
render_404 unless @repository
|
2018-03-06 23:32:39 +08:00
|
|
|
render_403 unless can_read_team?(@repository.team)
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def check_create_permissions
|
2018-02-19 21:47:36 +08:00
|
|
|
render_403 unless can_create_repository_rows?(@repository.team)
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
|
2018-02-16 01:46:29 +08:00
|
|
|
def check_manage_permissions
|
2018-04-03 02:48:44 +08:00
|
|
|
render_403 unless can_manage_repository_rows?(@repository.team)
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def record_params
|
2018-04-13 23:21:17 +08:00
|
|
|
params.permit(:repository_row_name).to_h
|
2017-12-20 00:53:45 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def cell_params
|
|
|
|
params.permit(repository_cells: {}).to_h[:repository_cells]
|
|
|
|
end
|
|
|
|
|
2018-08-21 22:46:47 +08:00
|
|
|
def remove_file_columns_params
|
|
|
|
JSON.parse(params.fetch(:remove_file_columns) { '[]' })
|
|
|
|
end
|
|
|
|
|
2017-12-20 00:53:45 +08:00
|
|
|
def selected_params
|
|
|
|
params.permit(selected_rows: []).to_h[:selected_rows]
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|
|
|
|
|
2018-05-16 15:31:19 +08:00
|
|
|
def load_available_rows(query)
|
|
|
|
@repository.repository_rows
|
|
|
|
.includes(:repository_cells)
|
|
|
|
.name_like(search_params[:q])
|
|
|
|
.limit(Constants::SEARCH_LIMIT)
|
|
|
|
.select(:id, :name)
|
|
|
|
.collect do |row|
|
|
|
|
with_asset_cell = row.repository_cells.where(
|
|
|
|
'repository_cells.repository_column_id = ?',
|
|
|
|
search_params[:repository_column_id]
|
|
|
|
)
|
|
|
|
AvailableRepositoryRow.new(row.id,
|
2018-05-17 17:21:34 +08:00
|
|
|
ellipsize(row.name, 75, 50),
|
2018-05-16 15:31:19 +08:00
|
|
|
with_asset_cell.present?)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def search_params
|
|
|
|
params.permit(:q, :repository_id, :repository_column_id)
|
|
|
|
end
|
|
|
|
|
2017-06-06 23:35:29 +08:00
|
|
|
def record_annotation_notification(record, cell, old_text = nil)
|
|
|
|
table_url = params.fetch(:request_url) { :request_url_must_be_present }
|
|
|
|
smart_annotation_notification(
|
|
|
|
old_text: (old_text if old_text),
|
|
|
|
new_text: cell.value.data,
|
|
|
|
title: t('notifications.repository_annotation_title',
|
|
|
|
user: current_user.full_name,
|
|
|
|
column: cell.repository_column.name,
|
|
|
|
record: record.name,
|
|
|
|
repository: record.repository),
|
|
|
|
message: t('notifications.repository_annotation_message_html',
|
|
|
|
record: link_to(record.name, table_url),
|
|
|
|
column: link_to(cell.repository_column.name, table_url))
|
|
|
|
)
|
|
|
|
end
|
2018-03-15 22:43:16 +08:00
|
|
|
|
|
|
|
def fetch_list_items(cell)
|
|
|
|
return [] if cell.value_type != 'RepositoryListValue'
|
|
|
|
RepositoryListItem.where(repository: @repository)
|
|
|
|
.where(repository_column: cell.repository_column)
|
|
|
|
.limit(Constants::SEARCH_LIMIT)
|
|
|
|
.pluck(:id, :data)
|
|
|
|
end
|
|
|
|
|
|
|
|
def fetch_columns_list_items
|
|
|
|
collection = []
|
|
|
|
@repository.repository_columns
|
|
|
|
.list_type
|
|
|
|
.preload(:repository_list_items)
|
|
|
|
.each do |column|
|
|
|
|
collection << {
|
|
|
|
column_id: column.id,
|
|
|
|
list_items: column.repository_list_items
|
|
|
|
.limit(Constants::SEARCH_LIMIT)
|
|
|
|
.pluck(:id, :data)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
collection
|
|
|
|
end
|
2017-06-06 23:35:29 +08:00
|
|
|
end
|