diff --git a/config/initializers/feature_decisions.rb b/config/initializers/feature_decisions.rb index 0428a38ac95c..1392c5ce04cf 100644 --- a/config/initializers/feature_decisions.rb +++ b/config/initializers/feature_decisions.rb @@ -47,6 +47,9 @@ description: "Allows to generate a PDF document from a work package description. " \ "See #45896 for details." +OpenProject::FeatureDecisions.add :recurring_meetings, + description: "Differentiate between one-time and recurring meetings." + # TODO: Remove once the feature flag primerized_work_package_activities is removed altogether OpenProject::FeatureDecisions.define_singleton_method(:primerized_work_package_activities_active?) do Rails.env.production? || diff --git a/modules/meeting/app/components/meetings/index_sub_header_component.html.erb b/modules/meeting/app/components/meetings/index_sub_header_component.html.erb index b1aca653a074..d4c665de8501 100644 --- a/modules/meeting/app/components/meetings/index_sub_header_component.html.erb +++ b/modules/meeting/app/components/meetings/index_sub_header_component.html.erb @@ -23,20 +23,30 @@ I18n.t(:label_meeting) end - menu.with_item(label: I18n.t("meeting.types.structured"), - tag: :a, - href: new_dialog_meetings_path(project_id: @project&.id, type: :structured), - content_arguments: { data: { controller: "async-dialog" }} - ) do |item| - item.with_description.with_content(t("meeting.types.structured_text")) - end + if OpenProject::FeatureDecisions.recurring_meetings_active? + menu.with_item(label: I18n.t("meeting.types.one_time"), + tag: :a, + href: new_dialog_meetings_path(project_id: @project&.id, type: :structured), + content_arguments: { data: { controller: "async-dialog" }} + ) do |item| + item.with_description.with_content(t("meeting.types.structured_text")) + end - menu.with_item(label: I18n.t("meeting.types.recurring"), - tag: :a, - href: new_dialog_meetings_path(project_id: @project&.id, type: :recurring), - content_arguments: { data: { controller: "async-dialog" }} - ) do |item| - item.with_description.with_content(t("meeting.types.recurring_text")) + menu.with_item(label: I18n.t("meeting.types.recurring"), + tag: :a, + href: new_dialog_meetings_path(project_id: @project&.id, type: :recurring), + content_arguments: { data: { controller: "async-dialog" }} + ) do |item| + item.with_description.with_content(t("meeting.types.recurring_text")) + end + else + menu.with_item(label: I18n.t("meeting.types.structured"), + tag: :a, + href: new_dialog_meetings_path(project_id: @project&.id, type: :structured), + content_arguments: { data: { controller: "async-dialog" }} + ) do |item| + item.with_description.with_content(t("meeting.types.structured_text")) + end end menu.with_item(label: I18n.t("meeting.types.classic"), diff --git a/modules/meeting/app/menus/meetings/menu.rb b/modules/meeting/app/menus/meetings/menu.rb index cb5a9d328c86..f4990f3d626e 100644 --- a/modules/meeting/app/menus/meetings/menu.rb +++ b/modules/meeting/app/menus/meetings/menu.rb @@ -34,9 +34,9 @@ def initialize(params:, project: nil) def menu_items [ OpenProject::Menu::MenuGroup.new(header: nil, children: top_level_menu_items), - OpenProject::Menu::MenuGroup.new(header: I18n.t(:label_meeting_series), children: meeting_series_menu_items), + meeting_series_menu_group, OpenProject::Menu::MenuGroup.new(header: I18n.t(:label_involvement), children: involvement_sidebar_menu_items) - ] + ].compact end def top_level_menu_items @@ -49,7 +49,13 @@ def top_level_menu_items recurring_menu_item, menu_item(title: I18n.t(:label_all_meetings), query_params: { filters: all_filter }) - ] + ].compact + end + + def meeting_series_menu_group + return unless OpenProject::FeatureDecisions.recurring_meetings_active? + + OpenProject::Menu::MenuGroup.new(header: I18n.t(:label_meeting_series), children: meeting_series_menu_items) end def meeting_series_menu_items @@ -71,6 +77,8 @@ def meeting_series_menu_items end def recurring_menu_item + return unless OpenProject::FeatureDecisions.recurring_meetings_active? + recurring_filter = [{ type: { operator: "=", values: ["t"] } }].to_json menu_item(title: I18n.t("label_recurring_meeting_plural"), diff --git a/modules/meeting/app/models/queries/meetings/filters/recurring_filter.rb b/modules/meeting/app/models/queries/meetings/filters/recurring_filter.rb index 47f4e224d2eb..01279912b04d 100644 --- a/modules/meeting/app/models/queries/meetings/filters/recurring_filter.rb +++ b/modules/meeting/app/models/queries/meetings/filters/recurring_filter.rb @@ -37,6 +37,10 @@ def human_name I18n.t("label_recurring_meeting_part_of") end + def available? + OpenProject::FeatureDecisions.recurring_meetings_active? + end + def apply_to(query_scope) if allowed_values.first.intersect?(values) query_scope.recurring diff --git a/modules/meeting/config/locales/en.yml b/modules/meeting/config/locales/en.yml index 6c16dc89c19c..70a70868a327 100644 --- a/modules/meeting/config/locales/en.yml +++ b/modules/meeting/config/locales/en.yml @@ -206,7 +206,8 @@ en: types: classic: "Classic" classic_text: "Organize your meeting as a single formattable text agenda and protocol." - structured: "One-time" + structured: "Structured" + one_time: "One-time" recurring: "Recurring" recurring_text: "Create meeting series with dynamic template for each occurrence." structured_text: "Organize your meeting as a dynamic list of agenda items, optionally linking them to a work package." diff --git a/modules/meeting/spec/features/meetings_index_spec.rb b/modules/meeting/spec/features/meetings_index_spec.rb index d85160fe7d6c..d4350d0df2f9 100644 --- a/modules/meeting/spec/features/meetings_index_spec.rb +++ b/modules/meeting/spec/features/meetings_index_spec.rb @@ -262,7 +262,7 @@ def invite_to_meeting(meeting) meetings_page.expect_create_new_button end - it "allows creation of both types of meetings" do + it "allows creation of both types of meetings", with_flag: { recurring_meetings: true } do meetings_page.visit! meetings_page.expect_create_new_types diff --git a/modules/meeting/spec/features/recurring_meetings/recurring_meeting_create_spec.rb b/modules/meeting/spec/features/recurring_meetings/recurring_meeting_create_spec.rb index 088f06039396..001730311040 100644 --- a/modules/meeting/spec/features/recurring_meetings/recurring_meeting_create_spec.rb +++ b/modules/meeting/spec/features/recurring_meetings/recurring_meeting_create_spec.rb @@ -35,7 +35,8 @@ RSpec.describe "Recurring meetings creation", :js, - :with_cuprite do + :with_cuprite, + with_flag: { recurring_meetings: true } do include Components::Autocompleter::NgSelectAutocompleteHelpers shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) } diff --git a/modules/meeting/spec/features/recurring_meetings/recurring_meeting_crud_spec.rb b/modules/meeting/spec/features/recurring_meetings/recurring_meeting_crud_spec.rb index 4d4eda1669c7..25880aa37f37 100644 --- a/modules/meeting/spec/features/recurring_meetings/recurring_meeting_crud_spec.rb +++ b/modules/meeting/spec/features/recurring_meetings/recurring_meeting_crud_spec.rb @@ -35,7 +35,8 @@ RSpec.describe "Recurring meetings CRUD", :js, - :with_cuprite do + :with_cuprite, + with_flag: { recurring_meetings: true } do include Components::Autocompleter::NgSelectAutocompleteHelpers shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) } diff --git a/modules/meeting/spec/features/structured_meetings/structured_meeting_crud_spec.rb b/modules/meeting/spec/features/structured_meetings/structured_meeting_crud_spec.rb index 01e87ed8e85e..c762251f9a59 100644 --- a/modules/meeting/spec/features/structured_meetings/structured_meeting_crud_spec.rb +++ b/modules/meeting/spec/features/structured_meetings/structured_meeting_crud_spec.rb @@ -34,7 +34,8 @@ RSpec.describe "Structured meetings CRUD", :js, - :with_cuprite do + :with_cuprite, + with_flag: { recurring_meetings: true } do include Components::Autocompleter::NgSelectAutocompleteHelpers shared_let(:project) { create(:project, enabled_module_names: %w[meetings work_package_tracking]) }