Merge pull request #23493 from opf/implementation/73350-add-search-wiki-page-dialog

[#73350] Use single selection tree view with search for page selection
This commit is contained in:
Eric Schubert
2026-06-03 15:03:23 +02:00
committed by GitHub
7 changed files with 169 additions and 14 deletions
@@ -28,11 +28,14 @@ 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 do
primer_form_with(**form_options) do |form|
render(Wikis::LinkExistingWikiPageForm.new(form))
<%
dialog.with_body(classes: "Overlay-body_autocomplete_height") do
primer_form_with(**form_options) do |form|
render(Wikis::LinkExistingWikiPageForm.new(form))
end
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)) { t("button_add") } %>
@@ -72,8 +72,17 @@ module Wikis
end
def relation_page_link_params
params.expect(wikis_relation_page_link: %i[identifier provider_id linkable_type linkable_id])
.merge(author_id: current_user.id)
params.expect(wikis_relation_page_link: %i[provider_id linkable_type linkable_id])
.merge(author_id: current_user.id, 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
def turbo_redirect_for_linkable(linkable)
@@ -0,0 +1,61 @@
# 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 SearchPagesController < ApplicationController
include Dry::Monads[:result]
# 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
def show
provider = Provider.visible.find(params.expect(:provider_id))
query = params[:query]
form_name = params[:name]
builder = ActionView::Helpers::FormBuilder.new("", nil, view_context, {})
search_result = search_pages(query, provider)
render layout: false, locals: { search_result:, builder:, name: form_name }
end
private
def search_pages(query, provider)
return Success([]) if query.blank?
Adapters::Input::SearchPages.build(query:).bind do |input_data|
provider.auth_strategy_for(current_user).bind do |auth_strategy|
provider.resolve("queries.search_pages").call(input_data:, auth_strategy:)
end
end
end
end
end
@@ -35,12 +35,37 @@ module Wikis
f.hidden(name: :linkable_type)
f.hidden(name: :linkable_id)
f.text_field(
name: :identifier,
label: RelationPageLink.human_attribute_name(:identifier),
required: true,
input_width: :large
)
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
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
end
end
@@ -0,0 +1,52 @@
<%#-- 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.
++#%>
<%=
search_result.either(
->(pages) do
render(
Primer::Alpha::TreeView.new(
form_arguments: { builder:, name: },
data: { target: "filterable-tree-view.treeViewList" }
)
) do |tree_view|
pages.each do |page|
tree_view.with_leaf(select_variant: :single, label: page.title, value: page.identifier) do |item|
item.with_leading_visual_icon(icon: :"op-file-doc")
end
end
end
end,
->(_failure) do
render(Primer::Alpha::TreeView.new(data: { target: "filterable-tree-view.treeViewList" })) do |tree_view|
tree_view.with_leaf(select_variant: :none, label: t("wikis.link_existing_wiki_page_dialog.no_results"))
end
end
)
%>
+5 -2
View File
@@ -64,11 +64,14 @@ en:
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
link_existing_wiki_page_dialog:
title: Add existing wiki page
page_links:
errors:
page_not_found: Linked wiki page no longer available
+2
View File
@@ -72,4 +72,6 @@ Rails.application.routes.draw do
resource :wiki_page_link_macro, controller: "wikis/page_link_macro", only: [] do
get :load
end
resource :search_wiki_pages, controller: "wikis/search_pages", only: %i[show]
end