Commit 7ecfaccf143a29f6114ccf0cbe45e015d62a481f

Authored by Dmitriy Zaporozhets
2 parents 3fa6ed8e 5add5f76

Merge branch 'master' into stable

CHANGELOG
  1 +v 3.0.3
  2 + - Fixed bug with issues list in Chrome
  3 + - New Feature: Import team from another project
  4 +
1 5 v 3.0.2
2 6 - Fixed gitlab:app:setup
3 7 - Fixed application error on empty project in admin area
... ...
VERSION
1   -3.0.2
  1 +3.0.3
... ...
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/issues/_form.html.haml
... ... @@ -12,7 +12,7 @@
12 12 = f.label :title do
13 13 %strong= "Subject *"
14 14 .input
15   - = f.text_field :title, maxlength: 255, class: "xxlarge gfm-input"
  15 + = f.text_field :title, maxlength: 255, class: "xxlarge gfm-input", autofocus: true
16 16 .issue_middle_block
17 17 .issue_assignee
18 18 = f.label :assignee_id do
... ...
app/views/issues/_show.html.haml
... ... @@ -16,7 +16,7 @@
16 16 = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put, class: "btn small grouped reopen_issue", remote: true
17 17 - else
18 18 = link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small grouped close_issue", remote: true
19   - = link_to edit_project_issue_path(issue.project, issue), class: "btn small edit-issue-link", remote: true do
  19 + = link_to edit_project_issue_path(issue.project, issue), class: "btn small edit-issue-link grouped", remote: true do
20 20 %i.icon-edit
21 21 Edit
22 22  
... ...
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
... ...