Commit 6c47bcef02c96ab61e2bd632d01f03fa1c8340e6

Authored by Dmitriy Zaporozhets
2 parents 713802fd e8860594

Merge branch 'refactor_merge_requests'

app/assets/images/.directory
1 [Dolphin] 1 [Dolphin]
2 ShowPreview=true 2 ShowPreview=true
3 -Timestamp=2011,10,28,13,16,25 3 +Timestamp=2011,12,13,12,22,12
4 Version=2 4 Version=2
app/assets/javascripts/merge_requests.js
@@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
  1 +var MergeRequest = {
  2 + diffs_loaded: false,
  3 + commits_loaded: false,
  4 +
  5 + init:
  6 + function() {
  7 + $(".merge-tabs a").live("click", function() {
  8 + $(".merge-tabs a").removeClass("active");
  9 + $(this).addClass("active");
  10 + });
  11 +
  12 + $(".merge-tabs a.merge-notes-tab").live("click", function() {
  13 + $(".merge-request-commits, .merge-request-diffs").hide();
  14 + $(".merge-request-notes").show();
  15 + });
  16 +
  17 + $(".merge-tabs a.merge-commits-tab").live("click", function() {
  18 + if(!MergeRequest.commits_loaded) {
  19 + MergeRequest.loadCommits();
  20 + }
  21 + $(".merge-request-notes, .merge-request-diffs").hide();
  22 + $(".merge-request-commits").show();
  23 + });
  24 +
  25 + $(".merge-tabs a.merge-diffs-tab").live("click", function() {
  26 + if(!MergeRequest.diffs_loaded) {
  27 + MergeRequest.loadDiff();
  28 + }
  29 + $(".merge-request-notes, .merge-request-commits").hide();
  30 + $(".merge-request-diffs").show();
  31 + });
  32 + },
  33 +
  34 + loadCommits:
  35 + function() {
  36 + $(".dashboard-loader").show();
  37 + $.ajax({
  38 + type: "GET",
  39 + url: $(".merge-commits-tab").attr("data-url"),
  40 + complete: function(){
  41 + MergeRequest.commits_loaded = true;
  42 + $(".merge-request-notes, .merge-request-diffs").hide();
  43 + $(".dashboard-loader").hide()},
  44 + dataType: "script"});
  45 + },
  46 +
  47 + loadDiff:
  48 + function() {
  49 + $(".dashboard-loader").show();
  50 + $.ajax({
  51 + type: "GET",
  52 + url: $(".merge-diffs-tab").attr("data-url"),
  53 + complete: function(){
  54 + MergeRequest.diffs_loaded = true;
  55 + $(".merge-request-notes, .merge-request-commits").hide();
  56 + $(".dashboard-loader").hide()},
  57 + dataType: "script"});
  58 + }
  59 +}
app/assets/stylesheets/projects.css.scss
@@ -438,42 +438,6 @@ body.project-page table.no-borders td{ @@ -438,42 +438,6 @@ body.project-page table.no-borders td{
438 border:none; 438 border:none;
439 } 439 }
440 440
441 -#gitlab-tabs {  
442 - .ui-tabs-nav {  
443 - border-bottom: 1px solid #DEDFE1;  
444 -  
445 - li {  
446 - background: none;  
447 - border:none;  
448 - font-size: 16px;  
449 - margin: 0;  
450 - padding: 0;  
451 -  
452 - a {  
453 - margin: 0;  
454 - padding: 10px 16px;  
455 - width:150px;  
456 - }  
457 -  
458 - &.ui-tabs-selected {  
459 - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));  
460 - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);  
461 - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);  
462 - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);  
463 - font-weight: bold;  
464 - border:1px solid #DEDFE1;  
465 - border-bottom: 1px solid #DEDFE1;  
466 - -webkit-border-top-left-radius: 5px;  
467 - -webkit-border-top-right-radius: 5px;  
468 - -moz-border-radius-topleft: 5px;  
469 - -moz-border-radius-topright: 5px;  
470 - border-top-left-radius: 5px;  
471 - border-top-right-radius: 5px;  
472 - }  
473 - }  
474 - }  
475 -}  
476 -  
477 .ajax-tab-loading { 441 .ajax-tab-loading {
478 padding:40px; 442 padding:40px;
479 display:none; 443 display:none;
@@ -587,3 +551,82 @@ h4.middle-panel { @@ -587,3 +551,82 @@ h4.middle-panel {
587 margin-right:30px; 551 margin-right:30px;
588 display:none; 552 display:none;
589 } 553 }
  554 +
  555 +.merge-tabs {
  556 + margin: 0;
  557 + border: 1px solid #ccc;
  558 + padding: 5px;
  559 + font-size: 12px;
  560 + background: #F7F7F7;
  561 + margin-bottom:20px;
  562 + height:26px;
  563 +
  564 + .tab {
  565 + font-weight: bold;
  566 + text-transform: uppercase;
  567 + border-right: 1px solid #ddd;
  568 + background:none;
  569 + padding: 10px;
  570 + width:60px;
  571 + float:left;
  572 + position:relative;
  573 + top:-5px;
  574 + left:-5px;
  575 + height:16px;
  576 + padding-left:34px;
  577 +
  578 + span {
  579 + width: 20px;
  580 + height: 20px;
  581 + display: inline-block;
  582 + position: absolute;
  583 + left: 8px;
  584 + top: 8px;
  585 + }
  586 +
  587 + &.active {
  588 + background: #eaeaea;
  589 + }
  590 + }
  591 +}
  592 +
  593 +.merge-notes-tab span { background: url("images.png") no-repeat -161px -1px; }
  594 +.merge-commits-tab span { background: url("images.png") no-repeat -86px 1px; }
  595 +.merge-diffs-tab span { background: url("images.png") no-repeat -118px 1px; }
  596 +.merge-tabs .dashboard-loader { padding:8px; }
  597 +
  598 +.user-mention {
  599 + color: #2FA0BB;
  600 + font-weight: bold;
  601 +}
  602 +
  603 +.author {
  604 + color: #999;
  605 +}
  606 +
  607 +
  608 +.red-button{
  609 + border-radius: 5px;
  610 + font-size: 12px;
  611 + font-weight: bold;
  612 + padding: 5px 17px;
  613 + border: 1px solid #999;
  614 + color: #666;
  615 + display: inline-block;
  616 + box-shadow: 0 1px 2px rgba(0,0,0,.3);
  617 + background: #D12F19;
  618 + color: white;
  619 +}
  620 +
  621 +.positive-button{
  622 + border-radius: 5px;
  623 + font-size: 12px;
  624 + font-weight: bold;
  625 + padding: 5px 17px;
  626 + border: 1px solid #999;
  627 + color: #666;
  628 + display: inline-block;
  629 + box-shadow: 0 1px 2px rgba(0,0,0,.3);
  630 + background: #4A2;
  631 + color: white;
  632 +}
app/assets/stylesheets/style.scss
@@ -130,7 +130,7 @@ table tr:hover, .listed_items tr.odd:hover{background-color:#FFFFCF} @@ -130,7 +130,7 @@ table tr:hover, .listed_items tr.odd:hover{background-color:#FFFFCF}
130 border-radius: 5px; 130 border-radius: 5px;
131 font-size: 12px; 131 font-size: 12px;
132 font-weight: bold; 132 font-weight: bold;
133 - padding: 6px 20px; 133 + padding: 5px 17px;
134 border: 1px solid #999; 134 border: 1px solid #999;
135 color: #666; 135 color: #666;
136 display: inline-block; 136 display: inline-block;
app/controllers/merge_requests_controller.rb
@@ -30,14 +30,11 @@ class MergeRequestsController < ApplicationController @@ -30,14 +30,11 @@ class MergeRequestsController < ApplicationController
30 30
31 def commits 31 def commits
32 @commits = @project.repo.commits_between(@merge_request.target_branch, @merge_request.source_branch).map {|c| Commit.new(c)} 32 @commits = @project.repo.commits_between(@merge_request.target_branch, @merge_request.source_branch).map {|c| Commit.new(c)}
33 - render :template => "merge_requests/_commits", :layout => false  
34 end 33 end
35 34
36 def diffs 35 def diffs
37 @diffs = @merge_request.diffs 36 @diffs = @merge_request.diffs
38 @commit = @merge_request.last_commit 37 @commit = @merge_request.last_commit
39 -  
40 - render :template => "merge_requests/_diffs", :layout => false  
41 end 38 end
42 39
43 def new 40 def new
app/models/project.rb
@@ -90,6 +90,10 @@ class Project < ActiveRecord::Base @@ -90,6 +90,10 @@ class Project < ActiveRecord::Base
90 users_projects.find_by_user_id(user.id) if user 90 users_projects.find_by_user_id(user.id) if user
91 end 91 end
92 92
  93 + def team_member_by_id(user_id)
  94 + users_projects.find_by_user_id(user_id)
  95 + end
  96 +
93 def fresh_issues(n) 97 def fresh_issues(n)
94 issues.includes(:project, :author).order("created_at desc").first(n) 98 issues.includes(:project, :author).order("created_at desc").first(n)
95 end 99 end
app/views/merge_requests/_form.html.haml
1 -%div.merge-request-form-holder  
2 - .ui-box.width-100p  
3 - %h3  
4 - = @merge_request.new_record? ? "New Merge Request" : "Edit Merge Request ##{@merge_request.id}"  
5 - = form_for [@project, @merge_request] do |f|  
6 - .data  
7 - %table.no-borders  
8 - -if @merge_request.errors.any?  
9 - %tr  
10 - %td Errors  
11 - %td  
12 - #error_explanation  
13 - - @merge_request.errors.full_messages.each do |msg|  
14 - %span= msg  
15 - %br 1 += form_for [@project, @merge_request] do |f|
  2 + %div
  3 + %span.entity-info
  4 + - if @merge_request.new_record?
  5 + = link_to project_merge_requests_path(@project) do
  6 + .entity-button
  7 + Back
  8 + %i
  9 + - else
  10 + = link_to project_merge_request_path(@project, @merge_request) do
  11 + .entity-button
  12 + Back
  13 + %i
  14 +
  15 + %h2= @merge_request.new_record? ? "New Merge Request" : "Edit Merge Request ##{@merge_request.id}"
  16 +
  17 + %hr
  18 + %table.no-borders
  19 + -if @merge_request.errors.any?
  20 + %tr
  21 + %td{:colspan => 2}
  22 + #error_explanation
  23 + - @merge_request.errors.full_messages.each do |msg|
  24 + %span= msg
  25 + %br
  26 + %tr
  27 + %td= f.label :source_branch, "From"
  28 + %td= f.select(:source_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px")
  29 + %tr
  30 + %td= f.label :target_branch, "To"
  31 + %td= f.select(:target_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px")
  32 + %tr
  33 + %td= f.label :assignee_id, "Assign to"
  34 + %td= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, :style => "width:250px")
  35 + = f.text_area :title, :style => "width:718px; height:100px", :maxlength => 255
  36 + %br
  37 + %br
  38 + .merge-tabs
  39 + = f.submit 'Save', :class => "grey-button"
  40 +  
  41 + - unless @merge_request.new_record?
  42 + .right
  43 + = link_to 'Remove', [@project, @merge_request], :confirm => 'Are you sure?', :method => :delete, :class => "red-button"
  44 +
  45 +
16 46
17 - %tr  
18 - %td= f.label :title  
19 - %td= f.text_field :title  
20 - %tr  
21 - %td= f.label :source_branch, "From"  
22 - %td= f.select(:source_branch, @project.heads.map(&:name), { :include_blank => "Select branch" })  
23 - %tr  
24 - %td= f.label :target_branch, "To"  
25 - %td= f.select(:target_branch, @project.heads.map(&:name), { :include_blank => "Select branch" })  
26 - %tr  
27 - %td= f.label :assignee_id, "Assign to"  
28 - %td= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" })  
29 - .buttons  
30 - = f.submit 'Save', :class => "grey-button"  
31 - .right= link_to 'Back', project_merge_requests_path(@project), :class => "grey-button"  
32 47
33 :javascript 48 :javascript
34 $(function(){ 49 $(function(){
app/views/merge_requests/_merge_request.html.haml
1 %a.update-item{:href => project_merge_request_path(merge_request.project, merge_request)} 1 %a.update-item{:href => project_merge_request_path(merge_request.project, merge_request)}
2 = image_tag gravatar_icon(merge_request.author_email), :class => "left", :width => 40 2 = image_tag gravatar_icon(merge_request.author_email), :class => "left", :width => 40
3 %span.update-title 3 %span.update-title
4 - = merge_request.title 4 + = truncate(merge_request.title, :length => 60)
5 %span.update-author 5 %span.update-author
6 %strong= merge_request.author_name 6 %strong= merge_request.author_name
7 authored 7 authored
app/views/merge_requests/commits.js.haml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +:plain
  2 + $(".merge-request-commits").html("#{escape_javascript(render(:partial => "commits"))}");
  3 +
  4 +
app/views/merge_requests/diffs.js.haml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +:plain
  2 + $(".merge-request-diffs").html("#{escape_javascript(render(:partial => "diffs"))}");
  3 +
  4 +
app/views/merge_requests/show.html.haml
1 -.merge-request-show-holder.ui-box.width-100p  
2 - %h3  
3 - = "Merge Request ##{@merge_request.id}:"  
4 -    
5 - .tag.commit.inline= @merge_request.source_branch  
6 - →  
7 - .tag.commit.inline= @merge_request.target_branch  
8 - .right  
9 - - if @merge_request.closed  
10 - %span.tag.high Closed  
11 - - else  
12 - %span.tag.today Open  
13 -  
14 - .data  
15 - %p= @merge_request.title  
16 -  
17 - - if @merge_request.author == @merge_request.assignee  
18 - = image_tag gravatar_icon(@merge_request.assignee_email), :width => 20, :style => "padding:0 5px;"  
19 - = @merge_request.assignee_name  
20 - - else  
21 - = image_tag gravatar_icon(@merge_request.author_email), :width => 20, :style => "padding:0 5px;"  
22 - = @merge_request.author_name 1 +%div
  2 + %span.entity-info
  3 + - if can?(current_user, :admin_project, @project) || @merge_request.author == current_user
  4 + = link_to edit_project_merge_request_path(@project, @merge_request) do
  5 + .entity-button
  6 + Edit Merge Request
  7 + %i
  8 + = image_tag gravatar_icon(@merge_request.author_email), :class => "left", :width => 40, :style => "padding-right:5px;"
  9 + %span.commit-title
  10 + %strong
  11 + = "Merge Request ##{@merge_request.id}:"
  12 +  
  13 + .tag.commit.inline= @merge_request.source_branch
23 → 14 →
24 - = image_tag gravatar_icon(@merge_request.assignee_email), :width => 20, :style => "padding:0 5px;"  
25 - = @merge_request.assignee_name  
26 - .right  
27 - %cite.cgray= @merge_request.created_at.stamp("21 Aug 2011, 11:15pm")  
28 - .clear 15 + .tag.commit.inline= @merge_request.target_branch
  16 + %span.commit-author
  17 + %strong
  18 + = link_to project_team_member_path(@project, @project.team_member_by_id(@merge_request.author.id)) do
  19 + %span.author= @merge_request.author_name
  20 + →
  21 + = link_to project_team_member_path(@project, @project.team_member_by_id(@merge_request.assignee.id)) do
  22 + %span.author= @merge_request.assignee_name
29 23
30 - .buttons  
31 - - if can? current_user, :write_project, @project  
32 - - if @merge_request.closed  
33 - = link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "grey-button"  
34 - - else  
35 - = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "grey-button"  
36 - .right  
37 - = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), :class => "grey-button positive" 24 +  
  25 +  
  26 + = @merge_request.created_at.stamp("Aug 21, 2011 9:23pm")
  27 +
  28 + %hr
  29 + %br
  30 + %h3
  31 + = simple_format @merge_request.title
38 32
39 .clear 33 .clear
40 %br 34 %br
41 %br 35 %br
42 36
43 -#gitlab-tabs  
44 - %ul  
45 - %li= link_to "Notes", "#merge-notes"  
46 - %li= link_to "Commits", commits_project_merge_request_path(@project, @merge_request)  
47 - %li= link_to "Diff", diffs_project_merge_request_path(@project, @merge_request) 37 +.merge-tabs
  38 + = link_to "#notes", :class => "merge-notes-tab active tab" do
  39 + %span
  40 + Notes
  41 + = link_to "#commits", "data-url" => commits_project_merge_request_path(@project, @merge_request), :class => "merge-commits-tab tab" do
  42 + %span
  43 + Commits
  44 + = link_to "#diffs", "data-url" => diffs_project_merge_request_path(@project, @merge_request), :class => "merge-diffs-tab tab" do
  45 + %span
  46 + Diff
  47 +
  48 + - if can?(current_user, :admin_project, @project) || @merge_request.author == current_user
  49 + .right
  50 + - if @merge_request.closed
  51 + = link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "red-button"
  52 + - else
  53 + = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "positive-button", :title => "Close merge request"
  54 + %img{:src => "/assets/ajax-loader-facebook.gif", :class => "dashboard-loader"}
  55 +
  56 +.merge-request-notes
  57 + .issue_notes= render "notes/notes"
  58 + .loading{ :style => "display:none;"}
  59 + %center= image_tag "ajax-loader.gif"
  60 + .clear
48 61
49 - #merge-notes  
50 - .issue_notes= render "notes/notes"  
51 - .loading{ :style => "display:none;"}  
52 - %center= image_tag "ajax-loader.gif"  
53 - .clear 62 +.merge-request-commits
  63 +.merge-request-diffs
54 64
55 65
56 :javascript 66 :javascript
57 $(function(){ 67 $(function(){
58 - $("#gitlab-tabs").tabs(); 68 + MergeRequest.init();
59 }) 69 })
spec/requests/merge_requests_spec.rb
@@ -42,8 +42,8 @@ describe "MergeRequests" do @@ -42,8 +42,8 @@ describe "MergeRequests" do
42 42
43 it { should have_content(@merge_request.title) } 43 it { should have_content(@merge_request.title) }
44 it "Show page should inform user that merge request closed" do 44 it "Show page should inform user that merge request closed" do
45 - within ".merge-request-show-holder h3" do  
46 - page.should have_content "Closed" 45 + within ".merge-tabs" do
  46 + page.should have_content "Reopen"
47 end 47 end
48 end 48 end
49 end 49 end
@@ -62,7 +62,7 @@ describe "MergeRequests" do @@ -62,7 +62,7 @@ describe "MergeRequests" do
62 it { current_path.should == project_merge_request_path(project, project.merge_requests.last) } 62 it { current_path.should == project_merge_request_path(project, project.merge_requests.last) }
63 63
64 it "should create merge request" do 64 it "should create merge request" do
65 - page.should have_content "Open" 65 + page.should have_content "Close"
66 page.should have_content @user.name 66 page.should have_content @user.name
67 end 67 end
68 end 68 end
vendor/assets/stylesheets/jquery-ui/jquery-ui.css
1 /* 1 /*
2 - * jQuery UI CSS Framework 1.8.16 2 + * jQuery UI CSS Framework 1.8.16 Patched for GitLab HQ
3 * 3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses. 5 * Dual licensed under the MIT or GPL Version 2 licenses.