From 1e2c0922b6ed34d0f082a50c0f12510e833332e3 Mon Sep 17 00:00:00 2001 From: Jan Sandbrink Date: Mon, 5 Jan 2026 16:41:08 +0100 Subject: [PATCH] Simplify project export Instead of showing a huge dialog that then just shows three links with huge icons and no further description, we just use a submenu, that immediately shows the export options as menu items. --- .../export_list_modal_component.html.erb | 23 -------- .../projects/export_list_modal_component.rb | 36 ------------ .../index_page_header_component.html.erb | 19 ++++--- app/controllers/projects_controller.rb | 10 +--- app/models/project.rb | 2 +- app/views/homescreen/robots.text.erb | 1 - config/initializers/permissions.rb | 2 +- config/routes.rb | 4 -- .../common/export-options/export-options.sass | 26 --------- .../common/openproject-common.module.sass | 1 - .../deprecated/modal_preview/default.html.erb | 57 ------------------- spec/routing/project_routing_spec.rb | 8 --- 12 files changed, 17 insertions(+), 172 deletions(-) delete mode 100644 app/components/projects/export_list_modal_component.html.erb delete mode 100644 app/components/projects/export_list_modal_component.rb delete mode 100644 frontend/src/global_styles/common/export-options/export-options.sass delete mode 100644 lookbook/previews/open_project/deprecated/modal_preview/default.html.erb diff --git a/app/components/projects/export_list_modal_component.html.erb b/app/components/projects/export_list_modal_component.html.erb deleted file mode 100644 index 398d929a8b9..00000000000 --- a/app/components/projects/export_list_modal_component.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -<%= render( - Primer::Alpha::Dialog.new( - title: t("js.label_export"), - id: MODAL_ID - ) - ) do |d| %> - <% d.with_header(variant: :large) %> - <% d.with_body do %> - - <% end %> -<% end %> diff --git a/app/components/projects/export_list_modal_component.rb b/app/components/projects/export_list_modal_component.rb deleted file mode 100644 index 28085a486ff..00000000000 --- a/app/components/projects/export_list_modal_component.rb +++ /dev/null @@ -1,36 +0,0 @@ -# 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. -# ++ - -class Projects::ExportListModalComponent < ApplicationComponent - include OpTurbo::Streamable - MODAL_ID = "op-project-list-export-dialog" - - options :query -end diff --git a/app/components/projects/index_page_header_component.html.erb b/app/components/projects/index_page_header_component.html.erb index 73e32a53d71..6ab7c06c21a 100644 --- a/app/components/projects/index_page_header_component.html.erb +++ b/app/components/projects/index_page_header_component.html.erb @@ -126,13 +126,18 @@ end if can_export? - menu.with_item( - tag: :a, - label: t("js.label_export"), - href: export_list_modal_projects_path(projects_query_params), - content_arguments: { data: { controller: "async-dialog" }, rel: "nofollow" } - ) do |item| - item.with_leading_visual_icon(icon: "sign-out") + menu.with_sub_menu_item(label: t("js.label_export")) do |submenu| + submenu.with_leading_visual_icon(icon: "sign-out") + helpers.supported_export_formats.each do |key| + submenu.with_item( + label: t("export.format.#{key}"), + tag: :a, + href: projects_path(format: key, **helpers.projects_query_params.except(:page, :per_page)), + content_arguments: { data: { controller: "job-dialog" }, rel: "nofollow" } + ) do |item| + item.with_leading_visual_icon(icon: "op-#{key == "csv" ? "file-csv" : key}") + end + end end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3b63b34e73e..bb62d32a288 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -34,10 +34,10 @@ class ProjectsController < ApplicationController menu_item :overview menu_item :roadmap, only: :roadmap - before_action :find_project, except: %i[index new create export_list_modal] - before_action :load_query_or_deny_access, only: %i[index export_list_modal] + before_action :find_project, except: %i[index new create] + before_action :load_query_or_deny_access, only: %i[index] before_action :authorize, - only: %i[copy_form copy deactivate_work_package_attachments export_list_modal export_project_initiation_pdf] + only: %i[copy_form copy deactivate_work_package_attachments export_project_initiation_pdf] before_action :authorize_global, only: %i[new create] before_action :require_admin, only: %i[destroy destroy_info] before_action :find_optional_parent, only: :new @@ -172,10 +172,6 @@ class ProjectsController < ApplicationController end end - def export_list_modal - respond_with_dialog Projects::ExportListModalComponent.new(query: @query) - end - def export_project_initiation_pdf export = Project::PDFExport::ProjectInitiation.new(@project).export! send_data(export.content, type: export.mime_type, filename: export.title) diff --git a/app/models/project.rb b/app/models/project.rb index aef24113909..05c86a7635c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -47,7 +47,7 @@ class Project < ApplicationRecord IDENTIFIER_MAX_LENGTH = 100 # reserved identifiers - RESERVED_IDENTIFIERS = %w[new menu queries filters export_list_modal].freeze + RESERVED_IDENTIFIERS = %w[new menu queries filters].freeze enum :workspace_type, { project: "project", diff --git a/app/views/homescreen/robots.text.erb b/app/views/homescreen/robots.text.erb index 19302ae9ce7..6a84ec81249 100644 --- a/app/views/homescreen/robots.text.erb +++ b/app/views/homescreen/robots.text.erb @@ -39,7 +39,6 @@ Disallow: <%= activities_path %> Disallow: /activity Disallow: <%= search_path %> Disallow: /project_queries/configure_view_modal -Disallow: /projects/export_list_modal <%# Generally allow /projects but disallow those links that change columns, sort order or per page settings %> Disallow: /projects?*columns= Disallow: /projects?*sortBy= diff --git a/config/initializers/permissions.rb b/config/initializers/permissions.rb index 5756079f2ea..670e7997846 100644 --- a/config/initializers/permissions.rb +++ b/config/initializers/permissions.rb @@ -158,7 +158,7 @@ Rails.application.reloader.to_prepare do map.permission :export_projects, { - projects: %i[export_list_modal export_project_initiation_pdf] + projects: %i[export_project_initiation_pdf] }, permissible_on: :project, dependencies: :view_project diff --git a/config/routes.rb b/config/routes.rb index 5ce4be47362..134f5c1f77c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -372,10 +372,6 @@ Rails.application.routes.draw do post :deactivate_work_package_attachments end - collection do - get :export_list_modal - end - resources :versions, only: %i[new create] do collection do put :close_completed diff --git a/frontend/src/global_styles/common/export-options/export-options.sass b/frontend/src/global_styles/common/export-options/export-options.sass deleted file mode 100644 index ae212558e6a..00000000000 --- a/frontend/src/global_styles/common/export-options/export-options.sass +++ /dev/null @@ -1,26 +0,0 @@ -.op-export-options - display: flex - flex-wrap: wrap - margin: 0 - padding: 20px 0 - list-style-type: none - - &--option - flex: 1 1 calc(33% - 40px) // line break after third element - margin: 20px - text-align: center - - &-link - cursor: pointer - text-decoration: none - color: var(--body-font-color) - font-weight: normal - overflow-wrap: break-word - word-wrap: break-word - &:hover, &:active - text-decoration: none - color: var(--body-font-color) - - &-label - display: block - padding: 10px 0 0 0 diff --git a/frontend/src/global_styles/common/openproject-common.module.sass b/frontend/src/global_styles/common/openproject-common.module.sass index 52ed4498087..adc7bbbed6f 100644 --- a/frontend/src/global_styles/common/openproject-common.module.sass +++ b/frontend/src/global_styles/common/openproject-common.module.sass @@ -6,6 +6,5 @@ @import '../../app/shared/components/option-list/option-list' @import '../../app/shared/components/table/table' @import '../../app/shared/components/table/scrollable-table' -@import 'export-options/export-options' @import 'select/select' @import 'wide-autocomplete-wrapper/wide-autocomplete-wrapper' diff --git a/lookbook/previews/open_project/deprecated/modal_preview/default.html.erb b/lookbook/previews/open_project/deprecated/modal_preview/default.html.erb deleted file mode 100644 index ef0bc898a16..00000000000 --- a/lookbook/previews/open_project/deprecated/modal_preview/default.html.erb +++ /dev/null @@ -1,57 +0,0 @@ -
-
-
- Export -
-
- -
-
- - -
-
-
-
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 942542d37ac..c2ab2f34b56 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -105,14 +105,6 @@ RSpec.describe ProjectsController do end end - describe "export_list_modal" do - it do - expect(get("/projects/export_list_modal")).to route_to( - controller: "projects", action: "export_list_modal" - ) - end - end - describe "templated" do it do expect(delete("/projects/123/templated"))