From 5a0d46afe1f6d5d6392649817e56e0c8862cc360 Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Wed, 13 May 2026 15:28:06 +0200 Subject: [PATCH 01/14] Add ResourceWorkPackageList model --- .../app/models/resource_work_package_list.rb | 42 +++++++++++++++++++ .../resource_management/config/locales/en.yml | 4 ++ 2 files changed, 46 insertions(+) create mode 100644 modules/resource_management/app/models/resource_work_package_list.rb diff --git a/modules/resource_management/app/models/resource_work_package_list.rb b/modules/resource_management/app/models/resource_work_package_list.rb new file mode 100644 index 000000000000..b464616619ec --- /dev/null +++ b/modules/resource_management/app/models/resource_work_package_list.rb @@ -0,0 +1,42 @@ +# 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 ResourceWorkPackageList < PersistedView + validate :query_must_be_work_package_query + + private + + def query_must_be_work_package_query + resolved = effective_query + return if resolved.nil? || resolved.is_a?(Query) + + errors.add(:query, I18n.t(:must_be_work_package_query)) + end +end diff --git a/modules/resource_management/config/locales/en.yml b/modules/resource_management/config/locales/en.yml index 1eb92248fbc4..a78edc52f894 100644 --- a/modules/resource_management/config/locales/en.yml +++ b/modules/resource_management/config/locales/en.yml @@ -27,6 +27,10 @@ en: attributes: end_date: greater_than_start_date: "must be after the start date." + resource_work_package_list: + attributes: + query: + must_be_work_package_query: "must be a work package query." plugin_openproject_resource_management: name: "OpenProject Resource Management" From d205f8e399dccc515b9d928619ceba95484c5a18 Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Wed, 13 May 2026 15:31:00 +0200 Subject: [PATCH 02/14] Add model names --- modules/resource_management/config/locales/en.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/resource_management/config/locales/en.yml b/modules/resource_management/config/locales/en.yml index a78edc52f894..b0fe67a30126 100644 --- a/modules/resource_management/config/locales/en.yml +++ b/modules/resource_management/config/locales/en.yml @@ -1,6 +1,10 @@ --- en: activerecord: + models: + resource_planner: "Resource Planner" + resource_allocation: "Resource Allocation" + resource_work_package_list: "Work packages list" attributes: resource_planner: name: "Name" From 13b859c2777e5cd59608c4465486eddb0f266e6e Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Wed, 13 May 2026 15:32:46 +0200 Subject: [PATCH 03/14] Move User Card view into the resource management module --- modules/resource_management/app/models/resource_planner.rb | 2 +- .../resource_management/app/models/user_card.rb | 2 +- modules/resource_management/config/locales/en.yml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) rename app/models/user_card_view.rb => modules/resource_management/app/models/user_card.rb (98%) diff --git a/modules/resource_management/app/models/resource_planner.rb b/modules/resource_management/app/models/resource_planner.rb index 2cd618f81daf..e41d6f13ca9d 100644 --- a/modules/resource_management/app/models/resource_planner.rb +++ b/modules/resource_management/app/models/resource_planner.rb @@ -29,7 +29,7 @@ #++ class ResourcePlanner < PersistedView - self.allowed_children = %w[UserCardView] + self.allowed_children = %w[UserCardView ResourceWorkPackageList] # Virtual attributes used by the new-planner form. They are not persisted on # the planner itself: `default_view_class_name` is consumed when creating the diff --git a/app/models/user_card_view.rb b/modules/resource_management/app/models/user_card.rb similarity index 98% rename from app/models/user_card_view.rb rename to modules/resource_management/app/models/user_card.rb index f568951f75f8..beff3b21efae 100644 --- a/app/models/user_card_view.rb +++ b/modules/resource_management/app/models/user_card.rb @@ -28,7 +28,7 @@ # See COPYRIGHT and LICENSE files for more details. #++ -class UserCardView < PersistedView +class UserCard < PersistedView SECONDARY_INFO = %w[role email login none].freeze TAG_SOURCES = %w[groups roles none].freeze CARD_SIZES = %w[compact default expanded].freeze diff --git a/modules/resource_management/config/locales/en.yml b/modules/resource_management/config/locales/en.yml index b0fe67a30126..423e70dc225c 100644 --- a/modules/resource_management/config/locales/en.yml +++ b/modules/resource_management/config/locales/en.yml @@ -5,6 +5,7 @@ en: resource_planner: "Resource Planner" resource_allocation: "Resource Allocation" resource_work_package_list: "Work packages list" + user_card: "User cards" attributes: resource_planner: name: "Name" From c5f62167c5c6f58b9c420f84ab597482a5e918ec Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Tue, 26 May 2026 14:38:22 +0200 Subject: [PATCH 04/14] Add a scope to pre-load all children --- app/models/persisted_view.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/persisted_view.rb b/app/models/persisted_view.rb index 9646870b7842..f23ea398a340 100644 --- a/app/models/persisted_view.rb +++ b/app/models/persisted_view.rb @@ -49,6 +49,7 @@ class PersistedView < ApplicationRecord scope :public_views, -> { where(public: true) } scope :private_views, ->(principal = User.current) { where(public: false, principal_id: principal.id) } + scope :with_children, -> { includes(:children) } scope :visible, (lambda do |principal = User.current| public_views.or(private_views(principal)) From 61242b0284fbaa78fdb50bd9a0c03bfaeb9c2df0 Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Tue, 26 May 2026 14:38:58 +0200 Subject: [PATCH 05/14] Implement the tabbar for views within a resource planner --- .../resource_planners/sub_views_component.rb | 73 +++++++++++++++++++ .../resource_planner_views_controller.rb | 65 +++++++++++++++++ .../resource_planners_controller.rb | 12 ++- .../app/models/resource_planner.rb | 1 + .../show.html.erb | 4 +- .../resource_management/config/locales/en.yml | 1 + modules/resource_management/config/routes.rb | 4 + .../resource_management/engine.rb | 1 + 8 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 modules/resource_management/app/components/resource_planners/sub_views_component.rb create mode 100644 modules/resource_management/app/controllers/resource_management/resource_planner_views_controller.rb rename modules/resource_management/app/views/resource_management/{resource_planners => resource_planner_views}/show.html.erb (90%) diff --git a/modules/resource_management/app/components/resource_planners/sub_views_component.rb b/modules/resource_management/app/components/resource_planners/sub_views_component.rb new file mode 100644 index 000000000000..d1b690c20dd6 --- /dev/null +++ b/modules/resource_management/app/components/resource_planners/sub_views_component.rb @@ -0,0 +1,73 @@ +# 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 ResourcePlanners + class SubViewsComponent < ApplicationComponent + attr_reader :resource_planner, :selected_view + + def initialize(resource_planner:, selected_view: nil) + super + + @resource_planner = resource_planner + @selected_view = selected_view + end + + def call + render(Primer::Alpha::TabNav.new(label: I18n.t("resource_management.sub_views"))) do |component| + resource_planner.children.each { |child| add_view_tab(component, child) } + add_create_tab(component) if can_add_views? + end + end + + private + + def add_view_tab(component, child) + component.with_tab( + selected: child.id == selected_view_id, + href: project_resource_planner_view_path(resource_planner.project, resource_planner, child) + ) { child.name } + end + + def add_create_tab(component) + component.with_tab(href: new_project_resource_planner_view_path(resource_planner.project, resource_planner)) do + render(Primer::Beta::Octicon.new(icon: :plus, size: :medium)) + end + end + + def selected_view_id + selected_view&.id || resource_planner.default_view_id + end + + def can_add_views? + # TODO: Proper permission check + true + end + end +end diff --git a/modules/resource_management/app/controllers/resource_management/resource_planner_views_controller.rb b/modules/resource_management/app/controllers/resource_management/resource_planner_views_controller.rb new file mode 100644 index 000000000000..e84e667f57cd --- /dev/null +++ b/modules/resource_management/app/controllers/resource_management/resource_planner_views_controller.rb @@ -0,0 +1,65 @@ +# 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 ::ResourceManagement + class ResourcePlannerViewsController < BaseController + menu_item :resource_management + + before_action :find_project_by_project_id + before_action :authorize + before_action :find_resource_planner + before_action :find_view, only: %i[show edit update destroy] + + def show; end + + def new; end + + def edit; end + + def create; end + + def update; end + + def destroy; end + + private + + def find_resource_planner + @resource_planner = ResourcePlanner + .visible(current_user) + .where(project: @project) + .with_children + .find(params.expect(:resource_planner_id)) + end + + def find_view + @view = @resource_planner.children.find(params.expect(:id)) + end + end +end diff --git a/modules/resource_management/app/controllers/resource_management/resource_planners_controller.rb b/modules/resource_management/app/controllers/resource_management/resource_planners_controller.rb index 2e7134a3dc84..66b2aecbcf6f 100644 --- a/modules/resource_management/app/controllers/resource_management/resource_planners_controller.rb +++ b/modules/resource_management/app/controllers/resource_management/resource_planners_controller.rb @@ -27,7 +27,6 @@ # # See COPYRIGHT and LICENSE files for more details. #++ - module ::ResourceManagement class ResourcePlannersController < BaseController include OpTurbo::ComponentStream @@ -46,7 +45,10 @@ def index .order(:name) end - def show; end + def show + @view = default_view + render "resource_management/resource_planner_views/show" + end def overview; end @@ -115,6 +117,7 @@ def find_resource_planner @resource_planner = ResourcePlanner .visible(current_user) .where(project: @project) + .with_children .find(params[:id]) end @@ -122,6 +125,11 @@ def build_resource_planner @resource_planner = ResourcePlanner.new(project: @project, principal: current_user) end + def default_view + children = @resource_planner.children + children.find { |c| c.id == @resource_planner.default_view_id } || children.first + end + def create_params extra = %i[default_view_class_name favorite] extra << :public if can_manage_public? diff --git a/modules/resource_management/app/models/resource_planner.rb b/modules/resource_management/app/models/resource_planner.rb index e41d6f13ca9d..d05361b2b90b 100644 --- a/modules/resource_management/app/models/resource_planner.rb +++ b/modules/resource_management/app/models/resource_planner.rb @@ -38,6 +38,7 @@ class ResourcePlanner < PersistedView store_attribute :options, :start_date, :date store_attribute :options, :end_date, :date + store_attribute :options, :default_view_id, :integer # resource planner cannot be nested, queries are assigned to the sub-views validates :parent, absence: true diff --git a/modules/resource_management/app/views/resource_management/resource_planners/show.html.erb b/modules/resource_management/app/views/resource_management/resource_planner_views/show.html.erb similarity index 90% rename from modules/resource_management/app/views/resource_management/resource_planners/show.html.erb rename to modules/resource_management/app/views/resource_management/resource_planner_views/show.html.erb index 8ca62f5a6e7a..a5efb7e7d43a 100644 --- a/modules/resource_management/app/views/resource_management/resource_planners/show.html.erb +++ b/modules/resource_management/app/views/resource_management/resource_planner_views/show.html.erb @@ -40,8 +40,10 @@ See COPYRIGHT and LICENSE files for more details. ) end %> +<%= render(ResourcePlanners::SubViewsComponent.new(resource_planner: @resource_planner, selected_view: @view)) %> + <%= render(Primer::Beta::Blankslate.new) do |blankslate| blankslate.with_visual_icon(icon: :people) - blankslate.with_heading(tag: :h2) { @resource_planner.name } + blankslate.with_heading(tag: :h2) { @view&.name || @resource_planner.name } blankslate.with_description { t("resource_management.show.placeholder") } end %> diff --git a/modules/resource_management/config/locales/en.yml b/modules/resource_management/config/locales/en.yml index 423e70dc225c..2c0d36ab043d 100644 --- a/modules/resource_management/config/locales/en.yml +++ b/modules/resource_management/config/locales/en.yml @@ -67,6 +67,7 @@ en: label_resource_planner: "Resource planner" label_resource_planner_plural: "Resource planners" label_new_resource_planner: "New resource planner" + sub_views: "Views in this resource planner" public_caption: > Make this view public to all members of the project. This does not affect the visibility of work packages which still depends on each user diff --git a/modules/resource_management/config/routes.rb b/modules/resource_management/config/routes.rb index 4211f1a5005a..99cd0a29ee5e 100644 --- a/modules/resource_management/config/routes.rb +++ b/modules/resource_management/config/routes.rb @@ -43,6 +43,10 @@ post :toggle_public end + resources :views, + controller: "resource_management/resource_planner_views", + only: %i[show new create edit update destroy] + collection do get "menu" => "resource_management/menus#show" end diff --git a/modules/resource_management/lib/open_project/resource_management/engine.rb b/modules/resource_management/lib/open_project/resource_management/engine.rb index 52ba7d9ee084..e1da2f9c8003 100644 --- a/modules/resource_management/lib/open_project/resource_management/engine.rb +++ b/modules/resource_management/lib/open_project/resource_management/engine.rb @@ -56,6 +56,7 @@ class Engine < ::Rails::Engine permission :view_resource_planners, { "resource_management/resource_planners": %i[index show overview new create edit update destroy], + "resource_management/resource_planner_views": %i[show new create edit update destroy], "resource_management/menus": %i[show] }, permissible_on: :project From 37240419a44fe613e01ef98c11389259f450c046 Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Tue, 26 May 2026 16:46:47 +0200 Subject: [PATCH 06/14] Use snake_case i18n keys for view types --- .../app/forms/resource_planners/forms/default_view_form.rb | 3 ++- modules/resource_management/app/models/resource_planner.rb | 2 +- modules/resource_management/config/locales/en.yml | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/resource_management/app/forms/resource_planners/forms/default_view_form.rb b/modules/resource_management/app/forms/resource_planners/forms/default_view_form.rb index 2741779e67d9..cf52d79ef80f 100644 --- a/modules/resource_management/app/forms/resource_planners/forms/default_view_form.rb +++ b/modules/resource_management/app/forms/resource_planners/forms/default_view_form.rb @@ -11,9 +11,10 @@ class DefaultViewForm < ApplicationForm input_width: :large ) do |select| ResourcePlanner.allowed_children.each do |class_name| + i18n_key = class_name.constantize.model_name.i18n_key select.option( value: class_name, - label: I18n.t("resource_management.view_types.#{class_name}", default: class_name.underscore.humanize) + label: I18n.t("resource_management.view_types.#{i18n_key}.label", default: class_name.underscore.humanize) ) end end diff --git a/modules/resource_management/app/models/resource_planner.rb b/modules/resource_management/app/models/resource_planner.rb index d05361b2b90b..864cad9c523c 100644 --- a/modules/resource_management/app/models/resource_planner.rb +++ b/modules/resource_management/app/models/resource_planner.rb @@ -29,7 +29,7 @@ #++ class ResourcePlanner < PersistedView - self.allowed_children = %w[UserCardView ResourceWorkPackageList] + self.allowed_children = %w[UserCard ResourceWorkPackageList] # Virtual attributes used by the new-planner form. They are not persisted on # the planner itself: `default_view_class_name` is consumed when creating the diff --git a/modules/resource_management/config/locales/en.yml b/modules/resource_management/config/locales/en.yml index 2c0d36ab043d..201ed12ce695 100644 --- a/modules/resource_management/config/locales/en.yml +++ b/modules/resource_management/config/locales/en.yml @@ -75,7 +75,12 @@ en: favorite_caption: > Make this view a favorite to add it on the top section of the sidebar menu. view_types: - UserCardView: "Users cards" + user_card: + label: "Users card list" + caption: "Create a view based on users and see their details and allocation in a list of user cards" + resource_work_package_list: + label: "Work packages list" + caption: "Create a view based on work packages and see its details and allocation in a list" action: favorite: "Add to favorites" unfavorite: "Remove from favorites" From e94122df8b5e287fbc01364f38adba7839f13fc4 Mon Sep 17 00:00:00 2001 From: Klaus Zanders Date: Tue, 26 May 2026 16:50:25 +0200 Subject: [PATCH 07/14] Add multi-step modal for creating resource planner views --- .../configure_step/footer_component.rb | 84 ++++++++++++++++++ .../configure_step/form_component.html.erb | 53 ++++++++++++ .../configure_step/form_component.rb | 69 +++++++++++++++ .../new_dialog_component.html.erb | 54 ++++++++++++ .../new_dialog_component.rb | 53 ++++++++++++ .../type_step/footer_component.rb | 63 ++++++++++++++ .../type_step/form_component.html.erb | 14 +++ .../type_step/form_component.rb | 49 +++++++++++ .../resource_planners/sub_views_component.rb | 5 +- .../resource_planner_views/base_contract.rb | 55 ++++++++++++ .../resource_planner_views/create_contract.rb | 47 ++++++++++ .../resource_planner_views_controller.rb | 66 +++++++++++++- .../forms/configure_form.rb | 70 +++++++++++++++ .../forms/type_select_form.rb | 54 ++++++++++++ .../app/models/resource_work_package_list.rb | 11 ++- .../app/models/user_card.rb | 7 ++ .../resource_planner_views/create_service.rb | 86 +++++++++++++++++++ .../set_attributes_service.rb | 41 +++++++++ .../resource_management/config/locales/en.yml | 12 +++ 19 files changed, 889 insertions(+), 4 deletions(-) create mode 100644 modules/resource_management/app/components/resource_planner_views/configure_step/footer_component.rb create mode 100644 modules/resource_management/app/components/resource_planner_views/configure_step/form_component.html.erb create mode 100644 modules/resource_management/app/components/resource_planner_views/configure_step/form_component.rb create mode 100644 modules/resource_management/app/components/resource_planner_views/new_dialog_component.html.erb create mode 100644 modules/resource_management/app/components/resource_planner_views/new_dialog_component.rb create mode 100644 modules/resource_management/app/components/resource_planner_views/type_step/footer_component.rb create mode 100644 modules/resource_management/app/components/resource_planner_views/type_step/form_component.html.erb create mode 100644 modules/resource_management/app/components/resource_planner_views/type_step/form_component.rb create mode 100644 modules/resource_management/app/contracts/resource_planner_views/base_contract.rb create mode 100644 modules/resource_management/app/contracts/resource_planner_views/create_contract.rb create mode 100644 modules/resource_management/app/forms/resource_planner_views/forms/configure_form.rb create mode 100644 modules/resource_management/app/forms/resource_planner_views/forms/type_select_form.rb create mode 100644 modules/resource_management/app/services/resource_planner_views/create_service.rb create mode 100644 modules/resource_management/app/services/resource_planner_views/set_attributes_service.rb diff --git a/modules/resource_management/app/components/resource_planner_views/configure_step/footer_component.rb b/modules/resource_management/app/components/resource_planner_views/configure_step/footer_component.rb new file mode 100644 index 000000000000..f0ff80515ceb --- /dev/null +++ b/modules/resource_management/app/components/resource_planner_views/configure_step/footer_component.rb @@ -0,0 +1,84 @@ +# 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 ResourcePlannerViews + module ConfigureStep + class FooterComponent < ApplicationComponent + include OpTurbo::Streamable + include OpPrimer::ComponentHelpers + + def initialize(submit_label: I18n.t(:button_create), + dialog_id: ResourcePlannerViews::NewDialogComponent::DIALOG_ID, + form_id: ResourcePlannerViews::NewDialogComponent::FORM_ID, + footer_id: ResourcePlannerViews::NewDialogComponent::FOOTER_ID, + cancel_href: nil) + super + @submit_label = submit_label + @dialog_id = dialog_id + @form_id = form_id + @footer_id = footer_id + @cancel_href = cancel_href + end + + attr_reader :footer_id + alias_method :wrapper_key, :footer_id + + def call + component_wrapper do + component_collection do |buttons| + buttons.with_component(cancel_button) { I18n.t(:button_cancel) } + + buttons.with_component( + Primer::Beta::Button.new( + scheme: :primary, + form: @form_id, + type: :submit + ) + ) { @submit_label } + end + end + end + + private + + # When a `cancel_href` is passed, Cancel becomes a link that navigates + # away — used by the new-planner flow so dismissing step 2 lands the + # user on a page that reflects the just-created planner. Without one, + # Cancel just dismisses the dialog (standalone "+ Add view" flow). + def cancel_button + if @cancel_href + Primer::Beta::Button.new(tag: :a, href: @cancel_href, mr: 1) + else + Primer::Beta::Button.new(data: { "close-dialog-id": @dialog_id }, mr: 1) + end + end + end + end +end diff --git a/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.html.erb b/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.html.erb new file mode 100644 index 000000000000..ee1e9b709cf4 --- /dev/null +++ b/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.html.erb @@ -0,0 +1,53 @@ +<%= + component_wrapper do + content_tag(:div, data: { controller: "show-when-value-selected" }) do + concat( + primer_form_with( + model: @view, + scope: :view, + url: @url, + method: @method, + html: { + data: { turbo_stream: true }, + id: @form_id + } + ) do |f| + flex_layout do |body| + if @view.errors[:base].present? + body.with_row(mb: 3) do + render(Primer::Alpha::Banner.new(mb: 3, icon: :stop, scheme: :danger)) { @view.errors[:base].join("\n") } + end + end + + @hidden_fields.each do |name, value| + body.with_row do + concat(hidden_field_tag(name, value)) + end + end + + body.with_row do + render(ResourcePlannerViews::Forms::ConfigureForm.new(f)) + end + end + end + ) + + if @filter_query + concat( + content_tag( + :div, + mt: 3, + data: { + target_name: "filter_mode", + value: "automatic", + "show-when-value-selected-target": "effect" + }, + hidden: !initial_filter_mode_automatic? + ) do + render(Filter::FilterComponent.new(query: @filter_query, initially_expanded: true)) + end + ) + end + end + end +%> diff --git a/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.rb b/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.rb new file mode 100644 index 000000000000..45a75e83e7c3 --- /dev/null +++ b/modules/resource_management/app/components/resource_planner_views/configure_step/form_component.rb @@ -0,0 +1,69 @@ +# 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 ResourcePlannerViews + module ConfigureStep + # Renders the "Configure view" form (name + filter mode). Used both for + # the new-view dialog (step 2) and for the future edit dialog. Callers + # pass the form `url`, HTTP `method`, and the model to bind to. The + # `form_id` lets the surrounding dialog wire its submit button to this + # form via `