Merge branch 'master' into 90-pull
Conflicts: db/schema.rb vendor/assets/javascripts/vendor.js
This commit is contained in:
commit
10b828c644
|
@ -4,9 +4,9 @@
|
||||||
//= require autocomplete-rails
|
//= require autocomplete-rails
|
||||||
//= require vendor
|
//= require vendor
|
||||||
//= require jquery.dataTables_ext
|
//= require jquery.dataTables_ext
|
||||||
//= require lib/lib
|
|
||||||
//= require_tree ./design
|
//= require_tree ./design
|
||||||
//= require_tree ./extra
|
//= require_tree ./extra
|
||||||
|
//= require_tree ./lib
|
||||||
|
|
||||||
//= require underscore
|
//= require underscore
|
||||||
//= require backbone
|
//= require backbone
|
||||||
|
|
|
@ -3,7 +3,91 @@ Rosa.Models.Advisory = Backbone.Model.extend({
|
||||||
id: null,
|
id: null,
|
||||||
description: null,
|
description: null,
|
||||||
references: null,
|
references: null,
|
||||||
update_type: null
|
update_type: null,
|
||||||
|
found: false
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
_.bindAll(this, 'findByAdvisoryID');
|
||||||
|
|
||||||
|
this.url = '/advisories';
|
||||||
|
},
|
||||||
|
|
||||||
|
findByAdvisoryID: function(id, bl_type, options) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var urlError = function() {
|
||||||
|
throw new Error("A 'url' property or function must be specified");
|
||||||
|
};
|
||||||
|
|
||||||
|
var typeError = function() {
|
||||||
|
throw new Error("A 'bl_type' must be 'security' or 'bugfix'");
|
||||||
|
};
|
||||||
|
|
||||||
|
var idError = function() {
|
||||||
|
throw new Error("A 'id' must be a string at least 4 characters long");
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( (typeof(id) != "string") || (id.length < 4) ) {
|
||||||
|
idError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (bl_type == undefined) || (bl_type == null) || ((bl_type != 'security') && (bl_type != 'bugfix')) ) {
|
||||||
|
typeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
options |= {};
|
||||||
|
var data = _.extend({
|
||||||
|
query: id,
|
||||||
|
bl_type: bl_type
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
var params = _.extend({
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
beforeSend: function( xhr ) {
|
||||||
|
var token = $('meta[name="csrf-token"]').attr('content');
|
||||||
|
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
||||||
|
|
||||||
|
self.trigger('search:start');
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
if (!params.url) {
|
||||||
|
params.url = ((_.isFunction(this.url) ? this.url() : this.url) + '/search') || urlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
params.data = data;
|
||||||
|
|
||||||
|
var complete = options.complete;
|
||||||
|
params.complete = function(jqXHR, textStatus) {
|
||||||
|
//console.log(jqXHR);
|
||||||
|
|
||||||
|
switch (jqXHR.status) {
|
||||||
|
case 200:
|
||||||
|
self.set(_.extend({
|
||||||
|
found: true
|
||||||
|
}, JSON.parse(jqXHR.responseText)), {silent: true});
|
||||||
|
self.trigger('search:end');
|
||||||
|
break
|
||||||
|
|
||||||
|
case 404:
|
||||||
|
self.set(self.defaults, {silent: true});
|
||||||
|
self.trigger('search:end');
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
self.set(self.defaults, {silent: true});
|
||||||
|
self.trigger('search:failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complete) complete(jqXHR, textStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax(params);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@ Rosa.Routers.BuildListsAdvisoriesRouter = Backbone.Router.extend({
|
||||||
routes: {},
|
routes: {},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.advisoriesCollection = new Rosa.Collections.AdvisoriesCollection(Rosa.bootstrapedData.advisories);
|
this.advisoriesView = new Rosa.Views.BuildListAdvisoriesView({ model: new Rosa.Models.Advisory() });
|
||||||
this.advisoriesView = new Rosa.Views.BuildListAdvisoriesView({ collection: this.advisoriesCollection });
|
|
||||||
|
|
||||||
this.advisoriesView.render();
|
this.advisoriesView.render();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,69 +1,178 @@
|
||||||
Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
|
Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
_.bindAll(this, 'popoverTitle', 'popoverDesc', 'showAdvisory',
|
_.bindAll(this, 'showAdvisory', 'showPreview', 'showForm',
|
||||||
'changeAdvisoryList', 'showPreview', 'showForm', 'hideAll');
|
'showSearch', 'hideAll', 'displayStatus', 'processSearch',
|
||||||
|
'showInTypeSelect', 'typeSelectChange');
|
||||||
|
|
||||||
this.$el = $('#advisory_block');
|
this.$el = $('#advisory_block');
|
||||||
|
this._$type_select = $('#build_list_update_type');
|
||||||
|
this._$publish_button = $('input[type="submit"][name="publish"]');
|
||||||
|
|
||||||
this._$form = this.$('#new_advisory_form');
|
this._$form = this.$('#new_advisory_form');
|
||||||
this._$preview = this.$('#advisory_preview');
|
this._$preview = this.$('#advisory_preview');
|
||||||
this._$type_select = $('#build_list_update_type');
|
|
||||||
|
this._$search = this.$('#advisory_search_block');
|
||||||
|
this._$search_field = this.$('#advisory_search');
|
||||||
|
this._$not_found = this.$('#advisory_search_block > .advisory_not_found');
|
||||||
|
this._$server_error = this.$('#advisory_search_block > .server_error');
|
||||||
|
this._$continue_input = this.$('#advisory_search_block > .continue_input');
|
||||||
|
this._search_timer = null;
|
||||||
|
|
||||||
this._$selector = this.$('#attach_advisory');
|
this._$selector = this.$('#attach_advisory');
|
||||||
|
|
||||||
|
this._state_vars = {};
|
||||||
|
this._state_vars = _.extend({
|
||||||
|
checked_update_type: this._$type_select.val(),
|
||||||
|
header_text: this._$preview.children('h3').html()
|
||||||
|
}, this.state_vars);
|
||||||
|
|
||||||
this._$selector.on('change', this.showAdvisory);
|
this._$selector.on('change', this.showAdvisory);
|
||||||
this._$type_select.on('change', this.changeAdvisoryList);
|
this._$search_field.on('input keyup', this.processSearch);
|
||||||
|
|
||||||
|
this._$type_select.on('change', this.typeSelectChange);
|
||||||
|
|
||||||
|
this.model.on('search:start', function() {
|
||||||
|
this._$publish_button.prop({disabled: true});
|
||||||
|
}, this);
|
||||||
|
this.model.on('search:end', this.showPreview, this);
|
||||||
|
this.model.on('search:failed', this.handleSearchError, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
changeAdvisoryList: function() {
|
showAdvisory: function(ev) {
|
||||||
this._$selector.children('.popoverable').hide();
|
this._$publish_button.prop({disabled: false});
|
||||||
this._$selector.children('.popoverable.' + this._$type_select.val()).show();
|
switch (this._$selector.val()) {
|
||||||
this._$selector.val('no').trigger('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
popoverTitle: function(el) {
|
|
||||||
return el.val();
|
|
||||||
},
|
|
||||||
|
|
||||||
popoverDesc: function(el) {
|
|
||||||
return this.collection.get(el.val()).get('popover_desc');
|
|
||||||
},
|
|
||||||
|
|
||||||
showAdvisory: function(el) {
|
|
||||||
var adv_id = this._$selector.val();
|
|
||||||
switch (adv_id) {
|
|
||||||
case 'no':
|
case 'no':
|
||||||
this.hideAll();
|
this.hideAll();
|
||||||
|
this.showInTypeSelect('all');
|
||||||
break
|
break
|
||||||
case 'new':
|
case 'new':
|
||||||
this.showForm();
|
this.showForm();
|
||||||
|
this.showInTypeSelect('advisoriable');
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
this.showPreview(adv_id);
|
this.showSearch();
|
||||||
|
this.showInTypeSelect('advisoriable');
|
||||||
|
this._$publish_button.prop({disabled: true});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
typeSelectChange: function(ev) {
|
||||||
|
switch (this._$selector.val()) {
|
||||||
|
case 'no':
|
||||||
|
this._state_vars.checked_update_type = this._$selector.val();
|
||||||
|
break
|
||||||
|
case 'new':
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
this._$search_field.trigger('input');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showInTypeSelect: function(type) {
|
||||||
|
var children = this._$type_select.children('option');
|
||||||
|
if (type != 'all') {
|
||||||
|
var visible_ch = children.filter('.' + type);
|
||||||
|
var sel = children.filter(':selected');
|
||||||
|
|
||||||
|
children.prop('disabled', true);
|
||||||
|
visible_ch.prop('disabled', false);
|
||||||
|
if (sel.prop('disabled')) {
|
||||||
|
sel.prop('selected', false);
|
||||||
|
visible_ch.first().prop('selected', true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
children.prop('disabled', false).prop('selected', false);
|
||||||
|
children.filter('option[value="' + this._state_vars.checked_update_type + '"]').prop('selected', true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
processSearch: function(ev) {
|
||||||
|
if (ev.type == "keyup") {
|
||||||
|
if (ev.keyCode != 13) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var TIMER_INTERVAL = 500;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var timerCallback = function() {
|
||||||
|
if (self._$search_field.val().length > 3) {
|
||||||
|
// real search
|
||||||
|
self.model.findByAdvisoryID(self._$search_field.val(), self._$type_select.val());
|
||||||
|
} else {
|
||||||
|
// hide preview if nothing to show
|
||||||
|
if (self._$preview.is(':visible')) {
|
||||||
|
self._$preview.slideUp();
|
||||||
|
}
|
||||||
|
self.displayStatus('found');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.model.get('advisory_id') == this._$search_field.val()) {
|
||||||
|
this.showPreview();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// timeout before real AJAX request
|
||||||
|
clearTimeout(this._search_timer);
|
||||||
|
this._search_timer = setTimeout(timerCallback, TIMER_INTERVAL);
|
||||||
|
},
|
||||||
|
|
||||||
showPreview: function(id) {
|
showPreview: function(id) {
|
||||||
|
this._$publish_button.prop({disabled: false});
|
||||||
if (this._$form.is(':visible')) {
|
if (this._$form.is(':visible')) {
|
||||||
this._$form.slideUp();
|
this._$form.slideUp();
|
||||||
}
|
}
|
||||||
var adv = this.collection.get(id);
|
|
||||||
var prev = this._$preview;
|
var prev = this._$preview;
|
||||||
prev.children('h3').html(prev.children('h3').html() + ' ' + adv.get('advisory_id'));
|
var adv = this.model;
|
||||||
|
if (adv.get('found')) {
|
||||||
|
this._$selector.children('option.advisory_id').val(adv.get('advisory_id'));
|
||||||
|
|
||||||
|
prev.children('h3').html(this._state_vars.header_text + ' ' + adv.get('advisory_id'));
|
||||||
prev.children('.descr').html(adv.get('description'));
|
prev.children('.descr').html(adv.get('description'));
|
||||||
prev.children('.refs').html(adv.get('references'));
|
prev.children('.refs').html(adv.get('references'));
|
||||||
if (!this._$preview.is(':visible')) {
|
if (!this._$preview.is(':visible')) {
|
||||||
this._$preview.slideDown();
|
this._$preview.slideDown();
|
||||||
}
|
}
|
||||||
|
this.displayStatus('found');
|
||||||
|
} else {
|
||||||
|
if (this._$preview.is(':visible')) {
|
||||||
|
this._$preview.slideUp();
|
||||||
|
}
|
||||||
|
this._$publish_button.prop({disabled: true});
|
||||||
|
this.displayStatus('not_found');
|
||||||
|
this._$selector.children('option.advisory_id').val('');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showForm: function() {
|
showForm: function() {
|
||||||
if (this._$preview.is(':visible')) {
|
if (this._$preview.is(':visible')) {
|
||||||
this._$preview.slideUp();
|
this._$preview.slideUp();
|
||||||
}
|
}
|
||||||
|
if (this._$search.is(':visible')) {
|
||||||
|
this._$search.slideUp();
|
||||||
|
}
|
||||||
if (!this._$form.is(':visible')) {
|
if (!this._$form.is(':visible')) {
|
||||||
this._$form.slideDown();
|
this._$form.slideDown();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hideAll: function() {
|
showSearch: function() {
|
||||||
|
if (this._$form.is(':visible')) {
|
||||||
|
this._$form.slideUp();
|
||||||
|
}
|
||||||
|
if (!this._$search.is(':visible')) {
|
||||||
|
this._$search.slideDown();
|
||||||
|
this._$search_field.trigger('input');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSearchError: function() {
|
||||||
|
this._$publish_button.prop({disabled: true});
|
||||||
|
this.displayStatus('error');
|
||||||
if (this._$preview.is(':visible')) {
|
if (this._$preview.is(':visible')) {
|
||||||
this._$preview.slideUp();
|
this._$preview.slideUp();
|
||||||
}
|
}
|
||||||
|
@ -72,14 +181,33 @@ Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hideAll: function() {
|
||||||
|
if (this._$preview.is(':visible')) {
|
||||||
|
this._$preview.slideUp();
|
||||||
|
}
|
||||||
|
if (this._$search.is(':visible')) {
|
||||||
|
this._$search.slideUp();
|
||||||
|
}
|
||||||
|
if (this._$form.is(':visible')) {
|
||||||
|
this._$form.slideUp();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
displayStatus: function(st) {
|
||||||
|
var ELEMS = {
|
||||||
|
'found': this._$continue_input,
|
||||||
|
'not_found': this._$not_found,
|
||||||
|
'error': this._$server_error
|
||||||
|
};
|
||||||
|
|
||||||
|
this._$continue_input.hide();
|
||||||
|
this._$not_found.hide();
|
||||||
|
this._$server_error.hide();
|
||||||
|
|
||||||
|
ELEMS[st].show();
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var title = this.popoverTitle;
|
|
||||||
var description = this.popoverDesc;
|
|
||||||
this.changeAdvisoryList();
|
|
||||||
this.$('#attach_advisory > .popoverable').popover({
|
|
||||||
title: function() { return title($(this)); },
|
|
||||||
content: function() { return description($(this)); }
|
|
||||||
});
|
|
||||||
this.showAdvisory();
|
this.showAdvisory();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ $(document).ready(function() {
|
||||||
if ($(this).val() == platform_id) {
|
if ($(this).val() == platform_id) {
|
||||||
if ($(this).attr('data-released') === '1') {
|
if ($(this).attr('data-released') === '1') {
|
||||||
$('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
|
$('#build_list_auto_publish').removeAttr('checked').attr('disabled', 'disabled');
|
||||||
disableUpdateTypes();
|
//disableUpdateTypes();
|
||||||
} else {
|
} else {
|
||||||
$('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
|
$('#build_list_auto_publish').removeAttr('disabled').attr('checked', 'checked');
|
||||||
enableUpdateTypes();
|
//enableUpdateTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
$(this).attr('checked', 'checked').removeAttr('disabled').trigger('change');
|
$(this).attr('checked', 'checked').removeAttr('disabled').trigger('change');
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
//= require ./jquery.placeholder
|
|
||||||
//= require ./bootstrap-tooltip
|
|
||||||
//= require ./bootstrap-popover
|
|
|
@ -962,10 +962,55 @@ form.mass_build input[type="checkbox"] {
|
||||||
height: 11px;
|
height: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#new_advisory_form, div#advisory_preview {
|
div#new_advisory_form,
|
||||||
|
div#advisory_preview,
|
||||||
|
div#advisory_search_block,
|
||||||
|
div#advisory_search_block div.info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.hint_text {
|
||||||
|
color: #666666;
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_block p.hint_text {
|
||||||
|
display: block;
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block div.info {
|
||||||
|
width: 565px;
|
||||||
|
border: solid 1px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block div.info p {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0.5em 2em 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block div.advisory_not_found {
|
||||||
|
background-color: #B7CFFF;
|
||||||
|
border-color: #6666FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block div.server_error {
|
||||||
|
background-color: #FACFCF;
|
||||||
|
border-color: #FF7777;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#advisory_search_block div.continue_input {
|
||||||
|
background-color: #CFFACF;
|
||||||
|
border-color: #00CF00;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
/*=============== popovers ===============*/
|
/*=============== popovers ===============*/
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
|
@ -1099,3 +1144,39 @@ form.mass_build section.right {
|
||||||
.min_width_120 {
|
.min_width_120 {
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chzn-select {
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages_info_container ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 25px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages_info_container ul.platforms {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove this lines after change to backbone */
|
||||||
|
table.tablesorter.advisories thead tr.search th {
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tablesorter.advisories thead tr.search th input[type='text'] {
|
||||||
|
width: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tablesorter.advisories thead tr.search th form {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tablesorter.advisories thead tr.search th form.button_to {
|
||||||
|
padding: 3px 0 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tablesorter tr td.no_results {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
/* end */
|
||||||
|
|
|
@ -1,20 +1,50 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
class AdvisoriesController < ApplicationController
|
class AdvisoriesController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
before_filter :find_advisory, :only => [:show]
|
|
||||||
skip_before_filter :authenticate_user! if APP_CONFIG['anonymous_access']
|
skip_before_filter :authenticate_user! if APP_CONFIG['anonymous_access']
|
||||||
load_and_authorize_resource
|
load_resource :find_by => :advisory_id
|
||||||
|
authorize_resource
|
||||||
|
|
||||||
|
before_filter :fetch_packages_info, :only => [:show]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@advisories = @advisories.scoped(:include => :platforms)
|
||||||
|
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
|
||||||
@advisories = @advisories.paginate(:page => params[:page])
|
@advisories = @advisories.paginate(:page => params[:page])
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.atom
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def search
|
||||||
|
@advisory = Advisory.by_update_type(params[:bl_type]).search_by_id(params[:query]).first
|
||||||
|
raise ActionController::RoutingError.new('Not Found') if @advisory.nil?
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render @advisory }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def find_advisory
|
# this method fetches and structurize packages attached to current advisory.
|
||||||
@advisory = Advisory.where(:advisory_id => params[:id]).limit(1).first if params[:id].present?
|
def fetch_packages_info
|
||||||
|
@packages_info = Hash.new { |h, k| h[k] = {} } # maaagic, it's maaagic ;)
|
||||||
|
@advisory.build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
|
||||||
|
batch.each do |build_list|
|
||||||
|
tmp = build_list.packages.inject({:srpm => nil, :rpm => []}) do |h, p|
|
||||||
|
p.package_type == 'binary' ? h[:rpm] << p.fullname : h[:srpm] = p.fullname
|
||||||
|
h
|
||||||
|
end
|
||||||
|
h = { build_list.project => tmp }
|
||||||
|
@packages_info[build_list.save_to_platform].merge!(h) do |pr, old, new|
|
||||||
|
{:srpm => new[:srpm], :rpm => old[:rpm].concat(new[:rpm]).uniq}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#class MassBuildsController < ApplicationController
|
||||||
|
class Platforms::MassBuildsController < Platforms::BaseController
|
||||||
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
|
load_and_authorize_resource :platform
|
||||||
|
load_and_authorize_resource
|
||||||
|
|
||||||
|
skip_load_and_authorize_resource :only => [:index, :create]
|
||||||
|
skip_load_and_authorize_resource :platform, :only => [:cancel, :failed_builds_list]
|
||||||
|
skip_authorize_resource :platform, :only => [:create, :index]
|
||||||
|
|
||||||
|
def create
|
||||||
|
mass_build = @platform.mass_builds.new(:repositories => params[:repositories],
|
||||||
|
:arches => params[:arches],
|
||||||
|
:auto_publish => params[:auto_publish] || false)
|
||||||
|
mass_build.user = current_user
|
||||||
|
authorize! :create, mass_build
|
||||||
|
|
||||||
|
if mass_build.save
|
||||||
|
redirect_to(platform_mass_builds_path(@platform), :notice => t("flash.platform.build_all_success"))
|
||||||
|
else
|
||||||
|
@auto_publish_selected = params[:auto_publish].present?
|
||||||
|
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
|
||||||
|
flash[:warning] = mass_build.errors.full_messages.join('. ')
|
||||||
|
flash[:error] = t("flash.platform.build_all_error")
|
||||||
|
render :index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def index
|
||||||
|
authorize! :edit, @platform
|
||||||
|
|
||||||
|
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
|
||||||
|
@auto_publish_selected = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def cancel
|
||||||
|
@mass_build.cancel_all
|
||||||
|
flash[:notice] = t("flash.platform.cancel_mass_build")
|
||||||
|
redirect_to platform_mass_builds_path(@mass_build.platform)
|
||||||
|
end
|
||||||
|
|
||||||
|
def failed_builds_list
|
||||||
|
render :text => @mass_build.generate_failed_builds_list
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,35 +7,6 @@ class Platforms::PlatformsController < Platforms::BaseController
|
||||||
|
|
||||||
autocomplete :user, :uname
|
autocomplete :user, :uname
|
||||||
|
|
||||||
def build_all
|
|
||||||
mass_build = MassBuild.new(
|
|
||||||
:platform => @platform,
|
|
||||||
:user => current_user,
|
|
||||||
:repositories => params[:repositories],
|
|
||||||
:arches => params[:arches],
|
|
||||||
:auto_publish => params[:auto_publish] || false
|
|
||||||
)
|
|
||||||
if mass_build.save
|
|
||||||
redirect_to(mass_builds_platform_path(@platform), :notice => t("flash.platform.build_all_success"))
|
|
||||||
else
|
|
||||||
@auto_publish_selected = params[:auto_publish].present?
|
|
||||||
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
|
|
||||||
flash[:warning] = mass_build.errors.full_messages.join('. ')
|
|
||||||
flash[:error] = t("flash.platform.build_all_error")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mass_builds
|
|
||||||
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
|
|
||||||
@auto_publish_selected = true
|
|
||||||
render :action => :build_all
|
|
||||||
end
|
|
||||||
|
|
||||||
def failed_builds_list
|
|
||||||
@mass_build = MassBuild.find params[:mass_build_id]
|
|
||||||
render :text => @mass_build.generate_failed_builds_list
|
|
||||||
end
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@platforms = @platforms.accessible_by(current_ability, :related).paginate(:page => params[:page], :per_page => 20)
|
@platforms = @platforms.accessible_by(current_ability, :related).paginate(:page => params[:page], :per_page => 20)
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,8 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
def index
|
def index
|
||||||
@action_url = @project ? search_project_build_lists_path(@project) : search_build_lists_path
|
@action_url = @project ? search_project_build_lists_path(@project) : search_build_lists_path
|
||||||
@filter = BuildList::Filter.new(@project, current_user, params[:filter] || {})
|
@filter = BuildList::Filter.new(@project, current_user, params[:filter] || {})
|
||||||
@build_lists = @filter.find.recent.paginate :page => params[:page]
|
@build_lists = @filter.find.scoped(:include => [:save_to_platform, :project, :user, :arch])
|
||||||
|
@build_lists = @build_lists.recent.paginate :page => params[:page]
|
||||||
|
|
||||||
@build_server_status = begin
|
@build_server_status = begin
|
||||||
BuildServer.get_status
|
BuildServer.get_status
|
||||||
|
@ -70,7 +71,6 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@item_groups = @build_list.items.group_by_level
|
@item_groups = @build_list.items.group_by_level
|
||||||
@advisories = @build_list.project.advisories
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -171,11 +171,16 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
@build_list.update_type = params[:build_list][:update_type] if params[:build_list][:update_type].present?
|
@build_list.update_type = params[:build_list][:update_type] if params[:build_list][:update_type].present?
|
||||||
|
|
||||||
if params[:attach_advisory].present? and params[:attach_advisory] != 'no' and !@build_list.advisory
|
if params[:attach_advisory].present? and params[:attach_advisory] != 'no' and !@build_list.advisory
|
||||||
|
|
||||||
|
unless @build_list.update_type.in? BuildList::RELEASE_UPDATE_TYPES
|
||||||
|
redirect_to :back, :notice => t('lyout.build_lists.publish_fail') and return
|
||||||
|
end
|
||||||
|
|
||||||
if params[:attach_advisory] == 'new'
|
if params[:attach_advisory] == 'new'
|
||||||
# create new advisory
|
# create new advisory
|
||||||
if !@build_list.build_advisory(params[:build_list][:advisory]) do |a|
|
unless @build_list.build_advisory(params[:build_list][:advisory]) do |a|
|
||||||
a.update_type = @build_list.update_type
|
a.update_type = @build_list.update_type
|
||||||
a.project = @build_list.project
|
a.projects << @build_list.project
|
||||||
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
||||||
end.save
|
end.save
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||||
|
@ -187,12 +192,15 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||||
end
|
end
|
||||||
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
||||||
|
a.projects << @build_list.project unless a.projects.include? @build_list.project
|
||||||
@build_list.advisory = a
|
@build_list.advisory = a
|
||||||
unless a.save
|
unless a.save
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if @build_list.save and @build_list.now_publish
|
if @build_list.save and @build_list.now_publish
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_success')
|
redirect_to :back, :notice => t('layout.build_lists.publish_success')
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
# -*- encoding : utf-8 -*-
|
# -*- encoding : utf-8 -*-
|
||||||
module AdvisoriesHelper
|
module AdvisoriesHelper
|
||||||
def advisories_select_options(advisories, opts = {:class => 'popoverable'})
|
def advisories_select_options(advisories, opts = {:class => 'popoverable'})
|
||||||
def_values = [[t("layout.advisories.no_"), 'no'], [t("layout.advisories.new"), 'new']]
|
def_values = [[t("layout.advisories.no_"), 'no'], [t("layout.advisories.new"), 'new'], [t("layout.advisories.existing"), 'existing', {:class => 'advisory_id'}]]
|
||||||
options_for_select(def_values, def_values.first) +
|
options_for_select(def_values, def_values.first)
|
||||||
options_for_select(advisories.map { |a| [a.advisory_id, :class => "#{opts[:class]} #{a.update_type}"] })
|
end
|
||||||
|
|
||||||
|
def advisory_id_for_hint
|
||||||
|
sprintf(Advisory::ID_STRING_TEMPLATE, :type => "{#{Advisory::TYPES.values.join(',')}}",
|
||||||
|
:year => 'YYYY', :id => 'XXXX')
|
||||||
end
|
end
|
||||||
|
|
||||||
def construct_ref_link(ref)
|
def construct_ref_link(ref)
|
||||||
|
|
|
@ -23,4 +23,24 @@ module BuildListsHelper
|
||||||
|
|
||||||
''
|
''
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_list_classified_update_types
|
||||||
|
advisoriable = BuildList::RELEASE_UPDATE_TYPES.map do |el|
|
||||||
|
[el, {:class => 'advisoriable'}]
|
||||||
|
end
|
||||||
|
nonadvisoriable = (BuildList::UPDATE_TYPES - BuildList::RELEASE_UPDATE_TYPES).map do |el|
|
||||||
|
[el, {:class => 'nonadvisoriable'}]
|
||||||
|
end
|
||||||
|
|
||||||
|
return advisoriable + nonadvisoriable
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_list_version_link(build_list, str_version = false)
|
||||||
|
if build_list.commit_hash.present?
|
||||||
|
link_to str_version ? "#{shortest_hash_id @build_list.commit_hash} ( #{@build_list.project_version} )" : shortest_hash_id(build_list.commit_hash),
|
||||||
|
commit_path(build_list.project.owner, build_list.project, build_list.commit_hash)
|
||||||
|
else
|
||||||
|
build_list.project_version
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,22 +85,25 @@ class Ability
|
||||||
can [:read, :related, :members], Platform, :owner_type => 'Group', :owner_id => user.group_ids
|
can [:read, :related, :members], Platform, :owner_type => 'Group', :owner_id => user.group_ids
|
||||||
can([:read, :related, :members], Platform, read_relations_for('platforms')) {|platform| local_reader? platform}
|
can([:read, :related, :members], Platform, read_relations_for('platforms')) {|platform| local_reader? platform}
|
||||||
can([:update, :members], Platform) {|platform| local_admin? platform}
|
can([:update, :members], Platform) {|platform| local_admin? platform}
|
||||||
can([:destroy, :members, :add_member, :remove_member, :remove_members, :build_all, :mass_builds] , Platform) {|platform| owner? platform}
|
can([:destroy, :members, :add_member, :remove_member, :remove_members] , Platform) {|platform| owner?(platform) || local_admin?(platform) }
|
||||||
can [:autocomplete_user_uname, :read_advisories, :advisories], Platform
|
can [:autocomplete_user_uname, :read_advisories, :advisories], Platform
|
||||||
|
|
||||||
|
can([:failed_builds_list, :create], MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && mass_build.platform.main? }
|
||||||
|
can(:cancel, MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && !mass_build.stop_build && mass_build.platform.main?}
|
||||||
|
|
||||||
can [:read, :projects_list], Repository, :platform => {:visibility => 'open'}
|
can [:read, :projects_list], Repository, :platform => {:visibility => 'open'}
|
||||||
can [:read, :projects_list], Repository, :platform => {:owner_type => 'User', :owner_id => user.id}
|
can [:read, :projects_list], Repository, :platform => {:owner_type => 'User', :owner_id => user.id}
|
||||||
can [:read, :projects_list], Repository, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
|
can [:read, :projects_list], Repository, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
|
||||||
can([:read, :projects_list], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
|
can([:read, :projects_list], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
|
||||||
can([:create, :update, :projects_list, :add_project, :remove_project], Repository) {|repository| local_admin? repository.platform}
|
can([:create, :update, :projects_list, :add_project, :remove_project], Repository) {|repository| local_admin? repository.platform}
|
||||||
can(:clear, Platform) {|platform| local_admin?(platform) && platform.platform_type == 'personal'}
|
can(:clear, Platform) {|platform| local_admin?(platform) && platform.personal?}
|
||||||
can([:change_visibility, :settings, :destroy], Repository) {|repository| owner? repository.platform}
|
can([:change_visibility, :settings, :destroy], Repository) {|repository| owner? repository.platform}
|
||||||
|
|
||||||
can :read, Product, :platform => {:visibility => 'open'}
|
can :read, Product, :platform => {:visibility => 'open'}
|
||||||
can :read, Product, :platform => {:owner_type => 'User', :owner_id => user.id, :platform_type => 'main'}
|
can :read, Product, :platform => {:owner_type => 'User', :owner_id => user.id, :platform_type => 'main'}
|
||||||
can :read, Product, :platform => {:owner_type => 'Group', :owner_id => user.group_ids, :platform_type => 'main'}
|
can :read, Product, :platform => {:owner_type => 'Group', :owner_id => user.group_ids, :platform_type => 'main'}
|
||||||
can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.platform_type == 'main'}
|
can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?}
|
||||||
can([:create, :update, :destroy, :clone], Product) {|product| local_admin? product.platform and product.platform.platform_type == 'main'}
|
can([:create, :update, :destroy, :clone], Product) {|product| local_admin? product.platform and product.platform.main?}
|
||||||
|
|
||||||
can(:create, ProductBuildList) {|pbl| can?(:update, pbl.product)}
|
can(:create, ProductBuildList) {|pbl| can?(:update, pbl.product)}
|
||||||
can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)}
|
can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)}
|
||||||
|
@ -131,7 +134,10 @@ class Ability
|
||||||
cannot [:members, :add_member, :remove_member, :remove_members], Platform, :platform_type => 'personal'
|
cannot [:members, :add_member, :remove_member, :remove_members], Platform, :platform_type => 'personal'
|
||||||
|
|
||||||
cannot [:create, :update, :destroy, :clone], Product, :platform => {:platform_type => 'personal'}
|
cannot [:create, :update, :destroy, :clone], Product, :platform => {:platform_type => 'personal'}
|
||||||
cannot [:clone, :build_all, :mass_builds], Platform, :platform_type => 'personal'
|
cannot [:clone], Platform, :platform_type => 'personal'
|
||||||
|
|
||||||
|
cannot([:failed_builds_list, :create], MassBuild) {|mass_build| mass_build.platform.personal?}
|
||||||
|
cannot(:cancel, MassBuild) {|mass_build| mass_build.platform.personal? || mass_build.stop_build}
|
||||||
|
|
||||||
can :create, Subscribe do |subscribe|
|
can :create, Subscribe do |subscribe|
|
||||||
!subscribe.subscribeable.subscribes.exists?(:user_id => user.id)
|
!subscribe.subscribeable.subscribes.exists?(:user_id => user.id)
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
class Advisory < ActiveRecord::Base
|
class Advisory < ActiveRecord::Base
|
||||||
has_and_belongs_to_many :platforms
|
has_and_belongs_to_many :platforms
|
||||||
|
has_and_belongs_to_many :projects
|
||||||
has_many :build_lists
|
has_many :build_lists
|
||||||
belongs_to :project
|
|
||||||
|
|
||||||
validates :description, :update_type, :presence => true
|
validates :description, :update_type, :presence => true
|
||||||
|
validates :update_type, :inclusion => BuildList::RELEASE_UPDATE_TYPES
|
||||||
|
|
||||||
after_create :generate_advisory_id
|
after_create :generate_advisory_id
|
||||||
before_save :normalize_references, :if => :references_changed?
|
before_save :normalize_references, :if => :references_changed?
|
||||||
|
|
||||||
ID_TEMPLATE = 'ROSA-%<type>s-%<year>d:%<id>04d'
|
ID_TEMPLATE = 'ROSA-%<type>s-%<year>d:%<id>04d'
|
||||||
|
ID_STRING_TEMPLATE = 'ROSA-%<type>s-%<year>04s:%<id>04s'
|
||||||
TYPES = {'security' => 'SA', 'bugfix' => 'A'}
|
TYPES = {'security' => 'SA', 'bugfix' => 'A'}
|
||||||
|
|
||||||
scope :by_project, lambda {|p| where('project_id' => p.try(:id) || p)}
|
scope :search_by_id, lambda { |aid| where('advisory_id ILIKE ?', "%#{aid.to_s.strip}%") }
|
||||||
|
scope :by_update_type, lambda { |ut| where(:update_type => ut) }
|
||||||
|
default_scope order('created_at DESC')
|
||||||
|
|
||||||
def to_param
|
def to_param
|
||||||
advisory_id
|
advisory_id
|
||||||
|
|
|
@ -16,9 +16,9 @@ class BuildList < ActiveRecord::Base
|
||||||
validates :project_id, :project_version, :arch, :include_repos, :presence => true
|
validates :project_id, :project_version, :arch, :include_repos, :presence => true
|
||||||
validates_numericality_of :priority, :greater_than_or_equal_to => 0
|
validates_numericality_of :priority, :greater_than_or_equal_to => 0
|
||||||
validates :update_type, :inclusion => UPDATE_TYPES,
|
validates :update_type, :inclusion => UPDATE_TYPES,
|
||||||
:unless => Proc.new { |b| b.save_to_platform.released }
|
:unless => Proc.new { |b| b.advisory.present? }
|
||||||
validates :update_type, :inclusion => {:in => RELEASE_UPDATE_TYPES, :message => I18n.t('flash.build_list.frozen_platform')},
|
validates :update_type, :inclusion => {:in => RELEASE_UPDATE_TYPES, :message => I18n.t('flash.build_list.frozen_platform')},
|
||||||
:if => Proc.new { |b| b.save_to_platform.released && b.mass_build_id.nil?}
|
:if => Proc.new { |b| b.advisory.present? }
|
||||||
validate lambda {
|
validate lambda {
|
||||||
errors.add(:build_for_platform, I18n.t('flash.build_list.wrong_platform')) if save_to_platform.platform_type == 'main' && save_to_platform_id != build_for_platform_id
|
errors.add(:build_for_platform, I18n.t('flash.build_list.wrong_platform')) if save_to_platform.platform_type == 'main' && save_to_platform_id != build_for_platform_id
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ class BuildList < ActiveRecord::Base
|
||||||
scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform.id) }
|
scope :for_platform, lambda { |platform| where(:build_for_platform_id => platform.id) }
|
||||||
scope :by_mass_build, lambda { |mass_build| where(:mass_build_id => mass_build) }
|
scope :by_mass_build, lambda { |mass_build| where(:mass_build_id => mass_build) }
|
||||||
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
|
scope :scoped_to_arch, lambda {|arch| where(:arch_id => arch) }
|
||||||
|
scope :scoped_to_save_platform, lambda {|pl_id| where(:save_to_platform_id => pl_id) }
|
||||||
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|
|
||||||
|
@ -219,6 +220,10 @@ class BuildList < ActiveRecord::Base
|
||||||
self.class.human_status(status)
|
self.class.human_status(status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.status_by_human(human)
|
||||||
|
BuildList::HUMAN_STATUSES.key human
|
||||||
|
end
|
||||||
|
|
||||||
def set_items(items_hash)
|
def set_items(items_hash)
|
||||||
self.items = []
|
self.items = []
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,17 @@ class BuildList::Filter
|
||||||
build_lists = build_lists.accessible_by(::Ability.new(@user), @options[:ownership].to_sym) if @options[:ownership]
|
build_lists = build_lists.accessible_by(::Ability.new(@user), @options[:ownership].to_sym) if @options[:ownership]
|
||||||
build_lists = build_lists.for_status(@options[:status]) if @options[:status]
|
build_lists = build_lists.for_status(@options[:status]) if @options[:status]
|
||||||
build_lists = build_lists.scoped_to_arch(@options[:arch_id]) if @options[:arch_id]
|
build_lists = build_lists.scoped_to_arch(@options[:arch_id]) if @options[:arch_id]
|
||||||
|
build_lists = build_lists.scoped_to_save_platform(@options[:platform_id]) if @options[:platform_id]
|
||||||
build_lists = build_lists.scoped_to_project_version(@options[:project_version]) if @options[:project_version]
|
build_lists = build_lists.scoped_to_project_version(@options[:project_version]) if @options[:project_version]
|
||||||
build_lists = build_lists.scoped_to_is_circle(@options[:is_circle]) if @options[:is_circle].present?
|
build_lists = build_lists.scoped_to_is_circle(@options[:is_circle]) if @options[:is_circle].present?
|
||||||
build_lists = build_lists.scoped_to_project_name(@options[:project_name]) if @options[:project_name]
|
build_lists = build_lists.scoped_to_project_name(@options[:project_name]) if @options[:project_name]
|
||||||
build_lists = build_lists.by_mass_build(@options[:mass_build_id]) if @options[:mass_build_id]
|
build_lists = build_lists.by_mass_build(@options[:mass_build_id]) if @options[:mass_build_id]
|
||||||
|
|
||||||
if @options[:created_at_start] || @options[:created_at_end]
|
# TODO [BuildList#created_at filters] Uncomment here and in build_lists/_filter.html.haml to return filters
|
||||||
build_lists = build_lists.for_creation_date_period(@options[:created_at_start], @options[:created_at_end])
|
#
|
||||||
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])
|
||||||
|
# end
|
||||||
if @options[:updated_at_start] || @options[:updated_at_end]
|
if @options[:updated_at_start] || @options[:updated_at_end]
|
||||||
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
|
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
|
||||||
end
|
end
|
||||||
|
@ -51,6 +54,7 @@ class BuildList::Filter
|
||||||
:updated_at_start => nil,
|
:updated_at_start => nil,
|
||||||
:updated_at_end => nil,
|
:updated_at_end => nil,
|
||||||
:arch_id => nil,
|
:arch_id => nil,
|
||||||
|
:platform_id => nil,
|
||||||
:is_circle => nil,
|
:is_circle => nil,
|
||||||
:project_version => nil,
|
:project_version => nil,
|
||||||
:bs_id => nil,
|
:bs_id => nil,
|
||||||
|
@ -66,6 +70,7 @@ class BuildList::Filter
|
||||||
@options[:updated_at_end] = build_date_from_params(:updated_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[:platform_id] = @options[:platform_id].present? ? @options[:platform_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
|
||||||
@options[:bs_id] = @options[:bs_id].presence
|
@options[:bs_id] = @options[:bs_id].presence
|
||||||
@options[:project_name] = @options[:project_name].presence
|
@options[:project_name] = @options[:project_name].presence
|
||||||
|
|
|
@ -6,11 +6,13 @@ class MassBuild < ActiveRecord::Base
|
||||||
scope :by_platform, lambda { |platform| where(:platform_id => platform.id) }
|
scope :by_platform, lambda { |platform| where(:platform_id => platform.id) }
|
||||||
|
|
||||||
attr_accessor :repositories, :arches
|
attr_accessor :repositories, :arches
|
||||||
|
attr_accessible :repositories, :arches, :auto_publish
|
||||||
|
|
||||||
validates :platform_id, :arch_names, :name, :user_id, :repositories, :presence => true
|
validates :platform_id, :arch_names, :name, :user_id, :repositories, :rep_names, :presence => true
|
||||||
validates_inclusion_of :auto_publish, :in => [true, false]
|
validates_inclusion_of :auto_publish, :in => [true, false]
|
||||||
|
|
||||||
after_create :build_all
|
after_create :build_all
|
||||||
|
before_validation :set_data
|
||||||
|
|
||||||
COUNT_STATUSES = [
|
COUNT_STATUSES = [
|
||||||
:build_lists,
|
:build_lists,
|
||||||
|
@ -21,16 +23,6 @@ class MassBuild < ActiveRecord::Base
|
||||||
:build_error
|
:build_error
|
||||||
]
|
]
|
||||||
|
|
||||||
def initialize(args = nil)
|
|
||||||
super
|
|
||||||
|
|
||||||
if new_record?
|
|
||||||
rep_names = Repository.where(:id => self.repositories).map(&:name).join(", ")
|
|
||||||
self.name = "#{Time.now.utc.to_date.strftime("%d.%b")}-#{platform.name}(#{rep_names})"
|
|
||||||
self.arch_names = Arch.where(:id => self.arches).map(&:name).join(", ")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ATTENTION: repositories and arches must be set before calling this method!
|
# ATTENTION: repositories and arches must be set before calling this method!
|
||||||
def build_all
|
def build_all
|
||||||
platform.build_all(
|
platform.build_all(
|
||||||
|
@ -50,4 +42,23 @@ class MassBuild < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
report
|
report
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cancel_all
|
||||||
|
self.update_attribute(:stop_build, true)
|
||||||
|
self.build_lists.find_each(:batch_size => 100) do |bl|
|
||||||
|
bl.cancel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
later :cancel_all, :queue => :clone_build
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_data
|
||||||
|
if new_record?
|
||||||
|
self.rep_names = Repository.where(:id => self.repositories).map(&:name).join(", ")
|
||||||
|
self.name = "#{Time.now.utc.to_date.strftime("%d.%b")}-#{platform.name}"
|
||||||
|
self.arch_names = Arch.where(:id => self.arches).map(&:name).join(", ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -107,6 +107,10 @@ class Platform < ActiveRecord::Base
|
||||||
platform_type == 'personal'
|
platform_type == 'personal'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def main?
|
||||||
|
platform_type == 'main'
|
||||||
|
end
|
||||||
|
|
||||||
def base_clone(attrs = {}) # :description, :name, :owner
|
def base_clone(attrs = {}) # :description, :name, :owner
|
||||||
dup.tap do |c|
|
dup.tap do |c|
|
||||||
attrs.each {|k,v| c.send("#{k}=", v)} # c.attributes = attrs
|
attrs.each {|k,v| c.send("#{k}=", v)} # c.attributes = attrs
|
||||||
|
@ -167,6 +171,7 @@ class Platform < ActiveRecord::Base
|
||||||
auto_publish = opts[:auto_publish] || false
|
auto_publish = opts[:auto_publish] || false
|
||||||
user = opts[:user]
|
user = opts[:user]
|
||||||
mass_build_id = opts[:mass_build_id]
|
mass_build_id = opts[:mass_build_id]
|
||||||
|
mass_build = MassBuild.find mass_build_id
|
||||||
|
|
||||||
repositories.each do |rep|
|
repositories.each do |rep|
|
||||||
rep.projects.find_in_batches(:batch_size => 2) do |group|
|
rep.projects.find_in_batches(:batch_size => 2) do |group|
|
||||||
|
@ -174,6 +179,7 @@ class Platform < ActiveRecord::Base
|
||||||
group.each do |p|
|
group.each do |p|
|
||||||
arches.map(&:name).each do |arch|
|
arches.map(&:name).each do |arch|
|
||||||
begin
|
begin
|
||||||
|
return if mass_build.reload.stop_build
|
||||||
p.build_for(self, user, arch, auto_publish, mass_build_id)
|
p.build_for(self, user, arch, auto_publish, mass_build_id)
|
||||||
rescue RuntimeError, Exception
|
rescue RuntimeError, Exception
|
||||||
# p.async(:build_for, self, user, arch, auto_publish, mass_build_id) # TODO need this?
|
# p.async(:build_for, self, user, arch, auto_publish, mass_build_id) # TODO need this?
|
||||||
|
|
|
@ -19,8 +19,8 @@ class Project < ActiveRecord::Base
|
||||||
has_many :collaborators, :through => :relations, :source => :actor, :source_type => 'User'
|
has_many :collaborators, :through => :relations, :source => :actor, :source_type => 'User'
|
||||||
has_many :groups, :through => :relations, :source => :actor, :source_type => 'Group'
|
has_many :groups, :through => :relations, :source => :actor, :source_type => 'Group'
|
||||||
|
|
||||||
has_many :advisories # should be without :dependent => :destroy
|
|
||||||
has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy
|
has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy
|
||||||
|
has_and_belongs_to_many :advisories # should be without :dependent => :destroy
|
||||||
|
|
||||||
validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
|
validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /^#{NAME_REGEXP}$/, :message => I18n.t("activerecord.errors.project.uname")}
|
||||||
validates :owner, :presence => true
|
validates :owner, :presence => true
|
||||||
|
|
|
@ -73,7 +73,7 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def fullname
|
def fullname
|
||||||
return "#{uname} (#{name})"
|
return name.present? && name.length > 0 ? "#{uname} (#{name})" : uname
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_appeal
|
def user_appeal
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
json.id advisory.id
|
||||||
|
json.advisory_id advisory.advisory_id
|
||||||
|
json.description advisory.description
|
||||||
|
json.references advisory.references.split("\n").map { |ref| construct_ref_link(ref) }.join('<br />')
|
||||||
|
json.update_type advisory.update_type
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
%h3= t("activerecord.attributes.advisory.description")
|
||||||
|
%p= simple_format advisory.description
|
||||||
|
|
||||||
|
%h3= t("activerecord.attributes.advisory.references")
|
||||||
|
%p
|
||||||
|
- advisory.references.gsub(/\r| /, '').split("\n").each do |ref|
|
||||||
|
= construct_ref_link(ref)
|
||||||
|
%br
|
|
@ -4,5 +4,29 @@
|
||||||
%th.th1= t("activerecord.attributes.advisory.advisory_id")
|
%th.th1= t("activerecord.attributes.advisory.advisory_id")
|
||||||
%th.th2= t("layout.advisories.affected_versions")
|
%th.th2= t("layout.advisories.affected_versions")
|
||||||
%th.th3= t("activerecord.attributes.advisory.description")
|
%th.th3= t("activerecord.attributes.advisory.description")
|
||||||
|
%tr.search
|
||||||
|
-# TODO: change filter to Backbone.js
|
||||||
|
%th{:colspan => 3, :rowspan => 1}
|
||||||
|
= form_tag advisories_path, :method => :get do |f|
|
||||||
|
= text_field_tag('q', params[:q], :placeholder => t("layout.advisories.search_by_id"), :class => params[:q].present? ? 'black' : 'gray')
|
||||||
|
%input{:type => 'submit', :value => t("layout.search.header")}
|
||||||
|
=# link_to t('layout.back'), advisories_path, :class => 'button'
|
||||||
|
= button_to t('layout.clear'), {:action => :index} , :method => :get
|
||||||
|
|
||||||
%tbody
|
%tbody
|
||||||
|
- if list.size > 0
|
||||||
= render :partial => 'list_item', :collection => list, :as => :advisory
|
= render :partial => 'list_item', :collection => list, :as => :advisory
|
||||||
|
- else
|
||||||
|
%tr.odd
|
||||||
|
%td.no_results{:colspan => 3}
|
||||||
|
= t("layout.search.no_results", :query => params[:q])
|
||||||
|
|
||||||
|
:javascript
|
||||||
|
$(function() {
|
||||||
|
var $search = $('tr.search > th input[type="text"]');
|
||||||
|
$search.on('blur focus', function() {
|
||||||
|
if ($search.val() === '') {
|
||||||
|
$search.toggleClass('gray black');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
.packages_info_container
|
||||||
|
%h3= t('layout.advisories.affected_in')
|
||||||
|
%ul.platforms
|
||||||
|
- @packages_info.each_pair do |platform, projects|
|
||||||
|
%li
|
||||||
|
%p= raw "#{t('activerecord.models.platform')} #{ link_to platform.name, platform_path(platform) }"
|
||||||
|
%ul
|
||||||
|
- projects.each_pair do |project, packages|
|
||||||
|
%li
|
||||||
|
%p= raw "#{ t('activerecord.models.project') } #{ link_to project.name, project_path(project) }"
|
||||||
|
%ul
|
||||||
|
%li
|
||||||
|
%p= "SRPM:"
|
||||||
|
%ul
|
||||||
|
%li= packages[:srpm]
|
||||||
|
%li
|
||||||
|
%p= "RPM:"
|
||||||
|
%ul
|
||||||
|
- packages[:rpm].each do |package|
|
||||||
|
%li= package
|
|
@ -0,0 +1,14 @@
|
||||||
|
atom_feed do |feed|
|
||||||
|
feed.title(t("layout.advisories.atom_title"))
|
||||||
|
feed.updated(@advisories.first.created_at) if @advisories.length > 0
|
||||||
|
|
||||||
|
@advisories.each do |advisory|
|
||||||
|
feed.entry(advisory, :url => advisory_url(advisory)) do |entry|
|
||||||
|
content = raw(render(:inline => true, :partial => 'feed_partial', :locals => { :advisory => advisory }))
|
||||||
|
|
||||||
|
entry.title("#{t("activerecord.models.advisory")} #{advisory.advisory_id}")
|
||||||
|
entry.content(content, :type => 'html')
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,8 @@
|
||||||
- set_meta_tags :title => t('layout.advisories.list_header')
|
- set_meta_tags :title => t('layout.advisories.list_header')
|
||||||
- render :partial => 'submenu'
|
- render :partial => 'submenu'
|
||||||
|
%h3.fix
|
||||||
|
= t("layout.advisories.list_header")
|
||||||
|
= link_to image_tag("rss.ico", :width => '15px', :height => '15px', :class => 'atom_icon'),
|
||||||
|
APP_CONFIG['anonymous_access'] ? advisories_path(:format => 'atom') : advisories_path(:format => 'atom', :token => current_user.authentication_token)
|
||||||
= render :partial => 'list', :object => @advisories
|
= render :partial => 'list', :object => @advisories
|
||||||
= will_paginate @advisories
|
= will_paginate @advisories
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
%h3= "#{t("activerecord.models.advisory")} #{@advisory.advisory_id}".html_safe
|
%h3= "#{t("activerecord.models.advisory")} #{@advisory.advisory_id}".html_safe
|
||||||
|
|
||||||
.leftlist= "#{t("layout.advisories.project_name")}:".html_safe
|
.leftlist= "#{t("layout.advisories.project_names")}:".html_safe
|
||||||
.rightlist= link_to @advisory.project.name, project_path(@advisory.project)
|
.rightlist
|
||||||
|
= raw @advisory.projects.map{ |p| link_to p.name_with_owner, project_path(p) }.join(', ')
|
||||||
.both
|
.both
|
||||||
|
|
||||||
.leftlist= "#{t("activerecord.attributes.advisory.created_at")}:".html_safe
|
.leftlist= "#{t("activerecord.attributes.advisory.created_at")}:".html_safe
|
||||||
|
@ -33,5 +34,12 @@
|
||||||
%br
|
%br
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
.leftlist= "#{t("layout.advisories.build_lists")}:".html_safe
|
||||||
|
.rightlist
|
||||||
|
= raw @advisory.build_lists.map{ |bl| link_to bl.id, build_list_path(bl) }.join(', ')
|
||||||
|
.both
|
||||||
|
|
||||||
|
= render :partial => 'packages_info'
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$('article .all').addClass('bigpadding');
|
$('article .all').addClass('bigpadding');
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
%span#niceCheckbox1.niceCheck-main= check_box_tag "user_remove[#{user.id}][]"
|
%span#niceCheckbox1.niceCheck-main= check_box_tag "user_remove[#{user.id}][]"
|
||||||
%td
|
%td
|
||||||
.img= image_tag avatar_url(user)
|
.img= image_tag avatar_url(user)
|
||||||
.forimg= link_to user.name, user_path(user)
|
.forimg= link_to user.fullname, user_path(user)
|
||||||
- Relation::ROLES.each_with_index do |role, i|
|
- Relation::ROLES.each_with_index do |role, i|
|
||||||
%td
|
%td
|
||||||
.radio= radio_button_tag "user[#{user.id}]", role, ((parent.actors.exists? :actor_id => user.id, :actor_type => 'User', :role => role) ? :checked : nil), :class => 'niceRadio'
|
.radio= radio_button_tag "user[#{user.id}]", role, ((parent.actors.exists? :actor_id => user.id, :actor_type => 'User', :role => role) ? :checked : nil), :class => 'niceRadio'
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
= link_to t("layout.platforms.about"), platform_path(@platform)
|
= link_to t("layout.platforms.about"), platform_path(@platform)
|
||||||
%li{:class => (contr == :repositories) ? 'active' : ''}
|
%li{:class => (contr == :repositories) ? 'active' : ''}
|
||||||
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
|
= link_to t("layout.repositories.list_header"), platform_repositories_path(@platform)
|
||||||
- if can? :mass_builds, @platform
|
- if can? :edit, @platform
|
||||||
%li{:class => (contr == :platforms && [:mass_builds, :build_all].include?(act)) ? 'active' : ''}
|
%li{:class => (contr == :mass_builds && [:index, :create].include?(act)) ? 'active' : ''}
|
||||||
= link_to t("layout.platforms.mass_build"), mass_builds_platform_path(@platform)
|
= link_to t("layout.platforms.mass_build"), platform_mass_builds_path(@platform)
|
||||||
- if can? :read, @platform.products.build
|
- if can? :read, @platform.products.build
|
||||||
%li{:class => (contr == :products) ? 'active' : ''}
|
%li{:class => (contr == :products) ? 'active' : ''}
|
||||||
= link_to t("layout.products.list_header"), platform_products_path(@platform)
|
= link_to t("layout.products.list_header"), platform_products_path(@platform)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
= render 'submenu'
|
= render 'platforms/base/submenu'
|
||||||
= render 'sidebar'
|
= render 'platforms/base/sidebar'
|
||||||
|
|
||||||
= form_for :build, :url => build_all_platform_path(@platform), :html => { :class => 'form mass_build', :method => :post } do |f|
|
= form_for :build, :url => platform_mass_builds_path(@platform), :html => { :class => 'form mass_build', :method => :post } do |f|
|
||||||
%section.left
|
%section.left
|
||||||
%h3= t("layout.mass_builds.repositories")
|
%h3= t("layout.mass_builds.repositories")
|
||||||
- @platform.repositories.each do |rep|
|
- @platform.repositories.each do |rep|
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
%th.lpadding16= t('activerecord.attributes.mass_build.name')
|
%th.lpadding16= t('activerecord.attributes.mass_build.name')
|
||||||
%th.lpadding16= t("layout.mass_builds.statuses")
|
%th.lpadding16= t("layout.mass_builds.statuses")
|
||||||
%th.lpadding16= t("layout.mass_builds.failed_builds_list")
|
%th.lpadding16= t("layout.mass_builds.failed_builds_list")
|
||||||
|
%th.lpadding16= t("layout.mass_builds.cancel_mass_build")
|
||||||
%th.lpadding16= t("layout.mass_builds.extended_data")
|
%th.lpadding16= t("layout.mass_builds.extended_data")
|
||||||
- @mass_builds.each do |mass_build|
|
- @mass_builds.each do |mass_build|
|
||||||
%tr
|
%tr
|
||||||
|
@ -39,16 +40,20 @@
|
||||||
%td= link_to mass_build.name, build_lists_path(:filter => {:mass_build_id => mass_build.id})
|
%td= link_to mass_build.name, build_lists_path(:filter => {:mass_build_id => mass_build.id})
|
||||||
%td.min_width_120
|
%td.min_width_120
|
||||||
- MassBuild::COUNT_STATUSES.each do |status|
|
- MassBuild::COUNT_STATUSES.each do |status|
|
||||||
= link_to t("layout.build_lists.statuses.#{status}") + ": ", build_lists_path(:filter => {:status => status, :mass_build_id => mass_build.id})
|
= link_to t("layout.build_lists.statuses.#{status}") + ": ", build_lists_path(:filter => {:mass_build_id => mass_build.id, :ownership => 'index'}.merge(status != :build_lists ? {:status => BuildList.status_by_human(status)} : {}))
|
||||||
= mass_build.read_attribute "#{status}_count"
|
= mass_build.read_attribute "#{status}_count"
|
||||||
.both
|
.both
|
||||||
%td= link_to t("layout.mass_builds.failed_builds_list"), failed_builds_list_platforms_path(:mass_build_id => mass_build.id), :target => "_blank"
|
%td= link_to t("layout.mass_builds.failed_builds_list"), failed_builds_list_platform_mass_build_path(@platform, mass_build.id), :target => "_blank" if can?(:failed_builds_list, mass_build)
|
||||||
|
%td= link_to image_tag('x.png'), cancel_platform_mass_build_path(@platform, mass_build.id), :method => :post, :confirm => t("layout.mass_builds.cancel_confirm") if can?(:cancel, mass_build)
|
||||||
%td
|
%td
|
||||||
%a.toggle_btn{:href => "#toggle_#{ mass_build.id }", :'data-target' => "#toggle_#{ mass_build.id }"}= t("layout.mass_builds.extended_data")
|
%a.toggle_btn{:href => "#toggle_#{ mass_build.id }", :'data-target' => "#toggle_#{ mass_build.id }"}= t("layout.mass_builds.extended_data")
|
||||||
.toggle{:id => "toggle_#{ mass_build.id }"}
|
.toggle{:id => "toggle_#{ mass_build.id }"}
|
||||||
= t('activerecord.attributes.mass_build.arch_names') + ": "
|
= t('activerecord.attributes.mass_build.arch_names') + ": "
|
||||||
= mass_build.arch_names
|
= mass_build.arch_names
|
||||||
.both
|
.both
|
||||||
|
= t('activerecord.attributes.mass_build.rep_names') + ": "
|
||||||
|
= mass_build.rep_names
|
||||||
|
.both
|
||||||
= t('activerecord.attributes.mass_build.user') + ": "
|
= t('activerecord.attributes.mass_build.user') + ": "
|
||||||
= link_to mass_build.user.fullname, mass_build.user
|
= link_to mass_build.user.fullname, mass_build.user
|
||||||
.both
|
.both
|
|
@ -5,8 +5,8 @@
|
||||||
"aaData": [
|
"aaData": [
|
||||||
<% @projects.each do |project| %>
|
<% @projects.each do |project| %>
|
||||||
[
|
[
|
||||||
"<%=j link_to("#{project.owner.respond_to?(:uname) ? project.owner.uname : project.owner.name} / #{project.name}", project) %>",
|
"<%=j link_to(project.name_with_owner, project) %>",
|
||||||
"<%= truncate(project.description || '', :length => 60).gsub("\n", ' ').gsub("\r", ' ') %>",
|
"<%= truncate(project.description || '', :length => 60).gsub(/\n|\r|\t/, ' ') %>",
|
||||||
"<%=j link_to t("layout.add"), url_for(:controller => :repositories, :action => :add_project, :project_id => project.id) %>"
|
"<%=j link_to t("layout.add"), url_for(:controller => :repositories, :action => :add_project, :project_id => project.id) %>"
|
||||||
]<%= project == @projects.last ? '' : ',' %>
|
]<%= project == @projects.last ? '' : ',' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
j(link_to("#{project.owner.respond_to?(:uname) ? project.owner.uname : project.owner.name} / #{project.name}", project)) +
|
j(link_to("#{project.owner.respond_to?(:uname) ? project.owner.uname : project.owner.name} / #{project.name}", project)) +
|
||||||
"</div>").html_safe
|
"</div>").html_safe
|
||||||
%>",
|
%>",
|
||||||
"<%= truncate(project.description || '', :length => 60).gsub("\n", ' ').gsub("\r", ' ') %>",
|
"<%= truncate(project.description || '', :length => 60).gsub(/\n|\r|\t/, ' ') %>",
|
||||||
"<%=
|
"<%=
|
||||||
if can? :remove_project, @repository
|
if can? :remove_project, @repository
|
||||||
j(link_to('<span class="delete"> </span>'.html_safe,
|
j(link_to('<span class="delete"> </span>'.html_safe,
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
%tr{:id => "row#{build_list_counter}", :class => "#{build_list_status_color(build_list.status)}"}
|
%tr{:id => "row#{build_list_counter}", :class => "#{build_list_status_color(build_list.status)}"}
|
||||||
%td= link_to (build_list.bs_id.present? ? build_list.bs_id : t("layout.build_lists.bs_id_not_set")), build_list
|
%td= link_to (build_list.bs_id.present? ? build_list.bs_id : t("layout.build_lists.bs_id_not_set")), build_list
|
||||||
%td= build_list.mass_build_id ? link_to(build_list.mass_build.name, mass_builds_platform_path(build_list.save_to_platform)) : ""
|
|
||||||
%td= build_list.human_status
|
%td= build_list.human_status
|
||||||
%td= link_to build_list.project.name, build_list.project
|
%td= link_to build_list.project.name_with_owner, build_list.project
|
||||||
%td= link_to build_list.project_version, "#"
|
%td= build_list_version_link(build_list)
|
||||||
|
%td= link_to build_list.save_to_platform.name, build_list.save_to_platform
|
||||||
%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 can?(:cancel, build_list)
|
|
||||||
%td= build_list.updated_at
|
|
||||||
|
|
|
@ -37,14 +37,15 @@
|
||||||
%br
|
%br
|
||||||
= f.submit t("layout.search.header")
|
= f.submit t("layout.search.header")
|
||||||
.block
|
.block
|
||||||
%h3.small= t("activerecord.attributes.build_list.mass_build")
|
|
||||||
.lineForm.aside= f.select :mass_build_id, options_from_collection_for_select( MassBuild.all, :id, :name, @filter.mass_build_id ), {:include_blank => true}
|
|
||||||
%h3.small= t("activerecord.attributes.build_list.status")
|
%h3.small= t("activerecord.attributes.build_list.status")
|
||||||
.lineForm.aside= f.select :status, BuildList::STATUSES.collect{|status| [BuildList.human_status(status), status]}, {:include_blank => true, :selected => @filter.status}, {:class => 'sel80 aside', :id => 'status', :tabindex => 2}
|
.lineForm.aside= f.select :status, BuildList::STATUSES.collect{|status| [BuildList.human_status(status), status]}, {:include_blank => true, :selected => @filter.status}, {:class => 'sel80 aside', :id => 'status', :tabindex => 2}
|
||||||
%h3.small= t("activerecord.attributes.build_list.is_circle")
|
%h3.small= t("activerecord.models.platform")
|
||||||
.lineForm.aside= f.select :is_circle, [[t("layout.yes_"), 1], [t("layout.no_"), 0]], {:include_blank => true, :selected => @filter.is_circle.present? ? (@filter.is_circle ? "1" : "0") : nil}, {:class => 'sel80 aside', :id => 'recurrent', :tabindex => 2}
|
.lineForm.aside= f.select :platform_id, Platform.main.collect{|pl| [pl.name, pl.id]}, {:include_blank => true, :selected => @filter.platform_id}, {:class => 'sel80 aside', :id => 'platform', :tabindex => 2}
|
||||||
|
%h3.small= t("activerecord.attributes.build_list.mass_build")
|
||||||
|
.lineForm.aside= f.select :mass_build_id, options_from_collection_for_select( MassBuild.all, :id, :name, @filter.mass_build_id ), {:include_blank => true}
|
||||||
%h3.small= t("activerecord.attributes.build_list.arch")
|
%h3.small= t("activerecord.attributes.build_list.arch")
|
||||||
.lineForm.aside= f.select :arch_id, Arch.recent.collect{|arch| [arch.name, arch.id]}, {:include_blank => true, :selected => @filter.arch_id}, {:class => 'sel80 aside', :id => 'architecture', :tabindex => 2}
|
.lineForm.aside= f.select :arch_id, Arch.recent.collect{|arch| [arch.name, arch.id]}, {:include_blank => true, :selected => @filter.arch_id}, {:class => 'sel80 aside', :id => 'architecture', :tabindex => 2}
|
||||||
|
-# TODO [BuildList#created_at filters] Uncomment here and in BuildList::Filter to return filters
|
||||||
%h3.small= t("layout.build_lists.created_at_start")
|
%h3.small= t("layout.build_lists.created_at_start")
|
||||||
.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")
|
||||||
|
|
|
@ -4,14 +4,12 @@
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.bs_id")
|
%th.lpadding16= t("activerecord.attributes.build_list.bs_id")
|
||||||
%th.lpadding16= t('activerecord.attributes.build_list.mass_build_id')
|
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.status")
|
%th.lpadding16= t("activerecord.attributes.build_list.status")
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.project")
|
%th.lpadding16= t("activerecord.attributes.build_list.project")
|
||||||
%th.lpadding16= t("activerecord.attributes.build_list.project_version")
|
%th.lpadding16= t("activerecord.attributes.build_list.project_version")
|
||||||
|
%th.lpadding16= t("activerecord.attributes.build_list.save_to_platform")
|
||||||
%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.lpadding16= t("activerecord.attributes.build_list.updated_at")
|
|
||||||
%tbody= render :partial => 'projects/build_lists/build_list', :collection => @build_lists
|
%tbody= render :partial => 'projects/build_lists/build_list', :collection => @build_lists
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
- container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
|
- container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
|
||||||
= link_to container_url, container_url
|
= link_to container_url, container_url
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
.leftlist= t("activerecord.attributes.build_list.bs_id")
|
||||||
|
.rightlist= @build_list.bs_id.present? ? @build_list.bs_id : t("layout.build_lists.bs_id_not_set")
|
||||||
|
.both
|
||||||
.leftlist= t("activerecord.attributes.build_list.user")
|
.leftlist= t("activerecord.attributes.build_list.user")
|
||||||
.rightlist
|
.rightlist
|
||||||
= link_to @build_list.user.try(:fullname), @build_list.user
|
= link_to @build_list.user.try(:fullname), @build_list.user
|
||||||
|
@ -32,7 +36,7 @@
|
||||||
.leftlist= t("activerecord.attributes.build_list.update_type")
|
.leftlist= t("activerecord.attributes.build_list.update_type")
|
||||||
.rightlist
|
.rightlist
|
||||||
- if @build_list.can_publish? and can?(:publish, @build_list)
|
- if @build_list.can_publish? and can?(:publish, @build_list)
|
||||||
= f.select :update_type, options_for_select(BuildList::RELEASE_UPDATE_TYPES, @build_list.update_type)
|
= f.select :update_type, options_for_select(build_list_classified_update_types, @build_list.update_type)
|
||||||
- else
|
- else
|
||||||
= @build_list.update_type
|
= @build_list.update_type
|
||||||
.both
|
.both
|
||||||
|
@ -43,7 +47,7 @@
|
||||||
.rightlist= t("layout.#{@build_list.auto_publish}_")
|
.rightlist= t("layout.#{@build_list.auto_publish}_")
|
||||||
.both
|
.both
|
||||||
.leftlist= t("activerecord.attributes.build_list.project_version")
|
.leftlist= t("activerecord.attributes.build_list.project_version")
|
||||||
.rightlist= @build_list.project_version
|
.rightlist= build_list_version_link(@build_list, true)
|
||||||
.both
|
.both
|
||||||
.leftlist= t("activerecord.attributes.build_list.arch")
|
.leftlist= t("activerecord.attributes.build_list.arch")
|
||||||
.rightlist= @build_list.arch.name
|
.rightlist= @build_list.arch.name
|
||||||
|
@ -55,6 +59,12 @@
|
||||||
.rightlist= t("layout.#{@build_list.is_circle?}_")
|
.rightlist= t("layout.#{@build_list.is_circle?}_")
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
- if @build_list.mass_build_id.present?
|
||||||
|
.leftlist= t("activerecord.attributes.mass_build_id")
|
||||||
|
.rightlist= link_to @build_list.mass_build.name, platform_mass_builds_path(@build_list.save_to_platform)
|
||||||
|
.both
|
||||||
|
|
||||||
|
|
||||||
- if @build_list.advisory.present?
|
- if @build_list.advisory.present?
|
||||||
.leftlist= t("layout.build_lists.attached_advisory")
|
.leftlist= t("layout.build_lists.attached_advisory")
|
||||||
.rightlist= link_to @build_list.advisory.advisory_id, advisory_path(@build_list.advisory)
|
.rightlist= link_to @build_list.advisory.advisory_id, advisory_path(@build_list.advisory)
|
||||||
|
@ -71,12 +81,29 @@
|
||||||
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
|
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
- if @build_list.can_cancel? and can?(:cancel, @build_list)
|
||||||
|
= link_to t("layout.build_lists.cancel"), cancel_build_list_path(@build_list),
|
||||||
|
:method => :put, :confirm => t("layout.confirm"), :class => 'button'
|
||||||
|
|
||||||
- if @build_list.can_publish? and @build_list.save_to_platform.released and @build_list.advisory.nil?
|
- if @build_list.can_publish? and @build_list.save_to_platform.released and @build_list.advisory.nil?
|
||||||
#advisory_block
|
#advisory_block
|
||||||
.leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory")
|
.leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory")
|
||||||
.rightlist= select_tag :attach_advisory, advisories_select_options(@advisories)
|
.rightlist
|
||||||
|
= select_tag :attach_advisory, advisories_select_options(@advisories)
|
||||||
|
%p.hint_text= t("layout.advisories.publication_info", :update_types => BuildList::RELEASE_UPDATE_TYPES.join(', '))
|
||||||
.both
|
.both
|
||||||
|
|
||||||
|
#advisory_search_block
|
||||||
|
%h3= t("layout.advisories.search_by_id")
|
||||||
|
.leftlist= label_tag :advisory_search, t("layout.advisories.search_hint")
|
||||||
|
.rightlist
|
||||||
|
%input#advisory_search{:type => 'text'}
|
||||||
|
%p.hint_text= t("layout.advisories.advisory_id_info", :advisory_format => advisory_id_for_hint)
|
||||||
|
.both
|
||||||
|
- %w(advisory_not_found server_error continue_input).each do |el|
|
||||||
|
.info{:class => el}
|
||||||
|
%p= t("layout.advisories.banners.#{el}")
|
||||||
|
|
||||||
#new_advisory_form
|
#new_advisory_form
|
||||||
= f.fields_for @build_list.build_advisory do |f|
|
= f.fields_for @build_list.build_advisory do |f|
|
||||||
= render :partial => 'advisories/form', :locals => {:f => f}
|
= render :partial => 'advisories/form', :locals => {:f => f}
|
||||||
|
@ -91,11 +118,8 @@
|
||||||
.leftlist= t("activerecord.attributes.advisory.references")
|
.leftlist= t("activerecord.attributes.advisory.references")
|
||||||
.rightlist.refs
|
.rightlist.refs
|
||||||
.both
|
.both
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$(function() {
|
$(function() {
|
||||||
Rosa.bootstrapedData.advisories = #{ render 'advisories/advisories.json.jbuilder',
|
|
||||||
:advisories => @advisories };
|
|
||||||
var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
|
var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -107,7 +131,6 @@
|
||||||
- if @item_groups.blank?
|
- if @item_groups.blank?
|
||||||
%h4.nomargin= t("layout.build_lists.no_items_data")
|
%h4.nomargin= t("layout.build_lists.no_items_data")
|
||||||
- @item_groups.each_with_index do |group, level|
|
- @item_groups.each_with_index do |group, level|
|
||||||
-#%h4.nomargin= "#{group} ##{level}"
|
|
||||||
- group.each do |item|
|
- group.each do |item|
|
||||||
%h4.nomargin= "#{item.name} ##{level}"
|
%h4.nomargin= "#{item.name} ##{level}"
|
||||||
%table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"}
|
%table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"}
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
%td
|
%td
|
||||||
= link_to project do
|
= link_to project do
|
||||||
.table-sort-left= image_tag visibility_icon(project.visibility)
|
.table-sort-left= image_tag visibility_icon(project.visibility)
|
||||||
.table-sort-right
|
.table-sort-right= link_to project.name_with_owner, project_path(project)
|
||||||
= link_to project.owner.uname, project.owner.class == User ? user_path(project.owner) : group_path(project.owner) #{project.owner.uname} / #{project.name}
|
|
||||||
#{ ' / ' }
|
|
||||||
= link_to project.name, project_path(project)
|
|
||||||
%td.td2= project.description
|
%td.td2= project.description
|
||||||
- alone_member = alone_member? project
|
- alone_member = alone_member? project
|
||||||
%td
|
%td
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
json.project do |proj|
|
json.project do |proj|
|
||||||
proj.visibility project.visibility.to_s
|
proj.visibility project.visibility.to_s
|
||||||
|
|
||||||
proj.name project.name
|
proj.name project.name_with_owner
|
||||||
proj.description project.description
|
proj.description project.description
|
||||||
proj.link project_path(project)
|
proj.link project_path(project)
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,10 @@
|
||||||
|
|
||||||
var image = '<img alt="' + project.visibility + '" src="' + icons.visibilities[project.visibility] + '" />';
|
var image = '<img alt="' + project.visibility + '" src="' + icons.visibilities[project.visibility] + '" />';
|
||||||
|
|
||||||
var owner = '<a href="' + project.owner.link + '">' + project.owner.name + '</a>';
|
|
||||||
var project = '<a href="' + project.link + '">' + project.name + '</a>';
|
var project = '<a href="' + project.link + '">' + project.name + '</a>';
|
||||||
|
|
||||||
return '<div class="table-sort-left">' + image + "</div>\n" +
|
return '<div class="table-sort-left">' + image + "</div>\n" +
|
||||||
'<div class="table-sort-right">' + owner + ' / ' + project + '<div>';
|
'<div class="table-sort-right">' + project + '<div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var thirdColumn = function(row) {
|
var thirdColumn = function(row) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ en:
|
||||||
read_access: read-only
|
read_access: read-only
|
||||||
|
|
||||||
by: by
|
by: by
|
||||||
|
clear: Clear
|
||||||
|
|
||||||
remove: Remove
|
remove: Remove
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ ru:
|
||||||
read_access: только чтение
|
read_access: только чтение
|
||||||
|
|
||||||
by: ''
|
by: ''
|
||||||
|
clear: Очистить
|
||||||
|
|
||||||
remove: Убрать
|
remove: Убрать
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ en:
|
||||||
header: Search
|
header: Search
|
||||||
advanced: Advanced search
|
advanced: Advanced search
|
||||||
all: Show All
|
all: Show All
|
||||||
|
no_results: Nothing found for "%{query}".
|
||||||
types:
|
types:
|
||||||
all: All
|
all: All
|
||||||
projects: Projects
|
projects: Projects
|
||||||
|
|
|
@ -4,6 +4,7 @@ ru:
|
||||||
header: Поиск
|
header: Поиск
|
||||||
advanced: Расширенный поиск
|
advanced: Расширенный поиск
|
||||||
all: Показать все
|
all: Показать все
|
||||||
|
no_results: По запросу "%{query}" ничего не найдено.
|
||||||
types:
|
types:
|
||||||
all: Все
|
all: Все
|
||||||
projects: Проекты
|
projects: Проекты
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
en:
|
en:
|
||||||
layout:
|
layout:
|
||||||
advisories:
|
advisories:
|
||||||
|
atom_header: Advisories
|
||||||
list_header: Advisories
|
list_header: Advisories
|
||||||
form_header: New advisory
|
form_header: New advisory
|
||||||
project_name: Project
|
project_name: Project
|
||||||
|
project_names: Projects
|
||||||
|
build_lists: Build Lists
|
||||||
affected_versions: Affected versions
|
affected_versions: Affected versions
|
||||||
|
affected_in: Affected in
|
||||||
ref_comment: Add links one by row
|
ref_comment: Add links one by row
|
||||||
no_: No
|
no_: No
|
||||||
new: New
|
new: New
|
||||||
|
existing: Existing
|
||||||
|
search_by_id: Search advisory by it's ID
|
||||||
|
search_hint: Paste full AdvisoryID into text field or enter there its uniq part.
|
||||||
|
advisory_id_info: AdvisoryID is a string %{advisory_format}, where 'XXXX' (at least 4 symbols) is a uniq part.
|
||||||
|
publication_info: Advisory might be applied only to Build Lists with [%{update_types}] update types.
|
||||||
|
|
||||||
|
banners:
|
||||||
|
advisory_not_found: Couldn't find advisory with given ID for this type of Build List.
|
||||||
|
server_error: Server problem. Please try again later.
|
||||||
|
continue_input: Continue input while needed Advisory appears in preview.
|
||||||
|
|
||||||
flash:
|
flash:
|
||||||
advisories:
|
advisories:
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
ru:
|
ru:
|
||||||
layout:
|
layout:
|
||||||
advisories:
|
advisories:
|
||||||
|
atom_title: Бюллетени
|
||||||
list_header: Бюллетени
|
list_header: Бюллетени
|
||||||
form_header: Новый бюллетень
|
form_header: Новый бюллетень
|
||||||
project_name: Проект
|
project_name: Проект
|
||||||
|
project_names: Проекты
|
||||||
|
build_lists: Сборочные листы
|
||||||
affected_versions: Применен в версиях
|
affected_versions: Применен в версиях
|
||||||
|
affected_in: Применен в
|
||||||
ref_comment: Вставляйте ссылки по одной на строку
|
ref_comment: Вставляйте ссылки по одной на строку
|
||||||
no_: Нет
|
no_: Нет
|
||||||
new: Новый
|
new: Новый
|
||||||
|
existing: Существующий
|
||||||
|
search_by_id: Искать бюллетень по его ID
|
||||||
|
search_hint: Скопируйте в поле ввода полный AdvisoryID или введите его уникальную часть
|
||||||
|
advisory_id_info: AdvisoryID имеет формат %{advisory_format}, где 'XXXX' (минимум 4 символа) - это уникальная часть.
|
||||||
|
publication_info: Бюллетень может быть присоединен только к сборочному листу с типами обновления %{update_types}.
|
||||||
|
|
||||||
|
banners:
|
||||||
|
advisory_not_found: Не удалось найти запрашиваемый бюллетень для сборочного листа этого типа.
|
||||||
|
server_error: Произошла ошибка сервера. Попробуйте позже.
|
||||||
|
continue_input: Продолжайте вводить ID до тех пор, пока не найдется нужный бюллетень.
|
||||||
|
|
||||||
flash:
|
flash:
|
||||||
advisories:
|
advisories:
|
||||||
|
|
|
@ -18,8 +18,8 @@ en:
|
||||||
additional_repos: Additional repositories
|
additional_repos: Additional repositories
|
||||||
include_repos: Included repositories
|
include_repos: Included repositories
|
||||||
created_at: Created on
|
created_at: Created on
|
||||||
save_to_platform: Repository for package storage
|
save_to_platform: Platform
|
||||||
build_for_platform: Platform
|
build_for_platform: Build for platform
|
||||||
update_type: Update type
|
update_type: Update type
|
||||||
build_requires: Build with all the required packages
|
build_requires: Build with all the required packages
|
||||||
auto_publish: Automated publising
|
auto_publish: Automated publising
|
||||||
|
@ -58,6 +58,7 @@ en:
|
||||||
packages_header: Container data
|
packages_header: Container data
|
||||||
no_items_data: No data
|
no_items_data: No data
|
||||||
show: Show
|
show: Show
|
||||||
|
cancel: Cancel build
|
||||||
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'
|
||||||
|
|
|
@ -18,8 +18,8 @@ ru:
|
||||||
additional_repos: Дополнительные репозитории
|
additional_repos: Дополнительные репозитории
|
||||||
include_repos: Подключаемые репозитории
|
include_repos: Подключаемые репозитории
|
||||||
created_at: Создан
|
created_at: Создан
|
||||||
save_to_platform: Репозиторий для сохранения пакетов
|
save_to_platform: Платформа
|
||||||
build_for_platform: Платформа
|
build_for_platform: Собрано для платформы
|
||||||
update_type: Критичность обновления
|
update_type: Критичность обновления
|
||||||
build_requires: Пересборка с зависимостями
|
build_requires: Пересборка с зависимостями
|
||||||
auto_publish: Автоматическая публикация
|
auto_publish: Автоматическая публикация
|
||||||
|
@ -57,6 +57,7 @@ ru:
|
||||||
packages_header: Данные о контейнере
|
packages_header: Данные о контейнере
|
||||||
no_items_data: Данных нет
|
no_items_data: Данных нет
|
||||||
show: Просмотр
|
show: Просмотр
|
||||||
|
cancel: Отменить сборку
|
||||||
cancel_success: 'Сборка отменена.'
|
cancel_success: 'Сборка отменена.'
|
||||||
cancel_fail: 'При отмене сборки произошла ошибка!'
|
cancel_fail: 'При отмене сборки произошла ошибка!'
|
||||||
publish_success: 'Сборка поставлена в очередь на публикацию.'
|
publish_success: 'Сборка поставлена в очередь на публикацию.'
|
||||||
|
|
|
@ -5,6 +5,8 @@ en:
|
||||||
extended_data: Extended data
|
extended_data: Extended data
|
||||||
failed_builds_list: Failed Builds List
|
failed_builds_list: Failed Builds List
|
||||||
statuses: Statuses
|
statuses: Statuses
|
||||||
|
cancel_mass_build: Cancel
|
||||||
|
cancel_confirm: Are you sure you want to cancel mass build?
|
||||||
activerecord:
|
activerecord:
|
||||||
models:
|
models:
|
||||||
mass_build: Mass Build
|
mass_build: Mass Build
|
||||||
|
@ -18,3 +20,4 @@ en:
|
||||||
user: User
|
user: User
|
||||||
auto_publish: Auto Publish
|
auto_publish: Auto Publish
|
||||||
repositories: Repositories
|
repositories: Repositories
|
||||||
|
rep_names: Repositories
|
||||||
|
|
|
@ -5,6 +5,8 @@ ru:
|
||||||
extended_data: Параметры задания
|
extended_data: Параметры задания
|
||||||
failed_builds_list: Список ошибок сборок
|
failed_builds_list: Список ошибок сборок
|
||||||
statuses: Статусы
|
statuses: Статусы
|
||||||
|
cancel_mass_build: Отмена
|
||||||
|
cancel_confirm: Вы уверены, что хотите отменить массовую сборку?
|
||||||
activerecord:
|
activerecord:
|
||||||
models:
|
models:
|
||||||
mass_build: Массовая Сборка
|
mass_build: Массовая Сборка
|
||||||
|
@ -18,3 +20,4 @@ ru:
|
||||||
user: Пользователь
|
user: Пользователь
|
||||||
auto_publish: Авто Публикация
|
auto_publish: Авто Публикация
|
||||||
repositories: Репозитории
|
repositories: Репозитории
|
||||||
|
rep_names: Репозитории
|
||||||
|
|
|
@ -59,6 +59,7 @@ en:
|
||||||
destroyed: Platform deleted
|
destroyed: Platform deleted
|
||||||
build_all_success: All project build in progress
|
build_all_success: All project build in progress
|
||||||
build_all_error: Mass build failed
|
build_all_error: Mass build failed
|
||||||
|
cancel_mass_build: Mass build canceled
|
||||||
clone_success: Cloned successfully
|
clone_success: Cloned successfully
|
||||||
members:
|
members:
|
||||||
already_added: "%{name} is already a member of platform"
|
already_added: "%{name} is already a member of platform"
|
||||||
|
|
|
@ -59,6 +59,7 @@ ru:
|
||||||
destroyed: Платформа успешно удалена
|
destroyed: Платформа успешно удалена
|
||||||
build_all_success: Все проекты успешно отправлены на сборку
|
build_all_success: Все проекты успешно отправлены на сборку
|
||||||
build_all_error: Сборка не удалась!
|
build_all_error: Сборка не удалась!
|
||||||
|
cancel_mass_build: Массовая сборка отменена
|
||||||
clone_success: Клонирование успешно
|
clone_success: Клонирование успешно
|
||||||
members:
|
members:
|
||||||
already_added: "%{name} уже является участником платформы"
|
already_added: "%{name} уже является участником платформы"
|
||||||
|
|
|
@ -38,7 +38,9 @@ Rosa::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :advisories, :only => [:index, :show]
|
resources :advisories, :only => [:index, :show, :search] do
|
||||||
|
get :search, :on => :collection
|
||||||
|
end
|
||||||
|
|
||||||
scope :module => 'platforms' do
|
scope :module => 'platforms' do
|
||||||
resources :platforms do
|
resources :platforms do
|
||||||
|
@ -51,13 +53,16 @@ Rosa::Application.routes.draw do
|
||||||
delete :remove_member
|
delete :remove_member
|
||||||
post :add_member
|
post :add_member
|
||||||
post :make_clone
|
post :make_clone
|
||||||
post :build_all
|
|
||||||
get :mass_builds
|
|
||||||
get :advisories
|
get :advisories
|
||||||
end
|
end
|
||||||
collection do
|
|
||||||
|
resources :mass_builds, :only => [:create, :index] do
|
||||||
|
member do
|
||||||
get :failed_builds_list
|
get :failed_builds_list
|
||||||
|
post :cancel
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
get :autocomplete_user_uname, :on => :collection
|
get :autocomplete_user_uname, :on => :collection
|
||||||
resources :repositories do
|
resources :repositories do
|
||||||
member do
|
member do
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
class AddManyProjectsToAdvisories < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
create_table :advisories_projects, :id => false do |t|
|
||||||
|
t.integer :advisory_id
|
||||||
|
t.integer :project_id
|
||||||
|
end
|
||||||
|
add_index :advisories_projects, :advisory_id
|
||||||
|
add_index :advisories_projects, :project_id
|
||||||
|
add_index :advisories_projects, [:advisory_id, :project_id], :name => :advisory_project_index, :unique => true
|
||||||
|
|
||||||
|
Advisory.find_in_batches do |b|
|
||||||
|
b.each do |advisory|
|
||||||
|
advisory.projects << Project.find(advisory.project_id)
|
||||||
|
advisory.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
change_table :advisories do |t|
|
||||||
|
t.remove :project_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
change_table :advisories do |t|
|
||||||
|
t.integer :project_id
|
||||||
|
end
|
||||||
|
|
||||||
|
Advisory.find_in_batches do |b|
|
||||||
|
b.each do |advisory|
|
||||||
|
advisory.project_id = advisory.projects.first.id
|
||||||
|
advisory.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_index :advisories_projects, :column => :advisory_id
|
||||||
|
remove_index :advisories_projects, :column => :project_id
|
||||||
|
remove_index :advisories_projects, :name => :advisory_project_index
|
||||||
|
drop_table :advisories_projects
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddRepNamesToMassBuilds < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :mass_builds, :rep_names, :string
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddStopBuildToMassBuilds < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :mass_builds, :stop_build, :boolean, :null => false, :default => false
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
class AddNullFalseToMassBuildsCounters < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
change_column :mass_builds, :build_lists_count, :integer, :default => 0, :null => false
|
||||||
|
change_column :mass_builds, :build_published_count, :integer, :default => 0, :null => false
|
||||||
|
change_column :mass_builds, :build_pending_count, :integer, :default => 0, :null => false
|
||||||
|
change_column :mass_builds, :build_started_count, :integer, :default => 0, :null => false
|
||||||
|
change_column :mass_builds, :build_publish_count, :integer, :default => 0, :null => false
|
||||||
|
change_column :mass_builds, :build_error_count, :integer, :default => 0, :null => false
|
||||||
|
end
|
||||||
|
end
|
27
db/schema.rb
27
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 => 20120628165702) do
|
ActiveRecord::Schema.define(:version => 20120703101719) 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
|
||||||
|
@ -23,7 +23,6 @@ ActiveRecord::Schema.define(:version => 20120628165702) do
|
||||||
|
|
||||||
create_table "advisories", :force => true do |t|
|
create_table "advisories", :force => true do |t|
|
||||||
t.string "advisory_id"
|
t.string "advisory_id"
|
||||||
t.integer "project_id"
|
|
||||||
t.text "description", :default => ""
|
t.text "description", :default => ""
|
||||||
t.text "references", :default => ""
|
t.text "references", :default => ""
|
||||||
t.text "update_type", :default => ""
|
t.text "update_type", :default => ""
|
||||||
|
@ -32,7 +31,6 @@ ActiveRecord::Schema.define(:version => 20120628165702) do
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "advisories", ["advisory_id"], :name => "index_advisories_on_advisory_id", :unique => true
|
add_index "advisories", ["advisory_id"], :name => "index_advisories_on_advisory_id", :unique => true
|
||||||
add_index "advisories", ["project_id"], :name => "index_advisories_on_project_id"
|
|
||||||
add_index "advisories", ["update_type"], :name => "index_advisories_on_update_type"
|
add_index "advisories", ["update_type"], :name => "index_advisories_on_update_type"
|
||||||
|
|
||||||
create_table "advisories_platforms", :id => false, :force => true do |t|
|
create_table "advisories_platforms", :id => false, :force => true do |t|
|
||||||
|
@ -44,6 +42,15 @@ ActiveRecord::Schema.define(:version => 20120628165702) do
|
||||||
add_index "advisories_platforms", ["advisory_id", "platform_id"], :name => "advisory_platform_index", :unique => true
|
add_index "advisories_platforms", ["advisory_id", "platform_id"], :name => "advisory_platform_index", :unique => true
|
||||||
add_index "advisories_platforms", ["platform_id"], :name => "index_advisories_platforms_on_platform_id"
|
add_index "advisories_platforms", ["platform_id"], :name => "index_advisories_platforms_on_platform_id"
|
||||||
|
|
||||||
|
create_table "advisories_projects", :id => false, :force => true do |t|
|
||||||
|
t.integer "advisory_id"
|
||||||
|
t.integer "project_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index "advisories_projects", ["advisory_id"], :name => "index_advisories_projects_on_advisory_id"
|
||||||
|
add_index "advisories_projects", ["advisory_id", "project_id"], :name => "advisory_project_index", :unique => true
|
||||||
|
add_index "advisories_projects", ["project_id"], :name => "index_advisories_projects_on_project_id"
|
||||||
|
|
||||||
create_table "arches", :force => true do |t|
|
create_table "arches", :force => true do |t|
|
||||||
t.string "name", :null => false
|
t.string "name", :null => false
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
|
@ -204,12 +211,14 @@ ActiveRecord::Schema.define(:version => 20120628165702) do
|
||||||
t.string "arch_names"
|
t.string "arch_names"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.boolean "auto_publish", :default => false, :null => false
|
t.boolean "auto_publish", :default => false, :null => false
|
||||||
t.integer "build_lists_count", :default => 0
|
t.integer "build_lists_count", :default => 0, :null => false
|
||||||
t.integer "build_published_count", :default => 0
|
t.integer "build_published_count", :default => 0, :null => false
|
||||||
t.integer "build_pending_count", :default => 0
|
t.integer "build_pending_count", :default => 0, :null => false
|
||||||
t.integer "build_started_count", :default => 0
|
t.integer "build_started_count", :default => 0, :null => false
|
||||||
t.integer "build_publish_count", :default => 0
|
t.integer "build_publish_count", :default => 0, :null => false
|
||||||
t.integer "build_error_count", :default => 0
|
t.integer "build_error_count", :default => 0, :null => false
|
||||||
|
t.string "rep_names"
|
||||||
|
t.boolean "stop_build", :default => false, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "platforms", :force => true do |t|
|
create_table "platforms", :force => true do |t|
|
||||||
|
|
|
@ -10,6 +10,14 @@ module Modules
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
|
||||||
|
def name_with_owner
|
||||||
|
"#{owner.respond_to?(:uname) ? owner.uname : owner.name}/#{self.name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
# -*- encoding : utf-8 -*-
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
shared_examples_for 'mass_build platform owner' do
|
||||||
|
it 'should be able to perform index action' do
|
||||||
|
get :index, :platform_id => @platform
|
||||||
|
response.should render_template(:index)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be able to perform create action' do
|
||||||
|
post :create, @create_params
|
||||||
|
response.should redirect_to(platform_mass_builds_path(@platform))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be able to perform cancel action' do
|
||||||
|
post :cancel, :platform_id => @platform, :id => @mass_build
|
||||||
|
response.should redirect_to(platform_mass_builds_path(@platform))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should change stop_build on cancel' do
|
||||||
|
post :cancel, :platform_id => @platform, :id => @mass_build
|
||||||
|
@mass_build.reload.stop_build.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not be able to perform cancel action if stop_build is true' do
|
||||||
|
@mass_build.update_attribute(:stop_build, true)
|
||||||
|
post :cancel, :platform_id => @platform, :id => @mass_build
|
||||||
|
response.should redirect_to(forbidden_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should change objects count on create success' do
|
||||||
|
lambda { post :create, @create_params }.should change{ MassBuild.count }.by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for personal platform' do
|
||||||
|
before(:each) do
|
||||||
|
Platform.update_all("platform_type = 'personal'")
|
||||||
|
end
|
||||||
|
|
||||||
|
[:cancel, :failed_builds_list, :create].each do |action|
|
||||||
|
it "should not be able to perform #{ action } action" do
|
||||||
|
get action, :platform_id => @platform, :id => @mass_build.id
|
||||||
|
response.should redirect_to(forbidden_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples_for 'mass_build platform reader' do
|
||||||
|
[:index, :create].each do |action|
|
||||||
|
it "should not be able to perform #{ action } action" do
|
||||||
|
get action, :platform_id => @platform
|
||||||
|
response.should redirect_to(forbidden_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[:cancel, :failed_builds_list].each do |action|
|
||||||
|
it "should not be able to perform #{ action } action" do
|
||||||
|
get action, :platform_id => @platform, :id => @mass_build.id
|
||||||
|
response.should redirect_to(forbidden_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not change objects count on create success' do
|
||||||
|
lambda { post :create, @create_params }.should change{ MassBuild.count }.by(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not change stop_build on cancel' do
|
||||||
|
post :cancel, :platform_id => @platform, :id => @mass_build
|
||||||
|
@mass_build.reload.stop_build.should == false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe Platforms::MassBuildsController do
|
||||||
|
before(:each) do
|
||||||
|
stub_symlink_methods
|
||||||
|
|
||||||
|
@platform = FactoryGirl.create(:platform)
|
||||||
|
@repository = FactoryGirl.create(:repository, :platform => @platform)
|
||||||
|
@personal_platform = FactoryGirl.create(:platform, :platform_type => 'personal')
|
||||||
|
@user = FactoryGirl.create(:user)
|
||||||
|
@create_params = {
|
||||||
|
:platform_id => @platform,
|
||||||
|
:repositories => [@platform.repositories.first.id],
|
||||||
|
:arches => [Arch.first.id],
|
||||||
|
:auto_publish => true
|
||||||
|
}
|
||||||
|
|
||||||
|
@mass_build = FactoryGirl.create(:mass_build, :platform => @platform, :user => @user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for guest' do
|
||||||
|
[:index, :create, :cancel, :failed_builds_list].each do |action|
|
||||||
|
it "should not be able to perform #{ action } action" do
|
||||||
|
get action, :platform_id => @platform
|
||||||
|
response.should redirect_to(new_user_session_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not change objects count on create success' do
|
||||||
|
lambda { post :create, @create_params }.should change{ MassBuild.count }.by(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not change stop_build on cancel' do
|
||||||
|
post :cancel, :platform_id => @platform, :id => @mass_build
|
||||||
|
@mass_build.reload.stop_build.should == false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for global admin' do
|
||||||
|
before(:each) do
|
||||||
|
@admin = FactoryGirl.create(:admin)
|
||||||
|
@user = FactoryGirl.create(:user)
|
||||||
|
set_session_for(@admin)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_should_behave_like 'mass_build platform owner'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for owner user' do
|
||||||
|
before(:each) do
|
||||||
|
@user = FactoryGirl.create(:user)
|
||||||
|
set_session_for(@user)
|
||||||
|
@platform.update_attribute(:owner, @user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_should_behave_like 'mass_build platform owner'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for admin user' do
|
||||||
|
before(:each) do
|
||||||
|
@user = FactoryGirl.create(:user)
|
||||||
|
set_session_for(@user)
|
||||||
|
@platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin')
|
||||||
|
end
|
||||||
|
|
||||||
|
it_should_behave_like 'mass_build platform owner'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for reader user' do
|
||||||
|
before(:each) do
|
||||||
|
@user = FactoryGirl.create(:user)
|
||||||
|
set_session_for(@user)
|
||||||
|
@platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
|
||||||
|
end
|
||||||
|
|
||||||
|
it_should_behave_like 'mass_build platform reader'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# -*- encoding : utf-8 -*-
|
||||||
|
FactoryGirl.define do
|
||||||
|
factory :mass_build do
|
||||||
|
association :platform
|
||||||
|
#name FactoryGirl.generate(:name)
|
||||||
|
association :user
|
||||||
|
repositories { |mb| [ mb.platform.repositories.first.id ] }
|
||||||
|
arches { [ Arch.first.id ] }
|
||||||
|
auto_publish true
|
||||||
|
stop_build false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 559 B |
File diff suppressed because it is too large
Load Diff
|
@ -11,5 +11,8 @@
|
||||||
//= require bootstrap-button
|
//= require bootstrap-button
|
||||||
//= require bootstrap-dropdown
|
//= require bootstrap-dropdown
|
||||||
//= require bootstrap-tab
|
//= require bootstrap-tab
|
||||||
|
// require bootstrap-tooltip
|
||||||
|
// require bootstrap-popover
|
||||||
|
//= require chosen.jquery
|
||||||
// require html5shiv
|
// require html5shiv
|
||||||
// require_tree .
|
// require_tree .
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
/* @group Base */
|
||||||
|
.chzn-container {
|
||||||
|
font-size: 13px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
zoom: 1;
|
||||||
|
*display: inline;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-drop {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-top: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 29px;
|
||||||
|
left: 0;
|
||||||
|
-webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
|
||||||
|
-moz-box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||||
|
-o-box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||||
|
box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||||
|
z-index: 1010;
|
||||||
|
}
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Single Chosen */
|
||||||
|
.chzn-container-single .chzn-single {
|
||||||
|
background-color: #ffffff;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );
|
||||||
|
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
|
||||||
|
background-image: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
||||||
|
background-image: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
||||||
|
background-image: -ms-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
||||||
|
background-image: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
-moz-border-radius : 5px;
|
||||||
|
border-radius : 5px;
|
||||||
|
-moz-background-clip : padding;
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
background-clip : padding-box;
|
||||||
|
border: 1px solid #aaaaaa;
|
||||||
|
-webkit-box-shadow: 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
|
||||||
|
-moz-box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
|
||||||
|
box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: relative;
|
||||||
|
height: 23px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 0 0 0 8px;
|
||||||
|
color: #444444;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-default {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-single span {
|
||||||
|
margin-right: 26px;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
-o-text-overflow: ellipsis;
|
||||||
|
-ms-text-overflow: ellipsis;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-single abbr {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 26px;
|
||||||
|
top: 6px;
|
||||||
|
width: 12px;
|
||||||
|
height: 13px;
|
||||||
|
font-size: 1px;
|
||||||
|
background: image-url('chosen/chosen-sprite.png') right top no-repeat;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-single abbr:hover {
|
||||||
|
background-position: right -11px;
|
||||||
|
}
|
||||||
|
.chzn-container-single.chzn-disabled .chzn-single abbr:hover {
|
||||||
|
background-position: right top;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-single div {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-single div b {
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 0 0;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-search {
|
||||||
|
padding: 3px 4px;
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 1010;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-search input {
|
||||||
|
background: #fff image-url('chosen/chosen-sprite.png') no-repeat 100% -22px;
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat 100% -22px, linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
margin: 1px 0;
|
||||||
|
padding: 4px 20px 4px 5px;
|
||||||
|
outline: 0;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
.chzn-container-single .chzn-drop {
|
||||||
|
-webkit-border-radius: 0 0 4px 4px;
|
||||||
|
-moz-border-radius : 0 0 4px 4px;
|
||||||
|
border-radius : 0 0 4px 4px;
|
||||||
|
-moz-background-clip : padding;
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
background-clip : padding-box;
|
||||||
|
}
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
.chzn-container-single-nosearch .chzn-search input {
|
||||||
|
position: absolute;
|
||||||
|
left: -9000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @group Multi Chosen */
|
||||||
|
.chzn-container-multi .chzn-choices {
|
||||||
|
background-color: #fff;
|
||||||
|
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
||||||
|
background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: text;
|
||||||
|
overflow: hidden;
|
||||||
|
height: auto !important;
|
||||||
|
height: 1%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices li {
|
||||||
|
float: left;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-field {
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-field input {
|
||||||
|
color: #666;
|
||||||
|
background: transparent !important;
|
||||||
|
border: 0 !important;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 100%;
|
||||||
|
height: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 1px 0;
|
||||||
|
outline: 0;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
-moz-box-shadow : none;
|
||||||
|
-o-box-shadow : none;
|
||||||
|
box-shadow : none;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-field .default {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-choice {
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius : 3px;
|
||||||
|
border-radius : 3px;
|
||||||
|
-moz-background-clip : padding;
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
background-clip : padding-box;
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
|
||||||
|
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
||||||
|
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||||
|
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||||
|
background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||||
|
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
||||||
|
-webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||||
|
-moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||||
|
box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #aaaaaa;
|
||||||
|
line-height: 13px;
|
||||||
|
padding: 3px 20px 3px 5px;
|
||||||
|
margin: 3px 0 3px 5px;
|
||||||
|
position: relative;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-choice-focus {
|
||||||
|
background: #d4d4d4;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-choice .search-choice-close {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 3px;
|
||||||
|
top: 4px;
|
||||||
|
width: 12px;
|
||||||
|
height: 13px;
|
||||||
|
font-size: 1px;
|
||||||
|
background: image-url('chosen/chosen-sprite.png') right top no-repeat;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover {
|
||||||
|
background-position: right -11px;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close {
|
||||||
|
background-position: right -11px;
|
||||||
|
}
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Results */
|
||||||
|
.chzn-container .chzn-results {
|
||||||
|
margin: 0 4px 4px 0;
|
||||||
|
max-height: 240px;
|
||||||
|
padding: 0 0 0 4px;
|
||||||
|
position: relative;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-results {
|
||||||
|
margin: -1px 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results li {
|
||||||
|
display: none;
|
||||||
|
line-height: 15px;
|
||||||
|
padding: 5px 6px;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .active-result {
|
||||||
|
cursor: pointer;
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .highlighted {
|
||||||
|
background-color: #3875d7;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 );
|
||||||
|
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
|
||||||
|
background-image: -webkit-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
|
||||||
|
background-image: -moz-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
|
||||||
|
background-image: -o-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
|
||||||
|
background-image: -ms-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
|
||||||
|
background-image: linear-gradient(top, #3875d7 20%, #2a62bc 90%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results li em {
|
||||||
|
background: #feffde;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .highlighted em {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .no-results {
|
||||||
|
background: #f4f4f4;
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .group-result {
|
||||||
|
cursor: default;
|
||||||
|
color: #999;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results .group-option {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
.chzn-container-multi .chzn-drop .result-selected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results-scroll {
|
||||||
|
background: white;
|
||||||
|
margin: 0 4px;
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
width: 321px; /* This should by dynamic with js */
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results-scroll span {
|
||||||
|
display: inline-block;
|
||||||
|
height: 17px;
|
||||||
|
text-indent: -5000px;
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results-scroll-down {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results-scroll-down span {
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -4px -3px;
|
||||||
|
}
|
||||||
|
.chzn-container .chzn-results-scroll-up span {
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -22px -3px;
|
||||||
|
}
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Active */
|
||||||
|
.chzn-container-active .chzn-single {
|
||||||
|
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||||
|
-moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
-o-box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
border: 1px solid #5897fb;
|
||||||
|
}
|
||||||
|
.chzn-container-active .chzn-single-with-drop {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
-webkit-box-shadow: 0 1px 0 #fff inset;
|
||||||
|
-moz-box-shadow : 0 1px 0 #fff inset;
|
||||||
|
-o-box-shadow : 0 1px 0 #fff inset;
|
||||||
|
box-shadow : 0 1px 0 #fff inset;
|
||||||
|
background-color: #eee;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );
|
||||||
|
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
|
||||||
|
background-image: -webkit-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
|
||||||
|
background-image: -moz-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
|
||||||
|
background-image: -o-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
|
||||||
|
background-image: -ms-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
|
||||||
|
background-image: linear-gradient(top, #eeeeee 20%, #ffffff 80%);
|
||||||
|
-webkit-border-bottom-left-radius : 0;
|
||||||
|
-webkit-border-bottom-right-radius: 0;
|
||||||
|
-moz-border-radius-bottomleft : 0;
|
||||||
|
-moz-border-radius-bottomright: 0;
|
||||||
|
border-bottom-left-radius : 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
.chzn-container-active .chzn-single-with-drop div {
|
||||||
|
background: transparent;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
.chzn-container-active .chzn-single-with-drop div b {
|
||||||
|
background-position: -18px 1px;
|
||||||
|
}
|
||||||
|
.chzn-container-active .chzn-choices {
|
||||||
|
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
|
||||||
|
-moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
-o-box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
box-shadow : 0 0 5px rgba(0,0,0,.3);
|
||||||
|
border: 1px solid #5897fb;
|
||||||
|
}
|
||||||
|
.chzn-container-active .chzn-choices .search-field input {
|
||||||
|
color: #111 !important;
|
||||||
|
}
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Disabled Support */
|
||||||
|
.chzn-disabled {
|
||||||
|
cursor: default;
|
||||||
|
opacity:0.5 !important;
|
||||||
|
}
|
||||||
|
.chzn-disabled .chzn-single {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.chzn-disabled .chzn-choices .search-choice .search-choice-close {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @group Right to Left */
|
||||||
|
.chzn-rtl { text-align: right; }
|
||||||
|
.chzn-rtl .chzn-single { padding: 0 8px 0 0; overflow: visible; }
|
||||||
|
.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; direction: rtl; }
|
||||||
|
|
||||||
|
.chzn-rtl .chzn-single div { left: 3px; right: auto; }
|
||||||
|
.chzn-rtl .chzn-single abbr {
|
||||||
|
left: 26px;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
.chzn-rtl .chzn-choices .search-field input { direction: rtl; }
|
||||||
|
.chzn-rtl .chzn-choices li { float: right; }
|
||||||
|
.chzn-rtl .chzn-choices .search-choice { padding: 3px 5px 3px 19px; margin: 3px 5px 3px 0; }
|
||||||
|
.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 4px; right: auto; background-position: right top;}
|
||||||
|
.chzn-rtl.chzn-container-single .chzn-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; }
|
||||||
|
.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 15px; }
|
||||||
|
.chzn-rtl.chzn-container-active .chzn-single-with-drop div { border-right: none; }
|
||||||
|
.chzn-rtl .chzn-search input {
|
||||||
|
background: #fff image-url('chosen/chosen-sprite.png') no-repeat -38px -22px;
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
background: image-url('chosen/chosen-sprite.png') no-repeat -38px -22px, linear-gradient(top, #eeeeee 1%, #ffffff 15%);
|
||||||
|
padding: 4px 5px 4px 20px;
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
/* @end */
|
|
@ -13,4 +13,5 @@
|
||||||
@import "codemirror/modes/rpm-spec";
|
@import "codemirror/modes/rpm-spec";
|
||||||
@import "codemirror/modes/tiddlywiki";
|
@import "codemirror/modes/tiddlywiki";
|
||||||
|
|
||||||
@import "bootstrap"
|
@import "bootstrap";
|
||||||
|
@import "chosen.scss";
|
||||||
|
|
Loading…
Reference in New Issue