Add principal form

This commit is contained in:
Oliver Günther
2025-10-09 09:40:25 +02:00
parent 525d16d175
commit b5758175a0
4 changed files with 43 additions and 30 deletions
+19 -13
View File
@@ -31,16 +31,15 @@ class Users::InviteController < ApplicationController
include OpTurbo::ComponentStream
authorize_with_permission :manage_members, global: true
before_action :create_form_model, only: %i[start_dialog step]
def start_dialog
respond_with_dialog(
Users::Invitation::DialogComponent.new(@invitation)
Users::Invitation::DialogComponent.new(form_model)
)
end
def step
if @invitation.valid?
if form_model.valid?
respond_with_next_step
else
handle_errors_in_step
@@ -52,10 +51,10 @@ class Users::InviteController < ApplicationController
def handle_errors_in_step
case params[:step]
when "project"
replace_via_turbo_stream(component: Users::Invitation::ProjectStep::FormComponent.new(@invitation))
replace_via_turbo_stream(component: Users::Invitation::ProjectStep::FormComponent.new(form_model))
respond_with_turbo_streams
when "principal"
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(@invitation))
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(form_model))
respond_with_turbo_streams
else
render_400 message: "Invalid step"
@@ -65,8 +64,8 @@ class Users::InviteController < ApplicationController
def respond_with_next_step
case params[:step]
when "project"
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(@invitation))
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FooterComponent.new(@invitation))
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(form_model))
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FooterComponent.new(form_model))
respond_with_turbo_streams
when "principal"
create_invitation
@@ -76,23 +75,30 @@ class Users::InviteController < ApplicationController
end
def create_invitation
# TODO, handle invite by mail
call = Members::CreateService
project = Project.find_by(id: form_model.project_id)
call = Members::BulkCreateService
.new(user: current_user)
.call(form_model_params)
.call(
project:,
user_id: form_model.id_or_email,
role_ids: [form_model.role_id],
notification_message: form_model.message,
send_notification: true
)
if call.success?
close_dialog_via_turbo_stream("##{Users::Invitation::DialogComponent::DIALOG_ID}",
additional: {})
else
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(call.result))
replace_via_turbo_stream(component: Users::Invitation::PrincipalStep::FormComponent.new(form_model))
end
respond_with_turbo_streams
end
def create_form_model
@invitation = Users::Invitation::FormModel.new(form_model_params)
def form_model
@form_model ||= Users::Invitation::FormModel.new(form_model_params)
end
def form_model_params
@@ -30,33 +30,42 @@
module Users::Invitation::PrincipalStep
class Form < ApplicationForm
include OpenProject::StaticRouting::UrlHelpers
include Redmine::I18n
form do |f|
f.hidden name: :project_id
f.hidden name: :principal_type
f.autocompleter(
name: :id_or_email,
label: TimeEntry.human_attribute_name(:user),
required: true,
autocomplete_options: {
defaultData: true,
component: "opce-user-autocompleter",
url: ::API::V3::Utilities::PathHelper::ApiV3Path.principals,
searchKey: "any_name_attribute",
resource: "principals",
component: "opce-members-autocompleter",
url: autocomplete_for_member_project_members_path(model.project_id) + ".json",
focusDirectly: false,
multiple: false,
clearable: false,
appendTo: "##{Users::Invitation::DialogComponent::DIALOG_ID}",
appendTo: "##{Users::Invitation::DialogComponent::DIALOG_ID}"
}
)
f.select_list(
name: "role_id",
label: "Role",
caption: "This is the role..",
include_blank: true
) do |city_list|
city_list.option(label: "Lopez Island", value: "lopez_island")
city_list.option(label: "Bellevue", value: "bellevue")
city_list.option(label: "Seattle", value: "seattle")
caption: link_translate("users.invite_user_modal.role.description",
links: { docs_link: %i[sysadmin_docs roles_and_permissions] }),
include_blank: false,
required: true
) do |role_list|
ProjectRole
.givable
.ordered_by_builtin_and_position
.find_each do |role|
role_list.option(label: role.name, value: role.id)
end
end
end
end
+2 -6
View File
@@ -755,13 +755,9 @@ en:
role:
label: "Role in %{project}"
no_roles_found: "No roles were found"
description: >-
description: >
This is the role that the user will receive when they join your project. The role defines which actions they are allowed to take and which information they are allowed to see.
<a
href="https://www.openproject.org/docs/system-admin-guide/users-permissions/roles-permissions/#roles-and-permissions"
target="_blank">
Learn more about roles and permissions.
</a>
[Learn more about roles and permissions.](docs_url)
required: "Please select a role"
next_button: "Next"
+2
View File
@@ -171,6 +171,8 @@ storage_docs:
troubleshooting:
href: https://www.openproject.org/docs/user-guide/file-management/nextcloud-integration/#possible-errors-and-troubleshooting
sysadmin_docs:
roles_and_permissions:
href: https://www.openproject.org/docs/system-admin-guide/users-permissions/roles-permissions/#roles-and-permissions
ldap:
href: https://www.openproject.org/docs/system-admin-guide/authentication/ldap-connections/
oidc: