mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
[#71305] Introduce MODULE_ENABLED event and use it for backlogs
This commit is contained in:
@@ -54,6 +54,8 @@ class EnabledModule < ApplicationRecord
|
||||
create_managed_repository
|
||||
end
|
||||
end
|
||||
|
||||
OpenProject::Notifications.send(OpenProject::Events::MODULE_ENABLED, enabled_module: self)
|
||||
end
|
||||
|
||||
def create_managed_repository
|
||||
|
||||
@@ -80,6 +80,7 @@ module OpenProject
|
||||
WATCHER_ADDED = "watcher_added"
|
||||
WATCHER_DESTROYED = "watcher_destroyed"
|
||||
|
||||
MODULE_ENABLED = "module_enabled"
|
||||
MODULE_DISABLED = "module_disabled"
|
||||
|
||||
WORK_PACKAGE_SHARED = "work_package_shared"
|
||||
|
||||
@@ -130,8 +130,7 @@ module OpenProject::Backlogs
|
||||
|
||||
patches %i[PermittedParams
|
||||
WorkPackage
|
||||
Project
|
||||
EnabledModule]
|
||||
Project]
|
||||
|
||||
patch_with_namespace :BasicData, :SettingSeeder
|
||||
patch_with_namespace :Projects, :CopyService
|
||||
@@ -193,6 +192,29 @@ module OpenProject::Backlogs
|
||||
|
||||
initializer "openproject_backlogs.event_subscriptions" do
|
||||
Rails.application.config.after_initialize do
|
||||
# When the backlogs module is first enabled on a project, automatically populate
|
||||
# the project's done_statuses with all statuses that are globally marked as closed
|
||||
# (is_closed: true). This mirrors the form behavior where these statuses are
|
||||
# pre-selected and disabled, so users never have to visit the settings page just
|
||||
# to get sensible defaults.
|
||||
OpenProject::Notifications.subscribe(OpenProject::Events::MODULE_ENABLED) do |payload|
|
||||
enabled_module = payload[:enabled_module]
|
||||
next unless enabled_module.name == "backlogs"
|
||||
|
||||
project = enabled_module.project
|
||||
next unless project
|
||||
|
||||
mandatory_ids = Status.where(is_closed: true).pluck(:id)
|
||||
next if mandatory_ids.empty?
|
||||
|
||||
merged_ids = project.done_statuses.reorder(nil).pluck(:id) | mandatory_ids
|
||||
|
||||
project.class.transaction do
|
||||
project.done_statuses = [] # explicit clearing is necessary due to HABTM cache behavior
|
||||
project.done_statuses = Status.where(id: merged_ids)
|
||||
end
|
||||
end
|
||||
|
||||
OpenProject::Notifications.subscribe(OpenProject::Events::MODULE_DISABLED) do |payload|
|
||||
disabled_module = payload[:disabled_module]
|
||||
next unless disabled_module.name == "backlogs"
|
||||
|
||||
@@ -1,59 +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.
|
||||
#++
|
||||
|
||||
module OpenProject::Backlogs::Patches::EnabledModulePatch
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :seed_backlogs_done_statuses, if: -> { name == "backlogs" }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# When the backlogs module is first enabled on a project, automatically populate
|
||||
# the project's done_statuses with all statuses that are globally marked as closed
|
||||
# (is_closed: true). This mirrors the form behavior where these statuses are
|
||||
# pre-selected and disabled, so users never have to visit the settings page just
|
||||
# to get sensible defaults.
|
||||
def seed_backlogs_done_statuses # rubocop:disable Metrics/AbcSize
|
||||
return unless project
|
||||
|
||||
mandatory_ids = Status.where(is_closed: true).pluck(:id)
|
||||
return if mandatory_ids.empty?
|
||||
|
||||
merged_ids = (project.done_statuses.reorder(nil).pluck(:id) | mandatory_ids)
|
||||
|
||||
# Normalize the HABTM association explicitly by clearing and setting it:
|
||||
project.class.transaction do
|
||||
project.done_statuses = [] # This explicit clearing is necessary for some weird reason
|
||||
project.done_statuses = Status.where(id: merged_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -195,7 +195,7 @@ RSpec.describe "Start and finish sprints", :js do
|
||||
before do
|
||||
# closed_status is a lazy `let` created after the shared_let(:project), so
|
||||
# it is not present when the backlogs module is first enabled on the project
|
||||
# and therefore not auto-seeded by EnabledModulePatch. We add it manually here.
|
||||
# and therefore not auto-seeded by the MODULE_ENABLED event. We add it manually here.
|
||||
project.done_statuses << closed_status unless project.done_statuses.include?(closed_status)
|
||||
end
|
||||
|
||||
|
||||
+2
-2
@@ -30,12 +30,12 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe OpenProject::Backlogs::Patches::EnabledModulePatch do # rubocop:disable RSpec/SpecFilePathFormat
|
||||
RSpec.describe "Backlogs MODULE_ENABLED event" do # rubocop:disable RSpec/DescribeClass
|
||||
let!(:closed_status1) { create(:status, is_closed: true) }
|
||||
let!(:closed_status2) { create(:status, is_closed: true) }
|
||||
let!(:open_status) { create(:status, is_closed: false) }
|
||||
|
||||
describe "seed_backlogs_done_statuses callback" do
|
||||
describe "seeding done_statuses on backlogs module enable" do
|
||||
context "when the backlogs module is enabled on a project" do
|
||||
it "seeds all is_closed statuses as done_statuses for the project" do
|
||||
project = create(:project, enabled_module_names: %w[backlogs work_package_tracking])
|
||||
@@ -34,6 +34,40 @@ RSpec.describe EnabledModule do
|
||||
# Force reload, as association is not always(?) showing
|
||||
let(:project) { create(:project, enabled_module_names: modules).reload }
|
||||
|
||||
describe "MODULE_ENABLED event" do
|
||||
let(:modules) { [] }
|
||||
|
||||
it "fires the event when a module is added" do
|
||||
project # force evaluation before the stub is set up
|
||||
|
||||
allow(OpenProject::Notifications)
|
||||
.to receive(:send)
|
||||
.with(OpenProject::Events::MODULE_ENABLED, enabled_module: anything)
|
||||
|
||||
project.enabled_module_names = ["wiki"]
|
||||
|
||||
expect(OpenProject::Notifications)
|
||||
.to have_received(:send)
|
||||
.with(OpenProject::Events::MODULE_ENABLED, enabled_module: anything)
|
||||
.once
|
||||
end
|
||||
|
||||
it "does not fire the event when removing a module" do
|
||||
project.enabled_module_names = ["wiki"]
|
||||
|
||||
allow(OpenProject::Notifications).to receive(:send).and_call_original # Consume journal events
|
||||
allow(OpenProject::Notifications)
|
||||
.to receive(:send)
|
||||
.with(OpenProject::Events::MODULE_ENABLED, enabled_module: anything)
|
||||
|
||||
project.enabled_module_names = []
|
||||
|
||||
expect(OpenProject::Notifications)
|
||||
.not_to have_received(:send)
|
||||
.with(OpenProject::Events::MODULE_ENABLED, enabled_module: anything)
|
||||
end
|
||||
end
|
||||
|
||||
describe "MODULE_DISABLED event" do
|
||||
let(:modules) { %w[wiki] }
|
||||
|
||||
@@ -55,13 +89,16 @@ RSpec.describe EnabledModule do
|
||||
it "does not fire the event when creating a module" do
|
||||
project.enabled_module_names = []
|
||||
|
||||
allow(OpenProject::Notifications).to receive(:send).and_call_original
|
||||
allow(OpenProject::Notifications)
|
||||
.to receive(:send)
|
||||
.with(OpenProject::Events::MODULE_DISABLED, disabled_module: anything)
|
||||
|
||||
project.enabled_module_names = ["wiki"]
|
||||
|
||||
expect(OpenProject::Notifications).not_to have_received(:send)
|
||||
expect(OpenProject::Notifications)
|
||||
.not_to have_received(:send)
|
||||
.with(OpenProject::Events::MODULE_DISABLED, disabled_module: anything)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user