Commit 6c40e89853a8211c3108245cd92063da0eb0a46b

Authored by Steven Verbeek
2 parents fafc34b0 1c6df8e0

merging upstream changes

Showing 54 changed files with 454 additions and 217 deletions   Show diff stats
CHANGELOG
  1 +v 2.3.0
  2 + - Dashboard r1
  3 + - Search r1
  4 + - Project page
  5 + - Close merge request on push
  6 + - Persist MR diff after merge
  7 + - mysql support
  8 + - Documentation
  9 +
  10 +v 2.2.0
  11 + - We’ve added support of LDAP auth
  12 + - Improved permission logic (4 roles system)
  13 + - Protected branches (now only masters can push to protected branches)
  14 + - Usability improved
  15 + - twitter bootstrap integrated
  16 + - compare view between commits
  17 + - wiki feature
  18 + - now you can enable/disable issues, wiki, wall features per project
  19 + - security fixes
  20 + - improved code browsing (ajax branch switch etc)
  21 + - improved per-line commenting
  22 + - git submodules displayed
  23 + - moved to rails 3.2
  24 + - help section improved
  25 +
1 26 v 2.1.0
2 27 - Project tab r1
3   - - Repository tab r1
  28 + - List branches/tags
  29 + - per line comments
  30 + - mass user import
4 31  
5 32 v 2.0.0
6 33 - gitolite as main git host system
... ...
VERSION
1   -2.3.0pre
  1 +2.3.0
... ...
app/assets/stylesheets/common.scss
... ... @@ -114,9 +114,17 @@ a:focus {
114 114 margin-top:10px;
115 115 }
116 116  
  117 +.prepend-top-20 {
  118 + margin-top:20px;
  119 +}
  120 +
117 121 .padded {
118 122 padding:20px;
119 123 }
  124 +
  125 +.ipadded {
  126 + padding:20px !important;
  127 +}
120 128 .no-borders {
121 129 border:none;
122 130 }
... ... @@ -354,12 +362,15 @@ img.lil_av {
354 362 top: 3px;
355 363 }
356 364  
357   -.media-grid {
358   - h3, h2 , h4 {
359   - &.media_h {
360   - padding-left:10px;
361   - float:left;
362   - }
  365 +.profile_avatar_holder {
  366 + float:left;
  367 + width:90px;
  368 + height:90px;
  369 + margin-right:20px;
  370 + img {
  371 + width:90px;
  372 + height:90px;
  373 + background:#eee;
363 374 }
364 375 }
365 376  
... ... @@ -465,10 +476,28 @@ img.lil_av {
465 476 border-top:none;
466 477  
467 478 form {
468   - padding-top:16px;
  479 + padding:9px 0;
  480 + margin:0px;
  481 + }
  482 +
  483 + .pills {
  484 + li {
  485 + padding:3px 0;
  486 + &.active a { background-color:$style_color; }
  487 + a {
  488 + border-radius:7px;
  489 + }
  490 + }
469 491 }
470 492 }
471 493  
  494 + .bottom {
  495 + background:#f5f5f5;
  496 + border-top: 1px solid #eee;
  497 + @include round-borders-bottom(4px);
  498 + border-bottom:none;
  499 + }
  500 +
472 501 &.padded {
473 502 h5, .title {
474 503 margin: -20px;
... ... @@ -847,14 +876,7 @@ p.time {
847 876 border:none;
848 877 &:hover {
849 878 background:none;
850   -
851   - h4 {
852   - color:#2FA0BB;
853   - .arrow {
854   - background:#2FA0BB;
855   - color:#fff;
856   - }
857   - }
  879 + h4 { color:#2FA0BB; }
858 880 }
859 881  
860 882 h4 {
... ... @@ -1042,4 +1064,18 @@ p.time {
1042 1064 color: #999;
1043 1065 line-height: 16px;
1044 1066 font-weight:bold;
1045   -}
  1067 +}
  1068 +
  1069 +.thin_area{
  1070 + height: 150px;
  1071 +}
  1072 +
  1073 +.gitlab_pagination {
  1074 + span a { color:$link_color; }
  1075 + .prev, .next, .current, .page a {
  1076 + padding:10px;
  1077 + }
  1078 + .current {
  1079 + border-bottom:2px solid $style_color;
  1080 + }
  1081 +}
... ...
app/controllers/dashboard_controller.rb
... ... @@ -13,6 +13,7 @@ class DashboardController < ApplicationController
13 13 @issues = @issues.includes(:author, :project)
14 14  
15 15 @events = Event.where(:project_id => @projects.map(&:id)).recent.limit(20)
  16 + @last_push = Event.where(:project_id => @projects.map(&:id)).recent.code_push.limit(1).first
16 17 end
17 18  
18 19 # Get authored or assigned open merge requests
... ...
app/controllers/issues_controller.rb
... ... @@ -28,9 +28,9 @@ class IssuesController < ApplicationController
28 28 when 2 then @project.issues.closed
29 29 when 3 then @project.issues.opened.assigned(current_user)
30 30 else @project.issues.opened
31   - end
  31 + end.page(params[:page]).per(20)
32 32  
33   - @issues = @issues.includes(:author, :project)
  33 + @issues = @issues.includes(:author, :project).order("critical, updated_at")
34 34  
35 35 respond_to do |format|
36 36 format.html # index.html.erb
... ... @@ -114,7 +114,7 @@ class IssuesController < ApplicationController
114 114 when 2 then @project.issues.closed
115 115 when 3 then @project.issues.opened.assigned(current_user)
116 116 else @project.issues.opened
117   - end
  117 + end.page(params[:page]).per(100)
118 118  
119 119 @issues = @issues.where("title LIKE ?", "%#{terms}%") unless terms.blank?
120 120  
... ...
app/controllers/merge_requests_controller.rb
... ... @@ -28,7 +28,7 @@ class MergeRequestsController < ApplicationController
28 28 when 2 then @merge_requests.closed
29 29 when 3 then @merge_requests.opened.assigned(current_user)
30 30 else @merge_requests.opened
31   - end
  31 + end.page(params[:page]).per(20)
32 32  
33 33 @merge_requests = @merge_requests.includes(:author, :project).order("created_at desc")
34 34 end
... ...
app/helpers/application_helper.rb
... ... @@ -11,6 +11,14 @@ module ApplicationHelper
11 11 true
12 12 end
13 13  
  14 + def request_protocol
  15 + request.ssl? ? "https" : "http"
  16 + end
  17 +
  18 + def web_app_url
  19 + "#{request_protocol}://#{GIT_HOST["host"]}/"
  20 + end
  21 +
14 22 def body_class(default_class = nil)
15 23 main = content_for(:body_class).blank? ?
16 24 default_class :
... ...
app/models/event.rb
... ... @@ -15,6 +15,7 @@ class Event < ActiveRecord::Base
15 15 serialize :data
16 16  
17 17 scope :recent, order("created_at DESC")
  18 + scope :code_push, where(:action => Pushed)
18 19  
19 20 def self.determine_action(record)
20 21 if [Issue, MergeRequest].include? record.class
... ...
app/models/user.rb
... ... @@ -5,13 +5,19 @@ class User < ActiveRecord::Base
5 5 :recoverable, :rememberable, :trackable, :validatable, :omniauthable
6 6  
7 7 # Setup accessible (or protected) attributes for your model
8   - attr_accessible :email, :password, :password_confirmation, :remember_me,
  8 + attr_accessible :email, :password, :password_confirmation, :remember_me, :bio,
9 9 :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme, :theme_id
10 10  
11 11 has_many :users_projects, :dependent => :destroy
12 12 has_many :projects, :through => :users_projects
13 13 has_many :my_own_projects, :class_name => "Project", :foreign_key => :owner_id
14 14 has_many :keys, :dependent => :destroy
  15 +
  16 + has_many :recent_events,
  17 + :class_name => "Event",
  18 + :foreign_key => :author_id,
  19 + :order => "id DESC"
  20 +
15 21 has_many :issues,
16 22 :foreign_key => :author_id,
17 23 :dependent => :destroy
... ... @@ -38,6 +44,7 @@ class User < ActiveRecord::Base
38 44 :presence => true,
39 45 :numericality => {:greater_than_or_equal_to => 0}
40 46  
  47 + validates :bio, :length => { :within => 0..255 }
41 48  
42 49 before_create :ensure_authentication_token
43 50 alias_attribute :private_token, :authentication_token
... ...
app/views/admin/projects/_form.html.haml
... ... @@ -20,7 +20,7 @@
20 20 Code
21 21 .input
22 22 .input-prepend
23   - %span.add-on= "http://#{GIT_HOST["host"]}/"
  23 + %span.add-on= web_app_url
24 24 = f.text_field :code, :placeholder => "example"
25 25  
26 26 - unless @admin_project.new_record?
... ...
app/views/admin/projects/index.html.haml
... ... @@ -19,4 +19,4 @@
19 19 %td= last_commit(project)
20 20 %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}", :class => "btn small"
21 21 %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
22   -= paginate @admin_projects
  22 += paginate @admin_projects, :theme => "admin"
... ...
app/views/admin/users/index.html.haml
... ... @@ -20,4 +20,4 @@
20 20 %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}", :class => "btn small"
21 21 %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger"
22 22  
23   -= paginate @admin_users
  23 += paginate @admin_users, :theme => "admin"
... ...
app/views/dashboard/_projects_feed.html.haml
... ... @@ -3,7 +3,7 @@
3 3 = link_to project do
4 4 %h4
5 5 %span.ico.project
6   - = project.name
  6 + = truncate project.name, :length => 30
7 7 %small
8 8 last activity at
9 9 = project.last_activity_date.stamp("Aug 25, 2011")
... ...
app/views/dashboard/index.html.haml
... ... @@ -20,17 +20,35 @@
20 20 .row
21 21 .dashboard_block
22 22 .row
23   - .span10= render "dashboard/projects_feed", :projects => @active_projects
24 23 .span4.right
25   - - if current_user.can_create_project?
26   - .alert-message.block-message.warning
27   - You can create up to
28   - = current_user.projects_limit
29   - projects. Click on link below to add a new one
30   - .link_holder
31   - = link_to new_project_path, :class => "" do
32   - New Project »
33   -
  24 + %div.borders.ipadded
  25 + %h1
  26 + = pluralize current_user.projects.count, "project", "projects"
  27 + - if current_user.can_create_project?
  28 + %hr
  29 + %div
  30 + You can create up to
  31 + = current_user.projects_limit
  32 + projects. Click on button below to add a new one
  33 + .link_holder
  34 + %br
  35 + = link_to new_project_path, :class => "btn" do
  36 + New Project »
  37 + - else
  38 + %hr
  39 + %div
  40 + You've reached project limit for your account.
  41 + You cannot create new projects.
  42 + .link_holder
  43 + %br
  44 + = link_to profile_path, :class => "btn" do
  45 + Your Profile »
  46 + .span10.left= render "dashboard/projects_feed", :projects => @active_projects
  47 + - if @last_push
  48 + .padded.prepend-top-20
  49 + %h5
  50 + %small Latest push was to the #{@last_push.branch_name} branch of #{@last_push.project.name}:
  51 + %ul.unstyled= render @last_push
34 52  
35 53 - if @merge_requests.any?
36 54 %div.dashboard_category
... ...
app/views/devise/sessions/new.html.erb
... ... @@ -9,6 +9,13 @@
9 9 <br/>
10 10 <%= f.submit "Sign in", :class => "primary btn" %>
11 11 <div class="right"> <%= render :partial => "devise/shared/links" %></div>
  12 +
  13 + <%- if devise_mapping.omniauthable? %>
  14 + <%- resource_class.omniauth_providers.each do |provider| %>
  15 + <hr/>
  16 + <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary" %><br />
  17 + <% end -%>
  18 + <% end -%>
12 19 <% if ldap_enable? -%>
13 20 <p><%= link_to "via LDAP", user_omniauth_authorize_path(:ldap)%></p>
14 21 <% end -%>
... ...
app/views/devise/shared/_links.erb
... ... @@ -17,9 +17,3 @@
17 17 <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18 18 <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
19 19 <% end -%>
20   -
21   -<%- if devise_mapping.omniauthable? %>
22   - <%- resource_class.omniauth_providers.each do |provider| %>
23   - <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
24   - <% end -%>
25   -<% end -%>
... ...
app/views/issues/_issues.html.haml
1   -- @issues.critical.each do |issue|
  1 +- @issues.select(&:critical).each do |issue|
2 2 = render(:partial => 'issues/show', :locals => {:issue => issue})
3 3  
4   -- @issues.non_critical.each do |issue|
  4 +- @issues.reject(&:critical).each do |issue|
5 5 = render(:partial => 'issues/show', :locals => {:issue => issue})
  6 +
  7 +- if @issues.present?
  8 + %li.bottom
  9 + .row
  10 + .span10= paginate @issues, :remote => true, :theme => "gitlab"
  11 + .span4.right
  12 + %span.cgray.right #{@issues.total_count} issues for this filter
... ...
app/views/issues/_show.html.haml
1 1 %li.wll{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(issue.project, issue) }
2 2 .right
3 3 - if issue.notes.any?
4   - %span.label= pluralize issue.notes.count, 'comment'
  4 + %span.btn.small.disabled.padded= pluralize issue.notes.count, 'note'
5 5 - if can? current_user, :modify_issue, issue
6 6 - if issue.closed
7   - = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn small", :remote => true
  7 + = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn small padded", :remote => true
8 8 - else
9   - = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "success btn small", :remote => true
  9 + = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "success btn small padded", :remote => true
10 10 = link_to 'Edit', edit_project_issue_path(issue.project, issue), :class => "btn small edit-issue-link", :remote => true
11 11 = image_tag gravatar_icon(issue.assignee_email), :class => "avatar"
12 12 %span.update-author
... ...
app/views/issues/index.html.haml
... ... @@ -38,7 +38,6 @@
38 38 - if @issues.blank?
39 39 %li
40 40 %p.padded Nothing to show here
41   -
42 41 :javascript
43 42 var href = $('.issue_search').parent().attr('action');
44 43 var last_terms = '';
... ...
app/views/kaminari/_first_page.html.haml
... ... @@ -1,9 +0,0 @@
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
... ... @@ -1,8 +0,0 @@
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
... ... @@ -1,9 +0,0 @@
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
... ... @@ -1,9 +0,0 @@
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
... ... @@ -1,10 +0,0 @@
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
... ... @@ -1,17 +0,0 @@
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
... ... @@ -1,9 +0,0 @@
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/kaminari/admin/_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/admin/_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/admin/_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/admin/_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/admin/_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/admin/_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/admin/_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/kaminari/gitlab/_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/gitlab/_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/gitlab/_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/gitlab/_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 +%span.next
  9 + = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
... ...
app/views/kaminari/gitlab/_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 +%span{:class => "page#{' current' if page.current?}"}
  10 + = link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
... ...
app/views/kaminari/gitlab/_paginator.html.haml 0 → 100644
... ... @@ -0,0 +1,16 @@
  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 + %nav.gitlab_pagination
  10 + = prev_page_tag
  11 + - each_page do |page|
  12 + - if page.left_outer? || page.right_outer? || page.inside_window?
  13 + = page_tag page
  14 + - elsif !page.was_truncated?
  15 + = gap_tag
  16 + = next_page_tag
... ...
app/views/kaminari/gitlab/_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 +%span.prev
  9 + = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
... ...
app/views/keys/_form.html.haml
... ... @@ -11,7 +11,7 @@
11 11 .input= f.text_field :title
12 12 .clearfix
13 13 = f.label :key
14   - .input= f.text_area :key, :class => "xlarge"
  14 + .input= f.text_area :key, :class => [:xxlarge, :thin_area]
15 15 .actions
16 16 = f.submit 'Save', :class => "primary btn"
17 17 = link_to "Cancel", keys_path, :class => "btn"
... ...
app/views/merge_requests/_how_to_merge.html.haml
... ... @@ -5,11 +5,10 @@
5 5 .modal-body
6 6 %pre
7 7 :erb
  8 + git checkout <%= @merge_request.target_branch %>
8 9 git fetch origin
9   - git checkout -b <%=@merge_request.source_branch%> origin/<%=@merge_request.source_branch%>
10   - git checkout <%=@merge_request.target_branch%>
11   - git merge <%=@merge_request.source_branch%>
12   - git push origin <%=@merge_request.target_branch%>
  10 + git merge origin/<%= @merge_request.source_branch %>
  11 + git push origin <%= @merge_request.target_branch %>
13 12  
14 13  
15 14 :javascript
... ...
app/views/merge_requests/_merge_request.html.haml
1 1 %li.wll
  2 + .right
  3 + .left
  4 + - if merge_request.notes.any?
  5 + %span.btn.small.disabled.padded= pluralize merge_request.notes.count, 'note'
  6 + %span.btn.small.disabled.padded
  7 + = merge_request.source_branch
  8 + &rarr;
  9 + = merge_request.target_branch
2 10 = image_tag gravatar_icon(merge_request.author_email), :class => "avatar"
3 11 %span.update-author
4 12 %strong= merge_request.author_name
5 13 authored
6 14 = time_ago_in_words(merge_request.created_at)
7 15 ago
8   - - if merge_request.notes.any?
9   - %span.pretty_label= pluralize merge_request.notes.count, 'note'
10 16 - if merge_request.upvotes > 0
11 17 %span.label.success= "+#{merge_request.upvotes}"
12   - .right
13   - %span.label= merge_request.source_branch
14   - &rarr;
15   - %span.label= merge_request.target_branch
16 18 = link_to project_merge_request_path(merge_request.project, merge_request) do
17   - %p.row_title= truncate(merge_request.title, :length => 100)
  19 + %p.row_title= truncate(merge_request.title, :length => 80)
... ...
app/views/merge_requests/index.html.haml
... ... @@ -27,5 +27,10 @@
27 27 - if @merge_requests.blank?
28 28 %li
29 29 %p.padded Nothing to show here
30   -
  30 + - if @merge_requests.present?
  31 + %li.bottom
  32 + .row
  33 + .span10= paginate @merge_requests, :theme => "gitlab"
  34 + .span4.right
  35 + %span.cgray.right #{@merge_requests.total_count} merge requests for this filter
31 36  
... ...
app/views/profile/show.html.haml
1   -.media-grid
2   - = link_to "#" do
3   - = image_tag gravatar_icon(@user.email, 90), :class => "thumbnail"
4   - %h3.media_h
5   - = @user.name
6   - %br
7   - %small
8   - = @user.email
9   -
10   - .right
11   - %p.alert-message.block-message You can change your avatar at gravatar.com
12   -
  1 +.row
  2 + .span10
  3 + .profile_avatar_holder
  4 + = image_tag gravatar_icon(@user.email, 90), :class => "styled_image"
  5 + %h3
  6 + = @user.name
  7 + %br
  8 + %small
  9 + = @user.email
  10 +
  11 + .span6.right
  12 + %div
  13 + %div
  14 + %h5.cgray
  15 + Personal projects:
  16 + %span.right
  17 + %span= current_user.my_own_projects.count
  18 + of
  19 + %span= current_user.projects_limit
  20 + %h5.cgray
  21 + SSH public keys:
  22 + %span.right
  23 + %span= current_user.keys.count
13 24 %hr
14 25  
15 26 = form_for @user, :url => profile_update_path, :method => :put do |f|
... ... @@ -18,23 +29,39 @@
18 29 %ul
19 30 - @user.errors.full_messages.each do |msg|
20 31 %li= msg
21   -
22   - .clearfix
23   - = f.label :name
24   - .input= f.text_field :name
25   - .clearfix
26   - = f.label :email
27   - .input= f.text_field :email
28   - .clearfix
29   - = f.label :skype
30   - .input= f.text_field :skype
31   - .clearfix
32   - = f.label :linkedin
33   - .input= f.text_field :linkedin
34   - .clearfix
35   - = f.label :twitter
36   - .input= f.text_field :twitter
  32 + .row
  33 + .span9
  34 + .clearfix
  35 + = f.label :name
  36 + .input
  37 + = f.text_field :name, :class => "xlarge"
  38 + %span.help-block Enter youre name, so people you know can recognize you.
  39 + .clearfix
  40 + = f.label :email
  41 + .input
  42 + = f.text_field :email, :class => "xlarge"
  43 + %span.help-block We also use email for avatar detection
  44 + .clearfix
  45 + = f.label :skype
  46 + .input= f.text_field :skype, :class => "xlarge"
  47 + .clearfix
  48 + = f.label :linkedin
  49 + .input= f.text_field :linkedin, :class => "xlarge"
  50 + .clearfix
  51 + = f.label :twitter
  52 + .input= f.text_field :twitter, :class => "xlarge"
  53 + .clearfix
  54 + = f.label :bio
  55 + .input
  56 + = f.text_area :bio, :rows => 6, :class => "xlarge", :maxlength => 250
  57 + %span.help-block About yourself in fewer than 250 characters.
  58 + .span7.right
  59 + %p.alert-message.block-message
  60 + %strong Tip:
  61 + You can change your avatar at gravatar.com
37 62  
38 63 .actions
39 64 = f.submit 'Save', :class => "primary btn"
40 65  
  66 +-#= link_to "New project", new_project_path, :class => "btn small padded"
  67 +-#= link_to "New public key", new_key_path, :class => "btn small"
... ...
app/views/projects/_form.html.haml
... ... @@ -19,7 +19,7 @@
19 19 Code
20 20 .input
21 21 .input-prepend
22   - %span.add-on= "http://#{GIT_HOST["host"]}/"
  22 + %span.add-on= web_app_url
23 23 = f.text_field :code, :placeholder => "example"
24 24  
25 25 - unless @project.new_record? || @project.heads.empty?
... ...
app/views/projects/empty.html.haml
... ... @@ -38,3 +38,7 @@
38 38 "git remote add origin #{@project.url_to_repo}",
39 39 "git push -u origin master"].join("\n")
40 40 = raw bash_lexer.highlight(exist_repo_setup_str)
  41 +
  42 + - if can? current_user, :admin_project, @project
  43 + .alert-message.block-message.error.prepend-top-20
  44 + = link_to 'Remove project', @project, :confirm => 'Are you sure?', :method => :delete, :class => "btn danger"
... ...
app/views/team_members/show.html.haml
1 1 - allow_admin = can? current_user, :admin_project, @project
2 2 - user = @team_member.user
3   -.media-grid
4   - = link_to "#" do
5   - = image_tag gravatar_icon(user.email, 60), :class => "thumbnail", :width => 60
6   - %h3.media_h
7   - = user.name
8   - %br
9   - %small= user.email
10   -
11   -.back_link
12   - = link_to team_project_path(@project), :class => "" do
13   - &larr; To team list
14 3  
15   -%br
16   -%table.zebra-striped.borders
17   - %tr
18   - %td Name
19   - %td= user.name
  4 +.row
  5 + .span8
  6 + .profile_avatar_holder
  7 + = image_tag gravatar_icon(user.email, 90), :class => "styled_image"
  8 + %h3
  9 + = user.name
  10 + %br
  11 + %small
  12 + = user.email
  13 + %br
  14 + .back_link
  15 + %br
  16 + = link_to team_project_path(@project), :class => "" do
  17 + &larr; To team list
20 18  
21   - %tr
22   - %td Email
23   - %td= user.email
  19 + .span8.right
  20 + %div
  21 + %div
  22 + %h5.cgray
  23 + Member since:
  24 + %span.right
  25 + = @team_member.created_at.stamp("Aug 21, 2011")
  26 + %h5.cgray
  27 + Project Access:
  28 + %small (#{link_to "read more", help_permissions_path, :class => "vlink"})
  29 + %span.right
  30 + = form_for(@team_member, :as => :team_member, :url => project_team_member_path(@project, @team_member)) do |f|
  31 + = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin
24 32  
25   - %tr
26   - %td Member since
27   - %td= @team_member.created_at.stamp("Aug 21, 2011")
28 33  
29   - %tr
30   - %td
31   - Project Access
32   - (#{link_to "read more", help_permissions_path, :class => "vlink"})
33   -
34   - %td
35   - = form_for(@team_member, :as => :team_member, :url => project_team_member_path(@project, @team_member)) do |f|
36   - = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin
37 34  
  35 +%div.prepend-top-20
38 36 - unless user.skype.empty?
39   - %tr
40   - %td Skype:
41   - %td= user.skype
  37 + %p
  38 + %b Skype:
  39 + = user.skype
42 40  
43 41 - unless user.linkedin.empty?
44   - %tr
45   - %td LinkedIn:
46   - %td= user.linkedin
  42 + %p
  43 + %b LinkedIn:
  44 + = user.linkedin
47 45  
48 46 - unless user.twitter.empty?
49   - %tr
50   - %td Twitter:
51   - %td= user.twitter
  47 + %p
  48 + %b Twitter:
  49 + = user.twitter
  50 + - unless user.bio.empty?
  51 + %p
  52 + %b Bio:
  53 + = user.bio
  54 +
  55 += render user.recent_events.limit(3)
  56 +
52 57  
53 58 - if can? current_user, :admin_project, @project
54 59 .actions
... ...
db/fixtures/development/004_teams.rb
1 1 UsersProject.seed(:id, [
2 2 { :id => 1, :project_id => 1, :user_id => 1, :project_access => UsersProject::MASTER },
3   - { :id => 2, :project_id => 1, :user_id => 2, :project_access => UsersProject::REPORTERW},
4   - { :id => 3, :project_id => 1, :user_id => 3, :project_access => UsersProject::REPORTERW},
  3 + { :id => 2, :project_id => 1, :user_id => 2, :project_access => UsersProject::REPORTER},
  4 + { :id => 3, :project_id => 1, :user_id => 3, :project_access => UsersProject::REPORTER},
5 5 { :id => 4, :project_id => 1, :user_id => 4, :project_access => UsersProject::REPORTER},
6 6 { :id => 5, :project_id => 1, :user_id => 5, :project_access => UsersProject::REPORTER},
7 7  
... ...
db/fixtures/development/005_issues.rb
... ... @@ -15,7 +15,25 @@ Issue.seed(:id, [
15 15 { :id => 13, :project_id => 3, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6)},
16 16 { :id => 14, :project_id => 3, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6)},
17 17 { :id => 15, :project_id => 3, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6)},
18   - { :id => 16, :project_id => 3, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6)}
  18 + { :id => 16, :project_id => 3, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6)},
  19 +
  20 + { :id => 21, :project_id => 1, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
  21 + { :id => 22, :project_id => 1, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
  22 + { :id => 23, :project_id => 1, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
  23 + { :id => 24, :project_id => 1, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
  24 + { :id => 25, :project_id => 1, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
  25 +
  26 + { :id => 26, :project_id => 2, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
  27 + { :id => 27, :project_id => 2, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
  28 + { :id => 28, :project_id => 2, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
  29 + { :id => 29, :project_id => 2, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
  30 + { :id => 30, :project_id => 2, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
  31 +
  32 + { :id => 32, :project_id => 3, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6)},
  33 + { :id => 33, :project_id => 3, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6)},
  34 + { :id => 34, :project_id => 3, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6)},
  35 + { :id => 35, :project_id => 3, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6)},
  36 + { :id => 36, :project_id => 3, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6)}
19 37 ])
20 38  
21 39  
... ...
db/migrate/20120323221339_add_bio_field_to_user.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +class AddBioFieldToUser < ActiveRecord::Migration
  2 + def change
  3 + add_column :users, :bio, :string, :null => true
  4 + end
  5 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20120315132931) do
  14 +ActiveRecord::Schema.define(:version => 20120323221339) do
15 15  
16 16 create_table "events", :force => true do |t|
17 17 t.string "target_type"
... ... @@ -156,6 +156,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120315132931) do
156 156 t.string "authentication_token"
157 157 t.boolean "dark_scheme", :default => false, :null => false
158 158 t.integer "theme_id", :default => 1, :null => false
  159 + t.string "bio"
159 160 end
160 161  
161 162 add_index "users", ["email"], :name => "index_users_on_email", :unique => true
... ...
doc/installation.md
... ... @@ -60,7 +60,7 @@ The installation consists of 6 steps:
60 60 # 2. Install ruby
61 61  
62 62 wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
63   - tar xfvz ruby-1.9.2-p290.tar.gz
  63 + tar xfv ruby-1.9.2-p290.tar.gz
64 64 cd ruby-1.9.2-p290
65 65 ./configure
66 66 make
... ... @@ -220,15 +220,11 @@ Edit /etc/nginx/nginx.conf. Add next code to **http** section:
220 220 server {
221 221 listen 80;
222 222 server_name mygitlab.com;
223   -
224   - location / {
225   -
226   - root /home/gitlab/gitlab/public;
227   -
228   - if (!-f $request_filename) {
229   - proxy_pass http://gitlab;
230   - break;
231   - }
  223 + root /home/gitlab/gitlab/public;
  224 + try_files $uri $uri/index.html $uri.html @gitlab;
  225 +
  226 + location @gitlab {
  227 + proxy_pass http://gitlab;
232 228 }
233 229  
234 230 }
... ...
resque.sh
1   -mkdir tmp/pids
2   -nohup bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production PIDFILE=tmp/pids/resque_worker.pid & >> log/resque_worker.log 2>&1
  1 +mkdir -p tmp/pids
  2 +bundle exec rake environment resque:work QUEUE=post_receive RAILS_ENV=production PIDFILE=tmp/pids/resque_worker.pid BACKGROUND=yes
... ...