diff --git a/app/controllers/project_comments_controller.rb b/app/controllers/project_comments_controller.rb index 03b4e22e4..b0d789c00 100644 --- a/app/controllers/project_comments_controller.rb +++ b/app/controllers/project_comments_controller.rb @@ -51,17 +51,7 @@ class ProjectCommentsController < ApplicationController respond_to do |format| if @comment.save project_comment_annotation_notification - # Generate activity - Activity.create( - type_of: :add_comment_to_project, - user: current_user, - project: @project, - message: t( - 'activities.add_comment_to_project', - user: current_user.full_name, - project: @project.name - ) - ) + log_activity(:add_comment_to_project) format.json { render json: { @@ -107,19 +97,9 @@ class ProjectCommentsController < ApplicationController respond_to do |format| format.json do if @comment.save - project_comment_annotation_notification(old_text) - # Generate activity - Activity.create( - type_of: :edit_project_comment, - user: current_user, - project: @project, - message: t( - 'activities.edit_project_comment', - user: current_user.full_name, - project: @project.name - ) - ) + log_activity(:edit_project_comment) + message = custom_auto_link(@comment.message, team: current_team) render json: { comment: message }, status: :ok else @@ -134,17 +114,8 @@ class ProjectCommentsController < ApplicationController respond_to do |format| format.json do if @comment.destroy - # Generate activity - Activity.create( - type_of: :delete_project_comment, - user: current_user, - project: @project, - message: t( - 'activities.delete_project_comment', - user: current_user.full_name, - project: @project.name - ) - ) + log_activity(:delete_project_comment) + # 'counter' and 'linked_id' are used for counter badge render json: { linked_id: @project.id, counter: @project.project_comments.count }, @@ -198,4 +169,14 @@ class ProjectCommentsController < ApplicationController project: link_to(@project.name, project_url(@project))) ) end + + def log_activity(type_of) + Activities::CreateActivityService + .call(activity_type: type_of, + owner: current_user, + subject: @project, + team: @project.team, + project: @project, + message_items: { project: @project.id }) + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index eac0a39af..e171cf911 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -102,14 +102,7 @@ class ProjectsController < ApplicationController project: @project ) up.save - - Activities::CreateActivityService - .call(activity_type: :create_project, - owner: current_user, - subject: @project, - team: @project.team, - project: @project, - message_items: { project: @project.id }) + log_activity(:create_project) message = t('projects.create.success_flash', name: @project.name) respond_to do |format| @@ -164,43 +157,32 @@ class ProjectsController < ApplicationController message_visibility = nil if (project_params.include? :name) && (project_params[:name] != @project.name) - message_renamed = t( - 'activities.rename_project', - user: current_user.full_name, - project_old: @project.name, - project_new: project_params[:name] - ) + message_renamed = true end if (project_params.include? :visibility) && (project_params[:visibility] != @project.visibility) - message_visibility = t( - 'activities.change_project_visibility', - user: current_user.full_name, - project: @project.name, - visibility: project_params[:visibility] == "visible" ? - t("general.public") : - t("general.private") - ) + message_visibility = if project_params[:visibility] == 'visible' + t('projects.activity.visibility_visible') + else + t('projects.activity.visibility_hidden') + end end @project.last_modified_by = current_user if !return_error && @project.update(project_params) # Add activities if needed if message_visibility.present? - Activity.create( - type_of: :change_project_visibility, - user: current_user, - project: @project, - message: message_visibility - ) + Activities::CreateActivityService + .call(activity_type: :change_project_visibility, + owner: current_user, + subject: @project, + team: @project.team, + project: @project, + message_items: { project: @project.id, + visibility: message_visibility }) end if message_renamed.present? - Activity.create( - type_of: :rename_project, - owner: current_user, - project: @project, - message: message_renamed - ) + log_activity(:rename_project) end flash_success = t('projects.update.success_flash', name: @project.name) @@ -216,34 +198,12 @@ class ProjectsController < ApplicationController # The project should be restored unless @project.archived @project.restore(current_user) - - # "Restore project" activity - Activity.create( - type_of: :restore_project, - user: current_user, - project: @project, - message: t( - 'activities.restore_project', - user: current_user.full_name, - project: @project.name - ) - ) + log_activity(:restore_project) end elsif @project.archived # The project should be archived @project.archive(current_user) - - # "Archive project" activity - Activity.create( - type_of: :archive_project, - user: current_user, - project: @project, - message: t( - 'activities.archive_project', - user: current_user.full_name, - project: @project.name - ) - ) + log_activity(:archive_project) end redirect_to projects_path flash[:success] = flash_success @@ -388,4 +348,14 @@ class ProjectsController < ApplicationController def check_manage_permissions render_403 unless can_manage_project?(@project) end + + def log_activity(type_of) + Activities::CreateActivityService + .call(activity_type: type_of, + owner: current_user, + subject: @project, + team: @project.team, + project: @project, + message_items: { project: @project.id }) + end end diff --git a/app/controllers/user_projects_controller.rb b/app/controllers/user_projects_controller.rb index f9fcd219e..fafa0aaac 100644 --- a/app/controllers/user_projects_controller.rb +++ b/app/controllers/user_projects_controller.rb @@ -52,19 +52,7 @@ class UserProjectsController < ApplicationController @up.assigned_by = current_user if @up.save - # Generate activity - Activity.create( - type_of: :assign_user_to_project, - user: current_user, - project: @project, - message: t( - "activities.assign_user_to_project", - assigned_user: @up.user.full_name, - role: @up.role_str, - project: @project.name, - assigned_by_user: current_user.full_name - ) - ) + log_activity(:assign_user_to_project) respond_to do |format| format.json do @@ -90,19 +78,7 @@ class UserProjectsController < ApplicationController @up.role = up_params[:role] if @up.save - # Generate activity - Activity.create( - type_of: :change_user_role_on_project, - user: current_user, - project: @project, - message: t( - "activities.change_user_role_on_project", - actor: current_user.full_name, - user: @up.user.full_name, - project: @project.name, - role: @up.role_str - ) - ) + log_activity(:change_user_role_on_project) respond_to do |format| format.json do @@ -123,20 +99,12 @@ class UserProjectsController < ApplicationController def destroy if @up.destroy - # Generate activity - Activity.create( - type_of: :unassign_user_from_project, - user: current_user, - project: @project, - message: t( - "activities.unassign_user_from_project", - unassigned_user: @up.user.full_name, - project: @project.name, - unassigned_by_user: current_user.full_name - ) - ) - generate_notification(current_user, @up.user, false, false, @project) - + log_activity(:unassign_user_from_project) + generate_notification(current_user, + @up.user, + false, + @up.role_str, + @project) respond_to do |format| format.json do redirect_to project_users_edit_path(format: :json), @@ -191,4 +159,16 @@ class UserProjectsController < ApplicationController def up_params params.require(:user_project).permit(:user_id, :project_id, :role) end + + def log_activity(type_of) + Activities::CreateActivityService + .call(activity_type: type_of, + owner: current_user, + subject: @project, + team: @project.team, + project: @project, + message_items: { project: @project.id, + user_target: @up.user.id, + role: @up.role_str }) + end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index f41eb90ac..c834a56b5 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -32,9 +32,10 @@ module NotificationsHelper message = "#{I18n.t('search.index.team')} #{team.name}" elsif project title = I18n.t('activities.unassign_user_from_project', - unassigned_user: target_user.full_name, + user_target: target_user.full_name, project: project.name, - unassigned_by_user: user.full_name) + user: user.full_name, + role: role) message = "#{I18n.t('search.index.project')} #{@project.name}" end diff --git a/config/locales/en.yml b/config/locales/en.yml index 2f5322d16..85e0902cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -319,6 +319,9 @@ en: users: "Users" experiments: "Experiments" tasks: "Tasks" + activity: + visibility_hidden: "Project members only" + visibility_visible: "All team members" create: success_flash: "Project %{name} successfully created." update: @@ -1314,13 +1317,13 @@ en: modal: modal_title: "Activities" create_project: "%{user} created project %{project}." - rename_project: "%{user} renamed project %{project_old} to %{project_new}." + rename_project: "%{user} renamed project %{project}." change_project_visibility: "%{user} changed project %{project}'s visibility to %{visibility}." archive_project: "%{user} moved project %{project} to archive." restore_project: "%{user} restored project %{project} from archive." - assign_user_to_project: "%{assigned_user} was added as %{role} to project %{project} by %{assigned_by_user}." - change_user_role_on_project: "%{actor} changed %{user}'s role on project %{project} to %{role}." - unassign_user_from_project: "%{unassigned_user} was removed from project %{project} by %{unassigned_by_user}." + assign_user_to_project: "%{user} assigned user %{user_target} with user role %{role} to project %{project}." + change_user_role_on_project: "%{user} changed %{user_target}'s role on project %{project} to %{role}." + unassign_user_from_project: "%{user} removed user %{user_target} with user role %{role} from project %{project}." create_module: "%{user} created task %{module}." assign_user_to_module: "%{assigned_user} was added to task %{module} by %{assigned_by_user}." unassign_user_from_module: "%{unassigned_user} was removed from task %{module} by %{unassigned_by_user}." diff --git a/spec/controllers/project_comments_controller_spec.rb b/spec/controllers/project_comments_controller_spec.rb new file mode 100644 index 000000000..121b9491d --- /dev/null +++ b/spec/controllers/project_comments_controller_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ProjectCommentsController, type: :controller do + login_user + + let(:user) { User.first } + let(:team) { create :team, created_by: user } + let(:user_team) { create :user_team, team: team, user: user } + let(:user_project) { create :user_project, :owner, user: user } + let(:project) do + create :project, team: team, user_projects: [user_project] + end + let(:project_comment) do + create :project_comment, project: project, user: user + end + + describe '#create' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + comment: { message: 'test message' } } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :add_comment_to_project)) + + post :create, params: params, format: :json + end + end + end + + describe '#update' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + id: project_comment.id, + comment: { message: 'test message updated' } } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :edit_project_comment)) + + put :update, params: params, format: :json + end + end + end + + describe '#destroy' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + id: project_comment.id } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :delete_project_comment)) + + delete :destroy, params: params, format: :json + end + end + end +end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 9fe134e77..0db6dfaf2 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -150,8 +150,8 @@ describe ProjectsController, type: :controller do context 'in HTML format' do let(:params) do { id: project_1.id, - project: { name: 'test project A1', team_id: team.id, - visibility: 'visible' } } + project: { name: project_1.name, team_id: project_1.team.id, + visibility: project_1.visibility } } end it 'returns redirect response' do @@ -159,6 +159,39 @@ describe ProjectsController, type: :controller do expect(response).to have_http_status(:redirect) expect(response.content_type).to eq 'text/html' end + + it 'calls create activity service (change_project_visibility)' do + params[:project][:visibility] = 'hidden' + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :change_project_visibility)) + + put :update, params: params + end + + it 'calls create activity service (rename_project)' do + params[:project][:name] = 'test project changed' + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :rename_project)) + + put :update, params: params + end + + it 'calls create activity service (restore_project)' do + project_1.update(archived: true) + params[:project][:archived] = false + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :restore_project)) + + put :update, params: params + end + + it 'calls create activity service (archive_project)' do + params[:project][:archived] = true + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :archive_project)) + + put :update, params: params + end end end diff --git a/spec/controllers/user_projects_controller_spec.rb b/spec/controllers/user_projects_controller_spec.rb new file mode 100644 index 000000000..fe409ff46 --- /dev/null +++ b/spec/controllers/user_projects_controller_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe UserProjectsController, type: :controller do + login_user + + let(:user) { User.first } + let(:user_two) { create :user } + let(:target_user) { create :user } + let!(:team) { create :team, created_by: user } + let!(:user_team) { create :user_team, team: team, user: user } + let(:user_project) { create :user_project, :owner, user: user } + let(:target_user_project) do + create :user_project, :normal_user, user: target_user + end + let(:project) do + create :project, team: team, user_projects: [user_project, + target_user_project] + end + + describe '#create' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + user_project: { user_id: user_two.id, + project_id: project.id, + role: :owner } } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :assign_user_to_project)) + + post :create, params: params, format: :json + end + end + end + + describe '#update' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + id: target_user_project.id, + user_project: { user_id: target_user.id, + project_id: project.id, + role: :viewer } } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :change_user_role_on_project)) + + put :update, params: params, format: :json + end + end + end + + describe '#destroy' do + context 'in JSON format' do + let(:params) do + { project_id: project.id, + id: target_user_project.id } + end + + it 'calls create activity service' do + expect(Activities::CreateActivityService).to receive(:call) + .with(hash_including(activity_type: :unassign_user_from_project)) + + delete :destroy, params: params, format: :json + end + end + end +end diff --git a/spec/factories/project_comments.rb b/spec/factories/project_comments.rb new file mode 100644 index 000000000..3e0d3992a --- /dev/null +++ b/spec/factories/project_comments.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :project_comment do + user + project + message { Faker::Lorem.sentence } + end +end