updated logger on build product page
This commit is contained in:
parent
ef967e97ae
commit
8f9cd0ff8a
|
@ -0,0 +1,111 @@
|
||||||
|
function initLogWrapper() {
|
||||||
|
var $wrapper = $('div.log-wrapper');
|
||||||
|
var $logBody = $wrapper.children('div.log-body').first();
|
||||||
|
var $logCont = $logBody.children('.log').first();
|
||||||
|
|
||||||
|
var logUrl = $logCont.data('url');
|
||||||
|
var $logHead = $wrapper.children('div.log-header').first();
|
||||||
|
|
||||||
|
var $trigger = $logHead.children('span').first();
|
||||||
|
var $autoload = $('#autoreload');
|
||||||
|
|
||||||
|
var state = $logBody.is(':visible');
|
||||||
|
var t = null; // timer
|
||||||
|
var first_open = true;
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
$trigger.removeClass('closed');
|
||||||
|
$wrapper.removeClass('inactive')
|
||||||
|
.addClass('active');
|
||||||
|
} else {
|
||||||
|
$trigger.addClass('closed');
|
||||||
|
$logBody.addClass('hidden');
|
||||||
|
$wrapper.removeClass('active')
|
||||||
|
.addClass('inactive');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLineHeight(element){
|
||||||
|
var temp = document.createElement(element.nodeName);
|
||||||
|
temp.setAttribute("style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize);
|
||||||
|
temp.innerHTML = "test";
|
||||||
|
temp = element.parentNode.appendChild(temp);
|
||||||
|
var ret = temp.clientHeight;
|
||||||
|
temp.parentNode.removeChild(temp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loadLog = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: logUrl,
|
||||||
|
type: "GET",
|
||||||
|
dataType: 'json',
|
||||||
|
data: $logCont.data(),
|
||||||
|
beforeSend: function( xhr ) {
|
||||||
|
var token = $('meta[name="csrf-token"]').attr('content');
|
||||||
|
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
||||||
|
},
|
||||||
|
success: function(data, textStatus, jqXHR) {
|
||||||
|
var l = $logCont[0];
|
||||||
|
var vScroll = l.scrollTop;
|
||||||
|
var hScroll = l.scrollLeft;
|
||||||
|
var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l);
|
||||||
|
|
||||||
|
$logCont.text(data.log);
|
||||||
|
|
||||||
|
$logCont.scrollLeft(hScroll);
|
||||||
|
$logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll);
|
||||||
|
first_open = false;
|
||||||
|
if (!data.building) $autoload.attr({'checked': false}).trigger('change');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var reloadChange = function() {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
first_open = true;
|
||||||
|
loadLog();
|
||||||
|
$logCont.scrollTop($logCont[0].scrollHeight - $logCont[0].clientHeight);
|
||||||
|
t = setInterval(function() {
|
||||||
|
loadLog();
|
||||||
|
}, $('#reload_interval').val());
|
||||||
|
} else {
|
||||||
|
clearInterval(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var toggleHandler = function() {
|
||||||
|
state = !state;
|
||||||
|
// if log opened
|
||||||
|
if (state) {
|
||||||
|
if ($autoload.is(':checked')) {
|
||||||
|
$autoload.trigger('change');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearInterval(t);
|
||||||
|
}
|
||||||
|
$logBody.slideToggle('slow')
|
||||||
|
.toggleClass('hidden');
|
||||||
|
$logHead.toggleClass('active inactive');
|
||||||
|
$trigger.toggleClass('closed');
|
||||||
|
|
||||||
|
window.location.href = $('a#log_anchor').attr('href');
|
||||||
|
}
|
||||||
|
|
||||||
|
$wrapper.on('click', '.log-header > span', toggleHandler);
|
||||||
|
$autoload.on('change', reloadChange);
|
||||||
|
|
||||||
|
$('#word_wrap').on('change', function() {
|
||||||
|
$logCont.attr({'wrap': ($(this).is(':checked')) ? 'soft' : 'off'});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#reload_interval').on('change', function() {
|
||||||
|
clearInterval(t);
|
||||||
|
if ($autoload.is(':checked')) {
|
||||||
|
t = setInterval($(this).val());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#load_lines').on('change', function() {
|
||||||
|
$logCont.data('load_lines', $(this).val());
|
||||||
|
}).trigger('change');
|
||||||
|
loadLog();
|
||||||
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
class Platforms::ProductBuildListsController < Platforms::BaseController
|
class Platforms::ProductBuildListsController < Platforms::BaseController
|
||||||
before_filter :authenticate_user!, :except => [:status_build]
|
before_filter :authenticate_user!, :except => [:status_build]
|
||||||
skip_before_filter :authenticate_user!, :only => [:index] if APP_CONFIG['anonymous_access']
|
skip_before_filter :authenticate_user!, :only => [:index] if APP_CONFIG['anonymous_access']
|
||||||
load_and_authorize_resource :platform, :only => [:create, :destroy, :new, :show]
|
load_and_authorize_resource :platform, :except => [:index, :status_build]
|
||||||
load_and_authorize_resource :product, :through => :platform, :only => [:create, :destroy, :new, :show]
|
load_and_authorize_resource :product, :through => :platform, :except => [:index, :status_build]
|
||||||
load_and_authorize_resource :product_build_list, :through => :product, :only => [:create, :destroy, :new, :show]
|
load_and_authorize_resource :product_build_list, :through => :product, :except => [:index, :status_build]
|
||||||
load_and_authorize_resource :only => [:index]
|
load_and_authorize_resource :only => [:index]
|
||||||
|
|
||||||
before_filter :authenticate_product_builder!, :only => [:status_build]
|
before_filter :authenticate_product_builder!, :only => [:status_build]
|
||||||
|
@ -22,7 +22,17 @@ class Platforms::ProductBuildListsController < Platforms::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@logs = JSON.parse(Resque.redis.get("abfworker::iso-worker-#{@product_build_list.id}") || '[]')
|
end
|
||||||
|
|
||||||
|
def log
|
||||||
|
@log = Resque.redis.get("abfworker::iso-worker-#{@product_build_list.id}") || ''
|
||||||
|
respond_to do |format|
|
||||||
|
format.json {
|
||||||
|
render :json => {
|
||||||
|
:log => @log,
|
||||||
|
:building => @product_build_list.build_started? }
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
|
@ -40,6 +40,10 @@ class ProductBuildList < ActiveRecord::Base
|
||||||
before_destroy :can_destroy?
|
before_destroy :can_destroy?
|
||||||
after_destroy :xml_delete_iso_container
|
after_destroy :xml_delete_iso_container
|
||||||
|
|
||||||
|
def build_started?
|
||||||
|
status == BUILD_STARTED
|
||||||
|
end
|
||||||
|
|
||||||
def container_path
|
def container_path
|
||||||
"/downloads/#{product.platform.name}/product/#{id}/"
|
"/downloads/#{product.platform.name}/product/#{id}/"
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,12 +8,6 @@
|
||||||
%h3= t("layout.product_build_lists.main_data")
|
%h3= t("layout.product_build_lists.main_data")
|
||||||
.both
|
.both
|
||||||
|
|
||||||
%div.reloader
|
|
||||||
= label_tag :autoreload do
|
|
||||||
= check_box_tag :autoreload, true, true
|
|
||||||
= t("layout.autoreload_page")
|
|
||||||
.both
|
|
||||||
|
|
||||||
.leftlist= t("activerecord.attributes.product_build_list.id")
|
.leftlist= t("activerecord.attributes.product_build_list.id")
|
||||||
.rightlist= pbl.id
|
.rightlist= pbl.id
|
||||||
.both
|
.both
|
||||||
|
@ -46,20 +40,8 @@
|
||||||
.rightlist= l(pbl.updated_at, :format => :long)
|
.rightlist= l(pbl.updated_at, :format => :long)
|
||||||
.both
|
.both
|
||||||
|
|
||||||
- if @logs.present?
|
- if pbl.build_started?
|
||||||
%h3= t("layout.product_build_lists.logs")
|
= render 'shared/log', { :build_started => true, :get_log_path => log_platform_product_product_build_list_path(pbl.product.platform, pbl.product, pbl) }
|
||||||
%table#logs.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"}
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th.lpadding16= '#'
|
|
||||||
%th
|
|
||||||
%tbody
|
|
||||||
- @logs.each do |item|
|
|
||||||
%tr
|
|
||||||
%td= item[0]
|
|
||||||
%td= item[1]
|
|
||||||
|
|
||||||
.both
|
|
||||||
|
|
||||||
%h3= t("layout.product_build_lists.results")
|
%h3= t("layout.product_build_lists.results")
|
||||||
- unless pbl.results.present?
|
- unless pbl.results.present?
|
||||||
|
@ -82,18 +64,4 @@
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){
|
$(function(){
|
||||||
$('article .all').addClass('bigpadding');
|
$('article .all').addClass('bigpadding');
|
||||||
|
|
||||||
var reloadChange = function() {
|
|
||||||
if ($(this).is(':checked')) {
|
|
||||||
//reload page every 1 minute
|
|
||||||
t = setTimeout(function() {
|
|
||||||
window.location.reload();
|
|
||||||
}, 10000);
|
|
||||||
} else {
|
|
||||||
clearTimeout(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#autoreload').on('change', reloadChange)
|
|
||||||
.trigger('change');
|
|
||||||
});
|
});
|
|
@ -1,148 +0,0 @@
|
||||||
.hr
|
|
||||||
%a{:name => 'log'}
|
|
||||||
.log-wrapper
|
|
||||||
.log-header
|
|
||||||
.text-wrap
|
|
||||||
= link_to({:anchor => :log}, {:id => 'log_anchor'}) do
|
|
||||||
%h3= t("layout.build_lists.log.build_log")
|
|
||||||
%span
|
|
||||||
.both
|
|
||||||
.log-body.hidden
|
|
||||||
.reloader
|
|
||||||
%table.options
|
|
||||||
%tr.top
|
|
||||||
%td.first
|
|
||||||
= label_tag :word_wrap do
|
|
||||||
= check_box_tag :word_wrap
|
|
||||||
= t("layout.word_wrap")
|
|
||||||
%td.last{ :class => @build_list.build_started? ? nil : :hidden }
|
|
||||||
= label_tag :autoreload do
|
|
||||||
= check_box_tag :autoreload, true, @build_list.build_started?
|
|
||||||
= t("layout.build_lists.log.autoreload")
|
|
||||||
= select_tag :reload_interval, log_reload_time_options
|
|
||||||
%tr.bottom
|
|
||||||
%td.first
|
|
||||||
= link_to t("layout.build_lists.log.download"), build_list_log_url(:build), :id => :log_url
|
|
||||||
%td.last{ :class => @build_list.build_started? ? nil : :hidden }
|
|
||||||
= label_tag :load_lines do
|
|
||||||
= raw t("layout.build_lists.log.load_lines", :count => select_tag(:load_lines, log_reload_lines_options))
|
|
||||||
.both
|
|
||||||
%textarea.log{ :readonly => :readonly, :wrap => 'off',
|
|
||||||
:data => { :url => log_build_list_path(@build_list), :log_type => :build } }
|
|
||||||
= t("layout.build_lists.log.not_available")
|
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function() {
|
|
||||||
(function() {
|
|
||||||
var $wrapper = $('div.log-wrapper');
|
|
||||||
var $logBody = $wrapper.children('div.log-body').first();
|
|
||||||
var $logCont = $logBody.children('.log').first();
|
|
||||||
|
|
||||||
var logUrl = $logCont.data('url');
|
|
||||||
var $logHead = $wrapper.children('div.log-header').first();
|
|
||||||
|
|
||||||
var $trigger = $logHead.children('span').first();
|
|
||||||
var $autoload = $('#autoreload');
|
|
||||||
|
|
||||||
var state = $logBody.is(':visible');
|
|
||||||
var t = null; // timer
|
|
||||||
var first_open = true;
|
|
||||||
|
|
||||||
if (state) {
|
|
||||||
$trigger.removeClass('closed');
|
|
||||||
$wrapper.removeClass('inactive')
|
|
||||||
.addClass('active');
|
|
||||||
} else {
|
|
||||||
$trigger.addClass('closed');
|
|
||||||
$logBody.addClass('hidden');
|
|
||||||
$wrapper.removeClass('active')
|
|
||||||
.addClass('inactive');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLineHeight(element){
|
|
||||||
var temp = document.createElement(element.nodeName);
|
|
||||||
temp.setAttribute("style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize);
|
|
||||||
temp.innerHTML = "test";
|
|
||||||
temp = element.parentNode.appendChild(temp);
|
|
||||||
var ret = temp.clientHeight;
|
|
||||||
temp.parentNode.removeChild(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
var loadLog = function() {
|
|
||||||
$.ajax({
|
|
||||||
url: logUrl,
|
|
||||||
type: "GET",
|
|
||||||
dataType: 'json',
|
|
||||||
data: $logCont.data(),
|
|
||||||
beforeSend: function( xhr ) {
|
|
||||||
var token = $('meta[name="csrf-token"]').attr('content');
|
|
||||||
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
|
||||||
},
|
|
||||||
success: function(data, textStatus, jqXHR) {
|
|
||||||
var l = $logCont[0];
|
|
||||||
var vScroll = l.scrollTop;
|
|
||||||
var hScroll = l.scrollLeft;
|
|
||||||
var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l);
|
|
||||||
|
|
||||||
$logCont.text(data.log);
|
|
||||||
|
|
||||||
$logCont.scrollLeft(hScroll);
|
|
||||||
$logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll);
|
|
||||||
first_open = false;
|
|
||||||
if (!data.building) $autoload.attr({'checked': false}).trigger('change');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var reloadChange = function() {
|
|
||||||
if ($(this).is(':checked')) {
|
|
||||||
first_open = true;
|
|
||||||
loadLog();
|
|
||||||
$logCont.scrollTop($logCont[0].scrollHeight - $logCont[0].clientHeight);
|
|
||||||
t = setInterval(function() {
|
|
||||||
loadLog();
|
|
||||||
}, $('#reload_interval').val());
|
|
||||||
} else {
|
|
||||||
clearInterval(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var toggleHandler = function() {
|
|
||||||
state = !state;
|
|
||||||
// if log opened
|
|
||||||
if (state) {
|
|
||||||
if ($autoload.is(':checked')) {
|
|
||||||
$autoload.trigger('change');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clearInterval(t);
|
|
||||||
}
|
|
||||||
$logBody.slideToggle('slow')
|
|
||||||
.toggleClass('hidden');
|
|
||||||
$logHead.toggleClass('active inactive');
|
|
||||||
$trigger.toggleClass('closed');
|
|
||||||
|
|
||||||
window.location.href = $('a#log_anchor').attr('href');
|
|
||||||
}
|
|
||||||
|
|
||||||
$wrapper.on('click', '.log-header > span', toggleHandler);
|
|
||||||
$autoload.on('change', reloadChange);
|
|
||||||
|
|
||||||
$('#word_wrap').on('change', function() {
|
|
||||||
$logCont.attr({'wrap': ($(this).is(':checked')) ? 'soft' : 'off'});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#reload_interval').on('change', function() {
|
|
||||||
clearInterval(t);
|
|
||||||
if ($autoload.is(':checked')) {
|
|
||||||
t = setInterval($(this).val());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('#load_lines').on('change', function() {
|
|
||||||
$logCont.data('load_lines', $(this).val());
|
|
||||||
}).trigger('change');
|
|
||||||
loadLog();
|
|
||||||
|
|
||||||
})();
|
|
||||||
});
|
|
|
@ -125,7 +125,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
- if BuildList::HUMAN_STATUSES[@build_list.status].in? [:build_started, :build_error, :success]
|
- if BuildList::HUMAN_STATUSES[@build_list.status].in? [:build_started, :build_error, :success]
|
||||||
= render :partial => 'projects/build_lists/log'
|
= render 'shared/log', { :build_started => @build_list.build_started?, :download_log_url => build_list_log_url(:build), :get_log_path => log_build_list_path(@build_list) }
|
||||||
|
|
||||||
|
|
||||||
- if (can_publish = @build_list.can_publish? && can?(:publish, @build_list))
|
- if (can_publish = @build_list.can_publish? && can?(:publish, @build_list))
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
-#
|
||||||
|
params:
|
||||||
|
- build_started
|
||||||
|
- download_log_url
|
||||||
|
- get_log_path
|
||||||
|
|
||||||
|
- download_log_url ||= false
|
||||||
|
|
||||||
|
.hr
|
||||||
|
%a{:name => 'log'}
|
||||||
|
.log-wrapper
|
||||||
|
.log-header
|
||||||
|
.text-wrap
|
||||||
|
= link_to({:anchor => :log}, {:id => 'log_anchor'}) do
|
||||||
|
%h3= t("layout.build_lists.log.build_log")
|
||||||
|
%span
|
||||||
|
.both
|
||||||
|
.log-body.hidden
|
||||||
|
.reloader
|
||||||
|
%table.options
|
||||||
|
%tr.top
|
||||||
|
%td.first
|
||||||
|
= label_tag :word_wrap do
|
||||||
|
= check_box_tag :word_wrap
|
||||||
|
= t("layout.word_wrap")
|
||||||
|
%td.last{ :class => build_started ? nil : :hidden }
|
||||||
|
= label_tag :autoreload do
|
||||||
|
= check_box_tag :autoreload, true, build_started
|
||||||
|
= t("layout.build_lists.log.autoreload")
|
||||||
|
= select_tag :reload_interval, log_reload_time_options
|
||||||
|
%tr.bottom
|
||||||
|
%td.first
|
||||||
|
- if download_log_url
|
||||||
|
= link_to t("layout.build_lists.log.download"), download_log_url, :id => :log_url
|
||||||
|
%td.last{ :class => build_started ? nil : :hidden }
|
||||||
|
= label_tag :load_lines do
|
||||||
|
= raw t("layout.build_lists.log.load_lines", :count => select_tag(:load_lines, log_reload_lines_options))
|
||||||
|
.both
|
||||||
|
%textarea.log{ :readonly => :readonly, :wrap => 'off',
|
||||||
|
:data => { :url => get_log_path, :log_type => :build } }
|
||||||
|
= t("layout.build_lists.log.not_available")
|
||||||
|
.both
|
||||||
|
|
||||||
|
:javascript
|
||||||
|
$(function() {
|
||||||
|
initLogWrapper();
|
||||||
|
});
|
|
@ -145,7 +145,9 @@ Rosa::Application.routes.draw do
|
||||||
end
|
end
|
||||||
resources :key_pairs, :only => [:create, :index, :destroy]
|
resources :key_pairs, :only => [:create, :index, :destroy]
|
||||||
resources :products do
|
resources :products do
|
||||||
resources :product_build_lists, :only => [:create, :destroy, :new, :show]
|
resources :product_build_lists, :only => [:create, :destroy, :new, :show] do
|
||||||
|
member { get :log }
|
||||||
|
end
|
||||||
collection { get :autocomplete_project }
|
collection { get :autocomplete_project }
|
||||||
end
|
end
|
||||||
resources :maintainers, :only => [:index]
|
resources :maintainers, :only => [:index]
|
||||||
|
|
Loading…
Reference in New Issue