mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Feature/send custom message from invite modal (#9222)
* fix malformed i18n key * sent custom message from invite modal * cleanup imports
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<%=
|
||||
I18n.t(:"mail_member_added_project.body.added_by#{@message.present? ? 'with_message' : 'without_message'}",
|
||||
I18n.t(:"mail_member_added_project.body.added_by.#{@message.present? ? 'with_message' : 'without_message'}",
|
||||
project: @project.name,
|
||||
user: User.current.name)
|
||||
%>
|
||||
|
||||
@@ -47,6 +47,11 @@ export class Apiv3MembershipsForm extends APIv3FormResource {
|
||||
project: { href: resource.project.href },
|
||||
principal: { href: resource.principal.href },
|
||||
roles: resource.roles.map(role => ({ href: role.href })),
|
||||
},
|
||||
_meta: {
|
||||
notificationMessage: {
|
||||
raw: resource.notificationMessage.raw
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,17 +34,9 @@ import {
|
||||
Apiv3ListResourceInterface, listParamsString
|
||||
} from "core-app/modules/apiv3/paths/apiv3-list-resource.interface";
|
||||
import {Observable} from "rxjs";
|
||||
import {HalResource} from "core-app/modules/hal/resources/hal-resource";
|
||||
import {CollectionResource} from "core-app/modules/hal/resources/collection-resource";
|
||||
import {MembershipResource, MembershipResourceEmbedded} from "core-app/modules/hal/resources/membership-resource";
|
||||
import {ProjectResource} from 'core-app/modules/hal/resources/project-resource';
|
||||
import {UserResource} from "core-app/modules/hal/resources/user-resource";
|
||||
import {GroupResource} from "core-app/modules/hal/resources/group-resource";
|
||||
import {PlaceholderUserResource} from "core-app/modules/hal/resources/placeholder-user-resource";
|
||||
import {RoleResource} from 'core-app/modules/hal/resources/role-resource';
|
||||
import {Apiv3MembershipsForm} from "core-app/modules/apiv3/endpoints/memberships/apiv3-memberships-form";
|
||||
import {SchemaResource} from "core-app/modules/hal/resources/schema-resource";
|
||||
import {map, switchMap} from "rxjs/operators";
|
||||
|
||||
|
||||
export class Apiv3MembershipsPaths
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
//++
|
||||
|
||||
import { HalResource } from 'core-app/modules/hal/resources/hal-resource';
|
||||
import { UserResource } from "core-app/modules/hal/resources/user-resource";
|
||||
import { RoleResource } from "core-app/modules/hal/resources/role-resource";
|
||||
import { ProjectResource } from "core-app/modules/hal/resources/project-resource";
|
||||
import Formattable = api.v3.Formattable;
|
||||
|
||||
export interface MembershipResourceLinks {
|
||||
update(payload:unknown):Promise<unknown>;
|
||||
@@ -41,6 +41,7 @@ export interface MembershipResourceEmbedded {
|
||||
principal:HalResource;
|
||||
roles:RoleResource[];
|
||||
project:ProjectResource;
|
||||
notificationMessage:Formattable;
|
||||
}
|
||||
|
||||
export class MembershipResource extends HalResource {
|
||||
|
||||
@@ -71,6 +71,9 @@ export class SummaryComponent {
|
||||
principal,
|
||||
project: this.project,
|
||||
roles: [this.role],
|
||||
notificationMessage: {
|
||||
raw: this.message
|
||||
}
|
||||
})
|
||||
.pipe(
|
||||
mapTo(principal)
|
||||
|
||||
+2
-2
@@ -57,9 +57,9 @@ declare namespace api {
|
||||
}
|
||||
|
||||
interface Formattable {
|
||||
format:string;
|
||||
format?:string;
|
||||
raw:string;
|
||||
html:string;
|
||||
html?:string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,21 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
|
||||
let(:permissions) { %i[view_work_packages edit_work_packages manage_members] }
|
||||
let(:global_permissions) { %i[] }
|
||||
let(:modal) do
|
||||
::Components::Users::InviteUserModal.new project: project,
|
||||
principal: principal,
|
||||
role: role,
|
||||
invite_message: invite_message
|
||||
end
|
||||
let!(:role) do
|
||||
FactoryBot.create :role,
|
||||
name: 'Member',
|
||||
permissions: permissions
|
||||
end
|
||||
let(:invite_message) { "Welcome to the team. **You'll like it here**."}
|
||||
let(:mail_membership_recipients) { [] }
|
||||
let(:mail_invite_recipients) { [] }
|
||||
|
||||
current_user do
|
||||
FactoryBot.create :user,
|
||||
member_in_project: project,
|
||||
@@ -42,21 +57,11 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
global_permissions: global_permissions
|
||||
end
|
||||
|
||||
let!(:role) do
|
||||
FactoryBot.create :role,
|
||||
name: 'Member',
|
||||
permissions: permissions
|
||||
end
|
||||
|
||||
let(:modal) do
|
||||
::Components::Users::InviteUserModal.new project: project,
|
||||
principal: principal,
|
||||
role: role
|
||||
end
|
||||
|
||||
shared_examples 'invites the principal to the project' do
|
||||
it 'will invite that principal to the project' do
|
||||
modal.run_all_steps
|
||||
it 'invites that principal to the project' do
|
||||
perform_enqueued_jobs do
|
||||
modal.run_all_steps
|
||||
end
|
||||
|
||||
assignee_field.expect_inactive!
|
||||
assignee_field.expect_display_value added_principal.name
|
||||
@@ -64,6 +69,32 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
new_member = project.reload.member_principals.find_by(user_id: added_principal.id)
|
||||
expect(new_member).to be_present
|
||||
expect(new_member.roles).to eq [role]
|
||||
|
||||
# Check that the expected number of emails are sent.
|
||||
# This includes no mails being sent if the recipient list is empty.
|
||||
expect(ActionMailer::Base.deliveries.size)
|
||||
.to eql mail_invite_recipients.size + mail_membership_recipients.size
|
||||
|
||||
mail_invite_recipients.each_with_index do |recipient, index|
|
||||
expect(ActionMailer::Base.deliveries[index].to)
|
||||
.to match_array [recipient.mail]
|
||||
|
||||
expect(ActionMailer::Base.deliveries[index].body.encoded)
|
||||
.to include "Welcome to OpenProject"
|
||||
end
|
||||
|
||||
mail_membership_recipients.each_with_index do |recipient, index|
|
||||
overall_index = index + mail_invite_recipients.length
|
||||
|
||||
expect(ActionMailer::Base.deliveries[overall_index].to)
|
||||
.to match_array [recipient.mail]
|
||||
|
||||
expect(ActionMailer::Base.deliveries[overall_index].body.encoded)
|
||||
.to include OpenProject::TextFormatting::Renderer.format_text(invite_message)
|
||||
|
||||
expect(ActionMailer::Base.deliveries[overall_index].body.encoded)
|
||||
.to include role.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -81,20 +112,15 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
end
|
||||
|
||||
context 'with an existing user' do
|
||||
let!(:principal) { FactoryBot.create :user,
|
||||
firstname: 'Nonproject firstname',
|
||||
lastname: 'nonproject lastname'
|
||||
}
|
||||
it 'can add an existing user to the project' do
|
||||
modal.run_all_steps
|
||||
let!(:principal) do
|
||||
FactoryBot.create :user,
|
||||
firstname: 'Nonproject firstname',
|
||||
lastname: 'nonproject lastname'
|
||||
end
|
||||
|
||||
assignee_field.expect_inactive!
|
||||
assignee_field.expect_display_value principal.name
|
||||
|
||||
# But the user got created
|
||||
new_member = project.reload.members.find_by(user_id: principal.id)
|
||||
expect(new_member).to be_present
|
||||
expect(new_member.roles).to eq [role]
|
||||
it_behaves_like 'invites the principal to the project' do
|
||||
let(:added_principal) { principal }
|
||||
let(:mail_membership_recipients) { [principal] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -107,6 +133,8 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
|
||||
it_behaves_like 'invites the principal to the project' do
|
||||
let(:added_principal) { User.find_by!(mail: principal.mail) }
|
||||
let(:mail_invite_recipients) { [added_principal] }
|
||||
let(:mail_membership_recipients) { [added_principal] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -114,7 +142,7 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
let(:permissions) { %i[view_work_packages edit_work_packages manage_members] }
|
||||
it 'does not show the invite user option' do
|
||||
modal.project_step
|
||||
ngselect = modal.open_select_in_step principal.mail
|
||||
ngselect = modal.open_select_in_step principal.mail
|
||||
expect(ngselect).to have_text "No users were found"
|
||||
expect(ngselect).not_to have_text "Invite: #{principal.mail}"
|
||||
end
|
||||
@@ -125,15 +153,17 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
let(:global_permissions) { %i[manage_user] }
|
||||
|
||||
let(:project_no_permissions) { FactoryBot.create :project }
|
||||
let(:role_no_permissions) { FactoryBot.create :role,
|
||||
permissions: %i[view_work_packages edit_work_packages]
|
||||
}
|
||||
let!(:membership_no_permission) {
|
||||
let(:role_no_permissions) do
|
||||
FactoryBot.create :role,
|
||||
permissions: %i[view_work_packages edit_work_packages]
|
||||
end
|
||||
|
||||
let!(:membership_no_permission) do
|
||||
FactoryBot.create :member,
|
||||
user: current_user,
|
||||
project: project_no_permissions,
|
||||
roles: [role_no_permissions]
|
||||
}
|
||||
user: current_user,
|
||||
project: project_no_permissions,
|
||||
roles: [role_no_permissions]
|
||||
end
|
||||
|
||||
it 'disables projects for which you do not have rights' do
|
||||
ngselect = modal.open_select_in_step
|
||||
@@ -153,6 +183,8 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
|
||||
it_behaves_like 'invites the principal to the project' do
|
||||
let(:added_principal) { PlaceholderUser.find_by!(name: 'MY NEW PLACEHOLDER') }
|
||||
# Placeholders get no invite mail
|
||||
let(:mail_membership_recipients) { [] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -173,6 +205,8 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
|
||||
it_behaves_like 'invites the principal to the project' do
|
||||
let(:added_principal) { principal }
|
||||
# Placeholders get no invite mail
|
||||
let(:mail_membership_recipients) { [] }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -187,10 +221,13 @@ feature 'Invite user modal', type: :feature, js: true do
|
||||
end
|
||||
|
||||
describe 'inviting groups' do
|
||||
let(:principal) { FactoryBot.create :group, name: 'MY NEW GROUP' }
|
||||
let(:group_user) { FactoryBot.create(:user) }
|
||||
let(:principal) { FactoryBot.create :group, name: 'MY NEW GROUP', members: [group_user] }
|
||||
|
||||
it_behaves_like 'invites the principal to the project' do
|
||||
let(:added_principal) { principal }
|
||||
# Groups get no invite mail themselves but their members do
|
||||
let(:mail_membership_recipients) { [group_user] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user