Commit cc043f32d8bfa7da5e94061806ae56fc11902d71

Authored by Dmitriy Zaporozhets
1 parent a769204f

Admin area improved

Showing 39 changed files with 434 additions and 334 deletions   Show diff stats
app/assets/stylesheets/application.css
... ... @@ -7,5 +7,5 @@
7 7 *= require jquery-ui/jquery.tagify
8 8 *= require chosen
9 9 *= require_self
10   - *= require common
  10 + *= require main
11 11 */
... ...
app/assets/stylesheets/common.scss
1   -@import "bootstrap";
2   -
3   -/** GITLAB colors **/
4   -$text_color:#222;
5   -$lite_text_color: #666;
6   -$link_color:#111;
7   -$active_link_color:#2FA0BB;
8   -$active_bg_color:#79C3E0;
9   -$active_bd_color: #2FA0BB;
10   -$border_color:#CCC;
11   -$lite_border_color:#EEE;
12   -$min_app_width:980px;
13   -$max_app_width:980px;
14   -$app_padding:20px;
15   -$bg_color: #FFF;
16   -$styled_border_color: #2FA0BB;
17   -$color: "#4BB8D2";
18   -$blue_link: "#2fa0bb";
19   -
20   -/** MIXINS **/
21   -@mixin round-borders-bottom($radius) {
22   - border-top: 1px solid #eaeaea;
23   - -moz-border-radius-bottomright: $radius;
24   - -moz-border-radius-bottomleft: $radius;
25   - border-bottom-right-radius: $radius;
26   - border-bottom-left-radius: $radius;
27   - -webkit-border-bottom-left-radius: $radius;
28   - -webkit-border-bottom-right-radius: $radius;
29   -}
30   -
31   -@mixin round-borders-top($radius) {
32   - border-top: 1px solid #eaeaea;
33   - -moz-border-radius-topright: $radius;
34   - -moz-border-radius-topleft: $radius;
35   - border-top-right-radius: $radius;
36   - border-top-left-radius: $radius;
37   - -webkit-border-top-left-radius: $radius;
38   - -webkit-border-top-right-radius: $radius;
39   -}
40   -
41   -@mixin round-borders-all($radius) {
42   - border: 1px solid #eaeaea;
43   - -moz-border-radius: $radius;
44   - -webkit-border-radius: $radius;
45   - border-radius: $radius;
46   -}
47   -
48 1 /** COLORS **/
49 2 .cgray { color:gray; }
50 3 .cred { color:#D12F19; }
... ... @@ -173,18 +126,38 @@ img.lil_av {
173 126 .author_link {
174 127 color: $active_link_color;
175 128 }
  129 +.entry {
  130 + position: relative;
  131 + padding: 7px 15px;
  132 + margin-bottom: 18px;
  133 + color: #404040;
  134 + filter:none;
  135 +
  136 + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
  137 + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  138 +
  139 + -webkit-border-radius: 4px;
  140 + -moz-border-radius: 4px;
  141 + border-radius: 4px;
176 142  
177   -@import "reset_bootstrap.scss";
178   -@import "top_panel.scss";
179   -@import "projects.css.scss";
180   -@import "commits.css.scss";
181   -@import "tree.scss";
182   -@import "issues.css.scss";
183   -@import "merge_requests.css.scss";
184   -@import "notes.css.scss";
185   -@import "login.scss";
  143 + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  144 + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  145 + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
186 146  
187   -/** CODE HIGHTLIGHT **/
188   -@import "highlight.css.scss";
189   -@import "highlight.black.css.scss";
  147 + background:#F1F1F1;
  148 + border: 1px solid #ccc;
  149 +
  150 + p {
  151 + margin-bottom: 0;
  152 + img {
  153 + position:relative;
  154 + top:3px;
  155 + }
  156 + }
  157 +}
  158 +
  159 +.widget {
  160 + padding:20px;
  161 + margin-bottom:20px;
  162 +}
190 163  
... ...
app/assets/stylesheets/issues.css.scss
... ... @@ -1,3 +0,0 @@
1   -#issue_assignee_id {
2   - width:300px;
3   -}
app/assets/stylesheets/main.scss 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +@import "bootstrap";
  2 +
  3 +/** GITLAB colors **/
  4 +$text_color:#222;
  5 +$lite_text_color: #666;
  6 +$link_color:#111;
  7 +$active_link_color:#2FA0BB;
  8 +$active_bg_color:#79C3E0;
  9 +$active_bd_color: #2FA0BB;
  10 +$border_color:#CCC;
  11 +$lite_border_color:#EEE;
  12 +$min_app_width:980px;
  13 +$max_app_width:980px;
  14 +$app_padding:20px;
  15 +$bg_color: #FFF;
  16 +$styled_border_color: #2FA0BB;
  17 +$color: "#4BB8D2";
  18 +$blue_link: "#2fa0bb";
  19 +
  20 +/** MIXINS **/
  21 +@mixin round-borders-bottom($radius) {
  22 + border-top: 1px solid #eaeaea;
  23 + -moz-border-radius-bottomright: $radius;
  24 + -moz-border-radius-bottomleft: $radius;
  25 + border-bottom-right-radius: $radius;
  26 + border-bottom-left-radius: $radius;
  27 + -webkit-border-bottom-left-radius: $radius;
  28 + -webkit-border-bottom-right-radius: $radius;
  29 +}
  30 +
  31 +@mixin round-borders-top($radius) {
  32 + border-top: 1px solid #eaeaea;
  33 + -moz-border-radius-topright: $radius;
  34 + -moz-border-radius-topleft: $radius;
  35 + border-top-right-radius: $radius;
  36 + border-top-left-radius: $radius;
  37 + -webkit-border-top-left-radius: $radius;
  38 + -webkit-border-top-right-radius: $radius;
  39 +}
  40 +
  41 +@mixin round-borders-all($radius) {
  42 + border: 1px solid #eaeaea;
  43 + -moz-border-radius: $radius;
  44 + -webkit-border-radius: $radius;
  45 + border-radius: $radius;
  46 +}
  47 +
  48 +
  49 +@import "reset_bootstrap.scss";
  50 +@import "common.scss";
  51 +@import "top_panel.scss";
  52 +
  53 +@import "projects.css.scss";
  54 +@import "commits.css.scss";
  55 +@import "tree.scss";
  56 +@import "merge_requests.css.scss";
  57 +@import "notes.css.scss";
  58 +@import "login.scss";
  59 +
  60 +/** CODE HIGHTLIGHT **/
  61 +@import "highlight.css.scss";
  62 +@import "highlight.black.css.scss";
  63 +
  64 +
... ...
app/assets/stylesheets/projects.css.scss
... ... @@ -201,3 +201,7 @@ input.git_clone_url {
201 201 width:60px;
202 202 }
203 203 }
  204 +
  205 +#issue_assignee_id {
  206 + width:300px;
  207 +}
... ...
app/assets/stylesheets/reset_bootstrap.scss
... ... @@ -5,38 +5,3 @@ a {
5 5 color: $active_link_color;
6 6 }
7 7 }
8   -
9   -.entry {
10   - position: relative;
11   - padding: 7px 15px;
12   - margin-bottom: 18px;
13   - color: #404040;
14   - filter:none;
15   -
16   - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
17   - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
18   -
19   - -webkit-border-radius: 4px;
20   - -moz-border-radius: 4px;
21   - border-radius: 4px;
22   -
23   - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
24   - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
25   - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
26   -
27   - background:#F1F1F1;
28   - border: 1px solid #ccc;
29   -
30   - p {
31   - margin-bottom: 0;
32   - img {
33   - position:relative;
34   - top:3px;
35   - }
36   - }
37   -}
38   -
39   -.widget {
40   - padding:20px;
41   - margin-bottom:20px;
42   -}
... ...
app/assets/stylesheets/top_panel.scss
... ... @@ -11,6 +11,7 @@ body header {
11 11 -moz-box-shadow: 0 -1px 0 white inset;
12 12 -webkit-box-shadow: 0 -1px 0 white inset;
13 13  
  14 + z-index:10;
14 15 height:60px;
15 16  
16 17 .wrapper {
... ...
app/controllers/admin/team_members_controller.rb
... ... @@ -3,39 +3,15 @@ class Admin::TeamMembersController < ApplicationController
3 3 before_filter :authenticate_user!
4 4 before_filter :authenticate_admin!
5 5  
6   - def index
7   - @admin_team_members = UsersProject.page(params[:page]).per(100).order("project_id DESC")
8   - end
9   -
10   - def show
11   - @admin_team_member = UsersProject.find(params[:id])
12   - end
13   -
14   - def new
15   - @admin_team_member = UsersProject.new(params[:team_member])
16   - end
17   -
18 6 def edit
19 7 @admin_team_member = UsersProject.find(params[:id])
20 8 end
21 9  
22   - def create
23   - @admin_team_member = UsersProject.new(params[:team_member])
24   - @admin_team_member.project_id = params[:team_member][:project_id]
25   -
26   - if @admin_team_member.save
27   - redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully created.'
28   - else
29   - render action: "new"
30   - end
31   - end
32   -
33 10 def update
34 11 @admin_team_member = UsersProject.find(params[:id])
35   - @admin_team_member.project_id = params[:team_member][:project_id]
36 12  
37 13 if @admin_team_member.update_attributes(params[:team_member])
38   - redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully updated.'
  14 + redirect_to [:admin, @admin_team_member.project], notice: 'Project Access was successfully updated.'
39 15 else
40 16 render action: "edit"
41 17 end
... ... @@ -45,6 +21,6 @@ class Admin::TeamMembersController < ApplicationController
45 21 @admin_team_member = UsersProject.find(params[:id])
46 22 @admin_team_member.destroy
47 23  
48   - redirect_to admin_team_members_url
  24 + redirect_to :back
49 25 end
50 26 end
... ...
app/controllers/admin/users_controller.rb
... ... @@ -9,8 +9,28 @@ class Admin::UsersController < ApplicationController
9 9  
10 10 def show
11 11 @admin_user = User.find(params[:id])
  12 +
  13 + @projects = if @admin_user.projects.empty?
  14 + Project
  15 + else
  16 + Project.without_user(@admin_user)
  17 + end.all
12 18 end
13 19  
  20 + def team_update
  21 + @admin_user = User.find(params[:id])
  22 +
  23 + UsersProject.user_bulk_import(
  24 + @admin_user,
  25 + params[:project_ids],
  26 + params[:project_access],
  27 + params[:repo_access]
  28 + )
  29 +
  30 + redirect_to [:admin, @admin_user], notice: 'Teams were successfully updated.'
  31 + end
  32 +
  33 +
14 34 def new
15 35 @admin_user = User.new(:projects_limit => 10)
16 36 end
... ...
app/models/project.rb
... ... @@ -53,6 +53,7 @@ class Project < ActiveRecord::Base
53 53 attr_protected :private_flag, :owner_id
54 54  
55 55 scope :public_only, where(:private_flag => false)
  56 + scope :without_user, lambda { |user| where("id not in (:ids)", :ids => user.projects.map(&:id) ) }
56 57  
57 58 def self.active
58 59 joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
... ...
app/models/users_project.rb
... ... @@ -27,6 +27,20 @@ class UsersProject < ActiveRecord::Base
27 27 end
28 28 end
29 29  
  30 + def self.user_bulk_import(user, project_ids, project_access, repo_access)
  31 + UsersProject.transaction do
  32 + project_ids.each do |project_id|
  33 + users_project = UsersProject.new(
  34 + :repo_access => repo_access,
  35 + :project_access => project_access,
  36 + )
  37 + users_project.project_id = project_id
  38 + users_project.user_id = user.id
  39 + users_project.save
  40 + end
  41 + end
  42 + end
  43 +
30 44 def update_repository
31 45 Gitlabhq::GitHost.system.new.configure do |c|
32 46 c.update_project(project.path, project)
... ...
app/views/admin/projects/_form.html.haml
1 1 = form_for [:admin, @admin_project] do |f|
2 2 -if @admin_project.errors.any?
3   - #error_explanation
4   - %h2= "#{pluralize(@admin_project.errors.count, "error")} prohibited this admin_project from being saved:"
  3 + .alert-message.block-message.error
5 4 %ul
6 5 - @admin_project.errors.full_messages.each do |msg|
7 6 %li= msg
... ... @@ -10,27 +9,58 @@
10 9 = f.label :name
11 10 .input= f.text_field :name
12 11 .clearfix
13   - = f.label :code
14   - .input= f.text_field :code
  12 + = f.label :path do
  13 + Path
  14 + .input
  15 + .input-prepend
  16 + %span.add-on= "git@#{GIT_HOST["host"]}:"
  17 + = f.text_field :path, :placeholder => "example_project", :disabled => !@admin_project.new_record?
15 18 .clearfix
16   - = f.label :path
17   - .input= f.text_field :path
  19 + = f.label :code do
  20 + Code
  21 + .input
  22 + .input-prepend
  23 + %span.add-on= "http://#{GIT_HOST["host"]}/"
  24 + = f.text_field :code, :placeholder => "example"
18 25  
19 26 - unless @admin_project.new_record?
20 27 .clearfix
21 28 = f.label :owner_id
22 29 .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }
23 30  
  31 + - unless @admin_project.heads.empty?
  32 + .clearfix
  33 + = f.label :default_branch, "Default Branch"
  34 + .input= f.select(:default_branch, @admin_project.heads.map(&:name), {}, :style => "width:210px;")
  35 +
  36 + .well
  37 + %h5 Features
  38 +
  39 + .clearfix
  40 + = f.label :issues_enabled, "Issues"
  41 + .input= f.check_box :issues_enabled
  42 +
  43 + .clearfix
  44 + = f.label :merge_requests_enabled, "Merge Requests"
  45 + .input= f.check_box :merge_requests_enabled
  46 +
  47 + .clearfix
  48 + = f.label :wall_enabled, "Wall"
  49 + .input= f.check_box :wall_enabled
  50 +
24 51 .clearfix
25 52 = f.label :description
26   - .input= f.text_area :description
  53 + .input= f.text_area :description, :class => "xxlarge"
27 54 .clear
28 55 %br
29 56 .actions
30   - = f.submit 'Save', :class => "btn"
  57 + = f.submit 'Save', :class => "btn primary"
  58 + = link_to 'Cancel', [:admin, @admin_project], :class => "btn"
  59 + = link_to 'Destroy', [:admin, @admin_project], :confirm => 'Are you sure?', :method => :delete, :class => "btn danger right"
31 60  
32 61 :javascript
33 62 $(function(){
34 63 taggifyForm();
35 64 $('#project_owner_id').chosen();
  65 + $('#project_default_branch').chosen();
36 66 })
... ...
app/views/admin/projects/edit.html.haml
1   -%h2= @admin_project.name
  1 +%h3= @admin_project.name
  2 +%hr
2 3 = render 'form'
3   -
4   -%br
5   -= link_to 'Back', admin_projects_path, :class => ""
6   -|
7   -= link_to 'Show', [:admin, @admin_project], :class => ""
... ...
app/views/admin/projects/index.html.haml
1   -%table
  1 +%h3
  2 + Projects
  3 + = link_to 'New Project', new_admin_project_path, :class => "btn small right"
  4 +%hr
  5 +%table.zebra-striped
2 6 %thead
3 7 %th Name
4   - %th Code
5 8 %th Path
6 9 %th Team Members
7 10 %th Last Commit
... ... @@ -11,12 +14,9 @@
11 14 - @admin_projects.each do |project|
12 15 %tr
13 16 %td= link_to project.name, [:admin, project]
14   - %td= project.code
15 17 %td= project.path
16 18 %td= project.users_projects.count
17 19 %td= last_commit(project)
18   - %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}"
19   - %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete
20   -
  20 + %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}", :class => "btn small"
  21 + %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
21 22 = paginate @admin_projects
22   -= link_to 'New Project', new_admin_project_path, :class => "btn"
... ...
app/views/admin/projects/show.html.haml
1   -- unless notice.nil?
2   - %p#notice= notice
  1 +%h3
  2 + = @admin_project.name
  3 + = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn right small"
3 4  
  5 +%hr
4 6  
5   -%h2= @admin_project.name
6   -
7   -%table.round-borders
  7 +%table.zebra-striped
8 8 %tr
9 9 %td
10 10 %b
... ... @@ -29,14 +29,33 @@
29 29 Description:
30 30 %td
31 31 = @admin_project.description
32   - %tr
33   - %td{:colspan => 2}
34   - = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn"
35 32  
36 33  
37 34 .span-14
38 35  
39   - %h2 Team
  36 + %h3
  37 + Team
  38 + %small
  39 + ( #{@admin_project.users_projects.count} )
  40 +
  41 + %hr
  42 +
  43 + %table.zebra-striped
  44 + %thead
  45 + %tr
  46 + %th Name
  47 + %th Project Access
  48 + %th Repository Access
  49 + %th
  50 +
  51 + - @admin_project.users_projects.each do |tm|
  52 + %tr
  53 + %td
  54 + = link_to tm.user_name, admin_users_path(tm.user)
  55 + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled
  56 + %td= select_tag :tm_repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "medium repo-access-select", :disabled => :disabled
  57 + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"
  58 + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn danger small"
40 59  
41 60 = form_tag team_update_admin_project_path(@admin_project), :class => "bulk_import", :method => :put do
42 61 %table
... ... @@ -51,27 +70,8 @@
51 70 %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select"
52 71 %td= select_tag :repo_access, options_for_select(Repository.access_options), :class => "repo-access-select"
53 72  
54   - %tr
55   - %td{ :colspan => 3 }
56   - = submit_tag 'Add', :class => "btn primary"
57   -
58   - %table.round-borders
59   - %thead
60   - %tr
61   - %th Name
62   - %th Added
63   - %th Project Access
64   - %th Repository Access
65   - %th
66   -
67   - - @admin_project.users_projects.each do |tm|
68   - %tr
69   - %td
70   - = link_to tm.user_name, admin_team_member_path(tm)
71   - %td= time_ago_in_words(tm.updated_at) + " ago"
72   - %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled
73   - %td= select_tag :tm_repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled
74   - %td= link_to 'Destroy', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete
  73 + .actions
  74 + = submit_tag 'Add', :class => "btn primary"
75 75  
76 76 :css
77 77 form select {
... ...
app/views/admin/team_members/_form.html.haml
1   -= form_for @admin_team_member, :as => :team_member, :url => @admin_team_member.new_record? ? admin_team_members_path(@admin_team_member) : admin_team_member_path(@admin_team_member) do |f|
  1 += form_for @admin_team_member, :as => :team_member, :url => admin_team_member_path(@admin_team_member) do |f|
2 2 -if @admin_team_member.errors.any?
3   - #error_explanation
4   - %h2= "#{pluralize(@admin_team_member.errors.count, "error")} prohibited this admin_project from being saved:"
  3 + .alert-message.block-message.error
5 4 %ul
6 5 - @admin_team_member.errors.full_messages.each do |msg|
7 6 %li= msg
8 7  
9   - - if @admin_team_member.new_record?
10   - .span-6
11   - = f.label :user_id
12   - .span-6
13   - = f.select :user_id, User.all.map { |user| [user.name, user.id] }
14   - .span-6
15   - = f.label :project_id
16   - .span-6
17   - = f.select :project_id, Project.all.map { |user| [user.name, user.id] }
  8 + .clearfix
  9 + %label Project Access:
  10 + .input
  11 + = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, :class => "project-access-select"
18 12  
19   - .span-6
20   - %b Project Access:
21   - .span-6
22   - = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, :class => "project-access-select"
23   -
24   - .span-6
25   - %b Repository Access:
26   - .span-6
27   - = f.select :repo_access, options_for_select(Repository.access_options, @admin_team_member.repo_access), {}, :class => "repo-access-select"
  13 + .clearfix
  14 + %label Repository Access:
  15 + .input
  16 + = f.select :repo_access, options_for_select(Repository.access_options, @admin_team_member.repo_access), {}, :class => "repo-access-select"
28 17 %br
29 18 .actions
30   - = f.submit 'Save', :class => "btn"
  19 + = f.submit 'Save', :class => "btn primary"
  20 + = link_to 'Cancel', :back, :class => "btn"
31 21  
32 22 :css
33 23 form select {
... ...
app/views/admin/team_members/edit.html.haml
1   -= render 'form'
  1 +%h3
  2 + Edit access
  3 + %small
  4 + = @admin_team_member.project.name
  5 + –
  6 + = @admin_team_member.user_name
2 7  
3   -%br
4   -= link_to 'Show', admin_team_member_path(@admin_team_member)
5   -\|
6   -= link_to 'Back', admin_team_members_path
  8 +%hr
  9 +%table.zebra-striped
  10 + %tr
  11 + %td User:
  12 + %td= @admin_team_member.user_name
  13 + %tr
  14 + %td Project:
  15 + %td= @admin_team_member.project.name
  16 + %tr
  17 + %td Since:
  18 + %td= @admin_team_member.updated_at.stamp("Nov 11, 2010")
  19 += render 'form'
... ...
app/views/admin/team_members/index.html.haml
... ... @@ -1,28 +0,0 @@
1   -- @admin_team_members.group_by(&:project).sort.each do |project, members|
2   - %h3= link_to project.name, [:admin, project]
3   - %table
4   - %thead
5   - %th Name
6   - %th Project Access
7   - %th Repo Access
8   - %th Added
9   - %th
10   - %th
11   - - members.each do |tm|
12   - - user = tm.user
13   - %tr
14   - %td.span-6
15   - = link_to tm.user_name, admin_team_member_path(tm)
16   - %br
17   - %br
18   - = tm.user_email
19   - %td.span-3= select_tag :project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled
20   - %td.span-3= select_tag :repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled
21   - %td.span-3= time_ago_in_words(tm.updated_at) + " ago"
22   - %td= link_to 'Edit', edit_admin_team_member_path(tm), :id => "edit_#{dom_id(tm)}"
23   - %td= link_to 'Destroy', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete
24   -
25   -%br
26   -
27   -= paginate @admin_team_members
28   -= link_to 'New Team Member', new_admin_team_member_path, :class => "btn"
app/views/admin/team_members/new.html.haml
... ... @@ -1,6 +0,0 @@
1   -%h1 New team member
2   -
3   -= render 'form'
4   -
5   -%br
6   -= link_to 'Back', admin_team_members_path
app/views/admin/team_members/show.html.haml
... ... @@ -1,26 +0,0 @@
1   -#infoblock
2   - %p
3   - %b Name:
4   - = @admin_team_member.user_name
5   - %p
6   - %b Project:
7   - = @admin_team_member.project.name
8   - %p
9   - %b Since:
10   - = @admin_team_member.updated_at.stamp("Nov 11, 2010")
11   -
12   -#infoblock
13   - .span-6
14   - %b Project Access:
15   - = select_tag :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), :class => "project-access-select", :disabled => true
16   -
17   - %br
18   - .span-6
19   - %b Repository Access:
20   - = select_tag :repo_access, options_for_select(Repository.access_options, @admin_team_member.repo_access), :class => "repo-access-select", :disabled => true
21   -
22   -%br
23   -
24   -= link_to 'Edit', edit_admin_team_member_path(@admin_project)
25   -\|
26   -= link_to 'Back', admin_team_members_path
app/views/admin/users/_form.html.haml
... ... @@ -18,9 +18,6 @@
18 18 .clearfix
19 19 = f.label :password_confirmation
20 20 .input= f.password_field :password_confirmation
21   - .clearfix
22   - = f.check_box :admin
23   - = f.label :admin
24 21  
25 22 .clearfix
26 23 = f.label :projects_limit
... ... @@ -35,8 +32,13 @@
35 32 .clearfix
36 33 = f.label :twitter
37 34 .input= f.text_field :twitter
38   - .clear
39   - %br
  35 + .clearfix
  36 + = f.label :admin do
  37 + = f.check_box :admin
  38 + %span Administrator
40 39 .actions
41 40 = f.submit 'Save', :class => "btn primary"
42   - = link_to 'Cancel', admin_users_path, :class => "btn"
  41 + - if @admin_user.new_record?
  42 + = link_to 'Cancel', admin_users_path, :class => "btn"
  43 + - else
  44 + = link_to 'Cancel', admin_user_path(@admin_user), :class => "btn"
... ...
app/views/admin/users/edit.html.haml
  1 +%h3= @admin_user.name
  2 +%hr
1 3 = render 'form'
2   -
3   -%br
4   -= link_to 'Back', admin_users_path, :class => ""
5   -|
6   -= link_to 'Show', [:admin, @admin_user], :class => ""
... ...
app/views/admin/users/index.html.haml
1   -%table
  1 +%h3
  2 + Users
  3 + = link_to 'New User', new_admin_user_path, :class => "btn small right"
  4 +%hr
  5 +%table.zebra-striped
2 6 %thead
3 7 %th Admin
4 8 %th Name
... ... @@ -13,9 +17,7 @@
13 17 %td= link_to user.name, [:admin, user]
14 18 %td= user.email
15 19 %td= user.users_projects.count
16   - %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}"
17   - %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete
  20 + %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}", :class => "btn small"
  21 + %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
18 22  
19 23 = paginate @admin_users
20   -%br
21   -= link_to 'New User', new_admin_user_path, :class => "btn"
... ...
app/views/admin/users/show.html.haml
1   -%h2= @admin_user.name
  1 +%h3
  2 + = @admin_user.name
  3 + = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn small right"
2 4  
3   -%table.round-borders
  5 +%hr
  6 +
  7 +%table.zebra-striped
4 8 %tr
5 9 %td
6 10 %b
... ... @@ -39,31 +43,57 @@
39 43 Twitter:
40 44 %td
41 45 = @admin_user.twitter
42   - %tr
43   - %td{:colspan => 2}
44   - = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn"
45 46  
46   -.span-14
47   - %h2 Projects
  47 +%h3 Projects
  48 +%hr
  49 +
  50 +%table.zebra-striped
  51 + %tr
  52 + %thead
  53 + %th Name
  54 + %th Project Access
  55 + %th Repository Access
  56 + %th
  57 + %th
48 58  
49   - %table.round-borders
  59 + - @admin_user.users_projects.each do |tm|
  60 + - project = tm.project
50 61 %tr
51   - %thead
52   - %th Name
53   - %th Added
54   - %th Project Access
55   - %th Repository Access
56   - %th
57   - %th
  62 + %td= link_to project.name, admin_project_path(project)
  63 + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled
  64 + %td= select_tag :tm_repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "medium repo-access-select", :disabled => :disabled
  65 + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small"
  66 + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
58 67  
59   - - @admin_user.users_projects.each do |tm|
60   - - project = tm.project
  68 += form_tag team_update_admin_user_path(@admin_user), :class => "bulk_import", :method => :put do
  69 + %table
  70 + %thead
61 71 %tr
62   - %td= link_to project.name, admin_project_path(project)
63   - %td= time_ago_in_words(tm.updated_at) + " ago"
64   - %td= select_tag :project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled
65   - %td= select_tag :repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled
66   - %td= link_to 'Edit', edit_admin_team_member_path(tm)
67   - %td= link_to 'Cancel', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete
  72 + %th Projects
  73 + %th Project Access:
  74 + %th Repo Access:
  75 +
  76 + %tr
  77 + %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), :multiple => true
  78 + %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select"
  79 + %td= select_tag :repo_access, options_for_select(Repository.access_options), :class => "repo-access-select"
  80 +
  81 + .actions
  82 + = submit_tag 'Add', :class => "btn primary"
  83 +
  84 +
  85 +:css
  86 + form select {
  87 + width:150px;
  88 + }
  89 +
  90 + #project_ids {
  91 + width:300px;
  92 + }
  93 +
  94 +
  95 +:javascript
  96 + $('select#project_ids').chosen();
  97 + $('select#repo_access').chosen();
  98 + $('select#project_access').chosen();
68 99  
69   - = link_to 'Add To Another Project', new_admin_team_member_path(:team_member => {:user_id => @admin_user.id}), :class => "btn"
... ...
app/views/kaminari/_first_page.html.haml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +-# Link to the "First" page
  2 +-# available local variables
  3 +-# url: url to the first page
  4 +-# current_page: a page object for the currently displayed page
  5 +-# num_pages: total number of pages
  6 +-# per_page: number of items to fetch per page
  7 +-# remote: data-remote
  8 +%span.first
  9 + = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
... ...
app/views/kaminari/_gap.html.haml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +-# Non-link tag that stands for skipped pages...
  2 +-# available local variables
  3 +-# current_page: a page object for the currently displayed page
  4 +-# num_pages: total number of pages
  5 +-# per_page: number of items to fetch per page
  6 +-# remote: data-remote
  7 +%span.page.gap
  8 + = raw(t 'views.pagination.truncate')
... ...
app/views/kaminari/_last_page.html.haml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +-# Link to the "Last" page
  2 +-# available local variables
  3 +-# url: url to the last page
  4 +-# current_page: a page object for the currently displayed page
  5 +-# num_pages: total number of pages
  6 +-# per_page: number of items to fetch per page
  7 +-# remote: data-remote
  8 +%span.last
  9 + = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
... ...
app/views/kaminari/_next_page.html.haml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +-# Link to the "Next" page
  2 +-# available local variables
  3 +-# url: url to the next page
  4 +-# current_page: a page object for the currently displayed page
  5 +-# num_pages: total number of pages
  6 +-# per_page: number of items to fetch per page
  7 +-# remote: data-remote
  8 +%li.next
  9 + = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
... ...
app/views/kaminari/_page.html.haml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +-# Link showing page number
  2 +-# available local variables
  3 +-# page: a page object for "this" page
  4 +-# url: url to this page
  5 +-# current_page: a page object for the currently displayed page
  6 +-# num_pages: total number of pages
  7 +-# per_page: number of items to fetch per page
  8 +-# remote: data-remote
  9 +%li{:class => "page#{' active' if page.current?}"}
  10 + = link_to page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
... ...
app/views/kaminari/_paginator.html.haml 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +-# The container tag
  2 +-# available local variables
  3 +-# current_page: a page object for the currently displayed page
  4 +-# num_pages: total number of pages
  5 +-# per_page: number of items to fetch per page
  6 +-# remote: data-remote
  7 +-# paginator: the paginator that renders the pagination tags inside
  8 += paginator.render do
  9 + %div.pagination
  10 + %ul
  11 + = prev_page_tag unless current_page.first?
  12 + - each_page do |page|
  13 + - if page.left_outer? || page.right_outer? || page.inside_window?
  14 + = page_tag page
  15 + - elsif !page.was_truncated?
  16 + = gap_tag
  17 + = next_page_tag unless current_page.last?
... ...
app/views/kaminari/_prev_page.html.haml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +-# Link to the "Previous" page
  2 +-# available local variables
  3 +-# url: url to the previous page
  4 +-# current_page: a page object for the currently displayed page
  5 +-# num_pages: total number of pages
  6 +-# per_page: number of items to fetch per page
  7 +-# remote: data-remote
  8 +%li{:class => "prev" }
  9 + = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
... ...
app/views/layouts/_app_side.html.haml
... ... @@ -4,7 +4,4 @@
4 4 = link_to "Projects", projects_path, :class => "#{"active" if current_page?(projects_path)}"
5 5 = link_to "Issues", dashboard_issues_path, :class => "#{"active" if current_page?(dashboard_issues_path)}", :id => "issues_slide"
6 6 = link_to "Requests", dashboard_merge_requests_path, :class => "#{"active" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide"
7   - - if current_user.is_admin?
8   - = link_to admin_root_path, :class => "admin", :title => "Admin" do
9   - Admin
10 7 = link_to "Help", help_path, :class => "#{"active" if controller.controller_name == "help"}"
... ...
app/views/layouts/_projects_side.html.haml
... ... @@ -4,8 +4,16 @@
4 4 You can create at least
5 5 = current_user.projects_limit
6 6 projects. Click on button to add a new one
7   - = link_to new_project_path, :class => "btn small" do
8   - New Project
  7 + .alert-actions
  8 + = link_to new_project_path, :class => "btn small" do
  9 + New Project »
  10 +
  11 + - if current_user.is_admin?
  12 + .alert-message.block-message.info
  13 + You have administrator privilegies. You can configure application following this button:
  14 + .alert-actions
  15 + = link_to admin_root_path, :class => "btn small", :title => "Admin" do
  16 + Visit Admin Area »
9 17  
10 18 - if current_user.projects.count > 0
11 19 %div.entry
... ... @@ -18,21 +26,5 @@
18 26 = project.name
19 27 = link_to "More » ", projects_path
20 28  
21   - -#%h5
22   - -#Your Issues:
23   - -#%ul
24   - -#- current_user.assigned_issues.order("id DESC").limit(5).each do |issue|
25   - -#%li
26   - -#= link_to project_issue_path(issue.project, issue) do
27   - -#= truncate issue.title
28   -
29   -
30   - -#%h5
31   - -#Your Merge Requests:
32   - -#%ul
33   - -#- current_user.assigned_merge_requests.order("id DESC").limit(5).each do |issue|
34   - -#%li
35   - -#= link_to project_merge_request_path(issue.project, issue) do
36   - -#= truncate issue.title
37 29  
38 30  
... ...
app/views/layouts/admin.html.haml
... ... @@ -10,7 +10,6 @@
10 10 %aside
11 11 = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil
12 12 = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil
13   - = link_to "Teams", admin_team_members_path, :class => controller.controller_name == "team_members" ? "current" : nil
14 13 = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil
15 14 = link_to "Resque", "/info/resque"
16 15  
... ...
app/views/profile/show.html.haml
... ... @@ -28,5 +28,6 @@
28 28 = f.label :twitter
29 29 .input= f.text_field :twitter
30 30  
31   - = f.submit 'Save', :class => "primary btn"
  31 + .actions
  32 + = f.submit 'Save', :class => "primary btn"
32 33  
... ...
config/routes.rb
... ... @@ -7,14 +7,18 @@ Gitlab::Application.routes.draw do
7 7 get 'help' => 'help#index'
8 8  
9 9 namespace :admin do
10   - resources :users
  10 + resources :users do
  11 + member do
  12 + put :team_update
  13 + end
  14 + end
11 15 resources :projects, :constraints => { :id => /[^\/]+/ } do
12 16 member do
13 17 get :team
14 18 put :team_update
15 19 end
16 20 end
17   - resources :team_members
  21 + resources :team_members, :only => [:edit, :update, :destroy]
18 22 get 'emails', :to => 'mailer#preview'
19 23 get 'mailer/preview_note'
20 24 get 'mailer/preview_user_new'
... ...
spec/requests/admin/admin_projects_spec.rb
... ... @@ -18,7 +18,6 @@ describe "Admin::Projects" do
18 18 end
19 19  
20 20 it "should have projects list" do
21   - page.should have_content(@project.code)
22 21 page.should have_content(@project.name)
23 22 end
24 23 end
... ... @@ -103,4 +102,18 @@ describe "Admin::Projects" do
103 102 page.should have_content(@project.description)
104 103 end
105 104 end
  105 +
  106 + describe "Add new team member" do
  107 + before do
  108 + @new_user = Factory :user
  109 + visit admin_project_path(@project)
  110 + end
  111 +
  112 + it "should create new user" do
  113 + select @new_user.name, :from => "user_ids"
  114 + expect { click_button "Add" }.to change { UsersProject.count }.by(1)
  115 + page.should have_content @new_user.name
  116 + current_path.should == admin_project_path(@project)
  117 + end
  118 + end
106 119 end
... ...
spec/requests/admin/admin_users_spec.rb
... ... @@ -99,4 +99,18 @@ describe "Admin::Users" do
99 99 end
100 100 end
101 101 end
  102 +
  103 + describe "Add new project" do
  104 + before do
  105 + @new_project = Factory :project
  106 + visit admin_user_path(@user)
  107 + end
  108 +
  109 + it "should create new user" do
  110 + select @new_project.name, :from => "project_ids"
  111 + expect { click_button "Add" }.to change { UsersProject.count }.by(1)
  112 + page.should have_content @new_project.name
  113 + current_path.should == admin_user_path(@user)
  114 + end
  115 + end
102 116 end
... ...
spec/requests/admin/security_spec.rb
... ... @@ -13,12 +13,6 @@ describe "Admin::Projects" do
13 13 it { admin_users_path.should be_denied_for :visitor }
14 14 end
15 15  
16   - describe "GET /admin/team_members" do
17   - it { admin_team_members_path.should be_allowed_for :admin }
18   - it { admin_team_members_path.should be_denied_for :user }
19   - it { admin_team_members_path.should be_denied_for :visitor }
20   - end
21   -
22 16 describe "GET /admin/emails" do
23 17 it { admin_emails_path.should be_allowed_for :admin }
24 18 it { admin_emails_path.should be_denied_for :user }
... ...