Commit 2d887d91e18a07b5656ae40bf514af48a2709706

Authored by randx
2 parents 50a6c614 f417a265

Merge branch 'piffio-public_submission_milestones_for_mr'

app/assets/javascripts/merge_requests.js
@@ -115,4 +115,15 @@ var MergeRequest = { @@ -115,4 +115,15 @@ var MergeRequest = {
115 $(".merge_in_progress").hide(); 115 $(".merge_in_progress").hide();
116 $(".automerge_widget.already_cannot_be_merged").show(); 116 $(".automerge_widget.already_cannot_be_merged").show();
117 } 117 }
  118 +};
  119 +
  120 +/*
  121 + * Filter merge requests
  122 + */
  123 +function merge_requestsPage() {
  124 + $("#assignee_id").chosen();
  125 + $("#milestone_id").chosen();
  126 + $("#milestone_id, #assignee_id").on("change", function(){
  127 + $(this).closest("form").submit();
  128 + });
118 } 129 }
app/assets/javascripts/milestones.js.coffee
@@ -5,3 +5,10 @@ $ -> @@ -5,3 +5,10 @@ $ ->
5 $('.milestone-issue-filter li').toggleClass('active') 5 $('.milestone-issue-filter li').toggleClass('active')
6 $('.milestone-issue-filter tr[data-closed]').toggleClass('hide') 6 $('.milestone-issue-filter tr[data-closed]').toggleClass('hide')
7 false 7 false
  8 +
  9 + $('.milestone-merge-requests-filter tr[data-closed]').addClass('hide')
  10 +
  11 + $('.milestone-merge-requests-filter ul.nav li a').click ->
  12 + $('.milestone-merge-requests-filter li').toggleClass('active')
  13 + $('.milestone-merge-requests-filter tr[data-closed]').toggleClass('hide')
  14 + false
app/assets/stylesheets/common.scss
@@ -670,3 +670,16 @@ pre { @@ -670,3 +670,16 @@ pre {
670 padding:0; 670 padding:0;
671 } 671 }
672 } 672 }
  673 +
  674 +.milestone .progress {
  675 + margin-bottom: 0;
  676 + margin-top:4px;
  677 +}
  678 +
  679 +.float-link {
  680 + float:left;
  681 + margin-right:15px;
  682 + .s16 {
  683 + margin-right:5px;
  684 + }
  685 +}
app/assets/stylesheets/sections/merge_requests.scss
@@ -121,3 +121,20 @@ li.merge_request { @@ -121,3 +121,20 @@ li.merge_request {
121 .mr_direction_tip { 121 .mr_direction_tip {
122 margin-top:40px 122 margin-top:40px
123 } 123 }
  124 +
  125 +.merge_requests_form_box {
  126 + @extend .main_box;
  127 + .merge_requests_middle_box {
  128 + @extend .middle_box_content;
  129 + height:30px;
  130 + .merge_requests_assignee {
  131 + @extend .span6;
  132 + float:left;
  133 + }
  134 + .merge_requests_milestone {
  135 + @extend .span4;
  136 + float:left;
  137 + }
  138 + }
  139 +}
  140 +
app/contexts/merge_requests_load_context.rb
  1 +# Build collection of Merge Requests
  2 +# based on filtering passed via params for @project
1 class MergeRequestsLoadContext < BaseContext 3 class MergeRequestsLoadContext < BaseContext
2 def execute 4 def execute
3 type = params[:f] 5 type = params[:f]
@@ -9,8 +11,21 @@ class MergeRequestsLoadContext &lt; BaseContext @@ -9,8 +11,21 @@ class MergeRequestsLoadContext &lt; BaseContext
9 when 'closed' then merge_requests.closed 11 when 'closed' then merge_requests.closed
10 when 'assigned-to-me' then merge_requests.opened.assigned(current_user) 12 when 'assigned-to-me' then merge_requests.opened.assigned(current_user)
11 else merge_requests.opened 13 else merge_requests.opened
12 - end.page(params[:page]).per(20) 14 + end
13 15
14 - merge_requests.includes(:author, :project).order("closed, created_at desc") 16 + merge_requests = merge_requests.page(params[:page]).per(20)
  17 + merge_requests = merge_requests.includes(:author, :project).order("closed, created_at desc")
  18 +
  19 + # Filter by specific assignee_id (or lack thereof)?
  20 + if params[:assignee_id].present?
  21 + merge_requests = merge_requests.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
  22 + end
  23 +
  24 + # Filter by specific milestone_id (or lack thereof)?
  25 + if params[:milestone_id].present?
  26 + merge_requests = merge_requests.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
  27 + end
  28 +
  29 + merge_requests
15 end 30 end
16 end 31 end
app/controllers/milestones_controller.rb
@@ -31,7 +31,8 @@ class MilestonesController &lt; ProjectResourceController @@ -31,7 +31,8 @@ class MilestonesController &lt; ProjectResourceController
31 31
32 def show 32 def show
33 @issues = @milestone.issues 33 @issues = @milestone.issues
34 - @users = @milestone.participants 34 + @users = UserDecorator.decorate(@milestone.participants)
  35 + @merge_requests = @milestone.merge_requests
35 36
36 respond_to do |format| 37 respond_to do |format|
37 format.html 38 format.html
app/decorators/user_decorator.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class UserDecorator < ApplicationDecorator
  2 + decorates :user
  3 +
  4 + def avatar_image size = 16
  5 + h.image_tag h.gravatar_icon(self.email, size), class: "avatar #{"s#{size}"}", width: size
  6 + end
  7 +
  8 + def tm_of(project)
  9 + project.team_member_by_id(self.id)
  10 + end
  11 +end
app/helpers/projects_helper.rb
@@ -10,5 +10,9 @@ module ProjectsHelper @@ -10,5 +10,9 @@ module ProjectsHelper
10 def link_to_project project 10 def link_to_project project
11 link_to project.name, project 11 link_to project.name, project
12 end 12 end
  13 +
  14 + def tm_path team_member
  15 + project_team_member_path(@project, team_member)
  16 + end
13 end 17 end
14 18
app/models/merge_request.rb
1 require Rails.root.join("app/models/commit") 1 require Rails.root.join("app/models/commit")
  2 +require Rails.root.join("app/roles/static_model")
2 3
3 class MergeRequest < ActiveRecord::Base 4 class MergeRequest < ActiveRecord::Base
4 include IssueCommonality 5 include IssueCommonality
5 include Votes 6 include Votes
6 7
7 - attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, 8 + attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id,
8 :author_id_of_changes 9 :author_id_of_changes
9 10
10 attr_accessor :should_remove_source_branch 11 attr_accessor :should_remove_source_branch
11 12
  13 + belongs_to :milestone
  14 +
12 BROKEN_DIFF = "--broken-diff" 15 BROKEN_DIFF = "--broken-diff"
13 16
14 UNCHECKED = 1 17 UNCHECKED = 1
@@ -26,6 +29,10 @@ class MergeRequest &lt; ActiveRecord::Base @@ -26,6 +29,10 @@ class MergeRequest &lt; ActiveRecord::Base
26 where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name) 29 where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
27 end 30 end
28 31
  32 + def self.find_all_by_milestone(milestone)
  33 + where("milestone_id = :milestone_id", milestone_id: milestone)
  34 + end
  35 +
29 def human_state 36 def human_state
30 states = { 37 states = {
31 CAN_BE_MERGED => "can_be_merged", 38 CAN_BE_MERGED => "can_be_merged",
@@ -212,5 +219,6 @@ end @@ -212,5 +219,6 @@ end
212 # st_diffs :text(4294967295 219 # st_diffs :text(4294967295
213 # merged :boolean default(FALSE), not null 220 # merged :boolean default(FALSE), not null
214 # state :integer default(1), not null 221 # state :integer default(1), not null
  222 +# milestone_id :integer
215 # 223 #
216 224
app/models/milestone.rb
@@ -3,6 +3,7 @@ class Milestone &lt; ActiveRecord::Base @@ -3,6 +3,7 @@ class Milestone &lt; ActiveRecord::Base
3 3
4 belongs_to :project 4 belongs_to :project
5 has_many :issues 5 has_many :issues
  6 + has_many :merge_requests
6 7
7 validates :title, presence: true 8 validates :title, presence: true
8 validates :project, presence: true 9 validates :project, presence: true
@@ -15,8 +16,20 @@ class Milestone &lt; ActiveRecord::Base @@ -15,8 +16,20 @@ class Milestone &lt; ActiveRecord::Base
15 User.where(id: issues.pluck(:assignee_id)) 16 User.where(id: issues.pluck(:assignee_id))
16 end 17 end
17 18
  19 + def open_items_count
  20 + self.issues.opened.count + self.merge_requests.opened.count
  21 + end
  22 +
  23 + def closed_items_count
  24 + self.issues.closed.count + self.merge_requests.closed.count
  25 + end
  26 +
  27 + def total_items_count
  28 + self.issues.count + self.merge_requests.count
  29 + end
  30 +
18 def percent_complete 31 def percent_complete
19 - ((self.issues.closed.count * 100) / self.issues.count).abs 32 + ((closed_items_count * 100) / total_items_count).abs
20 rescue ZeroDivisionError 33 rescue ZeroDivisionError
21 100 34 100
22 end 35 end
app/views/merge_requests/_form.html.haml
@@ -28,16 +28,22 @@ @@ -28,16 +28,22 @@
28 %h4.cdark 2. Fill info 28 %h4.cdark 2. Fill info
29 29
30 .clearfix 30 .clearfix
31 - .main_box 31 + .merge_requests_form_box
32 .top_box_content 32 .top_box_content
33 = f.label :title do 33 = f.label :title do
34 %strong= "Title *" 34 %strong= "Title *"
35 .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5 35 .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5
36 - .middle_box_content  
37 - = f.label :assignee_id do  
38 - %i.icon-user  
39 - Assign to  
40 - .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'}) 36 + .merge_requests_middle_box
  37 + .merge_requests_assignee
  38 + = f.label :assignee_id do
  39 + %i.icon-user
  40 + Assign to
  41 + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
  42 + .merge_requests_milestone
  43 + = f.label :milestone_id do
  44 + %i.icon-time
  45 + Milestone
  46 + .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
41 47
42 .control-group 48 .control-group
43 49
app/views/merge_requests/_merge_request.html.haml
@@ -10,6 +10,10 @@ @@ -10,6 +10,10 @@
10 %span.btn.small.disabled.grouped 10 %span.btn.small.disabled.grouped
11 %i.icon-comment 11 %i.icon-comment
12 = merge_request.mr_and_commit_notes.count 12 = merge_request.mr_and_commit_notes.count
  13 + - if merge_request.milestone_id?
  14 + %span.btn.small.disabled.grouped
  15 + %i.icon-time
  16 + = merge_request.project.milestones.find(merge_request.milestone_id).title
13 %span.btn.small.disabled.grouped 17 %span.btn.small.disabled.grouped
14 = merge_request.source_branch 18 = merge_request.source_branch
15 &rarr; 19 &rarr;
app/views/merge_requests/index.html.haml
@@ -9,19 +9,26 @@ @@ -9,19 +9,26 @@
9 9
10 .ui-box 10 .ui-box
11 .title 11 .title
12 - %ul.nav.nav-pills  
13 - %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}  
14 - = link_to project_merge_requests_path(@project, f: 'open') do  
15 - Open  
16 - %li{class: ("active" if params[:f] == "closed")}  
17 - = link_to project_merge_requests_path(@project, f: "closed") do  
18 - Closed  
19 - %li{class: ("active" if params[:f] == 'assigned-to-me')}  
20 - = link_to project_merge_requests_path(@project, f: 'assigned-to-me') do  
21 - To Me  
22 - %li{class: ("active" if params[:f] == 'all')}  
23 - = link_to project_merge_requests_path(@project, f: 'all') do  
24 - All 12 + .left
  13 + %ul.nav.nav-pills
  14 + %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
  15 + = link_to project_merge_requests_path(@project, f: 'open', milestone_id: params[:milestone_id]) do
  16 + Open
  17 + %li{class: ("active" if params[:f] == "closed")}
  18 + = link_to project_merge_requests_path(@project, f: "closed", milestone_id: params[:milestone_id]) do
  19 + Closed
  20 + %li{class: ("active" if params[:f] == 'assigned-to-me')}
  21 + = link_to project_merge_requests_path(@project, f: 'assigned-to-me', milestone_id: params[:milestone_id]) do
  22 + To Me
  23 + %li{class: ("active" if params[:f] == 'all')}
  24 + = link_to project_merge_requests_path(@project, f: 'all', milestone_id: params[:milestone_id]) do
  25 + All
  26 + .right
  27 + = form_tag project_merge_requests_path(@project), id: "merge_requests_search_form", method: :get, class: :right do
  28 + = select_tag(:assignee_id, options_from_collection_for_select([unassigned_filter] + @project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee")
  29 + = select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + @project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), prompt: "Milestone")
  30 + = hidden_field_tag :f, params[:f]
  31 + .clearfix
25 32
26 %ul.unstyled 33 %ul.unstyled
27 = render @merge_requests 34 = render @merge_requests
@@ -35,3 +42,7 @@ @@ -35,3 +42,7 @@
35 .span4.right 42 .span4.right
36 %span.cgray.right #{@merge_requests.total_count} merge requests for this filter 43 %span.cgray.right #{@merge_requests.total_count} merge requests for this filter
37 44
  45 +:javascript
  46 + $(function() {
  47 + merge_requestsPage();
  48 + })
app/views/merge_requests/show/_mr_box.html.haml
@@ -14,9 +14,13 @@ @@ -14,9 +14,13 @@
14 %strong.author= link_to_merge_request_author(@merge_request) 14 %strong.author= link_to_merge_request_author(@merge_request)
15 15
16 - if @merge_request.assignee 16 - if @merge_request.assignee
17 - %cite.cgray and currently assigned to 17 + %cite.cgray , currently assigned to
18 = image_tag gravatar_icon(@merge_request.assignee_email), width: 16, class: "lil_av" 18 = image_tag gravatar_icon(@merge_request.assignee_email), width: 16, class: "lil_av"
19 %strong.author= link_to_merge_request_assignee(@merge_request) 19 %strong.author= link_to_merge_request_assignee(@merge_request)
  20 + - if @merge_request.milestone
  21 + - milestone = @merge_request.milestone
  22 + %cite.cgray and attached to milestone
  23 + %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
20 24
21 25
22 - if @merge_request.closed 26 - if @merge_request.closed
app/views/milestones/_milestone.html.haml
1 %li{class: "milestone", id: dom_id(milestone) } 1 %li{class: "milestone", id: dom_id(milestone) }
2 .right 2 .right
3 - - if milestone.issues.any?  
4 - %span.btn.small.disabled.grouped= pluralize milestone.issues.count, 'issues'  
5 - - if milestone.issues.count > 0  
6 - = link_to 'Browse Issues', project_issues_path(milestone.project, milestone_id: milestone.id), class: "btn small grouped"  
7 - if can? current_user, :admin_milestone, milestone.project 3 - if can? current_user, :admin_milestone, milestone.project
8 - = link_to 'Edit', edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" 4 + = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
  5 + %i.icon-edit
  6 + Edit
9 %h4 7 %h4
10 - = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone), class: "row_title" 8 + = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
11 %small 9 %small
12 = milestone.expires_at 10 = milestone.expires_at
13 - %br  
14 - .progress.progress-success.span3 11 + .row
  12 + .progress.progress-info.span4
15 .bar{style: "width: #{milestone.percent_complete}%;"} 13 .bar{style: "width: #{milestone.percent_complete}%;"}
  14 + .span6
  15 + - if milestone.issues.any?
  16 + = link_to project_issues_path(milestone.project, milestone_id: milestone.id), class: "btn very_small" do
  17 + %strong= pluralize milestone.issues.count, 'Issue'
16 18
17 -  
18 - &nbsp; 19 + - if milestone.merge_requests.any?
  20 + = link_to project_merge_requests_path(milestone.project, milestone_id: milestone.id), class: "btn very_small" do
  21 + %strong= pluralize milestone.issues.count, 'Merge Request'
app/views/milestones/show.html.haml
@@ -31,10 +31,10 @@ @@ -31,10 +31,10 @@
31 %h5 31 %h5
32 Progress: 32 Progress:
33 %small 33 %small
34 - #{@milestone.issues.closed.count} closed 34 + #{@milestone.closed_items_count} closed
35 &ndash; 35 &ndash;
36 - #{@milestone.issues.opened.count} open  
37 - .progress.progress-success 36 + #{@milestone.open_items_count} open
  37 + .progress.progress-info
38 .bar{style: "width: #{@milestone.percent_complete}%;"} 38 .bar{style: "width: #{@milestone.percent_complete}%;"}
39 39
40 40
@@ -58,15 +58,28 @@ @@ -58,15 +58,28 @@
58 %span.badge.badge-info ##{issue.id} 58 %span.badge.badge-info ##{issue.id}
59 &ndash; 59 &ndash;
60 = link_to_gfm truncate(issue.title, length: 60), [@project, issue] 60 = link_to_gfm truncate(issue.title, length: 60), [@project, issue]
61 - %br  
62 61
63 .span6 62 .span6
64 - %table 63 + %table.milestone-merge-requests-filter
65 %thead 64 %thead
66 - %th Participants  
67 - - @users.each do |user|  
68 - %tr 65 + %th
  66 + %ul.nav.nav-pills
  67 + %li.active= link_to('Open Merge Requests', '#')
  68 + %li=link_to('All Merge Requests', '#')
  69 + - @merge_requests.each do |merge_request|
  70 + %tr{data: {closed: merge_request.closed}}
69 %td 71 %td
70 - = image_tag gravatar_icon(user.email, 24), width: "24"  
71 - &nbsp;  
72 - = user.name 72 + = link_to [@project, merge_request] do
  73 + %span.badge.badge-info ##{merge_request.id}
  74 + &ndash;
  75 + = link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request]
  76 +
  77 +%hr
  78 +%h6 Participants:
  79 +%div
  80 + - @users.each do |user|
  81 + = link_to tm_path(user.tm_of(@project)), class: 'float-link' do
  82 + = user.avatar_image
  83 + = user.name
  84 +
  85 +.clearfix
db/migrate/20121026114600_add_milestone_id_to_merge_requests.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddMilestoneIdToMergeRequests < ActiveRecord::Migration
  2 + def change
  3 + add_column :merge_requests, :milestone_id, :integer, :null => true
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20121009205010) do 14 +ActiveRecord::Schema.define(:version => 20121026114600) do
15 15
16 create_table "events", :force => true do |t| 16 create_table "events", :force => true do |t|
17 t.string "target_type" 17 t.string "target_type"
@@ -73,6 +73,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121009205010) do @@ -73,6 +73,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121009205010) do
73 t.text "st_diffs", :limit => 2147483647 73 t.text "st_diffs", :limit => 2147483647
74 t.boolean "merged", :default => false, :null => false 74 t.boolean "merged", :default => false, :null => false
75 t.integer "state", :default => 1, :null => false 75 t.integer "state", :default => 1, :null => false
  76 + t.integer "milestone_id"
76 end 77 end
77 78
78 add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id" 79 add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"