#214: updated UI of PullRequest#show

This commit is contained in:
Vokhmin Alexey V 2013-07-12 18:21:46 +04:00
parent c286dc4c87
commit ffcdd26c66
16 changed files with 194 additions and 40 deletions

View File

@ -1,4 +1,4 @@
RosaABF.controller('ProjectRefsController', function($scope, $http, $location, ApiProject) { RosaABF.controller('ProjectRefsController', function($scope, $http, ApiProject) {
$scope.branches = []; $scope.branches = [];
$scope.tags = []; $scope.tags = [];
@ -38,7 +38,7 @@ RosaABF.controller('ProjectRefsController', function($scope, $http, $location, A
}; };
$scope.destroy = function(branch) { $scope.destroy = function(branch) {
$http.delete(branch.delete_path($scope.project)).success(function(data) { $http.delete(branch.delete_path($scope.project.fullname)).success(function(data) {
$scope.getRefs(); $scope.getRefs();
}); });
} }

View File

@ -0,0 +1,72 @@
RosaABF.controller('PullRequestController', function($scope, $http, ApiPullRequest, ApiProject) {
$scope.project_id = null;
$scope.serial_id = null;
$scope.pull = null;
$scope.pull_request = null;
$scope.merged_at = null;
$scope.closed_at = null;
$scope.branch = null;
$scope.can_delete_branch = false;
$scope.init = function(project_id, serial_id) {
$scope.project_id = project_id;
$scope.serial_id = serial_id;
$scope.getPullRequest();
}
$scope.getPullRequest = function() {
$scope.pull_request = ApiPullRequest.resource.get(
{project_id: $scope.project_id, serial_id: $scope.serial_id},
function(results) {
$scope.pull = results.pull_request;
if ($scope.pull.merged_at) { $scope.merged_at = new Date($scope.pull.merged_at * 1000).toUTCString(); }
if ($scope.pull.closed_at) { $scope.closed_at = new Date($scope.pull.closed_at * 1000).toUTCString(); }
if ($scope.can_delete_branch) { $scope.getBranch(); }
}
);
}
$scope.getBranch = function() {
//returns [ProjectRef, ProjectRef, ...]
ApiProject.refs($scope.project_id, function(results){
_.each(results, function(result){
if (!result.isTag && result.ref == $scope.pull.from_ref.ref) {
$scope.branch = true;
return true;
}
});
});
}
$scope.reopen = function() {
$scope.pull.status = 'reopen';
$scope.pull_request.$update(function() {
$scope.getPullRequest();
});
}
$scope.close = function() {
$scope.pull.status = 'close';
$scope.pull_request.$update(function() {
$scope.getPullRequest();
});
}
$scope.deleteBranch = function() {
$http.delete($scope.branch_path())
.success(function(data) { $scope.branch = null; })
.error(function() { $scope.branch = null; });
}
$scope.restoreBranch = function() {
$http.put($scope.branch_path(), {sha: $scope.pull.from_ref.sha})
.success(function(data) { $scope.branch = true; });
}
$scope.branch_path = function() {
return '/' + $scope.pull.from_ref.project.fullname + '/branches/' + $scope.pull.from_ref.ref;
}
});

View File

@ -16,8 +16,12 @@ var ProjectRef = function(atts) {
return '/' + project.fullname + '/tree/' + self.ref; return '/' + project.fullname + '/tree/' + self.ref;
} }
self.delete_path = function(project) { self.restore_path = function(project_fullname) {
return '/' + project.fullname + '/branches/' + self.ref; return '/' + project_fullname + '/branches/' + self.ref;
}
self.delete_path = function(project_fullname) {
return '/' + project_fullname + '/branches/' + self.ref;
} }
self.diff_path = function(project, current_ref) { self.diff_path = function(project, current_ref) {

View File

@ -0,0 +1,40 @@
var ApiPullRequest = function($resource) {
var PullRequest = $resource(
'/api/v1/projects/:project_id/pull_requests/:serial_id.json', {},
{
get: {method:'GET', isArray: false},
update: {
method:'PUT',
params:{
project_id:'@pull_request.to_ref.project.id',
serial_id: '@pull_request.number'
}, isArray : false
}
}
);
// var queryPullRequest = function(project_id, serial_id, next) {
// PullRequest.get({project_id: project_id, serial_id: serial_id}, function(results) {
// next(results.pull_request);
// });
// }
// var queryUpdatePullRequest = function(project_id, serial_id, params, next) {
// PullRequest.put({
// project_id: project_id,
// serial_id: serial_id,
// pull_request: params
// }, function(results) {
// next(results);
// });
// }
return {
// pullRequest : queryPullRequest,
// updatePullRequest : queryUpdatePullRequest,
resource : PullRequest
}
}
RosaABF.factory("ApiPullRequest", ApiPullRequest);

View File

@ -744,7 +744,7 @@ div.admin-role {
padding-right: 10px; padding-right: 10px;
} }
article a.right_floated { .right_floated {
float: right; float: right;
} }

View File

@ -32,9 +32,14 @@ class Projects::Git::TreesController < Projects::Git::BaseController
def tags def tags
end end
def restore_branch
sha = params[:sha]
@project.restore_branch @treeish, sha if @treeish.present? && sha.present?
render :nothing => true
end
def destroy def destroy
raise Grit::NoSuchPathError unless @branch @project.delete_branch @branch, current_user if @branch
@project.delete_branch @branch, current_user
render :nothing => true render :nothing => true
end end

View File

@ -8,9 +8,9 @@ module PullRequestHelper
(common_comments + pull_comments + commits).sort_by{ |c| c[0] }.map{ |c| c[1] } (common_comments + pull_comments + commits).sort_by{ |c| c[0] }.map{ |c| c[1] }
end end
def pull_status_label pull def pull_status_label pull_status, options = {}
statuses = {'ready' => 'success', 'closed' => 'important', 'merged' => 'important', 'blocked' => 'warning'} statuses = {'ready' => 'success', 'closed' => 'important', 'merged' => 'important', 'blocked' => 'warning'}
content_tag :span, t("projects.pull_requests.statuses.#{pull.status}"), :class => "state label-bootstrap label-#{statuses[pull.status]}" content_tag :span, t("projects.pull_requests.statuses.#{pull_status}"), options.merge(:class => "state label-bootstrap label-#{statuses[pull_status]}")
end end
def pull_status pull def pull_status pull

View File

@ -49,6 +49,10 @@ class PullRequest < ActiveRecord::Base
end end
end end
def cross_pull?
from_project_id != to_project_id
end
def check(do_transaction = true) def check(do_transaction = true)
if do_transaction && !valid? if do_transaction && !valid?
issue.set_close nil issue.set_close nil

View File

@ -109,7 +109,7 @@ class CommentPresenter < ApplicationPresenter
statuses = {'open' => 'success', 'closed' => 'important'} statuses = {'open' => 'success', 'closed' => 'important'}
content_tag :span, t("layout.issues.status.#{@referenced_issue.status}"), :class => "state label-bootstrap label-#{statuses[@referenced_issue.status]}" content_tag :span, t("layout.issues.status.#{@referenced_issue.status}"), :class => "state label-bootstrap label-#{statuses[@referenced_issue.status]}"
else else
pull_status_label @referenced_issue pull_status_label @referenced_issue.status
end.html_safe end.html_safe
end end
end end

View File

@ -1,7 +1,7 @@
json.issue do |json| json.pull_request do |json|
json.partial! 'pull', :pull => @pull, :json => json json.partial! 'pull', :pull => @pull, :json => json
json.body @pull.body json.body @pull.body
json.closed_at pull.issue.closed_at.to_i if @pull.merged? || @pull.closed? json.closed_at @pull.issue.closed_at.to_i if @pull.merged? || @pull.closed?
json.closed_by do |json_user| json.closed_by do |json_user|
json.partial! 'api/v1/shared/member', :member => @pull.issue.closer, :tag => json_user json.partial! 'api/v1/shared/member', :member => @pull.issue.closer, :tag => json_user
end if @pull.issue.closer end if @pull.issue.closer

View File

@ -1,3 +1,3 @@
tag.(member, :id, :name) tag.(member, :id, :name, :uname)
tag.type member.class.name tag.type member.class.name
tag.url member_path(member) tag.url member_path(member)

View File

@ -2,14 +2,34 @@
%br %br
=form_for PullRequest.new, :url => merge_project_pull_request_path(@project, @pull), :html => { :method => :put, :class => :form } do |f| =form_for PullRequest.new, :url => merge_project_pull_request_path(@project, @pull), :html => { :method => :put, :class => :form } do |f|
=f.submit t 'projects.pull_requests.ready' =f.submit t 'projects.pull_requests.ready'
-else
.flash .flash{'ng-show' => '!pull.mergeable'}
%div{:class => @pull.ready? ? 'notice' : 'alert'} .notice{'ng-show' => "pull.status == 'blocked'"}
=pull_status @pull = t "projects.pull_requests.blocked"
wwwww .alert{'ng-show' => "pull.status == 'merged'"}
-if can? :update, @pull = t("projects.pull_requests.merged",
-if action = @pull.can_close? ? 'close' : ('reopen' if @pull.can_reopen?) :user => '{{pull.merged_by.uname}}',
:to_ref => show_ref(@pull, 'to'),
:from_ref => show_ref(@pull, 'from'),
:time => '{{merged_at}}').html_safe
.alert{'ng-show' => "pull.status == 'closed'"}
= t("projects.pull_requests.closed",
:user => '{{pull.closed_by.uname}}',
:time => '{{closed_at}}')
- if !@pull.cross_pull? && can?(:write, @project)
%div{'ng-init' => 'can_delete_branch = true', 'ng-show' => "pull.status == 'closed' || pull.status == 'merged'"}
%br %br
=form_for :pull, :url => [@project, @pull], :html => { :id => 'do_pull_action',:method => :put, :class => :form } do |f| %a.button{:href => '', 'ng-click' => 'deleteBranch()', 'ng-show' => "branch"}
=hidden_field_tag "pull_request_action", action = t('layout.projects.delete_branch')
=f.submit t ".#{action}" %a.button{:href => '', 'ng-click' => 'restoreBranch()', 'ng-hide' => "branch"}
= t('layout.projects.restore_branch')
-if can? :update, @pull
%br
%a.button{:href => '', 'ng-click' => 'reopen()', 'ng-show' => "pull.status == 'closed'"}
= t '.reopen'
%a.button{:href => '', 'ng-click' => 'close()', 'ng-show' => "pull.status == 'ready' || pull.status == 'open' || pull.status == 'blocked'"}
= t '.close'

View File

@ -1,19 +1,23 @@
-ar = 'activerecord.attributes.pull_requests' -ar = 'activerecord.attributes.pull_requests'
-set_meta_tags :title => [title_object(@project), t('.title', :name => @pull.title.truncate(40), :user => @pull.user.try(:uname))] -set_meta_tags :title => [title_object(@project), t('.title', :name => @pull.title.truncate(40), :user => @pull.user.try(:uname))]
= render :partial => 'submenu' = render :partial => 'submenu'
%h3.bpadding10
=pull_status_label @pull %div{'ng-controller' => 'PullRequestController', 'ng-init' => "init('#{@project.id}', '#{@pull.serial_id}')"}
=pull_header @pull
#repo-wrapper %h3.bpadding10
=render 'nav_tabs' - PullRequest::STATUSES.each do |status|
.tab-content.pull_diff_fix = pull_status_label status, {'ng-show' => "pull.status == '#{status}'"}
#discussion.tab-pane.active = pull_header @pull
=render 'projects/issues/header' #repo-wrapper
=render 'activity' =render 'nav_tabs'
%br .tab-content.pull_diff_fix
=render "projects/comments/add", :project => @project, :commentable => @issue if current_user #discussion.tab-pane.active
.pull_status =render 'projects/issues/header'
=render 'status' =render 'activity'
=render 'diff_commits_tabs' unless @pull.already? %br
=hidden_field_tag :preview_url, project_md_preview_path(@project) =render "projects/comments/add", :project => @project, :commentable => @issue if current_user
= render "projects/comments/markdown_help" .pull_status
=render 'status'
=render 'diff_commits_tabs' unless @pull.already?
=hidden_field_tag :preview_url, project_md_preview_path(@project)
= render "projects/comments/markdown_help"

View File

@ -21,7 +21,7 @@ ru:
ready: Данный пул реквест можно смержить автоматически. ready: Данный пул реквест можно смержить автоматически.
merged: | merged: |
%{user} смержил <span class="label-bootstrap label-info font14">%{to_ref}</span> %{user} смержил <span class="label-bootstrap label-info font14">%{to_ref}</span>
с <span class="label-bootstrap label-info font14">%{from_ref}</span> в %{time}' с <span class="label-bootstrap label-info font14">%{from_ref}</span> в %{time}
closed: '%{user} закрыл пул реквест в %{time}' closed: '%{user} закрыл пул реквест в %{time}'
is_big: Этот пул реквест слишком большой! Мы показываем только последние %{count} коммитов. is_big: Этот пул реквест слишком большой! Мы показываем только последние %{count} коммитов.
open: '' open: ''

View File

@ -334,6 +334,7 @@ Rosa::Application.routes.draw do
# Branches # Branches
get '/branches/:treeish' => "git/trees#branches", :as => :branches get '/branches/:treeish' => "git/trees#branches", :as => :branches
delete '/branches/:treeish' => "git/trees#destroy", :as => :branches delete '/branches/:treeish' => "git/trees#destroy", :as => :branches
put '/branches/:treeish' => "git/trees#restore_branch", :as => :branches
# Commits # Commits
get '/commits/:treeish(/*path)' => "git/commits#index", :as => :commits, :format => false get '/commits/:treeish(/*path)' => "git/commits#index", :as => :commits, :format => false
get '/commit/:id(.:format)' => "git/commits#show", :as => :commit get '/commit/:id(.:format)' => "git/commits#show", :as => :commit

View File

@ -33,6 +33,10 @@ module Modules
repo.tags.map(&:name) + repo.branches.map(&:name) repo.tags.map(&:name) + repo.branches.map(&:name)
end end
def restore_branch(branch, sha)
repo.git.native(:branch, {}, 'branch', branch, sha)
end
def delete_branch(branch, user) def delete_branch(branch, user)
message = repo.git.native(:branch, {}, '-D', branch.name) message = repo.git.native(:branch, {}, '-D', branch.name)
Resque.enqueue(GitHook,owner.uname, name, GitHook::ZERO, branch.commit.id, "refs/heads/#{branch.name}", 'commit', "user-#{user.id}", message) Resque.enqueue(GitHook,owner.uname, name, GitHook::ZERO, branch.commit.id, "refs/heads/#{branch.name}", 'commit', "user-#{user.id}", message)