From 3c25e204c979936d41c19050d54a329fc0e4bf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Wed, 22 Oct 2025 13:52:45 +0200 Subject: [PATCH 01/33] basic delete page for stacks --- app/controllers/stacks_controller.rb | 5 +++++ app/views/stacks/destroy.html.erb | 24 ++++++++++++++++++++++++ app/views/stacks/index.html.erb | 2 +- config/locales/fr.yml | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 app/views/stacks/destroy.html.erb diff --git a/app/controllers/stacks_controller.rb b/app/controllers/stacks_controller.rb index 82417b2b3..e7350a1f9 100644 --- a/app/controllers/stacks_controller.rb +++ b/app/controllers/stacks_controller.rb @@ -57,6 +57,11 @@ def update # DELETE /stacks/1 # DELETE /stacks/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @stack.destroy respond_to do |format| format.html { redirect_to stacks_url, notice: t(".flashes.destroyed") } diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb new file mode 100644 index 000000000..5382d7420 --- /dev/null +++ b/app/views/stacks/destroy.html.erb @@ -0,0 +1,24 @@ +<% + breadcrumb + .add_step(@stack, stack_path(@stack)) + .add_step(t("action.delete")) +%> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %> +
+

+ <%= t(".delete-confirm") %> +

+ <%= render ButtonComponent.new( + t("action.cancel"), + url: :back, + is_responsive: true + )%> + <%= render ButtonComponent.new( + t("action.delete"), + url: stack_path(@stack, confirm: true), + method: :delete, + variant: :danger, + icon: "trash", + is_responsive: true + )%> +
diff --git a/app/views/stacks/index.html.erb b/app/views/stacks/index.html.erb index f8c22f34d..ab7848429 100644 --- a/app/views/stacks/index.html.erb +++ b/app/views/stacks/index.html.erb @@ -50,7 +50,7 @@ <% end %> <% if allowed_to?(:destroy?, stack) %> - <%= link_to stack, method: :delete, data: { confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> + <%= link_to stack, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 45ec38190..2dc485fea 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -232,6 +232,8 @@ fr: flashes: updated: La stack a bien été modifiée. destroy: + title: Suppression + delete-confirm: Voulez-vous vraiment supprimer cette ressource ? flashes: destroyed: La stack a bien été supprimé. card_types: From f0830c04dfbc9a4f457b89c34105f533e9c81272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Thu, 23 Oct 2025 15:23:12 +0200 Subject: [PATCH 02/33] adding component system to visualize. Starting to fill model's collection component. Making Manufacture and Stack use this system --- .../bay_collection_component.rb | 73 +++++++++++++++++++ .../delete_dependency/defaults_component.rb | 30 ++++++++ .../delete_dependency/main_component.rb | 27 +++++++ .../modele_collection_component.rb | 47 ++++++++++++ .../server_collection_component.rb | 49 +++++++++++++ .../stack_collection_component.rb | 33 +++++++++ app/controllers/manufacturers_controller.rb | 5 ++ app/helpers/modeles_helper.rb | 2 +- app/models/application_record.rb | 1 + app/models/concerns/deletable_dependencies.rb | 58 +++++++++++++++ app/models/stack.rb | 2 + app/views/manufacturers/destroy.html.erb | 32 ++++++++ app/views/stacks/destroy.html.erb | 13 +++- config/locales/fr.yml | 5 +- 14 files changed, 373 insertions(+), 4 deletions(-) create mode 100644 app/components/delete_dependency/bay_collection_component.rb create mode 100644 app/components/delete_dependency/defaults_component.rb create mode 100644 app/components/delete_dependency/main_component.rb create mode 100644 app/components/delete_dependency/modele_collection_component.rb create mode 100644 app/components/delete_dependency/server_collection_component.rb create mode 100644 app/components/delete_dependency/stack_collection_component.rb create mode 100644 app/models/concerns/deletable_dependencies.rb create mode 100644 app/views/manufacturers/destroy.html.erb diff --git a/app/components/delete_dependency/bay_collection_component.rb b/app/components/delete_dependency/bay_collection_component.rb new file mode 100644 index 000000000..1c8a8cd39 --- /dev/null +++ b/app/components/delete_dependency/bay_collection_component.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +module DeleteDependency + class BayCollectionComponent < ApplicationComponent + erb_template <<~ERB +

<%= Bay.model_name.human %>

+ <%= render List::DataTableComponent.new(@bays) do |table| %> + + <% table.with_column(Bay.human_attribute_name(:name), name: :name) do |bay| %> + <%= link_to bay_path(bay), class: "fw-bold", target: "_blank" do %> + <% bay.frames.any? ? bay.to_s : bay.decorated.no_frame_warning_icon %> + <% end %> + <% end %> + + <% table.with_column(Room.model_name.human, name: :room_id) do |bay| %> + <%= link_to bay.room, room_path(bay.room), target: "_blank" %> + <% end %> + + <% table.with_column(Islet.model_name.human, name: :islet_id) do |bay| %> + <%= link_to bay.islet.name_with_room, islet_path(bay.islet), target: "_blank" %> + <% end %> + + <% table.with_column(Frame.model_name.human.pluralize, name: :frame_id) do |bay| %> + <%= + bay.frames.map do |frame| + link_to(frame.name, frame_path(frame), target: "_blank") + end.join(" / ").html_safe + %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:lane), name: :lane) do |bay| %> + <%= bay.lane %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:position), name: :position) do |bay| %> + <%= bay.position %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:width), name: :width) do |bay| %> + <%= bay.width %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:depth), name: :depth) do |bay| %> + <%= bay.depth %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:bay_type_id), name: :bay_type_id) do |bay| %> + <%= bay.bay_type %> + <% end %> + + <% table.with_column(Bay.human_attribute_name(:access_control), name: :access_control) do |bay| %> + <%= bay.access_control %> + <% end %> + + + <% table.with_column(Server.model_name.human(count: 2), name: :server_id) do |bay| %> + <%= link_to servers_path(bay_ids: bay.id), target: "_blank" do %> + <%= Bay.human_attribute_name(:materials_count, count: bay.materials.count) %> + <% end %> + <% end %> + + <% table.with_column(Manufacturer.model_name.human, name: :manufacturer_id) do |bay| %> + <%= link_to bay.manufacturer.name, manufacturer_path(bay.manufacturer), target: "_blank" if bay.manufacturer %> + <% end %> + <% end %> + ERB + + def initialize(bays) + @bays = bays + super + end + end +end diff --git a/app/components/delete_dependency/defaults_component.rb b/app/components/delete_dependency/defaults_component.rb new file mode 100644 index 000000000..007329f5e --- /dev/null +++ b/app/components/delete_dependency/defaults_component.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module DeleteDependency + class DefaultsComponent < ApplicationComponent + erb_template <<~ERB +

<%= @model.model_name.human %>

+ + ERB + + def initialize(model, records) + @model = model + @records = records + super + end + + private + + def show_link(record) + link_to record.to_s, url_for(record), target: "_blank", rel: "noopener" + rescue StandardError + "

#{record}

" + end + end +end diff --git a/app/components/delete_dependency/main_component.rb b/app/components/delete_dependency/main_component.rb new file mode 100644 index 000000000..97e17121f --- /dev/null +++ b/app/components/delete_dependency/main_component.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module DeleteDependency + class MainComponent < ApplicationComponent + erb_template <<~ERB + <% @dependencies.each do |dependency| %> + <%= render component_for(dependency[:klass], dependency[:records]) %> + <% end %> + ERB + + def initialize(record) + @dependencies = record.delete_dependencies + + super + end + + private + + def component_for(model, records) + class_name = "DeleteDependency::#{model.model_name.name}CollectionComponent" + component_class = class_name.safe_constantize + return component_class.new(records) unless component_class.nil? + + DeleteDependency::DefaultsComponent.new model, records + end + end +end diff --git a/app/components/delete_dependency/modele_collection_component.rb b/app/components/delete_dependency/modele_collection_component.rb new file mode 100644 index 000000000..b6c7b8d9d --- /dev/null +++ b/app/components/delete_dependency/modele_collection_component.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module DeleteDependency + class ModeleCollectionComponent < ApplicationComponent + include ModelesHelper + + erb_template <<~ERB +

<%= Modele.model_name.human %>

+ <%= render List::DataTableComponent.new(@modeles) do |table| %> + + <% table.with_column(class: "p-0", style: "width: 40px; height: 40px;") do |modele| %> + <% bgModeleColor = modele.try(:color) || lighten_color("#\#{Digest::MD5.hexdigest(modele.try(:name) || "test")[0..5]}", 0.4) %> +
+ <% end %> + + <% table.with_column(Modele.model_name.human) do |modele| %> + <%= link_to modele, modele_path(modele), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> + <% end %> + + <% table.with_column(Enclosure.human_attribute_name(:display)) do |modele| %> + <%= modele.decorated.displays_to_human %> + <% end %> + + <% table.with_column(Server.model_name.human(count: 2)) do |modele| %> + <%= link_to servers_path(modele_ids: modele.id), data: { turbo_frame: :_top }, target: "_blank" do %> + <%= pluralize(modele.servers.count, + modele.category.name.try(:downcase), + "\#{modele.category.name.try(:downcase)}\#{modele.category.name.blank? || + modele.category.name.end_with?("s") || + modele.category.name == "San" || + modele.category.name.end_with?("eau") ? "" : "s"}") + %> + <% end %> + <% end %> + + <% table.with_column(Modele.human_attribute_name(:network_types)) do |modele| %> + <%= modele.decorated.network_types_to_human %> + <% end %> + <% end %> + ERB + + def initialize(modeles) + @modeles = modeles + super + end + end +end diff --git a/app/components/delete_dependency/server_collection_component.rb b/app/components/delete_dependency/server_collection_component.rb new file mode 100644 index 000000000..1c6b21ed8 --- /dev/null +++ b/app/components/delete_dependency/server_collection_component.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module DeleteDependency + class ServerCollectionComponent < ApplicationComponent + erb_template <<~ERB +

<%= Server.model_name.human %>

+ <%= render List::DataTableComponent.new(@servers) do |table| %> + + <% table.with_column(Server.human_attribute_name(:name), name: :name) do |server| %> + <%= link_to server.name, server_path(server), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> + <% end %> + + <% table.with_column(Server.human_attribute_name(:numero), name: :numero) do |server| %> + <%= link_to server.numero, server_path(server), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> + <% end %> + + <% table.with_column(Modele.human_attribute_name(:category), name: :"modele_category_id") do |server| %> + <%= link_to server.modele.category, category_path(server.modele.category), + data: { turbo_frame: :_top }, target: "_blank" if server.modele.try(:category) %> + <% end %> + + <% table.with_column(Server.human_attribute_name(:room), name: :room) do |server| %> + <%= link_to server.room, room_path(server.room), data: { turbo_frame: :_top }, target: "_blank" if server.room %> + <% end %> + + <% table.with_column(Islet.model_name.human, name: :islet_id) do |server| %> + <%= link_to server.islet, islet_path(server.islet), data: { turbo_frame: :_top }, target: "_blank" if server.islet %> + <% end %> + + <% table.with_column(Bay.model_name.human, name: :bay_id) do |server| %> + <%= link_to server.bay, bay_path(server.bay), data: { turbo_frame: :_top }, target: "_blank" if server.bay %> + <% end %> + + <% table.with_column(Server.human_attribute_name(:network_types), name: :network_types) do |server| %> + <%= server.decorated.network_types_to_human %> + <% end %> + + <% table.with_column(Server.human_attribute_name(:position), name: :position) do |server| %> + <%= server.position %> + <% end %> + <% end %> + ERB + + def initialize(servers) + @servers = servers + super + end + end +end diff --git a/app/components/delete_dependency/stack_collection_component.rb b/app/components/delete_dependency/stack_collection_component.rb new file mode 100644 index 000000000..8eb90670a --- /dev/null +++ b/app/components/delete_dependency/stack_collection_component.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module DeleteDependency + class StackCollectionComponent < ApplicationComponent + erb_template <<~ERB +

<%= Stack.model_name.human %>

+ + + + + + + + + + <% @stacks.each do |stack| %> + + + + + + <% end %> + +
<%= Stack.human_attribute_name(:name) %><%= Stack.human_attribute_name(:color) %><%= Stack.human_attribute_name(:servers) %>
<%= link_to stack, stack_path(stack), target: "_blank" %><%= stack.color %><%= link_to Stack.human_attribute_name(:servers_count, count: stack.servers_count), + servers_path(stack_ids: stack.id), target: "_blank" %>
+ ERB + + def initialize(stacks) + @stacks = stacks + super + end + end +end diff --git a/app/controllers/manufacturers_controller.rb b/app/controllers/manufacturers_controller.rb index a1c88b796..6ba33c1b7 100644 --- a/app/controllers/manufacturers_controller.rb +++ b/app/controllers/manufacturers_controller.rb @@ -57,6 +57,11 @@ def update # DELETE /manufacturers/1 # DELETE /manufacturers/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @manufacturer.destroy respond_to do |format| format.html { redirect_to manufacturers_url, notice: t(".flashes.destroyed") } diff --git a/app/helpers/modeles_helper.rb b/app/helpers/modeles_helper.rb index 85219e425..e969b5f4c 100644 --- a/app/helpers/modeles_helper.rb +++ b/app/helpers/modeles_helper.rb @@ -8,6 +8,6 @@ def lighten_color(hex_color, amount = 0.6) rgb[1] = [(rgb[1].to_i + (255 * amount)).round, 255].min rgb[2] = [(rgb[2].to_i + (255 * amount)).round, 255].min - format("#%02x%02x%02x", *rgb) + Kernel.format("#%02x%02x%02x", *rgb) end end diff --git a/app/models/application_record.rb b/app/models/application_record.rb index a3f99934b..d6ad55706 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -2,6 +2,7 @@ class ApplicationRecord < ActiveRecord::Base include Changelogable + include DeletableDependencies primary_abstract_class diff --git a/app/models/concerns/deletable_dependencies.rb b/app/models/concerns/deletable_dependencies.rb new file mode 100644 index 000000000..121bfddf7 --- /dev/null +++ b/app/models/concerns/deletable_dependencies.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module DeletableDependencies + extend ActiveSupport::Concern + + ALLOW_DEPEDENCY_OPTIONS = %i[ + restrict_with_error + destroy + ].freeze + + included do + class_attribute :delete_dependency_config, instance_writer: false, default: {} + end + + class_methods do + def delete_dependency(only: nil, except: nil) + self.delete_dependency_config = { + only: Array(only).map(&:to_sym), + except: Array(except).map(&:to_sym), + } + end + end + + def delete_dependencies + self.class + .reflect_on_all_associations + .filter_map do |a| + # exclude according to config + next unless association_counts?(a) + + # get records + records = public_send(a.name) + next if records.blank? + + { + klass: a.klass, + records:, + } + end + end + + private + + def association_counts?(asso) + only = delete_dependency_config[:only] + expect = delete_dependency_config[:expect] + + # only is above default config + return only.include?(asso.name) unless only.nil? + + # default behavior + return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) + return false unless asso.name != changelog_entries + + # exept is not above default config + expect.nil? || expect.exclude?(asso.name) + end +end diff --git a/app/models/stack.rb b/app/models/stack.rb index 0a77f2b42..80b4ba478 100644 --- a/app/models/stack.rb +++ b/app/models/stack.rb @@ -5,6 +5,8 @@ class Stack < ApplicationRecord has_many :servers, dependent: :restrict_with_error + delete_dependency only: [:servers] + def to_s name end diff --git a/app/views/manufacturers/destroy.html.erb b/app/views/manufacturers/destroy.html.erb new file mode 100644 index 000000000..4278d68f2 --- /dev/null +++ b/app/views/manufacturers/destroy.html.erb @@ -0,0 +1,32 @@ +<% + breadcrumb + .add_step(@manufacturer, manufacturer_path(@manufacturer)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %> + +
+ +

+ <%= t(".delete-confirm") %> +

+ + <%= render ButtonComponent.new( + t("action.cancel"), + url: :back, + variant: :info, + is_responsive: true + )%> + + <%= render ButtonComponent.new( + t("action.delete"), + url: manufacturer_path(@manufacturer, confirm: true), + method: :delete, + variant: :danger, + icon: "trash", + is_responsive: true, + )%> + + <%= render DeleteDependency::MainComponent.new(@manufacturer) %> +
diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb index 5382d7420..5fe4e7794 100644 --- a/app/views/stacks/destroy.html.erb +++ b/app/views/stacks/destroy.html.erb @@ -3,22 +3,31 @@ .add_step(@stack, stack_path(@stack)) .add_step(t("action.delete")) %> + <%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %> +
+

<%= t(".delete-confirm") %>

+ <%= render ButtonComponent.new( t("action.cancel"), url: :back, + variant: :info, is_responsive: true )%> + <%= render ButtonComponent.new( t("action.delete"), - url: stack_path(@stack, confirm: true), + url: stack_path(@stack, confirm: @stack.servers.empty?), method: :delete, variant: :danger, icon: "trash", - is_responsive: true + is_responsive: true, + extra_classes: @stack.servers.empty? ? "" : "opacity-50" )%> + + <%= render DeleteDependency::MainComponent.new(@stack) %>
diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 2dc485fea..3d4062886 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -233,7 +233,8 @@ fr: updated: La stack a bien été modifiée. destroy: title: Suppression - delete-confirm: Voulez-vous vraiment supprimer cette ressource ? + delete-confirm: Voulez-vous vraiment supprimer cette Stack ? + dependencies_title: "Materiel dépendants :" flashes: destroyed: La stack a bien été supprimé. card_types: @@ -290,6 +291,8 @@ fr: flashes: updated: Le constructeur a bien été modifié. destroy: + title: Suppression + delete-confirm: Voulez-vous vraiment supprimer ce Constructeur ? flashes: destroyed: Le constructeur a bien été supprimé. domaines: From ee276ee35a22b22a3a18db70a15b3b646620e53f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Fri, 24 Oct 2025 12:47:44 +0200 Subject: [PATCH 03/33] implementing delete page for all model in sidebar. using default delete component exept for documents --- .../bay_collection_component.rb | 73 ------------------- .../delete_dependency/confirm_component.rb | 56 ++++++++++++++ .../delete_dependency/defaults_component.rb | 6 +- .../document_collection_component.rb | 32 ++++++++ .../delete_dependency/main_component.rb | 27 ------- .../modele_collection_component.rb | 47 ------------ .../server_collection_component.rb | 49 ------------- .../stack_collection_component.rb | 33 --------- .../air_conditioners_controller.rb | 5 ++ app/controllers/architectures_controller.rb | 5 ++ app/controllers/bays_controller.rb | 5 ++ app/controllers/card_types_controller.rb | 5 ++ app/controllers/categories_controller.rb | 5 ++ app/controllers/clusters_controller.rb | 5 ++ app/controllers/colors_controller.rb | 5 ++ .../contact_assignments_controller.rb | 5 ++ app/controllers/contact_roles_controller.rb | 5 ++ app/controllers/contacts_controller.rb | 5 ++ app/controllers/domaines_controller.rb | 5 ++ app/controllers/frames_controller.rb | 5 ++ app/controllers/gestions_controller.rb | 5 ++ app/controllers/islets_controller.rb | 5 ++ app/controllers/modeles_controller.rb | 5 ++ app/controllers/port_types_controller.rb | 5 ++ .../power_distribution_units_controller.rb | 5 ++ app/controllers/rooms_controller.rb | 5 ++ app/controllers/servers_controller.rb | 5 ++ app/controllers/sites_controller.rb | 5 ++ app/models/concerns/deletable_dependencies.rb | 5 +- app/views/air_conditioners/destroy.html.erb | 14 ++++ app/views/air_conditioners/index.html.erb | 3 +- app/views/architectures/destroy.html.erb | 14 ++++ app/views/architectures/index.html.erb | 1 - app/views/bays/destroy.html.erb | 14 ++++ app/views/bays/index.html.erb | 2 +- app/views/card_types/destroy.html.erb | 14 ++++ app/views/card_types/index.html.erb | 3 +- app/views/categories/destroy.html.erb | 14 ++++ app/views/categories/index.html.erb | 3 +- app/views/clusters/destroy.html.erb | 14 ++++ app/views/clusters/index.html.erb | 3 +- app/views/colors/destroy.html.erb | 14 ++++ app/views/colors/index.html.erb | 3 +- .../contact_assignments/destroy.html.erb | 14 ++++ app/views/contact_assignments/index.html.erb | 2 +- app/views/contact_roles/destroy.html.erb | 14 ++++ app/views/contact_roles/index.html.erb | 3 +- app/views/contacts/destroy.html.erb | 14 ++++ app/views/contacts/index.html.erb | 3 +- app/views/domaines/destroy.html.erb | 14 ++++ app/views/domaines/index.html.erb | 3 +- app/views/frames/destroy.html.erb | 14 ++++ app/views/frames/index.html.erb | 2 +- app/views/gestions/destroy.html.erb | 14 ++++ app/views/gestions/index.html.erb | 3 +- app/views/islets/destroy.html.erb | 14 ++++ app/views/islets/index.html.erb | 2 +- app/views/manufacturers/destroy.html.erb | 23 +----- app/views/manufacturers/index.html.erb | 3 +- app/views/modeles/destroy.html.erb | 13 ++++ app/views/modeles/index.html.erb | 2 +- app/views/port_types/destroy.html.erb | 14 ++++ app/views/port_types/index.html.erb | 3 +- .../power_distribution_units/destroy.html.erb | 14 ++++ .../power_distribution_units/index.html.erb | 2 +- app/views/rooms/destroy.html.erb | 14 ++++ app/views/rooms/index.html.erb | 2 +- app/views/servers/destroy.html.erb | 14 ++++ app/views/servers/index.html.erb | 2 +- app/views/sites/destroy.html.erb | 14 ++++ app/views/sites/index.html.erb | 2 +- app/views/stacks/destroy.html.erb | 23 +----- config/locales/fr.yml | 4 + 73 files changed, 502 insertions(+), 307 deletions(-) delete mode 100644 app/components/delete_dependency/bay_collection_component.rb create mode 100644 app/components/delete_dependency/confirm_component.rb create mode 100644 app/components/delete_dependency/document_collection_component.rb delete mode 100644 app/components/delete_dependency/main_component.rb delete mode 100644 app/components/delete_dependency/modele_collection_component.rb delete mode 100644 app/components/delete_dependency/server_collection_component.rb delete mode 100644 app/components/delete_dependency/stack_collection_component.rb create mode 100644 app/views/air_conditioners/destroy.html.erb create mode 100644 app/views/architectures/destroy.html.erb create mode 100644 app/views/bays/destroy.html.erb create mode 100644 app/views/card_types/destroy.html.erb create mode 100644 app/views/categories/destroy.html.erb create mode 100644 app/views/clusters/destroy.html.erb create mode 100644 app/views/colors/destroy.html.erb create mode 100644 app/views/contact_assignments/destroy.html.erb create mode 100644 app/views/contact_roles/destroy.html.erb create mode 100644 app/views/contacts/destroy.html.erb create mode 100644 app/views/domaines/destroy.html.erb create mode 100644 app/views/frames/destroy.html.erb create mode 100644 app/views/gestions/destroy.html.erb create mode 100644 app/views/islets/destroy.html.erb create mode 100644 app/views/modeles/destroy.html.erb create mode 100644 app/views/port_types/destroy.html.erb create mode 100644 app/views/power_distribution_units/destroy.html.erb create mode 100644 app/views/rooms/destroy.html.erb create mode 100644 app/views/servers/destroy.html.erb create mode 100644 app/views/sites/destroy.html.erb diff --git a/app/components/delete_dependency/bay_collection_component.rb b/app/components/delete_dependency/bay_collection_component.rb deleted file mode 100644 index 1c8a8cd39..000000000 --- a/app/components/delete_dependency/bay_collection_component.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class BayCollectionComponent < ApplicationComponent - erb_template <<~ERB -

<%= Bay.model_name.human %>

- <%= render List::DataTableComponent.new(@bays) do |table| %> - - <% table.with_column(Bay.human_attribute_name(:name), name: :name) do |bay| %> - <%= link_to bay_path(bay), class: "fw-bold", target: "_blank" do %> - <% bay.frames.any? ? bay.to_s : bay.decorated.no_frame_warning_icon %> - <% end %> - <% end %> - - <% table.with_column(Room.model_name.human, name: :room_id) do |bay| %> - <%= link_to bay.room, room_path(bay.room), target: "_blank" %> - <% end %> - - <% table.with_column(Islet.model_name.human, name: :islet_id) do |bay| %> - <%= link_to bay.islet.name_with_room, islet_path(bay.islet), target: "_blank" %> - <% end %> - - <% table.with_column(Frame.model_name.human.pluralize, name: :frame_id) do |bay| %> - <%= - bay.frames.map do |frame| - link_to(frame.name, frame_path(frame), target: "_blank") - end.join(" / ").html_safe - %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:lane), name: :lane) do |bay| %> - <%= bay.lane %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:position), name: :position) do |bay| %> - <%= bay.position %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:width), name: :width) do |bay| %> - <%= bay.width %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:depth), name: :depth) do |bay| %> - <%= bay.depth %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:bay_type_id), name: :bay_type_id) do |bay| %> - <%= bay.bay_type %> - <% end %> - - <% table.with_column(Bay.human_attribute_name(:access_control), name: :access_control) do |bay| %> - <%= bay.access_control %> - <% end %> - - - <% table.with_column(Server.model_name.human(count: 2), name: :server_id) do |bay| %> - <%= link_to servers_path(bay_ids: bay.id), target: "_blank" do %> - <%= Bay.human_attribute_name(:materials_count, count: bay.materials.count) %> - <% end %> - <% end %> - - <% table.with_column(Manufacturer.model_name.human, name: :manufacturer_id) do |bay| %> - <%= link_to bay.manufacturer.name, manufacturer_path(bay.manufacturer), target: "_blank" if bay.manufacturer %> - <% end %> - <% end %> - ERB - - def initialize(bays) - @bays = bays - super - end - end -end diff --git a/app/components/delete_dependency/confirm_component.rb b/app/components/delete_dependency/confirm_component.rb new file mode 100644 index 000000000..8ff706d14 --- /dev/null +++ b/app/components/delete_dependency/confirm_component.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module DeleteDependency + class ConfirmComponent < ApplicationComponent + erb_template <<~ERB + <% if @dependencies.empty? %> + +

<%= t(".confirm") %>

+ + <%= render ButtonComponent.new( + t("action.cancel"), + url: :back, + variant: :info, + is_responsive: true + )%> + + <%= render ButtonComponent.new( + t("action.delete"), + url: @full_delete_path, + method: :delete, + variant: :danger, + icon: "trash", + is_responsive: true, + )%> + + <% else %> + +

<%= t(".dependency_exist_message") %>

+ +
+ <% @dependencies.each do |dependency| %> +
+ <%= render component_for(dependency[:klass], dependency[:records], dependency[:asso_name]) %> +
+ <% end %> +
+ <% end %> + ERB + + def initialize(record, full_delete_path) + @dependencies = record.delete_dependencies + @full_delete_path = full_delete_path + super + end + + private + + def component_for(model, records, asso_name) + class_name = "DeleteDependency::#{model.model_name.name}CollectionComponent" + component_class = class_name.safe_constantize + return component_class.new(records, asso_name) unless component_class.nil? + + DeleteDependency::DefaultsComponent.new model, records, asso_name + end + end +end diff --git a/app/components/delete_dependency/defaults_component.rb b/app/components/delete_dependency/defaults_component.rb index 007329f5e..1ed53d697 100644 --- a/app/components/delete_dependency/defaults_component.rb +++ b/app/components/delete_dependency/defaults_component.rb @@ -4,6 +4,7 @@ module DeleteDependency class DefaultsComponent < ApplicationComponent erb_template <<~ERB

<%= @model.model_name.human %>

+

(<%= @asso_name %>)

    <% @records.each do |record| %>
  • @@ -13,9 +14,10 @@ class DefaultsComponent < ApplicationComponent
ERB - def initialize(model, records) + def initialize(model, records, asso_name) @model = model @records = records + @asso_name = asso_name super end @@ -24,7 +26,7 @@ def initialize(model, records) def show_link(record) link_to record.to_s, url_for(record), target: "_blank", rel: "noopener" rescue StandardError - "

#{record}

" + record.to_s end end end diff --git a/app/components/delete_dependency/document_collection_component.rb b/app/components/delete_dependency/document_collection_component.rb new file mode 100644 index 000000000..0554e2d70 --- /dev/null +++ b/app/components/delete_dependency/document_collection_component.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module DeleteDependency + class DocumentCollectionComponent < ApplicationComponent + erb_template <<~ERB +

<%= Document.model_name.human %>

+

(<%= @asso_name %>)

+
    + <% @docs.each do |doc| %> + <%- next unless doc.document.present? %> +
  • + <%= link_to(doc.document.metadata["filename"], doc.document_url, { target: :_blank }) %> +
  • + <% end %> +
+ ERB + + def initialize(docs, asso_name) + @docs = docs + @asso_name = asso_name + super + end + + private + + def show_link(record) + link_to record.to_s, url_for(record), target: "_blank", rel: "noopener" + rescue StandardError + record.to_s + end + end +end diff --git a/app/components/delete_dependency/main_component.rb b/app/components/delete_dependency/main_component.rb deleted file mode 100644 index 97e17121f..000000000 --- a/app/components/delete_dependency/main_component.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class MainComponent < ApplicationComponent - erb_template <<~ERB - <% @dependencies.each do |dependency| %> - <%= render component_for(dependency[:klass], dependency[:records]) %> - <% end %> - ERB - - def initialize(record) - @dependencies = record.delete_dependencies - - super - end - - private - - def component_for(model, records) - class_name = "DeleteDependency::#{model.model_name.name}CollectionComponent" - component_class = class_name.safe_constantize - return component_class.new(records) unless component_class.nil? - - DeleteDependency::DefaultsComponent.new model, records - end - end -end diff --git a/app/components/delete_dependency/modele_collection_component.rb b/app/components/delete_dependency/modele_collection_component.rb deleted file mode 100644 index b6c7b8d9d..000000000 --- a/app/components/delete_dependency/modele_collection_component.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class ModeleCollectionComponent < ApplicationComponent - include ModelesHelper - - erb_template <<~ERB -

<%= Modele.model_name.human %>

- <%= render List::DataTableComponent.new(@modeles) do |table| %> - - <% table.with_column(class: "p-0", style: "width: 40px; height: 40px;") do |modele| %> - <% bgModeleColor = modele.try(:color) || lighten_color("#\#{Digest::MD5.hexdigest(modele.try(:name) || "test")[0..5]}", 0.4) %> -
- <% end %> - - <% table.with_column(Modele.model_name.human) do |modele| %> - <%= link_to modele, modele_path(modele), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> - <% end %> - - <% table.with_column(Enclosure.human_attribute_name(:display)) do |modele| %> - <%= modele.decorated.displays_to_human %> - <% end %> - - <% table.with_column(Server.model_name.human(count: 2)) do |modele| %> - <%= link_to servers_path(modele_ids: modele.id), data: { turbo_frame: :_top }, target: "_blank" do %> - <%= pluralize(modele.servers.count, - modele.category.name.try(:downcase), - "\#{modele.category.name.try(:downcase)}\#{modele.category.name.blank? || - modele.category.name.end_with?("s") || - modele.category.name == "San" || - modele.category.name.end_with?("eau") ? "" : "s"}") - %> - <% end %> - <% end %> - - <% table.with_column(Modele.human_attribute_name(:network_types)) do |modele| %> - <%= modele.decorated.network_types_to_human %> - <% end %> - <% end %> - ERB - - def initialize(modeles) - @modeles = modeles - super - end - end -end diff --git a/app/components/delete_dependency/server_collection_component.rb b/app/components/delete_dependency/server_collection_component.rb deleted file mode 100644 index 1c6b21ed8..000000000 --- a/app/components/delete_dependency/server_collection_component.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class ServerCollectionComponent < ApplicationComponent - erb_template <<~ERB -

<%= Server.model_name.human %>

- <%= render List::DataTableComponent.new(@servers) do |table| %> - - <% table.with_column(Server.human_attribute_name(:name), name: :name) do |server| %> - <%= link_to server.name, server_path(server), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> - <% end %> - - <% table.with_column(Server.human_attribute_name(:numero), name: :numero) do |server| %> - <%= link_to server.numero, server_path(server), class: "fw-bold", data: { turbo_frame: :_top }, target: "_blank" %> - <% end %> - - <% table.with_column(Modele.human_attribute_name(:category), name: :"modele_category_id") do |server| %> - <%= link_to server.modele.category, category_path(server.modele.category), - data: { turbo_frame: :_top }, target: "_blank" if server.modele.try(:category) %> - <% end %> - - <% table.with_column(Server.human_attribute_name(:room), name: :room) do |server| %> - <%= link_to server.room, room_path(server.room), data: { turbo_frame: :_top }, target: "_blank" if server.room %> - <% end %> - - <% table.with_column(Islet.model_name.human, name: :islet_id) do |server| %> - <%= link_to server.islet, islet_path(server.islet), data: { turbo_frame: :_top }, target: "_blank" if server.islet %> - <% end %> - - <% table.with_column(Bay.model_name.human, name: :bay_id) do |server| %> - <%= link_to server.bay, bay_path(server.bay), data: { turbo_frame: :_top }, target: "_blank" if server.bay %> - <% end %> - - <% table.with_column(Server.human_attribute_name(:network_types), name: :network_types) do |server| %> - <%= server.decorated.network_types_to_human %> - <% end %> - - <% table.with_column(Server.human_attribute_name(:position), name: :position) do |server| %> - <%= server.position %> - <% end %> - <% end %> - ERB - - def initialize(servers) - @servers = servers - super - end - end -end diff --git a/app/components/delete_dependency/stack_collection_component.rb b/app/components/delete_dependency/stack_collection_component.rb deleted file mode 100644 index 8eb90670a..000000000 --- a/app/components/delete_dependency/stack_collection_component.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class StackCollectionComponent < ApplicationComponent - erb_template <<~ERB -

<%= Stack.model_name.human %>

- - - - - - - - - - <% @stacks.each do |stack| %> - - - - - - <% end %> - -
<%= Stack.human_attribute_name(:name) %><%= Stack.human_attribute_name(:color) %><%= Stack.human_attribute_name(:servers) %>
<%= link_to stack, stack_path(stack), target: "_blank" %><%= stack.color %><%= link_to Stack.human_attribute_name(:servers_count, count: stack.servers_count), - servers_path(stack_ids: stack.id), target: "_blank" %>
- ERB - - def initialize(stacks) - @stacks = stacks - super - end - end -end diff --git a/app/controllers/air_conditioners_controller.rb b/app/controllers/air_conditioners_controller.rb index 087abd77a..82d7161ff 100644 --- a/app/controllers/air_conditioners_controller.rb +++ b/app/controllers/air_conditioners_controller.rb @@ -49,6 +49,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + @air_conditioner.destroy! respond_to do |format| diff --git a/app/controllers/architectures_controller.rb b/app/controllers/architectures_controller.rb index 65384da07..598af67cb 100644 --- a/app/controllers/architectures_controller.rb +++ b/app/controllers/architectures_controller.rb @@ -57,6 +57,11 @@ def update # DELETE /architectures/1 # DELETE /architectures/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @architecture.destroy respond_to do |format| format.html { redirect_to architectures_url, notice: t(".destroy.flashes.destroyed") } diff --git a/app/controllers/bays_controller.rb b/app/controllers/bays_controller.rb index 547db57f1..157a66d74 100644 --- a/app/controllers/bays_controller.rb +++ b/app/controllers/bays_controller.rb @@ -62,6 +62,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + if @bay.destroy respond_to do |format| format.html { form_redirect_to bays_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/card_types_controller.rb b/app/controllers/card_types_controller.rb index 3b1f0a1b1..5f2eaf026 100644 --- a/app/controllers/card_types_controller.rb +++ b/app/controllers/card_types_controller.rb @@ -55,6 +55,11 @@ def update # DELETE /card_types/1 # DELETE /card_types/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @card_type.destroy respond_to do |format| format.html { redirect_to card_types_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 551eb0e00..52b859b42 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -58,6 +58,11 @@ def update # DELETE /categories/1 # DELETE /categories/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @category.destroy respond_to do |format| format.html { redirect_to categories_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/clusters_controller.rb b/app/controllers/clusters_controller.rb index f89fbd69c..e8a2ca793 100644 --- a/app/controllers/clusters_controller.rb +++ b/app/controllers/clusters_controller.rb @@ -59,6 +59,11 @@ def update # DELETE /clusters/1 # DELETE /clusters/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @cluster.destroy respond_to do |format| format.html { redirect_to clusters_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/colors_controller.rb b/app/controllers/colors_controller.rb index 4c9dc3f0d..b6b1ed31c 100644 --- a/app/controllers/colors_controller.rb +++ b/app/controllers/colors_controller.rb @@ -49,6 +49,11 @@ def update # DELETE /colors/1 # DELETE /colors/1.json def destroy + unless params["confirm"] == "true" + render + return + end + @color.destroy respond_to do |format| format.html { redirect_to colors_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contact_assignments_controller.rb b/app/controllers/contact_assignments_controller.rb index c2387d880..19f34573a 100644 --- a/app/controllers/contact_assignments_controller.rb +++ b/app/controllers/contact_assignments_controller.rb @@ -60,6 +60,11 @@ def update # DELETE /contact_assignments/1 # DELETE /contact_assignments/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @contact_assignment.destroy! respond_to do |format| format.html { redirect_to contact_assignments_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contact_roles_controller.rb b/app/controllers/contact_roles_controller.rb index 43928eb7e..952f4b9f9 100644 --- a/app/controllers/contact_roles_controller.rb +++ b/app/controllers/contact_roles_controller.rb @@ -58,6 +58,11 @@ def update # DELETE /contact_roles/1 # DELETE /contact_roles/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @contact_role.destroy respond_to do |format| format.html { redirect_to contact_roles_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index 1006ec008..b6224fa99 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -58,6 +58,11 @@ def update # DELETE /contacts/1 # DELETE /contacts/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @contact.destroy respond_to do |format| format.html { redirect_to contacts_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/domaines_controller.rb b/app/controllers/domaines_controller.rb index 80fac7c1a..20d84996f 100644 --- a/app/controllers/domaines_controller.rb +++ b/app/controllers/domaines_controller.rb @@ -57,6 +57,11 @@ def update # DELETE /domaines/1 # DELETE /domaines/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @domaine.destroy respond_to do |format| format.html { redirect_to domaines_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/frames_controller.rb b/app/controllers/frames_controller.rb index 33ead433f..ad667ecfc 100644 --- a/app/controllers/frames_controller.rb +++ b/app/controllers/frames_controller.rb @@ -65,6 +65,11 @@ def sort end def destroy + unless params["confirm"] == "true" + render + return + end + if @frame.destroy respond_to do |format| format.html { redirect_to frames_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/gestions_controller.rb b/app/controllers/gestions_controller.rb index b4cec4373..386f8e52a 100644 --- a/app/controllers/gestions_controller.rb +++ b/app/controllers/gestions_controller.rb @@ -57,6 +57,11 @@ def update # DELETE /gestions/1 # DELETE /gestions/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @gestion.destroy respond_to do |format| format.html { redirect_to gestions_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/islets_controller.rb b/app/controllers/islets_controller.rb index b10028a7f..e66c163e0 100644 --- a/app/controllers/islets_controller.rb +++ b/app/controllers/islets_controller.rb @@ -66,6 +66,11 @@ def update # DELETE /islets/1 # DELETE /islets/1.json def destroy + unless params["confirm"] == "true" + render + return + end + if @islet.destroy respond_to do |format| format.html { redirect_to islets_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/modeles_controller.rb b/app/controllers/modeles_controller.rb index b08010111..06cb5eb82 100644 --- a/app/controllers/modeles_controller.rb +++ b/app/controllers/modeles_controller.rb @@ -79,6 +79,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + if @modele.destroy respond_to do |format| format.html { redirect_to modeles_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/port_types_controller.rb b/app/controllers/port_types_controller.rb index 1cc232d10..e26c026ec 100644 --- a/app/controllers/port_types_controller.rb +++ b/app/controllers/port_types_controller.rb @@ -45,6 +45,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + @port_type.destroy respond_to do |format| format.html { redirect_to port_types_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/power_distribution_units_controller.rb b/app/controllers/power_distribution_units_controller.rb index f2d0a4d2c..70b37970e 100644 --- a/app/controllers/power_distribution_units_controller.rb +++ b/app/controllers/power_distribution_units_controller.rb @@ -59,6 +59,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + respond_to do |format| if @pdu.destroy format.html { redirect_to power_distribution_units_path(search_params), notice: t(".flashes.destroyed") } diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 50b22ef41..560cfed73 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -56,6 +56,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + if @room.destroy respond_to do |format| format.html { redirect_to rooms_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index dc8ca39ab..9d7fa0b4d 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -74,6 +74,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + respond_to do |format| if @server.destroy format.html { redirect_to servers_path(search_params), notice: t(".flashes.destroyed") } diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index f05ca808b..a11220ef9 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -48,6 +48,11 @@ def update end def destroy + unless params["confirm"] == "true" + render + return + end + if @site.destroy respond_to do |format| format.html { redirect_to sites_url, notice: t(".flashes.destroyed") } diff --git a/app/models/concerns/deletable_dependencies.rb b/app/models/concerns/deletable_dependencies.rb index 121bfddf7..edf0f5c68 100644 --- a/app/models/concerns/deletable_dependencies.rb +++ b/app/models/concerns/deletable_dependencies.rb @@ -5,7 +5,6 @@ module DeletableDependencies ALLOW_DEPEDENCY_OPTIONS = %i[ restrict_with_error - destroy ].freeze included do @@ -34,6 +33,7 @@ def delete_dependencies { klass: a.klass, + asso_name: a.name, records:, } end @@ -50,7 +50,8 @@ def association_counts?(asso) # default behavior return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) - return false unless asso.name != changelog_entries + return false if %i[changelog_entries slugs].include? asso.name + return false if asso.class_name.start_with?("ActiveStorage::") # exept is not above default config expect.nil? || expect.exclude?(asso.name) diff --git a/app/views/air_conditioners/destroy.html.erb b/app/views/air_conditioners/destroy.html.erb new file mode 100644 index 000000000..84a81721e --- /dev/null +++ b/app/views/air_conditioners/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@air_conditioner, air_conditioner_path(@air_conditioner)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@air_conditioner, air_conditioner_path(@air_conditioner, confirm: true)) %> + +
diff --git a/app/views/air_conditioners/index.html.erb b/app/views/air_conditioners/index.html.erb index 37f6e421d..9327e9ec9 100644 --- a/app/views/air_conditioners/index.html.erb +++ b/app/views/air_conditioners/index.html.erb @@ -71,8 +71,7 @@ <% end %> <% if allowed_to?(:destroy?, air_conditioner) %> - <%= link_to air_conditioner, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to air_conditioner, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/architectures/destroy.html.erb b/app/views/architectures/destroy.html.erb new file mode 100644 index 000000000..bd28ce476 --- /dev/null +++ b/app/views/architectures/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@architecture, architecture_path(@architecture)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@architecture, architecture_path(@architecture, confirm: true)) %> + +
diff --git a/app/views/architectures/index.html.erb b/app/views/architectures/index.html.erb index 5ebc6041e..1d097571a 100644 --- a/app/views/architectures/index.html.erb +++ b/app/views/architectures/index.html.erb @@ -50,7 +50,6 @@ <% if allowed_to?(:destroy?, architecture) %> <%= link_to architecture_path(architecture), method: :delete, - data: { confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> " diff --git a/app/views/bays/destroy.html.erb b/app/views/bays/destroy.html.erb new file mode 100644 index 000000000..fd429d4a5 --- /dev/null +++ b/app/views/bays/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@bay, bay_path(@bay)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@bay, bay_path(@bay, confirm: true)) %> + +
diff --git a/app/views/bays/index.html.erb b/app/views/bays/index.html.erb index 8e991a889..1b9dd67fe 100644 --- a/app/views/bays/index.html.erb +++ b/app/views/bays/index.html.erb @@ -162,7 +162,7 @@ <% if allowed_to?(:destroy?, bay) %> <%= link_to bay, method: :delete, - data: { turbo_frame: :_top, confirm: t(".delete_confirmation") }, + data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" diff --git a/app/views/card_types/destroy.html.erb b/app/views/card_types/destroy.html.erb new file mode 100644 index 000000000..16d7ef972 --- /dev/null +++ b/app/views/card_types/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@card_type, card_type_path(@card_type)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@card_type, card_type_path(@card_type, confirm: true)) %> + +
diff --git a/app/views/card_types/index.html.erb b/app/views/card_types/index.html.erb index f85a0d880..8cc33034e 100644 --- a/app/views/card_types/index.html.erb +++ b/app/views/card_types/index.html.erb @@ -69,8 +69,7 @@ <% end %> <% if allowed_to?(:destroy?, card_type) %> - <%= link_to card_type_path(card_type), method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to card_type_path(card_type), method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb new file mode 100644 index 000000000..b0fa1e410 --- /dev/null +++ b/app/views/categories/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@category, category_path(@category)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@category, category_path(@category, confirm: true)) %> + +
diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb index fff5bc84b..53cfe0d72 100644 --- a/app/views/categories/index.html.erb +++ b/app/views/categories/index.html.erb @@ -54,8 +54,7 @@ <% end %> <% if allowed_to?(:destroy?, category) %> - <%= link_to category, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to category, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/clusters/destroy.html.erb b/app/views/clusters/destroy.html.erb new file mode 100644 index 000000000..78329d849 --- /dev/null +++ b/app/views/clusters/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@cluster, cluster_path(@cluster)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@cluster, cluster_path(@cluster, confirm: true)) %> + +
diff --git a/app/views/clusters/index.html.erb b/app/views/clusters/index.html.erb index efa8b9dc7..97f006a23 100644 --- a/app/views/clusters/index.html.erb +++ b/app/views/clusters/index.html.erb @@ -58,8 +58,7 @@ <% end %> <% if allowed_to?(:destroy?, cluster) %> - <%= link_to cluster, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to cluster, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/colors/destroy.html.erb b/app/views/colors/destroy.html.erb new file mode 100644 index 000000000..818477813 --- /dev/null +++ b/app/views/colors/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@color, color_path(@color)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@color, color_path(@color, confirm: true)) %> + +
diff --git a/app/views/colors/index.html.erb b/app/views/colors/index.html.erb index 8d11240fa..b92065c86 100644 --- a/app/views/colors/index.html.erb +++ b/app/views/colors/index.html.erb @@ -44,8 +44,7 @@ <% end %> <% end %> <% if allowed_to?(:destroy?, color) %> - <%= link_to color_path(color), method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to color_path(color), method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/contact_assignments/destroy.html.erb b/app/views/contact_assignments/destroy.html.erb new file mode 100644 index 000000000..d1a0cf52f --- /dev/null +++ b/app/views/contact_assignments/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@contact_assignment, contact_assignment_path(@contact_assignment)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@contact_assignment, contact_assignment_path(@contact_assignment, confirm: true)) %> + +
diff --git a/app/views/contact_assignments/index.html.erb b/app/views/contact_assignments/index.html.erb index dd5c0886b..c929383f9 100644 --- a/app/views/contact_assignments/index.html.erb +++ b/app/views/contact_assignments/index.html.erb @@ -91,7 +91,7 @@ <% end %> <% if allowed_to?(:destroy?, contact_assignment) %> - <%= link_to contact_assignment, method: :delete, data: { turbo_frame: :_top, confirm: t(".delete_confirmation") }, + <%= link_to contact_assignment, method: :delete, data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" diff --git a/app/views/contact_roles/destroy.html.erb b/app/views/contact_roles/destroy.html.erb new file mode 100644 index 000000000..9a237c8b8 --- /dev/null +++ b/app/views/contact_roles/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@contact_role, contact_role_path(@contact_role)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@contact_role, contact_role_path(@contact_role, confirm: true)) %> + +
diff --git a/app/views/contact_roles/index.html.erb b/app/views/contact_roles/index.html.erb index a0cabe6ec..5753a055a 100644 --- a/app/views/contact_roles/index.html.erb +++ b/app/views/contact_roles/index.html.erb @@ -45,8 +45,7 @@ <% end %> <% if allowed_to?(:destroy?, contact_role) %> - <%= link_to contact_role, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to contact_role, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/contacts/destroy.html.erb b/app/views/contacts/destroy.html.erb new file mode 100644 index 000000000..3dbe00b88 --- /dev/null +++ b/app/views/contacts/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@contact, contact_path(@contact)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@contact, contact_path(@contact, confirm: true)) %> + +
diff --git a/app/views/contacts/index.html.erb b/app/views/contacts/index.html.erb index 2bfa1567a..95f165dc1 100644 --- a/app/views/contacts/index.html.erb +++ b/app/views/contacts/index.html.erb @@ -53,8 +53,7 @@ <% end %> <% if allowed_to?(:destroy?, contact) %> - <%= link_to contact, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to contact, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/domaines/destroy.html.erb b/app/views/domaines/destroy.html.erb new file mode 100644 index 000000000..e82b9e50a --- /dev/null +++ b/app/views/domaines/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@domaine, domaine_path(@domaine)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@domaine, manufacturer_path(@domaine, confirm: true)) %> + +
diff --git a/app/views/domaines/index.html.erb b/app/views/domaines/index.html.erb index 413a43a92..d326242ed 100644 --- a/app/views/domaines/index.html.erb +++ b/app/views/domaines/index.html.erb @@ -46,8 +46,7 @@ <% end %> <% if allowed_to?(:destroy?, domaine) %> - <%= link_to domaine, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to domaine, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/frames/destroy.html.erb b/app/views/frames/destroy.html.erb new file mode 100644 index 000000000..856de6918 --- /dev/null +++ b/app/views/frames/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@frame.name, frame_path(@frame)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@frame, frame_path(@frame, confirm: true)) %> + +
diff --git a/app/views/frames/index.html.erb b/app/views/frames/index.html.erb index 62881e405..8815ed1fb 100644 --- a/app/views/frames/index.html.erb +++ b/app/views/frames/index.html.erb @@ -113,7 +113,7 @@ <% end %> <% if allowed_to?(:destroy?, frame) %> - <%= link_to frame, method: :delete, data: { turbo_frame: :_top, confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> + <%= link_to frame, method: :delete, data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/gestions/destroy.html.erb b/app/views/gestions/destroy.html.erb new file mode 100644 index 000000000..8bf153d1f --- /dev/null +++ b/app/views/gestions/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@gestion, gestion_path(@gestion)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@gestion, gestion_path(@gestion, confirm: true)) %> + +
diff --git a/app/views/gestions/index.html.erb b/app/views/gestions/index.html.erb index 629fd4f3b..638f0597b 100644 --- a/app/views/gestions/index.html.erb +++ b/app/views/gestions/index.html.erb @@ -46,8 +46,7 @@ <% end %> <% if allowed_to?(:destroy?, gestion) %> - <%= link_to gestion, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to gestion, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/islets/destroy.html.erb b/app/views/islets/destroy.html.erb new file mode 100644 index 000000000..f4d2920c5 --- /dev/null +++ b/app/views/islets/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@islet, islet_path(@islet)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@islet, islet_path(@islet, confirm: true)) %> + +
diff --git a/app/views/islets/index.html.erb b/app/views/islets/index.html.erb index bb3e05c39..666fb6c18 100644 --- a/app/views/islets/index.html.erb +++ b/app/views/islets/index.html.erb @@ -100,7 +100,7 @@ <% end %> <% if allowed_to?(:destroy?, islet) %> - <%= link_to islet, method: :delete, data: { turbo_frame: :_top, confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> + <%= link_to islet, method: :delete, data: { turbo_frame: :_top }, class: "btn btn-danger" do %> <%= t("action.delete") %> <% end %> diff --git a/app/views/manufacturers/destroy.html.erb b/app/views/manufacturers/destroy.html.erb index 4278d68f2..a59b5b279 100644 --- a/app/views/manufacturers/destroy.html.erb +++ b/app/views/manufacturers/destroy.html.erb @@ -4,29 +4,10 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
-

- <%= t(".delete-confirm") %> -

+ <%= render DeleteDependency::ConfirmComponent.new(@manufacturer, manufacturer_path(@manufacturer, confirm: true)) %> - <%= render ButtonComponent.new( - t("action.cancel"), - url: :back, - variant: :info, - is_responsive: true - )%> - - <%= render ButtonComponent.new( - t("action.delete"), - url: manufacturer_path(@manufacturer, confirm: true), - method: :delete, - variant: :danger, - icon: "trash", - is_responsive: true, - )%> - - <%= render DeleteDependency::MainComponent.new(@manufacturer) %>
diff --git a/app/views/manufacturers/index.html.erb b/app/views/manufacturers/index.html.erb index 0d5e56fe3..112719db4 100644 --- a/app/views/manufacturers/index.html.erb +++ b/app/views/manufacturers/index.html.erb @@ -53,8 +53,7 @@ <% end %> <% if allowed_to?(:destroy?, manufacturer) %> - <%= link_to manufacturer, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to manufacturer, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/modeles/destroy.html.erb b/app/views/modeles/destroy.html.erb new file mode 100644 index 000000000..915a2d08b --- /dev/null +++ b/app/views/modeles/destroy.html.erb @@ -0,0 +1,13 @@ +<% + breadcrumb + .add_step(@modele, modele_path(@modele)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + <%= render DeleteDependency::ConfirmComponent.new(@modele, modele_path(@modele, confirm: true)) %> + +
diff --git a/app/views/modeles/index.html.erb b/app/views/modeles/index.html.erb index 03d59764f..a0a99d620 100644 --- a/app/views/modeles/index.html.erb +++ b/app/views/modeles/index.html.erb @@ -119,7 +119,7 @@ <% end %> <% if allowed_to?(:destroy?, modele) %> - <%= link_to modele, method: :delete, data: { confirm: t(".delete_confirmation"), turbo_frame: :_top }, class: 'btn btn-danger' do %> + <%= link_to modele, method: :delete, data: { turbo_frame: :_top }, class: 'btn btn-danger' do %> <%= t("action.delete") %> <% end %> diff --git a/app/views/port_types/destroy.html.erb b/app/views/port_types/destroy.html.erb new file mode 100644 index 000000000..34d7d5cb9 --- /dev/null +++ b/app/views/port_types/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@port_type, port_type_path(@port_type)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@port_type, port_type_path(@port_type, confirm: true)) %> + +
diff --git a/app/views/port_types/index.html.erb b/app/views/port_types/index.html.erb index 960075866..e7ea20021 100644 --- a/app/views/port_types/index.html.erb +++ b/app/views/port_types/index.html.erb @@ -52,8 +52,7 @@ <% end %> <% if allowed_to?(:destroy?, port_type) %> - <%= link_to port_type, method: :delete, data: { confirm: t(".delete_confirmation") }, - class: "btn btn-danger" do %> + <%= link_to port_type, method: :delete, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/app/views/power_distribution_units/destroy.html.erb b/app/views/power_distribution_units/destroy.html.erb new file mode 100644 index 000000000..5fb7d1c8f --- /dev/null +++ b/app/views/power_distribution_units/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@pdu, power_distribution_unit_path(@pdu)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@pdu, power_distribution_unit_path(@pdu, confirm: true)) %> + +
diff --git a/app/views/power_distribution_units/index.html.erb b/app/views/power_distribution_units/index.html.erb index 490e3c9be..e3f381933 100644 --- a/app/views/power_distribution_units/index.html.erb +++ b/app/views/power_distribution_units/index.html.erb @@ -150,7 +150,7 @@ <% if allowed_to?(:destroy?, pdu, with: PowerDistributionUnitPolicy) %> <%= link_to power_distribution_unit_path(pdu, @filter.attributes), method: :delete, - data: { turbo_frame: :_top, confirm: t("action.confirm") }, + data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" diff --git a/app/views/rooms/destroy.html.erb b/app/views/rooms/destroy.html.erb new file mode 100644 index 000000000..6745fffe6 --- /dev/null +++ b/app/views/rooms/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@room, room_path(@room)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@room, room_path(@room, confirm: true)) %> + +
diff --git a/app/views/rooms/index.html.erb b/app/views/rooms/index.html.erb index dcebf39db..73ec812f7 100644 --- a/app/views/rooms/index.html.erb +++ b/app/views/rooms/index.html.erb @@ -103,7 +103,7 @@ <% end %> <% if allowed_to?(:destroy?, room) %> - <%= link_to room, method: :delete, data: { turbo_frame: :_top, confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> + <%= link_to room, method: :delete, data: { turbo_frame: :_top }, class: "btn btn-danger" do %> <%= t("action.delete") %> <% end %> diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb new file mode 100644 index 000000000..60eaeed95 --- /dev/null +++ b/app/views/servers/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@server, server_path(@server)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@server, server_path(@server, confirm: true)) %> + +
diff --git a/app/views/servers/index.html.erb b/app/views/servers/index.html.erb index d3c69a587..fe5227a12 100644 --- a/app/views/servers/index.html.erb +++ b/app/views/servers/index.html.erb @@ -277,7 +277,7 @@ <% if allowed_to?(:destroy?, server) %> <%= link_to server_path(server, @filter.attributes), method: :delete, - data: { turbo_frame: :_top, confirm: t("action.confirm") }, + data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" diff --git a/app/views/sites/destroy.html.erb b/app/views/sites/destroy.html.erb new file mode 100644 index 000000000..71b7d6067 --- /dev/null +++ b/app/views/sites/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@site, site_path(@site)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
+ + + <%= render DeleteDependency::ConfirmComponent.new(@site, site_path(@site, confirm: true)) %> + +
diff --git a/app/views/sites/index.html.erb b/app/views/sites/index.html.erb index d17f7bb98..a347991ed 100644 --- a/app/views/sites/index.html.erb +++ b/app/views/sites/index.html.erb @@ -51,7 +51,7 @@ <% end %> <% if allowed_to?(:destroy?, site) %> - <%= link_to site, method: :delete, data: { confirm: t(".delete_confirmation") }, class: "btn btn-danger" do %> + <%= link_to site, method: :delete, class: "btn btn-danger" do %> <%= t("action.delete") %> <% end %> diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb index 5fe4e7794..d73e01ddd 100644 --- a/app/views/stacks/destroy.html.erb +++ b/app/views/stacks/destroy.html.erb @@ -4,30 +4,11 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
-

- <%= t(".delete-confirm") %> -

- <%= render ButtonComponent.new( - t("action.cancel"), - url: :back, - variant: :info, - is_responsive: true - )%> + <%= render DeleteDependency::ConfirmComponent.new(@stack, stack_path(@stack, confirm: true)) %> - <%= render ButtonComponent.new( - t("action.delete"), - url: stack_path(@stack, confirm: @stack.servers.empty?), - method: :delete, - variant: :danger, - icon: "trash", - is_responsive: true, - extra_classes: @stack.servers.empty? ? "" : "opacity-50" - )%> - - <%= render DeleteDependency::MainComponent.new(@stack) %>
diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 3d4062886..75cf0a8eb 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -979,3 +979,7 @@ fr: no_results_found: Aucun résultat trouvé select: placeholder: Tapez pour filtrer... + delete_dependency: + confirm_component: + dependency_exist_message: "La suppression est impossible à cause de ces resources :" + confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. From f687f251e241c5efd5ac1c99ebd4d0dc98b02bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Mon, 27 Oct 2025 16:30:59 +0100 Subject: [PATCH 04/33] updating test for model with delete page --- spec/requests/bays_controller_request_spec.rb | 18 +++++++++- .../card_types_controller_request_spec.rb | 18 +++++++++- ...act_assignments_controller_request_spec.rb | 33 +++++++++++++++---- .../contact_roles_controller_request_spec.rb | 32 ++++++++++++++---- .../contacts_controller_request_spec.rb | 32 ++++++++++++++---- .../frames_controller_request_spec.rb | 18 +++++++++- .../islets_controller_request_spec.rb | 18 +++++++++- .../modeles_controller_request_spec.rb | 18 +++++++++- ...tribution_units_controller_request_spec.rb | 26 ++++++++++++--- .../servers_controller_request_spec.rb | 28 ++++++++++++---- .../stacks_controller_request_spec.rb | 18 +++++++++- 11 files changed, 224 insertions(+), 35 deletions(-) diff --git a/spec/requests/bays_controller_request_spec.rb b/spec/requests/bays_controller_request_spec.rb index 2b724af96..e093db0ba 100644 --- a/spec/requests/bays_controller_request_spec.rb +++ b/spec/requests/bays_controller_request_spec.rb @@ -183,7 +183,7 @@ describe "DELETE #destroy" do subject(:response) do - delete bay_path(bay), params:, headers: { REFERER: "/visualization/rooms" } + delete bay_path(bay, confirm: true), params:, headers: { REFERER: "/visualization/rooms" } # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -193,6 +193,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete bay_path(bay), params:, headers: { REFERER: "/rooms/overview" } + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Bay, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Bay.exists?(bay.id)).to be true } + end + context "with bay without any frames" do let(:bay) { bays(:three) } diff --git a/spec/requests/card_types_controller_request_spec.rb b/spec/requests/card_types_controller_request_spec.rb index b27166ead..7e86692fe 100644 --- a/spec/requests/card_types_controller_request_spec.rb +++ b/spec/requests/card_types_controller_request_spec.rb @@ -162,7 +162,7 @@ describe "DELETE #destroy" do subject(:response) do - delete card_type_path(card_type) + delete card_type_path(card_type, confirm: true) # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -170,6 +170,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete card_type_path(card_type) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(CardType, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(CardType.exists?(card_type.id)).to be true } + end + context "with an card_type without cards" do let(:card_type) { card_types(:three) } diff --git a/spec/requests/contact_assignments_controller_request_spec.rb b/spec/requests/contact_assignments_controller_request_spec.rb index fc4e379a2..8fe20f06d 100644 --- a/spec/requests/contact_assignments_controller_request_spec.rb +++ b/spec/requests/contact_assignments_controller_request_spec.rb @@ -138,17 +138,38 @@ end describe "#destroy" do + subject(:response) do + delete contact_assignment_path(contact_assignment, confirm: true) + + @response # rubocop:disable RSpec/InstanceVariable + end + before { contact_assignment } - it "destroys the requested contact_assignment" do - expect do + context "without confirm" do + subject(:response) do delete contact_assignment_path(contact_assignment) - end.to change(ContactAssignment, :count).by(-1) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(ContactAssignment, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(ContactAssignment.exists?(contact_assignment.id)).to be true } end - it "redirects to the contact_assignments list" do - delete contact_assignment_path(contact_assignment) - expect(response).to redirect_to(contact_assignments_path) + context "with confirm" do + it "destroys the requested contact_assignment" do + expect { response }.to change(ContactAssignment, :count).by(-1) + end + + it "redirects to the contact_assignments list" do + expect(response).to redirect_to(contact_assignments_path) + end end end end diff --git a/spec/requests/contact_roles_controller_request_spec.rb b/spec/requests/contact_roles_controller_request_spec.rb index 6d80ad3df..e4e4fe399 100644 --- a/spec/requests/contact_roles_controller_request_spec.rb +++ b/spec/requests/contact_roles_controller_request_spec.rb @@ -129,15 +129,35 @@ end describe "#destroy" do - it "destroys the requested contact_role" do - expect do + subject(:response) do + delete contact_role_path(contact_role, confirm: true) + @response # rubocop:disable RSpec/InstanceVariable + end + + context "without confirm" do + subject(:response) do delete contact_role_path(contact_role) - end.to change(ContactRole, :count).by(-1) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(ContactRole, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(ContactRole.exists?(contact_role.id)).to be true } end - it "redirects to the contact_roles list" do - delete contact_role_path(contact_role) - expect(response).to redirect_to(contact_roles_path) + context "with confirm" do + it "destroys the requested contact_role" do + expect { response }.to change(ContactRole, :count).by(-1) + end + + it "redirects to the contact_roles list" do + expect(response).to redirect_to(contact_roles_path) + end end end end diff --git a/spec/requests/contacts_controller_request_spec.rb b/spec/requests/contacts_controller_request_spec.rb index 59b6d1639..27269c468 100644 --- a/spec/requests/contacts_controller_request_spec.rb +++ b/spec/requests/contacts_controller_request_spec.rb @@ -129,15 +129,35 @@ end describe "#destroy" do - it "destroys the requested contact" do - expect do + subject(:response) do + delete contact_path(contact, confirm: true) + @response # rubocop:disable RSpec/InstanceVariable + end + + context "without confirm" do + subject(:response) do delete contact_path(contact) - end.to change(Contact, :count).by(-1) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Contact, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Contact.exists?(contact.id)).to be true } end - it "redirects to the contacts list" do - delete contact_path(contact) - expect(response).to redirect_to(contacts_path) + context "with confirm" do + it "destroys the requested contact" do + expect { response }.to change(Contact, :count).by(-1) + end + + it "redirects to the contacts list" do + expect(response).to redirect_to(contacts_path) + end end end end diff --git a/spec/requests/frames_controller_request_spec.rb b/spec/requests/frames_controller_request_spec.rb index fdf5e601c..4a364c32e 100644 --- a/spec/requests/frames_controller_request_spec.rb +++ b/spec/requests/frames_controller_request_spec.rb @@ -181,7 +181,7 @@ describe "DELETE #destroy" do subject(:response) do - delete frame_path(frame) + delete frame_path(frame, confirm: true) # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -189,6 +189,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete frame_path(frame) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Frame, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Frame.exists?(frame.id)).to be true } + end + context "with frame without any IT equipments" do let(:frame) { frames(:two) } diff --git a/spec/requests/islets_controller_request_spec.rb b/spec/requests/islets_controller_request_spec.rb index 5bc60af70..7e1e1a5f2 100644 --- a/spec/requests/islets_controller_request_spec.rb +++ b/spec/requests/islets_controller_request_spec.rb @@ -164,7 +164,7 @@ describe "DELETE #destroy" do subject(:response) do - delete islet_path(islet) + delete islet_path(islet, confirm: true) # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -172,6 +172,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete islet_path(islet) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Islet, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Islet.exists?(islet.id)).to be true } + end + context "with an islet without bays" do let(:islet) { islets(:three) } diff --git a/spec/requests/modeles_controller_request_spec.rb b/spec/requests/modeles_controller_request_spec.rb index 110f527f3..97b4a2073 100644 --- a/spec/requests/modeles_controller_request_spec.rb +++ b/spec/requests/modeles_controller_request_spec.rb @@ -202,7 +202,7 @@ describe "DELETE #destroy" do subject(:response) do - delete modele_path(modele) + delete modele_path(modele, confirm: true) # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -210,6 +210,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete modele_path(modele) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Modele, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Modele.exists?(modele.id)).to be true } + end + context "with a modele not referenced on Server" do let(:modele) { modeles(:four) } diff --git a/spec/requests/power_distribution_units_controller_request_spec.rb b/spec/requests/power_distribution_units_controller_request_spec.rb index db439eedf..0aeda0095 100644 --- a/spec/requests/power_distribution_units_controller_request_spec.rb +++ b/spec/requests/power_distribution_units_controller_request_spec.rb @@ -197,20 +197,36 @@ end describe "DELETE #destroy" do + context "without confirm" do + subject(:response) do + delete power_distribution_unit_path(pdu2) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Server, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Server.exists?(pdu2.id)).to be true } + end + context "with a pdu without association" do it "destroys the requested pdu" do expect do - delete power_distribution_unit_path(pdu2) + delete power_distribution_unit_path(pdu2, confirm: true) end.to change(Server, :count).by(-1) end it "redirects to the pdus list" do - delete power_distribution_unit_path(pdu2) + delete power_distribution_unit_path(pdu2, confirm: true) expect(response).to redirect_to(power_distribution_units_path) end it "redirects to the pdus list and keep params" do - delete power_distribution_unit_path(pdu2, params: { sort: "asc", sort_by: "rooms.name" }) + delete power_distribution_unit_path(pdu2, confirm: true, params: { sort: "asc", sort_by: "rooms.name" }) expect(response).to redirect_to(power_distribution_units_path({ sort: "asc", sort_by: "rooms.name" })) end end @@ -218,12 +234,12 @@ context "with a pdu with association" do it "does not destroy the requested pdu" do expect do - delete power_distribution_unit_path(pdu) + delete power_distribution_unit_path(pdu, confirm: true) end.not_to change(Server, :count) end it "redirects to the pdus list" do - delete power_distribution_unit_path(pdu) + delete power_distribution_unit_path(pdu, confirm: true) expect(response).to redirect_to(power_distribution_units_path) end end diff --git a/spec/requests/servers_controller_request_spec.rb b/spec/requests/servers_controller_request_spec.rb index 19e96ab03..430495b96 100644 --- a/spec/requests/servers_controller_request_spec.rb +++ b/spec/requests/servers_controller_request_spec.rb @@ -202,21 +202,37 @@ end end - describe "DELETE #destroy" do + describe "DELETE /destroy" do + context "without confirm" do + subject(:response) do + delete server_path(server2) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Server, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Server.exists?(server.id)).to be true } + end + context "with a server without association" do it "destroys the requested server" do expect do - delete server_path(server2) + delete server_path(server2, confirm: true) end.to change(Server, :count).by(-1) end it "redirects to the servers list" do - delete server_path(server2) + delete server_path(server2, confirm: true) expect(response).to redirect_to(servers_path) end it "redirects to the servers list and keep params" do - delete server_path(server2, params: { sort: "asc", sort_by: "rooms.name" }) + delete server_path(server2, params: { sort: "asc", sort_by: "rooms.name" }, confirm: true) expect(response).to redirect_to(servers_path({ sort: "asc", sort_by: "rooms.name" })) end end @@ -224,12 +240,12 @@ context "with a server with association" do it "does not destroy the requested server" do expect do - delete server_path(server) + delete server_path(server, confirm: true) end.not_to change(Server, :count) end it "redirects to the servers list" do - delete server_path(server) + delete server_path(server, confirm: true) expect(response).to redirect_to(servers_path) end end diff --git a/spec/requests/stacks_controller_request_spec.rb b/spec/requests/stacks_controller_request_spec.rb index 2286d1f38..2be919d06 100644 --- a/spec/requests/stacks_controller_request_spec.rb +++ b/spec/requests/stacks_controller_request_spec.rb @@ -145,7 +145,7 @@ describe "DELETE #destroy" do subject(:response) do - delete stack_path(stack) + delete stack_path(stack, confirm: true) # NOTE: used to simplify usage and custom test done in final spec file. @response # rubocop:disable RSpec/InstanceVariable @@ -153,6 +153,22 @@ include_context "with authenticated admin" + context "without confirm" do + subject(:response) do + delete stack_path(stack) + @response # rubocop:disable RSpec/InstanceVariable + end + + it do + expect do + response + end.not_to change(Stack, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Stack.exists?(stack.id)).to be true } + end + context "with an stack without servers" do let(:stack) { stacks(:orange) } From 527e8365577955a5baaf6f6944d0cfb9b68987fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Mon, 27 Oct 2025 17:49:26 +0100 Subject: [PATCH 05/33] removing delete dependency concern, logic is now in component --- .../delete_dependency/confirm_component.rb | 73 +++++++++++++++++-- app/models/application_record.rb | 1 - app/models/concerns/deletable_dependencies.rb | 59 --------------- app/models/stack.rb | 2 - config/locales/fr.yml | 3 +- 5 files changed, 70 insertions(+), 68 deletions(-) delete mode 100644 app/models/concerns/deletable_dependencies.rb diff --git a/app/components/delete_dependency/confirm_component.rb b/app/components/delete_dependency/confirm_component.rb index 8ff706d14..0c359a3b9 100644 --- a/app/components/delete_dependency/confirm_component.rb +++ b/app/components/delete_dependency/confirm_component.rb @@ -1,9 +1,14 @@ # frozen_string_literal: true module DeleteDependency + ALLOW_DEPEDENCY_OPTIONS = %i[ + restrict_with_error + destroy + ].freeze + class ConfirmComponent < ApplicationComponent erb_template <<~ERB - <% if @dependencies.empty? %> + <% if @restrict.empty? %>

<%= t(".confirm") %>

@@ -23,28 +28,86 @@ class ConfirmComponent < ApplicationComponent is_responsive: true, )%> + <% unless @destroy.empty? %> +

<%= t(".destroy_dependency_exist_message") %>

+ <% end %> + <% else %> +

<%= t(".restrict_dependency_exist_message") %>

+ <% end %> -

<%= t(".dependency_exist_message") %>

+ <% dependencies = @restrict.empty? ? @destroy : @restrict %> + <% unless dependencies.empty? %>
- <% @dependencies.each do |dependency| %> + <% dependencies.each do |dependency| %>
<%= render component_for(dependency[:klass], dependency[:records], dependency[:asso_name]) %>
<% end %>
+ <% end %> ERB - def initialize(record, full_delete_path) - @dependencies = record.delete_dependencies + def initialize(record, full_delete_path, only: nil, exept: nil) @full_delete_path = full_delete_path + @only = only + @exept = exept + + compute_delete_dependencies(record) + super end private + def compute_delete_dependencies(record) + @restrict = [] + @destroy = [] + + record.class.reflect_on_all_associations.each do |a| + # exclude according to config + next unless association_counts?(a) + + asso_restricted = a.options[:dependent] == :restrict_with_error + + # don't fetch records if they don't restrict + # and theu are other restricted records + next if !asso_restricted && !@restrict.empty? + + # get records + records = record.public_send(a.name) + next if records.blank? + + # add in restrict or destroy + asso_hash = { + klass: a.klass, + asso_name: a.name, + records:, + } + + if asso_restricted + @restrict << asso_hash + else + @destroy << asso_hash + end + end + end + + def association_counts?(asso) + # only is above default config + return @only.include?(asso.name) unless @only.nil? + + # default behavior + return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) + return false if %i[changelog_entries slugs].include? asso.name + return false if asso.class_name.start_with?("ActiveStorage::") + + # exept is not above default config + @expect.nil? || @expect.exclude?(asso.name) + end + def component_for(model, records, asso_name) class_name = "DeleteDependency::#{model.model_name.name}CollectionComponent" component_class = class_name.safe_constantize diff --git a/app/models/application_record.rb b/app/models/application_record.rb index d6ad55706..a3f99934b 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -2,7 +2,6 @@ class ApplicationRecord < ActiveRecord::Base include Changelogable - include DeletableDependencies primary_abstract_class diff --git a/app/models/concerns/deletable_dependencies.rb b/app/models/concerns/deletable_dependencies.rb deleted file mode 100644 index edf0f5c68..000000000 --- a/app/models/concerns/deletable_dependencies.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module DeletableDependencies - extend ActiveSupport::Concern - - ALLOW_DEPEDENCY_OPTIONS = %i[ - restrict_with_error - ].freeze - - included do - class_attribute :delete_dependency_config, instance_writer: false, default: {} - end - - class_methods do - def delete_dependency(only: nil, except: nil) - self.delete_dependency_config = { - only: Array(only).map(&:to_sym), - except: Array(except).map(&:to_sym), - } - end - end - - def delete_dependencies - self.class - .reflect_on_all_associations - .filter_map do |a| - # exclude according to config - next unless association_counts?(a) - - # get records - records = public_send(a.name) - next if records.blank? - - { - klass: a.klass, - asso_name: a.name, - records:, - } - end - end - - private - - def association_counts?(asso) - only = delete_dependency_config[:only] - expect = delete_dependency_config[:expect] - - # only is above default config - return only.include?(asso.name) unless only.nil? - - # default behavior - return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) - return false if %i[changelog_entries slugs].include? asso.name - return false if asso.class_name.start_with?("ActiveStorage::") - - # exept is not above default config - expect.nil? || expect.exclude?(asso.name) - end -end diff --git a/app/models/stack.rb b/app/models/stack.rb index 80b4ba478..0a77f2b42 100644 --- a/app/models/stack.rb +++ b/app/models/stack.rb @@ -5,8 +5,6 @@ class Stack < ApplicationRecord has_many :servers, dependent: :restrict_with_error - delete_dependency only: [:servers] - def to_s name end diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 75cf0a8eb..c05c8ff0f 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -981,5 +981,6 @@ fr: placeholder: Tapez pour filtrer... delete_dependency: confirm_component: - dependency_exist_message: "La suppression est impossible à cause de ces resources :" + restrict_dependency_exist_message: "La suppression est impossible à cause de ces resources :" + destroy_dependency_exist_message: "Cela entraînera la suppression de ces ressources :" confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. From c45e842fe6fc96d56f830bb82f90c1ed8c02d39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Tue, 28 Oct 2025 11:10:21 +0100 Subject: [PATCH 06/33] refactor --- .../delete_dependency/confirm_component.rb | 119 --------------- .../delete_dependency/defaults_component.rb | 32 ---- .../document_collection_component.rb | 32 ---- app/components/delete_dependency_component.rb | 142 ++++++++++++++++++ app/helpers/modeles_helper.rb | 2 +- app/views/air_conditioners/destroy.html.erb | 5 +- app/views/architectures/destroy.html.erb | 5 +- app/views/bays/destroy.html.erb | 5 +- app/views/card_types/destroy.html.erb | 5 +- app/views/categories/destroy.html.erb | 5 +- app/views/clusters/destroy.html.erb | 5 +- app/views/colors/destroy.html.erb | 5 +- .../contact_assignments/destroy.html.erb | 5 +- app/views/contact_roles/destroy.html.erb | 5 +- app/views/contacts/destroy.html.erb | 5 +- app/views/domaines/destroy.html.erb | 5 +- app/views/frames/destroy.html.erb | 5 +- app/views/gestions/destroy.html.erb | 5 +- app/views/islets/destroy.html.erb | 5 +- app/views/manufacturers/destroy.html.erb | 4 +- app/views/modeles/destroy.html.erb | 4 +- app/views/port_types/destroy.html.erb | 5 +- .../power_distribution_units/destroy.html.erb | 5 +- app/views/rooms/destroy.html.erb | 5 +- app/views/servers/destroy.html.erb | 5 +- app/views/sites/destroy.html.erb | 5 +- app/views/stacks/destroy.html.erb | 5 +- config/locales/fr.yml | 3 +- 28 files changed, 166 insertions(+), 272 deletions(-) delete mode 100644 app/components/delete_dependency/confirm_component.rb delete mode 100644 app/components/delete_dependency/defaults_component.rb delete mode 100644 app/components/delete_dependency/document_collection_component.rb create mode 100644 app/components/delete_dependency_component.rb diff --git a/app/components/delete_dependency/confirm_component.rb b/app/components/delete_dependency/confirm_component.rb deleted file mode 100644 index 0c359a3b9..000000000 --- a/app/components/delete_dependency/confirm_component.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - ALLOW_DEPEDENCY_OPTIONS = %i[ - restrict_with_error - destroy - ].freeze - - class ConfirmComponent < ApplicationComponent - erb_template <<~ERB - <% if @restrict.empty? %> - -

<%= t(".confirm") %>

- - <%= render ButtonComponent.new( - t("action.cancel"), - url: :back, - variant: :info, - is_responsive: true - )%> - - <%= render ButtonComponent.new( - t("action.delete"), - url: @full_delete_path, - method: :delete, - variant: :danger, - icon: "trash", - is_responsive: true, - )%> - - <% unless @destroy.empty? %> -

<%= t(".destroy_dependency_exist_message") %>

- <% end %> - - <% else %> -

<%= t(".restrict_dependency_exist_message") %>

- <% end %> - - <% dependencies = @restrict.empty? ? @destroy : @restrict %> - <% unless dependencies.empty? %> - -
- <% dependencies.each do |dependency| %> -
- <%= render component_for(dependency[:klass], dependency[:records], dependency[:asso_name]) %> -
- <% end %> -
- - <% end %> - ERB - - def initialize(record, full_delete_path, only: nil, exept: nil) - @full_delete_path = full_delete_path - @only = only - @exept = exept - - compute_delete_dependencies(record) - - super - end - - private - - def compute_delete_dependencies(record) - @restrict = [] - @destroy = [] - - record.class.reflect_on_all_associations.each do |a| - # exclude according to config - next unless association_counts?(a) - - asso_restricted = a.options[:dependent] == :restrict_with_error - - # don't fetch records if they don't restrict - # and theu are other restricted records - next if !asso_restricted && !@restrict.empty? - - # get records - records = record.public_send(a.name) - next if records.blank? - - # add in restrict or destroy - asso_hash = { - klass: a.klass, - asso_name: a.name, - records:, - } - - if asso_restricted - @restrict << asso_hash - else - @destroy << asso_hash - end - end - end - - def association_counts?(asso) - # only is above default config - return @only.include?(asso.name) unless @only.nil? - - # default behavior - return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) - return false if %i[changelog_entries slugs].include? asso.name - return false if asso.class_name.start_with?("ActiveStorage::") - - # exept is not above default config - @expect.nil? || @expect.exclude?(asso.name) - end - - def component_for(model, records, asso_name) - class_name = "DeleteDependency::#{model.model_name.name}CollectionComponent" - component_class = class_name.safe_constantize - return component_class.new(records, asso_name) unless component_class.nil? - - DeleteDependency::DefaultsComponent.new model, records, asso_name - end - end -end diff --git a/app/components/delete_dependency/defaults_component.rb b/app/components/delete_dependency/defaults_component.rb deleted file mode 100644 index 1ed53d697..000000000 --- a/app/components/delete_dependency/defaults_component.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class DefaultsComponent < ApplicationComponent - erb_template <<~ERB -

<%= @model.model_name.human %>

-

(<%= @asso_name %>)

-
    - <% @records.each do |record| %> -
  • - <%= show_link record %> -
  • - <% end %> -
- ERB - - def initialize(model, records, asso_name) - @model = model - @records = records - @asso_name = asso_name - super - end - - private - - def show_link(record) - link_to record.to_s, url_for(record), target: "_blank", rel: "noopener" - rescue StandardError - record.to_s - end - end -end diff --git a/app/components/delete_dependency/document_collection_component.rb b/app/components/delete_dependency/document_collection_component.rb deleted file mode 100644 index 0554e2d70..000000000 --- a/app/components/delete_dependency/document_collection_component.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -module DeleteDependency - class DocumentCollectionComponent < ApplicationComponent - erb_template <<~ERB -

<%= Document.model_name.human %>

-

(<%= @asso_name %>)

-
    - <% @docs.each do |doc| %> - <%- next unless doc.document.present? %> -
  • - <%= link_to(doc.document.metadata["filename"], doc.document_url, { target: :_blank }) %> -
  • - <% end %> -
- ERB - - def initialize(docs, asso_name) - @docs = docs - @asso_name = asso_name - super - end - - private - - def show_link(record) - link_to record.to_s, url_for(record), target: "_blank", rel: "noopener" - rescue StandardError - record.to_s - end - end -end diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb new file mode 100644 index 000000000..7a2620bfa --- /dev/null +++ b/app/components/delete_dependency_component.rb @@ -0,0 +1,142 @@ +# frozen_string_literal: true + +class DeleteDependencyComponent < ApplicationComponent + ALLOW_DEPEDENCY_OPTIONS = %i[ + restrict_with_error + destroy + ].freeze + + erb_template <<~ERB + <% if @restricting_records.empty? %> + +

<%= t(".confirm") %>

+ + <%= render ButtonComponent.new( + t("action.cancel"), + url: :back, + variant: :info, + is_responsive: true + )%> + + <%= render ButtonComponent.new( + t("action.delete"), + url: @confirmation_path, + method: :delete, + variant: :danger, + icon: "trash", + is_responsive: true, + )%> + + <% unless @destroy_records.empty? %> +

<%= t(".destroy_dependency_exist_message") %>

+ <% end %> + + <% else %> +

<%= t(".restrict_dependency_exist_message") %>

+ <% end %> + + <% dependencies = @restricting_records.empty? ? @destroy_records : @restricting_records %> + <% unless dependencies.empty? %> + +
+ <% dependencies.each do |dependency| %> +
+ <%= render CollectionComponent.new dependency[:association], dependency[:records] %> +
+ <% end %> +
+ + <% end %> + ERB + + def initialize(record, confirmation_path, only: nil, exept: nil) + @confirmation_path = confirmation_path + @only = only + @exept = exept + + # restricting_records is a list of hashs with records + # that prevent current record from being destroyed + @restricting_records = [] + + # destroy_records is also a list of hashs with records + # but that will be destroyed if current record is + @destroy_records = [] + + fill_delete_dependencies(record) + + super + end + + private + + def fill_delete_dependencies(record) + record.class.reflect_on_all_associations.each do |a| + # exclude according to config + next unless association_counts?(a) + + asso_restricting = a.options[:dependent] == :restrict_with_error + + # don't fetch records if they are not restricting + # and we already found other restricting records + next if !asso_restricting && !@restricting_records.empty? + + # get records + records = record.public_send(a.name) + next if records.blank? + + # add in restrict or destroy + asso_hash = { association: a, records: } + if asso_restricting + @restricting_records << asso_hash + else + @destroy_records << asso_hash + end + end + end + + def association_counts?(asso) + # only is above default config + return @only.include?(asso.name) unless @only.nil? + + # default behavior + return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) + return false if %i[changelog_entries slugs].include? asso.name + return false if asso.class_name.start_with?("ActiveStorage::") + + # exept is not above default config + @expect.nil? || @expect.exclude?(asso.name) + end + + class CollectionComponent < ApplicationComponent + erb_template <<~ERB +

<%= @asso.klass.model_name.human %>

+

(<%= @asso.name %>)

+
    + <% @records.each do |record| %> +
  • + <%= show_link record %> +
  • + <% end %> +
+ ERB + + def initialize(asso, records) + @asso = asso + @records = records + super + end + + private + + def show_link(record) + case record + when Document + link_to record.document.metadata["filename"], record.document_url, target: :_blank, rel: :noopener + else + link_to record.to_s, url_for(record), target: "_blank", rel: :noopener + end + rescue StandardError + record.to_s + end + end +end diff --git a/app/helpers/modeles_helper.rb b/app/helpers/modeles_helper.rb index e969b5f4c..85219e425 100644 --- a/app/helpers/modeles_helper.rb +++ b/app/helpers/modeles_helper.rb @@ -8,6 +8,6 @@ def lighten_color(hex_color, amount = 0.6) rgb[1] = [(rgb[1].to_i + (255 * amount)).round, 255].min rgb[2] = [(rgb[2].to_i + (255 * amount)).round, 255].min - Kernel.format("#%02x%02x%02x", *rgb) + format("#%02x%02x%02x", *rgb) end end diff --git a/app/views/air_conditioners/destroy.html.erb b/app/views/air_conditioners/destroy.html.erb index 84a81721e..5b6f5902b 100644 --- a/app/views/air_conditioners/destroy.html.erb +++ b/app/views/air_conditioners/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@air_conditioner, air_conditioner_path(@air_conditioner, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@air_conditioner, air_conditioner_path(@air_conditioner, confirm: true)) %>
diff --git a/app/views/architectures/destroy.html.erb b/app/views/architectures/destroy.html.erb index bd28ce476..58d522213 100644 --- a/app/views/architectures/destroy.html.erb +++ b/app/views/architectures/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@architecture, architecture_path(@architecture, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@architecture, architecture_path(@architecture, confirm: true)) %>
diff --git a/app/views/bays/destroy.html.erb b/app/views/bays/destroy.html.erb index fd429d4a5..395ec54c8 100644 --- a/app/views/bays/destroy.html.erb +++ b/app/views/bays/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@bay, bay_path(@bay, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@bay, bay_path(@bay, confirm: true)) %>
diff --git a/app/views/card_types/destroy.html.erb b/app/views/card_types/destroy.html.erb index 16d7ef972..e04df67c0 100644 --- a/app/views/card_types/destroy.html.erb +++ b/app/views/card_types/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@card_type, card_type_path(@card_type, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@card_type, card_type_path(@card_type, confirm: true)) %>
diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb index b0fa1e410..f707b306e 100644 --- a/app/views/categories/destroy.html.erb +++ b/app/views/categories/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@category, category_path(@category, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@category, category_path(@category, confirm: true)) %>
diff --git a/app/views/clusters/destroy.html.erb b/app/views/clusters/destroy.html.erb index 78329d849..c34c95579 100644 --- a/app/views/clusters/destroy.html.erb +++ b/app/views/clusters/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@cluster, cluster_path(@cluster, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@cluster, cluster_path(@cluster, confirm: true)) %>
diff --git a/app/views/colors/destroy.html.erb b/app/views/colors/destroy.html.erb index 818477813..89aaebf7c 100644 --- a/app/views/colors/destroy.html.erb +++ b/app/views/colors/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@color, color_path(@color, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@color, color_path(@color, confirm: true)) %>
diff --git a/app/views/contact_assignments/destroy.html.erb b/app/views/contact_assignments/destroy.html.erb index d1a0cf52f..9971a0dd7 100644 --- a/app/views/contact_assignments/destroy.html.erb +++ b/app/views/contact_assignments/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@contact_assignment, contact_assignment_path(@contact_assignment, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@contact_assignment, contact_assignment_path(@contact_assignment, confirm: true)) %>
diff --git a/app/views/contact_roles/destroy.html.erb b/app/views/contact_roles/destroy.html.erb index 9a237c8b8..13bd7b43f 100644 --- a/app/views/contact_roles/destroy.html.erb +++ b/app/views/contact_roles/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@contact_role, contact_role_path(@contact_role, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@contact_role, contact_role_path(@contact_role, confirm: true)) %>
diff --git a/app/views/contacts/destroy.html.erb b/app/views/contacts/destroy.html.erb index 3dbe00b88..c9dd2a24c 100644 --- a/app/views/contacts/destroy.html.erb +++ b/app/views/contacts/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@contact, contact_path(@contact, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@contact, contact_path(@contact, confirm: true)) %>
diff --git a/app/views/domaines/destroy.html.erb b/app/views/domaines/destroy.html.erb index e82b9e50a..5d4c3ab86 100644 --- a/app/views/domaines/destroy.html.erb +++ b/app/views/domaines/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@domaine, manufacturer_path(@domaine, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@domaine, manufacturer_path(@domaine, confirm: true)) %>
diff --git a/app/views/frames/destroy.html.erb b/app/views/frames/destroy.html.erb index 856de6918..2d903cf15 100644 --- a/app/views/frames/destroy.html.erb +++ b/app/views/frames/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@frame, frame_path(@frame, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@frame, frame_path(@frame, confirm: true)) %>
diff --git a/app/views/gestions/destroy.html.erb b/app/views/gestions/destroy.html.erb index 8bf153d1f..1b1e52311 100644 --- a/app/views/gestions/destroy.html.erb +++ b/app/views/gestions/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@gestion, gestion_path(@gestion, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@gestion, gestion_path(@gestion, confirm: true)) %>
diff --git a/app/views/islets/destroy.html.erb b/app/views/islets/destroy.html.erb index f4d2920c5..af6e3e65e 100644 --- a/app/views/islets/destroy.html.erb +++ b/app/views/islets/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@islet, islet_path(@islet, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@islet, islet_path(@islet, confirm: true)) %>
diff --git a/app/views/manufacturers/destroy.html.erb b/app/views/manufacturers/destroy.html.erb index a59b5b279..b39318a03 100644 --- a/app/views/manufacturers/destroy.html.erb +++ b/app/views/manufacturers/destroy.html.erb @@ -7,7 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - <%= render DeleteDependency::ConfirmComponent.new(@manufacturer, manufacturer_path(@manufacturer, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@manufacturer, manufacturer_path(@manufacturer, confirm: true)) %>
diff --git a/app/views/modeles/destroy.html.erb b/app/views/modeles/destroy.html.erb index 915a2d08b..897bdc620 100644 --- a/app/views/modeles/destroy.html.erb +++ b/app/views/modeles/destroy.html.erb @@ -7,7 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - <%= render DeleteDependency::ConfirmComponent.new(@modele, modele_path(@modele, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@modele, modele_path(@modele, confirm: true)) %>
diff --git a/app/views/port_types/destroy.html.erb b/app/views/port_types/destroy.html.erb index 34d7d5cb9..270e271ed 100644 --- a/app/views/port_types/destroy.html.erb +++ b/app/views/port_types/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@port_type, port_type_path(@port_type, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@port_type, port_type_path(@port_type, confirm: true)) %>
diff --git a/app/views/power_distribution_units/destroy.html.erb b/app/views/power_distribution_units/destroy.html.erb index 5fb7d1c8f..ee4fcc2a9 100644 --- a/app/views/power_distribution_units/destroy.html.erb +++ b/app/views/power_distribution_units/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@pdu, power_distribution_unit_path(@pdu, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@pdu, power_distribution_unit_path(@pdu, confirm: true)) %>
diff --git a/app/views/rooms/destroy.html.erb b/app/views/rooms/destroy.html.erb index 6745fffe6..dcf0a0aa8 100644 --- a/app/views/rooms/destroy.html.erb +++ b/app/views/rooms/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@room, room_path(@room, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@room, room_path(@room, confirm: true)) %>
diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb index 60eaeed95..fa7d7c1e7 100644 --- a/app/views/servers/destroy.html.erb +++ b/app/views/servers/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@server, server_path(@server, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@server, server_path(@server, confirm: true)) %>
diff --git a/app/views/sites/destroy.html.erb b/app/views/sites/destroy.html.erb index 71b7d6067..0eda3a2cc 100644 --- a/app/views/sites/destroy.html.erb +++ b/app/views/sites/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@site, site_path(@site, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@site, site_path(@site, confirm: true)) %>
diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb index d73e01ddd..0ff4cc6ac 100644 --- a/app/views/stacks/destroy.html.erb +++ b/app/views/stacks/destroy.html.erb @@ -7,8 +7,5 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
- - - <%= render DeleteDependency::ConfirmComponent.new(@stack, stack_path(@stack, confirm: true)) %> - + <%= render DeleteDependencyComponent.new(@stack, stack_path(@stack, confirm: true)) %>
diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c05c8ff0f..357e481c1 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -979,8 +979,7 @@ fr: no_results_found: Aucun résultat trouvé select: placeholder: Tapez pour filtrer... - delete_dependency: - confirm_component: + delete_dependency_component: restrict_dependency_exist_message: "La suppression est impossible à cause de ces resources :" destroy_dependency_exist_message: "Cela entraînera la suppression de ces ressources :" confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. From 3e20f6461a2e9b5483684a55fdef135056e5841f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Tue, 28 Oct 2025 13:38:36 +0100 Subject: [PATCH 07/33] test for delete_dependency_component --- app/components/delete_dependency_component.rb | 6 +- config/locales/fr.yml | 2 +- .../delete_dependency_component_spec.rb | 67 +++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 spec/components/delete_dependency_component_spec.rb diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 7a2620bfa..cd6f9d0c4 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -28,11 +28,11 @@ class DeleteDependencyComponent < ApplicationComponent )%> <% unless @destroy_records.empty? %> -

<%= t(".destroy_dependency_exist_message") %>

+

<%= t(".destroy_dependency_exist_message") %>

<% end %> <% else %> -

<%= t(".restrict_dependency_exist_message") %>

+

<%= t(".restrict_dependency_exist_message") %>

<% end %> <% dependencies = @restricting_records.empty? ? @destroy_records : @restricting_records %> @@ -109,7 +109,7 @@ def association_counts?(asso) class CollectionComponent < ApplicationComponent erb_template <<~ERB -

<%= @asso.klass.model_name.human %>

+

<%= @asso.klass.model_name.human %>

(<%= @asso.name %>)

    <% @records.each do |record| %> diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 357e481c1..0486f3f21 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -981,5 +981,5 @@ fr: placeholder: Tapez pour filtrer... delete_dependency_component: restrict_dependency_exist_message: "La suppression est impossible à cause de ces resources :" - destroy_dependency_exist_message: "Cela entraînera la suppression de ces ressources :" + destroy_dependency_exist_message: "Cela entraînera la suppression des ressources ci dessous :" confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb new file mode 100644 index 000000000..ad1de5c36 --- /dev/null +++ b/spec/components/delete_dependency_component_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe DeleteDependencyComponent, type: :component do + let(:confirmation_path) { "/confirmation-path" } + let(:component) do + # stubbing url_for since it cannot found url for stubbed records + component = described_class.new(record, confirmation_path) + allow(component).to receive(:url_for).and_return("/fake/url") + component + end + + let(:rendered_component) { render_inline(component).to_html } + + context "with restricting dependency" do + let(:record) do + server = Server.new(name: "Dummy name") + document = Document.new + allow(document).to receive_messages( + document: instance_double(DocumentUploader::UploadedFile, metadata: { filename: "this is a filename" }), + document_url: "/fake/url", + ) + + allow(server).to receive_messages( + external_app_record: [], + documents: [document], + moves: [], + ) + + server + end + + it { expect(rendered_component).to have_tag("h4", title: Document.model_name.human) } + it { expect(rendered_component).to have_tag("a[target=_blank]", href: "/fake/url", title: "this is a filename") } + it { expect(rendered_component).not_to have_tag("a.btn-danger") } + it { expect(rendered_component).not_to have_tag("a.btn-default") } + end + + context "without restricting dependency" do + describe "with destroy dependency" do + let(:record) do + contact = Contact.new(first_name: "Dummy", last_name: "name") + allow(contact).to receive(:contact_assignments).and_return([ContactAssignment.new]) + contact + end + + it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } + it { expect(rendered_component).to have_tag("a.btn-default") } + it { expect(rendered_component).to have_tag("h4", title: ContactAssignment.model_name.human) } + it { expect(rendered_component).to have_tag("a[target=_blank]", href: "/fake/url", title: ContactAssignment.new.to_s) } + end + + describe "without destroy dependency" do + let(:record) do + contact = Contact.new(first_name: "Dummy", last_name: "name") + allow(contact).to receive(:contact_assignments).and_return([]) + contact + end + + it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } + it { expect(rendered_component).to have_tag("a.btn-default") } + it { expect(rendered_component).not_to have_tag("h4", title: ContactAssignment.model_name.human) } + it { expect(rendered_component).not_to have_tag("a[target=_blank]", href: "/fake/url", title: ContactAssignment.new.to_s) } + end + end +end From 76bfa706aea7c4571958a9869f23938e85b5ac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Tue, 28 Oct 2025 13:49:08 +0100 Subject: [PATCH 08/33] robocop fixes --- app/controllers/modeles_controller.rb | 2 +- app/controllers/rooms_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/modeles_controller.rb b/app/controllers/modeles_controller.rb index 06cb5eb82..f0cb1541c 100644 --- a/app/controllers/modeles_controller.rb +++ b/app/controllers/modeles_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ModelesController < ApplicationController +class ModelesController < ApplicationController # rubocop:disable Metrics/ClassLength include ModelesHelper before_action :set_modele, only: %i[show edit update destroy] diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 560cfed73..ead86b86d 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class RoomsController < ApplicationController +class RoomsController < ApplicationController # rubocop:disable Metrics/ClassLength include ServersHelper include RoomsHelper From 3835f72361c8c7e754a25f2edbd2c01dd3cfc6c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Wed, 29 Oct 2025 14:59:52 +0100 Subject: [PATCH 09/33] remove optimisation and show all association in delete_dependency_component --- app/components/delete_dependency_component.rb | 21 ++++++++----------- app/views/air_conditioners/destroy.html.erb | 5 ++++- app/views/architectures/destroy.html.erb | 5 ++++- app/views/bays/destroy.html.erb | 5 ++++- app/views/card_types/destroy.html.erb | 5 ++++- app/views/categories/destroy.html.erb | 5 ++++- app/views/clusters/destroy.html.erb | 5 ++++- app/views/colors/destroy.html.erb | 5 ++++- .../contact_assignments/destroy.html.erb | 5 ++++- app/views/contact_roles/destroy.html.erb | 5 ++++- app/views/contacts/destroy.html.erb | 5 ++++- app/views/domaines/destroy.html.erb | 5 ++++- app/views/frames/destroy.html.erb | 5 ++++- app/views/gestions/destroy.html.erb | 5 ++++- app/views/islets/destroy.html.erb | 5 ++++- app/views/manufacturers/destroy.html.erb | 5 ++++- app/views/modeles/destroy.html.erb | 5 ++++- app/views/port_types/destroy.html.erb | 5 ++++- .../power_distribution_units/destroy.html.erb | 5 ++++- app/views/rooms/destroy.html.erb | 5 ++++- app/views/servers/destroy.html.erb | 5 ++++- app/views/sites/destroy.html.erb | 5 ++++- app/views/stacks/destroy.html.erb | 5 ++++- config/locales/fr.yml | 4 ++-- .../delete_dependency_component_spec.rb | 2 +- .../servers_controller_request_spec.rb | 2 +- 26 files changed, 101 insertions(+), 38 deletions(-) diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index cd6f9d0c4..708b645a5 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -27,19 +27,16 @@ class DeleteDependencyComponent < ApplicationComponent is_responsive: true, )%> - <% unless @destroy_records.empty? %> -

    <%= t(".destroy_dependency_exist_message") %>

    - <% end %> - - <% else %> -

    <%= t(".restrict_dependency_exist_message") %>

    <% end %> - <% dependencies = @restricting_records.empty? ? @destroy_records : @restricting_records %> - <% unless dependencies.empty? %> + <% [ + {dep: @restricting_records, grp_title: t(".restrict_dependency_title")}, + {dep: @destroy_records, grp_title: t(".destroy_dependency_title")}, + ].filter { |grp| !grp[:dep].empty? }.each do |group| %> -
    - <% dependencies.each do |dependency| %> +

    <%= group[:grp_title] %>

    +
    + <% group[:dep].each do |dependency| %>
    <%= render CollectionComponent.new dependency[:association], dependency[:records] %>
    @@ -49,7 +46,7 @@ class DeleteDependencyComponent < ApplicationComponent <% end %> ERB - def initialize(record, confirmation_path, only: nil, exept: nil) + def initialize(record, confirmation_path:, only: nil, exept: nil) @confirmation_path = confirmation_path @only = only @exept = exept @@ -78,7 +75,7 @@ def fill_delete_dependencies(record) # don't fetch records if they are not restricting # and we already found other restricting records - next if !asso_restricting && !@restricting_records.empty? + # next if !asso_restricting && !@restricting_records.empty? # get records records = record.public_send(a.name) diff --git a/app/views/air_conditioners/destroy.html.erb b/app/views/air_conditioners/destroy.html.erb index 5b6f5902b..b10688ba2 100644 --- a/app/views/air_conditioners/destroy.html.erb +++ b/app/views/air_conditioners/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@air_conditioner, air_conditioner_path(@air_conditioner, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @air_conditioner, + confirmation_path: air_conditioner_path(@air_conditioner, confirm: true) + ) %>
    diff --git a/app/views/architectures/destroy.html.erb b/app/views/architectures/destroy.html.erb index 58d522213..206fab003 100644 --- a/app/views/architectures/destroy.html.erb +++ b/app/views/architectures/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@architecture, architecture_path(@architecture, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @architecture, + confirmation_path: architecture_path(@architecture, confirm: true) + ) %>
    diff --git a/app/views/bays/destroy.html.erb b/app/views/bays/destroy.html.erb index 395ec54c8..93ac75841 100644 --- a/app/views/bays/destroy.html.erb +++ b/app/views/bays/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@bay, bay_path(@bay, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @bay, + confirmation_path: bay_path(@bay, confirm: true) + ) %>
    diff --git a/app/views/card_types/destroy.html.erb b/app/views/card_types/destroy.html.erb index e04df67c0..f8810cb53 100644 --- a/app/views/card_types/destroy.html.erb +++ b/app/views/card_types/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@card_type, card_type_path(@card_type, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @card_type, + confirmation_path: card_type_path(@card_type, confirm: true) + ) %>
    diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb index f707b306e..34c8280b2 100644 --- a/app/views/categories/destroy.html.erb +++ b/app/views/categories/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@category, category_path(@category, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @category, + confirmation_path: category_path(@category, confirm: true) + ) %>
    diff --git a/app/views/clusters/destroy.html.erb b/app/views/clusters/destroy.html.erb index c34c95579..264d52736 100644 --- a/app/views/clusters/destroy.html.erb +++ b/app/views/clusters/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@cluster, cluster_path(@cluster, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @cluster, + confirmation_path: cluster_path(@cluster, confirm: true) + ) %>
    diff --git a/app/views/colors/destroy.html.erb b/app/views/colors/destroy.html.erb index 89aaebf7c..42e681264 100644 --- a/app/views/colors/destroy.html.erb +++ b/app/views/colors/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@color, color_path(@color, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @color, + confirmation_path: color_path(@color, confirm: true) + ) %>
    diff --git a/app/views/contact_assignments/destroy.html.erb b/app/views/contact_assignments/destroy.html.erb index 9971a0dd7..694189b37 100644 --- a/app/views/contact_assignments/destroy.html.erb +++ b/app/views/contact_assignments/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@contact_assignment, contact_assignment_path(@contact_assignment, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @contact_assignment, + confirmation_path: contact_assignment_path(@contact_assignment, confirm: true) + ) %>
    diff --git a/app/views/contact_roles/destroy.html.erb b/app/views/contact_roles/destroy.html.erb index 13bd7b43f..734565edb 100644 --- a/app/views/contact_roles/destroy.html.erb +++ b/app/views/contact_roles/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@contact_role, contact_role_path(@contact_role, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @contact_role, + confirmation_path: contact_role_path(@contact_role, confirm: true) + ) %>
    diff --git a/app/views/contacts/destroy.html.erb b/app/views/contacts/destroy.html.erb index c9dd2a24c..4b0c581bd 100644 --- a/app/views/contacts/destroy.html.erb +++ b/app/views/contacts/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@contact, contact_path(@contact, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @contact, + confirmation_path: contact_path(@contact, confirm: true) + ) %>
    diff --git a/app/views/domaines/destroy.html.erb b/app/views/domaines/destroy.html.erb index 5d4c3ab86..0e4b178dd 100644 --- a/app/views/domaines/destroy.html.erb +++ b/app/views/domaines/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@domaine, manufacturer_path(@domaine, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @domaine, + confirmation_path: manufacturer_path(@domaine, confirm: true) + ) %>
    diff --git a/app/views/frames/destroy.html.erb b/app/views/frames/destroy.html.erb index 2d903cf15..076d484cb 100644 --- a/app/views/frames/destroy.html.erb +++ b/app/views/frames/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@frame, frame_path(@frame, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @frame, + confirmation_path: frame_path(@frame, confirm: true) + ) %>
    diff --git a/app/views/gestions/destroy.html.erb b/app/views/gestions/destroy.html.erb index 1b1e52311..d2f5b8193 100644 --- a/app/views/gestions/destroy.html.erb +++ b/app/views/gestions/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@gestion, gestion_path(@gestion, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @gestion, + confirmation_path: gestion_path(@gestion, confirm: true) + ) %>
    diff --git a/app/views/islets/destroy.html.erb b/app/views/islets/destroy.html.erb index af6e3e65e..d7254190d 100644 --- a/app/views/islets/destroy.html.erb +++ b/app/views/islets/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@islet, islet_path(@islet, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @islet, + confirmation_path: islet_path(@islet, confirm: true) + ) %>
    diff --git a/app/views/manufacturers/destroy.html.erb b/app/views/manufacturers/destroy.html.erb index b39318a03..42f828863 100644 --- a/app/views/manufacturers/destroy.html.erb +++ b/app/views/manufacturers/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@manufacturer, manufacturer_path(@manufacturer, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @manufacturer, + confirmation_path: manufacturer_path(@manufacturer, confirm: true) + ) %>
    diff --git a/app/views/modeles/destroy.html.erb b/app/views/modeles/destroy.html.erb index 897bdc620..e26ecd00c 100644 --- a/app/views/modeles/destroy.html.erb +++ b/app/views/modeles/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@modele, modele_path(@modele, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @modele, + confirmation_path: modele_path(@modele, confirm: true) + ) %>
    diff --git a/app/views/port_types/destroy.html.erb b/app/views/port_types/destroy.html.erb index 270e271ed..862f7626a 100644 --- a/app/views/port_types/destroy.html.erb +++ b/app/views/port_types/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@port_type, port_type_path(@port_type, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @port_type, + confirmation_path: port_type_path(@port_type, confirm: true) + ) %>
    diff --git a/app/views/power_distribution_units/destroy.html.erb b/app/views/power_distribution_units/destroy.html.erb index ee4fcc2a9..0fbc52add 100644 --- a/app/views/power_distribution_units/destroy.html.erb +++ b/app/views/power_distribution_units/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@pdu, power_distribution_unit_path(@pdu, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @pdu, + confirmation_path: power_distribution_unit_path(@pdu, confirm: true) + ) %>
    diff --git a/app/views/rooms/destroy.html.erb b/app/views/rooms/destroy.html.erb index dcf0a0aa8..6405a8b4b 100644 --- a/app/views/rooms/destroy.html.erb +++ b/app/views/rooms/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@room, room_path(@room, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @room, + confirmation_path: room_path(@room, confirm: true) + ) %>
    diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb index fa7d7c1e7..0fe308beb 100644 --- a/app/views/servers/destroy.html.erb +++ b/app/views/servers/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@server, server_path(@server, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @server, + confirmation_path: server_path(@server, confirm: true) + ) %>
    diff --git a/app/views/sites/destroy.html.erb b/app/views/sites/destroy.html.erb index 0eda3a2cc..779699e65 100644 --- a/app/views/sites/destroy.html.erb +++ b/app/views/sites/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@site, site_path(@site, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @site, + confirmation_path: site_path(@site, confirm: true) + ) %>
    diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb index 0ff4cc6ac..f3d17b07a 100644 --- a/app/views/stacks/destroy.html.erb +++ b/app/views/stacks/destroy.html.erb @@ -7,5 +7,8 @@ <%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %>
    - <%= render DeleteDependencyComponent.new(@stack, stack_path(@stack, confirm: true)) %> + <%= render DeleteDependencyComponent.new( + @stack, + confirmation_path: stack_path(@stack, confirm: true) + ) %>
    diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 0486f3f21..5ee4ae810 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -980,6 +980,6 @@ fr: select: placeholder: Tapez pour filtrer... delete_dependency_component: - restrict_dependency_exist_message: "La suppression est impossible à cause de ces resources :" - destroy_dependency_exist_message: "Cela entraînera la suppression des ressources ci dessous :" + restrict_dependency_title: "Ressources empêchants la suppréssion" + destroy_dependency_title: "Ressources qui seront supprimées lors de la suppréssion" confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index ad1de5c36..9f9214b2b 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -6,7 +6,7 @@ let(:confirmation_path) { "/confirmation-path" } let(:component) do # stubbing url_for since it cannot found url for stubbed records - component = described_class.new(record, confirmation_path) + component = described_class.new(record, confirmation_path:) allow(component).to receive(:url_for).and_return("/fake/url") component end diff --git a/spec/requests/servers_controller_request_spec.rb b/spec/requests/servers_controller_request_spec.rb index 430495b96..2933648d6 100644 --- a/spec/requests/servers_controller_request_spec.rb +++ b/spec/requests/servers_controller_request_spec.rb @@ -202,7 +202,7 @@ end end - describe "DELETE /destroy" do + describe "DELETE #destroy" do context "without confirm" do subject(:response) do delete server_path(server2) From 6a39e6c2281a742a5d66e1cc45ca45e8f43fd0a5 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 29 Oct 2025 15:11:46 +0100 Subject: [PATCH 10/33] rework --- app/components/delete_dependency_component.rb | 130 ++++-------------- app/decorators/application_decorator.rb | 4 + app/decorators/document_decorator.rb | 7 + app/models/record_dependencies.rb | 72 ++++++++++ spec/decorators/document_decorator_spec.rb | 17 +++ 5 files changed, 123 insertions(+), 107 deletions(-) create mode 100644 app/decorators/document_decorator.rb create mode 100644 app/models/record_dependencies.rb create mode 100644 spec/decorators/document_decorator_spec.rb diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 708b645a5..cf531b549 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -1,139 +1,55 @@ # frozen_string_literal: true class DeleteDependencyComponent < ApplicationComponent - ALLOW_DEPEDENCY_OPTIONS = %i[ - restrict_with_error - destroy - ].freeze - erb_template <<~ERB <% if @restricting_records.empty? %> -

    <%= t(".confirm") %>

    - <%= render ButtonComponent.new( - t("action.cancel"), - url: :back, - variant: :info, - is_responsive: true - )%> - - <%= render ButtonComponent.new( - t("action.delete"), - url: @confirmation_path, - method: :delete, - variant: :danger, - icon: "trash", - is_responsive: true, - )%> - + <%= render ButtonComponent.new(t("action.cancel"), url: :back, variant: :info, is_responsive: true) %> + <%= render ButtonComponent.new(t("action.delete"), url: @confirmation_path, method: :delete, variant: :danger, + icon: :trash, is_responsive: true) %> <% end %> <% [ - {dep: @restricting_records, grp_title: t(".restrict_dependency_title")}, - {dep: @destroy_records, grp_title: t(".destroy_dependency_title")}, + {dep: @record_dependencies.restricted_with_error, grp_title: t(".restrict_dependency_title")}, + {dep: @record_dependencies.destroyable, grp_title: t(".destroy_dependency_title")}, ].filter { |grp| !grp[:dep].empty? }.each do |group| %> -

    <%= group[:grp_title] %>

    <% group[:dep].each do |dependency| %> -
    - <%= render CollectionComponent.new dependency[:association], dependency[:records] %> -
    + <%= render CollectionComponent.new(dependency) %> <% end %>
    - <% end %> ERB - def initialize(record, confirmation_path:, only: nil, exept: nil) + def initialize(record, confirmation_path:, only: [], exept: []) @confirmation_path = confirmation_path - @only = only - @exept = exept - - # restricting_records is a list of hashs with records - # that prevent current record from being destroyed - @restricting_records = [] - - # destroy_records is also a list of hashs with records - # but that will be destroyed if current record is - @destroy_records = [] - - fill_delete_dependencies(record) + @record_dependencies = RecordDependencies.new(record, only:, except:) super end - private - - def fill_delete_dependencies(record) - record.class.reflect_on_all_associations.each do |a| - # exclude according to config - next unless association_counts?(a) - - asso_restricting = a.options[:dependent] == :restrict_with_error - - # don't fetch records if they are not restricting - # and we already found other restricting records - # next if !asso_restricting && !@restricting_records.empty? - - # get records - records = record.public_send(a.name) - next if records.blank? - - # add in restrict or destroy - asso_hash = { association: a, records: } - if asso_restricting - @restricting_records << asso_hash - else - @destroy_records << asso_hash - end - end - end - - def association_counts?(asso) - # only is above default config - return @only.include?(asso.name) unless @only.nil? - - # default behavior - return false unless ALLOW_DEPEDENCY_OPTIONS.include?(asso.options[:dependent]) - return false if %i[changelog_entries slugs].include? asso.name - return false if asso.class_name.start_with?("ActiveStorage::") - - # exept is not above default config - @expect.nil? || @expect.exclude?(asso.name) - end - class CollectionComponent < ApplicationComponent erb_template <<~ERB -

    <%= @asso.klass.model_name.human %>

    -

    (<%= @asso.name %>)

    -
      - <% @records.each do |record| %> -
    • - <%= show_link record %> -
    • - <% end %> -
    +
    +

    <%= @dependency.klass.model_name.human %>

    +

    (<%= @dependency.name %>)

    + +
      + <% decorate(@dependency.records).each do |record| %> +
    • + <%= record.display_name %> +
    • + <% end %> +
    +
    ERB - def initialize(asso, records) - @asso = asso - @records = records - super - end - - private + def initialize(dependency) + @dependency = dependency - def show_link(record) - case record - when Document - link_to record.document.metadata["filename"], record.document_url, target: :_blank, rel: :noopener - else - link_to record.to_s, url_for(record), target: "_blank", rel: :noopener - end - rescue StandardError - record.to_s + super end end end diff --git a/app/decorators/application_decorator.rb b/app/decorators/application_decorator.rb index 5736c91f6..7f8b44ef7 100644 --- a/app/decorators/application_decorator.rb +++ b/app/decorators/application_decorator.rb @@ -7,4 +7,8 @@ def authorized_scope(relation, user:) klass.new(user:).apply_scope(relation, type: :active_record_relation) end end + + def display_name + to_s + end end diff --git a/app/decorators/document_decorator.rb b/app/decorators/document_decorator.rb new file mode 100644 index 000000000..f177ca7b0 --- /dev/null +++ b/app/decorators/document_decorator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class DocumentDecorator < ApplicationDecorator + def display_name + object.document.metadata["filename"] + end +end diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb new file mode 100644 index 000000000..d7dbdadef --- /dev/null +++ b/app/models/record_dependencies.rb @@ -0,0 +1,72 @@ +class RecordDependencies + ALLOW_DEPEDENCY_OPTIONS = %i[ + restrict_with_error + destroy + ].freeze + + EXCLUDED_KLASSES = [ActiveStorage::Blob, ActiveStorage::Attachment].freeze + + Dependency = Data.new(:association, :origin) do + delegate :name, :klass, to: :association + + def records + origin.public_send(association.name) + end + + def empty? + records.blank? + end + end + + def initialize(record, only: [], except: []) + @record = record + @only = only + @except = except + + @dependencies = {} + end + + def destroyable + dependencies[:destroy] + end + + def restricted_with_error + dependencies[:restrict_with_error] + end + + # def nillable + # end + + def dependencies + @dependencies ||= _load_dependencies + end + + private + + def _load_dependencies + @record.class.reflect_on_all_associations.each do |association| + # exclude according to config + next unless association_counts?(association) + + dependency = Dependency.new(association, @record) + + next if records.empty? + + (@dependencies[association.options[:dependent]] ||= []) << dependency + end + end + + # TODO: rename + def association_counts?(association) + # only is above default config + return @only.include?(association.name) unless @only.nil? + + # default behavior + return false unless ALLOW_DEPEDENCY_OPTIONS.include?(association.options[:dependent]) + return false if %i[changelog_entries slugs].include?(association.name) + return false if EXCLUDED_KLASSES.include?(association.klass) + + # exept is not above default config + @expect.nil? || @expect.exclude?(association.name) + end +end diff --git a/spec/decorators/document_decorator_spec.rb b/spec/decorators/document_decorator_spec.rb new file mode 100644 index 000000000..3d3a8d922 --- /dev/null +++ b/spec/decorators/document_decorator_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "rails_helper" + +# Example: +# +# describe DocumentDecorator, type: :decorator do +# let(:object) { User.new(first_name: "John", last_name: "Doe") } +# let(:decorated_user) { described_class.new(object) } +# +# describe "#full_name" do +# it { expect(decorated_user.full_name).to eq("John Doe") } +# end +# end +RSpec.describe DocumentDecorator, type: :decorator do + pending "add some examples to (or delete) #{__FILE__}" +end From abbade99deb9f2a1d0bddaaf204307346b98ed0b Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 29 Oct 2025 15:40:21 +0100 Subject: [PATCH 11/33] Code cleanup --- spec/components/delete_dependency_component_spec.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index 9f9214b2b..3c5815d34 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -4,15 +4,11 @@ RSpec.describe DeleteDependencyComponent, type: :component do let(:confirmation_path) { "/confirmation-path" } - let(:component) do - # stubbing url_for since it cannot found url for stubbed records - component = described_class.new(record, confirmation_path:) - allow(component).to receive(:url_for).and_return("/fake/url") - component - end - + let(:component) { described_class.new(record, confirmation_path:) } let(:rendered_component) { render_inline(component).to_html } + before { allow(component).to receive(:url_for).and_return("/fake/url") } + context "with restricting dependency" do let(:record) do server = Server.new(name: "Dummy name") From 25aea10c6de8f0e29418b50f4a14d3617046d5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Wed, 29 Oct 2025 17:30:00 +0100 Subject: [PATCH 12/33] renaming same variables, cleanup, and tests --- app/components/delete_dependency_component.rb | 24 ++++++--- app/models/record_dependencies.rb | 45 ++++++++--------- .../delete_dependency_component_spec.rb | 37 +++++++------- spec/models/record_dependencies_model_spec.rb | 50 +++++++++++++++++++ 4 files changed, 105 insertions(+), 51 deletions(-) create mode 100644 spec/models/record_dependencies_model_spec.rb diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index cf531b549..78e0a857a 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -2,7 +2,7 @@ class DeleteDependencyComponent < ApplicationComponent erb_template <<~ERB - <% if @restricting_records.empty? %> + <% if @record_dependencies.restricted_with_error.blank? %>

    <%= t(".confirm") %>

    <%= render ButtonComponent.new(t("action.cancel"), url: :back, variant: :info, is_responsive: true) %> @@ -11,19 +11,21 @@ class DeleteDependencyComponent < ApplicationComponent <% end %> <% [ - {dep: @record_dependencies.restricted_with_error, grp_title: t(".restrict_dependency_title")}, - {dep: @record_dependencies.destroyable, grp_title: t(".destroy_dependency_title")}, - ].filter { |grp| !grp[:dep].empty? }.each do |group| %> + {dependencies: @record_dependencies.restricted_with_error, grp_title: t(".restrict_dependency_title")}, + {dependencies: @record_dependencies.destroyable, grp_title: t(".destroy_dependency_title")}, + ].filter { |grp| !grp[:dependencies].empty? }.each do |group| %> +

    <%= group[:grp_title] %>

    - <% group[:dep].each do |dependency| %> + <% group[:dependencies].each do |dependency| %> <%= render CollectionComponent.new(dependency) %> <% end %>
    + <% end %> ERB - def initialize(record, confirmation_path:, only: [], exept: []) + def initialize(record, confirmation_path:, only: nil, except: nil) @confirmation_path = confirmation_path @record_dependencies = RecordDependencies.new(record, only:, except:) @@ -33,11 +35,11 @@ def initialize(record, confirmation_path:, only: [], exept: []) class CollectionComponent < ApplicationComponent erb_template <<~ERB
    -

    <%= @dependency.klass.model_name.human %>

    +

    <%= @dependency.title %>

    (<%= @dependency.name %>)

      - <% decorate(@dependency.records).each do |record| %> + <% records.each do |record| %>
    • <%= record.display_name %>
    • @@ -51,5 +53,11 @@ def initialize(dependency) super end + + def records + helpers.decorate(@dependency.records) + rescue Dekorator::DecoratorNotFound + helpers.decorate(@dependency.records, with: ApplicationDecorator) + end end end diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index d7dbdadef..0e5b72fb6 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -1,13 +1,15 @@ -class RecordDependencies - ALLOW_DEPEDENCY_OPTIONS = %i[ - restrict_with_error - destroy - ].freeze +# frozen_string_literal: true +class RecordDependencies + ALLOW_DEPEDENCY_OPTIONS = %i[restrict_with_error destroy].freeze EXCLUDED_KLASSES = [ActiveStorage::Blob, ActiveStorage::Attachment].freeze - Dependency = Data.new(:association, :origin) do - delegate :name, :klass, to: :association + Dependency = Data.define(:association, :origin) do + delegate :name, to: :association + + def title + association.klass.model_name.human + end def records origin.public_send(association.name) @@ -18,46 +20,43 @@ def empty? end end - def initialize(record, only: [], except: []) + def initialize(record, only: nil, except: nil) @record = record @only = only @except = except - - @dependencies = {} end def destroyable - dependencies[:destroy] + dependencies_per_type[:destroy] || [] end def restricted_with_error - dependencies[:restrict_with_error] + dependencies_per_type[:restrict_with_error] || [] end - # def nillable - # end - - def dependencies - @dependencies ||= _load_dependencies + def dependencies_per_type + _load_dependencies if @dependencies_per_type.nil? + @dependencies_per_type end private def _load_dependencies + @dependencies_per_type = {} @record.class.reflect_on_all_associations.each do |association| # exclude according to config - next unless association_counts?(association) - dependency = Dependency.new(association, @record) + next unless association_valid?(association) - next if records.empty? + dependency = Dependency.new(association, @record) + next if dependency.empty? - (@dependencies[association.options[:dependent]] ||= []) << dependency + # add dependency according to his type + (@dependencies_per_type[association.options[:dependent]] ||= []) << dependency end end - # TODO: rename - def association_counts?(association) + def association_valid?(association) # only is above default config return @only.include?(association.name) unless @only.nil? diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index 3c5815d34..bec35f1d8 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -7,57 +7,54 @@ let(:component) { described_class.new(record, confirmation_path:) } let(:rendered_component) { render_inline(component).to_html } - before { allow(component).to receive(:url_for).and_return("/fake/url") } - context "with restricting dependency" do - let(:record) do - server = Server.new(name: "Dummy name") - document = Document.new + let(:record) { Server.new(name: "Dummy name") } + let(:document) { Document.new } + + before do allow(document).to receive_messages( document: instance_double(DocumentUploader::UploadedFile, metadata: { filename: "this is a filename" }), document_url: "/fake/url", ) - allow(server).to receive_messages( + allow(record).to receive_messages( external_app_record: [], documents: [document], moves: [], ) - - server end it { expect(rendered_component).to have_tag("h4", title: Document.model_name.human) } - it { expect(rendered_component).to have_tag("a[target=_blank]", href: "/fake/url", title: "this is a filename") } + it { expect(rendered_component).to have_tag("li.list-group-item", title: "this is a filename") } it { expect(rendered_component).not_to have_tag("a.btn-danger") } it { expect(rendered_component).not_to have_tag("a.btn-default") } end context "without restricting dependency" do describe "with destroy dependency" do - let(:record) do - contact = Contact.new(first_name: "Dummy", last_name: "name") - allow(contact).to receive(:contact_assignments).and_return([ContactAssignment.new]) - contact + let(:record) { Contact.new(first_name: "Dummy", last_name: "name") } + + before do + allow(record).to receive(:contact_assignments).and_return([ContactAssignment.new]) end - it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } + it { expect(rendered_component).to have_tag("a.btn-danger", href: confirmation_path) } it { expect(rendered_component).to have_tag("a.btn-default") } it { expect(rendered_component).to have_tag("h4", title: ContactAssignment.model_name.human) } - it { expect(rendered_component).to have_tag("a[target=_blank]", href: "/fake/url", title: ContactAssignment.new.to_s) } + it { expect(rendered_component).to have_tag("li.list-group-item", title: ContactAssignment.new.to_s) } end describe "without destroy dependency" do - let(:record) do - contact = Contact.new(first_name: "Dummy", last_name: "name") - allow(contact).to receive(:contact_assignments).and_return([]) - contact + let(:record) { Contact.new(first_name: "Dummy", last_name: "name") } + + before do + allow(record).to receive(:contact_assignments).and_return([]) end it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } it { expect(rendered_component).to have_tag("a.btn-default") } it { expect(rendered_component).not_to have_tag("h4", title: ContactAssignment.model_name.human) } - it { expect(rendered_component).not_to have_tag("a[target=_blank]", href: "/fake/url", title: ContactAssignment.new.to_s) } + it { expect(rendered_component).not_to have_tag("li.list-group-item") } end end end diff --git a/spec/models/record_dependencies_model_spec.rb b/spec/models/record_dependencies_model_spec.rb new file mode 100644 index 000000000..b59fc7c6f --- /dev/null +++ b/spec/models/record_dependencies_model_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe RecordDependencies do + subject(:dep) do + described_class.new(record) + end + + context "with restricting dependency" do + let(:record) { Server.new(name: "Dummy name") } + let(:document) { Document.new } + + before do + allow(document).to receive_messages( + document: instance_double(DocumentUploader::UploadedFile, metadata: { filename: "this is a filename" }), + document_url: "/fake/url", + ) + + allow(record).to receive_messages( + external_app_record: [], + documents: [document], + moves: [], + ) + end + + it { expect(dep.restricted_with_error[0].records).to eq([document]) } + it { expect(dep.restricted_with_error[0].name).to be(:documents) } + it { expect(dep.restricted_with_error[0].title).to be(Document.model_name.human) } + it { expect(dep.destroyable.length).to be(0) } + end + + context "with destroyable dependency" do + let(:record) { Server.new(name: "Dummy name") } + let(:move) { Move.new } + + before do + allow(record).to receive_messages( + external_app_record: [], + documents: [], + moves: [move], + ) + end + + it { expect(dep.destroyable[0].records).to eq([move]) } + it { expect(dep.destroyable[0].name).to be(:moves) } + it { expect(dep.destroyable[0].title).to be(Move.model_name.human) } + it { expect(dep.restricted_with_error.length).to be(0) } + end +end From 845cd879500d7e6b7f395c38d0ec62992f7e9277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Wed, 29 Oct 2025 17:53:05 +0100 Subject: [PATCH 13/33] visual improuvment --- app/components/delete_dependency_component.rb | 15 +++++++++++---- config/locales/fr.yml | 5 +++-- .../delete_dependency_component_spec.rb | 6 +++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 78e0a857a..dca291b0e 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -15,7 +15,7 @@ class DeleteDependencyComponent < ApplicationComponent {dependencies: @record_dependencies.destroyable, grp_title: t(".destroy_dependency_title")}, ].filter { |grp| !grp[:dependencies].empty? }.each do |group| %> -

      <%= group[:grp_title] %>

      +

      <%= group[:grp_title] %>

      <% group[:dependencies].each do |dependency| %> <%= render CollectionComponent.new(dependency) %> @@ -33,17 +33,24 @@ def initialize(record, confirmation_path:, only: nil, except: nil) end class CollectionComponent < ApplicationComponent + MAX_RECORD_TO_SHOW = 20 + erb_template <<~ERB
      -

      <%= @dependency.title %>

      +
      <%= @dependency.title %>

      (<%= @dependency.name %>)

        - <% records.each do |record| %> -
      • + <% records.slice(0, MAX_RECORD_TO_SHOW).each do |record| %> +
      • <%= record.display_name %>
      • <% end %> + <% if records.length > MAX_RECORD_TO_SHOW %> +
      • + <%= t(".and_more", n_more: records.length - MAX_RECORD_TO_SHOW) %> +
      • + <% end %>
      ERB diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 5ee4ae810..e2aab93db 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -980,6 +980,7 @@ fr: select: placeholder: Tapez pour filtrer... delete_dependency_component: - restrict_dependency_title: "Ressources empêchants la suppréssion" - destroy_dependency_title: "Ressources qui seront supprimées lors de la suppréssion" + restrict_dependency_title: "Ressources empêchants la suppréssion :" + destroy_dependency_title: "Ressources qui seront supprimées lors de la suppréssion :" confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible. + and_more: Et %{n_more} autres ... diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index bec35f1d8..8aacd2efe 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -24,7 +24,7 @@ ) end - it { expect(rendered_component).to have_tag("h4", title: Document.model_name.human) } + it { expect(rendered_component).to have_tag("h5", title: Document.model_name.human) } it { expect(rendered_component).to have_tag("li.list-group-item", title: "this is a filename") } it { expect(rendered_component).not_to have_tag("a.btn-danger") } it { expect(rendered_component).not_to have_tag("a.btn-default") } @@ -40,7 +40,7 @@ it { expect(rendered_component).to have_tag("a.btn-danger", href: confirmation_path) } it { expect(rendered_component).to have_tag("a.btn-default") } - it { expect(rendered_component).to have_tag("h4", title: ContactAssignment.model_name.human) } + it { expect(rendered_component).to have_tag("h5", title: ContactAssignment.model_name.human) } it { expect(rendered_component).to have_tag("li.list-group-item", title: ContactAssignment.new.to_s) } end @@ -53,7 +53,7 @@ it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } it { expect(rendered_component).to have_tag("a.btn-default") } - it { expect(rendered_component).not_to have_tag("h4", title: ContactAssignment.model_name.human) } + it { expect(rendered_component).not_to have_tag("h5", title: ContactAssignment.model_name.human) } it { expect(rendered_component).not_to have_tag("li.list-group-item") } end end From 12fc5c8d8226d7c395216bf8961e5101d6ab5d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Thu, 30 Oct 2025 17:34:21 +0100 Subject: [PATCH 14/33] implementing nicolas's proposition --- app/components/delete_dependency_component.rb | 10 +++------- app/controllers/rooms_controller.rb | 2 +- app/models/record_dependencies.rb | 7 +++++++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index dca291b0e..181490da8 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -10,14 +10,10 @@ class DeleteDependencyComponent < ApplicationComponent icon: :trash, is_responsive: true) %> <% end %> - <% [ - {dependencies: @record_dependencies.restricted_with_error, grp_title: t(".restrict_dependency_title")}, - {dependencies: @record_dependencies.destroyable, grp_title: t(".destroy_dependency_title")}, - ].filter { |grp| !grp[:dependencies].empty? }.each do |group| %> - -

      <%= group[:grp_title] %>

      + <% @record_dependencies.grouped_by_dependent.each do |type, dependencies| %> +

      <%= t(".\#{type}_dependency_title") %>

      - <% group[:dependencies].each do |dependency| %> + <% dependencies.each do |dependency| %> <%= render CollectionComponent.new(dependency) %> <% end %>
      diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index ead86b86d..560cfed73 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class RoomsController < ApplicationController # rubocop:disable Metrics/ClassLength +class RoomsController < ApplicationController include ServersHelper include RoomsHelper diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index 0e5b72fb6..dc3347490 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -26,6 +26,13 @@ def initialize(record, only: nil, except: nil) @except = except end + def grouped_by_dependent + [ + [:restrict, restricted_with_error], + [:destroy, destroyable], + ] + end + def destroyable dependencies_per_type[:destroy] || [] end From 3679946c1c4aab1463a4bf15f67d680578506a19 Mon Sep 17 00:00:00 2001 From: B_Rass Date: Fri, 21 Nov 2025 15:08:41 +0100 Subject: [PATCH 15/33] Update component design (wip) --- app/assets/stylesheets/application.scss | 28 ++--- app/components/button_component.rb | 4 +- app/components/delete_dependency_component.rb | 108 +++++++++++++----- app/views/cables/_draw.html.erb | 2 +- config/locales/activerecord.en.yml | 3 + config/locales/activerecord.fr.yml | 3 + config/locales/components.en.yml | 7 ++ config/locales/components.fr.yml | 7 ++ config/locales/fr.yml | 5 - 9 files changed, 115 insertions(+), 52 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 534fcbc26..3af0a932f 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -440,19 +440,6 @@ dd { padding-left: 37px; } - .btn-collapse-vlans { - span.bi { - display: inline-block; - transition: transform 0.3s ease-in-out; - } - - &[aria-expanded="true"] { - span.bi { - transform: rotate(-180deg); - } - } - } - .cable { &.R { border-color: #ee3b3b !important; @@ -981,6 +968,19 @@ body { } } + .btn-collapse { + span.bi { + display: inline-block; + transition: transform 0.3s ease-in-out; + } + + &[aria-expanded="true"] { + span.bi { + transform: rotate(-180deg); + } + } + } + ul.list-group-flush { li { border-style: dashed; @@ -1019,7 +1019,7 @@ body { --bs-spinner-height: 0.875rem; } - ul.show-page_list-group-flush { + .card-body ul.list-group { /* Fix rounded border not showing correctly when in card */ border-bottom-right-radius: var(--bs-border-radius) !important; border-bottom-left-radius: var(--bs-border-radius) !important; diff --git a/app/components/button_component.rb b/app/components/button_component.rb index e538a7de3..989d733e4 100644 --- a/app/components/button_component.rb +++ b/app/components/button_component.rb @@ -4,7 +4,7 @@ class ButtonComponent < ApplicationComponent VARIANTS = %i[ default primary secondary success danger warning info light dark link - outline_primary outline_success outline_danger outline_info + outline_primary outline_secondary outline_success outline_danger outline_info ].freeze SIZES = %i[sm default lg].freeze @@ -30,7 +30,7 @@ def call title: @html_options&.dig(:data, :tooltip_title) || @title, **@html_options do concat(tag.span(class: "bi bi-#{@icon}")) if @icon - concat(tag.span(@title, class: class_names("ms-2", "d-none d-md-inline-flex": @is_responsive))) if @title + concat(tag.span(@title, class: class_names("ms-2": @icon, "d-none d-md-inline-flex": @is_responsive))) if @title end end end diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 181490da8..d86dccca9 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -2,23 +2,59 @@ class DeleteDependencyComponent < ApplicationComponent erb_template <<~ERB - <% if @record_dependencies.restricted_with_error.blank? %> -

      <%= t(".confirm") %>

      +
      + <% @record_dependencies.grouped_by_dependent.each_with_index do |(type, dependencies), i| %> + <% next unless dependencies.any? %> - <%= render ButtonComponent.new(t("action.cancel"), url: :back, variant: :info, is_responsive: true) %> - <%= render ButtonComponent.new(t("action.delete"), url: @confirmation_path, method: :delete, variant: :danger, - icon: :trash, is_responsive: true) %> - <% end %> + <%- if i > 0 %> +
      + <% end %> + +
      +
      -emphasis"><%= t(".\#{type}_dependency_title") %>
      + + + | + + +
      - <% @record_dependencies.grouped_by_dependent.each do |type, dependencies| %> -

      <%= t(".\#{type}_dependency_title") %>

      -
      <% dependencies.each do |dependency| %> - <%= render CollectionComponent.new(dependency) %> + <%= render CollectionComponent.new(dependency, type) %> <% end %> -
      + <% end %> + +
      + + <%= render ButtonComponent.new( + t("action.cancel"), url: :back, variant: :outline_secondary, extra_classes: "me-2" + ) %> - <% end %> + <%= render ButtonComponent.new( + t("action.delete"), + url: @confirmation_path, + method: :delete, + variant: :danger, + extra_classes: class_names(disabled: @record_dependencies.restricted_with_error.any?)) %> + +
      +
      ERB def initialize(record, confirmation_path:, only: nil, except: nil) @@ -29,30 +65,42 @@ def initialize(record, confirmation_path:, only: nil, except: nil) end class CollectionComponent < ApplicationComponent - MAX_RECORD_TO_SHOW = 20 + MAX_RECORDS_TO_SHOW = 20 erb_template <<~ERB -
      -
      <%= @dependency.title %>
      -

      (<%= @dependency.name %>)

      + <%= render CardComponent.new( + type: (@type == :restrict ? :danger : :warning), + extra_classes: "bg-body-tertiary mt-2 ms-5" + ) do |card| %> + <% card.with_header do %> + + <% end %> -
        - <% records.slice(0, MAX_RECORD_TO_SHOW).each do |record| %> -
      • - <%= record.display_name %> -
      • - <% end %> - <% if records.length > MAX_RECORD_TO_SHOW %> -
      • - <%= t(".and_more", n_more: records.length - MAX_RECORD_TO_SHOW) %> -
      • - <% end %> -
      -
      + <% card.with_body(extra_classes: "p-0 collapse collapse_\#{@type}", id: @collapse_id) do %> +
        + <% records.each do |record| %> +
      • + <%= record.display_name %> +
      • + <% end %> +
      + <% end %> + <% end %> ERB - def initialize(dependency) + def initialize(dependency, type) @dependency = dependency + @type = type + @collapse_id = "collapseCard-#{@dependency.name}" super end diff --git a/app/views/cables/_draw.html.erb b/app/views/cables/_draw.html.erb index df72669ec..f68a5ffea 100644 --- a/app/views/cables/_draw.html.erb +++ b/app/views/cables/_draw.html.erb @@ -19,7 +19,7 @@ <%= cable.decorated.server_connected_with_link(to_connection) %>
      - - | - - -
    - - <% dependencies.each do |dependency| %> - <%= render CollectionComponent.new(dependency, type) %> - <% end %> - <% end %> + <%= render CollectionGroupComponent.with_collection( + grouped_by_dependent, spacer_component: CollectionGroupSpacerComponent.new, + ) %>
    @@ -64,12 +31,79 @@ def initialize(record, confirmation_path:, only: nil, except: nil) super end + private + + def grouped_by_dependent + { + restrict_with_error: @record_dependencies.restricted_with_error, + destroy: @record_dependencies.destroyable, + }.to_a + end + + class CollectionGroupComponent < ApplicationComponent + TYPES = { + restrict_with_error: :danger, + destroy: :warning, + }.freeze + + erb_template <<~ERB +
    +
    <%= t(".\#{@type}_dependency_title") %>
    + + + | + + +
    + + <%= render DeleteDependencyComponent::CollectionComponent.with_collection(@dependencies) %> + ERB + + def initialize(collection_group:) + @type = collection_group[0] + @dependencies = collection_group[1] + + super() + end + + def render? + @dependencies.any? + end + end + + class CollectionGroupSpacerComponent < ApplicationComponent + erb_template <<~ERB +
    + ERB + end + class CollectionComponent < ApplicationComponent - MAX_RECORDS_TO_SHOW = 20 + with_collection_parameter :dependency + + TYPES = { + restrict_with_error: :danger, + destroy: :warning, + }.freeze erb_template <<~ERB <%= render CardComponent.new( - type: (@type == :restrict ? :danger : :warning), + type: TYPES[@type], extra_classes: "bg-body-tertiary mt-2 ms-5" ) do |card| %> <% card.with_header do %> @@ -97,9 +131,9 @@ class CollectionComponent < ApplicationComponent <% end %> ERB - def initialize(dependency, type) + def initialize(dependency:) @dependency = dependency - @type = type + @type = dependency.type @collapse_id = "collapseCard-#{@dependency.name}" super diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index dc3347490..e6a7eed1c 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -15,6 +15,10 @@ def records origin.public_send(association.name) end + def type + association.options[:dependent] + end + def empty? records.blank? end @@ -22,8 +26,8 @@ def empty? def initialize(record, only: nil, except: nil) @record = record - @only = only - @except = except + @only = Array(only).map(&:to_sym) if only.present? + @except = Array(except).map(&:to_sym) if except.present? end def grouped_by_dependent @@ -73,6 +77,6 @@ def association_valid?(association) return false if EXCLUDED_KLASSES.include?(association.klass) # exept is not above default config - @expect.nil? || @expect.exclude?(association.name) + @except.nil? || @except.exclude?(association.name) end end diff --git a/app/views/frames/destroy.html.erb b/app/views/frames/destroy.html.erb index 076d484cb..4b916e7b7 100644 --- a/app/views/frames/destroy.html.erb +++ b/app/views/frames/destroy.html.erb @@ -9,6 +9,7 @@
    <%= render DeleteDependencyComponent.new( @frame, + except: %i[materials], confirmation_path: frame_path(@frame, confirm: true) ) %>
    diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb index 0fe308beb..74b46b41d 100644 --- a/app/views/servers/destroy.html.erb +++ b/app/views/servers/destroy.html.erb @@ -9,6 +9,7 @@
    <%= render DeleteDependencyComponent.new( @server, + except: %i[external_app_records], confirmation_path: server_path(@server, confirm: true) ) %>
    diff --git a/config/locales/components.en.yml b/config/locales/components.en.yml index 0d24fe2c4..5a9e432cd 100644 --- a/config/locales/components.en.yml +++ b/config/locales/components.en.yml @@ -3,7 +3,7 @@ en: title: No data found delete_dependency_component: - restrict_dependency_title: Related resources blocking deletion + restrict_with_error_dependency_title: Related resources blocking deletion destroy_dependency_title: Related resources that will be removed show_all: Show all hide_all: Hide all diff --git a/config/locales/components.fr.yml b/config/locales/components.fr.yml index 5297667b3..64b0bee68 100644 --- a/config/locales/components.fr.yml +++ b/config/locales/components.fr.yml @@ -3,7 +3,7 @@ fr: title: Aucune donnée trouvée delete_dependency_component: - restrict_dependency_title: Ressources liées bloquant la suppression + restrict_with_error_dependency_title: Ressources liées bloquant la suppression destroy_dependency_title: Ressources liées qui vont être supprimées show_all: Afficher tout hide_all: Cacher tout diff --git a/spec/components/button_component_spec.rb b/spec/components/button_component_spec.rb index 83a8877da..8f712a18a 100644 --- a/spec/components/button_component_spec.rb +++ b/spec/components/button_component_spec.rb @@ -12,7 +12,7 @@ it do expect(rendered_component).to have_tag("a.btn-default.btn-default", href: "/url", title: "Title") do without_tag("span.bi") - with_tag("span.ms-2:not(.d-none)", text: "Title") + with_tag("span:not(.d-none)", text: "Title", without: { class: "ms-2" }) end end end @@ -50,6 +50,7 @@ it do expect(rendered_component).to have_tag("a.btn-default.btn-default", href: "/url", title: "Title") do + with_tag("span", text: "Title", with: { class: "ms-2" }) with_tag("span.bi-eye") end end @@ -60,7 +61,7 @@ it do expect(rendered_component).to have_tag("a.btn-default.btn-default", href: "/url", title: "Title") do - with_tag("span.ms-2.d-none", text: "Title") + with_tag("span.d-none", text: "Title", without: { class: "ms-2" }) end end end From c0fd0bb22a603f723a105cb019ad2e8fa9d255c6 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 26 Nov 2025 16:31:59 +0100 Subject: [PATCH 17/33] Code cleanup --- app/components/delete_dependency_component.rb | 2 +- app/models/air_conditioner_model.rb | 1 + app/models/record_dependencies.rb | 8 +++----- app/views/servers/destroy.html.erb | 2 +- spec/models/frame_spec.rb | 1 + 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index b852ea373..560677b60 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -37,7 +37,7 @@ def grouped_by_dependent { restrict_with_error: @record_dependencies.restricted_with_error, destroy: @record_dependencies.destroyable, - }.to_a + }.select { |_, dependencies| dependencies.any? }.to_a end class CollectionGroupComponent < ApplicationComponent diff --git a/app/models/air_conditioner_model.rb b/app/models/air_conditioner_model.rb index cc118942f..dc796b13c 100644 --- a/app/models/air_conditioner_model.rb +++ b/app/models/air_conditioner_model.rb @@ -4,6 +4,7 @@ class AirConditionerModel < ApplicationRecord has_changelog belongs_to :manufacturer + has_many :air_conditioners, dependent: :restrict_with_error def to_s diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index e6a7eed1c..ab360696e 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class RecordDependencies - ALLOW_DEPEDENCY_OPTIONS = %i[restrict_with_error destroy].freeze + ALLOWED_DEPEDENT_OPTIONS = %i[restrict_with_error destroy].freeze EXCLUDED_KLASSES = [ActiveStorage::Blob, ActiveStorage::Attachment].freeze Dependency = Data.define(:association, :origin) do @@ -55,14 +55,11 @@ def dependencies_per_type def _load_dependencies @dependencies_per_type = {} @record.class.reflect_on_all_associations.each do |association| - # exclude according to config - next unless association_valid?(association) dependency = Dependency.new(association, @record) next if dependency.empty? - # add dependency according to his type (@dependencies_per_type[association.options[:dependent]] ||= []) << dependency end end @@ -72,7 +69,8 @@ def association_valid?(association) return @only.include?(association.name) unless @only.nil? # default behavior - return false unless ALLOW_DEPEDENCY_OPTIONS.include?(association.options[:dependent]) + return false if association.options.key?(:through) + return false unless ALLOWED_DEPEDENT_OPTIONS.include?(association.options[:dependent]) return false if %i[changelog_entries slugs].include?(association.name) return false if EXCLUDED_KLASSES.include?(association.klass) diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb index 74b46b41d..2f7d680be 100644 --- a/app/views/servers/destroy.html.erb +++ b/app/views/servers/destroy.html.erb @@ -9,7 +9,7 @@
    <%= render DeleteDependencyComponent.new( @server, - except: %i[external_app_records], + except: %i[external_app_record], confirmation_path: server_path(@server, confirm: true) ) %>
    diff --git a/spec/models/frame_spec.rb b/spec/models/frame_spec.rb index d6b5b1eb4..855eee60b 100644 --- a/spec/models/frame_spec.rb +++ b/spec/models/frame_spec.rb @@ -10,6 +10,7 @@ describe "associations" do it { is_expected.to belong_to(:bay) } + it { is_expected.to have_one(:islet).through(:bay) } it { is_expected.to have_many(:materials) } it { is_expected.to have_many(:pdus) } From 829cf786903caf7e9e8a453de5867037b7922819 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 26 Nov 2025 16:32:51 +0100 Subject: [PATCH 18/33] Move Destroy confirm check in a shared method --- app/controllers/air_conditioners_controller.rb | 6 +----- app/controllers/application_controller.rb | 6 ++++++ app/controllers/architectures_controller.rb | 6 +----- app/controllers/bays_controller.rb | 6 +----- app/controllers/card_types_controller.rb | 6 +----- app/controllers/categories_controller.rb | 6 +----- app/controllers/clusters_controller.rb | 6 +----- app/controllers/colors_controller.rb | 6 +----- app/controllers/contact_assignments_controller.rb | 6 +----- app/controllers/contact_roles_controller.rb | 6 +----- app/controllers/contacts_controller.rb | 6 +----- app/controllers/domaines_controller.rb | 6 +----- app/controllers/frames_controller.rb | 6 +----- app/controllers/gestions_controller.rb | 6 +----- app/controllers/islets_controller.rb | 6 +----- app/controllers/manufacturers_controller.rb | 6 +----- app/controllers/modeles_controller.rb | 6 +----- app/controllers/port_types_controller.rb | 6 +----- app/controllers/power_distribution_units_controller.rb | 6 +----- app/controllers/rooms_controller.rb | 6 +----- app/controllers/servers_controller.rb | 6 +----- app/controllers/sites_controller.rb | 6 +----- app/controllers/stacks_controller.rb | 6 +----- 23 files changed, 28 insertions(+), 110 deletions(-) diff --git a/app/controllers/air_conditioners_controller.rb b/app/controllers/air_conditioners_controller.rb index 82d7161ff..5e5926bef 100644 --- a/app/controllers/air_conditioners_controller.rb +++ b/app/controllers/air_conditioners_controller.rb @@ -48,12 +48,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - @air_conditioner.destroy! respond_to do |format| diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4229e1abb..52eaddfd0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -123,4 +123,10 @@ def no_permission_scope render "no_permission_scope", layout: "application" end + + def self.destroy_confirmation(only: :destroy) + before_action only: do + render unless params[:confirm] == "true" + end + end end diff --git a/app/controllers/architectures_controller.rb b/app/controllers/architectures_controller.rb index 598af67cb..ef10e5ad8 100644 --- a/app/controllers/architectures_controller.rb +++ b/app/controllers/architectures_controller.rb @@ -56,12 +56,8 @@ def update # DELETE /architectures/1 # DELETE /architectures/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @architecture.destroy respond_to do |format| format.html { redirect_to architectures_url, notice: t(".destroy.flashes.destroyed") } diff --git a/app/controllers/bays_controller.rb b/app/controllers/bays_controller.rb index 157a66d74..4a775115d 100644 --- a/app/controllers/bays_controller.rb +++ b/app/controllers/bays_controller.rb @@ -61,12 +61,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @bay.destroy respond_to do |format| format.html { form_redirect_to bays_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/card_types_controller.rb b/app/controllers/card_types_controller.rb index 5f2eaf026..113d968be 100644 --- a/app/controllers/card_types_controller.rb +++ b/app/controllers/card_types_controller.rb @@ -54,12 +54,8 @@ def update # DELETE /card_types/1 # DELETE /card_types/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @card_type.destroy respond_to do |format| format.html { redirect_to card_types_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 52b859b42..7806f9f96 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -57,12 +57,8 @@ def update # DELETE /categories/1 # DELETE /categories/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @category.destroy respond_to do |format| format.html { redirect_to categories_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/clusters_controller.rb b/app/controllers/clusters_controller.rb index e8a2ca793..a63a17544 100644 --- a/app/controllers/clusters_controller.rb +++ b/app/controllers/clusters_controller.rb @@ -58,12 +58,8 @@ def update # DELETE /clusters/1 # DELETE /clusters/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @cluster.destroy respond_to do |format| format.html { redirect_to clusters_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/colors_controller.rb b/app/controllers/colors_controller.rb index b6b1ed31c..f286c68b3 100644 --- a/app/controllers/colors_controller.rb +++ b/app/controllers/colors_controller.rb @@ -48,12 +48,8 @@ def update # DELETE /colors/1 # DELETE /colors/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - @color.destroy respond_to do |format| format.html { redirect_to colors_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contact_assignments_controller.rb b/app/controllers/contact_assignments_controller.rb index 19f34573a..9496e9925 100644 --- a/app/controllers/contact_assignments_controller.rb +++ b/app/controllers/contact_assignments_controller.rb @@ -59,12 +59,8 @@ def update # DELETE /contact_assignments/1 # DELETE /contact_assignments/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @contact_assignment.destroy! respond_to do |format| format.html { redirect_to contact_assignments_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contact_roles_controller.rb b/app/controllers/contact_roles_controller.rb index 952f4b9f9..ae8066e0e 100644 --- a/app/controllers/contact_roles_controller.rb +++ b/app/controllers/contact_roles_controller.rb @@ -57,12 +57,8 @@ def update # DELETE /contact_roles/1 # DELETE /contact_roles/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @contact_role.destroy respond_to do |format| format.html { redirect_to contact_roles_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index b6224fa99..b3c42e716 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -57,12 +57,8 @@ def update # DELETE /contacts/1 # DELETE /contacts/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @contact.destroy respond_to do |format| format.html { redirect_to contacts_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/domaines_controller.rb b/app/controllers/domaines_controller.rb index 20d84996f..2174202ed 100644 --- a/app/controllers/domaines_controller.rb +++ b/app/controllers/domaines_controller.rb @@ -56,12 +56,8 @@ def update # DELETE /domaines/1 # DELETE /domaines/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @domaine.destroy respond_to do |format| format.html { redirect_to domaines_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/frames_controller.rb b/app/controllers/frames_controller.rb index ad667ecfc..0850e61b9 100644 --- a/app/controllers/frames_controller.rb +++ b/app/controllers/frames_controller.rb @@ -64,12 +64,8 @@ def sort head :ok end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @frame.destroy respond_to do |format| format.html { redirect_to frames_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/gestions_controller.rb b/app/controllers/gestions_controller.rb index 386f8e52a..2cf0cf588 100644 --- a/app/controllers/gestions_controller.rb +++ b/app/controllers/gestions_controller.rb @@ -56,12 +56,8 @@ def update # DELETE /gestions/1 # DELETE /gestions/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @gestion.destroy respond_to do |format| format.html { redirect_to gestions_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/islets_controller.rb b/app/controllers/islets_controller.rb index e66c163e0..33594d604 100644 --- a/app/controllers/islets_controller.rb +++ b/app/controllers/islets_controller.rb @@ -65,12 +65,8 @@ def update # DELETE /islets/1 # DELETE /islets/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @islet.destroy respond_to do |format| format.html { redirect_to islets_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/manufacturers_controller.rb b/app/controllers/manufacturers_controller.rb index 6ba33c1b7..69139f5f8 100644 --- a/app/controllers/manufacturers_controller.rb +++ b/app/controllers/manufacturers_controller.rb @@ -56,12 +56,8 @@ def update # DELETE /manufacturers/1 # DELETE /manufacturers/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @manufacturer.destroy respond_to do |format| format.html { redirect_to manufacturers_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/modeles_controller.rb b/app/controllers/modeles_controller.rb index f0cb1541c..a2786123e 100644 --- a/app/controllers/modeles_controller.rb +++ b/app/controllers/modeles_controller.rb @@ -78,12 +78,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @modele.destroy respond_to do |format| format.html { redirect_to modeles_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/port_types_controller.rb b/app/controllers/port_types_controller.rb index e26c026ec..78006b76a 100644 --- a/app/controllers/port_types_controller.rb +++ b/app/controllers/port_types_controller.rb @@ -44,12 +44,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - @port_type.destroy respond_to do |format| format.html { redirect_to port_types_path, notice: t(".flashes.destroyed") } diff --git a/app/controllers/power_distribution_units_controller.rb b/app/controllers/power_distribution_units_controller.rb index 70b37970e..c136b65b4 100644 --- a/app/controllers/power_distribution_units_controller.rb +++ b/app/controllers/power_distribution_units_controller.rb @@ -58,12 +58,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - respond_to do |format| if @pdu.destroy format.html { redirect_to power_distribution_units_path(search_params), notice: t(".flashes.destroyed") } diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 560cfed73..b8bbf6897 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -55,12 +55,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @room.destroy respond_to do |format| format.html { redirect_to rooms_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index 9d7fa0b4d..0dd4d12e5 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -73,12 +73,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - respond_to do |format| if @server.destroy format.html { redirect_to servers_path(search_params), notice: t(".flashes.destroyed") } diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index a11220ef9..6d1c2f5fd 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -47,12 +47,8 @@ def update end end + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @site.destroy respond_to do |format| format.html { redirect_to sites_url, notice: t(".flashes.destroyed") } diff --git a/app/controllers/stacks_controller.rb b/app/controllers/stacks_controller.rb index e7350a1f9..68420d25e 100644 --- a/app/controllers/stacks_controller.rb +++ b/app/controllers/stacks_controller.rb @@ -56,12 +56,8 @@ def update # DELETE /stacks/1 # DELETE /stacks/1.json + destroy_confirmation def destroy - unless params["confirm"] == "true" - render - return - end - if @stack.destroy respond_to do |format| format.html { redirect_to stacks_url, notice: t(".flashes.destroyed") } From 59ff7d350518ca7185c359216923f9146e45a844 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 26 Nov 2025 17:56:36 +0100 Subject: [PATCH 19/33] Rework tests and code cleanup --- app/controllers/application_controller.rb | 12 ++-- app/controllers/modeles_controller.rb | 2 +- app/models/record_dependencies.rb | 7 -- .../delete_dependency_component_spec.rb | 4 +- spec/models/record_dependencies_model_spec.rb | 50 ------------- spec/models/record_dependencies_spec.rb | 70 +++++++++++++++++++ spec/models/server_spec.rb | 8 ++- 7 files changed, 84 insertions(+), 69 deletions(-) delete mode 100644 spec/models/record_dependencies_model_spec.rb create mode 100644 spec/models/record_dependencies_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 52eaddfd0..5c5b8e0ec 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -27,6 +27,12 @@ class ApplicationController < ActionController::Base layout :layout_by_resource + def self.destroy_confirmation(only: :destroy) + before_action only: do + render unless params[:confirm] == "true" + end + end + def after_sign_in_path_for(resource) # return request.env['omniauth.origin'] || stored_location_for(resource) || root_path #=> with our setup, omniauth.origin always contain sign_in page since user was first redirected on it @@ -123,10 +129,4 @@ def no_permission_scope render "no_permission_scope", layout: "application" end - - def self.destroy_confirmation(only: :destroy) - before_action only: do - render unless params[:confirm] == "true" - end - end end diff --git a/app/controllers/modeles_controller.rb b/app/controllers/modeles_controller.rb index a2786123e..62ae839fa 100644 --- a/app/controllers/modeles_controller.rb +++ b/app/controllers/modeles_controller.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class ModelesController < ApplicationController # rubocop:disable Metrics/ClassLength +class ModelesController < ApplicationController include ModelesHelper before_action :set_modele, only: %i[show edit update destroy] diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index ab360696e..6fe0f37c0 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -30,13 +30,6 @@ def initialize(record, only: nil, except: nil) @except = Array(except).map(&:to_sym) if except.present? end - def grouped_by_dependent - [ - [:restrict, restricted_with_error], - [:destroy, destroyable], - ] - end - def destroyable dependencies_per_type[:destroy] || [] end diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index 8aacd2efe..1528fd64b 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -3,8 +3,8 @@ require "rails_helper" RSpec.describe DeleteDependencyComponent, type: :component do - let(:confirmation_path) { "/confirmation-path" } - let(:component) { described_class.new(record, confirmation_path:) } + let(:confirmation_path) { "/confirmation-path" } + let(:component) { described_class.new(record, confirmation_path:) } let(:rendered_component) { render_inline(component).to_html } context "with restricting dependency" do diff --git a/spec/models/record_dependencies_model_spec.rb b/spec/models/record_dependencies_model_spec.rb deleted file mode 100644 index b59fc7c6f..000000000 --- a/spec/models/record_dependencies_model_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe RecordDependencies do - subject(:dep) do - described_class.new(record) - end - - context "with restricting dependency" do - let(:record) { Server.new(name: "Dummy name") } - let(:document) { Document.new } - - before do - allow(document).to receive_messages( - document: instance_double(DocumentUploader::UploadedFile, metadata: { filename: "this is a filename" }), - document_url: "/fake/url", - ) - - allow(record).to receive_messages( - external_app_record: [], - documents: [document], - moves: [], - ) - end - - it { expect(dep.restricted_with_error[0].records).to eq([document]) } - it { expect(dep.restricted_with_error[0].name).to be(:documents) } - it { expect(dep.restricted_with_error[0].title).to be(Document.model_name.human) } - it { expect(dep.destroyable.length).to be(0) } - end - - context "with destroyable dependency" do - let(:record) { Server.new(name: "Dummy name") } - let(:move) { Move.new } - - before do - allow(record).to receive_messages( - external_app_record: [], - documents: [], - moves: [move], - ) - end - - it { expect(dep.destroyable[0].records).to eq([move]) } - it { expect(dep.destroyable[0].name).to be(:moves) } - it { expect(dep.destroyable[0].title).to be(Move.model_name.human) } - it { expect(dep.restricted_with_error.length).to be(0) } - end -end diff --git a/spec/models/record_dependencies_spec.rb b/spec/models/record_dependencies_spec.rb new file mode 100644 index 000000000..4e13430b8 --- /dev/null +++ b/spec/models/record_dependencies_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe RecordDependencies do + subject(:record_dependencies) { described_class.new(record) } + + let(:record) { Server.new(name: "Dummy name") } + let(:document) { Document.new } + let(:move) { Move.new } + + describe "#destroyable" do + context "when no records associated" do + it { expect(record_dependencies.destroyable).to be_empty } + end + + context "when destroyable records associated" do + before do + allow(record).to receive_messages(external_app_record: [], documents: [], moves: [move]) + end + + it { expect(record_dependencies.destroyable).not_to be_empty } + it { expect(record_dependencies.destroyable).to all(be_a(RecordDependencies::Dependency)) } + it { expect(record_dependencies.destroyable).to all(have_attributes(type: :destroy)) } + + it :aggregate_failures do # rubocop:disable RSpec/ExampleLength + expect(record_dependencies.destroyable.size).to eq(1) + + record_dependencies.destroyable.each do |dependency| + expect(dependency.title).to eq("Déplacement prévu") + expect(dependency.records).to all(be_a(Move)) + expect(dependency.type).to eq(:destroy) + expect(dependency.empty?).to be(false) + end + end + end + end + + describe "#restricted_with_error" do + context "when no records associated" do + it { expect(record_dependencies.restricted_with_error).to be_empty } + end + + context "when destroyable records associated" do + before do + allow(document).to receive_messages( + document: instance_double(DocumentUploader::UploadedFile, metadata: { filename: "this is a filename" }), + document_url: "/fake/url", + ) + + allow(record).to receive_messages(external_app_record: [], documents: [document], moves: []) + end + + it { expect(record_dependencies.restricted_with_error).not_to be_empty } + it { expect(record_dependencies.restricted_with_error).to all(be_a(RecordDependencies::Dependency)) } + it { expect(record_dependencies.restricted_with_error).to all(have_attributes(type: :restrict_with_error)) } + + it :aggregate_failures do # rubocop:disable RSpec/ExampleLength + expect(record_dependencies.restricted_with_error.size).to eq(1) + + record_dependencies.restricted_with_error.each do |dependency| + expect(dependency.title).to eq("Document") + expect(dependency.records).to all(be_a(Document)) + expect(dependency.type).to eq(:restrict_with_error) + expect(dependency.empty?).to be(false) + end + end + end + end +end diff --git a/spec/models/server_spec.rb b/spec/models/server_spec.rb index 08c3032cd..773b9c682 100644 --- a/spec/models/server_spec.rb +++ b/spec/models/server_spec.rb @@ -11,14 +11,16 @@ describe "associations" do it { is_expected.to belong_to(:frame) } - it { is_expected.to have_one(:bay).through(:frame) } - it { is_expected.to have_one(:islet).through(:frame) } - it { is_expected.to have_one(:room).through(:islet) } it { is_expected.to belong_to(:gestion).optional(true) } it { is_expected.to belong_to(:domaine).optional(true) } it { is_expected.to belong_to(:modele) } it { is_expected.to belong_to(:cluster).optional(true) } it { is_expected.to belong_to(:stack).optional(true) } + + it { is_expected.to have_one(:bay).through(:frame) } + it { is_expected.to have_one(:islet).through(:frame) } + it { is_expected.to have_one(:room).through(:islet) } + it { is_expected.to have_many(:cards) } it { is_expected.to have_many(:card_types).through(:cards) } it { is_expected.to have_many(:ports).through(:cards) } From 390ed833dbc4fd840ade6259d7ce41e80ce52174 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 26 Nov 2025 17:57:44 +0100 Subject: [PATCH 20/33] Add destroy confirmation to cables --- app/views/cables/destroy.html.erb | 14 ++++++++++++++ app/views/cables/index.html.erb | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 app/views/cables/destroy.html.erb diff --git a/app/views/cables/destroy.html.erb b/app/views/cables/destroy.html.erb new file mode 100644 index 000000000..d7eb16661 --- /dev/null +++ b/app/views/cables/destroy.html.erb @@ -0,0 +1,14 @@ +<% + breadcrumb + .add_step(@cable, cable_path(@cable)) + .add_step(t("action.delete")) +%> + +<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> + +
    + <%= render DeleteDependencyComponent.new( + @cable, + confirmation_path: cable_path(@cable, confirm: true) + ) %> +
    diff --git a/app/views/cables/index.html.erb b/app/views/cables/index.html.erb index b3ec28dd9..996532364 100644 --- a/app/views/cables/index.html.erb +++ b/app/views/cables/index.html.erb @@ -130,7 +130,7 @@ <% if allowed_to?(:destroy?, cable) %> <%= link_to cable_path(cable), method: :delete, - data: { confirm: t("action.confirm"), turbo_frame: :_top }, + data: { turbo_frame: :_top }, class: "btn btn-danger" do %> " aria-hidden="true" data-controller="tooltip" From 3cc6d3cdde844e8623be95a4c51c8f736b7c6f26 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 26 Nov 2025 18:15:31 +0100 Subject: [PATCH 21/33] Tests and cleanups --- .../power_distribution_units/destroy.html.erb | 1 + spec/decorators/document_decorator_spec.rb | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/views/power_distribution_units/destroy.html.erb b/app/views/power_distribution_units/destroy.html.erb index 0fbc52add..3c759209b 100644 --- a/app/views/power_distribution_units/destroy.html.erb +++ b/app/views/power_distribution_units/destroy.html.erb @@ -9,6 +9,7 @@
    <%= render DeleteDependencyComponent.new( @pdu, + except: %i[external_app_record], confirmation_path: power_distribution_unit_path(@pdu, confirm: true) ) %>
    diff --git a/spec/decorators/document_decorator_spec.rb b/spec/decorators/document_decorator_spec.rb index 3d3a8d922..f110a9ddb 100644 --- a/spec/decorators/document_decorator_spec.rb +++ b/spec/decorators/document_decorator_spec.rb @@ -2,16 +2,18 @@ require "rails_helper" -# Example: -# -# describe DocumentDecorator, type: :decorator do -# let(:object) { User.new(first_name: "John", last_name: "Doe") } -# let(:decorated_user) { described_class.new(object) } -# -# describe "#full_name" do -# it { expect(decorated_user.full_name).to eq("John Doe") } -# end -# end RSpec.describe DocumentDecorator, type: :decorator do - pending "add some examples to (or delete) #{__FILE__}" + let(:document) { Document.new } + let(:decorated_document) { document.decorated } + + before do + allow(document).to receive_messages( + document: instance_double(DocumentUploader::UploadedFile, metadata: { "filename" => "file.pdf" }), + document_url: "/fake/url", + ) + end + + describe "#display_name" do + it { expect(decorated_document.display_name).to eq("file.pdf") } + end end From c6ffae78ee68633ea34d7b9d9226fa8be57b4581 Mon Sep 17 00:00:00 2001 From: B_Rass Date: Thu, 27 Nov 2025 16:12:00 +0100 Subject: [PATCH 22/33] Add expand/collapse all buttons --- app/components/delete_dependency_component.rb | 29 +++++++-------- .../controllers/collapse_all_controller.js | 36 +++++++++++++++++++ .../power_distribution_units/show.html.erb | 27 +++++++++++++- app/views/servers/show.html.erb | 30 +++++++++++----- config/locales/components.en.yml | 2 -- config/locales/components.fr.yml | 2 -- config/locales/en.yml | 3 +- config/locales/fr.yml | 3 +- 8 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 app/javascript/controllers/collapse_all_controller.js diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 560677b60..59c19c66d 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -51,23 +51,24 @@ class CollectionGroupComponent < ApplicationComponent
    <%= t(".\#{@type}_dependency_title") %>
    - |
    @@ -104,7 +105,7 @@ class CollectionComponent < ApplicationComponent erb_template <<~ERB <%= render CardComponent.new( type: TYPES[@type], - extra_classes: "bg-body-tertiary mt-2 ms-5" + extra_classes: "bg-body-tertiary mt-2 ms-4" ) do |card| %> <% card.with_header do %>
    elt.show()) + } + + hideAll(_) { + if (this.collapses = []) { + this.fillCollapses() + } + + this.collapses.forEach(elt => elt.hide()) + } + + fillCollapses() { + let elements = document.getElementsByClassName(this.elementsValue) + this.collapses = [...elements].map(elt => new bootstrap.Collapse(elt, { toggle: false })) + } +} diff --git a/app/views/power_distribution_units/show.html.erb b/app/views/power_distribution_units/show.html.erb index c27c04fd4..3d6e7aa80 100644 --- a/app/views/power_distribution_units/show.html.erb +++ b/app/views/power_distribution_units/show.html.erb @@ -379,7 +379,32 @@ url: server_cables_path(@pdu.id), frame_id: dom_id(Connection, :table), extra_classes: "bg-body-tertiary" - ) %> + ) do |c| %> + <% c.with_actions do %> + + + + + <% end %> + <% end %>
    diff --git a/app/views/servers/show.html.erb b/app/views/servers/show.html.erb index 36628ade7..5df3caaf6 100644 --- a/app/views/servers/show.html.erb +++ b/app/views/servers/show.html.erb @@ -429,14 +429,28 @@ extra_classes: "bg-body-tertiary" ) do |c| %> <% c.with_actions do %> - + + + + <% end %> <% end %>
    diff --git a/config/locales/components.en.yml b/config/locales/components.en.yml index 5a9e432cd..b3b64c16b 100644 --- a/config/locales/components.en.yml +++ b/config/locales/components.en.yml @@ -5,8 +5,6 @@ en: delete_dependency_component: restrict_with_error_dependency_title: Related resources blocking deletion destroy_dependency_title: Related resources that will be removed - show_all: Show all - hide_all: Hide all confirm: Are you sure you want to delete this resource? This action cannot be undone export_dropdown_component: diff --git a/config/locales/components.fr.yml b/config/locales/components.fr.yml index 64b0bee68..a4b792188 100644 --- a/config/locales/components.fr.yml +++ b/config/locales/components.fr.yml @@ -5,8 +5,6 @@ fr: delete_dependency_component: restrict_with_error_dependency_title: Ressources liées bloquant la suppression destroy_dependency_title: Ressources liées qui vont être supprimées - show_all: Afficher tout - hide_all: Cacher tout confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible export_dropdown_component: diff --git a/config/locales/en.yml b/config/locales/en.yml index f1f3855fa..b258d33cb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -29,6 +29,8 @@ en: configure: Configure continue: Continue export: Export + show_all: Show all + hide_all: Hide all application: no_permission_scope: @@ -283,7 +285,6 @@ en: glpi_visit_page: See the PDU page on GLPI no_match_serial: "No match for this serial number: %{serial}" glpi_connection_error: "Problem connecting to GLPI :" - toggle_vlans: Toggle Vlans warning_no_frame: The current frame no longer exists, please enter a new one. new: title: Add a PDU diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 3d4062886..044b708f9 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -37,6 +37,8 @@ fr: configure: Configurer continue: Continuer export: Exporter + show_all: Afficher tout + hide_all: Cacher tout export_button: label: Exports @@ -443,7 +445,6 @@ fr: glpi_connection_error: "Problème lors de la connexion à GLPI :" moves_cta_tooltip: Prévoir son déplacement export_cta_tooltip: Export PDF pour les câbleurs - toggle_vlans: Afficher / Cacher les Vlans new: title: Ajouter un matériel I.T. create: From 0a571115afdf083ee5937deb3be59993604bde3f Mon Sep 17 00:00:00 2001 From: B_Rass Date: Thu, 27 Nov 2025 18:58:38 +0100 Subject: [PATCH 23/33] Update locales --- app/views/air_conditioners/destroy.html.erb | 2 +- app/views/architectures/destroy.html.erb | 2 +- app/views/bays/destroy.html.erb | 2 +- app/views/card_types/destroy.html.erb | 2 +- app/views/categories/destroy.html.erb | 2 +- app/views/clusters/destroy.html.erb | 2 +- app/views/colors/destroy.html.erb | 2 +- .../contact_assignments/destroy.html.erb | 2 +- app/views/contact_roles/destroy.html.erb | 2 +- app/views/contacts/destroy.html.erb | 2 +- app/views/domaines/destroy.html.erb | 2 +- app/views/frames/destroy.html.erb | 2 +- app/views/gestions/destroy.html.erb | 2 +- app/views/islets/destroy.html.erb | 2 +- app/views/manufacturers/destroy.html.erb | 2 +- app/views/modeles/destroy.html.erb | 2 +- app/views/port_types/destroy.html.erb | 2 +- .../power_distribution_units/destroy.html.erb | 2 +- app/views/rooms/destroy.html.erb | 2 +- app/views/servers/destroy.html.erb | 2 +- app/views/sites/destroy.html.erb | 2 +- app/views/stacks/destroy.html.erb | 2 +- config/locales/components.en.yml | 2 +- config/locales/components.fr.yml | 2 +- config/locales/en.yml | 80 ++++++++++++++++++- config/locales/fr.yml | 33 ++++++-- 26 files changed, 126 insertions(+), 35 deletions(-) diff --git a/app/views/air_conditioners/destroy.html.erb b/app/views/air_conditioners/destroy.html.erb index b10688ba2..b8c25adc1 100644 --- a/app/views/air_conditioners/destroy.html.erb +++ b/app/views/air_conditioners/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/architectures/destroy.html.erb b/app/views/architectures/destroy.html.erb index 206fab003..ca0d35955 100644 --- a/app/views/architectures/destroy.html.erb +++ b/app/views/architectures/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/bays/destroy.html.erb b/app/views/bays/destroy.html.erb index 93ac75841..ee0684a96 100644 --- a/app/views/bays/destroy.html.erb +++ b/app/views/bays/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/card_types/destroy.html.erb b/app/views/card_types/destroy.html.erb index f8810cb53..4b54db560 100644 --- a/app/views/card_types/destroy.html.erb +++ b/app/views/card_types/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb index 34c8280b2..e16d8f2c9 100644 --- a/app/views/categories/destroy.html.erb +++ b/app/views/categories/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/clusters/destroy.html.erb b/app/views/clusters/destroy.html.erb index 264d52736..b16c0ddff 100644 --- a/app/views/clusters/destroy.html.erb +++ b/app/views/clusters/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/colors/destroy.html.erb b/app/views/colors/destroy.html.erb index 42e681264..c52feeec2 100644 --- a/app/views/colors/destroy.html.erb +++ b/app/views/colors/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/contact_assignments/destroy.html.erb b/app/views/contact_assignments/destroy.html.erb index 694189b37..44ba62d69 100644 --- a/app/views/contact_assignments/destroy.html.erb +++ b/app/views/contact_assignments/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/contact_roles/destroy.html.erb b/app/views/contact_roles/destroy.html.erb index 734565edb..6664b49e1 100644 --- a/app/views/contact_roles/destroy.html.erb +++ b/app/views/contact_roles/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/contacts/destroy.html.erb b/app/views/contacts/destroy.html.erb index 4b0c581bd..22b9e380d 100644 --- a/app/views/contacts/destroy.html.erb +++ b/app/views/contacts/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/domaines/destroy.html.erb b/app/views/domaines/destroy.html.erb index 0e4b178dd..01c43acec 100644 --- a/app/views/domaines/destroy.html.erb +++ b/app/views/domaines/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/frames/destroy.html.erb b/app/views/frames/destroy.html.erb index 4b916e7b7..f8a89208d 100644 --- a/app/views/frames/destroy.html.erb +++ b/app/views/frames/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/gestions/destroy.html.erb b/app/views/gestions/destroy.html.erb index d2f5b8193..369a0dbac 100644 --- a/app/views/gestions/destroy.html.erb +++ b/app/views/gestions/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/islets/destroy.html.erb b/app/views/islets/destroy.html.erb index d7254190d..86e75dbee 100644 --- a/app/views/islets/destroy.html.erb +++ b/app/views/islets/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/manufacturers/destroy.html.erb b/app/views/manufacturers/destroy.html.erb index 42f828863..ea3cffa3f 100644 --- a/app/views/manufacturers/destroy.html.erb +++ b/app/views/manufacturers/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/modeles/destroy.html.erb b/app/views/modeles/destroy.html.erb index e26ecd00c..142dc3a36 100644 --- a/app/views/modeles/destroy.html.erb +++ b/app/views/modeles/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/port_types/destroy.html.erb b/app/views/port_types/destroy.html.erb index 862f7626a..d8c0124f2 100644 --- a/app/views/port_types/destroy.html.erb +++ b/app/views/port_types/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/power_distribution_units/destroy.html.erb b/app/views/power_distribution_units/destroy.html.erb index 3c759209b..a4f8c1c10 100644 --- a/app/views/power_distribution_units/destroy.html.erb +++ b/app/views/power_distribution_units/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/rooms/destroy.html.erb b/app/views/rooms/destroy.html.erb index 6405a8b4b..1b866abe6 100644 --- a/app/views/rooms/destroy.html.erb +++ b/app/views/rooms/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/servers/destroy.html.erb b/app/views/servers/destroy.html.erb index 2f7d680be..dace096f3 100644 --- a/app/views/servers/destroy.html.erb +++ b/app/views/servers/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/sites/destroy.html.erb b/app/views/sites/destroy.html.erb index 779699e65..993a3752f 100644 --- a/app/views/sites/destroy.html.erb +++ b/app/views/sites/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/app/views/stacks/destroy.html.erb b/app/views/stacks/destroy.html.erb index f3d17b07a..8b544d9c1 100644 --- a/app/views/stacks/destroy.html.erb +++ b/app/views/stacks/destroy.html.erb @@ -4,7 +4,7 @@ .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/config/locales/components.en.yml b/config/locales/components.en.yml index b3b64c16b..c59486df1 100644 --- a/config/locales/components.en.yml +++ b/config/locales/components.en.yml @@ -5,7 +5,7 @@ en: delete_dependency_component: restrict_with_error_dependency_title: Related resources blocking deletion destroy_dependency_title: Related resources that will be removed - confirm: Are you sure you want to delete this resource? This action cannot be undone + confirmation_message_html: Are you sure you want to delete %{name}? This action cannot be undone export_dropdown_component: export: diff --git a/config/locales/components.fr.yml b/config/locales/components.fr.yml index a4b792188..2d212bf2b 100644 --- a/config/locales/components.fr.yml +++ b/config/locales/components.fr.yml @@ -5,7 +5,7 @@ fr: delete_dependency_component: restrict_with_error_dependency_title: Ressources liées bloquant la suppression destroy_dependency_title: Ressources liées qui vont être supprimées - confirm: Êtes-vous sûr de vouloir supprimer cette ressource ? Cette action est irréversible + confirmation_message_html: Êtes-vous sûr de vouloir supprimer %{name} ? Cette action est irréversible export_dropdown_component: export: diff --git a/config/locales/en.yml b/config/locales/en.yml index b258d33cb..d461f6205 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -32,11 +32,19 @@ en: show_all: Show all hide_all: Hide all + air_conditioners: + destroy: + title: Delete the air conditionner + application: no_permission_scope: text: Permissions not configured subtext_html: Contact an administrator. + architectures: + destroy: + title: Delete the architecture + bays: index: new_bay: Add a single or double bay @@ -55,6 +63,7 @@ en: flashes: updated: The bay has been updated. destroy: + title: Delete the bay flashes: destroyed: The bay has been removed. decorator: @@ -72,15 +81,42 @@ en: flashes: destroyed: The selected %{resource} have successfully been deleted. not_destroyed: An error occured while deleting at least one %{resource} + cables: index: title: Connections + card_types: + destroy: + title: Delete the card type + + categories: + destroy: + title: Delete the category + cluster: blank: No cluster + clusters: + destroy: + title: Delete the cluster + + colors: + destroy: + title: Delete the color + contact_assignments: add_new: Add an assignment + destroy: + title: Delete the assignment + + contact_roles: + destroy: + title: Delete the role + + contacts: + destroy: + title: Delete the contact devise: passwords: @@ -89,6 +125,10 @@ en: edit: title: Change your password + domaines: + destroy: + title: Delete the domaine + export_button: label: Exports exports: @@ -141,8 +181,19 @@ en: form: submit: Confirm + frames: + add_new: Add a frame + destroy: + title: Delete the frame + + gestions: + destroy: + title: Delete the manager + islets: add_new: Add an islet + destroy: + title: Delete the islet layouts: breadcrumb: @@ -181,10 +232,16 @@ en: contacts: title: Contacts + manufacturers: + destroy: + title: Delete the manufacturer + modeles: add_new: Add a model decorator: no_enclosure: No Enclosure + destroy: + title: Delete the modele moved_connections: decorator: @@ -274,6 +331,10 @@ en: flashes: archived: This project is archived + port_types: + destroy: + title: Delete the port type + power_distribution_units: index: title: Electricity @@ -295,7 +356,7 @@ en: add_card: Add a card add_document: Add an attached document edit: - title: Update PDU + title: Update the PDU delete_confirmation: All data concerning this PDU will be deleted, along with all associated connections. Would you like to confirm? update: flashes: @@ -303,6 +364,7 @@ en: duplicate: title: Duplicate PDU %{pdu_name} destroy: + title: Delete the PDU flashes: destroyed: The PDU has been deleted. not_destroyed: An error occurred while deleting the PDU. @@ -310,9 +372,6 @@ en: connections_destroyed: The connections have been removed. connections_not_destroyed: An error prevented connections from being deleted. - frames: - add_new: Add a frame - rooms: action_buttons: caption: @@ -324,6 +383,8 @@ en: update: flashes: success: The room has successfully been updated + destroy: + title: Delete the room add_new: Add a room empty_overview: No bay to display @@ -346,6 +407,8 @@ en: domaine_ids: blank: Select a domain destroy: + destroy: + title: Delete the permissio scope flashes: destroyed: Permission Scope as been successfully destroyed. permission_scope_user_form: @@ -422,6 +485,7 @@ en: duplicate: title: Duplicate I.T. equipment %{server_name} destroy: + title: Delete the I.T. equipment flashes: destroyed: The I.T. equipment has been removed. not_destroyed: An error occurred when deleting I.T. equipment. @@ -434,6 +498,10 @@ en: index: title: Search for equipment + sites: + destroy: + title: Delete the site + show: cards: display: Display @@ -442,6 +510,10 @@ en: preview: Preview visualization: Representation + stacks: + destroy: + title: Delete the stack + unit: square_meter: m² mm: mm diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 044b708f9..cc2559ce0 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -121,21 +121,21 @@ fr: islets: index: new_islet: Ajouter un ilot - delete_confirmation: Cet ilôt ne pourra pas être supprimé tant qu'il sera associé à au moins une baie. Voulez-vous continuer ? new: - title: Nouvel îlot + title: Nouvel ilot create: flashes: created: L'ilôt a bien été créé. edit: - title: Modification de l'îlot + title: Modification de l'ilot update: flashes: - updated: L'ilôt a bien été modifié. + updated: L'ilot a bien été modifié. destroy: + title: Supprimer l'ilot flashes: destroyed: L'ilôt a bien été supprimé. - add_new: Ajouter un ilôt + add_new: Ajouter un ilot connections: edit: title: Modifier la connexion @@ -166,6 +166,7 @@ fr: form: add_contact_assignment: Assigner un contact destroy: + title: Supprimer le site flashes: destroyed: Site a bien été supprimé. gestions: @@ -183,6 +184,7 @@ fr: flashes: updated: Le gestionnaire a bien été modifié. destroy: + title: Supprimer le gestionnaire flashes: destroyed: Le gestionnaire a bien été supprimé. architectures: @@ -200,6 +202,7 @@ fr: flashes: updated: L'architecture a bien été modifiée. destroy: + title: Supprimer l'architecture flashes: destroyed: L'architecture a bien été supprimée. clusters: @@ -217,6 +220,7 @@ fr: flashes: updated: Le cluster a bien été modifié. destroy: + title: Supprimer le cluster flashes: destroyed: Le cluster a bien été supprimé. stacks: @@ -234,7 +238,7 @@ fr: flashes: updated: La stack a bien été modifiée. destroy: - title: Suppression + title: Supprimer le stack delete-confirm: Voulez-vous vraiment supprimer cette Stack ? dependencies_title: "Materiel dépendants :" flashes: @@ -255,6 +259,7 @@ fr: flashes: updated: Le type de carte a bien été modifié. destroy: + title: Supprimer le type de carte flashes: destroyed: Le type de carte a bien été supprimé. colors: @@ -271,6 +276,7 @@ fr: flashes: updated: La couleur a bien été modifiée. destroy: + title: Supprimer la couleur flashes: destroyed: La couleur a bien été supprimé. show: @@ -293,7 +299,7 @@ fr: flashes: updated: Le constructeur a bien été modifié. destroy: - title: Suppression + title: Supprimer le constructeur delete-confirm: Voulez-vous vraiment supprimer ce Constructeur ? flashes: destroyed: Le constructeur a bien été supprimé. @@ -312,6 +318,7 @@ fr: flashes: updated: Le domaine a bien été modifié. destroy: + title: Supprimer le domaine flashes: destroyed: Le domaine a bien été supprimé. ports: @@ -338,6 +345,7 @@ fr: flashes: updated: Le type de port a bien été modifié. destroy: + title: Supprimer le type de port flashes: destroyed: Le type de port a bien été supprimé. categories: @@ -357,6 +365,7 @@ fr: flashes: updated: La catégorie a bien été modifiée. destroy: + title: Supprimer la catégorie flashes: destroyed: La catégorie a bien été supprimée. modeles: @@ -381,6 +390,7 @@ fr: flashes: updated: Le modèle a été mis à jour. destroy: + title: Supprimer le modèle flashes: destroyed: Le modèle a bien été supprimé. duplicate: @@ -459,6 +469,7 @@ fr: duplicate: title: Dupliquer le matériel I.T. %{server_name} destroy: + title: Supprimer le matériel I.T. flashes: destroyed: Le matériel I.T. a bien été supprimé. not_destroyed: Une erreur est survenue lors de la suppression du matériel I.T. @@ -512,6 +523,7 @@ fr: duplicate: title: Dupliquer le PDU %{pdu_name} destroy: + title: Supprimer le PDU flashes: destroyed: Le PDU a bien été supprimé. not_destroyed: Une erreur est survenue lors de la suppression du PDU. @@ -540,6 +552,7 @@ fr: flashes: created: Le châssis a été ajouté. destroy: + title: Supprimer le châssis flashes: destroyed: Frame a bien été supprimé. network: @@ -689,6 +702,7 @@ fr: flashes: updated: La salle a été mise à jour. destroy: + title: Supprimer la salle flashes: destroyed: La salle a bien été supprimée. add_new: Ajouter une salle @@ -757,6 +771,7 @@ fr: flashes: updated: La climatisation a bien été modifiée. destroy: + title: Supprimer la climatisation flashes: destroyed: La climatisation a bien été supprimée. form: @@ -799,6 +814,7 @@ fr: flashes: updated: La baie a bien été mise à jour. destroy: + title: Supprimer la baie flashes: destroyed: La baie a bien été supprimée. decorator: @@ -828,6 +844,7 @@ fr: flashes: updated: Le contact a bien été mis à jour. destroy: + title: Supprimer le contact flashes: destroyed: Le contact a bien été supprimé. contact_roles: @@ -846,6 +863,7 @@ fr: flashes: updated: Le rôle a bien été mis à jour. destroy: + title: Supprimer le rôle flashes: destroyed: Le rôle a bien été supprimé. contact_assignments: @@ -864,6 +882,7 @@ fr: flashes: updated: L'assignation a bien été mise à jour. destroy: + title: Supprimer l'assignation flashes: destroyed: L'assignation a bien été supprimée. add_new: Ajouter une assignation From c4fcceb411bd6df180c6cd8f79c710fc2096e585 Mon Sep 17 00:00:00 2001 From: B_Rass Date: Wed, 3 Dec 2025 15:22:01 +0100 Subject: [PATCH 24/33] Update skin and tests --- app/components/delete_dependency_component.rb | 54 +++++++++++++------ .../moves_projects/_step_fields.html.erb | 1 - config/locales/components.en.yml | 3 +- config/locales/components.fr.yml | 5 +- .../delete_dependency_component_spec.rb | 46 ++++++++++++---- 5 files changed, 81 insertions(+), 28 deletions(-) diff --git a/app/components/delete_dependency_component.rb b/app/components/delete_dependency_component.rb index 59c19c66d..be7f0d8e2 100644 --- a/app/components/delete_dependency_component.rb +++ b/app/components/delete_dependency_component.rb @@ -3,23 +3,38 @@ class DeleteDependencyComponent < ApplicationComponent erb_template <<~ERB
    + <% if @record_dependencies.dependencies_per_type.empty? %> + <%= render CardEmptyDataComponent.new(icon: :check2_circle, text: t(".empty_state_text")) %> + <% end %> + <%= render CollectionGroupComponent.with_collection( grouped_by_dependent, spacer_component: CollectionGroupSpacerComponent.new, ) %> -
    - - <%= render ButtonComponent.new( - t("action.cancel"), url: :back, variant: :outline_secondary, extra_classes: "me-2" - ) %> - - <%= render ButtonComponent.new( - t("action.delete"), - url: @confirmation_path, - method: :delete, - variant: :danger, - extra_classes: class_names(disabled: @record_dependencies.restricted_with_error.any?)) %> - +
    +
    + <% unless @record_dependencies.restricted_with_error.any? %> + + + + <%= t(".confirmation_message_html", name: record.display_name) %> + + + <% end %> + + + <%= render ButtonComponent.new( + t("action.cancel"), url: :back, variant: :outline_secondary, extra_classes: "me-2" + ) %> + + <%= render ButtonComponent.new( + t("action.delete"), + url: @confirmation_path, + method: :delete, + variant: :danger, + extra_classes: class_names(disabled: @record_dependencies.restricted_with_error.any?)) %> + +
    ERB @@ -27,6 +42,7 @@ class DeleteDependencyComponent < ApplicationComponent def initialize(record, confirmation_path:, only: nil, except: nil) @confirmation_path = confirmation_path @record_dependencies = RecordDependencies.new(record, only:, except:) + @record = record super end @@ -40,6 +56,12 @@ def grouped_by_dependent }.select { |_, dependencies| dependencies.any? }.to_a end + def record + helpers.decorate(@record) + rescue Dekorator::DecoratorNotFound + helpers.decorate(@record, with: ApplicationDecorator) + end + class CollectionGroupComponent < ApplicationComponent TYPES = { restrict_with_error: :danger, @@ -57,6 +79,7 @@ class CollectionGroupComponent < ApplicationComponent data-collapse-all-elements-value="collapse_<%= @type %>" data-action="collapse-all#showAll" data-bs-placement="bottom" + data-bs-trigger="hover" aria-hidden="true"> @@ -67,6 +90,7 @@ class CollectionGroupComponent < ApplicationComponent data-collapse-all-elements-value="collapse_<%= @type %>" data-action="collapse-all#hideAll" data-bs-placement="bottom" + data-bs-trigger="hover" aria-hidden="true"> @@ -90,7 +114,7 @@ def render? class CollectionGroupSpacerComponent < ApplicationComponent erb_template <<~ERB -
    +
    ERB end @@ -116,7 +140,7 @@ class CollectionComponent < ApplicationComponent <%= @dependency.title %> (<%= records.length %>) - +
    <% end %> diff --git a/app/views/moves_projects/_step_fields.html.erb b/app/views/moves_projects/_step_fields.html.erb index 25d329ccf..c31b8f2b4 100644 --- a/app/views/moves_projects/_step_fields.html.erb +++ b/app/views/moves_projects/_step_fields.html.erb @@ -27,7 +27,6 @@ data-action="nested-form#remove" class="btn btn-outline-danger btn-sm float-end" title="<%= t("action.delete") %>" - aria-hidden="true" data-controller="tooltip" data-bs-placement="left"> diff --git a/config/locales/components.en.yml b/config/locales/components.en.yml index c59486df1..5c447714f 100644 --- a/config/locales/components.en.yml +++ b/config/locales/components.en.yml @@ -5,7 +5,8 @@ en: delete_dependency_component: restrict_with_error_dependency_title: Related resources blocking deletion destroy_dependency_title: Related resources that will be removed - confirmation_message_html: Are you sure you want to delete %{name}? This action cannot be undone + confirmation_message_html: Are you sure you want to delete the record %{name}? This action cannot be undone + empty_state_text: No related items export_dropdown_component: export: diff --git a/config/locales/components.fr.yml b/config/locales/components.fr.yml index 2d212bf2b..9f8d964a6 100644 --- a/config/locales/components.fr.yml +++ b/config/locales/components.fr.yml @@ -4,8 +4,9 @@ fr: delete_dependency_component: restrict_with_error_dependency_title: Ressources liées bloquant la suppression - destroy_dependency_title: Ressources liées qui vont être supprimées - confirmation_message_html: Êtes-vous sûr de vouloir supprimer %{name} ? Cette action est irréversible + destroy_dependency_title: Ressources liées qui seront supprimées + confirmation_message_html: Êtes-vous sûr de vouloir supprimer la ressource %{name} ? Cette action est irréversible + empty_state_text: Aucun élément lié export_dropdown_component: export: diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index 1528fd64b..107ca13a8 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -24,10 +24,20 @@ ) end - it { expect(rendered_component).to have_tag("h5", title: Document.model_name.human) } - it { expect(rendered_component).to have_tag("li.list-group-item", title: "this is a filename") } - it { expect(rendered_component).not_to have_tag("a.btn-danger") } - it { expect(rendered_component).not_to have_tag("a.btn-default") } + it do + expect(rendered_component).to have_tag("h5.text-danger-emphasis", + ext: "Ressources liées bloquant la suppression") + end + + it { expect(rendered_component).to have_tag("button", with: { "data-action": "collapse-all#showAll" }) } + it { expect(rendered_component).to have_tag("div.card-header.text-bg-danger") } + it { expect(rendered_component).not_to have_tag("div.card-header.text-bg-warning") } + it { expect(rendered_component).to have_tag("div#collapseCard-documents.collapse_restrict_with_error") } + it { expect(rendered_component).to have_tag("li.list-group-item", count: 1) } + it { expect(rendered_component).to have_tag("a.btn-danger.disabled", text: "Supprimer") } + it { expect(rendered_component).to have_tag("a.btn-default", text: "Annuler") } + it { expect(rendered_component).not_to have_tag("div.card.text-secondary-emphasis") } + it { expect(rendered_component).not_to have_tag("span.bi-exclamation-circle.text-danger") } end context "without restricting dependency" do @@ -38,10 +48,18 @@ allow(record).to receive(:contact_assignments).and_return([ContactAssignment.new]) end + it do + expect(rendered_component).not_to have_tag("h5.text-warning-emphasis", text: ContactAssignment.model_name.human) + end + + it { expect(rendered_component).to have_tag("div#collapseCard-contact_assignments") } it { expect(rendered_component).to have_tag("a.btn-danger", href: confirmation_path) } - it { expect(rendered_component).to have_tag("a.btn-default") } - it { expect(rendered_component).to have_tag("h5", title: ContactAssignment.model_name.human) } - it { expect(rendered_component).to have_tag("li.list-group-item", title: ContactAssignment.new.to_s) } + it { expect(rendered_component).not_to have_tag("a.btn-danger.disabled") } + it { expect(rendered_component).to have_tag("li.list-group-item", text: /#{ContactAssignment.new}/i) } + it { expect(rendered_component).not_to have_tag("div.card-header.text-bg-danger") } + it { expect(rendered_component).to have_tag("div.card-header.text-bg-warning") } + it { expect(rendered_component).not_to have_tag("div.card.text-secondary-emphasis") } + it { expect(rendered_component).to have_tag("span.bi-exclamation-circle.text-danger") } end describe "without destroy dependency" do @@ -51,10 +69,20 @@ allow(record).to receive(:contact_assignments).and_return([]) end + it do + expect(rendered_component).to have_tag("div.card.text-secondary-emphasis") do + with_tag("div.card-body > span.bi-check2-circle") + end + end + it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } - it { expect(rendered_component).to have_tag("a.btn-default") } - it { expect(rendered_component).not_to have_tag("h5", title: ContactAssignment.model_name.human) } + it { expect(rendered_component).not_to have_tag("a.btn-danger.disabled") } + it { expect(rendered_component).not_to have_tag("h5.text-danger-emphasis") } + it { expect(rendered_component).not_to have_tag("h5.text-warning-emphasis") } it { expect(rendered_component).not_to have_tag("li.list-group-item") } + it { expect(rendered_component).not_to have_tag("div.card-header.text-bg-danger") } + it { expect(rendered_component).not_to have_tag("div.card-header.text-bg-warning") } + it { expect(rendered_component).to have_tag("span.bi-exclamation-circle.text-danger") } end end end From 0858ce5a3621d7a97c2174d7daa0927c463be47d Mon Sep 17 00:00:00 2001 From: B_Rass Date: Wed, 3 Dec 2025 15:52:29 +0100 Subject: [PATCH 25/33] fix minitests --- test/controllers/air_conditioners_controller_test.rb | 2 +- test/controllers/architectures_controller_test.rb | 4 ++-- test/controllers/categories_controller_test.rb | 4 ++-- test/controllers/clusters_controller_test.rb | 4 ++-- test/controllers/domaines_controller_test.rb | 4 ++-- test/controllers/gestions_controller_test.rb | 4 ++-- test/controllers/manufacturers_controller_test.rb | 4 ++-- test/controllers/rooms_controller_test.rb | 4 ++-- test/controllers/sites_controller_test.rb | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/controllers/air_conditioners_controller_test.rb b/test/controllers/air_conditioners_controller_test.rb index 8d16b5a9c..fff1d6725 100644 --- a/test/controllers/air_conditioners_controller_test.rb +++ b/test/controllers/air_conditioners_controller_test.rb @@ -53,7 +53,7 @@ class AirConditionersControllerTest < ActionDispatch::IntegrationTest test "should destroy air_conditioner" do assert_difference("AirConditioner.count", -1) do - delete air_conditioner_url(@air_conditioner) + delete air_conditioner_url(@air_conditioner, confirm: true) end assert_redirected_to air_conditioners_url diff --git a/test/controllers/architectures_controller_test.rb b/test/controllers/architectures_controller_test.rb index 0a685ac46..c1ff2c533 100644 --- a/test/controllers/architectures_controller_test.rb +++ b/test/controllers/architectures_controller_test.rb @@ -46,7 +46,7 @@ class ArchitecturesControllerTest < ActionController::TestCase @architecture = Architecture.create assert_difference("Architecture.count", -1) do - delete :destroy, params: { id: @architecture } + delete :destroy, params: { id: @architecture, confirm: true } end assert_redirected_to architectures_path @@ -54,7 +54,7 @@ class ArchitecturesControllerTest < ActionController::TestCase test "should not destroy architecture that have modeles" do assert_difference("Architecture.count", 0) do - delete :destroy, params: { id: @architecture } + delete :destroy, params: { id: @architecture, confirm: true } end assert_redirected_to architectures_path diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb index ab57f500f..7d68060ac 100644 --- a/test/controllers/categories_controller_test.rb +++ b/test/controllers/categories_controller_test.rb @@ -46,13 +46,13 @@ class CategoriesControllerTest < ActionController::TestCase @category = Category.create assert_difference("Category.count", -1) do - delete :destroy, params: { id: @category } + delete :destroy, params: { id: @category, confirm: true } end end test "should not destroy category it has many categories: Categorie n°1 & 2 & 3" do assert_difference("Category.count", 0) do - delete :destroy, params: { id: @category } + delete :destroy, params: { id: @category, confirm: true } end assert_redirected_to categories_path diff --git a/test/controllers/clusters_controller_test.rb b/test/controllers/clusters_controller_test.rb index b3ee2bf25..a13d3ef0e 100644 --- a/test/controllers/clusters_controller_test.rb +++ b/test/controllers/clusters_controller_test.rb @@ -46,7 +46,7 @@ class ClustersControllerTest < ActionController::TestCase @cluster = Cluster.create assert_difference("Cluster.count", -1) do - delete :destroy, params: { id: @cluster } + delete :destroy, params: { id: @cluster, confirm: true } end assert_redirected_to clusters_path @@ -54,7 +54,7 @@ class ClustersControllerTest < ActionController::TestCase test "should not destroy cluster that have servers" do assert_difference("Cluster.count", 0) do - delete :destroy, params: { id: @cluster } + delete :destroy, params: { id: @cluster, confirm: true } end assert_redirected_to clusters_path diff --git a/test/controllers/domaines_controller_test.rb b/test/controllers/domaines_controller_test.rb index 61b2064d9..3bfb7e786 100644 --- a/test/controllers/domaines_controller_test.rb +++ b/test/controllers/domaines_controller_test.rb @@ -46,7 +46,7 @@ class DomainesControllerTest < ActionController::TestCase @domaine = Domaine.create assert_difference("Domaine.count", -1) do - delete :destroy, params: { id: @domaine } + delete :destroy, params: { id: @domaine, confirm: true } end assert_redirected_to domaines_path @@ -54,7 +54,7 @@ class DomainesControllerTest < ActionController::TestCase test "should not destroy domaine that have modeles" do assert_difference("Domaine.count", 0) do - delete :destroy, params: { id: @domaine } + delete :destroy, params: { id: @domaine, confirm: true } end assert_redirected_to domaines_path diff --git a/test/controllers/gestions_controller_test.rb b/test/controllers/gestions_controller_test.rb index 1a4b0c81a..0eebace9d 100644 --- a/test/controllers/gestions_controller_test.rb +++ b/test/controllers/gestions_controller_test.rb @@ -46,13 +46,13 @@ class GestionsControllerTest < ActionController::TestCase @gestion = Gestion.create assert_difference("Gestion.count", -1) do - delete :destroy, params: { id: @gestion } + delete :destroy, params: { id: @gestion, confirm: true } end end test "should not destroy gestion it has many servers Server n°1 & 2" do assert_difference("Gestion.count", 0) do - delete :destroy, params: { id: @gestion } + delete :destroy, params: { id: @gestion, confirm: true } end assert_redirected_to gestions_path diff --git a/test/controllers/manufacturers_controller_test.rb b/test/controllers/manufacturers_controller_test.rb index 7492fe44d..58ae3b5df 100644 --- a/test/controllers/manufacturers_controller_test.rb +++ b/test/controllers/manufacturers_controller_test.rb @@ -46,7 +46,7 @@ class ManufacturersControllerTest < ActionController::TestCase @manufacturer = Manufacturer.create assert_difference("Manufacturer.count", -1) do - delete :destroy, params: { id: @manufacturer } + delete :destroy, params: { id: @manufacturer, confirm: true } end assert_redirected_to manufacturers_path @@ -54,7 +54,7 @@ class ManufacturersControllerTest < ActionController::TestCase test "should not destroy manufacturer that have modeles" do assert_difference("Manufacturer.count", 0) do - delete :destroy, params: { id: @manufacturer } + delete :destroy, params: { id: @manufacturer, confirm: true } end assert_redirected_to manufacturers_path diff --git a/test/controllers/rooms_controller_test.rb b/test/controllers/rooms_controller_test.rb index f88bd094c..384d1228f 100644 --- a/test/controllers/rooms_controller_test.rb +++ b/test/controllers/rooms_controller_test.rb @@ -33,7 +33,7 @@ class RoomsControllerTest < ActionController::TestCase @room = rooms(:two) assert_difference("Room.count", -1) do - delete :destroy, params: { id: @room } + delete :destroy, params: { id: @room, confirm: true } end assert_redirected_to rooms_path @@ -41,7 +41,7 @@ class RoomsControllerTest < ActionController::TestCase test "should not destroy room that have islets" do assert_difference("Room.count", 0) do - delete :destroy, params: { id: @room } + delete :destroy, params: { id: @room, confirm: true } end assert_redirected_to rooms_path diff --git a/test/controllers/sites_controller_test.rb b/test/controllers/sites_controller_test.rb index b9b9ca30b..fb3986eed 100644 --- a/test/controllers/sites_controller_test.rb +++ b/test/controllers/sites_controller_test.rb @@ -41,13 +41,13 @@ class SitesControllerTest < ActionController::TestCase @site = Site.create assert_difference("Site.count", -1) do - delete :destroy, params: { id: @site } + delete :destroy, params: { id: @site, confirm: true } end end test "should not destroy the site it has many rooms Room n°1 & 2" do assert_difference("Site.count", 0) do - delete :destroy, params: { id: @site } + delete :destroy, params: { id: @site, confirm: true } end assert_redirected_to sites_path From 9c55a9375cc775a9e376296bd2b3a3cffcb11961 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 10 Dec 2025 16:58:53 +0100 Subject: [PATCH 26/33] test: cleanup --- app/models/record_dependencies.rb | 5 +- .../delete_dependency_component_spec.rb | 14 ++-- spec/models/record_dependencies_spec.rb | 68 +++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/app/models/record_dependencies.rb b/app/models/record_dependencies.rb index 6fe0f37c0..8a4000e3f 100644 --- a/app/models/record_dependencies.rb +++ b/app/models/record_dependencies.rb @@ -2,7 +2,9 @@ class RecordDependencies ALLOWED_DEPEDENT_OPTIONS = %i[restrict_with_error destroy].freeze - EXCLUDED_KLASSES = [ActiveStorage::Blob, ActiveStorage::Attachment].freeze + EXCLUDED_KLASSES = [ + ActiveStorage::Blob, ActiveStorage::Attachment, ChangelogEntry, FriendlyId::Slug, + ].freeze Dependency = Data.define(:association, :origin) do delegate :name, to: :association @@ -64,7 +66,6 @@ def association_valid?(association) # default behavior return false if association.options.key?(:through) return false unless ALLOWED_DEPEDENT_OPTIONS.include?(association.options[:dependent]) - return false if %i[changelog_entries slugs].include?(association.name) return false if EXCLUDED_KLASSES.include?(association.klass) # exept is not above default config diff --git a/spec/components/delete_dependency_component_spec.rb b/spec/components/delete_dependency_component_spec.rb index 107ca13a8..7f4acb402 100644 --- a/spec/components/delete_dependency_component_spec.rb +++ b/spec/components/delete_dependency_component_spec.rb @@ -8,7 +8,7 @@ let(:rendered_component) { render_inline(component).to_html } context "with restricting dependency" do - let(:record) { Server.new(name: "Dummy name") } + let(:record) { Server.new(name: "Dummy name") } let(:document) { Document.new } before do @@ -17,16 +17,12 @@ document_url: "/fake/url", ) - allow(record).to receive_messages( - external_app_record: [], - documents: [document], - moves: [], - ) + allow(record).to receive_messages(documents: [document]) end it do expect(rendered_component).to have_tag("h5.text-danger-emphasis", - ext: "Ressources liées bloquant la suppression") + text: "Ressources liées bloquant la suppression") end it { expect(rendered_component).to have_tag("button", with: { "data-action": "collapse-all#showAll" }) } @@ -53,7 +49,7 @@ end it { expect(rendered_component).to have_tag("div#collapseCard-contact_assignments") } - it { expect(rendered_component).to have_tag("a.btn-danger", href: confirmation_path) } + it { expect(rendered_component).to have_tag("a.btn-danger", with: { href: confirmation_path }) } it { expect(rendered_component).not_to have_tag("a.btn-danger.disabled") } it { expect(rendered_component).to have_tag("li.list-group-item", text: /#{ContactAssignment.new}/i) } it { expect(rendered_component).not_to have_tag("div.card-header.text-bg-danger") } @@ -75,7 +71,7 @@ end end - it { expect(rendered_component).to have_tag("a.btn-danger", href: "confirmation-path") } + it { expect(rendered_component).to have_tag("a.btn-danger", with: { href: "/confirmation-path" }) } it { expect(rendered_component).not_to have_tag("a.btn-danger.disabled") } it { expect(rendered_component).not_to have_tag("h5.text-danger-emphasis") } it { expect(rendered_component).not_to have_tag("h5.text-warning-emphasis") } diff --git a/spec/models/record_dependencies_spec.rb b/spec/models/record_dependencies_spec.rb index 4e13430b8..918aba4c2 100644 --- a/spec/models/record_dependencies_spec.rb +++ b/spec/models/record_dependencies_spec.rb @@ -67,4 +67,72 @@ end end end + + describe "#association_valid?" do + subject(:record_dependencies) { described_class.new(record, only:, except:) } + + let(:only) { nil } + let(:except) { nil } + + context "with only and except nil" do + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(true) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:changelog_entries))) + .to be(false) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cables))).to be(false) + end + end + + context "with only cards and changelog_entries" do + let(:only) { %i[cards changelog_entries] } + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(false) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:changelog_entries))) + .to be(true) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cables))).to be(false) + end + end + + context "with except cards" do + let(:except) { :cards } + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(false) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(true) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:changelog_entries))) + .to be(false) + end + + it do + expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cables))).to be(false) + end + end + end end From 420a018a1072c5d72a328aa39ef6da1ecf14dd94 Mon Sep 17 00:00:00 2001 From: B_Rass Date: Wed, 10 Dec 2025 17:37:42 +0100 Subject: [PATCH 27/33] Improve color.to_s --- app/models/color.rb | 4 ++++ app/views/colors/show.html.erb | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/color.rb b/app/models/color.rb index c0ed9d449..84be015ae 100644 --- a/app/models/color.rb +++ b/app/models/color.rb @@ -2,4 +2,8 @@ class Color < ApplicationRecord has_changelog + + def to_s + code + end end diff --git a/app/views/colors/show.html.erb b/app/views/colors/show.html.erb index a587a5e08..0556f1c40 100644 --- a/app/views/colors/show.html.erb +++ b/app/views/colors/show.html.erb @@ -1,4 +1,4 @@ -<% breadcrumb.add_step(title = @color.code) %> +<% breadcrumb.add_step(title = @color) %> <%= render Page::HeadingShowComponent.new( resource: @color, @@ -21,7 +21,7 @@
    <%= @color.public_send(attribute_name) %>
    <% end %> - + <% end %>
    From 29d014d07c42449fe38ef73fe96ae90b60d86de9 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 10 Dec 2025 18:10:56 +0100 Subject: [PATCH 28/33] Re-add confirmation to cables --- app/controllers/cables_controller.rb | 1 + app/decorators/cable_decorator.rb | 1 + app/decorators/connection_decorator.rb | 7 +++++++ app/views/cables/destroy.html.erb | 4 ++-- config/locales/en.yml | 2 ++ config/locales/fr.yml | 1 + spec/decorators/connection_decorator_spec.rb | 17 +++++++++++++++++ 7 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 app/decorators/connection_decorator.rb create mode 100644 spec/decorators/connection_decorator_spec.rb diff --git a/app/controllers/cables_controller.rb b/app/controllers/cables_controller.rb index 604477643..367a0bad9 100644 --- a/app/controllers/cables_controller.rb +++ b/app/controllers/cables_controller.rb @@ -19,6 +19,7 @@ def index end end + destroy_confirmation def destroy @cable.ports.each do |port| if @from_server.nil? diff --git a/app/decorators/cable_decorator.rb b/app/decorators/cable_decorator.rb index f1bb0faa1..c356f58f8 100644 --- a/app/decorators/cable_decorator.rb +++ b/app/decorators/cable_decorator.rb @@ -79,4 +79,5 @@ def description cablename: port_from.cable_name, color: port_from.color) end + alias to_s description end diff --git a/app/decorators/connection_decorator.rb b/app/decorators/connection_decorator.rb new file mode 100644 index 000000000..3c0b99dab --- /dev/null +++ b/app/decorators/connection_decorator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ConnectionDecorator < ApplicationDecorator + def display_name + "#{server} - #{card}" + end +end diff --git a/app/views/cables/destroy.html.erb b/app/views/cables/destroy.html.erb index d7eb16661..2ebe667f0 100644 --- a/app/views/cables/destroy.html.erb +++ b/app/views/cables/destroy.html.erb @@ -1,10 +1,10 @@ <% breadcrumb - .add_step(@cable, cable_path(@cable)) + .add_step(@cable.decorated, cable_path(@cable)) .add_step(t("action.delete")) %> -<%= render Page::HeadingComponent.new(title: t("action.delete"), breadcrumb:) %> +<%= render Page::HeadingComponent.new(title: t(".title"), breadcrumb:) %>
    <%= render DeleteDependencyComponent.new( diff --git a/config/locales/en.yml b/config/locales/en.yml index d461f6205..60bd4b7d2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -85,6 +85,8 @@ en: cables: index: title: Connections + destroy: + title: Delete the connection card_types: destroy: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index cc2559ce0..984320857 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -826,6 +826,7 @@ fr: title: Connexions instructions_to_show_hide_vlans: Cliquer pour afficher / cacher les Vlans destroy: + title: Supprimer la connexion flashes: destroyed: La connexion a bien été supprimée. contacts: diff --git a/spec/decorators/connection_decorator_spec.rb b/spec/decorators/connection_decorator_spec.rb new file mode 100644 index 000000000..8639d93fd --- /dev/null +++ b/spec/decorators/connection_decorator_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "rails_helper" + +# Example: +# +# describe ConnectionDecorator, type: :decorator do +# let(:object) { User.new(first_name: "John", last_name: "Doe") } +# let(:decorated_user) { described_class.new(object) } +# +# describe "#full_name" do +# it { expect(decorated_user.full_name).to eq("John Doe") } +# end +# end +RSpec.describe ConnectionDecorator, type: :decorator do + pending "add some examples to (or delete) #{__FILE__}" +end From a64a6b8d7c2e651fff265eedd5ff87cf4842c24f Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 17 Dec 2025 18:49:22 +0100 Subject: [PATCH 29/33] style: code cleanup + tests --- config/locales/en.yml | 1 - config/locales/fr.yml | 25 ----------------- spec/decorators/connection_decorator_spec.rb | 17 ++++------- spec/models/record_dependencies_spec.rb | 18 ++++++------ .../cables_controller_request_spec.rb | 28 +++++++++++++++++-- .../servers_controller_request_spec.rb | 2 +- 6 files changed, 41 insertions(+), 50 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 60bd4b7d2..e0ef3d809 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -49,7 +49,6 @@ en: index: new_bay: Add a single or double bay title: Bays and double bays - delete_confirmation: This bay cannot be deleted as long as it is associated with at least one frame. Would you like to continue? new: title: New bay create: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 984320857..b204e1e95 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -152,7 +152,6 @@ fr: index: title: Sites new_site: Ajouter un site - delete_confirmation: Ce site ne pourra pas être supprimé tant qu'il sera associé à au moins une salle. Voulez-vous continuer ? new: title: Nouveau site create: @@ -172,7 +171,6 @@ fr: gestions: index: new_gestion: Ajouter un gestionnaire - delete_confirmation: Ce gestionnaire ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur. Voulez-vous continuer ? new: title: Nouveau gestionnaire create: @@ -190,7 +188,6 @@ fr: architectures: index: new_architecture: Ajouter une architecture - delete_confirmation: Cette architecture ne pourra pas être supprimée tant qu'elle est associée à au moins un modèle. Voulez-vous continuer ? new: title: Nouvelle architecture create: @@ -208,7 +205,6 @@ fr: clusters: index: new_cluster: Nouveau cluster - delete_confirmation: Ce cluster ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur. Voulez-vous continuer ? new: title: Nouveau cluster create: @@ -226,7 +222,6 @@ fr: stacks: index: new_stack: Ajouter un stack - delete_confirmation: Ce stack ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur. Voulez-vous continuer ? new: title: Nouvelle stack create: @@ -239,14 +234,11 @@ fr: updated: La stack a bien été modifiée. destroy: title: Supprimer le stack - delete-confirm: Voulez-vous vraiment supprimer cette Stack ? - dependencies_title: "Materiel dépendants :" flashes: destroyed: La stack a bien été supprimé. card_types: index: new_card_type: Ajouter un type de carte - delete_confirmation: Ce type de carte ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur (via une carte). Voulez-vous continuer ? new: title: Nouveau type de carte create: @@ -263,8 +255,6 @@ fr: flashes: destroyed: Le type de carte a bien été supprimé. colors: - index: - delete_confirmation: Supprimer cette couleur la supprimera des données où elle est utilisée. Voulez-vous continuer ? new: title: Nouvelle couleur create: @@ -287,7 +277,6 @@ fr: information_html: il faut remplacer le numéro de série dans l'URL par %s. index: new_manufacturer: Ajouter un constructeur - delete_confirmation: Ce constructeur ne pourra pas être supprimé tant qu'il sera associé à au moins un modèle. Voulez-vous continuer ? new: title: Nouveau constructeur create: @@ -300,13 +289,11 @@ fr: updated: Le constructeur a bien été modifié. destroy: title: Supprimer le constructeur - delete-confirm: Voulez-vous vraiment supprimer ce Constructeur ? flashes: destroyed: Le constructeur a bien été supprimé. domaines: index: new_domaine: Ajouter un domaine - delete_confirmation: Ce domaine ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur. Voulez-vous continuer ? new: title: Nouveau domaine create: @@ -333,7 +320,6 @@ fr: port_types: index: new_port_type: Ajouter un type de port - delete_confirmation: Ce type de port ne pourra pas être supprimé tant qu'il sera associé à au moins un type de carte. Voulez-vous continuer ? create: flashes: created: Le type de port a bien été créé. @@ -352,7 +338,6 @@ fr: index: new_category: Ajouter une catégorie title: Catégories - delete_confirmation: Cette catégorie ne pourra pas être supprimé tant qu'il aura au moins un modèle associé. Voulez-vous continuer ? usage: Usage new: title: Nouvelle catégorie @@ -378,7 +363,6 @@ fr: add_slot: Ajouter un slot index: new_modele: Ajouter un modèle - delete_confirmation: Ce modèle ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur ou une enclosure. Voulez-vous continuer ?' new: title: Nouveau modèle create: @@ -462,7 +446,6 @@ fr: created: Le matériel I.T. a été créé avec succès. edit: title: Modifier le matériel I.T. - delete_confirmation: Toutes les données concernant ce matériel I.T. seront supprimées, ainsi que toutes les connexions associées. Souhaitez-vous confirmer ? update: flashes: updated: Le matériel I.T. a été mis à jour avec succès. @@ -516,7 +499,6 @@ fr: add_document: Ajouter une pièce jointe edit: title: Modifier le PDU - delete_confirmation: Toutes les données concernant ce PDU seront supprimées, ainsi que toutes les connexions associées. Souhaitez-vous confirmer ? update: flashes: updated: Le PDU a été mis à jour avec succès. @@ -538,7 +520,6 @@ fr: index: new_frame: Ajouter un châssis title: Tous les châssis - delete_confirmation: Ce châssis ne pourra pas être supprimé tant qu'il sera associé à au moins un serveur. Voulez-vous continuer ? show: title: Châssis %{frame} edit: @@ -689,7 +670,6 @@ fr: edit_clusters_modal: edit_clusters: Modifier les clusters index: - delete_confirmation: Cette salle ne pourra pas être supprimée tant qu'elle sera associée à au moins un ilôt. Voulez-vous continuer ? new_room: Ajouter une salle new: title: Nouvelle salle @@ -759,7 +739,6 @@ fr: index: new_air_conditioner: Ajouter une climatisation title: Climatisation - delete_confirmation: Cette climatisation sera supprimée. Voulez-vous continuer ? create: flashes: created: La climatisation a bien été ajoutée. @@ -800,7 +779,6 @@ fr: index: new_bay: Ajouter une baie ou un couple de baies title: Baies et doubles-baies - delete_confirmation: Cette baie ne pourra pas être supprimée tant qu'elle est associée à au moins un chassis. Voulez-vous continuer ? new: title: Nouvelle baie create: @@ -833,7 +811,6 @@ fr: index: new_contact: Ajouter un contact title: Contacts - delete_confirmation: La suppression de ce contact entrainera la suppression de ses assignations. Voulez-vous continuer ? new: title: Nouveau contact create: @@ -852,7 +829,6 @@ fr: index: new_contact_role: Ajouter un rôle title: Rôles de Contacts - delete_confirmation: Ce rôle ne pourra pas être supprimé tant qu'il est associé à au moins un Site. Voulez-vous continuer ? new: title: Nouveau rôle create: @@ -871,7 +847,6 @@ fr: index: new_contact_assignment: Ajouter une assignation title: Assignations de Contacts - delete_confirmation: Êtes vous sûr de vouloir supprimer cette assignation ? new: title: Nouvelle assignation create: diff --git a/spec/decorators/connection_decorator_spec.rb b/spec/decorators/connection_decorator_spec.rb index 8639d93fd..578321d4a 100644 --- a/spec/decorators/connection_decorator_spec.rb +++ b/spec/decorators/connection_decorator_spec.rb @@ -2,16 +2,11 @@ require "rails_helper" -# Example: -# -# describe ConnectionDecorator, type: :decorator do -# let(:object) { User.new(first_name: "John", last_name: "Doe") } -# let(:decorated_user) { described_class.new(object) } -# -# describe "#full_name" do -# it { expect(decorated_user.full_name).to eq("John Doe") } -# end -# end RSpec.describe ConnectionDecorator, type: :decorator do - pending "add some examples to (or delete) #{__FILE__}" + let(:connection) { connections(:one) } + let(:decorated_connection) { connection.decorated } + + describe "#display_name" do + it { expect(decorated_connection.display_name).to eq("ServerName1 - Carte ServerName1 / Card1 / compo1") } + end end diff --git a/spec/models/record_dependencies_spec.rb b/spec/models/record_dependencies_spec.rb index 918aba4c2..1417b062d 100644 --- a/spec/models/record_dependencies_spec.rb +++ b/spec/models/record_dependencies_spec.rb @@ -75,9 +75,9 @@ let(:except) { nil } context "with only and except nil" do - it do - expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) - end + # it do + # expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) + # end it do expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(true) @@ -96,9 +96,9 @@ context "with only cards and changelog_entries" do let(:only) { %i[cards changelog_entries] } - it do - expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) - end + # it do + # expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(true) + # end it do expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(false) @@ -117,9 +117,9 @@ context "with except cards" do let(:except) { :cards } - it do - expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(false) - end + # it do + # expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:cards))).to be(false) + # end it do expect(record_dependencies.send(:association_valid?, record.class.reflect_on_association(:moves))).to be(true) diff --git a/spec/requests/cables_controller_request_spec.rb b/spec/requests/cables_controller_request_spec.rb index 8bcdd6bfb..02a283568 100644 --- a/spec/requests/cables_controller_request_spec.rb +++ b/spec/requests/cables_controller_request_spec.rb @@ -57,19 +57,41 @@ end describe "DELETE #destroy" do - subject(:response) do - delete cable_path(cable) + context "without confirm" do + subject(:response) do + delete cable_path(cable) + @response # rubocop:disable RSpec/InstanceVariable + end - @response # rubocop:disable RSpec/InstanceVariable + it do + expect do + response + end.not_to change(Cable, :count) + end + + it { expect(response).to have_http_status(:success) } + it { expect(Cable.exists?(cable.id)).to be(true) } end context "with not found cable" do + subject(:response) do + delete cable_path(cable, confirm: true) + + @response # rubocop:disable RSpec/InstanceVariable + end + before { cable.id = 999_999_999 } it { expect { response }.to raise_error(ActiveRecord::RecordNotFound) } end context "with existing cable" do + subject(:response) do + delete cable_path(cable, confirm: true) + + @response # rubocop:disable RSpec/InstanceVariable + end + it { expect(response).to have_http_status(:redirect) } it do diff --git a/spec/requests/servers_controller_request_spec.rb b/spec/requests/servers_controller_request_spec.rb index 2933648d6..40c6db9a1 100644 --- a/spec/requests/servers_controller_request_spec.rb +++ b/spec/requests/servers_controller_request_spec.rb @@ -216,7 +216,7 @@ end it { expect(response).to have_http_status(:success) } - it { expect(Server.exists?(server.id)).to be true } + it { expect(Server.exists?(server.id)).to be(true) } end context "with a server without association" do From 5882c59817be3711a2ad277bf606fce84575fa36 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 17 Dec 2025 23:52:14 +0100 Subject: [PATCH 30/33] wip --- app/decorators/enclosure_decorator.rb | 7 +++ app/models/cluster.rb | 1 + app/models/frame.rb | 4 ++ app/models/move.rb | 4 ++ app/models/permission_scope_domain.rb | 2 + app/models/port_type.rb | 2 +- app/models/server.rb | 16 +++---- spec/decorators/enclosure_decorator_spec.rb | 17 +++++++ spec/models/frame_spec.rb | 4 ++ spec/models/server_spec.rb | 1 + .../servers_controller_request_spec.rb | 46 ++++++------------- .../requests/delete_confirmation.rb | 41 +++++++++++++++++ 12 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 app/decorators/enclosure_decorator.rb create mode 100644 spec/decorators/enclosure_decorator_spec.rb create mode 100644 spec/support/shared_examples/requests/delete_confirmation.rb diff --git a/app/decorators/enclosure_decorator.rb b/app/decorators/enclosure_decorator.rb new file mode 100644 index 000000000..0732b3356 --- /dev/null +++ b/app/decorators/enclosure_decorator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class EnclosureDecorator < ApplicationDecorator + def display_name + "#{position} - #{display} - #{grid_areas}" + end +end diff --git a/app/models/cluster.rb b/app/models/cluster.rb index 594791087..c1aa953dc 100644 --- a/app/models/cluster.rb +++ b/app/models/cluster.rb @@ -4,6 +4,7 @@ class Cluster < ApplicationRecord has_changelog has_many :servers, dependent: :restrict_with_error + has_many :cluster_rooms, dependent: :destroy scope :sorted, -> { order(Arel.sql("LOWER(name)")) } diff --git a/app/models/frame.rb b/app/models/frame.rb index 03663784d..7170d141f 100644 --- a/app/models/frame.rb +++ b/app/models/frame.rb @@ -11,9 +11,13 @@ class Frame < ApplicationRecord # rubocop:disable Metrics/ClassLength has_changelog belongs_to :bay + has_many :materials, -> { order("servers.position desc") }, class_name: "Server", dependent: :restrict_with_error has_many :pdus, -> { only_pdus }, class_name: "Server", dependent: :restrict_with_error has_many :servers, -> { no_pdus.order("servers.position desc") }, class_name: "Server", dependent: :restrict_with_error + has_many :target_moves, class_name: "Move", inverse_of: :frame, dependent: :destroy + has_many :origin_moves, class_name: "Move", foreign_key: :prev_frame_id, inverse_of: :prev_frame, dependent: :destroy + has_one :islet, through: :bay has_one :room, through: :islet delegate :name, to: :room, prefix: true, allow_nil: true diff --git a/app/models/move.rb b/app/models/move.rb index 646701027..683cf2017 100644 --- a/app/models/move.rb +++ b/app/models/move.rb @@ -36,6 +36,10 @@ def clear_connections end end + def to_s + "#{moves_project} - #{step} - #{moveable}" + end + def status executed? ? :executed : :planned end diff --git a/app/models/permission_scope_domain.rb b/app/models/permission_scope_domain.rb index 2063d9d18..8b01e7518 100644 --- a/app/models/permission_scope_domain.rb +++ b/app/models/permission_scope_domain.rb @@ -3,4 +3,6 @@ class PermissionScopeDomain < ApplicationRecord belongs_to :permission_scope belongs_to :domaine + + delegate :to_s, to: :permission_scope end diff --git a/app/models/port_type.rb b/app/models/port_type.rb index 3ba349040..4f220ad1c 100644 --- a/app/models/port_type.rb +++ b/app/models/port_type.rb @@ -3,7 +3,7 @@ class PortType < ApplicationRecord has_changelog - has_many :card_types + has_many :card_types, dependent: :restrict_with_error scope :sorted, -> { order(name: :asc) } diff --git a/app/models/server.rb b/app/models/server.rb index 9009b9845..23f6839d8 100644 --- a/app/models/server.rb +++ b/app/models/server.rb @@ -8,28 +8,28 @@ class Server < ApplicationRecord # rubocop:disable Metrics/ClassLength has_changelog belongs_to :frame - has_one :bay, through: :frame - has_one :islet, through: :frame - has_one :room, through: :islet belongs_to :gestion, optional: true, counter_cache: true belongs_to :domaine, optional: true, counter_cache: true belongs_to :modele, counter_cache: true belongs_to :cluster, optional: true, counter_cache: true belongs_to :stack, optional: true, counter_cache: true - has_many :cards, -> { joins(:composant).includes(:composant) } + has_one :bay, through: :frame + has_one :islet, through: :frame + has_one :room, through: :islet + + has_many :cards, -> { joins(:composant).includes(:composant) }, dependent: :destroy has_many :card_types, through: :cards has_many :ports, through: :cards has_many :connections, through: :ports has_many :cables, through: :connections - has_many :moves, as: :moveable, dependent: :destroy - has_many :documents, dependent: :restrict_with_error - has_one_attached :photo - + # TODO: should be plural has_many :external_app_record, dependent: :destroy + has_one_attached :photo + validates :numero, presence: true, uniqueness: true validates :name, presence: true validate :numero_cannot_be_a_current_server_name diff --git a/spec/decorators/enclosure_decorator_spec.rb b/spec/decorators/enclosure_decorator_spec.rb new file mode 100644 index 000000000..7543e4615 --- /dev/null +++ b/spec/decorators/enclosure_decorator_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "rails_helper" + +# Example: +# +# describe EnclosureDecorator, type: :decorator do +# let(:object) { User.new(first_name: "John", last_name: "Doe") } +# let(:decorated_user) { described_class.new(object) } +# +# describe "#full_name" do +# it { expect(decorated_user.full_name).to eq("John Doe") } +# end +# end +RSpec.describe EnclosureDecorator, type: :decorator do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/frame_spec.rb b/spec/models/frame_spec.rb index 855eee60b..3df443df8 100644 --- a/spec/models/frame_spec.rb +++ b/spec/models/frame_spec.rb @@ -12,9 +12,13 @@ it { is_expected.to belong_to(:bay) } it { is_expected.to have_one(:islet).through(:bay) } + it { is_expected.to have_one(:room).through(:islet) } + it { is_expected.to have_many(:materials) } it { is_expected.to have_many(:pdus) } it { is_expected.to have_many(:servers) } + it { is_expected.to have_many(:target_moves) } + it { is_expected.to have_many(:origin_moves) } end describe "validations" do diff --git a/spec/models/server_spec.rb b/spec/models/server_spec.rb index 773b9c682..00a8e0721 100644 --- a/spec/models/server_spec.rb +++ b/spec/models/server_spec.rb @@ -28,6 +28,7 @@ it { is_expected.to have_many(:cables).through(:connections) } it { is_expected.to have_many(:moves).dependent(:destroy) } it { is_expected.to have_many(:documents) } + it { is_expected.to have_many(:external_app_record) } end describe "attachement" do diff --git a/spec/requests/servers_controller_request_spec.rb b/spec/requests/servers_controller_request_spec.rb index 40c6db9a1..852caadde 100644 --- a/spec/requests/servers_controller_request_spec.rb +++ b/spec/requests/servers_controller_request_spec.rb @@ -203,49 +203,31 @@ end describe "DELETE #destroy" do - context "without confirm" do - subject(:response) do - delete server_path(server2) - @response # rubocop:disable RSpec/InstanceVariable - end - - it do - expect do - response - end.not_to change(Server, :count) - end - - it { expect(response).to have_http_status(:success) } - it { expect(Server.exists?(server.id)).to be(true) } - end + # it_behaves_like "with delete confirmation view", record: server2 do + # context "with filter params" do + # let(:params) { { sort: "asc", sort_by: "rooms.name" } } - context "with a server without association" do - it "destroys the requested server" do - expect do - delete server_path(server2, confirm: true) - end.to change(Server, :count).by(-1) - end + # it { expect(response).to redirect_to(servers_path({ sort: "asc", sort_by: "rooms.name" })) } + # end + # end - it "redirects to the servers list" do - delete server_path(server2, confirm: true) - expect(response).to redirect_to(servers_path) - end + # it_behaves_like "with delete confirmation view", record: server do + # context "with filter params" do + # let(:params) { { sort: "asc", sort_by: "rooms.name" } } - it "redirects to the servers list and keep params" do - delete server_path(server2, params: { sort: "asc", sort_by: "rooms.name" }, confirm: true) - expect(response).to redirect_to(servers_path({ sort: "asc", sort_by: "rooms.name" })) - end - end + # it { expect(response).to redirect_to(servers_path({ sort: "asc", sort_by: "rooms.name" })) } + # end + # end context "with a server with association" do it "does not destroy the requested server" do expect do - delete server_path(server, confirm: true) + delete server_path(server) end.not_to change(Server, :count) end it "redirects to the servers list" do - delete server_path(server, confirm: true) + delete server_path(server) expect(response).to redirect_to(servers_path) end end diff --git a/spec/support/shared_examples/requests/delete_confirmation.rb b/spec/support/shared_examples/requests/delete_confirmation.rb new file mode 100644 index 000000000..252d11d86 --- /dev/null +++ b/spec/support/shared_examples/requests/delete_confirmation.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +RSpec.shared_context "with delete confirmation view" do |record:, route: nil| + let(:confirm) { nil } + let(:params) { {} } + + context "with preferred columns in URL" do + if route + let(:response) do + delete public_send(route, record, params.merge(confirm:)) + + # NOTE: used to simplify usage and custom test done in final spec file. + @response # rubocop:disable RSpec/InstanceVariable + end + else + before do + delete url_for(record, params.merge(confirm:)) + end + end + + context "without confirmation" do + it { expect(response).to have_http_status(:success) } + it { expect(response).to render_template(:delete) } + it { expect { response }.not_to change(record.klass, :count) } + + it do + record.reload + + expect(record.destroyed?).to be(false) + end + + context "with confirmation" do + let(:confirm) { true } + + it { expect(response).to have_http_status(:redirection) } + it { expect { response }.to change(record.klass, :count).by(-1) } + it { expect {  record.reload }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + end +end From 075ba7380814408c23236d6ca0375273ec0422bf Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 14 Jan 2026 17:33:14 +0100 Subject: [PATCH 31/33] wip --- app/models/composant.rb | 2 +- app/models/modele.rb | 2 +- app/views/rooms/destroy.html.erb | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/composant.rb b/app/models/composant.rb index 179cb81c9..cc55e8649 100644 --- a/app/models/composant.rb +++ b/app/models/composant.rb @@ -7,7 +7,7 @@ class Composant < ApplicationRecord belongs_to :enclosure has_one :modele, through: :enclosure - has_many :cards + has_many :cards, dependent: :restrict_with_error validates :name, format: { without: /\s/ }, allow_blank: true diff --git a/app/models/modele.rb b/app/models/modele.rb index aed1a560d..e2c17f473 100644 --- a/app/models/modele.rb +++ b/app/models/modele.rb @@ -8,7 +8,7 @@ class Modele < ApplicationRecord has_changelog has_many :servers, dependent: :restrict_with_error - has_many :enclosures, dependent: :restrict_with_error + has_many :enclosures, dependent: :destroy has_many :composants, through: :enclosures belongs_to :manufacturer, counter_cache: true diff --git a/app/views/rooms/destroy.html.erb b/app/views/rooms/destroy.html.erb index 1b866abe6..9d119945b 100644 --- a/app/views/rooms/destroy.html.erb +++ b/app/views/rooms/destroy.html.erb @@ -9,6 +9,7 @@
    <%= render DeleteDependencyComponent.new( @room, + except: %i[cluster_rooms], confirmation_path: room_path(@room, confirm: true) ) %>
    From 49e14e2559f398d72f210ac8ad297eb47f3a1f9c Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 14 Jan 2026 17:41:21 +0100 Subject: [PATCH 32/33] fix --- spec/support/shared_examples/requests/delete_confirmation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/shared_examples/requests/delete_confirmation.rb b/spec/support/shared_examples/requests/delete_confirmation.rb index 252d11d86..25dc4619b 100644 --- a/spec/support/shared_examples/requests/delete_confirmation.rb +++ b/spec/support/shared_examples/requests/delete_confirmation.rb @@ -34,7 +34,7 @@ it { expect(response).to have_http_status(:redirection) } it { expect { response }.to change(record.klass, :count).by(-1) } - it { expect {  record.reload }.to raise_error(ActiveRecord::RecordNotFound) } + it { expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound) } end end end From 1f70562b970417f82ac0ea9c21171ff77edf8a73 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 18 Mar 2026 15:47:31 +0100 Subject: [PATCH 33/33] Cleanup --- app/models/frame.rb | 2 - app/models/move.rb | 4 -- config/locales/activerecord.en.yml | 1 + config/locales/activerecord.fr.yml | 1 + spec/models/frame_spec.rb | 2 - spec/models/server_spec.rb | 2 +- .../requests/delete_confirmation.rb | 41 ------------------- 7 files changed, 3 insertions(+), 50 deletions(-) delete mode 100644 spec/support/shared_examples/requests/delete_confirmation.rb diff --git a/app/models/frame.rb b/app/models/frame.rb index 6728110ae..c19fa50f0 100644 --- a/app/models/frame.rb +++ b/app/models/frame.rb @@ -14,8 +14,6 @@ class Frame < ApplicationRecord # rubocop:disable Metrics/ClassLength has_many :materials, -> { order("servers.position desc") }, class_name: "Server", dependent: :restrict_with_error has_many :pdus, -> { only_pdus }, class_name: "Server", dependent: :restrict_with_error has_many :servers, -> { no_pdus.order("servers.position desc") }, class_name: "Server", dependent: :restrict_with_error - has_many :target_moves, class_name: "Move", inverse_of: :frame, dependent: :destroy - has_many :origin_moves, class_name: "Move", foreign_key: :prev_frame_id, inverse_of: :prev_frame, dependent: :destroy has_one :islet, through: :bay has_one :room, through: :islet diff --git a/app/models/move.rb b/app/models/move.rb index 1082e2398..0733ba381 100644 --- a/app/models/move.rb +++ b/app/models/move.rb @@ -46,10 +46,6 @@ def clear_connections end end - def to_s - "#{moves_project} - #{step} - #{moveable}" - end - def status executed? ? :executed : :planned end diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 5bef4f495..afa992af4 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -38,6 +38,7 @@ en: stack: Stack user: User permission_scope: Permission Scope + permission_scope_domain: Permission Scope attributes: bay: diff --git a/config/locales/activerecord.fr.yml b/config/locales/activerecord.fr.yml index b5ee0a6c4..bf7758bb0 100644 --- a/config/locales/activerecord.fr.yml +++ b/config/locales/activerecord.fr.yml @@ -54,6 +54,7 @@ fr: contact_role: Rôle contact_assignment: Assignation permission_scope: Permission + permission_scope_domain: Permission attributes: room: diff --git a/spec/models/frame_spec.rb b/spec/models/frame_spec.rb index 197300cc6..5ee9c790c 100644 --- a/spec/models/frame_spec.rb +++ b/spec/models/frame_spec.rb @@ -17,8 +17,6 @@ it { is_expected.to have_many(:materials).dependent(:restrict_with_error) } it { is_expected.to have_many(:pdus).dependent(:restrict_with_error) } it { is_expected.to have_many(:servers).dependent(:restrict_with_error) } - it { is_expected.to have_many(:target_moves) } - it { is_expected.to have_many(:origin_moves) } end describe "validations" do diff --git a/spec/models/server_spec.rb b/spec/models/server_spec.rb index 9d550a07a..2b67594ec 100644 --- a/spec/models/server_spec.rb +++ b/spec/models/server_spec.rb @@ -13,9 +13,9 @@ it { is_expected.to belong_to(:frame) } it { is_expected.to belong_to(:gestion).optional(true) } it { is_expected.to belong_to(:domaine).optional(true) } - it { is_expected.to belong_to(:modele) } it { is_expected.to belong_to(:cluster).optional(true) } it { is_expected.to belong_to(:stack).optional(true) } + it { is_expected.to belong_to(:modele) } it { is_expected.to have_one(:bay).through(:frame) } it { is_expected.to have_one(:islet).through(:frame) } diff --git a/spec/support/shared_examples/requests/delete_confirmation.rb b/spec/support/shared_examples/requests/delete_confirmation.rb deleted file mode 100644 index 25dc4619b..000000000 --- a/spec/support/shared_examples/requests/delete_confirmation.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_context "with delete confirmation view" do |record:, route: nil| - let(:confirm) { nil } - let(:params) { {} } - - context "with preferred columns in URL" do - if route - let(:response) do - delete public_send(route, record, params.merge(confirm:)) - - # NOTE: used to simplify usage and custom test done in final spec file. - @response # rubocop:disable RSpec/InstanceVariable - end - else - before do - delete url_for(record, params.merge(confirm:)) - end - end - - context "without confirmation" do - it { expect(response).to have_http_status(:success) } - it { expect(response).to render_template(:delete) } - it { expect { response }.not_to change(record.klass, :count) } - - it do - record.reload - - expect(record.destroyed?).to be(false) - end - - context "with confirmation" do - let(:confirm) { true } - - it { expect(response).to have_http_status(:redirection) } - it { expect { response }.to change(record.klass, :count).by(-1) } - it { expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound) } - end - end - end -end