Commit 38175209c59a10e30d8444f5b90af507d168cc08

Authored by Valery Sizov
2 parents a7efeb37 6f4576b7

Merge branch 'feature/import_team_from_other_project' of dev.gitlabhq.com:gitlabhq

app/controllers/team_members_controller.rb
... ... @@ -43,4 +43,12 @@ class TeamMembersController < ProjectResourceController
43 43 format.js { render nothing: true }
44 44 end
45 45 end
  46 +
  47 + def apply_import
  48 + giver = Project.find(params[:source_project_id])
  49 + status = UsersProject.import_team(giver, project)
  50 + notice = status ? "Succesfully imported" : "Import failed"
  51 +
  52 + redirect_to project_team_members_path(project), notice: notice
  53 + end
46 54 end
... ...
app/models/users_project.rb
... ... @@ -21,6 +21,35 @@ class UsersProject < ActiveRecord::Base
21 21 delegate :name, :email, to: :user, prefix: true
22 22  
23 23 class << self
  24 + def import_team(source_project, target_project)
  25 + UsersProject.without_repository_callback do
  26 + UsersProject.transaction do
  27 + team = source_project.users_projects.all
  28 +
  29 + team.each do |tm|
  30 + # Skip if user already present in team
  31 + next if target_project.users.include?(tm.user)
  32 +
  33 + new_tm = tm.dup
  34 + new_tm.id = nil
  35 + new_tm.project_id = target_project.id
  36 + new_tm.save
  37 + end
  38 + end
  39 + end
  40 +
  41 + target_project.update_repository
  42 + true
  43 + rescue
  44 + false
  45 + end
  46 +
  47 + def without_repository_callback
  48 + UsersProject.skip_callback(:destroy, :after, :update_repository)
  49 + yield
  50 + UsersProject.set_callback(:destroy, :after, :update_repository)
  51 + end
  52 +
24 53 def bulk_delete(project, user_ids)
25 54 UsersProject.transaction do
26 55 UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project|
... ...
app/views/team_members/import.html.haml 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 += render "projects/project_head"
  2 +
  3 +%h3.page_title
  4 + = "Import team from another project"
  5 +%hr
  6 +%p.slead
  7 + Read more about team import #{link_to "here", '#', class: 'vlink'}.
  8 += form_tag apply_import_project_team_members_path(@project), method: 'post' do
  9 + %p.slead Choose project you want to use as team source:
  10 + .padded
  11 + = label_tag :source_project_id, "Project"
  12 + .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.projects, :id, :name), prompt: "Select project", class: "chosen xxlarge", required: true)
  13 +
  14 + .actions
  15 + = submit_tag 'Import', class: "btn save-btn"
  16 + = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
  17 +
... ...
app/views/team_members/index.html.haml
... ... @@ -5,9 +5,14 @@
5 5  
6 6 - if can? current_user, :admin_team_member, @project
7 7 %p.slead
8   - = link_to new_project_team_member_path(@project), class: "btn small right", title: "New Team Member" do
9   - New Team Member
10 8 Read more about project permissions
11 9 %strong= link_to "here", help_permissions_path, class: "vlink"
12 10  
  11 + %span.right
  12 + = link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
  13 + Import team from another project
  14 + = link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
  15 + New Team Member
  16 +
  17 + .clearfix
13 18 = render partial: "team_members/team", locals: {project: @project}
... ...
config/routes.rb
... ... @@ -188,7 +188,6 @@ Gitlab::Application.routes.draw do
188 188 :via => [:get, :post], constraints: {from: /.+/, to: /.+/}
189 189  
190 190 resources :team, controller: 'team_members', only: [:index]
191   - resources :team_members
192 191 resources :milestones
193 192 resources :labels, only: [:index]
194 193 resources :issues do
... ... @@ -199,6 +198,16 @@ Gitlab::Application.routes.draw do
199 198 end
200 199 end
201 200  
  201 + resources :team_members do
  202 + collection do
  203 +
  204 + # Used for import team
  205 + # from another project
  206 + get :import
  207 + post :apply_import
  208 + end
  209 + end
  210 +
202 211 resources :notes, only: [:index, :create, :destroy] do
203 212 collection do
204 213 post :preview
... ...
features/project/team_management.feature
... ... @@ -32,3 +32,10 @@ Feature: Project Team management
32 32 And I click link "Remove from team"
33 33 Then I visit project "Shop" team page
34 34 And I should not see "Sam" in team list
  35 +
  36 + Scenario: Import team from another project
  37 + Given I own project "Website"
  38 + And "Mike" is "Website" reporter
  39 + And I click link "Import team from another project"
  40 + When I submit "Website" project for import team
  41 + Then I should see "Mike" in team list as "Reporter"
... ...
features/steps/project/project_team_management.rb
... ... @@ -86,4 +86,24 @@ class ProjectTeamManagement &lt; Spinach::FeatureSteps
86 86 project = Project.find_by_name("Shop")
87 87 project.add_access(user, :write)
88 88 end
  89 +
  90 + Given 'I own project "Website"' do
  91 + @project = Factory :project, :name => "Website"
  92 + @project.add_access(@user, :admin)
  93 + end
  94 +
  95 + And '"Mike" is "Website" reporter' do
  96 + user = User.find_by_name("Mike")
  97 + project = Project.find_by_name("Website")
  98 + project.add_access(user, :read)
  99 + end
  100 +
  101 + And 'I click link "Import team from another project"' do
  102 + click_link "Import team from another project"
  103 + end
  104 +
  105 + When 'I submit "Website" project for import team' do
  106 + select 'Website', from: 'source_project_id'
  107 + click_button 'Import'
  108 + end
89 109 end
... ...
spec/models/users_project_spec.rb
... ... @@ -35,4 +35,37 @@ describe UsersProject do
35 35 it { should respond_to(:user_name) }
36 36 it { should respond_to(:user_email) }
37 37 end
  38 +
  39 + describe :import_team do
  40 + before do
  41 + @abilities = Six.new
  42 + @abilities << Ability
  43 +
  44 + @project_1 = create :project
  45 + @project_2 = create :project
  46 +
  47 + @user_1 = create :user
  48 + @user_2 = create :user
  49 +
  50 + @project_1.add_access @user_1, :write
  51 + @project_2.add_access @user_2, :read
  52 +
  53 + @status = UsersProject.import_team(@project_1, @project_2)
  54 + end
  55 +
  56 + it { @status.should be_true }
  57 +
  58 + describe 'project 2 should get user 1 as developer. user_2 should not be changed' do
  59 + it { @project_2.users.should include(@user_1) }
  60 + it { @project_2.users.should include(@user_2) }
  61 +
  62 + it { @abilities.allowed?(@user_1, :write_project, @project_2).should be_true }
  63 + it { @abilities.allowed?(@user_2, :read_project, @project_2).should be_true }
  64 + end
  65 +
  66 + describe 'project 1 should not be changed' do
  67 + it { @project_1.users.should include(@user_1) }
  68 + it { @project_1.users.should_not include(@user_2) }
  69 + end
  70 + end
38 71 end
... ...