Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/seeders/standard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ projects:
- board_view
- team_planner_view
- meetings
- documents
news:
- t_title: Welcome to your demo project
t_summary: |
Expand Down Expand Up @@ -389,6 +390,7 @@ projects:
- work_package_tracking
- gantt
- board_view
- documents
news:
- t_title: Welcome to your Scrum demo project
t_summary: |
Expand Down
14 changes: 12 additions & 2 deletions config/constants/settings/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,14 @@ class Definition
allowed: -> { Redmine::I18n.all_languages }
},
default_projects_modules: {
default: %w[calendar board_view work_package_tracking gantt news costs wiki],
default: -> {
base_modules = %w[calendar board_view work_package_tracking gantt news costs wiki]
if Setting.real_time_text_collaboration_enabled?
base_modules + %w[documents]
else
base_modules
end
},
allowed: -> { OpenProject::AccessControl.available_project_modules.map(&:to_s) }
},
default_projects_public: {
Expand Down Expand Up @@ -575,7 +582,10 @@ class Definition
},
real_time_text_collaboration_enabled: {
description: "Enable real-time collaborative editing of text fields using BlockNoteJS and Hocuspocus server.",
default: true
default: -> {
Setting.collaborative_editing_hocuspocus_url.present? &&
Setting.collaborative_editing_hocuspocus_secret.present?
}
},
collaborative_editing_hocuspocus_url: {
format: :string,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 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 AddDocumentsToDefaultProjectsModules < ActiveRecord::Migration[8.0]
def up
return unless Setting.exists?(:real_time_text_collaboration_enabled)
return unless Setting.real_time_text_collaboration_enabled?

# Only update if setting exists in DB (avoid updating on new installations - seeder handles that)
setting = Setting.find_by(name: "default_projects_modules")
return unless setting

current_modules = setting.value || []
return if current_modules.include?("documents")

Setting.default_projects_modules = current_modules + ["documents"]
end

def down
# No-op
end
end
2 changes: 2 additions & 0 deletions modules/bim/app/seeders/bim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ projects:
- wiki
- board_view
- team_planner_view
- documents
news:
- t_title: Welcome to your demo project
t_summary: |
Expand Down Expand Up @@ -395,6 +396,7 @@ projects:
- wiki
- board_view
- team_planner_view
- documents
news:
- t_title: Welcome to your demo project
t_summary: |
Expand Down
2 changes: 1 addition & 1 deletion modules/bim/spec/seeders/root_seeder_bim_edition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def group_name(reference)

it "creates the BIM demo data" do
expect(Project.count).to eq 4
expect(EnabledModule.count).to eq 27
expect(EnabledModule.count).to eq 29
expect(WorkPackage.count).to eq 76
expect(Wiki.count).to eq 3
expect(Query.count).to eq 29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,10 @@
end

describe "generate_oauth_token",
with_config: { collaborative_editing_hocuspocus_secret: "secret1234" } do
with_config: {
collaborative_editing_hocuspocus_url: "wss://hocuspocus.local",
collaborative_editing_hocuspocus_secret: "secret1234"
} do
let(:manage_role) { create(:project_role, permissions: %i[view_documents manage_documents]) }
let(:view_only_role) { create(:project_role, permissions: [:view_documents]) }
let(:user_with_manage) { create(:user) }
Expand Down
2 changes: 1 addition & 1 deletion modules/documents/spec/features/attachment_upload_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
end
end

context "for collaborative documents" do
context "for collaborative documents", with_settings: { real_time_text_collaboration_enabled: true } do
let(:document) { create(:document, project:) }
let(:editor) { FormFields::Primerized::BlockNoteEditorInput.new }
let(:attachments_list) { Components::AttachmentsList.new }
Expand Down
2 changes: 1 addition & 1 deletion modules/documents/spec/features/block_note_editor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

require "rails_helper"

RSpec.describe "BlockNote editor rendering", :js do
RSpec.describe "BlockNote editor rendering", :js, with_settings: { real_time_text_collaboration_enabled: true } do
let(:admin) { create(:admin) }
let(:type) { create(:document_type, :experimental) }
let(:document) { create(:document, type:) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

require "spec_helper"

RSpec.describe "Document collaboration settings admin", :js, :settings_reset do
RSpec.describe "Document collaboration settings admin",
:js,
:settings_reset do
include Flash::Expectations

current_user { create(:admin) }
Expand All @@ -39,6 +41,16 @@
it "can configure hocuspocus url and secret" do
visit admin_settings_document_collaboration_settings_path

within_test_selector("collaboration-settings-disabled-notice") do
expect(page).to have_heading("Real-time collaboration is not enabled")
expect(page).to have_content("Once enabled, multiple users will be able to work together on a " \
"document at the same time. All new documents will be based on a new " \
"editor (BlockNote) and will require a working connection to a Hocuspocus server.")
click_on "Enable real-time collaboration"
end

expect_and_dismiss_flash(message: "Real-time collaboration has been enabled.")

expect(page).to have_field("Hocuspocus server URL", with: "")
expect(page).to have_field("Client secret", with: "")

Expand Down Expand Up @@ -72,22 +84,12 @@
end

expect_and_dismiss_flash(message: "Real-time collaboration has been disabled.")

within_test_selector("collaboration-settings-disabled-notice") do
expect(page).to have_heading("Real-time collaboration is not enabled")
expect(page).to have_content("Once enabled, multiple users will be able to work together on a " \
"document at the same time. All new documents will be based on a new " \
"editor (BlockNote) and will require a working connection to a Hocuspocus server.")
click_on "Enable real-time collaboration"
end

expect_and_dismiss_flash(message: "Real-time collaboration has been enabled.")
expect(Setting.real_time_text_collaboration_enabled?).to be(true)
end
end

context "with hocuspocus url set via environment variable",
with_env: { "OPENPROJECT_COLLABORATIVE_EDITING_HOCUSPOCUS_URL" => "wss://env-hocuspocus.example.com" } do
with_env: { "OPENPROJECT_COLLABORATIVE_EDITING_HOCUSPOCUS_URL" => "wss://env-hocuspocus.example.com" },
with_settings: { collaborative_editing_hocuspocus_secret: "secret1234" } do
before do
reset(:collaborative_editing_hocuspocus_url)
visit admin_settings_document_collaboration_settings_path
Expand All @@ -99,11 +101,16 @@
expect(page).to have_field("Hocuspocus server URL",
with: "wss://env-hocuspocus.example.com",
disabled: true)

expect(page).to have_field("Client secret",
with: "",
disabled: false)
end
end

context "with secret set via environment variable",
with_env: { "OPENPROJECT_COLLABORATIVE_EDITING_HOCUSPOCUS_SECRET" => "envsupersecret" } do
with_env: { "OPENPROJECT_COLLABORATIVE_EDITING_HOCUSPOCUS_SECRET" => "envsupersecret" },
with_settings: { collaborative_editing_hocuspocus_url: "wss://env-hocuspocus.example.com" } do
before do
reset(:collaborative_editing_hocuspocus_secret)
visit admin_settings_document_collaboration_settings_path
Expand All @@ -112,6 +119,9 @@
it "shows the secret as read-only" do
expect(page).to have_content("Some values are configured via environment variables and cannot be edited here.")

expect(page).to have_field("Hocuspocus server URL",
with: "wss://env-hocuspocus.example.com",
disabled: false)
expect(page).to have_field("Client secret",
with: "",
disabled: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

current_user { manager }

context "for collaborative documents" do
context "for collaborative documents", with_settings: { real_time_text_collaboration_enabled: true } do
it "creates a new document via +Document buttons" do
index_page.visit!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
# rubocop:enable RSpec/AnyInstance
end

it "renders a collaborative document" do
it "renders a collaborative document",
with_settings: { real_time_text_collaboration_enabled: true } do
visit document_path(document)

expect(page).to have_content("Collaborative document")
Expand Down
2 changes: 1 addition & 1 deletion spec/constants/settings/definition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

described_class.add_all

expect(described_class.all.keys).to eq(described_class::DEFINITIONS.keys)
expect(described_class.all.keys).to match_array(described_class::DEFINITIONS.keys)
end

it "does not add any plugin/feature settings if they were removed for some reason" do
Expand Down
120 changes: 120 additions & 0 deletions spec/migrations/add_documents_to_default_projects_modules_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# 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.
#++

require "spec_helper"
require Rails.root.join("db/migrate/20260106151226_add_documents_to_default_projects_modules")

RSpec.describe AddDocumentsToDefaultProjectsModules, type: :model do
let(:base_modules) { %w[calendar board_view work_package_tracking gantt news costs wiki] }

before do
# Ensure a clean state
Setting.find_by(name: "default_projects_modules")&.destroy
Setting.clear_cache
end

context "when real_time_text_collaboration is enabled",
with_settings: { real_time_text_collaboration_enabled: true } do
context "when default_projects_modules setting exists in DB" do
before do
Setting.default_projects_modules = base_modules
end

it "adds documents to the default modules" do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

Setting.clear_cache
expect(Setting.default_projects_modules).to include("documents")
end

it "preserves existing modules" do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

Setting.clear_cache
expect(Setting.default_projects_modules).to include(*base_modules)
end

context "when documents is already in the default modules" do
before do
Setting.default_projects_modules = base_modules + ["documents"]
end

it "does not duplicate documents" do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

Setting.clear_cache
expect(Setting.default_projects_modules.count("documents")).to eq(1)
end
end
end

context "when default_projects_modules setting does not exist in DB" do
it "does not create the setting (seeder handles new installations)" do
expect(Setting.find_by(name: "default_projects_modules")).to be_nil

ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

# Setting should still not exist - seeder will handle it
expect(Setting.find_by(name: "default_projects_modules")).to be_nil
end
end
end

context "when real_time_text_collaboration is disabled",
with_settings: { real_time_text_collaboration_enabled: false } do
before do
Setting.default_projects_modules = base_modules
end

it "does not modify the default modules" do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

Setting.clear_cache
expect(Setting.default_projects_modules).not_to include("documents")
expect(Setting.default_projects_modules).to match_array(base_modules)
end
end

context "when real_time_text_collaboration_enabled setting does not exist" do
before do
Setting.default_projects_modules = base_modules
allow(Setting).to receive(:exists?).and_call_original
allow(Setting).to receive(:exists?).with(:real_time_text_collaboration_enabled).and_return(false)
end

it "does not modify the default modules" do
ActiveRecord::Migration.suppress_messages { described_class.migrate(:up) }

Setting.clear_cache
expect(Setting.default_projects_modules).not_to include("documents")
expect(Setting.default_projects_modules).to match_array(base_modules)
end
end
end
Loading
Loading