diff --git a/config/locales/en.yml b/config/locales/en.yml index 0dfcf46bfcc..9f04107cee8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2945,6 +2945,7 @@ en: button_login: "Sign in" button_move: "Move" button_move_and_follow: "Move and follow" + button_next: "Next" button_print: "Print" button_quote: "Quote" button_remove: Remove diff --git a/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.html.erb b/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.html.erb new file mode 100644 index 00000000000..90556381cc1 --- /dev/null +++ b/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.html.erb @@ -0,0 +1,47 @@ +<%#-- 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::Alpha::Dialog.new(id:, title: t(".title"), size: :large, **system_arguments)) do |dialog| %> + <% + dialog.with_body(classes: "Overlay-body_autocomplete_height") do + primer_form_with(**form_options) do |form| + render(::Wikis::CreateNewWikiPageForm.new(form)) + end + end + %> + + <% dialog.with_footer do %> + <%= render(Primer::Beta::Button.new(data: { "close-dialog-id": id })) { t(:button_cancel) } %> + <%= + render(Primer::Beta::Button.new(scheme: :primary, form: form_id, type: :submit)) do + show_first_step? ? t(:button_next) : t(:button_add) + end + %> + <% end %> +<% end %> diff --git a/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.rb b/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.rb new file mode 100644 index 00000000000..ca9ff5331fa --- /dev/null +++ b/modules/wikis/app/components/wikis/create_new_wiki_page_dialog.rb @@ -0,0 +1,66 @@ +# 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 Wikis + class CreateNewWikiPageDialog < ApplicationComponent + include OpTurbo::Streamable + + def id = "create-new-wiki-page-dialog" + + def form_id = "#{id}-form" + + def show_first_step? + model.page_title.blank? + end + + def form_options + if show_first_step? + { + id: form_id, + model:, + method: :get, + url: create_new_page_dialog_wiki_pages_path, + data: { turbo_stream: true } + } + else + { + id: form_id, + model:, + url: create_and_link_wiki_pages_path, + data: { turbo_frame: WorkPackageWikisTabComponent::TURBO_FRAME_ID } + } + end + end + + def system_arguments + options + end + end +end diff --git a/modules/wikis/app/components/wikis/relation_page_links_component.html.erb b/modules/wikis/app/components/wikis/relation_page_links_component.html.erb index bdbb740acae..fc01ecf67e8 100644 --- a/modules/wikis/app/components/wikis/relation_page_links_component.html.erb +++ b/modules/wikis/app/components/wikis/relation_page_links_component.html.erb @@ -52,7 +52,9 @@ See COPYRIGHT and LICENSE files for more details. ) menu.with_item( label: t(".link_new"), - disabled: true # work in progress + tag: :a, + href: create_new_page_dialog_wiki_pages_path(create_new_page_parameters), + content_arguments: { data: { controller: "async-dialog" } } ) end end diff --git a/modules/wikis/app/components/wikis/relation_page_links_component.rb b/modules/wikis/app/components/wikis/relation_page_links_component.rb index bd9fe9f2cd3..6f1556eb437 100644 --- a/modules/wikis/app/components/wikis/relation_page_links_component.rb +++ b/modules/wikis/app/components/wikis/relation_page_links_component.rb @@ -50,6 +50,16 @@ module Wikis provider.user_connected?(User.current) end + def create_new_page_parameters + { + wikis_forms_create_new_wiki_page_form_model: { + linkable_id: work_package.id, + linkable_type: work_package.class.name, + provider_id: provider.id + } + } + end + private def page_link_service diff --git a/modules/wikis/app/controllers/wikis/search_pages_controller.rb b/modules/wikis/app/controllers/wikis/pages_controller.rb similarity index 59% rename from modules/wikis/app/controllers/wikis/search_pages_controller.rb rename to modules/wikis/app/controllers/wikis/pages_controller.rb index 636d2f1338b..d1c94680813 100644 --- a/modules/wikis/app/controllers/wikis/search_pages_controller.rb +++ b/modules/wikis/app/controllers/wikis/pages_controller.rb @@ -29,14 +29,34 @@ #++ module Wikis - class SearchPagesController < ApplicationController + class PagesController < ApplicationController + include OpTurbo::ComponentStream include Dry::Monads[:result] + before_action :authorize, except: %i[search] + # The search is project independent and thus permission independent. The user will see results according to # the permissions set in each wiki. - no_authorization_required! :show + no_authorization_required! :search - def show + def create_and_link + # TODO: implement service to create page and link + render_error_flash_message_via_turbo_stream( + message: "Not implemented yet. Trying to create a new page with #{create_new_page_params.to_h}" + ) + respond_to_with_turbo_streams + end + + def create_new_page_dialog + params = create_new_page_params + form_object = Forms::CreateNewWikiPageFormModel.new(linkable_id: params[:linkable_id], + linkable_type: params[:linkable_type], + provider_id: params[:provider_id], + page_title: params[:page_title]) + respond_with_dialog Wikis::CreateNewWikiPageDialog.new(form_object) + end + + def search provider = Provider.visible.find(params.expect(:provider_id)) query = params[:query] form_name = params[:name] @@ -57,5 +77,19 @@ module Wikis end end end + + def create_new_page_params + params.expect(wikis_forms_create_new_wiki_page_form_model: %i[provider_id linkable_type linkable_id page_title]) + .merge(parent_page_identifier: parse_identifier(params[:wiki_page_selection])) + end + + def parse_identifier(wiki_page_selection) + case wiki_page_selection + in [selected_page] + MultiJson.load(selected_page, symbolize_keys: true)[:value] + else + nil + end + end end end diff --git a/modules/wikis/app/forms/wikis/create_new_wiki_page_form.rb b/modules/wikis/app/forms/wikis/create_new_wiki_page_form.rb new file mode 100644 index 00000000000..e0f2791a84f --- /dev/null +++ b/modules/wikis/app/forms/wikis/create_new_wiki_page_form.rb @@ -0,0 +1,85 @@ +# 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 Wikis + class CreateNewWikiPageForm < ApplicationForm + form do |f| + f.hidden(name: :provider_id) + f.hidden(name: :linkable_type) + f.hidden(name: :linkable_id) + + if first_step? + f.text_field(name: :page_title, label: I18n.t("wikis.create_new_wiki_page_dialog.page_title"), required: true) + else + f.hidden(name: :page_title) + + f.html_content do + render(Primer::Beta::Text.new) { I18n.t("wikis.create_new_wiki_page_dialog.parent_help_text") } + end + + f.html_content do + render( + Primer::OpenProject::FilterableTreeView.new( + src: helpers.search_wiki_pages_path(provider_id: model.provider_id, name: "wiki_page_selection"), + form_arguments: { builder: rails_builder(f), name: "wiki_page_selection" }, + filter_mode_control_arguments: { hidden: true }, + filter_input_arguments: { + placeholder: I18n.t("wikis.link_existing_wiki_page_form.placeholder"), + # every other property is just refilling the default values, + # as those are not merged into custom arguments + name: :filter, + label: I18n.t(:button_filter), + type: :search, + leading_visual: { icon: :search }, + visually_hide_label: true, + show_clear_button: true + }, + include_sub_items_check_box_arguments: { hidden: true }, + no_results_node_arguments: { label: I18n.t("wikis.link_existing_wiki_page_form.no_results") } + ) + ) + end + end + end + + private + + # Primer's FormObject stores the underlying ActionView/Primer form builder + # as @builder. FilterableTreeView requires an ActionView::FormBuilder to + # generate its hidden form inputs via hidden_field. + def rails_builder(form) + form.instance_variable_get(:@builder) + end + + def first_step? + model.page_title.blank? + end + end +end diff --git a/modules/wikis/app/models/wikis/forms/create_new_wiki_page_form_model.rb b/modules/wikis/app/models/wikis/forms/create_new_wiki_page_form_model.rb new file mode 100644 index 00000000000..d3553a24aa4 --- /dev/null +++ b/modules/wikis/app/models/wikis/forms/create_new_wiki_page_form_model.rb @@ -0,0 +1,46 @@ +# 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 Wikis + module Forms + class CreateNewWikiPageFormModel + extend ActiveModel::Naming + + attr_reader :linkable_id, :linkable_type, :provider_id, :page_title + + def initialize(linkable_id:, linkable_type:, provider_id:, page_title:) + @linkable_id = linkable_id + @linkable_type = linkable_type + @provider_id = provider_id + @page_title = page_title + end + end + end +end diff --git a/modules/wikis/app/views/wikis/search_pages/show.html.erb b/modules/wikis/app/views/wikis/pages/search.html.erb similarity index 100% rename from modules/wikis/app/views/wikis/search_pages/show.html.erb rename to modules/wikis/app/views/wikis/pages/search.html.erb diff --git a/modules/wikis/config/locales/en.yml b/modules/wikis/config/locales/en.yml index be289ec942f..81e621a8935 100644 --- a/modules/wikis/config/locales/en.yml +++ b/modules/wikis/config/locales/en.yml @@ -34,67 +34,13 @@ en: permission_manage_wiki_page_links: Manage Wiki Page Links project_module_wiki_platforms: Wiki providers wikis: - buttons: - connect_account: Connect %{provider} account - done_continue: Done, continue - open_wiki: Open wiki - save_and_continue: Save and continue - wiki_page: Wiki page - instructions: - xwiki: - integration: XWiki Administration - oauth_application_details_html: The client secret value will not be accessible again after you close this window. Please copy these values into the [XWiki OpenProject Integration settings](xwiki_admin_link). - provider_types: - xwiki: - name: XWiki - delete_relation_page_link_confirmation_dialog: - title: Delete related wiki page link - heading: Delete related wiki page link? - health_checks: - authentication: - existing_token: User token - header: Authentication - user_bound_request: User-based request authentication - base_configuration: - header: Configuration - provider_configured: Configuration complete - errors: - not_configured: The connection could not be validated. Please finish configuration first. - xwiki_oauth_connection_error: OpenProject could not connect to the configured XWiki instance. - xwiki_oauth_request_error: An unexpected error occured when trying to communicate with the XWiki instance. - xwiki_oauth_token_missing: OpenProject cannot test the user-level communication with XWiki as the user did not yet connect their XWiki account. - xwiki_oauth_unauthorized: The user token was not recognized by XWiki. - link_existing_wiki_page_dialog: - title: Add existing wiki page - link_existing_wiki_page_form: - no_results: No wiki pages found - placeholder: Search for a wiki page - work_package_wikis_tab_component: - inline_page_links: Inline page links - referencing_pages: Referenced in - page_links: - errors: - page_not_found: Linked wiki page no longer available - page_access_forbidden: You do not have permission to access this wiki page - unexpected: An unexpected error occurred - page_link_component: - remove: Remove page link - relation_page_links_component: - link_existing: Existing wiki page - link_new: New wiki page - empty_heading: No related pages - empty_text: Manually add links to other related wiki pages. - oauth_login_component: - heading: Not connected to %{provider} - description: Log in to %{provider} to view and manage related wiki pages from this OpenProject instance. - connect_button: Connect %{provider} account admin: destroy_confirmation_dialog_component: - title: Delete wiki provider - heading: Permanently delete this wiki provider? description_html: >- The wiki provider %{wiki_provider} and all the related wiki page links will be deleted. In addition, every inline wiki page link will no longer be accessible. This action is irreversible. + heading: Permanently delete this wiki provider? + title: Delete wiki provider forms: general_info_form_component: provider_description: Please make sure you have administration privileges in your XWiki instance before doing the setup. @@ -160,3 +106,61 @@ en: openproject_oauth_description: Allow XWiki to access OpenProject data using an OAuth. xwiki_oauth: XWiki OAuth xwiki_oauth_description: Allow OpenProject to access XWiki data using an OAuth. + buttons: + connect_account: Connect %{provider} account + done_continue: Done, continue + open_wiki: Open wiki + save_and_continue: Save and continue + wiki_page: Wiki page + create_new_wiki_page_dialog: + page_title: Title + parent_help_text: Select a parent for this new wiki page. + title: Create new wiki page + delete_relation_page_link_confirmation_dialog: + heading: Delete related wiki page link? + title: Delete related wiki page link + health_checks: + authentication: + existing_token: User token + header: Authentication + user_bound_request: User-based request authentication + base_configuration: + header: Configuration + provider_configured: Configuration complete + errors: + not_configured: The connection could not be validated. Please finish configuration first. + xwiki_oauth_connection_error: OpenProject could not connect to the configured XWiki instance. + xwiki_oauth_request_error: An unexpected error occured when trying to communicate with the XWiki instance. + xwiki_oauth_token_missing: OpenProject cannot test the user-level communication with XWiki as the user did not yet connect their XWiki account. + xwiki_oauth_unauthorized: The user token was not recognized by XWiki. + instructions: + xwiki: + integration: XWiki Administration + oauth_application_details_html: The client secret value will not be accessible again after you close this window. Please copy these values into the [XWiki OpenProject Integration settings](xwiki_admin_link). + link_existing_wiki_page_dialog: + title: Add existing wiki page + link_existing_wiki_page_form: + no_results: No wiki pages found + placeholder: Search for a wiki page + oauth_login_component: + connect_button: Connect %{provider} account + description: Log in to %{provider} to view and manage related wiki pages from this OpenProject instance. + heading: Not connected to %{provider} + page_link_component: + remove: Remove page link + page_links: + errors: + page_access_forbidden: You do not have permission to access this wiki page + page_not_found: Linked wiki page no longer available + unexpected: An unexpected error occurred + provider_types: + xwiki: + name: XWiki + relation_page_links_component: + empty_heading: No related pages + empty_text: Manually add links to other related wiki pages. + link_existing: Existing wiki page + link_new: New wiki page + work_package_wikis_tab_component: + inline_page_links: Inline page links + referencing_pages: Referenced in diff --git a/modules/wikis/config/routes.rb b/modules/wikis/config/routes.rb index 242e3c63458..f4f4fb3c95e 100644 --- a/modules/wikis/config/routes.rb +++ b/modules/wikis/config/routes.rb @@ -73,5 +73,9 @@ Rails.application.routes.draw do get :load end - resource :search_wiki_pages, controller: "wikis/search_pages", only: %i[show] + resource :wiki_pages, controller: "wikis/pages", only: [] do + get :search + get :create_new_page_dialog + post :create_and_link + end end diff --git a/modules/wikis/lib/open_project/wikis/engine.rb b/modules/wikis/lib/open_project/wikis/engine.rb index c0818091d09..351b8e77dc8 100644 --- a/modules/wikis/lib/open_project/wikis/engine.rb +++ b/modules/wikis/lib/open_project/wikis/engine.rb @@ -74,7 +74,11 @@ module OpenProject::Wikis project_module :work_package_tracking do permission :manage_wiki_page_links, { - "wikis/relation_page_links": %i[create destroy confirm_delete_dialog link_existing_dialog] + "wikis/pages": %i[create_and_link create_new_page_dialog], + "wikis/relation_page_links": %i[create + destroy + confirm_delete_dialog + link_existing_dialog] }, permissible_on: :project, dependencies: %i[edit_work_packages],