[issue #347] Merge branch 'master' into 347-javascript_refactoring
Conflicts: app/assets/stylesheets/design/custom.scss app/models/group.rb app/models/user.rb
This commit is contained in:
commit
510b0c0c50
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -60,4 +60,15 @@ $(document).ready(function() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.description-top .git_help').click(function() {
|
||||||
|
$('#git_help_data').toggle();
|
||||||
|
var desc = $('.description-top');
|
||||||
|
|
||||||
|
if ($('#git_help_data').css('display') == 'none') {
|
||||||
|
desc.css('height', '38px');
|
||||||
|
} else {
|
||||||
|
desc.css('height', '196px');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,32 +3,35 @@ $(document).ready(function() {
|
||||||
var platform_id = $(this).val();
|
var platform_id = $(this).val();
|
||||||
var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids');
|
var base_platforms = $('.all_platforms input[type=checkbox].build_bpl_ids');
|
||||||
|
|
||||||
//$('#include_repos').html($('.preloaded_include_repos .include_repos_' + platform_id).html());
|
|
||||||
|
|
||||||
base_platforms.each(function(){
|
base_platforms.each(function(){
|
||||||
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) >= 0) {
|
if ($.inArray(platform_id, base_platforms.map(function(){ return $(this).val() }).get()) >= 0) {
|
||||||
if ($(this).val() == platform_id) {
|
if ($(this).val() == platform_id) {
|
||||||
$(this).attr('checked', 'checked');
|
if ($(this).attr('data-released') === '1') {
|
||||||
$(this).removeAttr('disabled');
|
$('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
$('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).attr('checked', 'checked').removeAttr('disabled').trigger('change');
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled');
|
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled');
|
||||||
if ($(this).parent().find('.offset25 label').text() == 'main') {
|
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').attr('checked', 'checked');
|
var rep_name = $('#build_list_pl_id option[value="' + $(this).val() + '"]').text().match(/[\w-]+\/([\w-]+)/)[1];
|
||||||
|
if (rep_name != 'main') {
|
||||||
|
$(this).parent().find('.offset25 input[type="checkbox"][rep_name="' + rep_name + '"]').attr('checked', 'checked');
|
||||||
|
}
|
||||||
|
$(this).parent().find('.offset25 input[type="checkbox"][rep_name="main"]').attr('checked', 'checked');
|
||||||
|
} else {
|
||||||
|
$(this).removeAttr('checked').attr('disabled', 'disabled').trigger('change');
|
||||||
|
$(this).parent().find('.offset25 input[type="checkbox"]').attr('disabled', 'disabled').removeAttr('checked');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$(this).removeAttr('checked');
|
$(this).removeAttr('disabled').removeAttr('checked').trigger('change');
|
||||||
$(this).attr('disabled', 'disabled');
|
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled').removeAttr('checked');
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').attr('disabled', 'disabled');
|
$('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('checked');
|
|
||||||
}
|
|
||||||
//$('.additional_pl').parent().find('.offset25 input[type="checkbox"]').attr('disabled', 'disabled');
|
|
||||||
} else {
|
|
||||||
$(this).removeAttr('disabled');
|
|
||||||
$(this).removeAttr('checked');
|
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled');
|
|
||||||
$(this).parent().find('.offset25 input[type="checkbox"]').removeAttr('checked');
|
|
||||||
//$('.additional_pl').parent().find('.offset25 input[type="checkbox"]').removeAttr('disabled');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setBranchSelected();
|
||||||
});
|
});
|
||||||
$('#build_list_pl_id').trigger('change');
|
$('#build_list_pl_id').trigger('change');
|
||||||
|
|
||||||
|
@ -38,11 +41,45 @@ $(document).ready(function() {
|
||||||
$('.offset25 input[type="checkbox"]').click(function() {
|
$('.offset25 input[type="checkbox"]').click(function() {
|
||||||
setPlChecked(this, $(this).attr('checked'));
|
setPlChecked(this, $(this).attr('checked'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.build_bpl_ids').click(function() {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function setPlChecked(pointer, checked) {
|
function setPlChecked(pointer, checked) {
|
||||||
pl_cbx = $(pointer).parent().parent().parent().find('input[type="checkbox"].build_bpl_ids');
|
var pl_cbx = $(pointer).parent().parent().parent().find('input[type="checkbox"].build_bpl_ids');
|
||||||
|
var pl_id = pl_cbx.val();
|
||||||
if (checked && !$(pointer).attr('disabled')) {
|
if (checked && !$(pointer).attr('disabled')) {
|
||||||
pl_cbx.attr('checked', 'checked');
|
pl_cbx.attr('checked', 'checked').trigger('change');
|
||||||
|
} else if ($('input[pl_id=' + pl_id + '][checked="checked"]').size() == 0) {
|
||||||
|
pl_cbx.removeAttr('checked').trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBranchSelected() {
|
||||||
|
var pl_id = $('#build_list_pl_id').val();
|
||||||
|
// Checks if selected platform is main or not:
|
||||||
|
if ( $('.all_platforms').find('input[type="checkbox"][value=' + pl_id + '].build_bpl_ids').size() > 0 ) {
|
||||||
|
var pl_name = $('#build_list_pl_id option[value="' + pl_id + '"]').text().match(/([\w-]+)\/[\w-]+/)[1];
|
||||||
|
var branch_pl_opt = $('#build_list_project_version option[value="latest_' + pl_name + '"]');
|
||||||
|
// If there is branch we need - set it selected:
|
||||||
|
if ( branch_pl_opt.size() > 0 ) {
|
||||||
|
$('#build_list_project_version option[selected]').removeAttr('selected');
|
||||||
|
branch_pl_opt.attr('selected', 'selected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function platformChange() {
|
||||||
|
var rel = !!$('input[type="checkbox"].build_bpl_ids').filter(function(index) {
|
||||||
|
var $this = $(this);
|
||||||
|
return !!$this.attr('checked') && ($this.attr('data-released') === '1');
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
if (rel) {
|
||||||
|
$('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
$('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,28 +128,28 @@ $(document).ready(function() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
function remExecutor(form) {
|
function remAssignee(form) {
|
||||||
var el = form.find('.people.selected.remove_executor');
|
var el = form.find('.people.selected.remove_assignee');
|
||||||
var id = el.attr('id');
|
var id = el.attr('id');
|
||||||
$('#manage_issue_users_list .add_executor.people.selected').removeClass('select');
|
$('#manage_issue_users_list .add_assignee.people.selected').removeClass('select');
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.add_executor.people.selected').live('click', function() {
|
$('.add_assignee.people.selected').live('click', function() {
|
||||||
var form_new = $('form.issue');
|
var form_new = $('form.issue');
|
||||||
var form_edit = $('form.edit_form.issue');
|
var form_edit = $('form.edit_form.issue');
|
||||||
form_new.find('#people-span').fadeOut(0);
|
form_new.find('#people-span').fadeOut(0);
|
||||||
remExecutor(form_new);
|
remAssignee(form_new);
|
||||||
var clone = $(this).clone().removeClass('add_executor').addClass('remove_executor');
|
var clone = $(this).clone().removeClass('add_assignee').addClass('remove_assignee');
|
||||||
form_new.find('#issue_executor').html(clone);
|
form_new.find('#issue_assignee').html(clone);
|
||||||
$('.current_executor').html(clone.removeClass('select'));
|
$('.current_assignee').html(clone.removeClass('select'));
|
||||||
$(this).addClass('select');
|
$(this).addClass('select');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.remove_executor.people.selected').live('click', function() {
|
$('.remove_assignee.people.selected').live('click', function() {
|
||||||
var form = $('form.issue, form.edit_form issue');
|
var form = $('form.issue, form.edit_form issue');
|
||||||
form.find('#people-span').fadeIn(0);
|
form.find('#people-span').fadeIn(0);
|
||||||
remExecutor(form);
|
remAssignee(form);
|
||||||
});
|
});
|
||||||
|
|
||||||
function remLabel(form, id) {
|
function remLabel(form, id) {
|
||||||
|
@ -241,9 +241,9 @@ $(document).ready(function() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.button.manage_executor').live('click', function() {
|
$('.button.manage_assignee').live('click', function() {
|
||||||
$('form#search_user, .button.update_executor').fadeIn(0);
|
$('form#search_user, .button.update_assignee').fadeIn(0);
|
||||||
$('.current_executor .people').addClass('remove_executor selected').removeClass('nopointer');
|
$('.current_assignee .people').addClass('remove_assignee selected').removeClass('nopointer');
|
||||||
$(this).fadeOut(0);
|
$(this).fadeOut(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -254,16 +254,16 @@ $(document).ready(function() {
|
||||||
$(this).fadeOut(0);
|
$(this).fadeOut(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.button.update_executor').live('click', function() {
|
$('.button.update_assignee').live('click', function() {
|
||||||
var form = $('form.edit_executor.issue');
|
var form = $('form.edit_assignee.issue');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: form.attr("action"),
|
url: form.attr("action"),
|
||||||
data: form.serialize(),
|
data: form.serialize(),
|
||||||
success: function(data){
|
success: function(data){
|
||||||
$('.current_executor .people').removeClass('remove_executor selected').addClass('nopointer');
|
$('.current_assignee .people').removeClass('remove_assignee selected').addClass('nopointer');
|
||||||
$('form#search_user, .button.update_executor').fadeOut(0);
|
$('form#search_user, .button.update_assignee').fadeOut(0);
|
||||||
$('.button.manage_executor').fadeIn(0);
|
$('.button.manage_assignee').fadeIn(0);
|
||||||
$('#manage_issue_users_list').html('');
|
$('#manage_issue_users_list').html('');
|
||||||
},
|
},
|
||||||
error: function(data){
|
error: function(data){
|
||||||
|
|
|
@ -851,3 +851,73 @@ input.placeholder,
|
||||||
textarea.placeholder {
|
textarea.placeholder {
|
||||||
color: #CFCFCF;
|
color: #CFCFCF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.description-top div.git_help {
|
||||||
|
float: left;
|
||||||
|
margin-top: 11px;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: green;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#git_help_data {
|
||||||
|
display: none;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#git_help_data p {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for bootstrap
|
||||||
|
.close {
|
||||||
|
float: right;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #000000;
|
||||||
|
text-shadow: 0 1px 0 #ffffff;
|
||||||
|
opacity: 0.2;
|
||||||
|
filter: alpha(opacity=20);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close:hover {
|
||||||
|
color: #000000;
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.4;
|
||||||
|
filter: alpha(opacity=40);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
margin: -150px 0 0 -280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#forkModal.modal .btn.btn-primary {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zip {
|
||||||
|
float: left;
|
||||||
|
padding-left: 5px;
|
||||||
|
margin-top: 6px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav > li > a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: #DCECFA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown.open .dropdown-toggle {
|
||||||
|
background: none repeat scroll 0 0;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,9 @@ class ActivityFeedsController < ApplicationController
|
||||||
@activity_feeds = current_user.activity_feeds
|
@activity_feeds = current_user.activity_feeds
|
||||||
@activity_feeds = @activity_feeds.where(:kind => "ActivityFeed::#{@filter.upcase}".constantize) unless @filter == :all
|
@activity_feeds = @activity_feeds.where(:kind => "ActivityFeed::#{@filter.upcase}".constantize) unless @filter == :all
|
||||||
@activity_feeds = @activity_feeds.paginate :page => params[:page]
|
@activity_feeds = @activity_feeds.paginate :page => params[:page]
|
||||||
if request.format == '*/*'
|
respond_to do |format|
|
||||||
render '_list', :layout => false
|
format.html { request.xhr? ? render('_list', :layout => false) : render('index') }
|
||||||
else
|
format.atom
|
||||||
render 'index'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,9 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
layout :layout_by_resource
|
layout :layout_by_resource
|
||||||
|
|
||||||
|
# Hack to prevent token auth on all pages except atom feed:
|
||||||
|
prepend_before_filter lambda { redirect_to(new_user_session_path) if params[:token] && params[:format] != 'atom'}
|
||||||
|
|
||||||
before_filter :set_locale
|
before_filter :set_locale
|
||||||
before_filter lambda { EventLog.current_controller = self },
|
before_filter lambda { EventLog.current_controller = self },
|
||||||
:only => [:create, :destroy, :open_id, :cancel, :publish, :change_visibility] # :update
|
:only => [:create, :destroy, :open_id, :cancel, :publish, :change_visibility] # :update
|
||||||
|
|
|
@ -7,8 +7,9 @@ class BuildListsController < ApplicationController
|
||||||
before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS
|
before_filter :authenticate_build_service!, :only => CALLBACK_ACTIONS
|
||||||
skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access']
|
skip_before_filter :authenticate_user!, :only => [:show, :index, :search] if APP_CONFIG['anonymous_access']
|
||||||
before_filter :find_project, :only => NESTED_ACTIONS
|
before_filter :find_project, :only => NESTED_ACTIONS
|
||||||
before_filter :find_build_list, :only => [:show, :publish, :cancel]
|
before_filter :find_build_list, :only => [:show, :publish, :cancel, :reject_publish]
|
||||||
before_filter :find_build_list_by_bs, :only => [:publish_build, :status_build, :pre_build, :post_build, :circle_build]
|
before_filter :find_build_list_by_bs, :only => [:publish_build, :status_build, :pre_build, :post_build, :circle_build]
|
||||||
|
before_filter :find_platform, :only => [:create]
|
||||||
|
|
||||||
load_and_authorize_resource :project, :only => NESTED_ACTIONS
|
load_and_authorize_resource :project, :only => NESTED_ACTIONS
|
||||||
load_and_authorize_resource :build_list, :through => :project, :only => NESTED_ACTIONS, :shallow => true
|
load_and_authorize_resource :build_list, :through => :project, :only => NESTED_ACTIONS, :shallow => true
|
||||||
|
@ -40,12 +41,13 @@ class BuildListsController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
notices, errors = [], []
|
notices, errors = [], []
|
||||||
|
params[:build_list].delete(:auto_publish) if @platform.released
|
||||||
Arch.where(:id => params[:arches]).each do |arch|
|
Arch.where(:id => params[:arches]).each do |arch|
|
||||||
Platform.main.where(:id => params[:bpls]).each do |bpl|
|
Platform.main.where(:id => params[:bpls]).each do |bpl|
|
||||||
@build_list = @project.build_lists.build(params[:build_list])
|
@build_list = @project.build_lists.build(params[:build_list])
|
||||||
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version
|
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version
|
||||||
@build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user
|
@build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user
|
||||||
@build_list.include_repos = @build_list.include_repos.select { |ir| @build_list.bpl.repository_ids.include? ir.to_i }
|
@build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.bpl.repository_ids.include? ir.to_i}
|
||||||
@build_list.priority = 100 # User builds more priority than mass rebuild with zero priority
|
@build_list.priority = 100 # User builds more priority than mass rebuild with zero priority
|
||||||
flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl}
|
flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl}
|
||||||
if @build_list.save
|
if @build_list.save
|
||||||
|
@ -78,6 +80,14 @@ class BuildListsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reject_publish
|
||||||
|
if @build_list.reject_publish
|
||||||
|
redirect_to :back, :notice => t('layout.build_lists.reject_publish_success')
|
||||||
|
else
|
||||||
|
redirect_to :back, :notice => t('layout.build_lists.reject_publish_fail')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def cancel
|
def cancel
|
||||||
if @build_list.cancel
|
if @build_list.cancel
|
||||||
redirect_to :back, :notice => t('layout.build_lists.cancel_success')
|
redirect_to :back, :notice => t('layout.build_lists.cancel_success')
|
||||||
|
@ -94,7 +104,6 @@ class BuildListsController < ApplicationController
|
||||||
else
|
else
|
||||||
@build_list.status = BuildList::FAILED_PUBLISH
|
@build_list.status = BuildList::FAILED_PUBLISH
|
||||||
end
|
end
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -106,7 +115,6 @@ class BuildListsController < ApplicationController
|
||||||
@item.save
|
@item.save
|
||||||
|
|
||||||
@build_list.container_path = params[:container_path]
|
@build_list.container_path = params[:container_path]
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -114,7 +122,6 @@ class BuildListsController < ApplicationController
|
||||||
|
|
||||||
def pre_build
|
def pre_build
|
||||||
@build_list.status = BuildServer::BUILD_STARTED
|
@build_list.status = BuildServer::BUILD_STARTED
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -123,7 +130,6 @@ class BuildListsController < ApplicationController
|
||||||
def post_build
|
def post_build
|
||||||
@build_list.status = params[:status]
|
@build_list.status = params[:status]
|
||||||
@build_list.container_path = params[:container_path]
|
@build_list.container_path = params[:container_path]
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -134,7 +140,6 @@ class BuildListsController < ApplicationController
|
||||||
def circle_build
|
def circle_build
|
||||||
@build_list.is_circle = true
|
@build_list.is_circle = true
|
||||||
@build_list.container_path = params[:container_path]
|
@build_list.container_path = params[:container_path]
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -147,7 +152,6 @@ class BuildListsController < ApplicationController
|
||||||
@build_list.set_items(ActiveSupport::JSON.decode(params[:items]))
|
@build_list.set_items(ActiveSupport::JSON.decode(params[:items]))
|
||||||
@build_list.is_circle = (params[:is_circular].to_i != 0)
|
@build_list.is_circle = (params[:is_circular].to_i != 0)
|
||||||
@build_list.bs_id = params[:id]
|
@build_list.bs_id = params[:id]
|
||||||
@build_list.notified_at = Time.current
|
|
||||||
@build_list.save
|
@build_list.save
|
||||||
|
|
||||||
render :nothing => true, :status => 200
|
render :nothing => true, :status => 200
|
||||||
|
@ -159,6 +163,10 @@ class BuildListsController < ApplicationController
|
||||||
@project = Project.find_by_id params[:project_id]
|
@project = Project.find_by_id params[:project_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_platform
|
||||||
|
@platform = Platform.find params[:build_list][:pl_id]
|
||||||
|
end
|
||||||
|
|
||||||
def find_build_list
|
def find_build_list
|
||||||
@build_list = BuildList.find(params[:id])
|
@build_list = BuildList.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,26 +1,17 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
class CommentsController < ApplicationController
|
class CommentsController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
|
load_and_authorize_resource :project
|
||||||
|
before_filter :find_commentable
|
||||||
|
before_filter :find_or_build_comment
|
||||||
|
load_and_authorize_resource
|
||||||
|
|
||||||
load_resource :project
|
include CommentsHelper
|
||||||
before_filter :set_commentable
|
|
||||||
before_filter :find_comment, :only => [:edit, :update, :destroy]
|
|
||||||
authorize_resource
|
|
||||||
|
|
||||||
def index
|
|
||||||
@comments = @commentable.comments
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@comment = @commentable.comments.build(params[:comment]) if @commentable.class == Issue
|
|
||||||
if @commentable.class == Grit::Commit
|
|
||||||
@comment = Comment.new(params[:comment].merge(:commentable_id => @commentable.id.hex, :commentable_type => @commentable.class.name))
|
|
||||||
end
|
|
||||||
@comment.project = @project
|
|
||||||
@comment.user_id = current_user.id
|
|
||||||
if @comment.save
|
if @comment.save
|
||||||
flash[:notice] = I18n.t("flash.comment.saved")
|
flash[:notice] = I18n.t("flash.comment.saved")
|
||||||
redirect_to commentable_path
|
redirect_to project_commentable_path(@project, @commentable)
|
||||||
else
|
else
|
||||||
flash[:error] = I18n.t("flash.comment.save_error")
|
flash[:error] = I18n.t("flash.comment.save_error")
|
||||||
render :action => 'new'
|
render :action => 'new'
|
||||||
|
@ -28,19 +19,12 @@ class CommentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@update_url = case @commentable.class.name
|
|
||||||
when "Issue"
|
|
||||||
project_issue_comment_path(@project, @commentable, @comment)
|
|
||||||
when "Grit::Commit"
|
|
||||||
project_commit_comment_path(@project, @commentable, @comment)
|
|
||||||
end
|
|
||||||
@commentable_path = commentable_path
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if @comment.update_attributes(params[:comment])
|
if @comment.update_attributes(params[:comment])
|
||||||
flash[:notice] = I18n.t("flash.comment.saved")
|
flash[:notice] = I18n.t("flash.comment.saved")
|
||||||
redirect_to commentable_path
|
redirect_to project_commentable_path(@project, @commentable)
|
||||||
else
|
else
|
||||||
flash[:error] = I18n.t("flash.comment.save_error")
|
flash[:error] = I18n.t("flash.comment.save_error")
|
||||||
render :action => 'new'
|
render :action => 'new'
|
||||||
|
@ -49,30 +33,19 @@ class CommentsController < ApplicationController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@comment.destroy
|
@comment.destroy
|
||||||
|
|
||||||
flash[:notice] = t("flash.comment.destroyed")
|
flash[:notice] = t("flash.comment.destroyed")
|
||||||
redirect_to commentable_path
|
redirect_to project_commentable_path(@project, @commentable)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
protected
|
||||||
|
|
||||||
def set_commentable
|
def find_commentable
|
||||||
@commentable = if params[:issue_id].present?
|
@commentable = params[:issue_id].present? && @project.issues.find_by_serial_id(params[:issue_id]) ||
|
||||||
@project.issues.find_by_serial_id params[:issue_id]
|
params[:commit_id].present? && @project.git_repository.commit(params[:commit_id])
|
||||||
elsif params[:commit_id].present?
|
|
||||||
@project.git_repository.commit params[:commit_id]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_comment
|
def find_or_build_comment
|
||||||
@comment = Comment.find(params[:id])
|
@comment = params[:id].present? && Comment.find(params[:id]) ||
|
||||||
if @comment.commit_comment?
|
current_user.comments.build(params[:comment]) {|c| c.commentable = @commentable; c.project = @project}
|
||||||
@comment.project = @project
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def commentable_path
|
|
||||||
@commentable.class == Issue ? [@project, @commentable] : commit_path(@project, @commentable.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# -*- encoding : utf-8 -*-
|
|
||||||
class DownloadsController < ApplicationController
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
load_and_authorize_resource
|
|
||||||
|
|
||||||
def index
|
|
||||||
@downloads = Download.paginate :page => params[:page], :per_page => 30
|
|
||||||
end
|
|
||||||
|
|
||||||
def refresh
|
|
||||||
Download.rotate_nginx_log
|
|
||||||
Download.parse_and_remove_nginx_log
|
|
||||||
|
|
||||||
redirect_to downloads_path, :notice => t('flash.downloads.statistics_refreshed')
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
class Git::BaseController < ApplicationController
|
class Git::BaseController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
skip_before_filter :authenticate_user!, :only => [:show, :index, :blame, :raw] if APP_CONFIG['anonymous_access']
|
skip_before_filter :authenticate_user!, :only => [:show, :index, :blame, :raw, :archive] if APP_CONFIG['anonymous_access']
|
||||||
load_and_authorize_resource :project
|
load_and_authorize_resource :project
|
||||||
|
|
||||||
before_filter :find_git_repository
|
before_filter :find_git_repository
|
||||||
|
|
|
@ -15,4 +15,18 @@ class Git::TreesController < Git::BaseController
|
||||||
@tree = @tree / @path if @path
|
@tree = @tree / @path if @path
|
||||||
render :template => "git/trees/show"
|
render :template => "git/trees/show"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def archive
|
||||||
|
treeish = params[:treeish].presence || @project.default_branch
|
||||||
|
format = params[:format] || 'tar'
|
||||||
|
commit = @project.git_repository.log(treeish, nil, :max_count => 1).first
|
||||||
|
name = "#{@project.owner.uname}-#{@project.name}#{@project.tags.include?(treeish) ? "-#{treeish}" : ''}-#{commit.id[0..19]}"
|
||||||
|
fullname = "#{name}.#{format == 'tar' ? 'tar.gz' : 'zip'}"
|
||||||
|
file = Tempfile.new fullname, 'tmp'
|
||||||
|
system("cd #{@project.path}; git archive --format=#{format} --prefix=#{name}/ #{treeish} #{format == 'tar' ? ' | gzip -9' : ''} > #{file.path}")
|
||||||
|
file.close
|
||||||
|
send_file file.path, :disposition => 'attachment', :type => "application/#{format == 'tar' ? 'x-tar-gz' : 'zip'}",
|
||||||
|
:filename => fullname
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ class IssuesController < ApplicationController
|
||||||
@status = params[:status] == 'closed' ? 'closed' : 'open'
|
@status = params[:status] == 'closed' ? 'closed' : 'open'
|
||||||
@labels = params[:labels] || []
|
@labels = params[:labels] || []
|
||||||
@issues = @project.issues
|
@issues = @project.issues
|
||||||
@issues = @issues.where(:user_id => current_user.id) if @is_assigned_to_me
|
@issues = @issues.where(:assignee_id => current_user.id) if @is_assigned_to_me
|
||||||
@issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == []
|
@issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == []
|
||||||
|
|
||||||
if params[:search_issue]
|
if params[:search_issue]
|
||||||
|
@ -25,7 +25,7 @@ class IssuesController < ApplicationController
|
||||||
@issues = @issues.where(:status => @status)
|
@issues = @issues.where(:status => @status)
|
||||||
|
|
||||||
|
|
||||||
@issues = @issues.includes(:creator, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
|
@issues = @issues.includes(:assignee, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
|
||||||
if status == 200
|
if status == 200
|
||||||
render 'index', :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'?
|
render 'index', :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'?
|
||||||
else
|
else
|
||||||
|
@ -38,9 +38,9 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@user_uname = params[:user_uname]
|
@assignee_uname = params[:assignee_uname]
|
||||||
@issue = @project.issues.new(params[:issue])
|
@issue = @project.issues.new(params[:issue])
|
||||||
@issue.creator_id = current_user.id
|
@issue.user_id = current_user.id
|
||||||
|
|
||||||
if @issue.save
|
if @issue.save
|
||||||
@issue.subscribe_creator(current_user.id)
|
@issue.subscribe_creator(current_user.id)
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
class ProductsController < ApplicationController
|
class ProductsController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
before_filter :find_product, :only => [:show, :edit, :update, :destroy]
|
|
||||||
before_filter :find_platform
|
|
||||||
before_filter :build_product_stub, :only => [:new, :create]
|
|
||||||
|
|
||||||
load_and_authorize_resource :platform
|
load_and_authorize_resource :platform
|
||||||
load_and_authorize_resource :product, :through => :platform
|
load_and_authorize_resource :product, :through => :platform
|
||||||
|
@ -20,24 +17,17 @@ class ProductsController < ApplicationController
|
||||||
@product.build_script = DEFAULT_BUILD
|
@product.build_script = DEFAULT_BUILD
|
||||||
end
|
end
|
||||||
|
|
||||||
# def clone
|
|
||||||
# @template = @platform.products.find(params[:id])
|
|
||||||
# @product = @platform.products.new
|
|
||||||
# @product.clone_from!(@template)
|
|
||||||
#
|
|
||||||
# render :template => "products/new"
|
|
||||||
# end
|
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@product = @platform.products.new params[:product]
|
|
||||||
if @product.save
|
if @product.save
|
||||||
flash[:notice] = t('flash.product.saved')
|
flash[:notice] = t('flash.product.saved')
|
||||||
redirect_to platform_product_path(@platform, @product)
|
redirect_to platform_product_path(@platform, @product)
|
||||||
else
|
else
|
||||||
flash[:error] = t('flash.product.save_error')
|
flash[:error] = t('flash.product.save_error')
|
||||||
|
flash[:warning] = @product.errors.full_messages.join('. ')
|
||||||
render :action => :new
|
render :action => :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -45,9 +35,10 @@ class ProductsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
if @product.update_attributes(params[:product])
|
if @product.update_attributes(params[:product])
|
||||||
flash[:notice] = t('flash.product.saved')
|
flash[:notice] = t('flash.product.saved')
|
||||||
redirect_to @platform
|
redirect_to platform_product_path(@platform, @product)
|
||||||
else
|
else
|
||||||
flash[:error] = t('flash.product.save_error')
|
flash[:error] = t('flash.product.save_error')
|
||||||
|
flash[:warning] = @product.errors.full_messages.join('. ')
|
||||||
render :action => "edit"
|
render :action => "edit"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -61,17 +52,4 @@ class ProductsController < ApplicationController
|
||||||
redirect_to platform_products_path(@platform)
|
redirect_to platform_products_path(@platform)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def find_product
|
|
||||||
@product = Product.find params[:id]
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_platform
|
|
||||||
@platform = Platform.find params[:platform_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_product_stub
|
|
||||||
@product = Product.new(:platform_id => params[:platform_id])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,6 +26,7 @@ class ProjectsController < ApplicationController
|
||||||
@project = Project.new params[:project]
|
@project = Project.new params[:project]
|
||||||
@project.owner = choose_owner
|
@project.owner = choose_owner
|
||||||
@who_owns = (@project.owner_type == 'User' ? :me : :group)
|
@who_owns = (@project.owner_type == 'User' ? :me : :group)
|
||||||
|
authorize! :update, @project.owner if @project.owner.class == Group
|
||||||
|
|
||||||
if @project.save
|
if @project.save
|
||||||
flash[:notice] = t('flash.project.saved')
|
flash[:notice] = t('flash.project.saved')
|
||||||
|
@ -56,7 +57,9 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def fork
|
def fork
|
||||||
if forked = @project.fork(current_user) and forked.valid?
|
owner = (Group.find params[:group] if params[:group].present?) || current_user
|
||||||
|
authorize! :update, owner if owner.class == Group
|
||||||
|
if forked = @project.fork(owner) and forked.valid?
|
||||||
redirect_to forked, :notice => t("flash.project.forked")
|
redirect_to forked, :notice => t("flash.project.forked")
|
||||||
else
|
else
|
||||||
flash[:warning] = t("flash.project.fork_error")
|
flash[:warning] = t("flash.project.fork_error")
|
||||||
|
|
|
@ -3,4 +3,11 @@ module ActivityFeedsHelper
|
||||||
def render_activity_feed(activity_feed)
|
def render_activity_feed(activity_feed)
|
||||||
render :partial => activity_feed.partial, :locals => activity_feed.data.merge(:activity_feed => activity_feed)
|
render :partial => activity_feed.partial, :locals => activity_feed.data.merge(:activity_feed => activity_feed)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_feed_title_from_content(content)
|
||||||
|
# removes html tags and haml generator indentation whitespaces and new line chars:
|
||||||
|
feed_title = strip_tags(content).gsub(/(^\s+|\n| )/, ' ')
|
||||||
|
# removes multiple whitespaces in a row and strip it:
|
||||||
|
feed_title = feed_title.gsub(/\s{2,}/, ' ').strip
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,8 @@ module BuildListsHelper
|
||||||
return 'success'
|
return 'success'
|
||||||
end
|
end
|
||||||
if [BuildServer::BUILD_ERROR, BuildServer::PLATFORM_NOT_FOUND,
|
if [BuildServer::BUILD_ERROR, BuildServer::PLATFORM_NOT_FOUND,
|
||||||
BuildServer::PROJECT_NOT_FOUND,BuildServer::PROJECT_VERSION_NOT_FOUND, BuildList::FAILED_PUBLISH].include? status
|
BuildServer::PROJECT_NOT_FOUND, BuildServer::PROJECT_VERSION_NOT_FOUND,
|
||||||
|
BuildList::FAILED_PUBLISH, BuildList::REJECTED_PUBLISH].include? status
|
||||||
return 'error'
|
return 'error'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
module CommentsHelper
|
module CommentsHelper
|
||||||
|
def project_commentable_comment_path(project, commentable, comment)
|
||||||
|
case
|
||||||
|
when Comment.issue_comment?(commentable.class)
|
||||||
|
project_issue_comment_path(project, commentable, comment)
|
||||||
|
when Comment.commit_comment?(commentable.class)
|
||||||
|
project_commit_comment_path(project, commentable, comment)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def project_commentable_path(project, commentable)
|
||||||
|
case
|
||||||
|
when Comment.issue_comment?(commentable.class)
|
||||||
|
polymorphic_path [project, commentable]
|
||||||
|
when Comment.commit_comment?(commentable.class)
|
||||||
|
commit_path project, commentable.id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Ability
|
||||||
|
|
||||||
# Shared rights between guests and registered users
|
# Shared rights between guests and registered users
|
||||||
can :show, Project, :visibility => 'open'
|
can :show, Project, :visibility => 'open'
|
||||||
|
can :archive, Project, :visibility => 'open'
|
||||||
can :read, Issue, :project => {:visibility => 'open'}
|
can :read, Issue, :project => {:visibility => 'open'}
|
||||||
can :search, BuildList
|
can :search, BuildList
|
||||||
can :read, BuildList, :project => {:visibility => 'open'}
|
can :read, BuildList, :project => {:visibility => 'open'}
|
||||||
|
@ -51,13 +52,15 @@ class Ability
|
||||||
|
|
||||||
can :create, Project
|
can :create, Project
|
||||||
can :read, Project, :visibility => 'open'
|
can :read, Project, :visibility => 'open'
|
||||||
can :read, Project, :owner_type => 'User', :owner_id => user.id
|
can [:read, :archive], Project, :owner_type => 'User', :owner_id => user.id
|
||||||
can :read, Project, :owner_type => 'Group', :owner_id => user.group_ids
|
can [:read, :archive], Project, :owner_type => 'Group', :owner_id => user.group_ids
|
||||||
can([:read, :membered], Project, read_relations_for('projects')) {|project| local_reader? project}
|
can([:read, :membered], Project, read_relations_for('projects')) {|project| local_reader? project}
|
||||||
can(:write, Project) {|project| local_writer? project} # for grack
|
can(:write, Project) {|project| local_writer? project} # for grack
|
||||||
can([:update, :sections, :manage_collaborators], Project) {|project| local_admin? project}
|
can([:update, :sections, :manage_collaborators], Project) {|project| local_admin? project}
|
||||||
can(:fork, Project) {|project| can? :read, project}
|
can(:fork, Project) {|project| can? :read, project}
|
||||||
|
can(:fork_to_group, Project) {|project| project.owner_type == 'Group' and can? :update, project.owner}
|
||||||
can(:destroy, Project) {|project| owner? project}
|
can(:destroy, Project) {|project| owner? project}
|
||||||
|
can(:destroy, Project) {|project| project.owner_type == 'Group' and project.owner.objects.exists?(:object_type => 'User', :object_id => user.id, :role => 'admin')}
|
||||||
can :remove_user, Project
|
can :remove_user, Project
|
||||||
|
|
||||||
can [:read, :owned], BuildList, :user_id => user.id
|
can [:read, :owned], BuildList, :user_id => user.id
|
||||||
|
@ -65,7 +68,12 @@ class Ability
|
||||||
can [:read, :related], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
|
can [:read, :related], BuildList, :project => {:owner_type => 'Group', :owner_id => user.group_ids}
|
||||||
can(:read, BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
|
can(:read, BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project}
|
||||||
can(:create, BuildList) {|build_list| build_list.project.is_rpm && can?(:write, build_list.project)}
|
can(:create, BuildList) {|build_list| build_list.project.is_rpm && can?(:write, build_list.project)}
|
||||||
can(:publish, BuildList) {|build_list| build_list.can_publish? && can?(:write, build_list.project)}
|
can(:publish, BuildList) do |build_list|
|
||||||
|
build_list.can_publish? and build_list.pl.released ? local_admin?(build_list.pl) : can?(:write, build_list.project)
|
||||||
|
end
|
||||||
|
can(:reject_publish, BuildList) do |build_list|
|
||||||
|
build_list.can_reject_publish? and build_list.pl.released and local_admin?(build_list.pl)
|
||||||
|
end
|
||||||
can(:cancel, BuildList) {|build_list| build_list.can_cancel? && can?(:write, build_list.project)}
|
can(:cancel, BuildList) {|build_list| build_list.can_cancel? && can?(:write, build_list.project)}
|
||||||
|
|
||||||
can [:read, :members], Platform, :visibility => 'open'
|
can [:read, :members], Platform, :visibility => 'open'
|
||||||
|
|
|
@ -19,23 +19,23 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
||||||
ActivityFeed.create(
|
ActivityFeed.create(
|
||||||
:user => recipient,
|
:user => recipient,
|
||||||
:kind => 'new_issue_notification',
|
:kind => 'new_issue_notification',
|
||||||
:data => {:user_name => record.creator.name, :user_email => record.creator.email, :user_id => record.creator_id,:issue_serial_id => record.serial_id,
|
:data => {:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id,:issue_serial_id => record.serial_id,
|
||||||
:issue_title => record.title, :project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
:issue_title => record.title, :project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
if record.user_id_changed?
|
if record.assignee_id_changed?
|
||||||
UserMailer.delay.issue_assign_notification(record, record.user) if record.user.notifier.issue_assign && record.user.notifier.can_notify
|
UserMailer.delay.issue_assign_notification(record, record.assignee) if record.assignee.notifier.issue_assign && record.assignee.notifier.can_notify
|
||||||
ActivityFeed.create(
|
ActivityFeed.create(
|
||||||
:user => record.user,
|
:user => record.user,
|
||||||
:kind => 'issue_assign_notification',
|
:kind => 'issue_assign_notification',
|
||||||
:data => {:user_name => record.creator.name, :user_email => record.creator.email, :user_id => record.creator_id, :issue_serial_id => record.serial_id,
|
:data => {:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id, :issue_serial_id => record.serial_id,
|
||||||
:project_id => record.project.id, :issue_title => record.title, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
:project_id => record.project.id, :issue_title => record.title, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'Comment'
|
when 'Comment'
|
||||||
if record.commentable.class == Issue
|
if record.issue_comment?
|
||||||
subscribes = record.commentable.subscribes
|
subscribes = record.commentable.subscribes
|
||||||
subscribes.each do |subscribe|
|
subscribes.each do |subscribe|
|
||||||
if record.user_id != subscribe.user_id
|
if record.user_id != subscribe.user_id
|
||||||
|
@ -70,6 +70,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'GitHook'
|
when 'GitHook'
|
||||||
|
return unless record.project
|
||||||
change_type = record.change_type
|
change_type = record.change_type
|
||||||
branch_name = record.refname.split('/').last
|
branch_name = record.refname.split('/').last
|
||||||
|
|
||||||
|
@ -120,12 +121,12 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
||||||
def after_update(record)
|
def after_update(record)
|
||||||
case record.class.to_s
|
case record.class.to_s
|
||||||
when 'Issue'
|
when 'Issue'
|
||||||
if record.user_id && record.user_id_changed?
|
if record.assignee_id && record.assignee_id_changed?
|
||||||
UserMailer.delay.issue_assign_notification(record, record.user) if record.user.notifier.issue_assign && record.user.notifier.can_notify
|
UserMailer.delay.issue_assign_notification(record, record.assignee) if record.assignee.notifier.issue_assign && record.assignee.notifier.can_notify
|
||||||
ActivityFeed.create(
|
ActivityFeed.create(
|
||||||
:user => record.user,
|
:user => record.assignee,
|
||||||
:kind => 'issue_assign_notification',
|
:kind => 'issue_assign_notification',
|
||||||
:data => {:user_name => record.user.name, :user_email => record.user.email, :issue_serial_id => record.serial_id, :issue_title => record.title,
|
:data => {:user_name => record.assignee.name, :user_email => record.assignee.email, :issue_serial_id => record.serial_id, :issue_title => record.title,
|
||||||
:project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
:project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -138,7 +139,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
||||||
ActivityFeed.create(
|
ActivityFeed.create(
|
||||||
:user => User.find(recipient),
|
:user => User.find(recipient),
|
||||||
:kind => 'build_list_notification',
|
:kind => 'build_list_notification',
|
||||||
:data => {:task_num => record.bs_id, :build_list_id => record.id, :status => record.status, :notified_at => record.notified_at,
|
:data => {:task_num => record.bs_id, :build_list_id => record.id, :status => record.status, :updated_at => record.updated_at,
|
||||||
:project_id => record.project_id, :project_name => record.project.name, :project_owner => record.project.owner.uname,
|
:project_id => record.project_id, :project_name => record.project.name, :project_owner => record.project.owner.uname,
|
||||||
:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id}
|
:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id}
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,6 +23,7 @@ class BuildList < ActiveRecord::Base
|
||||||
BUILD_PUBLISHED = 6000
|
BUILD_PUBLISHED = 6000
|
||||||
BUILD_PUBLISH = 7000
|
BUILD_PUBLISH = 7000
|
||||||
FAILED_PUBLISH = 8000
|
FAILED_PUBLISH = 8000
|
||||||
|
REJECTED_PUBLISH = 9000
|
||||||
|
|
||||||
STATUSES = [ WAITING_FOR_RESPONSE,
|
STATUSES = [ WAITING_FOR_RESPONSE,
|
||||||
BUILD_CANCELED,
|
BUILD_CANCELED,
|
||||||
|
@ -30,6 +31,7 @@ class BuildList < ActiveRecord::Base
|
||||||
BUILD_PUBLISHED,
|
BUILD_PUBLISHED,
|
||||||
BUILD_PUBLISH,
|
BUILD_PUBLISH,
|
||||||
FAILED_PUBLISH,
|
FAILED_PUBLISH,
|
||||||
|
REJECTED_PUBLISH,
|
||||||
BuildServer::SUCCESS,
|
BuildServer::SUCCESS,
|
||||||
BuildServer::BUILD_STARTED,
|
BuildServer::BUILD_STARTED,
|
||||||
BuildServer::BUILD_ERROR,
|
BuildServer::BUILD_ERROR,
|
||||||
|
@ -47,6 +49,7 @@ class BuildList < ActiveRecord::Base
|
||||||
BUILD_PUBLISHED => :build_published,
|
BUILD_PUBLISHED => :build_published,
|
||||||
BUILD_PUBLISH => :build_publish,
|
BUILD_PUBLISH => :build_publish,
|
||||||
FAILED_PUBLISH => :failed_publish,
|
FAILED_PUBLISH => :failed_publish,
|
||||||
|
REJECTED_PUBLISH => :rejected_publish,
|
||||||
BuildServer::BUILD_ERROR => :build_error,
|
BuildServer::BUILD_ERROR => :build_error,
|
||||||
BuildServer::BUILD_STARTED => :build_started,
|
BuildServer::BUILD_STARTED => :build_started,
|
||||||
BuildServer::SUCCESS => :success,
|
BuildServer::SUCCESS => :success,
|
||||||
|
@ -59,32 +62,23 @@ class BuildList < ActiveRecord::Base
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :recent, order("#{table_name}.updated_at DESC")
|
scope :recent, order("#{table_name}.updated_at DESC")
|
||||||
# scope :current, lambda {
|
|
||||||
# outdatable_statuses = [BuildServer::SUCCESS, BuildServer::ERROR, BuildServer::PLATFORM_NOT_FOUND, BuildServer::PLATFORM_PENDING, BuildServer::PROJECT_NOT_FOUND, BuildServer::PROJECT_VERSION_NOT_FOUND]
|
|
||||||
# where(["status in (?) OR (status in (?) AND notified_at >= ?)", [WAITING_FOR_RESPONSE, BUILD_PENDING, BuildServer::BUILD_STARTED], outdatable_statuses, Time.now - 2.days])
|
|
||||||
# }
|
|
||||||
scope :for_status, lambda {|status| where(:status => status) }
|
scope :for_status, lambda {|status| where(:status => status) }
|
||||||
scope :for_user, lambda { |user| where(:user_id => user.id) }
|
scope :for_user, lambda { |user| where(:user_id => user.id) }
|
||||||
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
|
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
|
||||||
scope :scoped_to_project_version, lambda {|project_version| where(:project_version => project_version) }
|
scope :scoped_to_project_version, lambda {|project_version| where(:project_version => project_version) }
|
||||||
scope :scoped_to_is_circle, lambda {|is_circle| where(:is_circle => is_circle) }
|
scope :scoped_to_is_circle, lambda {|is_circle| where(:is_circle => is_circle) }
|
||||||
scope :for_creation_date_period, lambda{|start_date, end_date|
|
scope :for_creation_date_period, lambda{|start_date, end_date|
|
||||||
if start_date && end_date
|
s = scoped
|
||||||
where(["#{table_name}.created_at BETWEEN ? AND ?", start_date, end_date])
|
s = s.where(["build_lists.created_at >= ?", start_date]) if start_date
|
||||||
elsif start_date && !end_date
|
s = s.where(["build_lists.created_at <= ?", end_date]) if end_date
|
||||||
where(["#{table_name}.created_at >= ?", start_date])
|
s
|
||||||
elsif !start_date && end_date
|
|
||||||
where(["#{table_name}.created_at <= ?", end_date])
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
scope :for_notified_date_period, lambda{|start_date, end_date|
|
scope :for_notified_date_period, lambda{|start_date, end_date|
|
||||||
if start_date && end_date
|
s = scoped
|
||||||
where(["notified_at BETWEEN ? AND ?", start_date, end_date])
|
s = s.where(["build_lists.updated_at >= ?", start_date]) if start_date
|
||||||
elsif start_date && !end_date
|
s = s.where(["build_lists.updated_at <= ?", end_date]) if end_date
|
||||||
where(["notified_at >= ?", start_date])
|
s
|
||||||
elsif !start_date && end_date
|
|
||||||
where(["notified_at <= ?", end_date])
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")}
|
scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")}
|
||||||
|
|
||||||
|
@ -123,6 +117,15 @@ class BuildList < ActiveRecord::Base
|
||||||
status == BuildServer::SUCCESS or status == FAILED_PUBLISH
|
status == BuildServer::SUCCESS or status == FAILED_PUBLISH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reject_publish
|
||||||
|
return false unless can_reject_publish?
|
||||||
|
update_attribute(:status, REJECTED_PUBLISH)
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_reject_publish?
|
||||||
|
can_publish? and pl.released
|
||||||
|
end
|
||||||
|
|
||||||
def cancel
|
def cancel
|
||||||
return false unless can_cancel?
|
return false unless can_cancel?
|
||||||
has_canceled = BuildServer.delete_build_list bs_id
|
has_canceled = BuildServer.delete_build_list bs_id
|
||||||
|
@ -139,6 +142,23 @@ class BuildList < ActiveRecord::Base
|
||||||
{:project => project.name, :version => project_version, :arch => arch.name}.inspect
|
{:project => project.name, :version => project_version, :arch => arch.name}.inspect
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_duration
|
||||||
|
(Time.now.utc - started_at.utc).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def human_current_duration
|
||||||
|
I18n.t("layout.build_lists.human_current_duration", {:hours => (current_duration/3600).to_i, :minutes => (current_duration%3600/60).to_i})
|
||||||
|
end
|
||||||
|
|
||||||
|
def human_duration
|
||||||
|
I18n.t("layout.build_lists.human_duration", {:hours => (duration/3600).to_i, :minutes => (duration%3600/60).to_i})
|
||||||
|
end
|
||||||
|
|
||||||
|
def in_work?
|
||||||
|
status == BuildServer::BUILD_STARTED
|
||||||
|
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def set_default_status
|
def set_default_status
|
||||||
self.status = WAITING_FOR_RESPONSE unless self.status.present?
|
self.status = WAITING_FOR_RESPONSE unless self.status.present?
|
||||||
|
|
|
@ -22,8 +22,8 @@ class BuildList::Filter
|
||||||
if @options[:created_at_start] || @options[:created_at_end]
|
if @options[:created_at_start] || @options[:created_at_end]
|
||||||
build_lists = build_lists.for_creation_date_period(@options[:created_at_start], @options[:created_at_end])
|
build_lists = build_lists.for_creation_date_period(@options[:created_at_start], @options[:created_at_end])
|
||||||
end
|
end
|
||||||
if @options[:notified_at_start] || @options[:notified_at_end]
|
if @options[:updated_at_start] || @options[:updated_at_end]
|
||||||
build_lists = build_lists.for_notified_date_period(@options[:notified_at_start], @options[:notified_at_end])
|
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ class BuildList::Filter
|
||||||
:status => nil,
|
:status => nil,
|
||||||
:created_at_start => nil,
|
:created_at_start => nil,
|
||||||
:created_at_end => nil,
|
:created_at_end => nil,
|
||||||
:notified_at_start => nil,
|
:updated_at_start => nil,
|
||||||
:notified_at_end => nil,
|
:updated_at_end => nil,
|
||||||
:arch_id => nil,
|
:arch_id => nil,
|
||||||
:is_circle => nil,
|
:is_circle => nil,
|
||||||
:project_version => nil,
|
:project_version => nil,
|
||||||
|
@ -60,8 +60,8 @@ class BuildList::Filter
|
||||||
@options[:status] = @options[:status].present? ? @options[:status].to_i : nil
|
@options[:status] = @options[:status].present? ? @options[:status].to_i : nil
|
||||||
@options[:created_at_start] = build_date_from_params(:created_at_start, @options)
|
@options[:created_at_start] = build_date_from_params(:created_at_start, @options)
|
||||||
@options[:created_at_end] = build_date_from_params(:created_at_end, @options)
|
@options[:created_at_end] = build_date_from_params(:created_at_end, @options)
|
||||||
@options[:notified_at_start] = build_date_from_params(:notified_at_start, @options)
|
@options[:updated_at_start] = build_date_from_params(:updated_at_start, @options)
|
||||||
@options[:notified_at_end] = build_date_from_params(:notified_at_end, @options)
|
@options[:updated_at_end] = build_date_from_params(:updated_at_end, @options)
|
||||||
@options[:project_version] = @options[:project_version].presence
|
@options[:project_version] = @options[:project_version].presence
|
||||||
@options[:arch_id] = @options[:arch_id].present? ? @options[:arch_id].to_i : nil
|
@options[:arch_id] = @options[:arch_id].present? ? @options[:arch_id].to_i : nil
|
||||||
@options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil
|
@options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
class BuildList::Item < ActiveRecord::Base
|
class BuildList::Item < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :build_list
|
belongs_to :build_list, :touch => true
|
||||||
|
|
||||||
attr_protected :build_list_id
|
attr_protected :build_list_id
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
class BuildListObserver < ActiveRecord::Observer
|
||||||
|
observe :build_list
|
||||||
|
|
||||||
|
def before_update(record)
|
||||||
|
if record.status_changed?
|
||||||
|
record.started_at = Time.now if record.status == BuildServer::BUILD_STARTED
|
||||||
|
if [BuildServer::BUILD_ERROR, BuildServer::SUCCESS].include? record.status
|
||||||
|
# stores time interval beetwin build start and finish in seconds
|
||||||
|
record.duration = record.current_duration
|
||||||
|
|
||||||
|
if record.status == BuildServer::SUCCESS
|
||||||
|
# Update project average build time
|
||||||
|
build_count = record.project.build_count
|
||||||
|
new_av_time = ( record.project.average_build_time * build_count + record.duration ) / ( build_count + 1 )
|
||||||
|
record.project.update_attributes({ :average_build_time => new_av_time, :build_count => build_count + 1 }, :without_protection => true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,23 +6,45 @@ class Comment < ActiveRecord::Base
|
||||||
|
|
||||||
validates :body, :user_id, :commentable_id, :commentable_type, :project_id, :presence => true
|
validates :body, :user_id, :commentable_id, :commentable_type, :project_id, :presence => true
|
||||||
|
|
||||||
|
scope :for_commit, lambda {|c| where(:commentable_id => c.id.hex, :commentable_type => c.class)}
|
||||||
default_scope order('created_at')
|
default_scope order('created_at')
|
||||||
|
|
||||||
after_create :subscribe_on_reply, :unless => lambda {|c| c.commit_comment?}
|
after_create :subscribe_on_reply, :unless => lambda {|c| c.commit_comment?}
|
||||||
after_create :subscribe_users
|
after_create :subscribe_users
|
||||||
after_initialize do |comment|
|
|
||||||
class_eval { def commentable; project.git_repository.commit(commentable_id.to_s(16)); end } if commit_comment?
|
attr_accessible :body
|
||||||
|
|
||||||
|
def commentable
|
||||||
|
commit_comment? ? project.git_repository.commit(commentable_id.to_s(16)) : super
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessible :body, :commentable_id, :commentable_type
|
def commentable=(c)
|
||||||
attr_readonly :commentable_id, :commentable_type
|
if self.class.commit_comment?(c.class)
|
||||||
|
self.commentable_id = c.id.hex
|
||||||
|
self.commentable_type = c.class.name
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def own_comment?(user)
|
def self.commit_comment?(class_name)
|
||||||
user_id == user.id
|
class_name.to_s == 'Grit::Commit'
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit_comment?
|
def commit_comment?
|
||||||
commentable_type == 'Grit::Commit'
|
self.class.commit_comment?(commentable_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.issue_comment?(class_name)
|
||||||
|
class_name.to_s == 'Issue'
|
||||||
|
end
|
||||||
|
|
||||||
|
def issue_comment?
|
||||||
|
self.class.issue_comment?(commentable_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def own_comment?(user)
|
||||||
|
user_id == user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_notify_on_new_comment?(subscribe)
|
def can_notify_on_new_comment?(subscribe)
|
||||||
|
@ -32,19 +54,19 @@ class Comment < ActiveRecord::Base
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def subscribe_on_reply
|
def subscribe_on_reply
|
||||||
self.commentable.subscribes.create(:user_id => self.user_id) if !self.commentable.subscribes.exists?(:user_id => self.user_id)
|
commentable.subscribes.create(:user_id => user_id) if !commentable.subscribes.exists?(:user_id => user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe_users
|
def subscribe_users
|
||||||
if self.commentable.class == Issue
|
if issue_comment?
|
||||||
self.commentable.subscribes.create(:user => self.user) if !self.commentable.subscribes.exists?(:user_id => self.user.id)
|
commentable.subscribes.create(:user => user) if !commentable.subscribes.exists?(:user_id => user.id)
|
||||||
elsif self.commit_comment?
|
elsif commit_comment?
|
||||||
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map &:object # admins
|
recipients = project.relations.by_role('admin').where(:object_type => 'User').map &:object # admins
|
||||||
recipients << self.user << User.where(:email => self.commentable.committer.email).first # commentor and committer
|
recipients << user << User.where(:email => commentable.committer.email).first # commentor and committer
|
||||||
recipients << self.project.owner if self.project.owner_type == 'User' # project owner
|
recipients << project.owner if project.owner_type == 'User' # project owner
|
||||||
recipients.compact.uniq.each do |user|
|
recipients.compact.uniq.each do |user|
|
||||||
options = {:project_id => self.project.id, :subscribeable_id => self.commentable_id, :subscribeable_type => self.commentable.class.name, :user_id => user.id}
|
options = {:project_id => project.id, :subscribeable_id => commentable_id, :subscribeable_type => commentable.class.name, :user_id => user.id}
|
||||||
Subscribe.subscribe_to_commit(options) if Subscribe.subscribed_to_commit?(self.project, user, self.commentable)
|
Subscribe.subscribe_to_commit(options) if Subscribe.subscribed_to_commit?(project, user, commentable)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,30 +4,28 @@ class Issue < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :creator, :class_name => 'User', :foreign_key => 'creator_id'
|
belongs_to :assignee, :class_name => 'User', :foreign_key => 'assignee_id'
|
||||||
belongs_to :closer, :class_name => 'User', :foreign_key => 'closed_by'
|
belongs_to :closer, :class_name => 'User', :foreign_key => 'closed_by'
|
||||||
|
|
||||||
has_many :comments, :as => :commentable, :dependent => :destroy #, :finder_sql => proc { "comments.commentable_id = '#{self.id}' AND comments.commentable_type = '#{self.class.name}'"}
|
has_many :comments, :as => :commentable, :dependent => :destroy
|
||||||
has_many :subscribes, :as => :subscribeable, :dependent => :destroy #, :finder_sql => proc { "subscribes.subscribeable_id = '#{self.id}' AND subscribes.subscribeable_type = '#{self.class.name}'"}
|
has_many :subscribes, :as => :subscribeable, :dependent => :destroy
|
||||||
has_many :labels, :through => :labelings, :uniq => true
|
has_many :labels, :through => :labelings, :uniq => true
|
||||||
has_many :labelings
|
has_many :labelings
|
||||||
|
|
||||||
validates :title, :body, :project_id, :presence => true
|
validates :title, :body, :project_id, :presence => true
|
||||||
|
|
||||||
#attr_readonly :serial_id
|
|
||||||
|
|
||||||
after_create :set_serial_id
|
after_create :set_serial_id
|
||||||
after_create :subscribe_users
|
after_create :subscribe_users
|
||||||
after_update :subscribe_issue_assigned_user
|
after_update :subscribe_issue_assigned_user
|
||||||
|
|
||||||
attr_accessible :labelings_attributes, :title, :body, :user_id
|
attr_accessible :labelings_attributes, :title, :body, :assignee_id
|
||||||
accepts_nested_attributes_for :labelings, :allow_destroy => true
|
accepts_nested_attributes_for :labelings, :allow_destroy => true
|
||||||
|
|
||||||
scope :opened, where(:status => 'open', :closed_by => nil, :closed_at => nil)
|
scope :opened, where(:status => 'open', :closed_by => nil, :closed_at => nil)
|
||||||
scope :closed, where(:status => 'closed').where("closed_by is not null and closed_at is not null")
|
scope :closed, where(:status => 'closed').where("closed_by is not null and closed_at is not null")
|
||||||
|
|
||||||
def assign_uname
|
def assign_uname
|
||||||
user.uname if user
|
assignee.uname if assignee
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_param
|
def to_param
|
||||||
|
@ -57,7 +55,7 @@ class Issue < ActiveRecord::Base
|
||||||
|
|
||||||
def collect_recipient_ids
|
def collect_recipient_ids
|
||||||
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
|
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
|
||||||
recipients = recipients | [self.user_id] if self.user_id
|
recipients = recipients | [self.assignee_id] if self.assignee_id
|
||||||
recipients = recipients | [self.project.owner_id] if self.project.owner_type == 'User'
|
recipients = recipients | [self.project.owner_id] if self.project.owner_type == 'User'
|
||||||
|
|
||||||
recipients
|
recipients
|
||||||
|
@ -80,10 +78,10 @@ class Issue < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe_issue_assigned_user
|
def subscribe_issue_assigned_user
|
||||||
if self.user_id && self.user_id_changed?
|
if self.assignee_id && self.assignee_id_changed?
|
||||||
self.subscribes.where(:user_id => self.user_id_was).first.destroy unless self.user_id_was.blank?
|
self.subscribes.where(:user_id => self.assignee_id_was).first.destroy unless self.assignee_id_was.blank?
|
||||||
if self.user.notifier.issue_assign && !self.subscribes.exists?(:user_id => self.user_id)
|
if self.assignee.notifier.issue_assign && !self.subscribes.exists?(:user_id => self.assignee_id)
|
||||||
self.subscribes.create(:user_id => self.user_id)
|
self.subscribes.create(:user_id => self.assignee_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Platform < ActiveRecord::Base
|
||||||
after_update :update_owner_relation
|
after_update :update_owner_relation
|
||||||
|
|
||||||
scope :search_order, order("CHAR_LENGTH(name) ASC")
|
scope :search_order, order("CHAR_LENGTH(name) ASC")
|
||||||
scope :search, lambda {|q| where("name ILIKE ?", "%#{q.strip}%")}
|
scope :search, lambda {|q| where("name ILIKE ?", "%#{q.to_s.strip}%")}
|
||||||
scope :by_visibilities, lambda {|v| where(:visibility => v)}
|
scope :by_visibilities, lambda {|v| where(:visibility => v)}
|
||||||
scope :opened, where(:visibility => 'open')
|
scope :opened, where(:visibility => 'open')
|
||||||
scope :hidden, where(:visibility => 'hidden')
|
scope :hidden, where(:visibility => 'hidden')
|
||||||
|
|
|
@ -15,6 +15,10 @@ class Product < ActiveRecord::Base
|
||||||
|
|
||||||
scope :recent, order("name ASC")
|
scope :recent, order("name ASC")
|
||||||
|
|
||||||
|
attr_accessible :name, :counter, :ks, :menu, :tar, :cron_tab, :use_cron
|
||||||
|
attr_accessible :description, :build_script, :delete_tar
|
||||||
|
attr_readonly :platform_id
|
||||||
|
|
||||||
def delete_tar
|
def delete_tar
|
||||||
@delete_tar ||= "0"
|
@delete_tar ||= "0"
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,17 +16,20 @@ class ProductBuildList < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :product
|
belongs_to :product
|
||||||
|
|
||||||
validates :product, :status, :presence => true
|
validates :product_id, :status, :presence => true
|
||||||
validates :status, :inclusion => { :in => [BUILD_STARTED, BUILD_COMPLETED, BUILD_FAILED] }
|
validates :status, :inclusion => { :in => [BUILD_STARTED, BUILD_COMPLETED, BUILD_FAILED] }
|
||||||
|
|
||||||
|
attr_accessor :base_url
|
||||||
|
attr_accessible :status, :notified_at, :base_url
|
||||||
|
attr_readonly :product_id
|
||||||
|
|
||||||
|
|
||||||
scope :default_order, order('notified_at DESC')
|
scope :default_order, order('notified_at DESC')
|
||||||
scope :for_status, lambda {|status| where(:status => status) }
|
scope :for_status, lambda {|status| where(:status => status) }
|
||||||
scope :for_user, lambda { |user| where(:user_id => user.id) }
|
scope :for_user, lambda { |user| where(:user_id => user.id) }
|
||||||
scope :scoped_to_product_name, lambda {|product_name| joins(:product).where('products.name LIKE ?', "%#{product_name}%")}
|
scope :scoped_to_product_name, lambda {|product_name| joins(:product).where('products.name LIKE ?', "%#{product_name}%")}
|
||||||
scope :recent, order("#{table_name}.updated_at DESC")
|
scope :recent, order("#{table_name}.updated_at DESC")
|
||||||
|
|
||||||
attr_accessor :base_url
|
|
||||||
|
|
||||||
after_create :xml_rpc_create
|
after_create :xml_rpc_create
|
||||||
after_destroy :xml_delete_iso_container
|
after_destroy :xml_delete_iso_container
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Project < ActiveRecord::Base
|
||||||
|
|
||||||
scope :recent, order("name ASC")
|
scope :recent, order("name ASC")
|
||||||
scope :search_order, order("CHAR_LENGTH(name) ASC")
|
scope :search_order, order("CHAR_LENGTH(name) ASC")
|
||||||
scope :search, lambda {|q| by_name("%#{q.strip}%")}
|
scope :search, lambda {|q| by_name("%#{q.to_s.strip}%")}
|
||||||
scope :by_name, lambda {|name| where('projects.name ILIKE ?', name)}
|
scope :by_name, lambda {|name| where('projects.name ILIKE ?', name)}
|
||||||
scope :by_visibilities, lambda {|v| where(:visibility => v)}
|
scope :by_visibilities, lambda {|v| where(:visibility => v)}
|
||||||
scope :opened, where(:visibility => 'open')
|
scope :opened, where(:visibility => 'open')
|
||||||
|
@ -37,11 +37,12 @@ class Project < ActiveRecord::Base
|
||||||
|
|
||||||
after_create :attach_to_personal_repository
|
after_create :attach_to_personal_repository
|
||||||
after_create :create_git_repo
|
after_create :create_git_repo
|
||||||
|
after_create {|p| p.delay(:queue => 'fork', :priority => 20).fork_git_repo unless is_root?}
|
||||||
after_save :create_wiki
|
after_save :create_wiki
|
||||||
|
|
||||||
after_destroy :destroy_git_repo
|
after_destroy :destroy_git_repo
|
||||||
after_destroy :destroy_wiki
|
after_destroy :destroy_wiki
|
||||||
after_save {|p| p.delay.import_attached_srpm if p.srpm?} # should be after create_git_repo
|
after_save {|p| p.delay(:queue => 'import', :priority => 10).import_attached_srpm if p.srpm?} # should be after create_git_repo
|
||||||
# after_rollback lambda { destroy_git_repo rescue true if new_record? }
|
# after_rollback lambda { destroy_git_repo rescue true if new_record? }
|
||||||
|
|
||||||
has_ancestry
|
has_ancestry
|
||||||
|
@ -50,18 +51,25 @@ class Project < ActiveRecord::Base
|
||||||
|
|
||||||
include Modules::Models::Owner
|
include Modules::Models::Owner
|
||||||
|
|
||||||
def build_for(platform, user, arch = 'i586') # Return i586 after mass rebuild
|
def build_for(platform, user, arch = 'i586')
|
||||||
|
# Select main and project platform repository(contrib, non-free and etc)
|
||||||
|
# If main does not exist, will connect only project platform repository
|
||||||
|
# If project platform repository is main, only main will be connect
|
||||||
|
build_reps = [platform.repositories.find_by_name('main')]
|
||||||
|
build_reps += platform.repositories.select {|rep| self.repository_ids.include? rep.id}
|
||||||
|
build_ids = build_reps.compact.map(&:id).uniq
|
||||||
|
|
||||||
arch = Arch.find_by_name(arch) if arch.acts_like?(:string)
|
arch = Arch.find_by_name(arch) if arch.acts_like?(:string)
|
||||||
build_lists.create do |bl|
|
build_lists.create do |bl|
|
||||||
bl.pl = platform
|
bl.pl = platform
|
||||||
bl.bpl = platform
|
bl.bpl = platform
|
||||||
bl.update_type = 'newpackage'
|
bl.update_type = 'newpackage'
|
||||||
bl.arch = arch
|
bl.arch = arch
|
||||||
bl.project_version = "latest_#{platform.name}" # "latest_import_mandriva2011"
|
bl.project_version = "latest_#{platform.name}"
|
||||||
bl.build_requires = false # already set as db default
|
bl.build_requires = false # already set as db default
|
||||||
bl.user = user
|
bl.user = user
|
||||||
bl.auto_publish = true # already set as db default
|
bl.auto_publish = true # already set as db default
|
||||||
bl.include_repos = [platform.repositories.find_by_name('main').id]
|
bl.include_repos = build_ids
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -117,6 +125,13 @@ class Project < ActiveRecord::Base
|
||||||
tags.map(&:name) + branches.map{|b| "latest_#{b.name}"}
|
tags.map(&:name) + branches.map{|b| "latest_#{b.name}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def versions_for_group_select
|
||||||
|
[
|
||||||
|
['Branches', branches.map{|b| "latest_#{b.name}"}],
|
||||||
|
['Tags', tags.map(&:name)]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
def members
|
def members
|
||||||
collaborators + groups.map(&:members).flatten
|
collaborators + groups.map(&:members).flatten
|
||||||
end
|
end
|
||||||
|
@ -180,10 +195,6 @@ class Project < ActiveRecord::Base
|
||||||
system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm_path} #{path} #{branch_name} >> /dev/null 2>&1")
|
system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm_path} #{path} #{branch_name} >> /dev/null 2>&1")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.commit_comments(commit, project)
|
|
||||||
comments = Comment.where(:commentable_id => commit.id.hex, :commentable_type => 'Grit::Commit')
|
|
||||||
end
|
|
||||||
|
|
||||||
def owner?(user)
|
def owner?(user)
|
||||||
owner == user
|
owner == user
|
||||||
end
|
end
|
||||||
|
@ -199,6 +210,11 @@ class Project < ActiveRecord::Base
|
||||||
recipients
|
recipients
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def human_average_build_time
|
||||||
|
time = average_build_time
|
||||||
|
I18n.t("layout.projects.human_average_build_time", {:hours => (time/3600).to_i, :minutes => (time%3600/60).to_i})
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def build_path(dir)
|
def build_path(dir)
|
||||||
|
@ -214,8 +230,15 @@ class Project < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_git_repo
|
def create_git_repo
|
||||||
is_root? ? Grit::Repo.init_bare(path) : parent.git_repository.repo.delay.fork_bare(path)
|
if is_root?
|
||||||
write_hook.delay
|
Grit::Repo.init_bare(path)
|
||||||
|
write_hook.delay(:queue => 'fork', :priority => 15)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fork_git_repo
|
||||||
|
dummy = Grit::Repo.new(path) rescue parent.git_repository.repo.fork_bare(path)
|
||||||
|
write_hook
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_git_repo
|
def destroy_git_repo
|
||||||
|
@ -248,7 +271,7 @@ class Project < ActiveRecord::Base
|
||||||
hook = File.join(::Rails.root.to_s, 'tmp', "post-receive-hook")
|
hook = File.join(::Rails.root.to_s, 'tmp', "post-receive-hook")
|
||||||
FileUtils.cp(File.join(::Rails.root.to_s, 'bin', "post-receive-hook.partial"), hook)
|
FileUtils.cp(File.join(::Rails.root.to_s, 'bin', "post-receive-hook.partial"), hook)
|
||||||
File.open(hook, 'a') do |f|
|
File.open(hook, 'a') do |f|
|
||||||
s = "\n /bin/bash -l -c \"cd #{is_production ? '/srv/rosa_build/current' : Rails.root.to_s} && #{is_production ? 'RAILS_ENV=production' : ''} bundle exec rails runner 'Project.delay.process_hook(\\\"$owner\\\", \\\"$reponame\\\", \\\"$newrev\\\", \\\"$oldrev\\\", \\\"$ref\\\", \\\"$newrev_type\\\", \\\"$oldrev_type\\\")'\""
|
s = "\n /bin/bash -l -c \"cd #{is_production ? '/srv/rosa_build/current' : Rails.root.to_s} && #{is_production ? 'RAILS_ENV=production' : ''} bundle exec rails runner 'Project.delay(:queue => \\\"hook\\\").process_hook(\\\"$owner\\\", \\\"$reponame\\\", \\\"$newrev\\\", \\\"$oldrev\\\", \\\"$ref\\\", \\\"$newrev_type\\\", \\\"$oldrev_type\\\")'\""
|
||||||
s << " > /dev/null 2>&1" if is_production
|
s << " > /dev/null 2>&1" if is_production
|
||||||
s << "\ndone\n"
|
s << "\ndone\n"
|
||||||
f.write(s)
|
f.write(s)
|
||||||
|
|
|
@ -5,7 +5,7 @@ class User < ActiveRecord::Base
|
||||||
LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
|
LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
|
||||||
MAX_AVATAR_SIZE = 5.megabyte
|
MAX_AVATAR_SIZE = 5.megabyte
|
||||||
|
|
||||||
devise :database_authenticatable, :registerable, :omniauthable, # :token_authenticatable, :encryptable, :timeoutable
|
devise :database_authenticatable, :registerable, :omniauthable, :token_authenticatable,# :encryptable, :timeoutable
|
||||||
:recoverable, :rememberable, :validatable, :lockable, :confirmable#, :reconfirmable, :trackable
|
:recoverable, :rememberable, :validatable, :lockable, :confirmable#, :reconfirmable, :trackable
|
||||||
has_attached_file :avatar, :styles =>
|
has_attached_file :avatar, :styles =>
|
||||||
{ :micro => { :geometry => "16x16#", :format => :jpg, :convert_options => '-strip -background white -flatten -quality 70'},
|
{ :micro => { :geometry => "16x16#", :format => :jpg, :convert_options => '-strip -background white -flatten -quality 70'},
|
||||||
|
@ -55,6 +55,7 @@ class User < ActiveRecord::Base
|
||||||
include Modules::Models::ActsLikeMember
|
include Modules::Models::ActsLikeMember
|
||||||
|
|
||||||
after_create lambda { self.create_notifier }
|
after_create lambda { self.create_notifier }
|
||||||
|
before_create :ensure_authentication_token
|
||||||
|
|
||||||
def admin?
|
def admin?
|
||||||
role == 'admin'
|
role == 'admin'
|
||||||
|
|
|
@ -30,10 +30,10 @@ class CommentPresenter < ApplicationPresenter
|
||||||
def buttons
|
def buttons
|
||||||
project = options[:project]
|
project = options[:project]
|
||||||
commentable = options[:commentable]
|
commentable = options[:commentable]
|
||||||
(ep, dp) = if commentable.class == Issue
|
(ep, dp) = if Comment.issue_comment?(commentable.class)
|
||||||
[edit_project_issue_comment_path(project, commentable, comment),
|
[edit_project_issue_comment_path(project, commentable, comment),
|
||||||
project_issue_comment_path(project, commentable, comment)]
|
project_issue_comment_path(project, commentable, comment)]
|
||||||
elsif commentable.class == Grit::Commit
|
elsif Comment.commit_comment?(commentable.class)
|
||||||
[edit_project_commit_comment_path(project, commentable, comment),
|
[edit_project_commit_comment_path(project, commentable, comment),
|
||||||
project_commit_comment_path(project, commentable, comment)]
|
project_commit_comment_path(project, commentable, comment)]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
- @activity_feeds.each do |activity_feed|
|
- @activity_feeds.each do |activity_feed|
|
||||||
.activity
|
.activity{:id => "#feed#{activity_feed.id}"}
|
||||||
= render_activity_feed(activity_feed)
|
= render_activity_feed(activity_feed)
|
||||||
- if @activity_feeds.next_page
|
- if @activity_feeds.next_page
|
||||||
%a{:href => root_path({:filter => @filter, :page => @activity_feeds.next_page}), :class => 'more_activities'}
|
%a{:href => root_path({:filter => @filter, :page => @activity_feeds.next_page}), :class => 'more_activities'}
|
||||||
|
|
|
@ -18,30 +18,15 @@
|
||||||
%td
|
%td
|
||||||
= link_to t("layout.activity_feed.all_my_projects"), projects_path
|
= link_to t("layout.activity_feed.all_my_projects"), projects_path
|
||||||
.block
|
.block
|
||||||
- midnight = Time.new.midnight
|
- midnight = Date.today
|
||||||
%h3= t("layout.activity_feed.my_builds_by_day")
|
%h3= t("layout.activity_feed.my_builds_by_day")
|
||||||
%table{:cellpadding => "0", :cellspacing => "0"}
|
%table{:cellpadding => "0", :cellspacing => "0"}
|
||||||
%tbody
|
%tbody
|
||||||
|
- ['BuildList::BUILD_PUBLISHED', 'BuildServer::SUCCESS', 'BuildServer::BUILD_STARTED', 'BuildList::BUILD_PENDING', 'BuildServer::BUILD_ERROR'].each do |state|
|
||||||
%tr
|
%tr
|
||||||
%td.first
|
%td.first
|
||||||
= link_to t("layout.build_lists.statuses.#{:build_published}"), build_lists_path(:filter => {:status => BuildList::BUILD_PUBLISHED, :notified_at => midnight})
|
= link_to t("layout.build_lists.statuses.#{state.demodulize.downcase}"), build_lists_path(:filter => {:status => state.constantize, :'updated_at_start(1i)' => midnight.year, :'updated_at_start(2i)' => midnight.month, :'updated_at_start(3i)' => midnight.day})
|
||||||
%td= BuildList.for_status(BuildList::BUILD_PUBLISHED).for_user(current_user).for_notified_date_period(midnight, nil).count
|
%td= BuildList.for_status(state.constantize).for_user(current_user).for_notified_date_period(midnight, nil).count
|
||||||
%tr
|
|
||||||
%td.first
|
|
||||||
= link_to t("layout.build_lists.statuses.#{:success}"), build_lists_path(:filter => {:status => BuildServer::SUCCESS, :notified_at => midnight})
|
|
||||||
%td= BuildList.for_status(BuildServer::SUCCESS).for_user(current_user).for_notified_date_period(midnight, nil).count
|
|
||||||
%tr
|
|
||||||
%td.first
|
|
||||||
= link_to t("layout.build_lists.statuses.#{:build_started}"), build_lists_path(:filter => {:status => BuildServer::BUILD_STARTED, :notified_at => midnight})
|
|
||||||
%td= BuildList.for_status(BuildServer::BUILD_STARTED).for_user(current_user).for_notified_date_period(midnight, nil).count
|
|
||||||
%tr
|
|
||||||
%td.first
|
|
||||||
= link_to t("layout.build_lists.statuses.#{:build_pending}"), build_lists_path(:filter => {:status => BuildList::BUILD_PENDING, :notified_at => midnight})
|
|
||||||
%td= BuildList.for_status(BuildList::BUILD_PENDING).for_user(current_user).for_notified_date_period(midnight, nil).count
|
|
||||||
%tr
|
|
||||||
%td.first
|
|
||||||
= link_to t("layout.build_lists.statuses.#{:build_error}"), build_lists_path(:filter => {:status => BuildServer::BUILD_ERROR, :notified_at => midnight})
|
|
||||||
%td= BuildList.for_status(BuildServer::BUILD_ERROR).for_user(current_user).for_notified_date_period(midnight, nil).count
|
|
||||||
%tr
|
%tr
|
||||||
%td.first
|
%td.first
|
||||||
= link_to t("layout.activity_feed.all_my_builds"), build_lists_path
|
= link_to t("layout.activity_feed.all_my_builds"), build_lists_path
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
atom_feed do |feed|
|
||||||
|
feed.title(t("layout.activity_feed.atom_title"))
|
||||||
|
feed.updated(@activity_feeds[0].created_at) if @activity_feeds.length > 0
|
||||||
|
|
||||||
|
@activity_feeds.each do |activity_feed|
|
||||||
|
feed.entry(activity_feed, :url => root_url(:anchor => "feed#{activity_feed.id}")) do |entry|
|
||||||
|
feed_content = raw(render(:inline => true, :partial => activity_feed.partial, :locals => activity_feed.data.merge(:activity_feed => activity_feed)))
|
||||||
|
|
||||||
|
entry.title(truncate(get_feed_title_from_content(feed_content), :length => 50))
|
||||||
|
entry.content(feed_content, :type => 'html')
|
||||||
|
|
||||||
|
entry.author do |author|
|
||||||
|
author.name(activity_feed.data[:user_name])
|
||||||
|
author.email(activity_feed.data[:user_email])
|
||||||
|
end if activity_feed.kind != 'git_delete_branch_notification'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,5 +15,5 @@
|
||||||
- else ['failed', t("layout.build_lists.statuses.#{BuildList::HUMAN_STATUSES[status]}")]
|
- else ['failed', t("layout.build_lists.statuses.#{BuildList::HUMAN_STATUSES[status]}")]
|
||||||
= raw t("notifications.bodies.build_status.#{message}", :error => error)
|
= raw t("notifications.bodies.build_status.#{message}", :error => error)
|
||||||
.both
|
.both
|
||||||
%span.date= notified_at
|
%span.date= updated_at
|
||||||
.both
|
.both
|
||||||
|
|
|
@ -6,4 +6,4 @@
|
||||||
%td= build_list.arch.name
|
%td= build_list.arch.name
|
||||||
%td= link_to build_list.user.try(:fullname), build_list.user
|
%td= link_to build_list.user.try(:fullname), build_list.user
|
||||||
%td= link_to image_tag('x.png', :class => 'delete-row', :id => "delete-row#{build_list_counter}"), cancel_build_list_path(build_list), :method => :put, :confirm => t('layout.confirm') if build_list.can_cancel? and can?(:cancel, build_list)
|
%td= link_to image_tag('x.png', :class => 'delete-row', :id => "delete-row#{build_list_counter}"), cancel_build_list_path(build_list), :method => :put, :confirm => t('layout.confirm') if build_list.can_cancel? and can?(:cancel, build_list)
|
||||||
%td= build_list.notified_at
|
%td= build_list.updated_at
|
||||||
|
|
|
@ -47,10 +47,10 @@
|
||||||
.date_select= f.date_select(:created_at_start, :include_blank => true, :selected => @filter.created_at_start)
|
.date_select= f.date_select(:created_at_start, :include_blank => true, :selected => @filter.created_at_start)
|
||||||
%h3.small= t("layout.build_lists.created_at_end")
|
%h3.small= t("layout.build_lists.created_at_end")
|
||||||
.date_select= f.date_select(:created_at_end, :include_blank => true, :selected => @filter.created_at_end)
|
.date_select= f.date_select(:created_at_end, :include_blank => true, :selected => @filter.created_at_end)
|
||||||
%h3.small= t("layout.build_lists.notified_at_start")
|
%h3.small= t("layout.build_lists.updated_at_start")
|
||||||
.date_select= f.date_select(:notified_at_start, :include_blank => true, :selected => @filter.notified_at_start)
|
.date_select= f.date_select(:updated_at_start, :include_blank => true, :selected => @filter.updated_at_start)
|
||||||
%h3.small= t("layout.build_lists.notified_at_end")
|
%h3.small= t("layout.build_lists.updated_at_end")
|
||||||
.date_select= f.date_select(:notified_at_end, :include_blank => true, :selected => @filter.notified_at_end)
|
.date_select= f.date_select(:updated_at_end, :include_blank => true, :selected => @filter.updated_at_end)
|
||||||
%h3.small= t("layout.build_lists.project_name_search")
|
%h3.small= t("layout.build_lists.project_name_search")
|
||||||
= f.text_field :project_name
|
= f.text_field :project_name
|
||||||
%h3.small= t("layout.build_lists.bs_id_search")
|
%h3.small= t("layout.build_lists.bs_id_search")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- platform.repositories.each do |repo|
|
- platform.repositories.each do |repo|
|
||||||
.both
|
.both
|
||||||
= check_box_tag "build_list[include_repos][]", repo.id, repo.name == 'main' || @project.repositories.map(&:id).include?(repo.id), :id => "include_repos_#{repo.id}" # (params[:build_list]||[]).fetch(:include_repos, []).include?(repo.id.to_s)
|
= check_box_tag "build_list[include_repos][]", repo.id, repo.name == 'main' || @project.repositories.map(&:id).include?(repo.id), :id => "include_repos_#{repo.id}", :pl_id => platform.id, :rep_name => repo.name
|
||||||
= label_tag "include_repos_#{repo.id}", repo.name
|
= label_tag "include_repos_#{repo.id}", repo.name
|
|
@ -2,4 +2,4 @@
|
||||||
%td= link_to (platform_build_list.bs_id.present? ? platform_build_list.bs_id : t("layout.build_lists.bs_id_not_set")), platform_build_list
|
%td= link_to (platform_build_list.bs_id.present? ? platform_build_list.bs_id : t("layout.build_lists.bs_id_not_set")), platform_build_list
|
||||||
%td= platform_build_list.human_status
|
%td= platform_build_list.human_status
|
||||||
%td= link_to platform_build_list.project.name, platform_build_list.project
|
%td= link_to platform_build_list.project.name, platform_build_list.project
|
||||||
%td= platform_build_list.notified_at
|
%td= platform_build_list.updated_at
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.arch")
|
%th.lpadding16= t("activerecord.attributes.build_list.arch")
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.user")
|
%th.lpadding16= t("activerecord.attributes.build_list.user")
|
||||||
%th= t("layout.build_lists.action")
|
%th= t("layout.build_lists.action")
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.notified_at")
|
%th.lpadding16= t("activerecord.attributes.build_list.updated_at")
|
||||||
%tbody= render @build_lists
|
%tbody= render @build_lists
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,31 @@
|
||||||
-set_meta_tags :title => [title_object(@project), t('layout.build_lists.new_header')]
|
-set_meta_tags :title => [title_object(@project), t('layout.build_lists.new_header')]
|
||||||
= form_for [@project, @build_list], :html => { :class => :form, :method => :post } do |f|
|
= form_for [@project, @build_list], :html => { :class => :form, :method => :post } do |f|
|
||||||
%section.left
|
%section.left
|
||||||
%h3= t("activerecord.attributes.build_list.project_version")
|
|
||||||
.lineForm= f.select :project_version, @project.versions
|
|
||||||
%h3= t("activerecord.attributes.build_list.bpl")
|
%h3= t("activerecord.attributes.build_list.bpl")
|
||||||
.all_platforms
|
.all_platforms
|
||||||
- Platform.main.each do |pl|
|
- Platform.main.each do |pl|
|
||||||
- if pl.repository_ids.size > 0
|
- if pl.repository_ids.size > 0
|
||||||
.both
|
.both
|
||||||
= check_box_tag "bpls[]", pl.id, (params[:bpls]||[]).include?(pl.id.to_s), :class => 'build_bpl_ids', :id => "bpls_#{pl.id}"
|
= check_box_tag "bpls[]", pl.id, (params[:bpls]||[]).include?(pl.id.to_s), :class => 'build_bpl_ids', :id => "bpls_#{pl.id}", :'data-released' => pl.released ? 1 : 0
|
||||||
= label_tag "bpls_#{pl.id}", pl.name
|
= label_tag "bpls_#{pl.id}", pl.name
|
||||||
.offset25{:style => 'padding-left: 25px'}
|
.offset25{:style => 'padding-left: 25px'}
|
||||||
= render 'include_repos', :platform => pl
|
= render 'include_repos', :platform => pl
|
||||||
%section.right
|
%section.right
|
||||||
|
%h3= t("activerecord.attributes.build_list.pl")
|
||||||
|
.lineForm= f.select :pl_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]}
|
||||||
|
%h3= t("activerecord.attributes.build_list.project_version")
|
||||||
|
- if controller.action_name == 'new'
|
||||||
|
.lineForm= f.select :project_version, @project.versions_for_group_select, :selected => "latest_" + @project.default_branch
|
||||||
|
- else
|
||||||
|
.lineForm= f.select :project_version, @project.versions_for_group_select
|
||||||
%h3= t("activerecord.attributes.build_list.arch")
|
%h3= t("activerecord.attributes.build_list.arch")
|
||||||
- Arch.recent.each do |arch|
|
- Arch.recent.each do |arch|
|
||||||
.both
|
.both
|
||||||
|
- if controller.action_name == 'new'
|
||||||
|
= check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s), :id => "arches_#{arch.id}", :checked => 'checked'
|
||||||
|
- else
|
||||||
= check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s), :id => "arches_#{arch.id}"
|
= check_box_tag "arches[]", arch.id, (params[:arches]||[]).include?(arch.id.to_s), :id => "arches_#{arch.id}"
|
||||||
= label_tag "arches_#{arch.id}", arch.name
|
= label_tag "arches_#{arch.id}", arch.name
|
||||||
%h3= t("activerecord.attributes.build_list.pl")
|
|
||||||
.lineForm= f.select :pl_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]}
|
|
||||||
%h3= t("activerecord.attributes.build_list.update_type")
|
%h3= t("activerecord.attributes.build_list.update_type")
|
||||||
.lineForm= f.select :update_type, BuildList::UPDATE_TYPES
|
.lineForm= f.select :update_type, BuildList::UPDATE_TYPES
|
||||||
%h3= t("activerecord.attributes.build_list.preferences")
|
%h3= t("activerecord.attributes.build_list.preferences")
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
= link_to @build_list.user.try(:fullname), @build_list.user
|
= link_to @build_list.user.try(:fullname), @build_list.user
|
||||||
.both
|
.both
|
||||||
= link_to t("layout.publish"), publish_build_list_path(@build_list), :method => "put", :confirm => t("layout.confirm"), :class => "button tmargin10" if @build_list.can_publish? and can?(:publish, @build_list)
|
= link_to t("layout.publish"), publish_build_list_path(@build_list), :method => "put", :confirm => t("layout.confirm"), :class => "button tmargin10" if @build_list.can_publish? and can?(:publish, @build_list)
|
||||||
|
= link_to t("layout.reject_publish"), reject_publish_build_list_path(@build_list), :method => "put", :confirm => t("layout.confirm"), :class => "button tmargin10" if @build_list.can_reject_publish? and can?(:reject_publish, @build_list)
|
||||||
.hr
|
.hr
|
||||||
%h3= t("layout.build_lists.main_data")
|
%h3= t("layout.build_lists.main_data")
|
||||||
.leftside.width125= t("activerecord.attributes.build_list.bpl")
|
.leftside.width125= t("activerecord.attributes.build_list.bpl")
|
||||||
|
@ -46,12 +47,24 @@
|
||||||
.leftside.width125= t("activerecord.attributes.build_list.arch")
|
.leftside.width125= t("activerecord.attributes.build_list.arch")
|
||||||
.leftside= @build_list.arch.name
|
.leftside= @build_list.arch.name
|
||||||
.both
|
.both
|
||||||
.leftside.width125= t("activerecord.attributes.build_list.notified_at")
|
.leftside.width125= t("activerecord.attributes.build_list.updated_at")
|
||||||
.leftside= @build_list.notified_at
|
.leftside= @build_list.updated_at
|
||||||
.both
|
.both
|
||||||
.leftside.width125= t("activerecord.attributes.build_list.is_circle")
|
.leftside.width125= t("activerecord.attributes.build_list.is_circle")
|
||||||
.leftside= t("layout.#{@build_list.is_circle?}_")
|
.leftside= t("layout.#{@build_list.is_circle?}_")
|
||||||
.both
|
.both
|
||||||
|
- if !@build_list.in_work? && @build_list.started_at
|
||||||
|
%br
|
||||||
|
.leftside.width125
|
||||||
|
.leftside= @build_list.human_duration
|
||||||
|
.both
|
||||||
|
- if @build_list.in_work?
|
||||||
|
%br
|
||||||
|
.leftside.width125
|
||||||
|
.leftside
|
||||||
|
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
|
||||||
|
.both
|
||||||
|
|
||||||
.hr
|
.hr
|
||||||
%h3= t("layout.build_lists.items_header")
|
%h3= t("layout.build_lists.items_header")
|
||||||
- if @item_groups.blank?
|
- if @item_groups.blank?
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#open-comment.comment.view
|
#open-comment.comment.view
|
||||||
%h3.tmargin0= t("layout.comments.new_header")
|
%h3.tmargin0= t("layout.comments.new_header")
|
||||||
- if commentable.class == Issue
|
- if Comment.issue_comment?(commentable.class)
|
||||||
- new_path = project_issue_comments_path(project, commentable)
|
- new_path = project_issue_comments_path(project, commentable)
|
||||||
- is_subscribed = commentable.subscribes.exists?(:user_id => current_user.id)
|
- is_subscribed = commentable.subscribes.exists?(:user_id => current_user.id)
|
||||||
- subscribe_path = is_subscribed ? project_issue_subscribe_path(project, commentable, current_user.id) : project_issue_subscribes_path(project, commentable)
|
- subscribe_path = is_subscribed ? project_issue_subscribe_path(project, commentable, current_user.id) : project_issue_subscribes_path(project, commentable)
|
||||||
- else commentable.class == Grit::Commit
|
- else Comment.commit_comment?(commentable.class)
|
||||||
- new_path = project_commit_comments_path(project, commentable)
|
- new_path = project_commit_comments_path(project, commentable)
|
||||||
- is_subscribed = Subscribe.subscribed_to_commit?(project, current_user, commentable)
|
- is_subscribed = Subscribe.subscribed_to_commit?(project, current_user, commentable)
|
||||||
- subscribe_path = is_subscribed ? unsubscribe_commit_path(project, commentable) : subscribe_commit_path(project, commentable)
|
- subscribe_path = is_subscribed ? unsubscribe_commit_path(project, commentable) : subscribe_commit_path(project, commentable)
|
||||||
|
|
|
@ -1,14 +1,2 @@
|
||||||
.wrapper
|
.wrapper= f.text_area :body, :cols => 80
|
||||||
= f.text_area :body, :cols => 80
|
.comment-right= submit_tag t("layout.save")
|
||||||
.comment-right
|
|
||||||
= submit_tag t("layout.save")
|
|
||||||
-#.group
|
|
||||||
= f.label :body, t("activerecord.attributes.comment.body"), :class => :label
|
|
||||||
= f.text_area :body, :class => 'text_field', :cols => 80
|
|
||||||
|
|
||||||
-#.group.navform.wat-cf
|
|
||||||
%button.button{:type => "submit"}
|
|
||||||
= image_tag("choose.png", :alt => t("layout.save"))
|
|
||||||
= t("layout.save")
|
|
||||||
%span.text_button_padding= t("layout.or")
|
|
||||||
= link_to t("layout.cancel"), @commentable_path , :class => "text_button_padding link_button"
|
|
|
@ -4,36 +4,3 @@
|
||||||
- list.each do |comment|
|
- list.each do |comment|
|
||||||
- CommentPresenter.present(comment, :project => project, :commentable => commentable) do |presenter|
|
- CommentPresenter.present(comment, :project => project, :commentable => commentable) do |presenter|
|
||||||
= render :partial => 'shared/feed_message', :locals => {:presenter => presenter}
|
= render :partial => 'shared/feed_message', :locals => {:presenter => presenter}
|
||||||
-#.block#block-list
|
|
||||||
.content
|
|
||||||
%h2.title
|
|
||||||
= t("layout.issues.comments_header")
|
|
||||||
.inner
|
|
||||||
%ul.list
|
|
||||||
- list.each do |comment|
|
|
||||||
%li
|
|
||||||
.left
|
|
||||||
= link_to comment.user.uname, user_path(comment.user.uname)
|
|
||||||
.item
|
|
||||||
= comment.body
|
|
||||||
%br
|
|
||||||
%br
|
|
||||||
- if commentable.class == Issue
|
|
||||||
- edit_path = edit_project_issue_comment_path(project, commentable, comment)
|
|
||||||
- delete_path = project_issue_comment_path(project, commentable, comment)
|
|
||||||
- elsif commentable.class == Grit::Commit
|
|
||||||
- edit_path = edit_project_commit_comment_path(project, commentable, comment)
|
|
||||||
- delete_path = project_commit_comment_path(project, commentable, comment)
|
|
||||||
= link_to t("layout.edit"), edit_path if can? :update, comment
|
|
||||||
=# link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), delete_path, :method => "delete", :class => "button", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
|
|
||||||
= link_to t("layout.delete"), delete_path, :method => "delete", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
|
|
||||||
|
|
||||||
-#.block
|
|
||||||
.content
|
|
||||||
%h2.title
|
|
||||||
= t("layout.comments.new_header")
|
|
||||||
.inner
|
|
||||||
- new_path = project_issue_comments_path(project, commentable) if commentable.class == Issue
|
|
||||||
- new_path = project_commit_comments_path(project, commentable) if commentable.class == Grit::Commit
|
|
||||||
= form_for :comment, :url => new_path, :method => :post, :html => { :class => :form } do |f|
|
|
||||||
= render :partial => "comments/form", :locals => {:f => f}
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
.block
|
.block
|
||||||
.secondary-navigation
|
.secondary-navigation
|
||||||
%ul.wat-cf
|
%ul.wat-cf
|
||||||
%li.first= link_to t("layout.comments.back"), @commentable_path
|
%li.first= link_to t("layout.comments.back"), project_commentable_path(@project, @commentable)
|
||||||
.content
|
.content
|
||||||
%h2.title
|
%h2.title
|
||||||
= t("layout.comments.edit_header")
|
= t("layout.comments.edit_header")
|
||||||
.inner
|
.inner
|
||||||
= form_for @comment, :url => @update_url, :html => { :class => :form } do |f|
|
= form_for @comment, :url => project_commentable_comment_path(@project, @commentable, @comment), :html => {:class => :form} do |f|
|
||||||
= render :partial => "form", :locals => {:f => f}
|
= render :partial => "form", :locals => {:f => f}
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
%nav
|
%nav
|
||||||
%a{:href => new_register_request_path}
|
%a{:href => new_register_request_path}
|
||||||
%p=t("layout.devise.shared_links.sign_up")
|
%p=t("layout.devise.shared_links.sign_up")
|
||||||
/ Top block
|
|
||||||
%header
|
%header
|
||||||
.logo
|
.logo
|
||||||
/ Page
|
|
||||||
%article
|
%article
|
||||||
%br
|
%br
|
||||||
%h1= title t('devise.passwords.edit')
|
%h1= title t('devise.passwords.edit')
|
||||||
|
@ -17,11 +15,11 @@
|
||||||
= f.hidden_field :reset_password_token
|
= f.hidden_field :reset_password_token
|
||||||
.left.first=t('activerecord.attributes.user.password')
|
.left.first=t('activerecord.attributes.user.password')
|
||||||
.right.first
|
.right.first
|
||||||
= f.text_field :password, :id => 'password', :class => "registartion-input #{password_error ? 'registartion-input-error' : ''}"
|
= f.password_field :password, :id => 'password', :class => "registartion-input #{password_error ? 'registartion-input-error' : ''}"
|
||||||
.both
|
.both
|
||||||
.left=t('activerecord.attributes.user.password_confirm')
|
.left=t('activerecord.attributes.user.password_confirm')
|
||||||
.right
|
.right
|
||||||
= f.text_field :password_confirmation, :id => 'password2', :class => "registartion-input #{password_error ? 'registartion-input-error' : ''}"
|
= f.password_field :password_confirmation, :id => 'password2', :class => "registartion-input #{password_error ? 'registartion-input-error' : ''}"
|
||||||
.both
|
.both
|
||||||
%br
|
%br
|
||||||
=f.submit t("devise.passwords.edit_button"), :class => 'button', :id => 'btnLogin'
|
=f.submit t("devise.passwords.edit_button"), :class => 'button', :id => 'btnLogin'
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
.block
|
|
||||||
.content
|
|
||||||
%h2.title
|
|
||||||
= title t("layout.downloads.title")
|
|
||||||
.inner
|
|
||||||
%h3= t("layout.downloads.message")
|
|
||||||
.inner
|
|
||||||
%table.table
|
|
||||||
%tr
|
|
||||||
%th.first= t("activerecord.attributes.download.name")
|
|
||||||
%th= t("activerecord.attributes.download.version")
|
|
||||||
%th= t("activerecord.attributes.download.distro")
|
|
||||||
%th= t("activerecord.attributes.download.platform")
|
|
||||||
%th.last= t("activerecord.attributes.download.counter")
|
|
||||||
- @downloads.each do |download|
|
|
||||||
%tr{:class => cycle("odd", "even")}
|
|
||||||
%td
|
|
||||||
= download.name
|
|
||||||
%td
|
|
||||||
= download.version
|
|
||||||
%td
|
|
||||||
= download.distro
|
|
||||||
%td
|
|
||||||
= download.platform
|
|
||||||
%td.last
|
|
||||||
= download.counter
|
|
||||||
.actions-bar.wat-cf
|
|
||||||
.actions
|
|
||||||
= will_paginate @downloads
|
|
||||||
= render 'admin/submenu'
|
|
|
@ -16,5 +16,5 @@
|
||||||
#repo-wrapper
|
#repo-wrapper
|
||||||
= render :partial => 'show'
|
= render :partial => 'show'
|
||||||
|
|
||||||
= render :partial => "comments/list", :locals => {:list => Project.commit_comments(@commit, @project), :project => @project, :commentable => @commit}
|
= render :partial => "comments/list", :locals => {:list => Comment.for_commit(@commit), :project => @project, :commentable => @commit}
|
||||||
= render :partial => "comments/add", :locals => {:project => @project, :commentable => @commit} if current_user
|
= render :partial => "comments/add", :locals => {:project => @project, :commentable => @commit} if current_user
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
- if owner.projects.exists? :name => @project.name
|
||||||
|
- is_group = owner.class == Group ? "(#{t 'activerecord.models.group'})" : ''
|
||||||
|
%p.center
|
||||||
|
=t 'layout.projects.already_exists'
|
||||||
|
=link_to "#{owner.uname}/#{@project.name} #{is_group}", project_path(owner.projects.by_name(@project.name).first.id)
|
||||||
|
- else
|
||||||
|
= form_for @project, :url => fork_project_path(@project), :html => { :class => :form, :multipart => true, :method => :post } do |f|
|
||||||
|
= hidden_field_tag :group, owner.id if owner.class == Group
|
||||||
|
=f.submit t('layout.projects.fork_to', :to => "#{owner.uname} #{is_group}"), :class => 'btn btn-primary disabled', 'data-loading-text' => t('layout.processing'), :id => 'create_fork'
|
||||||
|
|
||||||
|
:javascript
|
||||||
|
$('#create_fork').click(function () {
|
||||||
|
$(this).button('loading');
|
||||||
|
})
|
|
@ -1,2 +1,11 @@
|
||||||
- if can? :fork, @project
|
- if can? :fork, @project
|
||||||
.r#fork-and-edit= link_to t('layout.projects.fork_and_edit'), fork_project_path(@project), :method => :post, :confirm => t("layout.confirm"), :class => 'button'
|
.r#fork-and-edit= link_to t('layout.projects.fork_and_edit'), '#forkModal', :class => 'button', 'data-toggle' => 'modal'
|
||||||
|
#forkModal.modal{:style => 'display: none;'}
|
||||||
|
.modal-header
|
||||||
|
%a.close{"data-dismiss" => "modal"} ×
|
||||||
|
%h3=t 'layout.projects.fork_modal_header'
|
||||||
|
.modal-footer=render :partial => 'git/shared/choose_fork', :locals => {:owner => current_user}
|
||||||
|
- Group.can_own_project(current_user).each do |group|
|
||||||
|
.modal-footer=render :partial => 'git/shared/choose_fork', :locals => {:owner => group}
|
||||||
|
- if can? :create, @project.build_lists.new
|
||||||
|
.r{:style => "display: block"}= link_to t('layout.projects.new_build_list'), new_project_build_list_path(@project), :class => 'button'
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
.leftlist= t('activerecord.attributes.issue.body') + ':'
|
.leftlist= t('activerecord.attributes.issue.body') + ':'
|
||||||
.rightlist= f.text_area :body
|
.rightlist= f.text_area :body
|
||||||
.both
|
.both
|
||||||
.leftlist= t('activerecord.attributes.issue.user') + ':'
|
.leftlist= t('activerecord.attributes.issue.assignee') + ':'
|
||||||
.rightlist
|
.rightlist
|
||||||
%span#people-span.small-text= t('layout.issues.choose_user_on_left')
|
%span#people-span.small-text= t('layout.issues.choose_user_on_left')
|
||||||
#issue_executor
|
#issue_assignee
|
||||||
.both
|
.both
|
||||||
.leftlist= t('layout.issues.labels')
|
.leftlist= t('layout.issues.labels') + ':'
|
||||||
.rightlist
|
.rightlist
|
||||||
%span#flag-span.small-text= t('layout.issues.choose_labels_on_left')
|
%span#flag-span.small-text= t('layout.issues.choose_labels_on_left')
|
||||||
#issue_labels
|
#issue_labels
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
%tr
|
%tr
|
||||||
%td=radio_button_tag :myradio, 'to_me', @is_assigned_to_me, {:id => 'myradio1', :class => 'niceRadio', :name => 'filter'}
|
%td=radio_button_tag :myradio, 'to_me', @is_assigned_to_me, {:id => 'myradio1', :class => 'niceRadio', :name => 'filter'}
|
||||||
%td=t("layout.issues.to_me")
|
%td=t("layout.issues.to_me")
|
||||||
%td.width30.right=@project.issues.where(:user_id => current_user).count
|
%td.width30.right=@project.issues.where(:assignee_id => current_user.id).count
|
||||||
=form_tag project_issues_path(@project), :id => 'search_issue', :method => :get do
|
=form_tag project_issues_path(@project), :id => 'search_issue', :method => :get do
|
||||||
.bordered.bpadding20
|
.bordered.bpadding20
|
||||||
=tracker_search_field(:search_issue, t('layout.issues.search'))
|
=tracker_search_field(:search_issue, t('layout.issues.search'))
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
%div.issue_title=issue.title
|
%div.issue_title=issue.title
|
||||||
.smalltext
|
.smalltext
|
||||||
=issue.created_at.to_s(:long)
|
=issue.created_at.to_s(:long)
|
||||||
=t("layout.by") if issue.creator
|
=t("layout.by") if issue.user
|
||||||
=link_to(issue.creator.uname, user_path(issue.creator)) if issue.creator
|
=link_to(issue.user.uname, user_path(issue.user)) if issue.user
|
||||||
-issue.labels.each do |label|
|
-issue.labels.each do |label|
|
||||||
.left.nomargin
|
.left.nomargin
|
||||||
.label.selected.tracker.left
|
.label.selected.tracker.left
|
||||||
.labeltext.selected{:style => "background: ##{label.color};"}=label.name
|
.labeltext.selected{:style => "background: ##{label.color};"}=label.name
|
||||||
%td.td3
|
%td.td3
|
||||||
.avatar
|
.avatar
|
||||||
=link_to image_tag(avatar_url(issue.user), :alt => 'avatar'), user_path(issue.user) if issue.user
|
=link_to image_tag(avatar_url(issue.assignee), :alt => 'avatar'), user_path(issue.assignee) if issue.assignee
|
||||||
%a{:href => "#{project_issue_path @project, issue}#block-list"}
|
%a{:href => "#{project_issue_path @project, issue}#block-list"}
|
||||||
.answers
|
.answers
|
||||||
.pic= image_tag 'answers.png'
|
.pic= image_tag 'answers.png'
|
||||||
|
|
|
@ -10,30 +10,30 @@
|
||||||
=form_tag [@project, @issue], :id => 'update_issue_status', :method => :put do
|
=form_tag [@project, @issue], :id => 'update_issue_status', :method => :put do
|
||||||
=hidden_field_tag "issue_status", @issue.closed? ? 'closed' : 'open', :name => "issue[status]"
|
=hidden_field_tag "issue_status", @issue.closed? ? 'closed' : 'open', :name => "issue[status]"
|
||||||
.bordered.nopadding
|
.bordered.nopadding
|
||||||
%h3=t('layout.issues.executor')
|
%h3=t('layout.issues.assignee')
|
||||||
- if @issue.persisted?
|
- if @issue.persisted?
|
||||||
-if can_manage
|
-if can_manage
|
||||||
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_executor issue'} do |f|
|
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_assignee issue'} do |f|
|
||||||
=hidden_field_tag "user-default_executor", nil, :name => 'issue[user_id]'
|
=hidden_field_tag "user-default_assignee", nil, :name => 'issue[assignee_id]'
|
||||||
.current_executor
|
.current_assignee
|
||||||
- if @issue.user
|
- if @issue.assignee
|
||||||
#user-0.people.nopointer
|
#user-0.people.nopointer
|
||||||
.avatar=image_tag avatar_url(@issue.user), :alt => 'avatar'
|
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
|
||||||
.name="#{@issue.user.uname} (#{@issue.user.name})"
|
.name="#{@issue.user.uname} (#{@issue.assignee.name})"
|
||||||
=hidden_field_tag "user-0", @issue.user.id, :name => 'issue[user_id]'
|
=hidden_field_tag "user-0", @issue.assignee.id, :name => 'issue[assignee_id]'
|
||||||
.both
|
.both
|
||||||
- elsif @issue.user
|
- elsif @issue.assignee
|
||||||
.people.nopointer
|
.people.nopointer
|
||||||
.avatar=image_tag avatar_url(@issue.user), :alt => 'avatar'
|
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
|
||||||
.name="#{@issue.user.uname} (#{@issue.user.name})"
|
.name="#{@issue.assignee.uname} (#{@issue.assignee.name})"
|
||||||
.both
|
.both
|
||||||
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_executor") if can_manage
|
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
|
||||||
- if can_manage
|
- if can_manage
|
||||||
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
|
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
|
||||||
=tracker_search_field(:search_user, t('layout.issues.search_user'))
|
=tracker_search_field(:search_user, t('layout.issues.search_user'))
|
||||||
#manage_issue_users_list
|
#manage_issue_users_list
|
||||||
=render 'issues/search_collaborators'
|
=render 'issues/search_collaborators'
|
||||||
=link_to(t('layout.issues.done'), '#', :class => "button tmargin10 update_executor", :style => 'display:none') if can_manage
|
=link_to(t('layout.issues.done'), '#', :class => "button tmargin10 update_assignee", :style => 'display:none') if can_manage
|
||||||
|
|
||||||
.block
|
.block
|
||||||
%h3=t('layout.issues.labels')
|
%h3=t('layout.issues.labels')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
- (@users || []).each_with_index do |user, index|
|
- (@users || []).each_with_index do |user, index|
|
||||||
.people.selected{:id => "user-#{index}", :class => 'add_executor'}
|
.people.selected{:id => "user-#{index}", :class => 'add_assignee'}
|
||||||
.avatar= image_tag(avatar_url(user), :alt => 'avatar')
|
.avatar= image_tag(avatar_url(user), :alt => 'avatar')
|
||||||
.name="#{user.uname} (#{user.name})"
|
.name="#{user.uname} (#{user.name})"
|
||||||
=hidden_field_tag "user-#{index}", user.id, :name => 'issue[user_id]'
|
=hidden_field_tag "user-#{index}", user.id, :name => 'issue[assignee_id]'
|
||||||
.both
|
.both
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
.activity
|
.activity
|
||||||
.top
|
.top
|
||||||
.image
|
.image
|
||||||
=image_tag(avatar_url(@issue.creator, :medium), :alt => 'avatar') if @issue.creator
|
=image_tag(avatar_url(@issue.user, :medium), :alt => 'avatar') if @issue.user
|
||||||
.text
|
.text
|
||||||
%span.name=link_to("#{@issue.creator.uname} (#{@issue.creator.name})", user_path(@issue.creator)) if @issue.creator
|
%span.name=link_to("#{@issue.user.uname} (#{@issue.user.name})", user_path(@issue.user)) if @issue.user
|
||||||
%br/
|
%br/
|
||||||
%span.date=@issue.created_at.to_s(:long)
|
%span.date=@issue.created_at.to_s(:long)
|
||||||
%br/
|
%br/
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
= javascript_include_tag "application"
|
= javascript_include_tag "application"
|
||||||
= csrf_meta_tag
|
= csrf_meta_tag
|
||||||
= display_meta_tags :site => APP_CONFIG['project_name'], :reverse => true, :separator => '-'
|
= display_meta_tags :site => APP_CONFIG['project_name'], :reverse => true, :separator => '-'
|
||||||
|
- if user_signed_in?
|
||||||
|
= auto_discovery_link_tag :atom, root_path(:format => 'atom', :token => current_user.authentication_token), :title => t("layout.atom_link_tag_title", :nickname => current_user.name, :app_name => APP_CONFIG['project_name'])
|
||||||
|
|
||||||
%body
|
%body
|
||||||
.wrap{:class => content_for?(:sidebar) ? 'columns' : ''}
|
.wrap{:class => content_for?(:sidebar) ? 'columns' : ''}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
%table.tablesorter{:cellpadding => "0", :cellspacing => "0"}
|
%table.tablesorter{:cellpadding => "0", :cellspacing => "0"}
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
-#%th.lpadding16= t("activerecord.attributes.product_build_list.bs_id")
|
|
||||||
%th.lpadding16= t("activerecord.attributes.product_build_list.id")
|
%th.lpadding16= t("activerecord.attributes.product_build_list.id")
|
||||||
%th.lpadding16= t("activerecord.attributes.product_build_list.status")
|
%th.lpadding16= t("activerecord.attributes.product_build_list.status")
|
||||||
%th.lpadding16= t("activerecord.attributes.product_build_list.container_path")
|
%th.lpadding16= t("activerecord.attributes.product_build_list.container_path")
|
||||||
|
|
|
@ -37,16 +37,9 @@
|
||||||
|
|
||||||
= render :partial => "products/crontab", :locals => { :form => f }
|
= render :partial => "products/crontab", :locals => { :form => f }
|
||||||
|
|
||||||
- content_for :commented do
|
|
||||||
.leftlist= f.label :system_wide, :class => :label
|
|
||||||
.rightlist= f.check_box :system_wide, :class => 'check_box'
|
|
||||||
|
|
||||||
.both
|
.both
|
||||||
.button_block
|
.button_block
|
||||||
= submit_tag t("layout.save")
|
= submit_tag t("layout.save")
|
||||||
-#%input.button{:type => "submit", :class => "button"}
|
|
||||||
-#= image_tag("choose.png", :alt => t("layout.save"))
|
|
||||||
-#= t("layout.clone")
|
|
||||||
%span.text_button_padding= t("layout.or")
|
%span.text_button_padding= t("layout.or")
|
||||||
= link_to t("layout.cancel"), @product.new_record? ? platform_path(@platform) : platform_product_path(@platform, @product), :class => "button"
|
= link_to t("layout.cancel"), @product.new_record? ? platform_path(@platform) : platform_product_path(@platform, @product), :class => "button"
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,3 @@
|
||||||
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
||||||
= render :partial => "form", :locals => {:f => f}
|
= render :partial => "form", :locals => {:f => f}
|
||||||
|
|
||||||
-#.block
|
|
||||||
.secondary-navigation
|
|
||||||
%ul.wat-cf
|
|
||||||
%li.first= link_to @platform.name, platform_path(@platform) + "#products"
|
|
||||||
%li.active= link_to @product.name, edit_platform_product_path(@platform, @product)
|
|
||||||
.content
|
|
||||||
%h2.title= t("layout.products.edit_header")
|
|
||||||
.inner
|
|
||||||
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
|
||||||
= render :partial => "form", :locals => {:f => f}
|
|
||||||
|
|
||||||
-#- content_for :sidebar, render(:partial => 'sidebar')
|
|
||||||
|
|
|
@ -5,15 +5,3 @@
|
||||||
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
||||||
= render :partial => "form", :locals => {:f => f}
|
= render :partial => "form", :locals => {:f => f}
|
||||||
|
|
||||||
-#.block
|
|
||||||
.secondary-navigation
|
|
||||||
%ul.wat-cf
|
|
||||||
%li.first= link_to @platform.name, platform_path(@platform) + "#products"
|
|
||||||
%li.active= link_to t("layout.products.new"), new_platform_product_path(@platform)
|
|
||||||
.content
|
|
||||||
%h2.title= t("layout.products.new_header")
|
|
||||||
.inner
|
|
||||||
= form_for [@platform, @product], :html => { :class => :form, :multipart => true } do |f|
|
|
||||||
= render :partial => "form", :locals => {:f => f}
|
|
||||||
|
|
||||||
-#- content_for :sidebar, render(:partial => 'sidebar')
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
= link_to image_tag("code.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_platform_product_path(@platform, @product), :class => "button"
|
= link_to image_tag("code.png", :alt => t("layout.edit")) + " " + t("layout.edit"), edit_platform_product_path(@platform, @product), :class => "button"
|
||||||
- if can? :destroy, @product
|
- if can? :destroy, @product
|
||||||
= link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), platform_product_path(@platform, @product), :method => "delete", :class => "button", :confirm => t("layout.products.confirm_delete")
|
= link_to image_tag("x.png", :alt => t("layout.delete")) + " " + t("layout.delete"), platform_product_path(@platform, @product), :method => "delete", :class => "button", :confirm => t("layout.products.confirm_delete")
|
||||||
-# if @product.can_clone?
|
|
||||||
=# link_to t("layout.products.clone"), clone_platform_product_path(@platform, @product), :class => "button"
|
|
||||||
- if can?(:create, @product.product_build_lists.build)
|
- if can?(:create, @product.product_build_lists.build)
|
||||||
= link_to t("layout.products.build"), platform_product_product_build_lists_path(@platform, @product), :class => "button", :method => 'post', :confirm => t("layout.confirm")
|
= link_to t("layout.products.build"), platform_product_product_build_lists_path(@platform, @product), :class => "button", :method => 'post', :confirm => t("layout.confirm")
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,28 @@
|
||||||
.description-top
|
.description-top
|
||||||
|
%ul.nav.zip
|
||||||
|
%li#menu-archive.dropdown
|
||||||
|
%a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#menu-archive"}
|
||||||
|
=image_tag 'zip.png', :alt => 'ZIP'
|
||||||
|
%b.caret
|
||||||
|
%ul.dropdown-menu
|
||||||
|
%li=link_to "tar.gz", archive_path(project.id, 'tar', @treeish)
|
||||||
|
%li=link_to "zip", archive_path(project.id, 'zip', @treeish)
|
||||||
|
|
||||||
= text_field_tag :url, git_repo_url(project.git_repo_name), :class => 'name', :spellcheck => 'false', :readonly => true
|
= text_field_tag :url, git_repo_url(project.git_repo_name), :class => 'name', :spellcheck => 'false', :readonly => true
|
||||||
|
.git_help ?
|
||||||
.role= can?(:write, project) ? t("layout.read_write_access") : t("layout.read_access")
|
.role= can?(:write, project) ? t("layout.read_write_access") : t("layout.read_access")
|
||||||
= render :partial => 'projects/branch_select', :locals => {:project => project}
|
= render :partial => 'projects/branch_select', :locals => {:project => project}
|
||||||
|
#git_help_data
|
||||||
|
%p= t("layout.projects.git_help.cloning") + ":"
|
||||||
|
%p
|
||||||
|
%p~ "git clone #{git_repo_url(project.git_repo_name)} #{project.name}"
|
||||||
|
%p~ "cd #{project.name}"
|
||||||
|
%p
|
||||||
|
%p= t("layout.projects.git_help.remote") + ":"
|
||||||
|
%p
|
||||||
|
%p~ "git remote add #{project.name} #{git_repo_url(project.git_repo_name)}"
|
||||||
|
%p~ "git fetch #{project.name}"
|
||||||
|
%p~ "git checkout -b my-local-tracking-branch #{project.name}/master_or_other_branch"
|
||||||
.both
|
.both
|
||||||
:javascript
|
:javascript
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
%p== Hello, #{@user.user_appeal}.
|
%p== Hello, #{@user.user_appeal}.
|
||||||
|
|
||||||
- if @comment.commentable.class == Issue
|
- if @comment.issue_comment?
|
||||||
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
|
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
|
||||||
- object = 'issue'
|
- object = 'issue'
|
||||||
- elsif @comment.commit_comment?
|
- elsif @comment.commit_comment?
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
%p== Здравствуйте, #{@user.user_appeal}.
|
%p== Здравствуйте, #{@user.user_appeal}.
|
||||||
|
|
||||||
- if @comment.commentable.class == Issue
|
- if @comment.issue_comment?
|
||||||
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
|
- link = link_to @comment.commentable.title, project_issue_url(@comment.commentable.project, @comment.commentable)
|
||||||
- object = 'задаче'
|
- object = 'задаче'
|
||||||
- elsif @comment.commit_comment?
|
- elsif @comment.commit_comment?
|
||||||
|
|
|
@ -31,7 +31,7 @@ module Rosa
|
||||||
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
||||||
|
|
||||||
# Activate observers that should always be running.
|
# Activate observers that should always be running.
|
||||||
config.active_record.observers = :event_log_observer, :activity_feed_observer
|
config.active_record.observers = :event_log_observer, :activity_feed_observer, :build_list_observer
|
||||||
|
|
||||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||||
|
|
|
@ -11,7 +11,6 @@ set :default_environment, {
|
||||||
|
|
||||||
require 'rvm/capistrano'
|
require 'rvm/capistrano'
|
||||||
require 'bundler/capistrano'
|
require 'bundler/capistrano'
|
||||||
require 'delayed/recipes'
|
|
||||||
require 'airbrake/capistrano'
|
require 'airbrake/capistrano'
|
||||||
|
|
||||||
set :whenever_command, "bundle exec whenever"
|
set :whenever_command, "bundle exec whenever"
|
||||||
|
@ -38,6 +37,7 @@ set :deploy_via, :remote_cache
|
||||||
require 'lib/recipes/nginx'
|
require 'lib/recipes/nginx'
|
||||||
require 'lib/recipes/unicorn'
|
require 'lib/recipes/unicorn'
|
||||||
require 'lib/recipes/bluepill'
|
require 'lib/recipes/bluepill'
|
||||||
|
require 'lib/recipes/delayed_job'
|
||||||
|
|
||||||
namespace :deploy do
|
namespace :deploy do
|
||||||
task :stub_xml_rpc do
|
task :stub_xml_rpc do
|
||||||
|
@ -88,7 +88,7 @@ after "deploy:setup", "deploy:symlink_pids"
|
||||||
# DJ
|
# DJ
|
||||||
after "deploy:stop", "delayed_job:stop"
|
after "deploy:stop", "delayed_job:stop"
|
||||||
after "deploy:start", "delayed_job:start"
|
after "deploy:start", "delayed_job:start"
|
||||||
# after "deploy:restart", "delayed_job:restart"
|
after "deploy:restart", "delayed_job:restart"
|
||||||
|
|
||||||
after "deploy:restart", "deploy:cleanup"
|
after "deploy:restart", "deploy:cleanup"
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ en:
|
||||||
true_: True
|
true_: True
|
||||||
false_: False
|
false_: False
|
||||||
publish: Publish
|
publish: Publish
|
||||||
|
reject_publish: Reject
|
||||||
add: Add
|
add: Add
|
||||||
upload: Upload
|
upload: Upload
|
||||||
not_access: Access denied!
|
not_access: Access denied!
|
||||||
|
@ -44,6 +45,7 @@ en:
|
||||||
back: Back
|
back: Back
|
||||||
processing: working ...
|
processing: working ...
|
||||||
invalid_content_type: incorrect type
|
invalid_content_type: incorrect type
|
||||||
|
atom_link_tag_title: Private feed for %{nickname} | %{app_name}
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
label: Settings
|
label: Settings
|
||||||
|
@ -64,11 +66,6 @@ en:
|
||||||
unlock: Do not receive unlock instructions?
|
unlock: Do not receive unlock instructions?
|
||||||
sign_in_through: Sign in by %{provider}
|
sign_in_through: Sign in by %{provider}
|
||||||
|
|
||||||
downloads:
|
|
||||||
title: Downloads statistic
|
|
||||||
message: Automatically updated every 24 hours
|
|
||||||
refresh_btn: Refresh
|
|
||||||
|
|
||||||
weekdays:
|
weekdays:
|
||||||
Monday: Monday
|
Monday: Monday
|
||||||
Tuesday: Tuesday
|
Tuesday: Tuesday
|
||||||
|
@ -137,9 +134,6 @@ en:
|
||||||
|
|
||||||
exception_message: Access violation to this page!
|
exception_message: Access violation to this page!
|
||||||
|
|
||||||
downloads:
|
|
||||||
statistics_refreshed: Statistics refreshed
|
|
||||||
|
|
||||||
collaborators:
|
collaborators:
|
||||||
successfully_changed: Collaborators list successfully changed
|
successfully_changed: Collaborators list successfully changed
|
||||||
error_in_changing: Collaborators list changing error
|
error_in_changing: Collaborators list changing error
|
||||||
|
@ -172,7 +166,6 @@ en:
|
||||||
arch: Arch
|
arch: Arch
|
||||||
private_user: Private user
|
private_user: Private user
|
||||||
product_build_list: Product build list
|
product_build_list: Product build list
|
||||||
download: Statistics
|
|
||||||
|
|
||||||
attributes:
|
attributes:
|
||||||
settings:
|
settings:
|
||||||
|
@ -195,9 +188,3 @@ en:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
updated_at: Updated
|
updated_at: Updated
|
||||||
|
|
||||||
download:
|
|
||||||
name: Name
|
|
||||||
version: Version
|
|
||||||
distro: Source
|
|
||||||
platform: Platform
|
|
||||||
counter: Downloads
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ en:
|
||||||
repositories: Repositories
|
repositories: Repositories
|
||||||
personal_repository: My repository
|
personal_repository: My repository
|
||||||
products: Products
|
products: Products
|
||||||
downloads: Statistics
|
|
||||||
top_menu:
|
top_menu:
|
||||||
platforms: Platforms
|
platforms: Platforms
|
||||||
projects: Projects
|
projects: Projects
|
||||||
|
@ -38,5 +37,4 @@ en:
|
||||||
users: Users
|
users: Users
|
||||||
register_requests: Invites
|
register_requests: Invites
|
||||||
event_logs: Event log
|
event_logs: Event log
|
||||||
downloads: Download statistic
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ ru:
|
||||||
products: Продукты
|
products: Продукты
|
||||||
repositories: Репозитории
|
repositories: Репозитории
|
||||||
personal_repository: Мой репозиторий
|
personal_repository: Мой репозиторий
|
||||||
downloads: Статистика
|
|
||||||
top_menu:
|
top_menu:
|
||||||
platforms: Платформы
|
platforms: Платформы
|
||||||
projects: Проекты
|
projects: Проекты
|
||||||
|
@ -38,4 +37,3 @@ ru:
|
||||||
users: Пользователи
|
users: Пользователи
|
||||||
register_requests: Инвайты
|
register_requests: Инвайты
|
||||||
event_logs: Лог событий
|
event_logs: Лог событий
|
||||||
downloads: Статистика закачек пакетов
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ en:
|
||||||
my_builds_by_day: My today builds
|
my_builds_by_day: My today builds
|
||||||
new_project: Create project
|
new_project: Create project
|
||||||
load_messages: show previous messages
|
load_messages: show previous messages
|
||||||
|
atom_title: Activity Feed
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
subjects:
|
subjects:
|
||||||
|
|
|
@ -8,6 +8,7 @@ ru:
|
||||||
my_builds_by_day: Мои сборки за день
|
my_builds_by_day: Мои сборки за день
|
||||||
new_project: Создать проект
|
new_project: Создать проект
|
||||||
load_messages: показать предыдущие сообщения
|
load_messages: показать предыдущие сообщения
|
||||||
|
atom_title: Лента активности
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
subjects:
|
subjects:
|
||||||
|
|
|
@ -14,10 +14,9 @@ en:
|
||||||
arch_id: Architecture
|
arch_id: Architecture
|
||||||
arch: Architecture
|
arch: Architecture
|
||||||
is_circle: Recurrent build
|
is_circle: Recurrent build
|
||||||
notified_at: Notified at
|
updated_at: Notified at
|
||||||
additional_repos: Additional repositories
|
additional_repos: Additional repositories
|
||||||
include_repos: Included repositories
|
include_repos: Included repositories
|
||||||
updated_at: Updated on
|
|
||||||
created_at: Created on
|
created_at: Created on
|
||||||
pl: Repository for package storage
|
pl: Repository for package storage
|
||||||
pl_id: Repository for package storage
|
pl_id: Repository for package storage
|
||||||
|
@ -29,6 +28,8 @@ en:
|
||||||
project_version: Version
|
project_version: Version
|
||||||
user: User
|
user: User
|
||||||
preferences: Preferences
|
preferences: Preferences
|
||||||
|
started_at: Build started at
|
||||||
|
duration: Build duration in seconds
|
||||||
|
|
||||||
build_list/item:
|
build_list/item:
|
||||||
name: Name
|
name: Name
|
||||||
|
@ -43,8 +44,8 @@ en:
|
||||||
current: Curent
|
current: Curent
|
||||||
created_at_start: "Build to start on:"
|
created_at_start: "Build to start on:"
|
||||||
created_at_end: "Build to start until:"
|
created_at_end: "Build to start until:"
|
||||||
notified_at_start: "Last update from BS on:"
|
updated_at_start: "Last update from BS on:"
|
||||||
notified_at_end: " Last update from BS until:"
|
updated_at_end: " Last update from BS until:"
|
||||||
bs_id_search: 'Search by Id'
|
bs_id_search: 'Search by Id'
|
||||||
project_name_search: Search by project name
|
project_name_search: Search by project name
|
||||||
bs_id_not_set: Id has not been configured yet
|
bs_id_not_set: Id has not been configured yet
|
||||||
|
@ -54,11 +55,15 @@ en:
|
||||||
cancel_success: 'Build canceled'
|
cancel_success: 'Build canceled'
|
||||||
cancel_fail: 'Errors during build cancelation!'
|
cancel_fail: 'Errors during build cancelation!'
|
||||||
publish_success: 'Build is queued for publishing'
|
publish_success: 'Build is queued for publishing'
|
||||||
|
reject_publish_success: 'Publishing rejected'
|
||||||
publish_fail: 'Errors during build publishing!'
|
publish_fail: 'Errors during build publishing!'
|
||||||
|
reject_publish_fail: 'Rejecting publishing failed'
|
||||||
container_published: 'Container published in a repository'
|
container_published: 'Container published in a repository'
|
||||||
action: Action
|
action: Action
|
||||||
new_header: New build
|
new_header: New build
|
||||||
main_data: Main data
|
main_data: Main data
|
||||||
|
human_current_duration: Build currently takes %{hours} h. %{minutes} min.
|
||||||
|
human_duration: Builded in %{hours} h. %{minutes} min.
|
||||||
|
|
||||||
ownership:
|
ownership:
|
||||||
header: Build list ownership
|
header: Build list ownership
|
||||||
|
@ -84,6 +89,7 @@ en:
|
||||||
statuses:
|
statuses:
|
||||||
build_error: Build error
|
build_error: Build error
|
||||||
build_published: Build has been published
|
build_published: Build has been published
|
||||||
|
rejected_publish: Publishing rejected
|
||||||
build_publish: Build is being publishing
|
build_publish: Build is being publishing
|
||||||
failed_publish: Publishing error
|
failed_publish: Publishing error
|
||||||
dependencies_fail: Dependences not found
|
dependencies_fail: Dependences not found
|
||||||
|
@ -95,7 +101,7 @@ en:
|
||||||
success: Build complete
|
success: Build complete
|
||||||
build_started: Build started
|
build_started: Build started
|
||||||
platform_not_found: Platform not found
|
platform_not_found: Platform not found
|
||||||
platform_pending: Platforn pending
|
platform_pending: Platform pending
|
||||||
project_not_found: Project not found
|
project_not_found: Project not found
|
||||||
project_version_not_found: Project version not found
|
project_version_not_found: Project version not found
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,9 @@ ru:
|
||||||
arch_id: Архитектура
|
arch_id: Архитектура
|
||||||
arch: Архитектура
|
arch: Архитектура
|
||||||
is_circle: Циклическая сборка
|
is_circle: Циклическая сборка
|
||||||
notified_at: Информация получена
|
updated_at: Информация получена
|
||||||
additional_repos: Дополнительные репозитории
|
additional_repos: Дополнительные репозитории
|
||||||
include_repos: Подключаемые репозитории
|
include_repos: Подключаемые репозитории
|
||||||
updated_at: Обновлен
|
|
||||||
created_at: Создан
|
created_at: Создан
|
||||||
pl: Репозиторий для сохранения пакетов
|
pl: Репозиторий для сохранения пакетов
|
||||||
pl_id: Репозиторий для сохранения пакетов
|
pl_id: Репозиторий для сохранения пакетов
|
||||||
|
@ -29,6 +28,7 @@ ru:
|
||||||
project_version: Версия
|
project_version: Версия
|
||||||
user: Пользователь
|
user: Пользователь
|
||||||
preferences: Настройки
|
preferences: Настройки
|
||||||
|
duration: Длительность билда в секундах
|
||||||
|
|
||||||
build_list/item:
|
build_list/item:
|
||||||
name: Название
|
name: Название
|
||||||
|
@ -43,8 +43,8 @@ ru:
|
||||||
current: Текущие
|
current: Текущие
|
||||||
created_at_start: "Время постановки на сборку с:"
|
created_at_start: "Время постановки на сборку с:"
|
||||||
created_at_end: "Время постановки на сборку по:"
|
created_at_end: "Время постановки на сборку по:"
|
||||||
notified_at_start: "Время последнего обновления от BS с:"
|
updated_at_start: "Время последнего обновления от BS с:"
|
||||||
notified_at_end: "Время последнего обновления от BS по:"
|
updated_at_end: "Время последнего обновления от BS по:"
|
||||||
bs_id_search: 'Поиск по Id'
|
bs_id_search: 'Поиск по Id'
|
||||||
project_name_search: Поиск по названию проекта
|
project_name_search: Поиск по названию проекта
|
||||||
bs_id_not_set: Id еще не присвоен
|
bs_id_not_set: Id еще не присвоен
|
||||||
|
@ -54,12 +54,17 @@ ru:
|
||||||
cancel_success: 'Сборка отменена.'
|
cancel_success: 'Сборка отменена.'
|
||||||
cancel_fail: 'При отмене сборки произошла ошибка!'
|
cancel_fail: 'При отмене сборки произошла ошибка!'
|
||||||
publish_success: 'Сборка поставлена в очередь на публикацию.'
|
publish_success: 'Сборка поставлена в очередь на публикацию.'
|
||||||
|
reject_publish_success: 'Публикация отклонена'
|
||||||
publish_fail: 'При публикации сборки произошла ошибка!'
|
publish_fail: 'При публикации сборки произошла ошибка!'
|
||||||
|
reject_publish_fail: 'Не удалось отклонить публикацию сборки'
|
||||||
container_published: 'Контейнер размещен в репозитории'
|
container_published: 'Контейнер размещен в репозитории'
|
||||||
action: Действие
|
action: Действие
|
||||||
new_header: Новая сборка
|
new_header: Новая сборка
|
||||||
main_data: Основные данные
|
main_data: Основные данные
|
||||||
|
|
||||||
|
human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин.
|
||||||
|
human_duration: Собрано за %{hours} ч. %{minutes} мин.
|
||||||
|
|
||||||
ownership:
|
ownership:
|
||||||
header: Принадлежность заданий
|
header: Принадлежность заданий
|
||||||
owned: Мне
|
owned: Мне
|
||||||
|
@ -84,6 +89,7 @@ ru:
|
||||||
statuses:
|
statuses:
|
||||||
build_error: ошибка сборки
|
build_error: ошибка сборки
|
||||||
build_published: опубликован
|
build_published: опубликован
|
||||||
|
rejected_publish: публикация отклонена
|
||||||
build_publish: публикуется
|
build_publish: публикуется
|
||||||
failed_publish: ошибка публикации
|
failed_publish: ошибка публикации
|
||||||
dependencies_fail: зависимости не найдены
|
dependencies_fail: зависимости не найдены
|
||||||
|
|
|
@ -4,8 +4,8 @@ en:
|
||||||
issue:
|
issue:
|
||||||
title: Name
|
title: Name
|
||||||
body: Description
|
body: Description
|
||||||
user: Assigned
|
assignee: Assigned
|
||||||
user_id: Assigned
|
assignee_id: Assigned
|
||||||
project: Project
|
project: Project
|
||||||
status: Status
|
status: Status
|
||||||
|
|
||||||
|
@ -41,10 +41,10 @@ en:
|
||||||
update_label: Update label
|
update_label: Update label
|
||||||
label_custom_color: Custom color
|
label_custom_color: Custom color
|
||||||
label_manage: Manage labels
|
label_manage: Manage labels
|
||||||
executor: Executor
|
assignee: Assignee
|
||||||
search_user: Find user...
|
search_user: Find user...
|
||||||
search_labels: Find labels...
|
search_labels: Find labels...
|
||||||
choose_user_on_left: Choose executor on the left
|
choose_user_on_left: Choose assignee on the left
|
||||||
choose_labels_on_left: Choose labels on the left
|
choose_labels_on_left: Choose labels on the left
|
||||||
at: at
|
at: at
|
||||||
cancel_button: Cancel
|
cancel_button: Cancel
|
||||||
|
|
|
@ -4,8 +4,8 @@ ru:
|
||||||
issue:
|
issue:
|
||||||
title: Название
|
title: Название
|
||||||
body: Описание
|
body: Описание
|
||||||
user: Назначена
|
assignee: Назначена
|
||||||
user_id: Назначена
|
assignee_id: Назначена
|
||||||
project: Проект
|
project: Проект
|
||||||
status: Статус
|
status: Статус
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ ru:
|
||||||
update_label: Обновить метку
|
update_label: Обновить метку
|
||||||
label_custom_color: Свой цвет
|
label_custom_color: Свой цвет
|
||||||
label_manage: Управление
|
label_manage: Управление
|
||||||
executor: Исполнитель
|
assignee: Исполнитель
|
||||||
search_user: Найти пользователя...
|
search_user: Найти пользователя...
|
||||||
search_labels: Найти метки...
|
search_labels: Найти метки...
|
||||||
choose_user_on_left: выберите исполнителя слева
|
choose_user_on_left: выберите исполнителя слева
|
||||||
|
|
|
@ -4,12 +4,16 @@ en:
|
||||||
add: Add
|
add: Add
|
||||||
edit: Settings
|
edit: Settings
|
||||||
fork_and_edit: Fork
|
fork_and_edit: Fork
|
||||||
|
fork_to: Fork to %{to}
|
||||||
|
fork_modal_header: Where do you want to fork this project?
|
||||||
|
already_exists: Project already exists
|
||||||
list: List
|
list: List
|
||||||
list_header: Projects
|
list_header: Projects
|
||||||
edit_header: Edit project
|
edit_header: Edit project
|
||||||
show: Project
|
show: Project
|
||||||
build: Build
|
build: Build
|
||||||
new_build: New build %{project_name}
|
new_build: New build %{project_name}
|
||||||
|
new_build_list: New build
|
||||||
confirm_delete: Are you sure you want to delete this project?
|
confirm_delete: Are you sure you want to delete this project?
|
||||||
new: New project
|
new: New project
|
||||||
location: Location
|
location: Location
|
||||||
|
@ -29,6 +33,11 @@ en:
|
||||||
sections: Sections
|
sections: Sections
|
||||||
has_issue_description: Tracker adds a lightweight issue management system tightly integrated with your repository.
|
has_issue_description: Tracker adds a lightweight issue management system tightly integrated with your repository.
|
||||||
has_wiki_description: Wikis are the simplest way to allow other users to contribute content. Any user can create and edit pages for documentation, examples, support or anything you wish.
|
has_wiki_description: Wikis are the simplest way to allow other users to contribute content. Any user can create and edit pages for documentation, examples, support or anything you wish.
|
||||||
|
human_average_build_time: Expected time is %{hours} h. %{minutes} min.
|
||||||
|
|
||||||
|
git_help:
|
||||||
|
cloning: Cloning the repository
|
||||||
|
remote: Add this repository as a remote to an existing local repository
|
||||||
|
|
||||||
diff_show_header: "%{files} with %{additions} and %{deletions}."
|
diff_show_header: "%{files} with %{additions} and %{deletions}."
|
||||||
about_subheader: "About project"
|
about_subheader: "About project"
|
||||||
|
|
|
@ -4,12 +4,16 @@ ru:
|
||||||
add: Добавить
|
add: Добавить
|
||||||
edit: Настройки
|
edit: Настройки
|
||||||
fork_and_edit: Клонировать
|
fork_and_edit: Клонировать
|
||||||
|
fork_to: Клонировать в %{to}
|
||||||
|
fork_modal_header: Куда Вы хотите клонировать проект?
|
||||||
|
already_exists: Проект уже существует
|
||||||
list: Список
|
list: Список
|
||||||
list_header: Проекты
|
list_header: Проекты
|
||||||
edit_header: Редактировать проект
|
edit_header: Редактировать проект
|
||||||
show: Проект
|
show: Проект
|
||||||
build: Собрать
|
build: Собрать
|
||||||
new_build: Новая сборка %{project_name}
|
new_build: Новая сборка %{project_name}
|
||||||
|
new_build_list: Новая сборка
|
||||||
confirm_delete: Вы уверены, что хотите удалить этот проект?
|
confirm_delete: Вы уверены, что хотите удалить этот проект?
|
||||||
new: Новый проект
|
new: Новый проект
|
||||||
location: Расположение
|
location: Расположение
|
||||||
|
@ -29,6 +33,7 @@ ru:
|
||||||
sections: Разделы
|
sections: Разделы
|
||||||
has_issue_description: Трэкер предоставляет лекговесный менеджер для задач по разработке Вашего проекта.
|
has_issue_description: Трэкер предоставляет лекговесный менеджер для задач по разработке Вашего проекта.
|
||||||
has_wiki_description: Wiki - это самый простой способ предоставить другим вносить свой вклад в развитие Вашего проекта. Каждый пользователь нашего сервиса может использовать Wiki для документирования, примеров, поддержки или всего другого, в чем у Вас появится необходимость.
|
has_wiki_description: Wiki - это самый простой способ предоставить другим вносить свой вклад в развитие Вашего проекта. Каждый пользователь нашего сервиса может использовать Wiki для документирования, примеров, поддержки или всего другого, в чем у Вас появится необходимость.
|
||||||
|
human_average_build_time: 'Ожидаемое время: %{hours} ч. %{minutes} мин.'
|
||||||
|
|
||||||
diff_show_header: "%{files} с %{additions} и %{deletions}."
|
diff_show_header: "%{files} с %{additions} и %{deletions}."
|
||||||
about_subheader: "О проекте"
|
about_subheader: "О проекте"
|
||||||
|
@ -45,6 +50,10 @@ ru:
|
||||||
current_commit: Текущий коммит
|
current_commit: Текущий коммит
|
||||||
files_in_project: Файлы в
|
files_in_project: Файлы в
|
||||||
|
|
||||||
|
git_help:
|
||||||
|
cloning: Клонирование этого репозитория
|
||||||
|
remote: Добавление этого репозитория как удаленного к существующему локальному репозиторию
|
||||||
|
|
||||||
flash:
|
flash:
|
||||||
project:
|
project:
|
||||||
saved: Проект успешно сохранен
|
saved: Проект успешно сохранен
|
||||||
|
|
|
@ -36,6 +36,7 @@ ru:
|
||||||
true_: Да
|
true_: Да
|
||||||
false_: Нет
|
false_: Нет
|
||||||
publish: Опубликовать
|
publish: Опубликовать
|
||||||
|
reject_publish: Отклонить
|
||||||
add: Добавить
|
add: Добавить
|
||||||
upload: Загрузить
|
upload: Загрузить
|
||||||
not_access: Нет доступа!
|
not_access: Нет доступа!
|
||||||
|
@ -44,6 +45,7 @@ ru:
|
||||||
back: Назад
|
back: Назад
|
||||||
processing: Обрабатывается...
|
processing: Обрабатывается...
|
||||||
invalid_content_type: имеет неверный тип
|
invalid_content_type: имеет неверный тип
|
||||||
|
atom_link_tag_title: Приватная лента для %{nickname} | %{app_name}
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
label: 'Настройки'
|
label: 'Настройки'
|
||||||
|
@ -64,11 +66,6 @@ ru:
|
||||||
unlock: Не получили инструкции по разблокировке?
|
unlock: Не получили инструкции по разблокировке?
|
||||||
sign_in_through: Войти через %{provider}
|
sign_in_through: Войти через %{provider}
|
||||||
|
|
||||||
downloads:
|
|
||||||
title: Статистика закачек пакетов
|
|
||||||
message: Обновляется автоматически каждые 24 часа
|
|
||||||
refresh_btn: Обновить
|
|
||||||
|
|
||||||
weekdays:
|
weekdays:
|
||||||
Monday: Понедельник
|
Monday: Понедельник
|
||||||
Tuesday: Вторник
|
Tuesday: Вторник
|
||||||
|
@ -137,9 +134,6 @@ ru:
|
||||||
|
|
||||||
exception_message: У Вас нет доступа к этой странице!
|
exception_message: У Вас нет доступа к этой странице!
|
||||||
|
|
||||||
downloads:
|
|
||||||
statistics_refreshed: Статистика обновлена
|
|
||||||
|
|
||||||
collaborators:
|
collaborators:
|
||||||
successfully_changed: Список коллабораторов успешно изменен
|
successfully_changed: Список коллабораторов успешно изменен
|
||||||
error_in_changing: Ошибка изменения списка коллабораторов
|
error_in_changing: Ошибка изменения списка коллабораторов
|
||||||
|
@ -172,7 +166,6 @@ ru:
|
||||||
arch: Arch
|
arch: Arch
|
||||||
private_user: Приватный пользователь
|
private_user: Приватный пользователь
|
||||||
product_build_list: Сборочный лист продукта
|
product_build_list: Сборочный лист продукта
|
||||||
download: Статистика
|
|
||||||
auto_build_list: Автоматическая пересборка пакетов
|
auto_build_list: Автоматическая пересборка пакетов
|
||||||
|
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -196,9 +189,3 @@ ru:
|
||||||
created_at: Создана
|
created_at: Создана
|
||||||
updated_at: Обновлена
|
updated_at: Обновлена
|
||||||
|
|
||||||
download:
|
|
||||||
name: Название
|
|
||||||
version: Версия
|
|
||||||
distro: Дистрибутив
|
|
||||||
platform: Архитектура
|
|
||||||
counter: Закачки
|
|
||||||
|
|
|
@ -4,14 +4,16 @@ app_name = ENV['APP_NAME'] || 'rosa_build'
|
||||||
Bluepill.application(app_name) do |app|
|
Bluepill.application(app_name) do |app|
|
||||||
app.uid = app.gid = 'rosa'
|
app.uid = app.gid = 'rosa'
|
||||||
app.working_dir = "/srv/#{app_name}/current"
|
app.working_dir = "/srv/#{app_name}/current"
|
||||||
app.process("delayed_job") do |process|
|
%w(fork import hook default).each do |queue|
|
||||||
|
app.process("delayed_job_#{queue}_queue") do |process|
|
||||||
process.start_grace_time = 10.seconds
|
process.start_grace_time = 10.seconds
|
||||||
process.stop_grace_time = 10.seconds
|
process.stop_grace_time = 10.seconds
|
||||||
process.restart_grace_time = 10.seconds
|
process.restart_grace_time = 10.seconds
|
||||||
|
|
||||||
process.start_command = "/usr/bin/env ruby script/delayed_job start"
|
process.start_command = "/usr/bin/env ruby script/delayed_job --queue=#{queue} -p #{queue} --pid-dir=/srv/#{app_name}/current/tmp/#{queue}_pids start"
|
||||||
process.stop_command = "/usr/bin/env ruby script/delayed_job stop"
|
process.stop_command = "/usr/bin/env ruby script/delayed_job --pid-dir=/srv/#{app_name}/current/tmp/#{queue}_pids stop"
|
||||||
process.pid_file = File.join(app.working_dir, 'tmp', 'pids', 'delayed_job.pid')
|
process.pid_file = File.join(app.working_dir, 'tmp', "#{queue}_pids", 'delayed_job.pid')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
app.process("newrelic") do |process|
|
app.process("newrelic") do |process|
|
||||||
|
|
|
@ -8,10 +8,12 @@ Rosa::Application.routes.draw do
|
||||||
get '/users/new' => 'admin/users#new', :as => :new_user
|
get '/users/new' => 'admin/users#new', :as => :new_user
|
||||||
get '/users/list' => 'admin/users#list', :as => :users_list
|
get '/users/list' => 'admin/users#list', :as => :users_list
|
||||||
post '/users/create' => 'admin/users#create', :as => :create_user
|
post '/users/create' => 'admin/users#create', :as => :create_user
|
||||||
|
constraints :id => /\d+/ do
|
||||||
get '/users/:id/edit' => 'admin/users#profile', :as => :edit_user
|
get '/users/:id/edit' => 'admin/users#profile', :as => :edit_user
|
||||||
put '/users/:id/edit' => 'admin/users#update', :as => :update_user
|
put '/users/:id/edit' => 'admin/users#update', :as => :update_user
|
||||||
delete '/users/:id/delete' => 'admin/users#destroy', :as => :delete_user
|
delete '/users/:id/delete' => 'admin/users#destroy', :as => :delete_user
|
||||||
end
|
end
|
||||||
|
end
|
||||||
devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'}
|
devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'}
|
||||||
resources :users, :only => [:show, :profile, :update] do
|
resources :users, :only => [:show, :profile, :update] do
|
||||||
collection do
|
collection do
|
||||||
|
@ -28,7 +30,7 @@ Rosa::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
get 'users/:id/settings/private' => 'users#private', :as => :user_private_settings
|
get 'users/:id/settings/private' => 'users#private', :as => :user_private_settings
|
||||||
get 'users/:id/settings/private' => 'users#private', :as => :user_private_settings
|
put 'users/:id/settings/private' => 'users#private'
|
||||||
|
|
||||||
resources :groups do
|
resources :groups do
|
||||||
get :autocomplete_group_uname, :on => :collection
|
get :autocomplete_group_uname, :on => :collection
|
||||||
|
@ -144,6 +146,8 @@ Rosa::Application.routes.draw do
|
||||||
# Raw
|
# Raw
|
||||||
get '/projects/:project_id/raw/:treeish/*path' => "git/blobs#raw", :defaults => {:treeish => :master}, :as => :raw, :format => false
|
get '/projects/:project_id/raw/:treeish/*path' => "git/blobs#raw", :defaults => {:treeish => :master}, :as => :raw, :format => false
|
||||||
|
|
||||||
|
get '/projects/:project_id/archive/:format/tree/:treeish' => "git/trees#archive", :defaults => {:treeish => :master}, :as => :archive, :format => /zip|tar/
|
||||||
|
|
||||||
# Core callbacks
|
# Core callbacks
|
||||||
match 'build_lists/publish_build', :to => "build_lists#publish_build"
|
match 'build_lists/publish_build', :to => "build_lists#publish_build"
|
||||||
match 'build_lists/status_build', :to => "build_lists#status_build"
|
match 'build_lists/status_build', :to => "build_lists#status_build"
|
||||||
|
@ -157,6 +161,7 @@ Rosa::Application.routes.draw do
|
||||||
member do
|
member do
|
||||||
put :cancel
|
put :cancel
|
||||||
put :publish
|
put :publish
|
||||||
|
put :reject_publish
|
||||||
end
|
end
|
||||||
collection { post :search }
|
collection { post :search }
|
||||||
end
|
end
|
||||||
|
@ -166,18 +171,15 @@ Rosa::Application.routes.draw do
|
||||||
|
|
||||||
resources :event_logs, :only => :index
|
resources :event_logs, :only => :index
|
||||||
|
|
||||||
match 'statistics/' => 'downloads#index', :as => :downloads
|
|
||||||
match 'statistics/refresh' => 'downloads#refresh', :as => :downloads_refresh
|
|
||||||
|
|
||||||
match '/forbidden', :to => 'pages#forbidden', :as => 'forbidden'
|
match '/forbidden', :to => 'pages#forbidden', :as => 'forbidden'
|
||||||
match '/terms-of-service', :to => 'pages#tos', :as => 'tos'
|
match '/terms-of-service', :to => 'pages#tos', :as => 'tos'
|
||||||
|
|
||||||
if APP_CONFIG['anonymous_access']
|
if APP_CONFIG['anonymous_access']
|
||||||
authenticated do
|
authenticated do
|
||||||
root :to => "activity_feeds#index"
|
get "/(.:format)" => "activity_feeds#index", :as => :root
|
||||||
end
|
end
|
||||||
root :to => 'pages#root'
|
root :to => 'pages#root'
|
||||||
else
|
else
|
||||||
root :to => "activity_feeds#index"
|
get "/(.:format)" => "activity_feeds#index", :as => :root
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,12 +7,6 @@
|
||||||
# runner "Download.parse_and_remove_nginx_log"
|
# runner "Download.parse_and_remove_nginx_log"
|
||||||
#end
|
#end
|
||||||
|
|
||||||
every 1.day, :at => '5:00' do
|
|
||||||
#rake "sudo_test:projects"
|
|
||||||
runner "Download.rotate_nginx_log"
|
|
||||||
runner "Download.parse_and_remove_nginx_log"
|
|
||||||
end
|
|
||||||
|
|
||||||
every 1.day, :at => '4:00 am' do
|
every 1.day, :at => '4:00 am' do
|
||||||
rake "import:sync:all", :output => 'log/sync.log'
|
rake "import:sync:all", :output => 'log/sync.log'
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- encoding : utf-8 -*-
|
||||||
class RemoveContainersAndRpms < ActiveRecord::Migration
|
class RemoveContainersAndRpms < ActiveRecord::Migration
|
||||||
def up
|
def up
|
||||||
drop_table :containers
|
drop_table :containers
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
# -*- encoding : utf-8 -*-
|
||||||
class CustomizePlatform < ActiveRecord::Migration
|
class CustomizePlatform < ActiveRecord::Migration
|
||||||
def self.up
|
def self.up
|
||||||
change_column_null :platforms, :name, false
|
change_column_null :platforms, :name, false
|
||||||
change_column_null :platforms, :distrib_type, false
|
#change_column_null :platforms, :distrib_type, false
|
||||||
change_column_null :platforms, :platform_type, false
|
change_column_null :platforms, :platform_type, false
|
||||||
change_column_null :platforms, :released, false
|
change_column_null :platforms, :released, false
|
||||||
change_column_null :platforms, :visibility, false
|
change_column_null :platforms, :visibility, false
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# -*- encoding : utf-8 -*-
|
||||||
|
class ClearProduct < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
remove_column :products, :build_status
|
||||||
|
remove_column :products, :build_path
|
||||||
|
remove_column :products, :system_wide
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
add_column :products, :build_status, :integer, :default => 2, :null => false
|
||||||
|
add_column :products, :build_path, :string
|
||||||
|
add_column :products, :system_wide, :boolean, :default => false
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
class ModifyDefaultQueue < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
change_column :delayed_jobs, :queue, :string, :default => 'default'
|
||||||
|
execute "UPDATE delayed_jobs SET queue = 'default'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
change_column :delayed_jobs, :queue, :string, :default => nil
|
||||||
|
execute "UPDATE delayed_jobs SET queue = null"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,6 @@
|
||||||
|
class AddStartedAtAndDurationToBuildLists < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :build_lists, :started_at, :datetime
|
||||||
|
add_column :build_lists, :duration, :integer
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
class BuildAverageTime < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :projects, :average_build_time, :integer, :null => false, :default => 0
|
||||||
|
add_column :projects, :build_count, :integer, :null => false, :default => 0
|
||||||
|
end
|
||||||
|
|
||||||
|
ActivityFeed.where(:kind => 'build_list_notification').destroy_all
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
class AddAssigneeToIssues < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
rename_column :issues, :user_id, :assignee_id
|
||||||
|
rename_column :issues, :creator_id, :user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
rename_column :issues, :user_id, :creator_id
|
||||||
|
rename_column :issues, :assignee_id, :user_id
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
class RemoveDownloads < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
drop_table :downloads
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
create_table "downloads", :force => true do |t|
|
||||||
|
t.string "name", :null => false
|
||||||
|
t.string "version"
|
||||||
|
t.string "distro"
|
||||||
|
t.string "platform"
|
||||||
|
t.integer "counter", :default => 0
|
||||||
|
t.datetime "created_at"
|
||||||
|
t.datetime "updated_at"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
class AddTokenAuthenticatableToUsers < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
add_column :users, :authentication_token, :string
|
||||||
|
add_index :users, :authentication_token
|
||||||
|
|
||||||
|
User.all.each do |user|
|
||||||
|
user.ensure_authentication_token!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
remove_column :users, :authentication_token
|
||||||
|
remove_index :users, :authentication_token
|
||||||
|
end
|
||||||
|
end
|
43
db/schema.rb
43
db/schema.rb
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended to check this file into your version control system.
|
# It's strongly recommended to check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(:version => 20120331180541) do
|
ActiveRecord::Schema.define(:version => 20120418100619) do
|
||||||
|
|
||||||
create_table "activity_feeds", :force => true do |t|
|
create_table "activity_feeds", :force => true do |t|
|
||||||
t.integer "user_id", :null => false
|
t.integer "user_id", :null => false
|
||||||
|
@ -75,6 +75,8 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.string "package_version"
|
t.string "package_version"
|
||||||
t.string "commit_hash"
|
t.string "commit_hash"
|
||||||
t.integer "priority", :default => 0, :null => false
|
t.integer "priority", :default => 0, :null => false
|
||||||
|
t.datetime "started_at"
|
||||||
|
t.integer "duration"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "build_lists", ["arch_id"], :name => "index_build_lists_on_arch_id"
|
add_index "build_lists", ["arch_id"], :name => "index_build_lists_on_arch_id"
|
||||||
|
@ -102,21 +104,11 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.string "locked_by"
|
t.string "locked_by"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "queue"
|
t.string "queue", :default => "default"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
|
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
|
||||||
|
|
||||||
create_table "downloads", :force => true do |t|
|
|
||||||
t.string "name", :null => false
|
|
||||||
t.string "version"
|
|
||||||
t.string "distro"
|
|
||||||
t.string "platform"
|
|
||||||
t.integer "counter", :default => 0
|
|
||||||
t.datetime "created_at"
|
|
||||||
t.datetime "updated_at"
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "event_logs", :force => true do |t|
|
create_table "event_logs", :force => true do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.string "user_name"
|
t.string "user_name"
|
||||||
|
@ -145,13 +137,13 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
create_table "issues", :force => true do |t|
|
create_table "issues", :force => true do |t|
|
||||||
t.integer "serial_id"
|
t.integer "serial_id"
|
||||||
t.integer "project_id"
|
t.integer "project_id"
|
||||||
t.integer "user_id"
|
t.integer "assignee_id"
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.text "body"
|
t.text "body"
|
||||||
t.string "status", :default => "open"
|
t.string "status", :default => "open"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "creator_id"
|
t.integer "user_id"
|
||||||
t.datetime "closed_at"
|
t.datetime "closed_at"
|
||||||
t.integer "closed_by"
|
t.integer "closed_by"
|
||||||
end
|
end
|
||||||
|
@ -188,7 +180,7 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.string "owner_type"
|
t.string "owner_type"
|
||||||
t.string "visibility", :default => "open", :null => false
|
t.string "visibility", :default => "open", :null => false
|
||||||
t.string "platform_type", :default => "main", :null => false
|
t.string "platform_type", :default => "main", :null => false
|
||||||
t.string "distrib_type", :null => false
|
t.string "distrib_type"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
|
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
|
||||||
|
@ -215,8 +207,6 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
create_table "products", :force => true do |t|
|
create_table "products", :force => true do |t|
|
||||||
t.string "name", :null => false
|
t.string "name", :null => false
|
||||||
t.integer "platform_id", :null => false
|
t.integer "platform_id", :null => false
|
||||||
t.integer "build_status", :default => 2, :null => false
|
|
||||||
t.string "build_path"
|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.text "build_script"
|
t.text "build_script"
|
||||||
|
@ -227,7 +217,6 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.string "tar_content_type"
|
t.string "tar_content_type"
|
||||||
t.integer "tar_file_size"
|
t.integer "tar_file_size"
|
||||||
t.datetime "tar_updated_at"
|
t.datetime "tar_updated_at"
|
||||||
t.boolean "system_wide", :default => false
|
|
||||||
t.text "cron_tab"
|
t.text "cron_tab"
|
||||||
t.boolean "use_cron", :default => false
|
t.boolean "use_cron", :default => false
|
||||||
t.text "description"
|
t.text "description"
|
||||||
|
@ -262,25 +251,25 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.string "ancestry"
|
t.string "ancestry"
|
||||||
t.boolean "has_issues", :default => true
|
t.boolean "has_issues", :default => true
|
||||||
|
t.boolean "has_wiki", :default => false
|
||||||
t.string "srpm_file_name"
|
t.string "srpm_file_name"
|
||||||
t.string "srpm_content_type"
|
t.string "srpm_content_type"
|
||||||
t.integer "srpm_file_size"
|
t.integer "srpm_file_size"
|
||||||
t.datetime "srpm_updated_at"
|
t.datetime "srpm_updated_at"
|
||||||
t.boolean "has_wiki", :default => false
|
|
||||||
t.string "default_branch", :default => "master"
|
t.string "default_branch", :default => "master"
|
||||||
t.boolean "is_rpm", :default => true
|
t.boolean "is_rpm", :default => true
|
||||||
|
t.integer "average_build_time", :default => 0, :null => false
|
||||||
|
t.integer "build_count", :default => 0, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false
|
|
||||||
|
|
||||||
create_table "register_requests", :force => true do |t|
|
create_table "register_requests", :force => true do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.string "email"
|
t.string "email"
|
||||||
t.string "token"
|
t.string "token"
|
||||||
t.boolean "approved", :default => false
|
t.boolean "approved", :default => false
|
||||||
t.boolean "rejected", :default => false
|
t.boolean "rejected", :default => false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at", :null => false
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at", :null => false
|
||||||
t.string "interest"
|
t.string "interest"
|
||||||
t.text "more"
|
t.text "more"
|
||||||
end
|
end
|
||||||
|
@ -342,6 +331,9 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.string "uname"
|
t.string "uname"
|
||||||
t.string "role"
|
t.string "role"
|
||||||
t.string "language", :default => "en"
|
t.string "language", :default => "en"
|
||||||
|
t.string "confirmation_token"
|
||||||
|
t.datetime "confirmed_at"
|
||||||
|
t.datetime "confirmation_sent_at"
|
||||||
t.integer "own_projects_count", :default => 0, :null => false
|
t.integer "own_projects_count", :default => 0, :null => false
|
||||||
t.datetime "reset_password_sent_at"
|
t.datetime "reset_password_sent_at"
|
||||||
t.text "professional_experience"
|
t.text "professional_experience"
|
||||||
|
@ -355,11 +347,10 @@ ActiveRecord::Schema.define(:version => 20120331180541) do
|
||||||
t.integer "failed_attempts", :default => 0
|
t.integer "failed_attempts", :default => 0
|
||||||
t.string "unlock_token"
|
t.string "unlock_token"
|
||||||
t.datetime "locked_at"
|
t.datetime "locked_at"
|
||||||
t.string "confirmation_token"
|
t.string "authentication_token"
|
||||||
t.datetime "confirmed_at"
|
|
||||||
t.datetime "confirmation_sent_at"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token"
|
||||||
add_index "users", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
|
add_index "users", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
|
||||||
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
|
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
|
||||||
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
|
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
|
||||||
|
|
|
@ -1,323 +0,0 @@
|
||||||
КРАТКОЕ ОПИСАНИЕ ACL
|
|
||||||
====================
|
|
||||||
|
|
||||||
Предназначение
|
|
||||||
--------------
|
|
||||||
|
|
||||||
ACL предназначена для контроля прав пользователя на выполнение действий в
|
|
||||||
системе и доступа к моделям по областям видимости.
|
|
||||||
|
|
||||||
Решаемые задачи
|
|
||||||
---------------
|
|
||||||
|
|
||||||
* Проверка наличия у пользователя прав для выполнения метода контроллера;
|
|
||||||
* Прозрачная фильтрация моделей для исключения невидимых для пользователя
|
|
||||||
записей.
|
|
||||||
|
|
||||||
Возможности
|
|
||||||
-----------
|
|
||||||
|
|
||||||
* Неограниченное количество моделей, над которыми могут выполняться
|
|
||||||
действия (`target`);
|
|
||||||
* Неограниченное количество моделей, которые могут выполнять действия над
|
|
||||||
другими (`acter`);
|
|
||||||
* Геренатор прав основывающийся на структуре приложения (см. далее);
|
|
||||||
* Неограниченное количество ролей, которые могут назначаться для `acter` и
|
|
||||||
содержать любую комбинацию прав и доступных видимостей;
|
|
||||||
* Объединение прав `acter`-ов на глубину одной модели (см. далее);
|
|
||||||
* Разграничение назначения ролей по классам (не завершено, на данный
|
|
||||||
момент не критично);
|
|
||||||
* Разграничение ролей на глобальные и локальные (см. далее).
|
|
||||||
|
|
||||||
Типы моделей, с которыми взаимодействует ACL
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
* __ActerModel__ -- модель, которая может выполнять действия, разрешенные
|
|
||||||
ролями, над другими моделями;
|
|
||||||
* __TargetTarget__ -- модель, над которой могут выполняться действия,
|
|
||||||
разрешенные ролями.
|
|
||||||
|
|
||||||
__ActerModel__ может иметь глобальную роль, которая определяет возможность
|
|
||||||
выполнения действий без привязки к конкретному экземпляру __TargetModel__ и
|
|
||||||
неограниченное количество прав по отношению к конкретному экземпляру
|
|
||||||
__TargetModel__.
|
|
||||||
|
|
||||||
__TODO__: *Реализовать дополнение необходимым функционалом моделей, выбранных
|
|
||||||
в качестве __ActerModel__ или __TargetModel__ при декларировании их роли в
|
|
||||||
системе*
|
|
||||||
|
|
||||||
Схема взаимодействия объектов ACL
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
Функционал ACL реализуется путем взаимодействия моделей `Right, Role, Relation`,
|
|
||||||
реализующих основной функционал и особых моделей проекта, обозначенных на схеме
|
|
||||||
как `ActerModel` и `TargetModel`.
|
|
||||||
|
|
||||||
Экземпляры __ActerModel__ и __TargetModel__ связываются посредством модели
|
|
||||||
`Relation`, через которую экземпляр __ActerModel__ получает неограниченное
|
|
||||||
количество ролей по отношению к экземпляру __TargetModel__.
|
|
||||||
|
|
||||||
### Схема связей моделей:
|
|
||||||
|
|
||||||
--------------
|
|
||||||
| ActerModel |
|
|
||||||
/ --------------
|
|
||||||
--------- -------- |
|
|
||||||
| Right | | Role | V
|
|
||||||
--------- -------- ------------
|
|
||||||
... <= ... <= | Relation |
|
|
||||||
--------- -------- ------------
|
|
||||||
| Right | | Role | |
|
|
||||||
--------- -------- V
|
|
||||||
---------------
|
|
||||||
| TargetModel |
|
|
||||||
---------------
|
|
||||||
|
|
||||||
* Обозначения: <= -- Связь с несколькими моделями
|
|
||||||
<-,/,| -- Связь с одной моделью
|
|
||||||
|
|
||||||
|
|
||||||
Генератор прав
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Генератор ролей является Rake-task-ом и запускается командой
|
|
||||||
`rake rights:generate`.
|
|
||||||
|
|
||||||
Желательно запускать после добавления нового метода в контроллер для того,
|
|
||||||
чтобы на этот метод в системе появилось право.
|
|
||||||
|
|
||||||
Загрузка ролей из дампа
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Загрузку ролей из заранее подготовленного дампа можно произвести двумя
|
|
||||||
способами:
|
|
||||||
|
|
||||||
* В консоли, используя Rake task `rake roles:load`, который загрузит в базу
|
|
||||||
роли, описанные в `config/roles.yml`
|
|
||||||
* Через Web-интерфейс, на странице `/roles`, если у пользователя есть
|
|
||||||
соответствующие права. Для загрузки через Web-интерфейс необходимо выбрать
|
|
||||||
файл в поле выбора вверху страницы и нажать __Загрузить__.
|
|
||||||
|
|
||||||
Получение дампа ролей
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Дамп ролей может получить пользователь, имеющий на это права, зайдя на страницу
|
|
||||||
`roles` и нажав кнопку `Скачать в YML`.
|
|
||||||
|
|
||||||
Задание областей видимости моделей
|
|
||||||
----------------------------------
|
|
||||||
*Этот функционал скорее всего будет изменяться*
|
|
||||||
|
|
||||||
Если модель должна иметь несколько областей видимости, нужно сделать следующее:
|
|
||||||
|
|
||||||
* Добавить в модель константу `VISIBILITIES`, в которой задать названия областей
|
|
||||||
видимости;
|
|
||||||
* Добавить к таблице моделей поле `visibility:text`;
|
|
||||||
* Добавить `attr_accessible :visibility` в модель;
|
|
||||||
* Создать `scope :by_visibility`, принимающий аргументом массив областей
|
|
||||||
видимости.
|
|
||||||
|
|
||||||
После выполнения этих действий на странице редактирования роли появится поле
|
|
||||||
выбора областей видимости для этой модели.
|
|
||||||
|
|
||||||
### Пример:
|
|
||||||
|
|
||||||
model VisibilitiesExample < ActiveRecord::Base
|
|
||||||
VISIBILITIES = ['open', 'hidden', 'open_for_admins']
|
|
||||||
attr_accessible :visibility
|
|
||||||
|
|
||||||
scope :by_visibility, lambda {|v| {:conditions => ['visibility in (?)', v]}}
|
|
||||||
end
|
|
||||||
|
|
||||||
*Назначение методов описано в API*
|
|
||||||
|
|
||||||
Задание типа модели
|
|
||||||
-------------------
|
|
||||||
*Этот функционал скорее всего будет изменяться*
|
|
||||||
|
|
||||||
Если модель должна иметь возможность быть связанной с другими с использованием
|
|
||||||
ролей, необходимо произвести следующие действия:
|
|
||||||
|
|
||||||
* Добавить в модель декларацию `relationable`, с аргументом `:as`, который
|
|
||||||
может принимать заначения из `[:object, :target]`. Если модель будет
|
|
||||||
__acter__-ом, передается `:object`, иначе `:target`
|
|
||||||
Пример: `relationable :as => :object`
|
|
||||||
* Добавить в модель связь `belongs_to :global_role, :class_name => 'Role'`
|
|
||||||
* Добавить в модель связь с моделью `Relation`
|
|
||||||
* Если модель -- __acter__ и она должна использовать как свои роли, так и
|
|
||||||
роли из другой модели, необходимо добавить декларацию `inherit_rights_from`
|
|
||||||
которой аргументом присвоить имя/имена связей с моделями, из которых должны
|
|
||||||
браться роли.
|
|
||||||
|
|
||||||
### Примеры:
|
|
||||||
|
|
||||||
* Модель, являющаяся __acter__:
|
|
||||||
|
|
||||||
class ActerModel < ActiveRecord::Base
|
|
||||||
relationable :as => :object
|
|
||||||
|
|
||||||
belongs_to :global_role, :class_name => 'Role'
|
|
||||||
has_many :targets, :as => :object, :class_name => 'Relation'
|
|
||||||
end
|
|
||||||
* Модель, являющаяся __acter__ и наследующая права другой модели:
|
|
||||||
|
|
||||||
class ActerWithInheritableRolesModel < ActiveRecord::Base
|
|
||||||
relationable :as => :object
|
|
||||||
ingerit_rights_from :another_acter_model
|
|
||||||
|
|
||||||
has_many :another_acters_models
|
|
||||||
|
|
||||||
belongs_to :global_role, :class_name => 'Role'
|
|
||||||
has_many :targets, :as => :object, :class_name => 'Relation'
|
|
||||||
end
|
|
||||||
* Модель, являющаяся __target__:
|
|
||||||
|
|
||||||
class TargetModel < ActiveRecord::Base
|
|
||||||
relationable :as => :target
|
|
||||||
|
|
||||||
has_many :objects, :as => :target, :class_name => 'Relation'
|
|
||||||
end
|
|
||||||
* Модель, являющаяся и __acter__, и __target__:
|
|
||||||
|
|
||||||
class ActerAndTargetModel < ActiveRecord::Base
|
|
||||||
relationable :as => :object
|
|
||||||
relationable :as => :target
|
|
||||||
|
|
||||||
belongs_to :global_role, :class_name => 'Role'
|
|
||||||
has_many :targets, :as => :object, :class_name => 'Relation'
|
|
||||||
has_many :objects, :as => :target, :class_name => 'Relation'
|
|
||||||
end
|
|
||||||
|
|
||||||
*Назначение методов описано в API*
|
|
||||||
|
|
||||||
Использование ACL в контроллере
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Если необходимо ограничить доступ ко всем методам контроллера по глобальной
|
|
||||||
роли пользователя вне зависимости от текущей модели, необходимо установить
|
|
||||||
`before_filter :check_global_rights`.
|
|
||||||
В случае, если у пользователя нет прав для выполнения текущего действия, он
|
|
||||||
будет переотправлен на предыдущую страницу.
|
|
||||||
|
|
||||||
Если необходимо проверить, может ли пользователь выполнить конкретное действие,
|
|
||||||
необходимо в начале этого метода вызвать метод `can_perform?`. Если методу
|
|
||||||
передан параметр, являющийся экземпляром класса __TargetModel__, метод возвратит
|
|
||||||
`true`, если одна или несколько ролей пользователя над этой моделью позволяет
|
|
||||||
ему выполнить может выполнить действие и `false` в противном случае. Если
|
|
||||||
необязательный параметр опущен, или в качестве параметра передано `:system`,
|
|
||||||
учитываются только глобальные роли.
|
|
||||||
|
|
||||||
### Примеры
|
|
||||||
|
|
||||||
* Контроллер, некоторые методы которого доступны для всех:
|
|
||||||
|
|
||||||
class StuffController < ApplicationController
|
|
||||||
def index # доступ у всех
|
|
||||||
...
|
|
||||||
end
|
|
||||||
|
|
||||||
def show # 'Что-то полезное' выполнится только у тех, чьи роли над
|
|
||||||
# @data позволяют выполнить конкретное действие.
|
|
||||||
@data = Stuff.find(params[:id])
|
|
||||||
if can_perform? @data
|
|
||||||
#что-то полезное
|
|
||||||
else
|
|
||||||
# сообщаем пользователю, что он не может выполнить действие
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create # 'Что-то полезное' выполнится только у тех, чьи
|
|
||||||
# глобальные роли позволяют выполнить метод
|
|
||||||
if can_perform?
|
|
||||||
# что-то полезное
|
|
||||||
else
|
|
||||||
# сообщаем пользователю, что он не может выполнить действие
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
* Контроллер, доступ к методам которого возможен только при наличии необходимых
|
|
||||||
прав в глобальных ролях:
|
|
||||||
|
|
||||||
class StuffController < ApplicationController
|
|
||||||
before_filter :check_global_rights # разрешаем доступ только тем,
|
|
||||||
# чьи роли это позволяют.
|
|
||||||
|
|
||||||
def index # доступ только у тех, кому это позволяет глобальная роль
|
|
||||||
...
|
|
||||||
end
|
|
||||||
|
|
||||||
def show # 'Что-то полезное' выполнится только у тех, чьи роли
|
|
||||||
# над @data это позволяют
|
|
||||||
@data = Stuff.find(params[:id])
|
|
||||||
if can_perform? @data
|
|
||||||
#что-то полезное
|
|
||||||
else
|
|
||||||
# сообщаем пользователю, что он не может выполнить действие
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Использование ACL во view
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Используется метод `can_perform?` модели, для которой нужно проверить права
|
|
||||||
доступа. Обычно этой моделью является `current_user`.
|
|
||||||
|
|
||||||
### Примеры:
|
|
||||||
|
|
||||||
* Проверка на возможность выполнения глобального действия:
|
|
||||||
|
|
||||||
-if current_user.can_perform?('some_controller', 'some_aciton')
|
|
||||||
%a{:href => controller_action_path}= Some description
|
|
||||||
|
|
||||||
* Проверка на возможность выполнения действия над текущей моделью:
|
|
||||||
|
|
||||||
-if current_user.can_perform?('some_controller', 'some_aciton', @data)
|
|
||||||
%a{:href => controller_action_path(@data)}= Some description
|
|
||||||
|
|
||||||
API для работы с ACL
|
|
||||||
--------------------
|
|
||||||
*Этот функционал скорее всего будет изменяться*
|
|
||||||
|
|
||||||
### Методы потомков `ActiveRecord::Base`
|
|
||||||
|
|
||||||
* Методы классов:
|
|
||||||
- `relationable` -- устанавливает, кем является модель (acter/target)
|
|
||||||
- `relationable?` -- может ли иметь связь с ролью/ролями с другими
|
|
||||||
- `relation_acters` -- список моделей, которые могут иметь роли
|
|
||||||
по отношению к другим (след. метод)
|
|
||||||
- `relation_targets` -- список моделей, над которыми могут совершаться
|
|
||||||
действия
|
|
||||||
- `relation_acter? (model)`, `relation_target? (model)` -- является ли
|
|
||||||
тем или другим
|
|
||||||
- `inherit_rights_from (:relation_name | [:relation_names])` -- права из
|
|
||||||
каких связанных моделей наследовать
|
|
||||||
- `visible_to (model)` -- все видимые для модели записи, может
|
|
||||||
включаться в цепочку (например, для paginate)
|
|
||||||
|
|
||||||
* Методы инстансов:
|
|
||||||
- `add_role_to(acter, role)` -- привязать acter-а с ролью к текущей записи
|
|
||||||
- `add_role_on(target, role)` -- привязать текущую модель с ролью
|
|
||||||
- `roles_to(object)` -- если object == :system, возвращает глобальные роли
|
|
||||||
текущей записи, если передана запись -- то роли текущей модели над записью
|
|
||||||
- `rights_to(object)` -- аргументы те же, но возвращается список прав,
|
|
||||||
собранный из всех ролей
|
|
||||||
- `right_to(controller_name, action)` -- возвращает запись с правом на
|
|
||||||
выполнение действия action в контроллере c именем `controller_name`
|
|
||||||
- `can_perform? (controller_name, action, target = :system)` -- показывает,
|
|
||||||
может ли текущая модель выполнить действие контроллера над целью
|
|
||||||
|
|
||||||
### Методы потомков `ActiveController::Base`
|
|
||||||
*Возможно, будут вынесены в хелпер для универсализации системы*
|
|
||||||
|
|
||||||
- `can_perform? (target = :system)` -- может ли `current_user` выполнить
|
|
||||||
текущее действие
|
|
||||||
- `check_global_access` -- делает редирект назад или на главную, если
|
|
||||||
пользователь вообще не может совершить текущее действие
|
|
||||||
- `roles_to(object)` -- возвращает список ролей `current_user`-а по отношению
|
|
||||||
к объекту
|
|
||||||
- `rights_to(object)` -- возвращает список прав `current_user`-а по отношению
|
|
||||||
к объекту
|
|
||||||
|
|
|
@ -23,9 +23,12 @@
|
||||||
<div class="middle">
|
<div class="middle">
|
||||||
<!--Main menu-->
|
<!--Main menu-->
|
||||||
<menu>
|
<menu>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="#"><img src="pics/logo-mini.png" alt="Главная" /></a>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="first">Главная</a>
|
<a href="#">Главная</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="active">Проекты</a>
|
<a href="#" class="active">Проекты</a>
|
||||||
|
@ -43,9 +46,7 @@
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="logo">
|
|
||||||
<img src="pics/logo-mini.png" alt="logo" />
|
|
||||||
</div>
|
|
||||||
</menu>
|
</menu>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
|
|
|
@ -22,9 +22,12 @@
|
||||||
<div class="middle">
|
<div class="middle">
|
||||||
<!--Main menu-->
|
<!--Main menu-->
|
||||||
<menu>
|
<menu>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="#"><img src="pics/logo-mini.png" alt="Главная" /></a>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="first">Главная</a>
|
<a href="#">Главная</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="active">Проекты</a>
|
<a href="#" class="active">Проекты</a>
|
||||||
|
@ -42,9 +45,6 @@
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="logo">
|
|
||||||
<img src="pics/logo-mini.png" alt="logo" />
|
|
||||||
</div>
|
|
||||||
</menu>
|
</menu>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
|
|
|
@ -24,9 +24,12 @@
|
||||||
<div class="middle">
|
<div class="middle">
|
||||||
<!--Main menu-->
|
<!--Main menu-->
|
||||||
<menu>
|
<menu>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="#"><img src="pics/logo-mini.png" alt="Главная" /></a>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="first">Главная</a>
|
<a href="#">Главная</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="active">Проекты</a>
|
<a href="#" class="active">Проекты</a>
|
||||||
|
@ -44,9 +47,7 @@
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="logo">
|
|
||||||
<img src="pics/logo-mini.png" alt="logo" />
|
|
||||||
</div>
|
|
||||||
</menu>
|
</menu>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
<div class="middle">
|
<div class="middle">
|
||||||
<!--Main menu-->
|
<!--Main menu-->
|
||||||
<menu>
|
<menu>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="#"><img src="pics/logo-mini.png" alt="Главная" /></a>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="first">Главная</a>
|
<a href="#">Главная</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="active">Проекты</a>
|
<a href="#" class="active">Проекты</a>
|
||||||
|
@ -38,9 +41,7 @@
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="logo">
|
|
||||||
<img src="pics/logo-mini.png" alt="logo" />
|
|
||||||
</div>
|
|
||||||
</menu>
|
</menu>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
<div class="middle">
|
<div class="middle">
|
||||||
<!--Main menu-->
|
<!--Main menu-->
|
||||||
<menu>
|
<menu>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="#"><img src="pics/logo-mini.png" alt="Главная" /></a>
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="first">Главная</a>
|
<a href="#">Главная</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="active">Проекты</a>
|
<a href="#" class="active">Проекты</a>
|
||||||
|
@ -40,9 +43,6 @@
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="logo">
|
|
||||||
<img src="pics/logo-mini.png" alt="logo" />
|
|
||||||
</div>
|
|
||||||
</menu>
|
</menu>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<!--Search-->
|
<!--Search-->
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue