mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-24 00:29:30 +08:00
Implement storage location activities [SCI-10925]
This commit is contained in:
parent
8d5adad6b5
commit
c4c14553ff
10 changed files with 233 additions and 71 deletions
|
@ -17,30 +17,36 @@ class StorageLocationRepositoryRowsController < ApplicationController
|
|||
meta: (pagination_dict(storage_location_repository_row) unless @storage_location.with_grid?)
|
||||
end
|
||||
|
||||
def update
|
||||
@storage_location_repository_row.update(storage_location_repository_row_params)
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@storage_location_repository_row = StorageLocationRepositoryRow.new(
|
||||
repository_row: @repository_row,
|
||||
storage_location: @storage_location,
|
||||
metadata: storage_location_repository_row_params[:metadata] || {},
|
||||
created_by: current_user
|
||||
)
|
||||
|
||||
if @storage_location_repository_row.save
|
||||
render json: @storage_location_repository_row,
|
||||
serializer: Lists::StorageLocationRepositoryRowSerializer
|
||||
else
|
||||
render json: @storage_location_repository_row.errors, status: :unprocessable_entity
|
||||
if @storage_location_repository_row.save
|
||||
log_activity(:storage_location_repository_row_created)
|
||||
render json: @storage_location_repository_row,
|
||||
serializer: Lists::StorageLocationRepositoryRowSerializer
|
||||
else
|
||||
render json: @storage_location_repository_row.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@storage_location_repository_row = StorageLocationRepositoryRow.new(
|
||||
repository_row: @repository_row,
|
||||
storage_location: @storage_location,
|
||||
metadata: storage_location_repository_row_params[:metadata] || {},
|
||||
created_by: current_user
|
||||
)
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
@storage_location_repository_row.update(storage_location_repository_row_params)
|
||||
|
||||
if @storage_location_repository_row.save
|
||||
render json: @storage_location_repository_row,
|
||||
serializer: Lists::StorageLocationRepositoryRowSerializer
|
||||
else
|
||||
render json: @storage_location_repository_row.errors, status: :unprocessable_entity
|
||||
if @storage_location_repository_row.save
|
||||
log_activity(:storage_location_repository_row_moved)
|
||||
render json: @storage_location_repository_row,
|
||||
serializer: Lists::StorageLocationRepositoryRowSerializer
|
||||
else
|
||||
render json: @storage_location_repository_row.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,7 +59,7 @@ class StorageLocationRepositoryRowsController < ApplicationController
|
|||
metadata: storage_location_repository_row_params[:metadata] || {},
|
||||
created_by: current_user
|
||||
)
|
||||
|
||||
log_activity(:storage_location_repository_row_moved)
|
||||
render json: @storage_location_repository_row,
|
||||
serializer: Lists::StorageLocationRepositoryRowSerializer
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
|
@ -63,10 +69,13 @@ class StorageLocationRepositoryRowsController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
if @storage_location_repository_row.discard
|
||||
render json: {}
|
||||
else
|
||||
render json: { errors: @storage_location_repository_row.errors.full_messages }, status: :unprocessable_entity
|
||||
ActiveRecord::Base.transaction do
|
||||
if @storage_location_repository_row.discard
|
||||
log_activity(:storage_location_repository_row_deleted)
|
||||
render json: {}
|
||||
else
|
||||
render json: { errors: @storage_location_repository_row.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -74,7 +83,7 @@ class StorageLocationRepositoryRowsController < ApplicationController
|
|||
render json: {
|
||||
actions: Toolbars::StorageLocationRepositoryRowsService.new(
|
||||
current_user,
|
||||
items_ids: JSON.parse(params[:items]).map { |i| i['id'] }
|
||||
items_ids: JSON.parse(params[:items]).pluck('id')
|
||||
).actions
|
||||
}
|
||||
end
|
||||
|
@ -116,4 +125,18 @@ class StorageLocationRepositoryRowsController < ApplicationController
|
|||
def check_manage_permissions
|
||||
render_403 unless can_manage_storage_location?(@storage_location)
|
||||
end
|
||||
|
||||
def log_activity(type_of, message_items = {})
|
||||
Activities::CreateActivityService
|
||||
.call(activity_type: type_of,
|
||||
owner: current_user,
|
||||
team: @storage_location.team,
|
||||
subject: @storage_location_repository_row.repository_row,
|
||||
message_items: {
|
||||
storage_location: @storage_location_repository_row.storage_location_id,
|
||||
repository_row: @storage_location_repository_row.repository_row_id,
|
||||
position: @storage_location_repository_row.human_readable_position,
|
||||
user: current_user.id
|
||||
}.merge(message_items))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,60 +21,78 @@ class StorageLocationsController < ApplicationController
|
|||
|
||||
def show; end
|
||||
|
||||
def update
|
||||
@storage_location.image.purge if params[:file_name].blank?
|
||||
@storage_location.image.attach(params[:signed_blob_id]) if params[:signed_blob_id]
|
||||
@storage_location.update(storage_location_params)
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@storage_location = StorageLocation.new(
|
||||
storage_location_params.merge({ created_by: current_user })
|
||||
)
|
||||
|
||||
if @storage_location.save
|
||||
render json: @storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
@storage_location.team = @storage_location.root_storage_location.team || current_team
|
||||
|
||||
@storage_location.image.attach(params[:signed_blob_id]) if params[:signed_blob_id]
|
||||
|
||||
if @storage_location.save
|
||||
log_activity('storage_location_created')
|
||||
render json: @storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@storage_location = StorageLocation.new(
|
||||
storage_location_params.merge({ created_by: current_user })
|
||||
)
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
@storage_location.image.purge if params[:file_name].blank?
|
||||
@storage_location.image.attach(params[:signed_blob_id]) if params[:signed_blob_id]
|
||||
@storage_location.update(storage_location_params)
|
||||
|
||||
@storage_location.team = @storage_location.root_storage_location.team || current_team
|
||||
|
||||
@storage_location.image.attach(params[:signed_blob_id]) if params[:signed_blob_id]
|
||||
|
||||
if @storage_location.save
|
||||
render json: @storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
if @storage_location.save
|
||||
log_activity('storage_location_edited')
|
||||
render json: @storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @storage_location.discard
|
||||
render json: {}
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
ActiveRecord::Base.transaction do
|
||||
if @storage_location.discard
|
||||
log_activity('storage_location_deleted')
|
||||
render json: {}
|
||||
else
|
||||
render json: { error: @storage_location.errors.full_messages }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def duplicate
|
||||
new_storage_location = @storage_location.duplicate!
|
||||
if new_storage_location
|
||||
render json: new_storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { errors: :failed }, status: :unprocessable_entity
|
||||
ActiveRecord::Base.transaction do
|
||||
new_storage_location = @storage_location.duplicate!
|
||||
if new_storage_location
|
||||
@storage_location = new_storage_location
|
||||
log_activity('storage_location_created')
|
||||
render json: @storage_location, serializer: Lists::StorageLocationSerializer
|
||||
else
|
||||
render json: { errors: :failed }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def move
|
||||
storage_location_destination =
|
||||
if move_params[:destination_storage_location_id] == 'root_storage_location'
|
||||
nil
|
||||
else
|
||||
current_team.storage_locations.find(move_params[:destination_storage_location_id])
|
||||
end
|
||||
ActiveRecord::Base.transaction do
|
||||
original_storage_location = @storage_location.parent
|
||||
destination_storage_location =
|
||||
if move_params[:destination_storage_location_id] == 'root_storage_location'
|
||||
nil
|
||||
else
|
||||
current_team.storage_locations.find(move_params[:destination_storage_location_id])
|
||||
end
|
||||
|
||||
@storage_location.update!(parent: storage_location_destination)
|
||||
@storage_location.update!(parent: destination_storage_location)
|
||||
|
||||
log_activity('storage_location_moved', { storage_location_original: original_storage_location.id, storage_location_destination: destination_storage_location.id })
|
||||
end
|
||||
|
||||
render json: { message: I18n.t('storage_locations.index.move_modal.success_flash') }
|
||||
rescue StandardError => e
|
||||
|
@ -93,7 +111,11 @@ class StorageLocationsController < ApplicationController
|
|||
end
|
||||
|
||||
def unassign_rows
|
||||
@storage_location.storage_location_repository_rows.where(id: params[:ids]).discard_all
|
||||
ActiveRecord::Base.transaction do
|
||||
@storage_location_repository_rows = @storage_location.storage_location_repository_rows.where(id: params[:ids])
|
||||
@storage_location_repository_rows.each(&:discard)
|
||||
log_unassign_activities
|
||||
end
|
||||
|
||||
render json: { status: :ok }
|
||||
end
|
||||
|
@ -206,4 +228,32 @@ class StorageLocationsController < ApplicationController
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
def log_activity(type_of, message_items = {})
|
||||
Activities::CreateActivityService
|
||||
.call(activity_type: "#{'container_' if @storage_location.container}#{type_of}",
|
||||
owner: current_user,
|
||||
team: @storage_location.team,
|
||||
subject: @storage_location,
|
||||
message_items: {
|
||||
storage_location: @storage_location.id,
|
||||
user: current_user.id
|
||||
}.merge(message_items))
|
||||
end
|
||||
|
||||
def log_unassign_activities
|
||||
@storage_location_repository_rows.each do |storage_location_repository_row|
|
||||
Activities::CreateActivityService
|
||||
.call(activity_type: :storage_location_repository_row_deleted,
|
||||
owner: current_user,
|
||||
team: @storage_location.team,
|
||||
subject: storage_location_repository_row.repository_row,
|
||||
message_items: {
|
||||
storage_location: storage_location_repository_row.storage_location_id,
|
||||
repository_row: storage_location_repository_row.repository_row_id,
|
||||
position: storage_location_repository_row.human_readable_position,
|
||||
user: current_user.id
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -71,7 +71,7 @@ class TeamSharedObjectsController < ApplicationController
|
|||
}
|
||||
end
|
||||
|
||||
def log_activity(type_of, team_shared_object)
|
||||
def log_activity(type_of)
|
||||
# log activity logic
|
||||
end
|
||||
end
|
||||
|
|
|
@ -108,6 +108,8 @@ module GlobalActivitiesHelper
|
|||
else
|
||||
project_folder_path(obj, team: obj.team.id)
|
||||
end
|
||||
when StorageLocation
|
||||
path = storage_location_path(obj)
|
||||
else
|
||||
return current_value
|
||||
end
|
||||
|
|
|
@ -187,6 +187,9 @@ class Activity < ApplicationRecord
|
|||
when Asset
|
||||
breadcrumbs[:asset] = subject.blob.filename.to_s
|
||||
generate_breadcrumb(subject.result || subject.step || subject.repository_cell.repository_row.repository)
|
||||
when StorageLocation
|
||||
breadcrumbs[:storage_location] = subject.name
|
||||
generate_breadcrumb(subject.team)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -14,10 +14,17 @@ class StorageLocationRepositoryRow < ApplicationRecord
|
|||
validate :ensure_uniq_position
|
||||
end
|
||||
|
||||
def human_readable_position
|
||||
return unless metadata['position']
|
||||
|
||||
column_letter = ('A'..'Z').to_a[metadata['position'][0] - 1]
|
||||
row_number = metadata['position'][1]
|
||||
|
||||
"#{column_letter}#{row_number}"
|
||||
end
|
||||
|
||||
def position_must_be_present
|
||||
if metadata['position'].blank?
|
||||
errors.add(:base, I18n.t('activerecord.errors.models.storage_location.missing_position'))
|
||||
end
|
||||
errors.add(:base, I18n.t('activerecord.errors.models.storage_location.missing_position')) if metadata['position'].blank?
|
||||
end
|
||||
|
||||
def ensure_uniq_position
|
||||
|
|
|
@ -61,7 +61,11 @@ module Activities
|
|||
end
|
||||
|
||||
if id
|
||||
obj = const.find id
|
||||
obj = if const.respond_to?(:with_discarded)
|
||||
const.with_discarded.find id
|
||||
else
|
||||
const.find id
|
||||
end
|
||||
@activity.message_items[k] = { type: const.to_s, value: obj.public_send(getter_method).to_s, id: id }
|
||||
@activity.message_items[k][:value_for] = getter_method
|
||||
@activity.message_items[k][:value_type] = value_type unless value_type.nil?
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<%= render partial: "global_activities/references/team",
|
||||
locals: { team: team, subject: team, breadcrumbs: breadcrumbs, values: values, type_of: type_of } %>
|
||||
<div class="ga-breadcrumb">
|
||||
<span class="sn-icon sn-icon-storage"></span>
|
||||
<% if subject %>
|
||||
<%= route_to_other_team(storage_location_path(subject.id, team: subject.team.id),
|
||||
team,
|
||||
subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH),
|
||||
title: subject.name) %>
|
||||
<% else %>
|
||||
<span title="<%= breadcrumbs['storage_location'] %>">
|
||||
<%= breadcrumbs['storage_location']&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
|
@ -188,7 +188,7 @@ class Extends
|
|||
|
||||
ACTIVITY_SUBJECT_TYPES = %w(
|
||||
Team RepositoryBase Project Experiment MyModule Result Protocol Report RepositoryRow
|
||||
ProjectFolder Asset Step LabelTemplate
|
||||
ProjectFolder Asset Step LabelTemplate StorageLocation StorageLocationRepositoryRow
|
||||
).freeze
|
||||
|
||||
SEARCHABLE_ACTIVITY_SUBJECT_TYPES = %w(
|
||||
|
@ -205,7 +205,8 @@ class Extends
|
|||
my_module: %i(results protocols),
|
||||
result: [:assets],
|
||||
protocol: [:steps],
|
||||
step: [:assets]
|
||||
step: [:assets],
|
||||
storage_location: [:storage_location_repository_rows]
|
||||
}
|
||||
|
||||
ACTIVITY_MESSAGE_ITEMS_TYPES =
|
||||
|
@ -495,7 +496,24 @@ class Extends
|
|||
task_step_asset_renamed: 305,
|
||||
result_asset_renamed: 306,
|
||||
protocol_step_asset_renamed: 307,
|
||||
inventory_items_added_or_updated_with_import: 308
|
||||
inventory_items_added_or_updated_with_import: 308,
|
||||
storage_location_created: 309,
|
||||
storage_location_deleted: 310,
|
||||
storage_location_edited: 311,
|
||||
storage_location_moved: 312,
|
||||
storage_location_shared: 313,
|
||||
storage_location_unshared: 314,
|
||||
storage_location_sharing_updated: 315,
|
||||
container_storage_location_created: 316,
|
||||
container_storage_location_deleted: 317,
|
||||
container_storage_location_edited: 318,
|
||||
container_storage_location_moved: 319,
|
||||
container_storage_location_shared: 320,
|
||||
container_storage_location_unshared: 321,
|
||||
container_storage_location_sharing_updated: 322,
|
||||
storage_location_repository_row_created: 323,
|
||||
storage_location_repository_row_deleted: 324,
|
||||
storage_location_repository_row_moved: 325
|
||||
}
|
||||
|
||||
ACTIVITY_GROUPS = {
|
||||
|
@ -515,7 +533,10 @@ class Extends
|
|||
190, 191, *204..215, 220, 223, 227, 228, 229, *230..235,
|
||||
*237..240, *253..256, *279..283, 300, 304, 307],
|
||||
team: [92, 94, 93, 97, 104, 244, 245],
|
||||
label_templates: [*216..219]
|
||||
label_templates: [*216..219],
|
||||
storage_locations: [*309..315],
|
||||
container_storage_location: [*316..322],
|
||||
storage_location_repository_rows: [*323..325]
|
||||
}
|
||||
|
||||
TOP_LEVEL_ASSIGNABLES = %w(Project Team Protocol Repository).freeze
|
||||
|
|
|
@ -322,6 +322,23 @@ en:
|
|||
protocol_step_asset_renamed_html: "%{user} renamed file %{old_name} to %{new_name} on protocol’s step <strong>%{step}</strong> in Protocol repository."
|
||||
result_asset_renamed_html: "%{user} renamed file %{old_name} to %{new_name} on result <strong>%{result}</strong> on task <strong>%{my_module}</strong>."
|
||||
item_added_with_import_html: "%{user} edited %{num_of_items} inventory item(s) in %{repository}."
|
||||
storage_location_created_html: "%{user} created location %{storage_location}."
|
||||
storage_location_deleted_html: "%{user} deleted location %{storage_location}."
|
||||
storage_location_edited_html: "%{user} edited location %{storage_location}."
|
||||
storage_location_moved_html: "%{user} moved location %{storage_location} from %{storage_location_original} to %{storage_location_destination}."
|
||||
storage_location_shared_html: "%{user} shared location %{storage_location} with team %{team} with %{permission_level} permission."
|
||||
storage_location_unshared_html: "%{user} unshared location %{storage_location} with team %{team}."
|
||||
storage_location_sharing_updated_html: "%{user} changed permission of shared location %{storage_location} with team %{team} to %{permission_level}."
|
||||
container_storage_location_created_html: "%{user} created box %{storage_location}."
|
||||
container_storage_location_deleted_html: "%{user} deleted box %{storage_location}."
|
||||
container_storage_location_edited_html: "%{user} edited box %{storage_location}."
|
||||
container_storage_location_moved_html: "%{user} moved box %{storage_location} from %{storage_location_original} to %{storage_location_destination}."
|
||||
container_storage_location_shared_html: "%{user} shared box %{storage_location} with team %{team} with %{permission_level} permission."
|
||||
container_storage_location_unshared_html: "%{user} unshared box %{storage_location} with team %{team}."
|
||||
container_storage_location_sharing_updated_html: "%{user} changed permission of shared box %{storage_location} with team %{team} to %{permission_level}."
|
||||
storage_location_repository_row_created_html: "%{user} assigned %{repository_row} to box %{storage_location} %{position}."
|
||||
storage_location_repository_row_deleted_html: "%{user} unassigned %{repository_row} from box %{storage_location} %{position}."
|
||||
storage_location_repository_row_moved_html: "%{user} moved item %{repository_row} from box %{storage_location_original} %{positions} to box %{storage_location_destination} %{positions}."
|
||||
activity_name:
|
||||
create_project: "Project created"
|
||||
rename_project: "Project renamed"
|
||||
|
@ -601,6 +618,23 @@ en:
|
|||
task_step_file_duplicated: "File attachment on Task step duplicated"
|
||||
result_file_duplicated: "File attachment on Task result duplicated"
|
||||
protocol_step_file_duplicated: "File attachment on Protocol step duplicated"
|
||||
storage_location_created: "Location created"
|
||||
storage_location_deleted: "Location deleted"
|
||||
storage_location_edited: "Location edited"
|
||||
storage_location_moved: "Location moved"
|
||||
storage_location_shared: "Location shared"
|
||||
storage_location_unshared: "Location unshared"
|
||||
storage_location_sharing_updated: "Location sharing permission updated"
|
||||
container_storage_location_created: "Box created"
|
||||
container_storage_location_deleted: "Box deleted"
|
||||
container_storage_location_edited: "Box edited"
|
||||
container_storage_location_moved: "Box moved"
|
||||
container_storage_location_shared: "Box shared"
|
||||
container_storage_location_unshared: "Box unshared"
|
||||
container_storage_location_sharing_updated: "Box sharing permission updated"
|
||||
storage_location_repository_row_created: "Inventory item location assigned"
|
||||
storage_location_repository_row_deleted: "Inventory item location unassigned"
|
||||
storage_location_repository_row_moved: "Inventory item location moved"
|
||||
activity_group:
|
||||
projects: "Projects"
|
||||
task_results: "Task results"
|
||||
|
@ -614,6 +648,8 @@ en:
|
|||
team: "Team"
|
||||
exports: "Exports"
|
||||
label_templates: "Label templates"
|
||||
storage_locations: "Locations"
|
||||
container_storage_locations: "Boxes"
|
||||
subject_name:
|
||||
repository: "Inventory"
|
||||
project: "Project"
|
||||
|
@ -623,3 +659,4 @@ en:
|
|||
protocol: "Protocol"
|
||||
step: "Step"
|
||||
report: "Report"
|
||||
storage_location: "Location"
|
||||
|
|
Loading…
Reference in a new issue