Merge pull request #528 from warpc/428-advisory

[issue #428] Advisories: final version:

* Added Many2Many relation between advisories and projects;
* Added autocompletion to build list's advisory;
* Bootstrap's JS moved to vendor;
* Added Atom feed for advisories;
* Added search in advisories page.
This commit is contained in:
Vladimir Sharshov 2012-07-04 07:29:30 -07:00
commit ce1c1ff403
35 changed files with 1964 additions and 113 deletions

View File

@ -4,9 +4,9 @@
//= require autocomplete-rails
//= require vendor
//= require jquery.dataTables_ext
//= require lib/lib
//= require_tree ./design
//= require_tree ./extra
//= require_tree ./lib
//= require underscore
//= require backbone

View File

@ -3,7 +3,91 @@ Rosa.Models.Advisory = Backbone.Model.extend({
id: null,
description: 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;
}
});

View File

@ -2,8 +2,7 @@ Rosa.Routers.BuildListsAdvisoriesRouter = Backbone.Router.extend({
routes: {},
initialize: function() {
this.advisoriesCollection = new Rosa.Collections.AdvisoriesCollection(Rosa.bootstrapedData.advisories);
this.advisoriesView = new Rosa.Views.BuildListAdvisoriesView({ collection: this.advisoriesCollection });
this.advisoriesView = new Rosa.Views.BuildListAdvisoriesView({ model: new Rosa.Models.Advisory() });
this.advisoriesView.render();
}

View File

@ -1,33 +1,42 @@
Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'popoverTitle', 'popoverDesc', 'showAdvisory',
'changeAdvisoryList', 'showPreview', 'showForm', 'hideAll');
this.$el = $('#advisory_block');
this._$form = this.$('#new_advisory_form');
this._$preview = this.$('#advisory_preview');
this._$type_select = $('#build_list_update_type');
this._$selector = this.$('#attach_advisory');
_.bindAll(this, 'showAdvisory', 'showPreview', 'showForm',
'showSearch', 'hideAll', 'displayStatus', 'processSearch');
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._$preview = this.$('#advisory_preview');
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._header_text = this._$preview.children('h3').html();
this._$selector.on('change', this.showAdvisory);
this._$type_select.on('change', this.changeAdvisoryList);
this._$search_field.on('input keyup', this.processSearch);
var self = this;
this._$type_select.on('change', function() {
self._$search_field.trigger('input');
});
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() {
this._$selector.children('.popoverable').hide();
this._$selector.children('.popoverable.' + this._$type_select.val()).show();
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) {
showAdvisory: function(ev) {
var adv_id = this._$selector.val();
this._$publish_button.prop({disabled: false});
switch (adv_id) {
case 'no':
this.hideAll();
@ -36,21 +45,70 @@ Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
this.showForm();
break
default:
this.showPreview(adv_id);
this.showSearch();
this._$publish_button.prop({disabled: 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) {
this._$publish_button.prop({disabled: false});
if (this._$form.is(':visible')) {
this._$form.slideUp();
}
var adv = this.collection.get(id);
var prev = this._$preview;
prev.children('h3').html(prev.children('h3').html() + ' ' + adv.get('advisory_id'));
prev.children('.descr').html(adv.get('description'));
prev.children('.refs').html(adv.get('references'));
if (!this._$preview.is(':visible')) {
this._$preview.slideDown();
var adv = this.model;
if (adv.get('found')) {
this._$selector.children('option.advisory_id').val(adv.get('advisory_id'));
prev.children('h3').html(this._header_text + ' ' + adv.get('advisory_id'));
prev.children('.descr').html(adv.get('description'));
prev.children('.refs').html(adv.get('references'));
if (!this._$preview.is(':visible')) {
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('');
}
},
@ -58,12 +116,27 @@ Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({
if (this._$preview.is(':visible')) {
this._$preview.slideUp();
}
if (this._$search.is(':visible')) {
this._$search.slideUp();
}
if (!this._$form.is(':visible')) {
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')) {
this._$preview.slideUp();
}
@ -72,14 +145,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() {
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();
return this;
}

View File

@ -1,3 +0,0 @@
//= require ./jquery.placeholder
//= require ./bootstrap-tooltip
//= require ./bootstrap-popover

View File

@ -954,10 +954,55 @@ form.mass_build input[type="checkbox"] {
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;
}
div#advisory_search_block {
padding-bottom: 15px;
}
p.hint_text {
color: #666666;
font-size: 0.9em;
padding: 0;
}
div#advisory_search_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 ===============*/
.popover {
@ -1091,3 +1136,39 @@ form.mass_build section.right {
.min_width_120 {
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 */

View File

@ -1,20 +1,36 @@
# -*- encoding : utf-8 -*-
class AdvisoriesController < ApplicationController
before_filter :authenticate_user!
before_filter :find_advisory, :only => [:show]
skip_before_filter :authenticate_user! if APP_CONFIG['anonymous_access']
load_and_authorize_resource
load_resource :find_by => :advisory_id
authorize_resource
def index
@advisories = @advisories.scoped(:include => :platforms)
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
@advisories = @advisories.paginate(:page => params[:page])
respond_to do |format|
format.html
format.atom
end
end
def show
@packages_info = Hash.new { |h, k| h[k] = {} }
@advisory.build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
batch.each do |build_list|
h = { build_list.project => build_list.packages }
@packages_info[build_list.save_to_platform].merge!(h) { |pr, old, new| (old + new).compact!.uniq! }
end
end
end
protected
def find_advisory
@advisory = Advisory.where(:advisory_id => params[:id]).limit(1).first if params[:id].present?
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
end

View File

@ -70,7 +70,6 @@ class Projects::BuildListsController < Projects::BaseController
def show
@item_groups = @build_list.items.group_by_level
@advisories = @build_list.project.advisories
end
def update
@ -173,7 +172,7 @@ class Projects::BuildListsController < Projects::BaseController
if params[:attach_advisory].present? and params[:attach_advisory] != 'no' and !@build_list.advisory
if params[:attach_advisory] == 'new'
# 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.project = @build_list.project
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform

View File

@ -1,9 +1,13 @@
# -*- encoding : utf-8 -*-
module AdvisoriesHelper
def advisories_select_options(advisories, opts = {:class => 'popoverable'})
def_values = [[t("layout.advisories.no_"), 'no'], [t("layout.advisories.new"), 'new']]
options_for_select(def_values, def_values.first) +
options_for_select(advisories.map { |a| [a.advisory_id, :class => "#{opts[:class]} #{a.update_type}"] })
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)
end
def advisory_id_for_hint
sprintf(Advisory::ID_STRING_TEMPLATE, :type => "{#{Advisory::TYPES.values.join(',')}}",
:year => 'YYYY', :id => 'XXXX')
end
def construct_ref_link(ref)

View File

@ -1,17 +1,20 @@
class Advisory < ActiveRecord::Base
has_and_belongs_to_many :platforms
has_and_belongs_to_many :projects
has_many :build_lists
belongs_to :project
validates :description, :update_type, :presence => true
after_create :generate_advisory_id
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'}
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
advisory_id

View File

@ -18,8 +18,8 @@ class Project < ActiveRecord::Base
has_many :collaborators, :through => :relations, :source => :actor, :source_type => 'User'
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_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 :owner, :presence => true

View File

@ -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

View File

@ -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

View File

@ -4,5 +4,29 @@
%th.th1= t("activerecord.attributes.advisory.advisory_id")
%th.th2= t("layout.advisories.affected_versions")
%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
= render :partial => 'list_item', :collection => list, :as => :advisory
- if list.size > 0
= 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');
}
});
});

View File

@ -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= project.srpm_file_name
%li
%p= "RPM:"
%ul
- packages.each do |package|
%li= package.fullname

View File

@ -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

View File

@ -1,4 +1,8 @@
- set_meta_tags :title => t('layout.advisories.list_header')
- 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
= will_paginate @advisories

View File

@ -4,7 +4,10 @@
%h3= "#{t("activerecord.models.advisory")} #{@advisory.advisory_id}".html_safe
.leftlist= "#{t("layout.advisories.project_name")}:".html_safe
.rightlist= link_to @advisory.project.name, project_path(@advisory.project)
.rightlist
- @advisory.projects.each do |project|
= link_to project.name, project_path(project)
%br
.both
.leftlist= "#{t("activerecord.attributes.advisory.created_at")}:".html_safe
@ -33,5 +36,7 @@
%br
.both
= render :partial => 'packages_info'
:javascript
$('article .all').addClass('bigpadding');

View File

@ -74,9 +74,28 @@
- if @build_list.can_publish? and @build_list.save_to_platform.released and @build_list.advisory.nil?
#advisory_block
.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)
.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}")
-#.info.advisory_not_found
%p= t("layout.advisories.banners.advisory_not_found")
-#.info.server_error
%p= t("layout.advisories.banners.server_error")
-#.info.continue_input
%p= t("layout.advisories.banners.continue_input")
#new_advisory_form
= f.fields_for @build_list.build_advisory do |f|
= render :partial => 'advisories/form', :locals => {:f => f}
@ -91,11 +110,8 @@
.leftlist= t("activerecord.attributes.advisory.references")
.rightlist.refs &nbsp;
.both
:javascript
$(function() {
Rosa.bootstrapedData.advisories = #{ render 'advisories/advisories.json.jbuilder',
:advisories => @advisories };
var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
});
@ -107,7 +123,6 @@
- if @item_groups.blank?
%h4.nomargin= t("layout.build_lists.no_items_data")
- @item_groups.each_with_index do |group, level|
-#%h4.nomargin= "#{group} ##{level}"
- group.each do |item|
%h4.nomargin= "#{item.name} ##{level}"
%table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"}

View File

@ -14,6 +14,7 @@ en:
read_access: read-only
by: by
clear: Clear
remove: Remove

View File

@ -14,6 +14,7 @@ ru:
read_access: только чтение
by: ''
clear: Очистить
remove: Убрать

View File

@ -4,6 +4,7 @@ en:
header: Search
advanced: Advanced search
all: Show All
no_results: Nothing found for "%{query}".
types:
all: All
projects: Projects

View File

@ -4,6 +4,7 @@ ru:
header: Поиск
advanced: Расширенный поиск
all: Показать все
no_results: По запросу "%{query}" ничего не найдено.
types:
all: Все
projects: Проекты

View File

@ -1,13 +1,24 @@
en:
layout:
advisories:
atom_header: Advisories
list_header: Advisories
form_header: New advisory
project_name: Project
affected_versions: Affected versions
affected_in: Affected in
ref_comment: Add links one by row
no_: No
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.
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:
advisories:

View File

@ -1,13 +1,24 @@
ru:
layout:
advisories:
atom_title: Бюллетени
list_header: Бюллетени
form_header: Новый бюллетень
project_name: Проект
affected_versions: Применен в версиях
affected_in: Применен в
ref_comment: Вставляйте ссылки по одной на строку
no_: Нет
new: Новый
existing: Существующий
search_by_id: Искать бюллетень по его ID
search_hint: Скопируйте в поле ввода полный AdvisoryID или введите его уникальную часть
advisory_id_info: AdvisoryID имеет формат %{advisory_format}, где 'XXXX' (минимум 4 символа) - это уникальная часть.
banners:
advisory_not_found: Не удалось найти запрашиваемый бюллетень для сборочного листа этого типа.
server_error: Произошла ошибка сервера. Попробуйте позже.
continue_input: Продолжайте вводить ID до тех пор, пока не найдется нужный бюллетень.
flash:
advisories:

View File

@ -38,7 +38,9 @@ Rosa::Application.routes.draw do
end
end
resources :advisories, :only => [:index, :show]
resources :advisories, :only => [:index, :show, :search] do
get :search, :on => :collection
end
scope :module => 'platforms' do
resources :platforms do

View File

@ -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

View File

@ -23,7 +23,6 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
create_table "advisories", :force => true do |t|
t.string "advisory_id"
t.integer "project_id"
t.text "description", :default => ""
t.text "references", :default => ""
t.text "update_type", :default => ""
@ -32,7 +31,6 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
end
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"
create_table "advisories_platforms", :id => false, :force => true do |t|
@ -44,10 +42,19 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
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"
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|
t.string "name", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "arches", ["name"], :name => "index_arches_on_name", :unique => true
@ -56,8 +63,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.integer "user_id"
t.string "provider"
t.string "uid"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "authentications", ["provider", "uid"], :name => "index_authentications_on_provider_and_uid", :unique => true
@ -68,8 +75,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.integer "level"
t.integer "status"
t.integer "build_list_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "version"
end
@ -100,8 +107,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.integer "project_id"
t.integer "arch_id"
t.datetime "notified_at"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "is_circle", :default => false
t.text "additional_repos"
t.string "name"
@ -130,8 +137,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "commentable_type"
t.integer "user_id"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "commentable_id", :precision => 50, :scale => 0
t.integer "project_id"
end
@ -148,14 +155,14 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "controller"
t.string "action"
t.text "message"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "groups", :force => true do |t|
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "uname"
t.integer "own_projects_count", :default => 0, :null => false
t.text "description"
@ -168,8 +175,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "title"
t.text "body"
t.string "status", :default => "open"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
t.datetime "closed_at"
t.integer "closed_by"
@ -218,14 +225,14 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "description"
t.string "name", :null => false
t.integer "parent_platform_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "released", :default => false, :null => false
t.integer "owner_id"
t.string "owner_type"
t.string "visibility", :default => "open", :null => false
t.string "platform_type", :default => "main", :null => false
t.string "distrib_type", :null => false
t.string "distrib_type"
end
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
@ -234,8 +241,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.integer "platform_id"
t.string "login"
t.string "password"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
@ -251,8 +258,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
create_table "products", :force => true do |t|
t.string "name", :null => false
t.integer "platform_id", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "build_script"
t.text "counter"
t.text "ks"
@ -271,8 +278,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "name"
t.string "version"
t.datetime "file_mtime"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "platform_id"
end
@ -281,14 +288,14 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
create_table "project_to_repositories", :force => true do |t|
t.integer "project_id"
t.integer "repository_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "projects", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "owner_id"
t.string "owner_type"
t.string "visibility", :default => "open"
@ -328,16 +335,16 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "actor_type"
t.integer "target_id"
t.string "target_type"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "role"
end
create_table "repositories", :force => true do |t|
t.string "description", :null => false
t.integer "platform_id", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "name", :null => false
end
@ -348,8 +355,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.boolean "new_comment_reply", :default => true
t.boolean "new_issue", :default => true
t.boolean "issue_assign", :default => true
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "new_comment_commit_owner", :default => true
t.boolean "new_comment_commit_repo_owner", :default => true
t.boolean "new_comment_commit_commentor", :default => true
@ -358,8 +365,8 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
create_table "subscribes", :force => true do |t|
t.string "subscribeable_type"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "status", :default => true
t.integer "project_id"
t.decimal "subscribeable_id", :precision => 50, :scale => 0
@ -371,9 +378,11 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "ssh_key"
t.string "uname"
t.string "role"
t.string "language", :default => "en"
@ -390,11 +399,11 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.integer "failed_attempts", :default => 0
t.integer "failed_attempts", :default => 0
t.string "unlock_token"
t.datetime "locked_at"
t.string "authentication_token"
t.integer "build_priority", :default => 50
t.integer "build_priority", :default => 50
end
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token"

BIN
vendor/assets/images/chosen/chosen-sprite.png vendored Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

1003
vendor/assets/javascripts/chosen.jquery.js vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -10,5 +10,8 @@
//= require bootstrap-modal
//= require bootstrap-button
//= require bootstrap-dropdown
// require bootstrap-tooltip
// require bootstrap-popover
//= require chosen.jquery
// require html5shiv
// require_tree .

396
vendor/assets/stylesheets/chosen.scss vendored Executable file
View File

@ -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 */

View File

@ -13,4 +13,5 @@
@import "codemirror/modes/rpm-spec";
@import "codemirror/modes/tiddlywiki";
@import "bootstrap"
@import "bootstrap";
@import "chosen.scss";