From c4ba892559e59d556de1b01aa58146058ade8569 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Wed, 7 Jan 2026 19:30:18 +0200 Subject: [PATCH] refactor clone --- app/controllers/application_controller.rb | 5 ++ app/controllers/templates_clone_controller.rb | 56 +++++++++++++++++++ app/controllers/templates_controller.rb | 52 ++--------------- app/views/templates/_file_form.html.erb | 12 +--- app/views/templates/_template.html.erb | 2 +- app/views/templates/_title.html.erb | 2 +- app/views/templates_clone/_form.html.erb | 29 ++++++++++ app/views/templates_clone/new.html.erb | 3 + config/routes.rb | 1 + 9 files changed, 103 insertions(+), 59 deletions(-) create mode 100644 app/controllers/templates_clone_controller.rb create mode 100644 app/views/templates_clone/_form.html.erb create mode 100644 app/views/templates_clone/new.html.erb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cd8d228c..191f1dc8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -17,6 +17,7 @@ class ApplicationController < ActionController::Base helper_method :button_title, :current_account, + :true_ability, :form_link_host, :svg_icon @@ -102,6 +103,10 @@ class ApplicationController < ActionController::Base current_user&.account end + def true_ability + @true_ability ||= Ability.new(true_user) + end + def maybe_redirect_to_setup redirect_to setup_index_path unless User.exists? end diff --git a/app/controllers/templates_clone_controller.rb b/app/controllers/templates_clone_controller.rb new file mode 100644 index 00000000..802a97e0 --- /dev/null +++ b/app/controllers/templates_clone_controller.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class TemplatesCloneController < ApplicationController + load_and_authorize_resource :template, instance_name: :base_template + + def new + authorize!(:create, Template) + + @template = Template.new(name: "#{@base_template.name} (#{I18n.t('clone')})") + end + + def create + ActiveRecord::Associations::Preloader.new( + records: [@base_template], + associations: [schema_documents: :preview_images_attachments] + ).call + + @template = Templates::Clone.call(@base_template, author: current_user, + name: params.dig(:template, :name), + folder_name: params[:folder_name]) + + authorize!(:create, @template) + + if params[:account_id].present? && true_ability.authorize!(:manage, Account.find(params[:account_id])) + @template.account_id = params[:account_id] + @template.author = true_user if true_user.account_id == @template.account_id + @template.folder = @template.account.default_template_folder if @template.account_id != current_account.id + else + @template.account = current_account + end + + Templates.maybe_assign_access(@template) + + if @template.save + Templates::CloneAttachments.call(template: @template, original_template: @base_template) + + SearchEntries.enqueue_reindex(@template) + + WebhookUrls.enqueue_events(@template, 'template.created') + + maybe_redirect_to_template(@template) + else + render turbo_stream: turbo_stream.replace(:modal, partial: 'templates_clone/form'), status: :unprocessable_content + end + end + + private + + def maybe_redirect_to_template(template) + if template.account == current_account + redirect_to(edit_template_path(template)) + else + redirect_back(fallback_location: root_path, notice: I18n.t('template_has_been_cloned')) + end + end +end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index c96360d9..39b45044 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -3,8 +3,6 @@ class TemplatesController < ApplicationController load_and_authorize_resource :template - before_action :load_base_template, only: %i[new create] - def show submissions = @template.submissions.accessible_by(current_ability) submissions = submissions.active if @template.archived_at.blank? @@ -26,9 +24,7 @@ class TemplatesController < ApplicationController redirect_to root_path end - def new - @template.name = "#{@base_template.name} (#{I18n.t('clone')})" if @base_template - end + def new; end def edit ActiveRecord::Associations::Preloader.new( @@ -48,37 +44,18 @@ class TemplatesController < ApplicationController end def create - if @base_template - ActiveRecord::Associations::Preloader.new( - records: [@base_template], - associations: [schema_documents: :preview_images_attachments] - ).call - - @template = Templates::Clone.call(@base_template, author: current_user, - name: params.dig(:template, :name), - folder_name: params[:folder_name]) - else - @template.author = current_user - @template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name]) - end - - if params[:account_id].present? && authorized_clone_account_id?(params[:account_id]) - @template.account_id = params[:account_id] - @template.folder = @template.account.default_template_folder if @template.account_id != current_account.id - else - @template.account = current_account - end + @template.author = current_user + @template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name]) + @template.account = current_account Templates.maybe_assign_access(@template) if @template.save - Templates::CloneAttachments.call(template: @template, original_template: @base_template) if @base_template - SearchEntries.enqueue_reindex(@template) WebhookUrls.enqueue_events(@template, 'template.created') - maybe_redirect_to_template(@template) + redirect_to(edit_template_path(@template)) else render turbo_stream: turbo_stream.replace(:modal, template: 'templates/new'), status: :unprocessable_content end @@ -132,23 +109,4 @@ class TemplatesController < ApplicationController areas: [%i[x y w h cell_w attachment_uuid option_uuid page]] }]] } ) end - - def authorized_clone_account_id?(account_id) - true_user.account_id.to_s == account_id.to_s || - true_user.account.linked_accounts.accessible_by(current_ability).exists?(id: account_id) - end - - def maybe_redirect_to_template(template) - if template.account == current_account - redirect_to(edit_template_path(@template)) - else - redirect_back(fallback_location: root_path, notice: I18n.t('template_has_been_cloned')) - end - end - - def load_base_template - return if params[:base_template_id].blank? - - @base_template = Template.accessible_by(current_ability).find_by(id: params[:base_template_id]) - end end diff --git a/app/views/templates/_file_form.html.erb b/app/views/templates/_file_form.html.erb index d0c59485..eaedc346 100644 --- a/app/views/templates/_file_form.html.erb +++ b/app/views/templates/_file_form.html.erb @@ -1,12 +1,4 @@ <%= form_for @template, data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %> - <% if @base_template %> - <%= hidden_field_tag :base_template_id, @base_template.id %> - <% end %> - <% if @base_template && (can?(:manage, :tenants) || true_user != current_user) && true_user.account.linked_accounts.active.accessible_by(current_ability).exists? %> -
- <%= select_tag :account_id, options_for_select([true_user.account, *true_user.account.linked_accounts.active.accessible_by(current_ability)].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %> -
- <% end %>
<%= f.text_field :name, required: true, placeholder: t('document_name'), class: 'base-input', dir: 'auto' %>
@@ -16,7 +8,7 @@ - +
- <%= f.button button_title(title: @base_template ? t('submit') : t('create'), disabled_with: t('creating')), class: 'base-button' %> + <%= f.button button_title(title: t('create'), disabled_with: t('creating')), class: 'base-button' %>
<% end %> diff --git a/app/views/templates/_template.html.erb b/app/views/templates/_template.html.erb index 1495be02..2ba35ebd 100644 --- a/app/views/templates/_template.html.erb +++ b/app/views/templates/_template.html.erb @@ -53,7 +53,7 @@ <% end %> <% if can?(:create, template) %> - + <%= svg_icon('copy', class: 'w-4 h-4') %> diff --git a/app/views/templates/_title.html.erb b/app/views/templates/_title.html.erb index 99f11044..5d563e22 100644 --- a/app/views/templates/_title.html.erb +++ b/app/views/templates/_title.html.erb @@ -63,7 +63,7 @@ <%= button_to button_title(title: t('archive'), disabled_with: t('archiving'), title_class: 'inline', icon: svg_icon('archive', class: 'w-6 h-6')), template_path(template), class: 'btn btn-outline btn-sm w-full', form_class: 'flex-1', method: :delete, data: { turbo_confirm: t('are_you_sure_') } %> <% end %> <% if can?(:create, current_account.templates.new(author: current_user)) %> - <%= link_to new_template_path(base_template_id: template.id), class: 'btn btn-outline btn-sm flex-1', data: { turbo_frame: :modal } do %> + <%= link_to new_template_clone_path(template), class: 'btn btn-outline btn-sm flex-1', data: { turbo_frame: :modal } do %> <%= svg_icon('copy', class: 'w-6 h-6') %> <%= t('clone') %> diff --git a/app/views/templates_clone/_form.html.erb b/app/views/templates_clone/_form.html.erb new file mode 100644 index 00000000..b2fb88b5 --- /dev/null +++ b/app/views/templates_clone/_form.html.erb @@ -0,0 +1,29 @@ +<%= form_for @template, url: template_clone_index_path(@base_template), data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %> + <% accounts = Account.accessible_by(true_ability).where.not(id: true_user.account.testing_accounts).where(User.where(User.arel_table[:account_id].eq(Account.arel_table[:id])).arel.exists).active %> + <% if (can?(:manage, :tenants) || true_user != current_user) && accounts.where.not(id: current_account.id).exists? %> +
+ <%= select_tag :account_id, options_for_select([current_account, *accounts.order(:name)].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %> +
+ <% end %> +
+ <%= f.text_field :name, required: true, placeholder: t('document_name'), class: 'base-input', dir: 'auto' %> +
+
+ + + + + + + + + +
+
+ <%= f.button button_title(title: t('submit'), disabled_with: t('creating')), class: 'base-button' %> +
+<% end %> diff --git a/app/views/templates_clone/new.html.erb b/app/views/templates_clone/new.html.erb new file mode 100644 index 00000000..728c6d48 --- /dev/null +++ b/app/views/templates_clone/new.html.erb @@ -0,0 +1,3 @@ +<%= render 'shared/turbo_modal', title: t('clone_template') do %> + <%= render 'templates_clone/form' %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index fa510839..26b6d617 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -92,6 +92,7 @@ Rails.application.routes.draw do resources :templates, only: %i[index], controller: 'templates_dashboard' resources :submissions_filters, only: %i[show], param: 'name' resources :templates, only: %i[new create edit update show destroy] do + resources :clone, only: %i[new create], controller: 'templates_clone' resource :debug, only: %i[show], controller: 'templates_debug' if Rails.env.development? resources :documents, only: %i[index create], controller: 'template_documents' resources :clone_and_replace, only: %i[create], controller: 'templates_clone_and_replace'