diff --git a/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.html.erb b/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.html.erb new file mode 100644 index 000000000000..3ddbcb1ccb9b --- /dev/null +++ b/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.html.erb @@ -0,0 +1,56 @@ +<%#-- copyright +OpenProject is an open source project management software. +Copyright (C) the OpenProject GmbH + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 3. + +OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +Copyright (C) 2006-2013 Jean-Philippe Lang +Copyright (C) 2010-2013 the ChiliProject Team + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +See COPYRIGHT and LICENSE files for more details. + +++#%> + +<%= + render(Primer::Alpha::Dialog.new(id: DIALOG_ID, title: "Delete item")) do |dialog| + dialog.with_header(variant: :large) + dialog.with_body do + "Are you sure you want to delete this item from the current hierarchy level?" + end + + dialog.with_footer do + concat(render(Primer::ButtonComponent.new(data: { "close-dialog-id": DIALOG_ID })) do + I18n.t(:button_cancel) + end) + + concat(primer_form_with( + model: @custom_field, + url: custom_field_item_path(custom_field_id: @custom_field.id, id: @hierarchy_item.id), + method: :delete, + data: { turbo: true } + ) do + render(Primer::ButtonComponent.new(scheme: :danger, + type: :submit, + data: { "close-dialog-id": DIALOG_ID })) do + I18n.t(:button_delete) + end + end) + end + end +%> diff --git a/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.rb b/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.rb new file mode 100644 index 000000000000..e7b9307bcb4a --- /dev/null +++ b/app/components/admin/custom_fields/hierarchy/delete_item_dialog_component.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module Admin + module CustomFields + module Hierarchy + class DeleteItemDialogComponent < ApplicationComponent + include OpTurbo::Streamable + + DIALOG_ID = "op-hierarchy-item--deletion-confirmation" + + def initialize(custom_field:, hierarchy_item:) + super + @custom_field = custom_field + @hierarchy_item = hierarchy_item + end + end + end + end +end diff --git a/app/components/admin/custom_fields/hierarchy/item_component.html.erb b/app/components/admin/custom_fields/hierarchy/item_component.html.erb index 369d9234804f..a1f989219537 100644 --- a/app/components/admin/custom_fields/hierarchy/item_component.html.erb +++ b/app/components/admin/custom_fields/hierarchy/item_component.html.erb @@ -46,9 +46,12 @@ See COPYRIGHT and LICENSE files for more details. # Actions item_container.with_column do - render(Primer::Beta::IconButton.new(scheme: :default, - icon: "kebab-horizontal", - "aria-label": I18n.t("custom_fields.admin.items.more_actions"))) + render(Primer::Alpha::ActionMenu.new(data: { test_selector: "op-hierarchy-item--action-menu" })) do |menu| + menu.with_show_button(icon: "kebab-horizontal", + scheme: :invisible, + "aria-label": I18n.t("custom_fields.admin.items.actions")) + deletion_action_item(menu) + end end end end diff --git a/app/components/admin/custom_fields/hierarchy/item_component.rb b/app/components/admin/custom_fields/hierarchy/item_component.rb index ddf8b1e16fcc..2a22a4b7d537 100644 --- a/app/components/admin/custom_fields/hierarchy/item_component.rb +++ b/app/components/admin/custom_fields/hierarchy/item_component.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + #-- copyright # OpenProject is an open source project management software. # Copyright (C) the OpenProject GmbH @@ -33,14 +35,26 @@ class ItemComponent < ApplicationComponent include OpTurbo::Streamable include OpPrimer::ComponentHelpers - def initialize(hierarchy_item:) + def initialize(custom_field:, hierarchy_item:) super + @custom_field = custom_field @hierarchy_item = hierarchy_item end def short_text "(#{@hierarchy_item.short})" end + + def deletion_action_item(menu) + menu.with_item(label: I18n.t(:button_delete), + scheme: :danger, + tag: :a, + href: deletion_dialog_custom_field_item_path(custom_field_id: @custom_field.id, + id: @hierarchy_item.id), + content_arguments: { data: { controller: "async-dialog" } }) do |item| + item.with_leading_visual_icon(icon: :trash) + end + end end end end diff --git a/app/components/admin/custom_fields/hierarchy/items_component.html.erb b/app/components/admin/custom_fields/hierarchy/items_component.html.erb index 46ad4c347698..f729fcbe7f81 100644 --- a/app/components/admin/custom_fields/hierarchy/items_component.html.erb +++ b/app/components/admin/custom_fields/hierarchy/items_component.html.erb @@ -44,7 +44,10 @@ See COPYRIGHT and LICENSE files for more details. item_box.with_header { @custom_field.name } items.each do |item| - item_box.with_row { render Admin::CustomFields::Hierarchy::ItemComponent.new(hierarchy_item: item) } + item_box.with_row do + render Admin::CustomFields::Hierarchy::ItemComponent.new(custom_field: @custom_field, + hierarchy_item: item) + end end if show_new_item_form? diff --git a/app/components/admin/custom_fields/hierarchy/items_component.rb b/app/components/admin/custom_fields/hierarchy/items_component.rb index d98747609159..a0c91411f7d4 100644 --- a/app/components/admin/custom_fields/hierarchy/items_component.rb +++ b/app/components/admin/custom_fields/hierarchy/items_component.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + #-- copyright # OpenProject is an open source project management software. # Copyright (C) the OpenProject GmbH diff --git a/app/controllers/admin/custom_fields/hierarchy/items_controller.rb b/app/controllers/admin/custom_fields/hierarchy/items_controller.rb index c8fa3440e330..542b2c80563d 100644 --- a/app/controllers/admin/custom_fields/hierarchy/items_controller.rb +++ b/app/controllers/admin/custom_fields/hierarchy/items_controller.rb @@ -33,13 +33,15 @@ module CustomFields module Hierarchy class ItemsController < ApplicationController include OpTurbo::ComponentStream + include OpTurbo::DialogStreamHelper layout "admin" model_object CustomField before_action :require_admin - before_action :find_model_object + before_action :find_model_object, except: %i[destroy deletion_dialog] + before_action :find_custom_field_and_item, only: %i[destroy deletion_dialog] menu_item :custom_fields @@ -63,6 +65,23 @@ def create respond_with_turbo_streams end + def destroy + ::CustomFields::Hierarchy::HierarchicalItemService + .new + .delete_branch(item: @hierarchy_item) + .either( + ->(_) { update_via_turbo_stream(component: ItemsComponent.new(custom_field: @custom_field)) }, + ->(errors) { update_flash_message_via_turbo_stream(message: errors.full_messages, scheme: :danger) } + ) + + respond_with_turbo_streams + end + + def deletion_dialog + respond_with_dialog DeleteItemDialogComponent.new(custom_field: @custom_field, + hierarchy_item: @hierarchy_item) + end + private def item_input @@ -86,6 +105,13 @@ def find_model_object(object_id = :custom_field_id) super @custom_field = @object end + + def find_custom_field_and_item + @custom_field = CustomField.find(params[:custom_field_id]) + @hierarchy_item = CustomField::Hierarchy::Item.find(params[:id]) + rescue ActiveRecord::RecordNotFound + render_404 + end end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index aad32a55bcd1..1da6dc23e8ae 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -248,7 +248,7 @@ en: blankslate: title: "Your list of items is empty" description: "Start by adding items to the custom field of type hierarchy. Each item can be used to create a hierarchy bellow it. To navigate and create sub-items inside a hierarchy click on the created item." - more_actions: "More actions" + actions: "Item actions" placeholder: label: "Item label" short: "Short name" diff --git a/config/routes.rb b/config/routes.rb index bac6cb7e3bf9..eff38e6da7ad 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -180,7 +180,9 @@ only: :destroy resources :items, controller: "/admin/custom_fields/hierarchy/items", - only: %i[index new create] + only: %i[index new create destroy] do + get :deletion_dialog, on: :member + end end end end