From 97ac9799b2f54c8352ef4d2eee57aabae4da253c Mon Sep 17 00:00:00 2001 From: Kabiru Mwenja Date: Mon, 24 Nov 2025 12:55:03 +0300 Subject: [PATCH] Add real-time collaboration settings admin form --- config/static_links.yml | 2 + .../page_header_component.html.erb | 45 +++++++++++++ .../page_header_component.rb | 55 +++++++++++++++ .../settings_form_component.html.erb | 67 +++++++++++++++++++ .../settings_form_component.rb | 57 ++++++++++++++++ ...ument_collaboration_settings_controller.rb | 41 ++++++++++++ .../index.html.erb | 36 ++++++++++ modules/documents/config/locales/en.yml | 18 +++++ modules/documents/config/routes.rb | 2 + .../lib/open_project/documents/engine.rb | 7 ++ 10 files changed, 330 insertions(+) create mode 100644 modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.html.erb create mode 100644 modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.rb create mode 100644 modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.html.erb create mode 100644 modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.rb create mode 100644 modules/documents/app/controllers/documents/admin/settings/document_collaboration_settings_controller.rb create mode 100644 modules/documents/app/views/documents/admin/settings/document_collaboration_settings/index.html.erb diff --git a/config/static_links.yml b/config/static_links.yml index 9b02fee002c..7f8c4f76242 100644 --- a/config/static_links.yml +++ b/config/static_links.yml @@ -90,6 +90,8 @@ glossary: label: homescreen.links.glossary github: href: https://github.com/opf/openproject +hocuspocus_server_docs: + href: https://github.com/opf/op-blocknote-hocuspocus ical_docs: href: https://www.openproject.org/docs/user-guide/calendar/#subscribe-to-a-calendar installation_guides: diff --git a/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.html.erb b/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.html.erb new file mode 100644 index 00000000000..988fd358fd2 --- /dev/null +++ b/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.html.erb @@ -0,0 +1,45 @@ +<%# + -- 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. + + ++# +%> + +<%= + render(Primer::OpenProject::PageHeader.new) do |header| + header.with_title { t("documents.menu.collaboration_settings") } + header.with_breadcrumbs( + [ + { href: admin_index_path, text: t("label_administration") }, + { href: admin_settings_document_collaboration_settings_path, text: t("project_module_documents") }, + t("documents.menu.collaboration_settings") + ] + ) + + header.with_description.with_content(description) + end +%> diff --git a/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.rb b/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.rb new file mode 100644 index 00000000000..ba235382a43 --- /dev/null +++ b/modules/documents/app/components/documents/admin/collaboration_settings/page_header_component.rb @@ -0,0 +1,55 @@ +# 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 Documents + module Admin + module CollaborationSettings + class PageHeaderComponent < ApplicationComponent + def description + I18n.t("documents.admin.collaboration_settings.page_header.description", hocuspocus_server_link:).html_safe + end + + def hocuspocus_server_link + render( + Primer::Beta::Link.new( + href: OpenProject::Static::Links.url_for(:hocuspocus_server_docs), + target: "_blank", + underline: true + ) + ) do |link| + link.with_trailing_visual_icon(icon: :"link-external") + I18n.t("documents.admin.collaboration_settings.hocuspocus_server") + end + end + end + end + end +end diff --git a/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.html.erb b/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.html.erb new file mode 100644 index 00000000000..d869e68e468 --- /dev/null +++ b/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.html.erb @@ -0,0 +1,67 @@ +<%# + -- 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. + + ++# +%> + +<%= + settings_primer_form_with(scope: :settings, action: :update, method: :patch) do |f| + render_inline_settings_form(f) do |form| + form.html_content do + if some_unwritable_settings? + render(Primer::Alpha::Banner.new(icon: :info)) do + I18n.t("documents.admin.collaboration_settings.banner.#{none_writable_settings? ? 'none_writable' : 'some_unwritable'}") + end + end + end + + form.text_field( + name: :collaborative_editing_hocuspocus_url, + label: I18n.t("documents.admin.collaboration_settings.hocuspocus_server_url.label"), + required: true, + input_width: :large, + caption: I18n.t("documents.admin.collaboration_settings.hocuspocus_server_url.caption"), + **disabled_setting_option(:collaborative_editing_hocuspocus_url) + ) + + form.text_field( + name: :collaborative_editing_hocuspocus_secret, + label: I18n.t("documents.admin.collaboration_settings.hocuspocus_server_secret.label"), + required: true, + input_width: :large, + caption: I18n.t("documents.admin.collaboration_settings.hocuspocus_server_secret.caption"), + type: :password, + value: nil, # IMPORTANT: Don't expose the secret in the form + placeholder: Setting.collaborative_editing_hocuspocus_secret.present? ? "••••••••••••••••" : nil, + **disabled_setting_option(:collaborative_editing_hocuspocus_secret) + ) + + form.submit + end + end +%> diff --git a/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.rb b/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.rb new file mode 100644 index 00000000000..cd88c1c4515 --- /dev/null +++ b/modules/documents/app/components/documents/admin/collaboration_settings/settings_form_component.rb @@ -0,0 +1,57 @@ +# 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 Documents + module Admin + module CollaborationSettings + class SettingsFormComponent < ApplicationComponent + include OpPrimer::FormHelpers + + delegate :disabled_setting_option, :writable_setting?, to: :helpers + + def none_writable_settings? + settings.none? { writable_setting?(it) } + end + + def some_unwritable_settings? + settings.any? { !writable_setting?(it) } + end + + private + + def settings + %i[collaborative_editing_hocuspocus_url + collaborative_editing_hocuspocus_secret] + end + end + end + end +end diff --git a/modules/documents/app/controllers/documents/admin/settings/document_collaboration_settings_controller.rb b/modules/documents/app/controllers/documents/admin/settings/document_collaboration_settings_controller.rb new file mode 100644 index 00000000000..7afc633623a --- /dev/null +++ b/modules/documents/app/controllers/documents/admin/settings/document_collaboration_settings_controller.rb @@ -0,0 +1,41 @@ +# 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 Documents + module Admin + module Settings + class DocumentCollaborationSettingsController < ::Admin::SettingsController + menu_item :document_collaboration_settings + + def index; end + end + end + end +end diff --git a/modules/documents/app/views/documents/admin/settings/document_collaboration_settings/index.html.erb b/modules/documents/app/views/documents/admin/settings/document_collaboration_settings/index.html.erb new file mode 100644 index 00000000000..c882f57f38a --- /dev/null +++ b/modules/documents/app/views/documents/admin/settings/document_collaboration_settings/index.html.erb @@ -0,0 +1,36 @@ +<%# + -- 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. + + ++# +%> + +<% html_title t(:label_administration), t("documents.menu.collaboration_settings") %> + +<%= render(Documents::Admin::CollaborationSettings::PageHeaderComponent.new) %> + +<%= render(Documents::Admin::CollaborationSettings::SettingsFormComponent.new) %> diff --git a/modules/documents/config/locales/en.yml b/modules/documents/config/locales/en.yml index d0195bfb48b..dea45ff8843 100644 --- a/modules/documents/config/locales/en.yml +++ b/modules/documents/config/locales/en.yml @@ -89,6 +89,7 @@ en: menu: all: "All documents" types: "Types" + collaboration_settings: "Real-time collaboration" last_updated_at: "Last updated %{time}." @@ -119,6 +120,23 @@ en: heading: Cannot delete the last document type message: There must always be at least one document type configured. Create another one first if you want to delete this one. + admin: + collaboration_settings: + page_header: + description: |- + When enabled, real-time collaboration allows multiple users to edit a document at the same time. + It requires a working %{hocuspocus_server_link} to function. + banner: + none_writable: These values are configured via environment variables and cannot be edited here. + some_unwritable: Some values are configured via environment variables and cannot be edited here. + hocuspocus_server_url: + label: "Hocuspocus server URL" + caption: "The address of the a working Hocuspocus server." + hocuspocus_server_secret: + label: "Client secret" + caption: "Paste the secret provided by the Hocuspocus server." + hocuspocus_server: Hocuspocus server + label_document_added: "Document added" label_document_new: "New document" label_document_plural: "Documents" diff --git a/modules/documents/config/routes.rb b/modules/documents/config/routes.rb index 0af6125ee65..2968c2c03f7 100644 --- a/modules/documents/config/routes.rb +++ b/modules/documents/config/routes.rb @@ -58,6 +58,8 @@ Rails.application.routes.draw do get :delete_dialog, defaults: { format: :turbo_stream } end end + + resources :document_collaboration_settings, only: [:index] end end end diff --git a/modules/documents/lib/open_project/documents/engine.rb b/modules/documents/lib/open_project/documents/engine.rb index 3549ef92b1a..59c6081af3e 100644 --- a/modules/documents/lib/open_project/documents/engine.rb +++ b/modules/documents/lib/open_project/documents/engine.rb @@ -81,6 +81,13 @@ module OpenProject::Documents caption: :"documents.menu.types", parent: :documents + menu :admin_menu, + :document_collaboration_settings, + { controller: "/documents/admin/settings/document_collaboration_settings", action: :index }, + if: ->(_) { User.current.admin? }, + caption: :"documents.menu.collaboration_settings", + parent: :documents + menu :admin_menu, :document_categories, { controller: "/admin/settings/document_categories", action: :index },