mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-03-04 19:53:19 +08:00
Add duplicate action to locations [SCI-10862]
This commit is contained in:
parent
e56e9b7dac
commit
1c3cc71174
7 changed files with 80 additions and 10 deletions
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class StorageLocationsController < ApplicationController
|
||||
before_action :load_storage_location, only: %i(update destroy)
|
||||
before_action :load_storage_location, only: %i(update destroy duplicate)
|
||||
before_action :check_read_permissions, only: :index
|
||||
before_action :check_manage_permissions, except: :index
|
||||
before_action :set_breadcrumbs_items, only: :index
|
||||
|
@ -51,6 +51,15 @@ class StorageLocationsController < ApplicationController
|
|||
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
|
||||
end
|
||||
end
|
||||
|
||||
def actions_toolbar
|
||||
render json: {
|
||||
actions:
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@create_location="openCreateLocationModal"
|
||||
@create_box="openCreateBoxModal"
|
||||
@edit="edit"
|
||||
@duplicate="duplicate"
|
||||
@tableReloaded="reloadingTable = false"
|
||||
/>
|
||||
<Teleport to="body">
|
||||
|
@ -25,8 +26,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
/* global */
|
||||
/* global HelperModule */
|
||||
|
||||
import axios from '../../packs/custom_axios.js';
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import EditModal from './modals/new_edit.vue';
|
||||
|
||||
|
@ -154,6 +156,16 @@ export default {
|
|||
this.editModalMode = params[0].container ? 'box' : 'location';
|
||||
[this.editStorageLocation] = params;
|
||||
},
|
||||
duplicate(action) {
|
||||
axios.post(action.path)
|
||||
.then(() => {
|
||||
this.reloadingTable = true;
|
||||
HelperModule.flashAlertMsg(this.i18n.t('storage_locations.index.duplicate.success_message'), 'success');
|
||||
})
|
||||
.catch(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
});
|
||||
},
|
||||
// Renderers
|
||||
nameRenderer(params) {
|
||||
const {
|
||||
|
|
|
@ -7,12 +7,18 @@ module Cloneable
|
|||
raise NotImplementedError, "Cloneable model must implement the '.parent' method!" unless respond_to?(:parent)
|
||||
|
||||
clone_label = I18n.t('general.clone_label')
|
||||
last_clone_number =
|
||||
parent.public_send(self.class.table_name)
|
||||
.select("substring(#{self.class.table_name}.name, '(?:^#{clone_label} )(\\d+)')::int AS clone_number")
|
||||
.where('name ~ ?', "^#{clone_label} \\d+ - #{Regexp.escape(name)}$")
|
||||
.order(clone_number: :asc)
|
||||
.last&.clone_number
|
||||
|
||||
records = if parent
|
||||
parent.public_send(self.class.table_name)
|
||||
else
|
||||
self.class.where(parent_id: nil, team: team)
|
||||
end
|
||||
|
||||
last_clone_number = records
|
||||
.select("substring(#{self.class.table_name}.name, '(?:^#{clone_label} )(\\d+)')::int AS clone_number")
|
||||
.where('name ~ ?', "^#{clone_label} \\d+ - #{Regexp.escape(name)}$")
|
||||
.order(clone_number: :asc)
|
||||
.last&.clone_number
|
||||
|
||||
"#{clone_label} #{(last_clone_number || 0) + 1} - #{name}".truncate(Constants::NAME_MAX_LENGTH)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class StorageLocation < ApplicationRecord
|
||||
include Cloneable
|
||||
include Discard::Model
|
||||
ID_PREFIX = 'SL'
|
||||
include PrefixedIdModel
|
||||
|
@ -14,6 +15,7 @@ class StorageLocation < ApplicationRecord
|
|||
belongs_to :created_by, class_name: 'User'
|
||||
|
||||
has_many :storage_location_repository_rows, inverse_of: :storage_location
|
||||
has_many :storage_locations, foreign_key: :parent_id, dependent: :destroy, inverse_of: :parent
|
||||
has_many :repository_rows, through: :storage_location_repository_row
|
||||
|
||||
validates :name, length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||
|
@ -22,4 +24,43 @@ class StorageLocation < ApplicationRecord
|
|||
StorageLocation.where(parent_id: id).find_each(&:discard)
|
||||
storage_location_repository_rows.each(&:discard)
|
||||
end
|
||||
|
||||
def duplicate!
|
||||
ActiveRecord::Base.transaction do
|
||||
new_storage_location = dup
|
||||
new_storage_location.name = next_clone_name
|
||||
new_storage_location.save!
|
||||
copy_image(self, new_storage_location)
|
||||
recursive_duplicate(id, new_storage_location.id)
|
||||
new_storage_location
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def recursive_duplicate(old_parent_id = nil, new_parent_id = nil)
|
||||
StorageLocation.where(parent_id: old_parent_id).find_each do |child|
|
||||
new_child = child.dup
|
||||
new_child.parent_id = new_parent_id
|
||||
new_child.save!
|
||||
copy_image(child, new_child)
|
||||
recursive_duplicate(child.id, new_child.id)
|
||||
end
|
||||
end
|
||||
|
||||
def copy_image(old_storage_location, new_storage_location)
|
||||
return unless old_storage_location.image.attached?
|
||||
|
||||
old_blob = old_storage_location.image.blob
|
||||
old_blob.open do |tmp_file|
|
||||
to_blob = ActiveStorage::Blob.create_and_upload!(
|
||||
io: tmp_file,
|
||||
filename: old_blob.filename,
|
||||
metadata: old_blob.metadata
|
||||
)
|
||||
new_storage_location.image.attach(to_blob)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -64,7 +64,7 @@ module Toolbars
|
|||
name: 'duplicate',
|
||||
label: I18n.t('storage_locations.index.toolbar.duplicate'),
|
||||
icon: 'sn-icon sn-icon-duplicate',
|
||||
path: copy_storage_location_path(@storage_locations.first),
|
||||
path: duplicate_storage_location_path(@storage_locations.first),
|
||||
type: :emit
|
||||
}
|
||||
end
|
||||
|
|
|
@ -2672,6 +2672,8 @@ en:
|
|||
head_title: "Locations"
|
||||
new_location: "New location"
|
||||
new_box: "New box"
|
||||
duplicate:
|
||||
success_message: "Location was successfully duplicated."
|
||||
toolbar:
|
||||
edit: 'Edit'
|
||||
move: 'Move'
|
||||
|
|
|
@ -813,7 +813,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
member do
|
||||
post :move
|
||||
post :copy
|
||||
post :duplicate
|
||||
end
|
||||
resources :storage_location_repository_rows, only: %i(index create destroy update)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue