mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-09 21:36:44 +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
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StorageLocationsController < ApplicationController
|
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_read_permissions, only: :index
|
||||||
before_action :check_manage_permissions, except: :index
|
before_action :check_manage_permissions, except: :index
|
||||||
before_action :set_breadcrumbs_items, only: :index
|
before_action :set_breadcrumbs_items, only: :index
|
||||||
|
@ -51,6 +51,15 @@ class StorageLocationsController < ApplicationController
|
||||||
end
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def actions_toolbar
|
def actions_toolbar
|
||||||
render json: {
|
render json: {
|
||||||
actions:
|
actions:
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
@create_location="openCreateLocationModal"
|
@create_location="openCreateLocationModal"
|
||||||
@create_box="openCreateBoxModal"
|
@create_box="openCreateBoxModal"
|
||||||
@edit="edit"
|
@edit="edit"
|
||||||
|
@duplicate="duplicate"
|
||||||
@tableReloaded="reloadingTable = false"
|
@tableReloaded="reloadingTable = false"
|
||||||
/>
|
/>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
|
@ -25,8 +26,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* global */
|
/* global HelperModule */
|
||||||
|
|
||||||
|
import axios from '../../packs/custom_axios.js';
|
||||||
import DataTable from '../shared/datatable/table.vue';
|
import DataTable from '../shared/datatable/table.vue';
|
||||||
import EditModal from './modals/new_edit.vue';
|
import EditModal from './modals/new_edit.vue';
|
||||||
|
|
||||||
|
@ -154,6 +156,16 @@ export default {
|
||||||
this.editModalMode = params[0].container ? 'box' : 'location';
|
this.editModalMode = params[0].container ? 'box' : 'location';
|
||||||
[this.editStorageLocation] = params;
|
[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
|
// Renderers
|
||||||
nameRenderer(params) {
|
nameRenderer(params) {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -7,12 +7,18 @@ module Cloneable
|
||||||
raise NotImplementedError, "Cloneable model must implement the '.parent' method!" unless respond_to?(:parent)
|
raise NotImplementedError, "Cloneable model must implement the '.parent' method!" unless respond_to?(:parent)
|
||||||
|
|
||||||
clone_label = I18n.t('general.clone_label')
|
clone_label = I18n.t('general.clone_label')
|
||||||
last_clone_number =
|
|
||||||
parent.public_send(self.class.table_name)
|
records = if parent
|
||||||
.select("substring(#{self.class.table_name}.name, '(?:^#{clone_label} )(\\d+)')::int AS clone_number")
|
parent.public_send(self.class.table_name)
|
||||||
.where('name ~ ?', "^#{clone_label} \\d+ - #{Regexp.escape(name)}$")
|
else
|
||||||
.order(clone_number: :asc)
|
self.class.where(parent_id: nil, team: team)
|
||||||
.last&.clone_number
|
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)
|
"#{clone_label} #{(last_clone_number || 0) + 1} - #{name}".truncate(Constants::NAME_MAX_LENGTH)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StorageLocation < ApplicationRecord
|
class StorageLocation < ApplicationRecord
|
||||||
|
include Cloneable
|
||||||
include Discard::Model
|
include Discard::Model
|
||||||
ID_PREFIX = 'SL'
|
ID_PREFIX = 'SL'
|
||||||
include PrefixedIdModel
|
include PrefixedIdModel
|
||||||
|
@ -14,6 +15,7 @@ class StorageLocation < ApplicationRecord
|
||||||
belongs_to :created_by, class_name: 'User'
|
belongs_to :created_by, class_name: 'User'
|
||||||
|
|
||||||
has_many :storage_location_repository_rows, inverse_of: :storage_location
|
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
|
has_many :repository_rows, through: :storage_location_repository_row
|
||||||
|
|
||||||
validates :name, length: { maximum: Constants::NAME_MAX_LENGTH }
|
validates :name, length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||||
|
@ -22,4 +24,43 @@ class StorageLocation < ApplicationRecord
|
||||||
StorageLocation.where(parent_id: id).find_each(&:discard)
|
StorageLocation.where(parent_id: id).find_each(&:discard)
|
||||||
storage_location_repository_rows.each(&:discard)
|
storage_location_repository_rows.each(&:discard)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -64,7 +64,7 @@ module Toolbars
|
||||||
name: 'duplicate',
|
name: 'duplicate',
|
||||||
label: I18n.t('storage_locations.index.toolbar.duplicate'),
|
label: I18n.t('storage_locations.index.toolbar.duplicate'),
|
||||||
icon: 'sn-icon sn-icon-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
|
type: :emit
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -2672,6 +2672,8 @@ en:
|
||||||
head_title: "Locations"
|
head_title: "Locations"
|
||||||
new_location: "New location"
|
new_location: "New location"
|
||||||
new_box: "New box"
|
new_box: "New box"
|
||||||
|
duplicate:
|
||||||
|
success_message: "Location was successfully duplicated."
|
||||||
toolbar:
|
toolbar:
|
||||||
edit: 'Edit'
|
edit: 'Edit'
|
||||||
move: 'Move'
|
move: 'Move'
|
||||||
|
|
|
@ -813,7 +813,7 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
member do
|
member do
|
||||||
post :move
|
post :move
|
||||||
post :copy
|
post :duplicate
|
||||||
end
|
end
|
||||||
resources :storage_location_repository_rows, only: %i(index create destroy update)
|
resources :storage_location_repository_rows, only: %i(index create destroy update)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue