diff --git a/modules/storages/app/components/storages/admin/edit_form_header_component.html.erb b/modules/storages/app/components/storages/admin/edit_form_header_component.html.erb index b5129d3b5acc..d856c0965c22 100644 --- a/modules/storages/app/components/storages/admin/edit_form_header_component.html.erb +++ b/modules/storages/app/components/storages/admin/edit_form_header_component.html.erb @@ -47,16 +47,15 @@ See COPYRIGHT and LICENSE files for more details. end if OpenProject::FeatureDecisions.enable_storage_for_multiple_projects_active? - header.with_tab_nav(label: nil, test_selector: :project_attribute_detail_header) do |tab_nav| + header.with_tab_nav(label: nil, test_selector: :storage_detail_header) do |tab_nav| tab_nav.with_tab( selected: tab_selected?(:edit), href: edit_admin_settings_storage_path(@storage) ) do |tab| tab.with_text { t(:label_details) } end - tab_nav.with_tab( - selected: tab_selected?(:project_mappings), + selected: tab_selected?(:project_storages), href: admin_settings_storage_project_storages_path(@storage) ) do |tab| tab.with_text { t(:label_project_mappings) } diff --git a/modules/storages/app/components/storages/admin/edit_form_header_component.rb b/modules/storages/app/components/storages/admin/edit_form_header_component.rb index f6a923e06e40..27101c28935f 100644 --- a/modules/storages/app/components/storages/admin/edit_form_header_component.rb +++ b/modules/storages/app/components/storages/admin/edit_form_header_component.rb @@ -31,7 +31,7 @@ module Admin class EditFormHeaderComponent < ApplicationComponent # rubocop:disable OpenProject/AddPreviewForViewComponent TAB_NAVS = %i[ edit - project_mappings + project_storages ].freeze def initialize(storage:, selected:) diff --git a/modules/storages/app/components/storages/project_storages/projects/row_component.rb b/modules/storages/app/components/storages/project_storages/projects/row_component.rb new file mode 100644 index 000000000000..a06da84d543d --- /dev/null +++ b/modules/storages/app/components/storages/project_storages/projects/row_component.rb @@ -0,0 +1,34 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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. +#++ + +# Purpose: Defines how to format the components within a table row of Projects +# associated with a Storage +module Storages::ProjectStorages::Projects + class RowComponent < Projects::RowComponent # rubocop:disable OpenProject/AddPreviewForViewComponent + end +end diff --git a/modules/storages/app/components/storages/project_storages/projects/table_component.rb b/modules/storages/app/components/storages/project_storages/projects/table_component.rb new file mode 100644 index 000000000000..6e4a3cfa1b7e --- /dev/null +++ b/modules/storages/app/components/storages/project_storages/projects/table_component.rb @@ -0,0 +1,48 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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. +#++ + +# Purpose: Defines a table based on TableComponent for listing the +# Projects for a given Storage. +# See also: row_component.rb, which contains a method +# for every "column" defined below. +module Storages::ProjectStorages::Projects + class TableComponent < Projects::TableComponent # rubocop:disable OpenProject/AddPreviewForViewComponent + include OpTurbo::Streamable + + def sortable? + false + end + + # Overwritten to avoid loading data that is not needed in this context + def projects(query) + query + .results + .paginate(page: helpers.page_param(params), per_page: helpers.per_page_param(params)) + end + end +end diff --git a/modules/storages/app/controllers/storages/admin/storages/project_storages_controller.rb b/modules/storages/app/controllers/storages/admin/storages/project_storages_controller.rb index c666d129a808..5254c801bfab 100644 --- a/modules/storages/app/controllers/storages/admin/storages/project_storages_controller.rb +++ b/modules/storages/app/controllers/storages/admin/storages/project_storages_controller.rb @@ -40,7 +40,16 @@ class Storages::Admin::Storages::ProjectStoragesController < ApplicationControll menu_item :external_file_storages - def index; end + def index + @project_query = ProjectQuery.new( + name: "project-storage-mappings-#{@storage.id}" + ) do |query| + query.where(:id, "=", @storage.projects.ids) + query.select(:name) + query.order("lft" => "asc") + end + end + def new; end def create; end def destroy; end diff --git a/modules/storages/app/controllers/storages/admin/storages_controller.rb b/modules/storages/app/controllers/storages/admin/storages_controller.rb index c029f3a51a9d..13ec7e2007b8 100644 --- a/modules/storages/app/controllers/storages/admin/storages_controller.rb +++ b/modules/storages/app/controllers/storages/admin/storages_controller.rb @@ -46,7 +46,7 @@ class Storages::Admin::StoragesController < ApplicationController before_action :require_admin before_action :find_model_object, only: %i[show_oauth_application destroy edit edit_host confirm_destroy update - change_health_notifications_enabled replace_oauth_application project_mappings] + change_health_notifications_enabled replace_oauth_application] before_action :ensure_valid_provider_type_selected, only: %i[select_provider] before_action :require_ee_token_for_one_drive, only: %i[select_provider] @@ -245,8 +245,6 @@ def replace_oauth_application end end - def project_mappings; end - def default_breadcrumb; end def show_local_breadcrumb diff --git a/modules/storages/app/views/storages/admin/storages/project_mappings.html.erb b/modules/storages/app/views/storages/admin/storages/project_mappings.html.erb deleted file mode 100644 index 7dbce9141416..000000000000 --- a/modules/storages/app/views/storages/admin/storages/project_mappings.html.erb +++ /dev/null @@ -1,36 +0,0 @@ -<%#-- copyright -OpenProject is an open source project management software. -Copyright (C) 2012-2023 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(Storages::Admin::EditFormHeaderComponent.new( - storage: @storage, - selected: :project_mappings - ) - ) -%> diff --git a/modules/storages/app/views/storages/admin/storages/project_storages/index.html.erb b/modules/storages/app/views/storages/admin/storages/project_storages/index.html.erb index a9b840abb921..1768dcbe3e8d 100644 --- a/modules/storages/app/views/storages/admin/storages/project_storages/index.html.erb +++ b/modules/storages/app/views/storages/admin/storages/project_storages/index.html.erb @@ -30,7 +30,7 @@ See COPYRIGHT and LICENSE files for more details. <%= render(Storages::Admin::EditFormHeaderComponent.new( storage: @storage, - selected: :project_mappings + selected: :project_storages ) ) %> @@ -50,3 +50,11 @@ See COPYRIGHT and LICENSE files for more details. end end %> + +<%= + render(Storages::ProjectStorages::Projects::TableComponent.new( + query: @project_query, + params: + ) + ) +%> diff --git a/modules/storages/config/routes.rb b/modules/storages/config/routes.rb index 90a1fafdb803..963f9eb14820 100644 --- a/modules/storages/config/routes.rb +++ b/modules/storages/config/routes.rb @@ -64,7 +64,6 @@ patch :change_health_notifications_enabled get :confirm_destroy delete :replace_oauth_application - get :project_mappings end get :upsale, on: :collection diff --git a/modules/storages/spec/features/storages/admin/project_storages_spec.rb b/modules/storages/spec/features/storages/admin/project_storages_spec.rb new file mode 100644 index 000000000000..60b5177900d5 --- /dev/null +++ b/modules/storages/spec/features/storages/admin/project_storages_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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. +#++ + +require "spec_helper" +require_module_spec_helper + +RSpec.describe "Admin lists project mappings for a storage", + :js, + :storage_server_helpers, + with_flag: { enable_storage_for_multiple_projects: true } do + shared_let(:admin) { create(:admin, preferences: { time_zone: "Etc/UTC" }) } + shared_let(:non_admin) { create(:user) } + shared_let(:project) { create(:project, name: "My active Project") } + shared_let(:archived_project) { create(:project, active: false, name: "My archived Project") } + shared_let(:storage) { create(:nextcloud_storage, name: "My Nextcloud Storage") } + shared_let(:project_storage) { create :project_storage, project:, storage: } + shared_let(:archived_project_project_storage) { create :project_storage, project: archived_project, storage: } + + current_user { admin } + + context "with insufficient permissions" do + it "is not accessible" do + login_as(non_admin) + visit admin_settings_storage_project_storages_path(storage) + + expect(page).to have_text("You are not authorized to access this page.") + end + end + + context "with sufficient permissions" do + before do + login_as(admin) + visit admin_settings_storage_project_storages_path(storage) + end + + it "renders a list of projects linked to the storage" do + aggregate_failures "shows a correct breadcrumb menu" do + within ".PageHeader-breadcrumbs" do + expect(page).to have_link("Administration") + expect(page).to have_link("Files") + expect(page).to have_link("My Nextcloud Storage") + end + end + + aggregate_failures "shows tab navigation" do + within_test_selector("storage_detail_header") do + expect(page).to have_link("Details") + expect(page).to have_link("Enabled in projects") + end + end + + aggregate_failures "shows the correct project mappings" do + within "#project-table" do + expect(page).to have_text(project.name) + expect(page).to have_text(archived_project.name) + end + end + end + end +end