├── .gitignore ├── Procfile ├── views ├── index.erb ├── hostedit.erb ├── layout.erb └── hostlist.erb ├── Capfile ├── scripts ├── etc │ └── yasi.yml ├── init.d │ ├── thin │ └── selenium ├── bin │ ├── yasi-cli.sh │ └── cacti-cli.sh ├── yasi-cli.sh ├── yasi-cli.rb └── cacti-cli.sh ├── Rakefile ├── Gemfile ├── config.ru ├── main.rb ├── README.md ├── resque.god ├── History.md ├── lib ├── helpers.rb ├── nagiosql2_debug.rb └── nagiosql.rb └── public ├── js └── bootstrap-dropdown.js └── css └── yasi.css /.gitignore: -------------------------------------------------------------------------------- 1 | release.sh 2 | config/* 3 | tmp/ 4 | .*.swp 5 | .rvmrc 6 | .DS_Store 7 | vendor/* 8 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec shotgun -s thin config.ru -E production 2 | #web: bundle exec thin start -R config.ru -e development -p 9393 3 | #worker: bundle exec rake resque:work QUEUE=* 4 | -------------------------------------------------------------------------------- /views/index.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | × 4 | Information: Metrics are being cooked. 5 |
6 |
7 | -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | load 'deploy' if respond_to?(:namespace) # cap2 differentiator 2 | 3 | # Uncomment if you are using Rails' asset pipeline 4 | # load 'deploy/assets' 5 | 6 | Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } 7 | 8 | ## load 'config/deploy' # remove this line to skip loading any of the default tasks 9 | -------------------------------------------------------------------------------- /scripts/etc/yasi.yml: -------------------------------------------------------------------------------- 1 | user: www-data 2 | group: www-data 3 | pid: /var/run/thin.pid 4 | timeout: 30 5 | wait: 30 6 | log: /var/log/thin.log 7 | max_conns: 1024 8 | require: [] 9 | environment: development 10 | max_persistent_conns: 512 11 | servers: 1 12 | threaded: true 13 | no-epoll: true 14 | daemonize: true 15 | chdir: /servers/yasi 16 | tag: yasi-0.0.4 17 | address: localhost 18 | port: 9393 19 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler.require(:default) 3 | 4 | require File.dirname(__FILE__) + "/main.rb" 5 | require File.dirname(__FILE__) + "/lib/nagiosql.rb" 6 | 7 | require 'resque/tasks' 8 | 9 | desc "resque Worker" 10 | task "resque:setup" do 11 | ENV['QUEUE'] = '*' 12 | 13 | Resque.redis = Redis.new( :host => 'localhost', 14 | :port => 6379, 15 | :thread_safe => true ) 16 | end -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | gem 'rack' 3 | gem 'rack-protection' 4 | gem 'sinatra', :require => 'sinatra/base' 5 | gem 'sinatra-contrib' 6 | gem 'mongoid' 7 | gem 'bson' 8 | gem 'bson_ext' 9 | gem 'selenium', :require => 'selenium/server' 10 | gem 'selenium-webdriver' 11 | gem 'resque', :require => 'resque/server' 12 | gem 'logger' 13 | gem 'foreman' 14 | gem 'thin' 15 | gem 'shotgun' 16 | 17 | gem 'pry-padrino' 18 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler.require(:default) 3 | 4 | require File.dirname(__FILE__) + "/main.rb" 5 | require File.dirname(__FILE__) + "/lib/nagiosql.rb" 6 | 7 | $stdout.sync = true 8 | 9 | use Rack::ShowExceptions 10 | 11 | use Rack::Auth::Basic, "Restricted Area" do |username, password| 12 | [username, password] == ['USER', 'PASS'] 13 | end 14 | 15 | 16 | map('/') { run Yasi::Main } 17 | 18 | map('/nagiosql') { run Yasi::Nagiosql::Main } 19 | 20 | Resque.redis = Redis.new( :host => 'localhost', 21 | :port => 6379, 22 | :thread_safe => true ) 23 | 24 | map('/resque') { run Resque::Server } -------------------------------------------------------------------------------- /main.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require File.dirname(__FILE__) + "/lib/helpers.rb" 3 | 4 | module Yasi 5 | 6 | class Main < Sinatra::Base 7 | 8 | use Yasi::Confs::MyCfg 9 | helpers Yasi::CommonHelpers 10 | 11 | error do 12 | e = request.env['sinatra.error'] 13 | Kernel.puts e.backtrace.join("\n") 14 | "Application Error" 15 | end 16 | 17 | not_found do 18 | "Not found!" 19 | end 20 | 21 | # BEFORE FILTERS 22 | 23 | before do 24 | headers 'Content-Type' => 'text/html; charset=utf-8' 25 | end 26 | 27 | # CONTROLLERS 28 | 29 | get '/' do 30 | erb :index 31 | end 32 | 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /scripts/init.d/thin: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: thin 4 | # Required-Start: $local_fs $remote_fs 5 | # Required-Stop: $local_fs $remote_fs 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: S 0 1 6 8 | # Short-Description: thin initscript 9 | # Description: thin 10 | ### END INIT INFO 11 | 12 | # Original author: Forrest Robertson 13 | 14 | # Do NOT "set -e" 15 | 16 | rvm use 1.9.2@sin 17 | 18 | DAEMON=/usr/local/rvm/gems/ruby-1.9.2-p290@sin/bin/thin 19 | SCRIPT_NAME=/etc/init.d/thin 20 | CONFIG_PATH=/servers/etc/thin 21 | 22 | # Exit if the package is not installed 23 | [ -x "$DAEMON" ] || exit 0 24 | 25 | case "$1" in 26 | start) 27 | $DAEMON start --all $CONFIG_PATH 28 | ;; 29 | stop) 30 | $DAEMON stop --all $CONFIG_PATH 31 | ;; 32 | restart) 33 | $DAEMON restart --all $CONFIG_PATH 34 | ;; 35 | *) 36 | echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2 37 | exit 3 38 | ;; 39 | esac 40 | 41 | : 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **YASI** - Yet Another Stupid Idea 2 | 3 | This software acts as a glue between Puppet and Nagios while managed through NagiosQL. 4 | 5 | 6 | Under Puppet you must build a class as: 7 | 8 | define yasi_monit($ostype) { 9 | 10 | case $ostype { 11 | /(linux|freebsd)/: { 12 | exec { 'conf_nagios_cacti': 13 | command => "/servers/scripts/system/hosts/global/yasi-cli.sh addhost $::hostname $::ipaddress $::fqdn default \'linux default\'", 14 | } 15 | } 16 | 17 | /windows/: { 18 | exec { 'conf_nagios_cacti': 19 | path => $::path, 20 | command => "cmd.exe /c ruby C:\\servers\\scripts\\system\\hosts\\global\\yasi-cli.rb addhost $::hostname $::ipaddress ${::hostname}.%USERDNSDOMAIN% default \'windows default\' snmpmaster", 21 | } 22 | } 23 | } 24 | } 25 | 26 | Host manifests must be registered as: 27 | 28 | exec { "conf_nagios_cacti": 29 | command => "/servers/scripts/system/hosts/global/yasi-cli.sh addhost $::hostname $::ipaddress_be $::fqdn webservers \'webservers staging\'", 30 | schedule => 'daily' 31 | } 32 | 33 | (readme)… to be continued -------------------------------------------------------------------------------- /views/hostedit.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
HostnameAddressFQDNHostgroupHostgroup descStatus
24 |
35 |
36 |
-------------------------------------------------------------------------------- /resque.god: -------------------------------------------------------------------------------- 1 | God.watch do |w| 2 | w.name = 'resque' 3 | w.interval = 30.seconds 4 | w.env = { 'RACK_ENV' => 'production', 'QUEUE' => '*' } 5 | w.uid = 'nagiosmaster' 6 | w.gid = 'nagiosmaster' 7 | #w.dir = File.expand_path(File.join(File.dirname(__FILE__),'..')) 8 | #w.start = "rake resque:work" 9 | w.start = "cd /servers/yasi && RACK_ENV=production rake resque:work" 10 | w.start_grace = 10.seconds 11 | w.log = File.expand_path(File.join(File.dirname(__FILE__), 'log','resque-worker.log')) 12 | 13 | # restart if memory gets too high 14 | w.transition(:up, :restart) do |on| 15 | on.condition(:memory_usage) do |c| 16 | c.above = 200.megabytes 17 | c.times = 2 18 | end 19 | end 20 | 21 | # determine the state on startup 22 | w.transition(:init, { true => :up, false => :start }) do |on| 23 | on.condition(:process_running) do |c| 24 | c.running = true 25 | end 26 | end 27 | 28 | # determine when process has finished starting 29 | w.transition([:start, :restart], :up) do |on| 30 | on.condition(:process_running) do |c| 31 | c.running = true 32 | c.interval = 5.seconds 33 | end 34 | 35 | # failsafe 36 | on.condition(:tries) do |c| 37 | c.times = 5 38 | c.transition = :start 39 | c.interval = 5.seconds 40 | end 41 | end 42 | 43 | # start if process is not running 44 | w.transition(:up, :start) do |on| 45 | on.condition(:process_running) do |c| 46 | c.running = false 47 | end 48 | end 49 | end -------------------------------------------------------------------------------- /scripts/bin/yasi-cli.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # puppet-cli.sh Abstract curl 3 | # Version - 0.1 4 | # Date 9/12/2011 - 5 | 6 | DATE="$(date "+%Y%m%d%H")" 7 | 8 | ARGS=6 9 | E_BADARGS=65 10 | 11 | CURL_BIN="/usr/bin/curl" 12 | CURL_OPT="-i -d" 13 | 14 | YASI_HOST="localhost" 15 | YASI_PORT="9393" 16 | YASI_ADDHOST_URI="/nagiosql/c/host" 17 | 18 | ACTION=$1 19 | HOSTNAME=$2 20 | ADDRESS=$3 21 | FQDN=$4 22 | HOSTGROUP=$5 23 | HOSTGROUPDESC=$6 24 | 25 | function help { 26 | echo "" 27 | echo "Usage:" 28 | echo " yasi-cli.sh help" 29 | echo " yasi-cli.sh addhost hostname ip fqdn hostgroup hostgroupdesc" 30 | echo "" 31 | echo "Example:" 32 | echo " ./yasi-cli.sh addhost lolcat 127.0.0.1 lolcat.domain.tld lolcats \"lolcats servers\"" 33 | echo "" 34 | } 35 | 36 | function addhost { 37 | 38 | if [ -z ${HOSTNAME} ]; then 39 | echo "Insert hostname please!" 40 | exit 1; 41 | elif [ -z ${ADDRESS} ]; then 42 | echo "Insert address please!" 43 | exit 1; 44 | elif [ -z ${FQDN} ]; then 45 | echo "Insert FQDN please!" 46 | exit 1; 47 | elif [ -z ${HOSTGROUP} ]; then 48 | echo "Insert hostgroup" 49 | exit 1; 50 | elif [ -z "${HOSTGROUPDESC}" ]; then 51 | echo "Insert hostgroup description" 52 | exit 1; 53 | fi 54 | 55 | # curl -i -d "hostname=lolcat&address=127.0.0.1&fqdn=lolcat.domain.tld&hostgroup=lolcat&hostgroupdesc=my%20sweet" http://nagios3:9393/nagiosql/c/host 56 | 57 | # change spaces into %20 58 | HOSTGROUPDESC_CLEAN="$(echo ${HOSTGROUPDESC} | sed 's/ /%20/g')" 59 | 60 | YASI_ADDHOST_PAYLOAD="hostname=${HOSTNAME}&address=${ADDRESS}&fqdn=${FQDN}&hostgroup=${HOSTGROUP}&hostgroupdesc=${HOSTGROUPDESC_CLEAN}" 61 | 62 | ${CURL_BIN} ${CURL_OPT} "${YASI_ADDHOST_PAYLOAD}" http://${YASI_HOST}:${YASI_PORT}/${YASI_ADDHOST_URI} 63 | 64 | } 65 | 66 | 67 | case "${ACTION}" in 68 | "addhost" ) addhost ;; 69 | "help" | "" | * ) help exit 0 ;; 70 | esac 71 | -------------------------------------------------------------------------------- /views/layout.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | YASI 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 |
57 |
58 | <%= yield %> 59 |
60 |
61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.0.8 / 2012-08-14 3 | ================== 4 | 5 | * fix merge conflicts 6 | * * Mongoid 2.x to 3.x * Added cacti_template_id * Added operatingsystem type 7 | * try 1 cacti_template_id 8 | * added info about operatingsystem 9 | 10 | 0.0.5 / 2011-12-15 11 | ================== 12 | 13 | * Merge branch 'release/v005' into develop 14 | * history file 15 | 16 | 0.0.4 / 2011-12-15 17 | ================== 18 | 19 | * removed old slim 20 | * changed hostlist from slim to erb with some new stuff to add hosts 21 | * Merge branch 'feature/fix' into develop 22 | * recover changes from prod 23 | * recover changes from prod 24 | * Merge branch 'feature/cap' into develop 25 | * fix gitignore 26 | * capfile incompleto 27 | * Merge branch 'feature/cacti' into develop 28 | * added ssh command 29 | * modify some views 30 | * Merge branch 'feature/mongo' into develop 31 | * cacti start 32 | * fix after_perform to update status 33 | * fix address and description mismatch 34 | * logging and callback to mongo update status 35 | * logging fixes 36 | * Merge branch 'release/003' into develop 37 | 38 | 0.0.3 / 2011-11-16 39 | ================== 40 | 41 | * Merge branch 'feature/worker' into develop 42 | * worker finished to add hosts 43 | * worker 99% 44 | * view updated 45 | * resque done, queue 90% 46 | * Merge branch 'feature/mongo' into develop 47 | * finish simple queue 48 | * queue almost done 49 | * capture request2 50 | * capture request 51 | * document and url handler 52 | * first thoughts on queue 53 | * Merge branch 'release/v002' into develop 54 | * concluido 55 | * stuff out of order 56 | * Merge branch 'feature/queue' into develop 57 | * headless feature all complete 58 | * cleanup 59 | * Merge branch 'feature/sinatracontrib' into develop 60 | * cleanup 61 | * sinatra contrib ok 62 | * Merge branch 'release/v001' into develop 63 | 64 | 0.0.2 / 2011-11-04 65 | ================== 66 | 67 | * concluido 68 | * stuff out of order 69 | * Merge branch 'feature/queue' into develop 70 | * headless feature all complete 71 | * cleanup 72 | * clean2 73 | * Merge branch 'feature/sinatracontrib' into develop 74 | * cleanup 75 | * sinatra contrib ok 76 | * Merge branch 'release/v001' into develop 77 | 78 | 0.0.1 / 2011-10-26 79 | ================== 80 | 81 | * Core started 82 | * Initial commit 83 | -------------------------------------------------------------------------------- /scripts/yasi-cli.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # puppet-cli.sh Abstract curl 3 | # Version - 0.4 4 | # Date 9/12/2011 - 5 | 6 | DATE="$(date "+%Y-%m-%d_%H:%M")" 7 | 8 | LOGFILE="/tmp/yasi-cli-${DATE}.log" 9 | exec > >(tee ${LOGFILE}) 10 | exec 2>&1 11 | 12 | # CLEANUP 13 | find /tmp/ -iname 'yasi-cli*.log' -type f -mtime +2 -exec rm {} \; 14 | 15 | ARGS=8 16 | E_BADARGS=65 17 | 18 | USER="USER" 19 | PASS="CHANGEME" 20 | 21 | CURL_BIN="/usr/bin/curl" 22 | CURL_OPT="--user ${USER}:${PASS} -v -i -d" 23 | 24 | YASI_HOST="localhost" 25 | YASI_PORT="9393" 26 | YASI_ADDHOST_URI="/nagiosql/c/host" 27 | 28 | ACTION=$1 29 | HOSTNAME=$2 30 | ADDRESS=$3 31 | FQDN=$4 32 | HOSTGROUP=$5 33 | HOSTGROUPDESC=$6 34 | SNMP_COMMUNITY=$7 35 | SNMP_DEFAULT_COMMUNITY="snmpcommunity" 36 | OPERATINGSYSTEM=$8 37 | 38 | if [ -z ${SNMP_COMMUNITY} ]; then 39 | SNMP_COMMUNITY="${SNMP_DEFAULT_COMMUNITY}" 40 | fi 41 | 42 | if [ -z ${OPERATINGSYSTEM} ]; then 43 | OPERATINGSYSTEM="Debian" 44 | fi 45 | 46 | function help { 47 | echo "" 48 | echo "Usage:" 49 | echo " yasi-cli.sh help" 50 | echo " yasi-cli.sh addhost hostname ip fqdn hostgroup hostgroupdesc snmpcommunity operatingsystem" 51 | echo "" 52 | echo "Example:" 53 | echo " ./yasi-cli.sh addhost lolcat 127.0.0.1 lolcat.domain.tld lolcats \"lolcats servers\" Debian" 54 | echo "" 55 | } 56 | 57 | function addhost { 58 | 59 | if [ -z ${HOSTNAME} ]; then 60 | echo "Insert hostname please!" 61 | exit 1; 62 | elif [ -z ${ADDRESS} ]; then 63 | echo "Insert address please!" 64 | exit 1; 65 | elif [ -z ${FQDN} ]; then 66 | echo "Insert FQDN please!" 67 | exit 1; 68 | elif [ -z ${HOSTGROUP} ]; then 69 | echo "Insert hostgroup" 70 | exit 1; 71 | elif [ -z "${HOSTGROUPDESC}" ]; then 72 | echo "Insert hostgroup description" 73 | exit 1; 74 | fi 75 | 76 | # curl -i -d "hostname=lolcat&address=127.0.0.1&fqdn=lolcat.domain.tld&hostgroup=lolcat&hostgroupdesc=my%20sweet&snmpcommunity=snmpcom&operatingsystem=Debian" http://localhost:9393/nagiosql/c/host 77 | 78 | # change spaces into %20 79 | HOSTGROUPDESC_CLEAN="$(echo ${HOSTGROUPDESC} | sed 's/ /%20/g')" 80 | 81 | YASI_ADDHOST_PAYLOAD="hostname=${HOSTNAME}&address=${ADDRESS}&fqdn=${FQDN}&hostgroup=${HOSTGROUP}&hostgroupdesc=${HOSTGROUPDESC_CLEAN}&snmpcommunity=${SNMP_COMMUNITY}&operatingsystem=${OPERATINGSYSTEM}" 82 | 83 | echo ${DATE} >> ${LOGFILE} 84 | ${CURL_BIN} ${CURL_OPT} "${YASI_ADDHOST_PAYLOAD}" http://${YASI_HOST}:${YASI_PORT}/${YASI_ADDHOST_URI} >> ${LOGFILE} 85 | 86 | } 87 | 88 | case "${ACTION}" in 89 | "addhost" ) addhost ;; 90 | "help" | "" | * ) help exit 0 ;; 91 | esac 92 | -------------------------------------------------------------------------------- /lib/helpers.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'logger' 3 | require 'sinatra/base' 4 | require 'sinatra/config_file' 5 | require 'sinatra/json' 6 | require 'mongoid' 7 | 8 | module Yasi 9 | 10 | module Confs 11 | 12 | class MyCfg < Sinatra::Base 13 | register Sinatra::ConfigFile 14 | 15 | if ENV['RACK_ENV'] == 'production' 16 | config_file '../config/config.yml' 17 | else 18 | config_file '../config/config_dev.yml' 19 | end 20 | 21 | ## use Rack::Flash 22 | use Rack::Session::Cookie 23 | 24 | @@yasi_host = settings.yasi["host"] 25 | @@yasi_port = settings.yasi["port"] 26 | @@yasi_domain = settings.yasi["domain"] 27 | @@yasi_secret = settings.yasi["session_secret"] 28 | @@yasi_tick = settings.yasi["tick"] 29 | 30 | configure :production do 31 | set :sessions, :domain => "#{@@yasi_domain}" 32 | set :session_secret, "#{@@yasi_secret}" 33 | enable :protection, :logging, :dump_errors 34 | enable :methodoverride 35 | set :root, File.dirname(__FILE__) + '/../' 36 | set :public_folder, File.dirname(__FILE__) + 'public' 37 | set :views, File.dirname(__FILE__) + '/../views' 38 | 39 | $logger = Logger.new(STDOUT) 40 | 41 | $logger.info "info: Hit configure block" 42 | 43 | Mongoid.configure do |config| 44 | name = @@mongodb_db 45 | config.master = Mongo::Connection.new.db(name) 46 | #config.logger = Logger.new($stdout, :warn) 47 | #config.logger = logger 48 | config.persist_in_safe_mode = false 49 | end 50 | 51 | end 52 | 53 | configure :development, :production do 54 | set :sessions, :domain => "#{@@yasi_domain}" 55 | set :session_secret, "#{@@yasi_secret}" 56 | enable :protection, :logging, :dump_errors 57 | enable :methodoverride 58 | set :root, File.dirname(__FILE__) + '/../' 59 | set :public_folder, File.dirname(__FILE__) + 'public' 60 | set :views, File.dirname(__FILE__) + '/../views' 61 | 62 | $logger = Logger.new(STDOUT) 63 | $logger.level = Logger::DEBUG 64 | 65 | $logger.info "INFO: Environment [#{ENV['RACK_ENV']}] defined!" 66 | 67 | Mongoid.load!("config/mongoid.yml") 68 | end 69 | 70 | 71 | end 72 | 73 | end 74 | 75 | module CommonHelpers 76 | 77 | include Rack::Utils 78 | alias_method :h, :escape_html 79 | 80 | def link_to(name, location, alternative = false) 81 | if alternative and alternative[:condition] 82 | "#{alternative[:name]}" 83 | else 84 | "#{name}" 85 | end 86 | end 87 | 88 | end 89 | 90 | end 91 | -------------------------------------------------------------------------------- /public/js/bootstrap-dropdown.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-dropdown.js v2.0.1 3 | * http://twitter.github.com/bootstrap/javascript.html#dropdowns 4 | * ============================================================ 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* DROPDOWN CLASS DEFINITION 26 | * ========================= */ 27 | 28 | var toggle = '[data-toggle="dropdown"]' 29 | , Dropdown = function ( element ) { 30 | var $el = $(element).on('click.dropdown.data-api', this.toggle) 31 | $('html').on('click.dropdown.data-api', function () { 32 | $el.parent().removeClass('open') 33 | }) 34 | } 35 | 36 | Dropdown.prototype = { 37 | 38 | constructor: Dropdown 39 | 40 | , toggle: function ( e ) { 41 | var $this = $(this) 42 | , selector = $this.attr('data-target') 43 | , $parent 44 | , isActive 45 | 46 | if (!selector) { 47 | selector = $this.attr('href') 48 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 49 | } 50 | 51 | $parent = $(selector) 52 | $parent.length || ($parent = $this.parent()) 53 | 54 | isActive = $parent.hasClass('open') 55 | 56 | clearMenus() 57 | !isActive && $parent.toggleClass('open') 58 | 59 | return false 60 | } 61 | 62 | } 63 | 64 | function clearMenus() { 65 | $(toggle).parent().removeClass('open') 66 | } 67 | 68 | 69 | /* DROPDOWN PLUGIN DEFINITION 70 | * ========================== */ 71 | 72 | $.fn.dropdown = function ( option ) { 73 | return this.each(function () { 74 | var $this = $(this) 75 | , data = $this.data('dropdown') 76 | if (!data) $this.data('dropdown', (data = new Dropdown(this))) 77 | if (typeof option == 'string') data[option].call($this) 78 | }) 79 | } 80 | 81 | $.fn.dropdown.Constructor = Dropdown 82 | 83 | 84 | /* APPLY TO STANDARD DROPDOWN ELEMENTS 85 | * =================================== */ 86 | 87 | $(function () { 88 | $('html').on('click.dropdown.data-api', clearMenus) 89 | $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) 90 | }) 91 | 92 | }( window.jQuery ); -------------------------------------------------------------------------------- /views/hostlist.erb: -------------------------------------------------------------------------------- 1 |

Registered Servers

2 | 3 |
4 | 5 |
6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
HostnameAddressFQDNHostgroupHostgroup descStatus
40 |
41 |
42 |
43 | 44 |
45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | <% @h.each do |host| %> 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | <% end %> 80 | 81 |
DateHostnameAddressFQDNHostgroupHostgroup descStatus
<%= host.created_at.strftime("%m/%d/%Y") %><%= host.hostname %><%= host.address %><%= host.fqdn %><%= host.hostgroup %><%= host.hostgroupdesc %><%= host.status %>
Edit
82 |
83 |
84 | -------------------------------------------------------------------------------- /scripts/init.d/selenium: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SELENIUM_HOME=/servers/selenium 3 | LOG_DIR=/var/log/selenium 4 | ERROR_LOG=$LOG_DIR/selenium_error.log 5 | STD_LOG=$LOG_DIR/selenium_std.log 6 | TMP_DIR=$SELENIUM_HOME/tmp 7 | PID_FILE=/var/run/selenium.pid 8 | JAVA=/usr/bin/java 9 | SELENIUM_APP="$SELENIUM_HOME/selenium-server-standalone-2.14.0.jar" 10 | USER=selenium 11 | 12 | case "${1:-''}" in 13 | 'start') 14 | if test -f $PID_FILE 15 | then 16 | PID=`cat $PID_FILE` 17 | if ps --pid $PID >/dev/null ; 18 | then 19 | echo "Selenium is running...$PID" 20 | exit 0 21 | else 22 | echo "Selenium isn't running..." 23 | echo "Removing stale pid file: $PID_FILE" 24 | fi 25 | fi 26 | echo "Starting Selenium..." 27 | #echo "COMMAND: su $USER -c \"$JAVA -jar $SELENIUM_APP >$STD_LOG 2>$ERROR_LOG &\"" 28 | 29 | su $USER -c "$JAVA -jar $SELENIUM_APP -port 4444 >$STD_LOG 2>$ERROR_LOG &" 30 | error=$? 31 | if test $error -gt 0 32 | then 33 | echo "${bon}Error $error! Couldn't start Selenium!${boff}" 34 | fi 35 | ps -C java -o pid,cmd | grep $SELENIUM_APP | awk {'print $1 '} > $PID_FILE 36 | ;; 37 | 'stop') 38 | if test -f $PID_FILE 39 | then 40 | echo "Stopping Selenium..." 41 | PID=`cat $PID_FILE` 42 | kill -9 $PID 43 | if kill -9 $PID ; 44 | then 45 | sleep 2 46 | test -f $PID_FILE && rm -f $PID_FILE 47 | else 48 | echo "Selenium could not be stopped..." 49 | fi 50 | else 51 | echo "Selenium is not running." 52 | fi 53 | ;; 54 | 55 | 'restart') 56 | if test -f $PID_FILE 57 | then 58 | su $USER -c "kill -HUP `cat $PID_FILE`" 59 | test -f $PID_FILE && rm -f $PID_FILE 60 | sleep 1 61 | su $USER -c "$JAVA -jar $SELENIUM_APP >$STD_LOG 2>$ERROR_LOG &" 62 | error=$? 63 | if test $error -gt 0 64 | then 65 | echo "${bon}Error $error! Couldn't start Selenium!${boff}" 66 | fi 67 | ps -C java -o pid,cmd | grep $SELENIUM_APP | awk {'print $1 '} > $PID_FILE 68 | echo "Reload Selenium..." 69 | else 70 | echo "Selenium isn't running..." 71 | fi 72 | ;; 73 | 'status') 74 | if test -f $PID_FILE 75 | then 76 | PID=`cat $PID_FILE` 77 | if ps --pid $PID >/dev/null ; 78 | then 79 | echo "Selenium is running...$PID" 80 | else 81 | echo "Selenium isn't running..." 82 | fi 83 | else 84 | echo "Selenium isn't running..." 85 | fi 86 | ;; 87 | *) # no parameter specified 88 | echo "Usage: $SELF start|stop|restart|status" 89 | exit 1 90 | ;; 91 | esac 92 | -------------------------------------------------------------------------------- /scripts/yasi-cli.rb: -------------------------------------------------------------------------------- 1 | # yasi-cli.rb - Command Line Helper to YASI webservice. 2 | # This script should be run by Puppet on every host. 3 | # Puppet will fill in every argument with host facts and 4 | # yasi-cli post them to YASI webservice. 5 | # Version - 0.2 6 | # Date 14/Ago/2012 - operatingsystem\n" 56 | puts "" 57 | puts "Optional" 58 | puts " snmpcommunity defaults to 'snmpcom'" 59 | puts "" 60 | puts "Example:" 61 | puts " ./yasi-cli.rb addhost lolcat 127.0.0.1 lolcat.domain.tld lolcats \"lolcats servers\" snmpmaster Debian\n\n" 62 | end 63 | 64 | ## 65 | # MEthod to Verify if every argument needed is present. 66 | 67 | def validateCmd 68 | if (ARGV.length < 8) 69 | puts "\nExiting: Please fill all the arguments [#{ARGV.length} of 8]\n" 70 | @@logger.error('Error') {"Argument error"} 71 | help 72 | @@logger.close 73 | Kernel.exit(1) 74 | end 75 | end 76 | 77 | validateCmd 78 | 79 | ## 80 | # Addhost method baked to handle a payload or arguments. 81 | # Authentication goes here too. 82 | 83 | def addhost(hostname, address, fqdn, hostgroup, hostgroupdesc, snmp_community, operatingsystem) 84 | 85 | payload = { "hostname" => hostname, 86 | "address" => address, 87 | "fqdn" => fqdn, 88 | "hostgroup" => hostgroup, 89 | "hostgroupdesc" => hostgroupdesc, 90 | "snmpcommunity" => snmp_community, 91 | "operatingsystem" => operatingsystem } 92 | 93 | uri = URI("http://#{@@yasiHost}:#{@@yasiPort}#{@@addHostUri}") 94 | 95 | request = Net::HTTP::Post.new(uri.request_uri) 96 | 97 | request.basic_auth @@yasiUser, @@yasiPass 98 | 99 | request.set_form_data(payload) 100 | 101 | res = Net::HTTP.start(@@yasiHost, @@yasiPort) do |http| 102 | http.request(request) 103 | end 104 | 105 | if res.to_s.include? "HTTPUnauthorized" 106 | @@logger.error('Error') {"Authentication failed"} 107 | else 108 | @@logger.info('AddingHost') {payload} 109 | end 110 | 111 | @@logger.close 112 | 113 | Kernel.exit(0) 114 | end 115 | 116 | 117 | case action 118 | when "addhost" then addhost(hostname, address, fqdn, hostgroup, hostgroupdesc, snmp_community, operatingsystem) 119 | when "help" then help 120 | else 121 | puts "Unrecognized action" 122 | help 123 | end -------------------------------------------------------------------------------- /scripts/bin/cacti-cli.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # cacti-cli.sh Manage Cacti 3 | # Version - 0.3 4 | # Date - 17/11/2011 5 | # Francisco Cabrita - 6 | 7 | DATE="$(date "+%Y%m%d%H")" 8 | 9 | PHP_PATH="/servers/apache/php/bin" 10 | PHP_CMD="php" 11 | PHP_OPT="-q" 12 | CACTI_CLI_PATH="/servers/apache/htdocs/cacti/cli" 13 | ADD_DEVICE_CMD="add_device.php" 14 | ADD_GRAPHS_CMD="add_graphs.php" 15 | ADD_TREE_CMD="add_tree.php" 16 | 17 | TMP_FILE="/tmp/cacti-cli-${DATE}.txt" 18 | if [ -f "${TMP_FILE}" ]; then 19 | rm -f /tmp/cacti-cli-* 20 | fi 21 | 22 | ARGS=6 23 | E_BADARGS=85 24 | 25 | ACTION=$1 26 | ARG1=$1 27 | ARG2=$2 28 | ARG3=$3 29 | ARG4=$4 30 | ARG5=$5 31 | ARG6=$6 32 | 33 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 34 | 35 | function help { 36 | echo "" 37 | echo "Usage:" 38 | echo " cacti-cli.sh help" 39 | echo " cacti-cli.sh adddevice hostname ip template_id=10 community hostgroup" 40 | echo " cacti-cli.sh listhosttemplates" 41 | echo "" 42 | } 43 | 44 | function adddevice { 45 | 46 | GREAT_CMD="${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}" 47 | 48 | HOSTNAME=$ARG2 49 | IP=$ARG3 50 | DEVICE_TEMPLATE=$ARG4 51 | SNMP_COMMUNITY=$ARG5 52 | HOSTGROUP=$ARG6 53 | 54 | if [ -z ${HOSTNAME} ]; then 55 | echo "Insert Hostname please!" 56 | exit 1; 57 | elif [ -z ${IP} ]; then 58 | echo "Insert IP Address please!" 59 | exit 1; 60 | elif [ -z ${DEVICE_TEMPLATE} ]; then 61 | echo "Insert Template id please!" 62 | exit 1; 63 | elif [ -z ${SNMP_COMMUNITY} ]; then 64 | echo "Insert snmp community please" 65 | exit 1; 66 | elif [ -z ${HOSTGROUP} ]; then 67 | echo "Insert hostgroup please!" 68 | exit 1; 69 | fi 70 | 71 | 72 | echo "Step 1 - Add device" 73 | echo "-------------------" 74 | 75 | # php -q add_device.php --description="Device Add Test" --ip="router.mydomain.com" --template=10 --community="public" 76 | 77 | HOST_NAME="$(${GREAT_CMD}/${ADD_GRAPHS_CMD} --list-hosts | grep $HOSTNAME | awk -F' ' '{print $4}')" 78 | 79 | # Verifies if hostname already exists 80 | 81 | if [ "${HOST_NAME}" = "${HOSTNAME}" ]; then 82 | echo "ERROR! Host ${HOSTNAME} already exists!" 83 | exit 1; 84 | fi 85 | 86 | 87 | # Add host 88 | 89 | ADD_DEVICE_PARAMS="--description="${HOSTNAME}" --ip="${IP}" --template=${DEVICE_TEMPLATE} --community="${SNMP_COMMUNITY}"" 90 | 91 | ${GREAT_CMD}/${ADD_DEVICE_CMD} ${ADD_DEVICE_PARAMS} 92 | 93 | 94 | # Verifies if host has an host_id 95 | 96 | HOST_ID="$(${GREAT_CMD}/${ADD_GRAPHS_CMD} --list-hosts | grep $HOSTNAME | awk -F' ' '{print $1}')" 97 | 98 | if [ -z "${HOST_ID}" ]; then 99 | echo "ERROR! Host id: ${HOST_ID} not found for host: ${HOSTMAME}" 100 | exit 1; 101 | else 102 | echo "Step 2 - Add graph templates" 103 | echo "----------------------------" 104 | echo "CG Graphs" 105 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=4 --host-id=${HOST_ID} >> ${TMP_FILE} 106 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=7 --host-id=${HOST_ID} >> ${TMP_FILE} 107 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=11 --host-id=${HOST_ID} >> ${TMP_FILE} 108 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=14 --host-id=${HOST_ID} >> ${TMP_FILE} 109 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=77 --host-id=${HOST_ID} >> ${TMP_FILE} 110 | 111 | echo "DS Graphs" 112 | # graph-template-id=2 => Interfacea traffic 113 | # snmp-query-id=1 => SNMP Interface Stats 114 | # snmp-query-type-id=14 => In/Out Bits (64-bit Counters) 115 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --host-id=${HOST_ID} --graph-type=ds --graph-template-id=2 --snmp-query-id=1 --snmp-query-type-id=14 --snmp-field=ifOperStatus --snmp-value=Up >> ${TMP_FILE} 116 | 117 | cat ${TMP_FILE} | awk -F' ' '{print $5}' | sed -e 's,(,,' -e 's,),,' > ${TMP_FILE}.swp 118 | mv ${TMP_FILE}.swp ${TMP_FILE} 119 | fi 120 | 121 | 122 | echo "Step 3 - Add tree" 123 | echo "-----------------" 124 | 125 | TREE_ID="$(${GREAT_CMD}/${ADD_TREE_CMD} --list-trees | grep ${HOSTGROUP} | awk -F' ' '{print $1}')" 126 | 127 | if [ -z "${TREE_ID}" ]; then 128 | TREE_ID="$(${GREAT_CMD}/${ADD_TREE_CMD} --type=tree --name="${HOSTGROUP}" --sort-method=manual | awk -F' ' '{print $NF}' | sed -e 's,(,,' -e 's,),,')" 129 | fi 130 | 131 | 132 | echo "Step 4 - Add host node to tree" 133 | echo "------------------------------" 134 | 135 | OUT="$(${GREAT_CMD}/${ADD_TREE_CMD} --type=node --node-type=host --tree-id=${TREE_ID} --host-id=${HOST_ID})" 136 | 137 | echo "${OUT}" 138 | 139 | echo "Step 5 - Add graph node to tree" 140 | echo "-------------------------------" 141 | 142 | N=0 143 | cat ${TMP_FILE} | while read LINE ; do 144 | GRAPH_ID=${LINE} 145 | N=$((N+1)) 146 | ${GREAT_CMD}/${ADD_TREE_CMD} --type=node --node-type=graph --tree-id=${TREE_ID} --graph-id=${GRAPH_ID} 147 | done 148 | 149 | exit 0; 150 | } 151 | 152 | 153 | function listhosttemplates { 154 | 155 | ${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}/${ADD_DEVICE_CMD} --list-host-templates 156 | 157 | } 158 | 159 | 160 | case "${ACTION}" in 161 | "adddevice" ) adddevice ;; 162 | "listhosttemplates" ) listhosttemplates ;; 163 | "help" | "" | * ) help exit 0; ;; 164 | esac 165 | 166 | exit 0; 167 | -------------------------------------------------------------------------------- /scripts/cacti-cli.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # cacti-cli.sh Manage Cacti 3 | # Version - 0.6 4 | # Date - 17/11/2011 5 | # Francisco Cabrita - 6 | 7 | DATE="$(date "+%Y-%m-%d_%H:%M")" 8 | 9 | LOGFILE="/tmp/cacti-cli-${DATE}.log" 10 | exec > >(tee ${LOGFILE}) 11 | exec 2>&1 12 | 13 | # CLEANUP 14 | find /tmp/ -iname 'cacti-cli*.log' -type f -mtime +2 -exec rm {} \; 15 | 16 | PHP_PATH="/servers/apache/php/bin" 17 | PHP_CMD="php" 18 | PHP_OPT="-q" 19 | CACTI_CLI_PATH="/servers/apache/htdocs/cacti/cli" 20 | ADD_DEVICE_CMD="add_device.php" 21 | ADD_GRAPHS_CMD="add_graphs.php" 22 | ADD_GRAPH_TEMPLATE="add_graph_template.php" 23 | ADD_TREE_CMD="add_tree.php" 24 | 25 | TMP_FILE="/tmp/cacti-cli-${DATE}.txt" 26 | if [ -f "${TMP_FILE}" ]; then 27 | rm -f /tmp/cacti-cli-* 28 | fi 29 | 30 | ARGS=6 31 | E_BADARGS=85 32 | 33 | ACTION=$1 34 | ARG1=$1 35 | ARG2=$2 36 | ARG3=$3 37 | ARG4=$4 38 | ARG5=$5 39 | ARG6=$6 40 | 41 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 42 | 43 | function help { 44 | echo "" 45 | echo "Usage:" 46 | echo " cacti-cli.sh help" 47 | echo " cacti-cli.sh adddevice hostname ip template_id community hostgroup" 48 | echo " cacti-cli.sh listhosttemplates" 49 | echo " cacti-cli.sh listgraphtemplates" 50 | echo " cacti-cli.sh listhosts" 51 | echo "" 52 | echo "Notes:" 53 | echo " template_id=10 > *nix hosts" 54 | echo " template_id=11 > windows hosts" 55 | echo "" 56 | } 57 | 58 | function adddevice { 59 | 60 | GREAT_CMD="${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}" 61 | 62 | HOSTNAME=$ARG2 63 | IP=$ARG3 64 | DEVICE_TEMPLATE=$ARG4 65 | SNMP_COMMUNITY=$ARG5 66 | HOSTGROUP=$ARG6 67 | 68 | if [ -z ${HOSTNAME} ]; then 69 | echo "Insert Hostname please!" 70 | exit 1; 71 | elif [ -z ${IP} ]; then 72 | echo "Insert IP Address please!" 73 | exit 1; 74 | elif [ -z ${DEVICE_TEMPLATE} ]; then 75 | echo "Insert Template id please!" 76 | exit 1; 77 | elif [ -z ${SNMP_COMMUNITY} ]; then 78 | echo "Insert snmp community please" 79 | exit 1; 80 | elif [ -z ${HOSTGROUP} ]; then 81 | echo "Insert hostgroup please!" 82 | exit 1; 83 | elif [ -z ${DEVICE_TEMPLATE} ]; then 84 | echo "Didn't receive a template_id argument!" 85 | exit 1; 86 | fi 87 | 88 | 89 | echo "Step 1 - Add device" 90 | echo "-------------------" 91 | 92 | # php -q add_device.php --description="Device Add Test" --ip="router.mydomain.com" --template=10 --community="public" 93 | 94 | HOST_NAME="$(${GREAT_CMD}/${ADD_GRAPHS_CMD} --list-hosts | grep $HOSTNAME | awk -F' ' '{print $4}')" 95 | 96 | # Verifies if hostname already exists 97 | 98 | if [ "${HOST_NAME}" = "${HOSTNAME}" ]; then 99 | echo "ERROR! Host ${HOSTNAME} already exists!" 100 | exit 1; 101 | fi 102 | 103 | 104 | # Add host 105 | 106 | ADD_DEVICE_PARAMS="--description="${HOSTNAME}" --ip="${IP}" --template=${DEVICE_TEMPLATE} --community="${SNMP_COMMUNITY}"" 107 | 108 | ${GREAT_CMD}/${ADD_DEVICE_CMD} ${ADD_DEVICE_PARAMS} 109 | 110 | # ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 111 | # 112 | # ALGURES AQUI VOU TER DE VERIFICAR A CONTINUIDADE DA OPERACAO COM BASE NO TIPO DE SISTEMA OPERATIVO 113 | # 114 | # ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 115 | 116 | 117 | # Verifies if host has an host_id 118 | 119 | HOST_ID="$(${GREAT_CMD}/${ADD_GRAPHS_CMD} --list-hosts | grep $HOSTNAME | awk -F' ' '{print $1}')" 120 | 121 | if [ -z "${HOST_ID}" ]; then 122 | echo "ERROR! Host id: ${HOST_ID} not found for host: ${HOSTMAME}" 123 | exit 1; 124 | else 125 | echo "Step 2 - Add graph templates" 126 | echo "----------------------------" 127 | echo "CG Graphs" 128 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=4 --host-id=${HOST_ID} >> ${TMP_FILE} # ucd/net - CPU Usage 129 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=7 --host-id=${HOST_ID} >> ${TMP_FILE} # Unix - Ping Latency 130 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=11 --host-id=${HOST_ID} >> ${TMP_FILE} # ucd/net - Load Average 131 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=13 --host-id=${HOST_ID} >> ${TMP_FILE} # ucd/net - Memory Usage 132 | # ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=14 --host-id=${HOST_ID} >> ${TMP_FILE} # 133 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=77 --host-id=${HOST_ID} >> ${TMP_FILE} # TCP Connections by Type 134 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=78 --host-id=${HOST_ID} >> ${TMP_FILE} # IOSTAT - Disk1 - io/s 135 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=79 --host-id=${HOST_ID} >> ${TMP_FILE} # IOSTAT - Disk1 - io usage 136 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=80 --host-id=${HOST_ID} >> ${TMP_FILE} # IOSTAT - Disk1 - queue 137 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=81 --host-id=${HOST_ID} >> ${TMP_FILE} # IOSTAT - Disk1 - service time 138 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --graph-type=cg --graph-template-id=82 --host-id=${HOST_ID} >> ${TMP_FILE} # IOSTAT - Disk1 - Throughput Bytes/s 139 | 140 | echo "DS Graphs" 141 | # graph-template-id=2 => Interfacea traffic 142 | # snmp-query-id=1 => SNMP Interface Stats 143 | # snmp-query-type-id=14 => In/Out Bits (64-bit Counters) 144 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --host-id=${HOST_ID} --graph-type=ds --graph-template-id=2 --snmp-query-id=1 --snmp-query-type-id=14 --snmp-field=ifOperStatus --snmp-value=Up >> ${TMP_FILE} 145 | 146 | # graph-template-id=26 => Host MIB - Available Disk Space 147 | # snmp-query-id=8 => SNMP - Get Mounted Partitions 148 | # snmp-query-type-id=18 => Available Disk Spacec 149 | ${GREAT_CMD}/${ADD_GRAPHS_CMD} --host-id=${HOST_ID} --graph-type=ds --graph-template-id=26 --snmp-query-id=8 --snmp-query-type-id=18 --snmp-field=hrStorageDescr --snmp-value='/' >> ${TMP_FILE} 150 | 151 | 152 | cat ${TMP_FILE} | awk -F' ' '{print $5}' | sed -e 's,(,,' -e 's,),,' > ${TMP_FILE}.swp 153 | mv ${TMP_FILE}.swp ${TMP_FILE} 154 | fi 155 | 156 | 157 | echo "Step 3 - Add tree" 158 | echo "-----------------" 159 | 160 | TREE_ID="$(${GREAT_CMD}/${ADD_TREE_CMD} --list-trees | grep ${HOSTGROUP} | awk -F' ' '{print $1}')" 161 | 162 | if [ -z "${TREE_ID}" ]; then 163 | TREE_ID="$(${GREAT_CMD}/${ADD_TREE_CMD} --type=tree --name="${HOSTGROUP}" --sort-method=alpha | awk -F' ' '{print $NF}' | sed -e 's,(,,' -e 's,),,')" 164 | fi 165 | 166 | 167 | echo "Step 4 - Add host node to tree" 168 | echo "------------------------------" 169 | 170 | OUT="$(${GREAT_CMD}/${ADD_TREE_CMD} --type=node --node-type=host --tree-id=${TREE_ID} --host-id=${HOST_ID})" 171 | 172 | echo "${OUT}" 173 | 174 | echo "Step 5 - Add graph node to tree" 175 | echo "-------------------------------" 176 | 177 | N=0 178 | cat ${TMP_FILE} | while read LINE ; do 179 | GRAPH_ID=${LINE} 180 | N=$((N+1)) 181 | ${GREAT_CMD}/${ADD_TREE_CMD} --type=node --node-type=graph --tree-id=${TREE_ID} --graph-id=${GRAPH_ID} 182 | done 183 | 184 | exit 0; 185 | } 186 | 187 | 188 | function listhosttemplates { 189 | 190 | ${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}/${ADD_DEVICE_CMD} --list-host-templates 191 | 192 | } 193 | 194 | function listgraphtemplates { 195 | 196 | ${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}/${ADD_GRAPH_TEMPLATE} --list-graph-templates 197 | 198 | } 199 | 200 | function listhosts { 201 | 202 | ${PHP_PATH}/${PHP_CMD} ${PHP_OPT} ${CACTI_CLI_PATH}/${ADD_GRAPHS_CMD} --list-hosts 203 | 204 | } 205 | 206 | 207 | case "${ACTION}" in 208 | "adddevice" ) adddevice ;; 209 | "listhosttemplates" ) listhosttemplates ;; 210 | "listgraphtemplates" ) listgraphtemplates ;; 211 | "listhosts" ) listhosts ;; 212 | "help" | "" | * ) help exit 0; ;; 213 | esac 214 | 215 | exit 0; 216 | -------------------------------------------------------------------------------- /lib/nagiosql2_debug.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require "selenium/server" 3 | require "selenium-webdriver" 4 | require "resque/server" 5 | require File.dirname(__FILE__) + "/helpers.rb" 6 | 7 | MONGODB_HOST_DOC_VERSION = 1 8 | MONGODB_QUEUE_DOC_VERSION = 1 9 | 10 | include Selenium 11 | 12 | module Yasi 13 | 14 | module Nagiosql 15 | 16 | module Burnhost 17 | 18 | def self.authselenium 19 | $logger.info "info: authenticating..." 20 | @@driver = Selenium::WebDriver.for( 21 | :remote, 22 | :url => "#{$SELENIUM_HOST}:#{$SELENIUM_PORT}/#{$SELENIUM_URI}", 23 | :desired_capabilities => $CAPABILITIES) 24 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}" 25 | element = @@driver.find_element(:name, 'tfUsername') 26 | element.send_keys "#{$NAGIOSQL_USR}" 27 | element = @@driver.find_element(:name, 'tfPassword') 28 | element.send_keys "#{$NAGIOSQL_PAS}" 29 | element.submit 30 | end 31 | 32 | def self.addhostgroup(hostgroupname, hostgroupdesc) 33 | $logger.info "info: adding hostgroup..." 34 | authselenium 35 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}/admin/hostgroups.php" 36 | element = @@driver.find_element(:id, 'subAdd').click 37 | element = @@driver.find_element(:name, 'tfName') 38 | element.send_keys "#{hostgroupname}" 39 | element = @@driver.find_element(:name, 'tfFriendly') 40 | element.send_keys "#{hostgroupdesc}" 41 | element = @@driver.find_element(:id, 'subForm').click 42 | @@driver.close 43 | end 44 | 45 | def self.addcacti(hostname, address, template_id, snmp_community, hostgroup) 46 | $logger.info "info: init add host to cacti" 47 | $logger.info "#{hostname} #{address} #{hostgroup}" 48 | 49 | # exec = `ssh cabrita@nagios3 'ls /var/log ; touch /tmp/lol'` 50 | 51 | puts exec = `ssh -o "StrictHostKeyChecking no" -i #{$CACTI_SSHKEY} #{$CACTI_USR}@#{$CACTI_HOST} #{$CACTI_PATH}/#{$CACTI_SCRIPT} adddevice #{hostname} #{address} #{$CACTI_TEMPLID} company #{hostgroup}` 52 | 53 | $logger.info "info: end add host to cacti #{exec}" 54 | end 55 | 56 | def self.addhost(hostname, address, fqdn, hostgroup, hostgroupdesc) 57 | description = Array.new 58 | description = fqdn 59 | $logger.info "info: Running stuff on selenium... [#{hostname} #{address} #{description} #{hostgroup}]" 60 | authselenium 61 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}/admin/hosts.php" 62 | element = @@driver.find_element(:id, 'subAdd').click 63 | element = @@driver.find_element(:id, 'tfName') 64 | element.send_keys "#{hostname}" 65 | element = @@driver.find_element(:id, 'tfFriendly') 66 | element.send_keys "#{description}" 67 | element = @@driver.find_element(:id, 'tfAddress') 68 | element.send_keys "#{address}" 69 | select = @@driver.find_element(:id => "selHostCommand") 70 | option = select.find_elements(:tag_name => "option").find { |o| o.text == "#{$NAGIOSQL_CMD}" } 71 | raise "could not find the right option" if option.nil? 72 | option.click 73 | element = @@driver.find_element(:id, 'tfArg1') 74 | element.send_keys "100.0,20%" 75 | element = @@driver.find_element(:id, 'tfArg2') 76 | element.send_keys "500.0,60%" 77 | element = @@driver.find_element(:name, 'butTemplDefinition').click 78 | element = @@driver.find_element(:id, 'subForm1').click 79 | @@driver.close 80 | 81 | $logger.warn "WARNING: >>>> description= #{description} hostgroup= #{hostgroup}" 82 | 83 | addcacti(hostname, address, $CACTI_TEMPLID, $SNMP_COMMUNITY, hostgroup) 84 | end 85 | 86 | end 87 | 88 | module AfterJob 89 | 90 | def after_perform(h) 91 | $logger.info "info: Job done" 92 | hostname = h['hostname'] 93 | Host.update_status(hostname) 94 | end 95 | 96 | end 97 | 98 | 99 | class Host 100 | extend AfterJob 101 | 102 | include Mongoid::Document 103 | include Mongoid::Timestamps 104 | 105 | field :hostname, type: String 106 | field :address, type: String 107 | field :fqdn, type: String 108 | field :hostgroup, type: String 109 | field :hostgroupdesc, type: String 110 | field :status, type: String 111 | field :puppet_url, type: String 112 | field :doc_version, type: Integer, default: -> { MONGODB_HOST_DOC_VERSION } 113 | 114 | validates_presence_of :hostname, :address, :fqdn, :hostgroup 115 | validates_uniqueness_of :hostname, :address 116 | 117 | def self.update_status(hostname) 118 | status = "registered" 119 | if Host.where(hostname: hostname).update_all(status: status) 120 | $logger.info "info: Update [#{hostname}] status successful" 121 | else 122 | $logger.warn "WARNING: Update [#{hostname}] status failed" 123 | end 124 | end 125 | 126 | @queue = :burnhosts 127 | 128 | def self.perform(h) 129 | 130 | h['status'] = "building" 131 | 132 | hostname = h['hostname'] 133 | address = h['address'] 134 | fqdn = h['fqdn'] 135 | hostgroup = h['hostgroup'] 136 | hostgroupdesc = h['hostgroupdesc'] 137 | status = h['status'] 138 | 139 | $logger.info "info: Queueing job to add host [#{hostname} #{address} #{fqdn} #{hostgroup}]" 140 | 141 | Yasi::Nagiosql::Burnhost::addhost(hostname, address, fqdn, hostgroup, hostgroupdesc) 142 | 143 | end 144 | 145 | end 146 | 147 | 148 | class Main < Sinatra::Base 149 | register Sinatra::ConfigFile 150 | config_file '../config/config.yml' 151 | 152 | use Yasi::Confs::MyCfg 153 | helpers Yasi::CommonHelpers 154 | helpers Sinatra::JSON 155 | 156 | set :views, File.dirname(__FILE__) + '/../views' 157 | 158 | $SELENIUM_HOST = settings.selenium["host"] 159 | $SELENIUM_PORT = settings.selenium["port"] 160 | $SELENIUM_URI = settings.selenium["uri"] 161 | 162 | $NAGIOSQL_HOST = settings.nagiosql["host"] 163 | $NAGIOSQL_URI = settings.nagiosql["uri"] 164 | $NAGIOSQL_USR = settings.nagiosql["username"] 165 | $NAGIOSQL_PAS = settings.nagiosql["password"] 166 | $NAGIOSQL_CMD = settings.nagiosql["check_cmd"] 167 | 168 | $CACTI_HOST = settings.cacti["host"] 169 | $CACTI_USR = settings.cacti["username"] 170 | $CACTI_SSHKEY = settings.cacti["ssh_key"] 171 | $CACTI_PATH = settings.cacti["script_path"] 172 | $CACTI_SCRIPT = settings.cacti["script"] 173 | $CACTI_TEMPLID = settings.cacti["template_id"] 174 | 175 | $SNMP_COMMUNITY = settings.snmp["community"] 176 | 177 | $REDIS_HOST = settings.redis["host"] 178 | $REDIS_PORT = settings.redis["port"] 179 | 180 | $CAPABILITIES = Selenium::WebDriver::Remote::Capabilities.htmlunit( 181 | :browser_name => "htmlunit", 182 | :javascript_enabled => true, 183 | :css_selectors_enabled => true, 184 | :takes_screenshot => true, 185 | :native_events => true, 186 | :rotatable => false, 187 | :firefox_profile => nil, 188 | :proxy => nil) 189 | 190 | @@driver = Array.new 191 | @@action = String.new 192 | 193 | 194 | def check_document(action, name, *args) 195 | 196 | if action == "addhostgroup" 197 | if Host.exists?(conditions: { hostgroup: "#{name}" }) 198 | $logger.info "WARNING: Hostgroup [#{name}] exists!" 199 | else 200 | $logger.info "info: action: [#{action}] / name: [#{name}]" 201 | # TODO addhostgroup function 202 | end 203 | elsif action == "addhost" 204 | if Host.exists?(conditions: { hostname: "#{name}" }) 205 | $logger.warn "WARNING: [#{action}] / name: [#{name}] EXISTS!" 206 | else 207 | @hostname = name 208 | @address = args[0] 209 | @fqdn = args[1] 210 | @hostgroup = args[2] 211 | @hostgroupdesc = args[3] 212 | @status = "queued" 213 | h = Host.new(hostname: @hostname, 214 | address: @address, 215 | fqdn: @fqdn, 216 | hostgroup: @hostgroup, 217 | hostgroupdesc: @hostgroupdesc, 218 | status: @status) 219 | 220 | if h.save 221 | $logger.info "info: host saved [#{@hostname} #{@address} #{@fqdn}]" 222 | 223 | Resque.redis = Redis.new(:host => '127.0.0.1', :port => 6379) 224 | 225 | Resque.enqueue(Host, h) 226 | $logger.info "info: host queued [#{@hostname} #{@address} #{@fqdn}]" 227 | else 228 | $logger.warn "WARNING: host failed to save [#{@hostname} #{@address} #{@fqdn}]" 229 | end 230 | end 231 | end 232 | 233 | end 234 | 235 | 236 | # // BEFORE FILERS 237 | 238 | before do 239 | headers 'Content-Type' => 'text/html; charset=utf-8' 240 | 241 | rpath = request.path 242 | pinfo = request.path_info 243 | 244 | @@action = "addhost" if pinfo.include? "host" 245 | @@action = "addhostgroup" if pinfo.include? "hostgroup" # TODO WARNING da merda se ha um parametro com a key hostgroup :) 246 | end 247 | 248 | 249 | 250 | # // CONTROLLERS 251 | 252 | # HOME 253 | 254 | get '/' do 255 | erb "you may use /c/hostgroup or /c/host/ with its params", {:layout => :layout} 256 | end 257 | 258 | 259 | 260 | # HOSTGROUP 261 | 262 | get '/c/hostgroup' do 263 | json({ 264 | :msg => "Sample command", 265 | :cmd => "curl -i -d groupname=LOL&hostgroupdesc=BITCH' http://127.0.0.1:9393/nagiosql/c/hostgroup" 266 | }, :encoder => :to_json, :content_type => :js) 267 | end 268 | 269 | post '/c/hostgroup' do 270 | hostgroupname = params[:hostgroupname] 271 | hostgroupdesc = params[:hostgroupdesc] 272 | 273 | addhostgroup(hostgroupname, hostgroupdesc) 274 | 275 | erb "Hostgroup created" 276 | end 277 | 278 | 279 | 280 | # HOSTS 281 | # 282 | 283 | get '/c/host/:hostname/:address/:fqdn/:hostgroup/:hostgroupdesc' do 284 | name = params[:hostname] 285 | address = params[:address] 286 | fqdn = params[:fqdn] 287 | hostgroup = params[:hostgroup] 288 | hostgroupdesc = params[:hostgroupdesc] 289 | 290 | check_document(@@action, name, address, fqdn, hostgroup, hostgroupdesc) 291 | end 292 | 293 | post '/c/host' do 294 | hostname = params[:hostname] 295 | address = params[:address] 296 | fqdn = params[:fqdn] 297 | hostgroup = params[:hostgroup] 298 | hostgroupdesc = params[:hostgroupdesc] 299 | 300 | check_document(@@action, name, address, fqdn, hostgroup, hostgroupdesc) 301 | end 302 | 303 | get '/host/list' do 304 | @h = Host.all 305 | slim :hostlist 306 | end 307 | 308 | delete '/d/host/:id' do 309 | h = Host.find(params[:id]) 310 | if h.delete 311 | redirect '/nagiosql/host/list' 312 | else 313 | "Error deleting host" 314 | end 315 | 316 | end 317 | 318 | 319 | 320 | # // AFTER FILTERS 321 | 322 | after do 323 | $logger.info response.status 324 | end 325 | 326 | end 327 | 328 | end 329 | 330 | end 331 | -------------------------------------------------------------------------------- /lib/nagiosql.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require "selenium/server" 3 | require "selenium-webdriver" 4 | require "resque/server" 5 | require File.dirname(__FILE__) + "/helpers.rb" 6 | 7 | # TODO: Finish document code with RDoc 8 | 9 | MONGODB_HOST_DOC_VERSION = 3 10 | MONGODB_QUEUE_DOC_VERSION = 1 11 | 12 | include Selenium 13 | 14 | module Yasi 15 | 16 | module Nagiosql 17 | 18 | module Burnhost 19 | 20 | def self.authselenium 21 | $logger.info "info: Selenium: authenticating..." 22 | @@driver = Selenium::WebDriver.for( 23 | :remote, 24 | :url => "#{$SELENIUM_HOST}:#{$SELENIUM_PORT}/#{$SELENIUM_URI}", 25 | :desired_capabilities => $CAPABILITIES) 26 | @@driver.manage.timeouts.implicit_wait = 60 27 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}" 28 | element = @@driver.find_element(:name, 'tfUsername') 29 | element.send_keys "#{$NAGIOSQL_USR}" 30 | element = @@driver.find_element(:name, 'tfPassword') 31 | element.send_keys "#{$NAGIOSQL_PAS}" 32 | element.submit 33 | end 34 | 35 | 36 | def self.addhostgroup(hostgroupname, hostgroupdesc) 37 | $logger.info "info: Seleniun: adding hostgroup..." 38 | authselenium 39 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}/admin/hostgroups.php" 40 | element = @@driver.find_element(:id, 'subAdd').click 41 | element = @@driver.find_element(:name, 'tfName') 42 | element.send_keys "#{hostgroupname}" 43 | element = @@driver.find_element(:name, 'tfFriendly') 44 | element.send_keys "#{hostgroupdesc}" 45 | element = @@driver.find_element(:id, 'subForm').click 46 | @@driver.close 47 | end 48 | 49 | 50 | ## 51 | # Receives arguments and passes them to CACTI CLI through remote SSH command. 52 | 53 | def self.addcacti(hostname, address, cacti_template_id, snmpcommunity, hostgroup) 54 | 55 | puts exec = `ssh -o "StrictHostKeyChecking no" -i #{$CACTI_SSHKEY} #{$CACTI_USR}@#{$CACTI_HOST} #{$CACTI_PATH}/#{$CACTI_SCRIPT} adddevice #{hostname} #{address} #{cacti_template_id} #{snmpcommunity} #{hostgroup}` 56 | 57 | $logger.info "info: Cacti: end add host to cacti #{exec} [ hostname:#{hostname} address:#{address} hostgroup:#{hostgroup} snmpcommunity:#{snmpcommunity}]" 58 | end 59 | 60 | 61 | ## 62 | # This method receives every argument needed by NagiosQL and passes them to Selenium @@driver which will 63 | # create a simple host, defining automatically a check_ping command for that host. 64 | 65 | def self.addhost(hostname, address, fqdn, hostgroup, hostgroupdesc, snmpcommunity, operatingsystem) 66 | description = Array.new 67 | description = fqdn 68 | $logger.info "info: Selenium: Adding host... [ hostname:#{hostname} address:#{address} description:#{description} hostgroup:#{hostgroup} snmpcommunity:#{snmpcommunity}]" 69 | 70 | # Run nagiosql auth form. 71 | authselenium 72 | 73 | # Opens Admin hosts uri. 74 | @@driver.navigate.to "#{$NAGIOSQL_HOST}/#{$NAGIOSQL_URI}/admin/hosts.php" 75 | 76 | # Add host click 77 | element = @@driver.find_element(:id, 'subAdd').click 78 | 79 | # Fill in host arguments 80 | element = @@driver.find_element(:id, 'tfName') 81 | element.send_keys "#{hostname}" 82 | element = @@driver.find_element(:id, 'tfFriendly') 83 | element.send_keys "#{description}" 84 | element = @@driver.find_element(:id, 'tfAddress') 85 | element.send_keys "#{address}" 86 | 87 | # Add check command (check_ping). One may change this in config/config.yml. 88 | select = @@driver.find_element(:id => "selHostCommand") 89 | option = select.find_elements(:tag_name => "option").find { |o| o.text == "#{$NAGIOSQL_CMD}" } 90 | raise "could not find the right option" if option.nil? 91 | option.click 92 | 93 | # Fill in check comamnd arguments 94 | element = @@driver.find_element(:id, 'tfArg1') 95 | element.send_keys "100.0,20%" 96 | element = @@driver.find_element(:id, 'tfArg2') 97 | element.send_keys "500.0,60%" 98 | 99 | # Choose and insert template used on this host. (default) 100 | element = @@driver.find_element(:name, 'butTemplDefinition').click 101 | 102 | # Click save host 103 | element = @@driver.find_element(:id, 'subForm1').click 104 | 105 | # Warning: You have not filled in all command arguments (ARGx) for your selected command 106 | element = @@driver.find_element(:id, 'yui-gen10-button').click 107 | 108 | @@driver.close 109 | 110 | 111 | ## 112 | # Because we can receive two kinds of hosts, Linux and Windows, 113 | # we must verify which cacti device template to use based on operatingsystem type. 114 | 115 | cacti_template_id = Array.new 116 | 117 | case operatingsystem 118 | when /Linux|Debian|CentOS/ then cacti_template_id = $CACTI_NIX_TEMPLID 119 | when /Windows/ then cacti_template_id = $CACTI_WIN_TEMPLID 120 | else $logger.info "ERROR: Operating System not defined!" 121 | end 122 | 123 | addcacti(hostname, address, cacti_template_id, snmpcommunity, hostgroup) 124 | 125 | end 126 | 127 | end 128 | 129 | 130 | module AfterJob 131 | 132 | ## 133 | # This method runs after the resque job is complete and changes the host status field to 'registered'. 134 | 135 | def after_perform(h) 136 | $logger.info "info: Redis: Job done" 137 | hostname = h['hostname'] 138 | Host.update_status(hostname) 139 | end 140 | end 141 | 142 | 143 | class Host 144 | extend AfterJob 145 | 146 | include Mongoid::Document 147 | include Mongoid::Timestamps 148 | 149 | field :hostname, type: String 150 | field :address, type: String 151 | field :fqdn, type: String 152 | field :hostgroup, type: String 153 | field :hostgroupdesc, type: String 154 | field :snmpcommunity, type: String 155 | field :status, type: String 156 | field :puppet_url, type: String 157 | field :operatingsystem, type: Strign 158 | field :doc_version, type: Integer, default: -> { MONGODB_HOST_DOC_VERSION } 159 | 160 | validates_presence_of :hostname, :address, :fqdn, :hostgroup 161 | validates_uniqueness_of :hostname, :address 162 | 163 | 164 | ## 165 | # Update host status method 166 | 167 | def self.update_status(hostname) 168 | status = "registered" 169 | if Host.where(hostname: hostname).update_all(status: status) 170 | $logger.info "info: Mongodb: Update [#{hostname}] status successful" 171 | else 172 | $logger.warn "WARNING: Mongodb: Update [#{hostname}] status failed" 173 | end 174 | end 175 | 176 | 177 | # Resque working queue 178 | 179 | @queue = :burnhosts 180 | 181 | 182 | ## 183 | # Method to start the resque dirty job 184 | 185 | def self.perform(h) 186 | 187 | h['status'] = "building" 188 | 189 | hostname = h['hostname'] 190 | address = h['address'] 191 | fqdn = h['fqdn'] 192 | hostgroup = h['hostgroup'] 193 | hostgroupdesc = h['hostgroupdesc'] 194 | snmpcommunity = h['snmpcommunity'] 195 | operatingsystem = h['operatingsystem'] 196 | status = h['status'] 197 | 198 | $logger.info "info: Redis: Queueing job to add host [#{hostname} #{address} #{fqdn} #{hostgroup} #{snmpcommunity} #{operatingsystem}]" 199 | 200 | Yasi::Nagiosql::Burnhost::addhost(hostname, address, fqdn, hostgroup, hostgroupdesc, snmpcommunity, operatingsystem) 201 | 202 | end 203 | 204 | end 205 | 206 | 207 | class Main < Sinatra::Base 208 | register Sinatra::ConfigFile 209 | config_file '../config/config.yml' 210 | 211 | use Yasi::Confs::MyCfg 212 | helpers Yasi::CommonHelpers 213 | helpers Sinatra::JSON 214 | 215 | set :views, File.dirname(__FILE__) + '/../views' 216 | 217 | # Load configurations from 'config/config.yml' and set some vars 218 | 219 | $SELENIUM_HOST = settings.selenium["host"] 220 | $SELENIUM_PORT = settings.selenium["port"] 221 | $SELENIUM_URI = settings.selenium["uri"] 222 | 223 | $NAGIOSQL_HOST = settings.nagiosql["host"] 224 | $NAGIOSQL_URI = settings.nagiosql["uri"] 225 | $NAGIOSQL_USR = settings.nagiosql["username"] 226 | $NAGIOSQL_PAS = settings.nagiosql["password"] 227 | $NAGIOSQL_CMD = settings.nagiosql["check_cmd"] 228 | 229 | $CACTI_HOST = settings.cacti["host"] 230 | $CACTI_USR = settings.cacti["username"] 231 | $CACTI_SSHKEY = settings.cacti["ssh_key"] 232 | $CACTI_PATH = settings.cacti["script_path"] 233 | $CACTI_SCRIPT = settings.cacti["script"] 234 | $CACTI_NIX_TEMPLID = settings.cacti["template_nix_id"] 235 | $CACTI_WIN_TEMPLID = settings.cacti["template_win_id"] 236 | 237 | $SNMP_COMMUNITY = settings.snmp["community"] 238 | 239 | $REDIS_HOST = settings.redis["host"] 240 | $REDIS_PORT = settings.redis["port"] 241 | 242 | $CAPABILITIES = Selenium::WebDriver::Remote::Capabilities.htmlunit( 243 | :browser_name => "htmlunit", 244 | :javascript_enabled => true, 245 | :css_selectors_enabled => true, 246 | :takes_screenshot => true, 247 | :native_events => true, 248 | :rotatable => false, 249 | :firefox_profile => nil, 250 | :proxy => nil) 251 | 252 | @@driver = Array.new 253 | @@action = String.new 254 | 255 | 256 | ## 257 | # This method takes 2 + n arguments and verifies if host (name) exists. 258 | # If (name) exists, do nothing; else use (*args) and add host to mongodb with status = queued. 259 | # Finally enqueue job to later burn. 260 | 261 | def check_document(action, name, *args) 262 | 263 | if action == "addhostgroup" 264 | if Host.where(hostgroup: "#{name}").exists? 265 | $logger.info "WARNING: Hostgroup [#{name}] exists!" 266 | else 267 | $logger.info "info: action: [#{action}] / name: [#{name}]" 268 | # TODO: addhostgroup function 269 | end 270 | elsif action == "addhost" 271 | if Host.where(hostgroup: "#{name}").exists? 272 | $logger.warn "WARNING: [#{action}] / name: [#{name}] EXISTS!" 273 | else 274 | @hostname = name 275 | @address = args[0] 276 | @fqdn = args[1] 277 | @hostgroup = args[2] 278 | @hostgroupdesc = args[3] 279 | @snmpcommunity = args[4] 280 | @operatingsystem = args[5] 281 | @status = "queued" 282 | 283 | h = Host.new(hostname: @hostname, 284 | address: @address, 285 | fqdn: @fqdn, 286 | hostgroup: @hostgroup, 287 | hostgroupdesc: @hostgroupdesc, 288 | snmpcommunity: @snmpcommunity, 289 | operatingsystem: @operatingsystem, 290 | status: @status) 291 | 292 | # Saves host document to mongodb 293 | 294 | if h.save 295 | $logger.info "info: host saved [#{@hostname} #{@address} #{@fqdn}]" 296 | 297 | # Starts a new Resque object and opens a connection to Redis Server. 298 | 299 | Resque.redis = Redis.new( :host => $REDIS_HOST, 300 | :port => $REDIS_PORT, 301 | :thread_safe => true) 302 | 303 | # Guess what!? Enqueues the job! 304 | 305 | Resque.enqueue(Host, h) 306 | 307 | $logger.info "info: Redis: host queued [#{@hostname} #{@address} #{@fqdn} #{@snmpcommunity} #{@operatingsystem}]" 308 | else 309 | $logger.warn "WARNING: Redis: host failed to save [#{@hostname} #{@address} #{@fqdn} #{@snmpcommunity} #{@operatingsystem}]" 310 | end 311 | end 312 | end 313 | 314 | end 315 | 316 | 317 | # BEFORE FILERS 318 | 319 | before do 320 | headers 'Content-Type' => 'text/html; charset=utf-8' 321 | 322 | rpath = request.path 323 | pinfo = request.path_info 324 | 325 | # TODO: WARNING da merda se ha um parametro com a key hostgroup :) 326 | 327 | @@action = "addhost" if pinfo.include? "host" 328 | @@action = "addhostgroup" if pinfo.include? "hostgroup" 329 | end 330 | 331 | 332 | # CONTROLLERS 333 | 334 | # HOME 335 | 336 | get '/' do 337 | erb "you may use /c/hostgroup or /c/host/ with its params", {:layout => :layout} 338 | end 339 | 340 | # NOTE: Re-factor this block to addhostgroups in a clever way! 341 | 342 | =begin 343 | # HOSTGROUP 344 | 345 | get '/c/hostgroup' do 346 | json({ 347 | :msg => "Sample command", 348 | :cmd => "curl -i -d groupname=LOL&hostgroupdesc=BITCH' http://127.0.0.1:9393/nagiosql/c/hostgroup" 349 | }, :encoder => :to_json, :content_type => :js) 350 | end 351 | 352 | post '/c/hostgroup' do 353 | hostgroupname = params[:hostgroupname] 354 | hostgroupdesc = params[:hostgroupdesc] 355 | 356 | addhostgroup(hostgroupname, hostgroupdesc) 357 | 358 | erb "Hostgroup created" 359 | end 360 | =end 361 | 362 | 363 | # HOSTS 364 | # 365 | 366 | get '/c/host/:hostname/:address/:fqdn/:hostgroup/:hostgroupdesc' do 367 | name = params[:hostname] 368 | address = params[:address] 369 | fqdn = params[:fqdn] 370 | hostgroup = params[:hostgroup] 371 | hostgroupdesc = params[:hostgroupdesc] 372 | 373 | check_document(@@action, name, address, fqdn, hostgroup, hostgroupdesc) 374 | end 375 | 376 | post '/c/host' do 377 | name = params[:hostname] 378 | address = params[:address] 379 | fqdn = params[:fqdn] 380 | hostgroup = params[:hostgroup] 381 | hostgroupdesc = params[:hostgroupdesc] 382 | snmpcommunity = params[:snmpcommunity] 383 | operatingsystem = params[:operatingsystem] 384 | 385 | check_document(@@action, name, address, fqdn, hostgroup, hostgroupdesc, snmpcommunity, operatingsystem) 386 | 387 | redirect '/nagiosql/host/list' 388 | end 389 | 390 | get '/e/host/:id' do 391 | @h = Host.find(params[:id]) 392 | erb :hostedit 393 | end 394 | 395 | put '/e/host/:id' do 396 | @h = Host.find(params[:id]) 397 | @h.update_attributes(params[:host]) # receives nested values 398 | redirect '/nagiosql/host/list' 399 | end 400 | 401 | get '/host/list' do 402 | 403 | # TODO: Finish sorting by date 404 | 405 | begin_migration = Time.local(2011, "nov", 1) 406 | 407 | condition = Host.where( :created_at.gte => begin_migration, 408 | :created_at.lte => Date.today.at_end_of_month).selector 409 | 410 | @h = Host.all 411 | erb :hostlist 412 | end 413 | 414 | delete '/d/host/:id' do 415 | h = Host.find(params[:id]) 416 | if h.delete 417 | redirect '/nagiosql/host/list' 418 | else 419 | "Error deleting host" 420 | end 421 | 422 | end 423 | 424 | # AFTER FILTERS 425 | after do 426 | $logger.info response.status 427 | end 428 | 429 | end 430 | 431 | end 432 | 433 | end 434 | -------------------------------------------------------------------------------- /public/css/yasi.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v2.0.0 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | article, 11 | aside, 12 | details, 13 | figcaption, 14 | figure, 15 | footer, 16 | header, 17 | hgroup, 18 | nav, 19 | section { 20 | display: block; 21 | } 22 | audio, canvas, video { 23 | display: inline-block; 24 | *display: inline; 25 | *zoom: 1; 26 | } 27 | audio:not([controls]) { 28 | display: none; 29 | } 30 | html { 31 | font-size: 100%; 32 | -webkit-text-size-adjust: 100%; 33 | -ms-text-size-adjust: 100%; 34 | } 35 | a:focus { 36 | outline: thin dotted; 37 | outline: 5px auto -webkit-focus-ring-color; 38 | outline-offset: -2px; 39 | } 40 | a:hover, a:active { 41 | outline: 0; 42 | } 43 | sub, sup { 44 | position: relative; 45 | font-size: 75%; 46 | line-height: 0; 47 | vertical-align: baseline; 48 | } 49 | sup { 50 | top: -0.5em; 51 | } 52 | sub { 53 | bottom: -0.25em; 54 | } 55 | img { 56 | max-width: 100%; 57 | height: auto; 58 | border: 0; 59 | -ms-interpolation-mode: bicubic; 60 | } 61 | button, 62 | input, 63 | select, 64 | textarea { 65 | margin: 0; 66 | font-size: 100%; 67 | vertical-align: middle; 68 | } 69 | button, input { 70 | *overflow: visible; 71 | line-height: normal; 72 | } 73 | button::-moz-focus-inner, input::-moz-focus-inner { 74 | padding: 0; 75 | border: 0; 76 | } 77 | button, 78 | input[type="button"], 79 | input[type="reset"], 80 | input[type="submit"] { 81 | cursor: pointer; 82 | -webkit-appearance: button; 83 | } 84 | input[type="search"] { 85 | -webkit-appearance: textfield; 86 | -webkit-box-sizing: content-box; 87 | -moz-box-sizing: content-box; 88 | box-sizing: content-box; 89 | } 90 | input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { 91 | -webkit-appearance: none; 92 | } 93 | textarea { 94 | overflow: auto; 95 | vertical-align: top; 96 | } 97 | body { 98 | margin: 0; 99 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 100 | font-size: 13px; 101 | line-height: 18px; 102 | color: #333333; 103 | background-color: #ffffff; 104 | } 105 | a { 106 | color: #0088cc; 107 | text-decoration: none; 108 | } 109 | a:hover { 110 | color: #005580; 111 | text-decoration: underline; 112 | } 113 | .row { 114 | margin-left: -20px; 115 | *zoom: 1; 116 | } 117 | .row:before, .row:after { 118 | display: table; 119 | content: ""; 120 | } 121 | .row:after { 122 | clear: both; 123 | } 124 | [class*="span"] { 125 | float: left; 126 | margin-left: 20px; 127 | } 128 | .span1 { 129 | width: 60px; 130 | } 131 | .span2 { 132 | width: 140px; 133 | } 134 | .span3 { 135 | width: 220px; 136 | } 137 | .span4 { 138 | width: 247px; 139 | } 140 | .span5 { 141 | width: 380px; 142 | } 143 | .span6 { 144 | width: 460px; 145 | } 146 | .span7 { 147 | width: 540px; 148 | } 149 | .span8 { 150 | width: 620px; 151 | } 152 | .span9 { 153 | width: 700px; 154 | } 155 | .span10 { 156 | width: 780px; 157 | } 158 | .span11 { 159 | width: 860px; 160 | } 161 | .span12, .container { 162 | width: 940px; 163 | } 164 | .offset1 { 165 | margin-left: 100px; 166 | } 167 | .offset2 { 168 | margin-left: 180px; 169 | } 170 | .offset3 { 171 | margin-left: 260px; 172 | } 173 | .offset4 { 174 | margin-left: 340px; 175 | } 176 | .offset5 { 177 | margin-left: 420px; 178 | } 179 | .offset6 { 180 | margin-left: 500px; 181 | } 182 | .offset7 { 183 | margin-left: 580px; 184 | } 185 | .offset8 { 186 | margin-left: 660px; 187 | } 188 | .offset9 { 189 | margin-left: 740px; 190 | } 191 | .offset10 { 192 | margin-left: 820px; 193 | } 194 | .offset11 { 195 | margin-left: 900px; 196 | } 197 | .row-fluid { 198 | width: 100%; 199 | *zoom: 1; 200 | } 201 | .row-fluid:before, .row-fluid:after { 202 | display: table; 203 | content: ""; 204 | } 205 | .row-fluid:after { 206 | clear: both; 207 | } 208 | .row-fluid > [class*="span"] { 209 | float: left; 210 | margin-left: 2.127659574%; 211 | } 212 | .row-fluid > [class*="span"]:first-child { 213 | margin-left: 0; 214 | } 215 | .row-fluid .span1 { 216 | width: 6.382978723%; 217 | } 218 | .row-fluid .span2 { 219 | width: 14.89361702%; 220 | } 221 | .row-fluid .span3 { 222 | width: 23.404255317%; 223 | } 224 | .row-fluid .span4 { 225 | width: 31.914893614%; 226 | } 227 | .row-fluid .span5 { 228 | width: 40.425531911%; 229 | } 230 | .row-fluid .span6 { 231 | width: 48.93617020799999%; 232 | } 233 | .row-fluid .span7 { 234 | width: 57.446808505%; 235 | } 236 | .row-fluid .span8 { 237 | width: 65.95744680199999%; 238 | } 239 | .row-fluid .span9 { 240 | width: 74.468085099%; 241 | } 242 | .row-fluid .span10 { 243 | width: 82.97872339599999%; 244 | } 245 | .row-fluid .span11 { 246 | width: 91.489361693%; 247 | } 248 | .row-fluid .span12 { 249 | width: 99.99999998999999%; 250 | } 251 | .container { 252 | width: 940px; 253 | margin-left: auto; 254 | margin-right: auto; 255 | *zoom: 1; 256 | } 257 | .container:before, .container:after { 258 | display: table; 259 | content: ""; 260 | } 261 | .container:after { 262 | clear: both; 263 | } 264 | .container-fluid { 265 | padding-left: 20px; 266 | padding-right: 20px; 267 | *zoom: 1; 268 | } 269 | .container-fluid:before, .container-fluid:after { 270 | display: table; 271 | content: ""; 272 | } 273 | .container-fluid:after { 274 | clear: both; 275 | } 276 | p { 277 | margin: 0 0 9px; 278 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 279 | font-size: 16px; 280 | line-height: 18px; 281 | } 282 | p small { 283 | font-size: 11px; 284 | color: #999999; 285 | } 286 | .lead { 287 | margin-bottom: 18px; 288 | font-size: 20px; 289 | font-weight: 200; 290 | line-height: 27px; 291 | } 292 | h1, 293 | h2, 294 | h3, 295 | h4, 296 | h5, 297 | h6 { 298 | margin: 0; 299 | font-weight: bold; 300 | color: #333333; 301 | text-rendering: optimizelegibility; 302 | } 303 | h1 small, 304 | h2 small, 305 | h3 small, 306 | h4 small, 307 | h5 small, 308 | h6 small { 309 | font-weight: normal; 310 | color: #333333; 311 | } 312 | h1 { 313 | font-size: 30px; 314 | line-height: 36px; 315 | } 316 | h1 small { 317 | font-size: 18px; 318 | } 319 | h2 { 320 | font-size: 24px; 321 | line-height: 36px; 322 | } 323 | h2 small { 324 | font-size: 18px; 325 | } 326 | h3 { 327 | line-height: 27px; 328 | font-size: 18px; 329 | } 330 | h3 small { 331 | font-size: 14px; 332 | } 333 | h4, h5, h6 { 334 | line-height: 18px; 335 | } 336 | h4 { 337 | font-size: 14px; 338 | } 339 | h4 small { 340 | font-size: 12px; 341 | } 342 | h5 { 343 | font-size: 12px; 344 | } 345 | h6 { 346 | font-size: 11px; 347 | color: #999999; 348 | text-transform: uppercase; 349 | } 350 | .page-header { 351 | padding-bottom: 17px; 352 | margin: 18px 0; 353 | border-bottom: 1pxpx solid #eeeeee; 354 | } 355 | .page-header h1 { 356 | line-height: 1; 357 | } 358 | ul, ol { 359 | padding: 0; 360 | margin: 0 0 9px 25px; 361 | } 362 | ul ul, 363 | ul ol, 364 | ol ol, 365 | ol ul { 366 | margin-bottom: 0; 367 | } 368 | ul { 369 | list-style: disc; 370 | } 371 | ol { 372 | list-style: decimal; 373 | } 374 | li { 375 | line-height: 18px; 376 | } 377 | ul.unstyled { 378 | margin-left: 0; 379 | list-style: none; 380 | } 381 | dl { 382 | margin-bottom: 18px; 383 | } 384 | dt, dd { 385 | line-height: 18px; 386 | } 387 | dt { 388 | font-weight: bold; 389 | } 390 | dd { 391 | margin-left: 9px; 392 | } 393 | hr { 394 | margin: 18px 0; 395 | border: 0; 396 | border-top: 1px solid #e5e5e5; 397 | border-bottom: 1px solid #ffffff; 398 | } 399 | strong { 400 | font-weight: bold; 401 | } 402 | em { 403 | font-style: italic; 404 | } 405 | .muted { 406 | color: #999999; 407 | } 408 | abbr { 409 | font-size: 90%; 410 | text-transform: uppercase; 411 | border-bottom: 1px dotted #ddd; 412 | cursor: help; 413 | } 414 | blockquote { 415 | padding: 0 0 0 15px; 416 | margin: 0 0 18px; 417 | border-left: 5px solid #eeeeee; 418 | } 419 | blockquote p { 420 | margin-bottom: 0; 421 | font-size: 16px; 422 | font-weight: 300; 423 | line-height: 22.5px; 424 | } 425 | blockquote small { 426 | display: block; 427 | line-height: 18px; 428 | color: #999999; 429 | } 430 | blockquote small:before { 431 | content: '\2014 \00A0'; 432 | } 433 | blockquote.pull-right { 434 | float: right; 435 | padding-left: 0; 436 | padding-right: 15px; 437 | border-left: 0; 438 | border-right: 5px solid #eeeeee; 439 | } 440 | blockquote.pull-right p, blockquote.pull-right small { 441 | text-align: right; 442 | } 443 | q:before, 444 | q:after, 445 | blockquote:before, 446 | blockquote:after { 447 | content: ""; 448 | } 449 | address { 450 | display: block; 451 | margin-bottom: 18px; 452 | line-height: 18px; 453 | font-style: normal; 454 | } 455 | small { 456 | font-size: 100%; 457 | } 458 | cite { 459 | font-style: normal; 460 | } 461 | code, pre { 462 | padding: 0 3px 2px; 463 | font-family: Menlo, Monaco, "Courier New", monospace; 464 | font-size: 12px; 465 | color: #333333; 466 | -webkit-border-radius: 3px; 467 | -moz-border-radius: 3px; 468 | border-radius: 3px; 469 | } 470 | code { 471 | padding: 3px 4px; 472 | color: #d14; 473 | background-color: #f7f7f9; 474 | border: 1px solid #e1e1e8; 475 | } 476 | pre { 477 | display: block; 478 | padding: 8.5px; 479 | margin: 0 0 9px; 480 | font-size: 12px; 481 | line-height: 18px; 482 | background-color: #f5f5f5; 483 | border: 1px solid #ccc; 484 | border: 1px solid rgba(0, 0, 0, 0.15); 485 | -webkit-border-radius: 4px; 486 | -moz-border-radius: 4px; 487 | border-radius: 4px; 488 | white-space: pre; 489 | white-space: pre-wrap; 490 | word-break: break-all; 491 | } 492 | pre.prettyprint { 493 | margin-bottom: 18px; 494 | } 495 | pre code { 496 | padding: 0; 497 | background-color: transparent; 498 | } 499 | form { 500 | margin: 0 0 18px; 501 | } 502 | fieldset { 503 | padding: 0; 504 | margin: 0; 505 | border: 0; 506 | } 507 | legend { 508 | display: block; 509 | width: 100%; 510 | padding: 0; 511 | margin-bottom: 27px; 512 | font-size: 19.5px; 513 | line-height: 36px; 514 | color: #333333; 515 | border: 0; 516 | border-bottom: 1px solid #eee; 517 | } 518 | label, 519 | input, 520 | button, 521 | select, 522 | textarea { 523 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 524 | font-size: 13px; 525 | font-weight: normal; 526 | line-height: 18px; 527 | } 528 | label { 529 | display: block; 530 | margin-bottom: 5px; 531 | color: #333333; 532 | } 533 | input, 534 | textarea, 535 | select, 536 | .uneditable-input { 537 | display: inline-block; 538 | background-color: #ffffff; 539 | width: 210px; 540 | height: 18px; 541 | padding: 4px 4px 4px 4px; 542 | margin-bottom: 9px; 543 | font-size: 13px; 544 | line-height: 18px; 545 | color: #555555; 546 | border: 1px solid #ccc; 547 | -webkit-border-radius: 3px; 548 | -moz-border-radius: 3px; 549 | border-radius: 3px; 550 | } 551 | .uneditable-textarea { 552 | width: auto; 553 | height: auto; 554 | } 555 | label input, label textarea, label select { 556 | display: block; 557 | } 558 | input[type="image"], input[type="checkbox"], input[type="radio"] { 559 | width: auto; 560 | height: auto; 561 | padding: 0; 562 | margin: 3px 0; 563 | *margin-top: 0; 564 | /* IE7 */ 565 | 566 | line-height: normal; 567 | border: 0; 568 | cursor: pointer; 569 | -webkit-border-radius: 0; 570 | -moz-border-radius: 0; 571 | border-radius: 0; 572 | } 573 | input[type="file"] { 574 | padding: initial; 575 | line-height: initial; 576 | border: initial; 577 | background-color: #ffffff; 578 | background-color: initial; 579 | -webkit-box-shadow: none; 580 | -moz-box-shadow: none; 581 | box-shadow: none; 582 | } 583 | [type="button"], input[type="reset"], input[type="submit"] { 584 | width: auto; 585 | height: auto; 586 | } 587 | select, input[type="file"] { 588 | height: auto; 589 | /* In IE7, the height of the select element cannot be changed by height, only font-size */ 590 | 591 | *margin-top: 4px; 592 | /* For IE7, add top margin to align select with labels */ 593 | 594 | line-height: 28px; 595 | } 596 | select { 597 | width: 220px; 598 | background-color: #ffffff; 599 | } 600 | select[multiple], select[size] { 601 | height: auto; 602 | } 603 | input[type="image"] { 604 | -webkit-box-shadow: none; 605 | -moz-box-shadow: none; 606 | box-shadow: none; 607 | } 608 | textarea { 609 | height: auto; 610 | } 611 | input[type="hidden"] { 612 | display: none; 613 | } 614 | .radio, .checkbox { 615 | padding-left: 18px; 616 | } 617 | .radio input[type="radio"], .checkbox input[type="checkbox"] { 618 | float: left; 619 | margin-left: -18px; 620 | } 621 | .controls > .radio:first-child, .controls > .checkbox:first-child { 622 | padding-top: 5px; 623 | } 624 | .radio.inline, .checkbox.inline { 625 | display: inline-block; 626 | margin-bottom: 0; 627 | vertical-align: middle; 628 | } 629 | .radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { 630 | margin-left: 10px; 631 | } 632 | .controls > .radio.inline:first-child, .controls > .checkbox.inline:first-child { 633 | padding-top: 0; 634 | } 635 | input, textarea { 636 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 637 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 638 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 639 | -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; 640 | -moz-transition: border linear 0.2s, box-shadow linear 0.2s; 641 | -ms-transition: border linear 0.2s, box-shadow linear 0.2s; 642 | -o-transition: border linear 0.2s, box-shadow linear 0.2s; 643 | transition: border linear 0.2s, box-shadow linear 0.2s; 644 | } 645 | input:focus, textarea:focus { 646 | border-color: rgba(82, 168, 236, 0.8); 647 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 648 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 649 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); 650 | outline: 0; 651 | outline: thin dotted \9; 652 | /* IE6-8 */ 653 | 654 | } 655 | input[type="file"]:focus, input[type="checkbox"]:focus, select:focus { 656 | -webkit-box-shadow: none; 657 | -moz-box-shadow: none; 658 | box-shadow: none; 659 | outline: thin dotted; 660 | outline: 5px auto -webkit-focus-ring-color; 661 | outline-offset: -2px; 662 | } 663 | .input-mini { 664 | width: 60px; 665 | } 666 | .input-small { 667 | width: 90px; 668 | } 669 | .input-medium { 670 | width: 150px; 671 | } 672 | .input-large { 673 | width: 210px; 674 | } 675 | .input-xlarge { 676 | width: 270px; 677 | } 678 | .input-xxlarge { 679 | width: 530px; 680 | } 681 | input[class*="span"], 682 | select[class*="span"], 683 | textarea[class*="span"], 684 | .uneditable-input { 685 | float: none; 686 | margin-left: 0; 687 | } 688 | input.span1, textarea.span1, .uneditable-input.span1 { 689 | width: 50px; 690 | } 691 | input.span2, textarea.span2, .uneditable-input.span2 { 692 | width: 130px; 693 | } 694 | input.span3, textarea.span3, .uneditable-input.span3 { 695 | width: 210px; 696 | } 697 | input.span4, textarea.span4, .uneditable-input.span4 { 698 | width: 290px; 699 | } 700 | input.span5, textarea.span5, .uneditable-input.span5 { 701 | width: 370px; 702 | } 703 | input.span6, textarea.span6, .uneditable-input.span6 { 704 | width: 450px; 705 | } 706 | input.span7, textarea.span7, .uneditable-input.span7 { 707 | width: 530px; 708 | } 709 | input.span8, textarea.span8, .uneditable-input.span8 { 710 | width: 610px; 711 | } 712 | input.span9, textarea.span9, .uneditable-input.span9 { 713 | width: 690px; 714 | } 715 | input.span10, textarea.span10, .uneditable-input.span10 { 716 | width: 770px; 717 | } 718 | input.span11, textarea.span11, .uneditable-input.span11 { 719 | width: 850px; 720 | } 721 | input.span12, textarea.span12, .uneditable-input.span12 { 722 | width: 930px; 723 | } 724 | input[disabled], 725 | select[disabled], 726 | textarea[disabled], 727 | input[readonly], 728 | select[readonly], 729 | textarea[readonly] { 730 | background-color: #f5f5f5; 731 | border-color: #ddd; 732 | cursor: not-allowed; 733 | } 734 | .control-group.warning > label, .control-group.warning .help-block, .control-group.warning .help-inline { 735 | color: #c09853; 736 | } 737 | .control-group.warning input, .control-group.warning select, .control-group.warning textarea { 738 | color: #c09853; 739 | border-color: #c09853; 740 | } 741 | .control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { 742 | border-color: #a47e3c; 743 | -webkit-box-shadow: 0 0 6px #dbc59e; 744 | -moz-box-shadow: 0 0 6px #dbc59e; 745 | box-shadow: 0 0 6px #dbc59e; 746 | } 747 | .control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { 748 | color: #c09853; 749 | background-color: #fcf8e3; 750 | border-color: #c09853; 751 | } 752 | .control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline { 753 | color: #b94a48; 754 | } 755 | .control-group.error input, .control-group.error select, .control-group.error textarea { 756 | color: #b94a48; 757 | border-color: #b94a48; 758 | } 759 | .control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { 760 | border-color: #953b39; 761 | -webkit-box-shadow: 0 0 6px #d59392; 762 | -moz-box-shadow: 0 0 6px #d59392; 763 | box-shadow: 0 0 6px #d59392; 764 | } 765 | .control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { 766 | color: #b94a48; 767 | background-color: #f2dede; 768 | border-color: #b94a48; 769 | } 770 | .control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline { 771 | color: #468847; 772 | } 773 | .control-group.success input, .control-group.success select, .control-group.success textarea { 774 | color: #468847; 775 | border-color: #468847; 776 | } 777 | .control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { 778 | border-color: #356635; 779 | -webkit-box-shadow: 0 0 6px #7aba7b; 780 | -moz-box-shadow: 0 0 6px #7aba7b; 781 | box-shadow: 0 0 6px #7aba7b; 782 | } 783 | .control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { 784 | color: #468847; 785 | background-color: #dff0d8; 786 | border-color: #468847; 787 | } 788 | input:focus:required:invalid, textarea:focus:required:invalid, select:focus:required:invalid { 789 | color: #b94a48; 790 | border-color: #ee5f5b; 791 | } 792 | input:focus:required:invalid:focus, textarea:focus:required:invalid:focus, select:focus:required:invalid:focus { 793 | border-color: #e9322d; 794 | -webkit-box-shadow: 0 0 6px #f8b9b7; 795 | -moz-box-shadow: 0 0 6px #f8b9b7; 796 | box-shadow: 0 0 6px #f8b9b7; 797 | } 798 | .form-actions { 799 | padding: 17px 20px 18px; 800 | margin-top: 18px; 801 | margin-bottom: 18px; 802 | background-color: #f5f5f5; 803 | border-top: 1px solid #ddd; 804 | } 805 | .uneditable-input { 806 | display: block; 807 | background-color: #ffffff; 808 | border-color: #eee; 809 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 810 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 811 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); 812 | cursor: not-allowed; 813 | } 814 | :-moz-placeholder { 815 | color: #999999; 816 | } 817 | ::-webkit-input-placeholder { 818 | color: #999999; 819 | } 820 | .help-block { 821 | margin-top: 5px; 822 | margin-bottom: 0; 823 | color: #999999; 824 | } 825 | .help-inline { 826 | display: inline-block; 827 | *display: inline; 828 | /* IE7 inline-block hack */ 829 | 830 | *zoom: 1; 831 | margin-bottom: 9px; 832 | vertical-align: middle; 833 | padding-left: 5px; 834 | } 835 | .input-prepend, .input-append { 836 | margin-bottom: 5px; 837 | *zoom: 1; 838 | } 839 | .input-prepend:before, 840 | .input-append:before, 841 | .input-prepend:after, 842 | .input-append:after { 843 | display: table; 844 | content: ""; 845 | } 846 | .input-prepend:after, .input-append:after { 847 | clear: both; 848 | } 849 | .input-prepend input, 850 | .input-append input, 851 | .input-prepend .uneditable-input, 852 | .input-append .uneditable-input { 853 | -webkit-border-radius: 0 3px 3px 0; 854 | -moz-border-radius: 0 3px 3px 0; 855 | border-radius: 0 3px 3px 0; 856 | } 857 | .input-prepend input:focus, 858 | .input-append input:focus, 859 | .input-prepend .uneditable-input:focus, 860 | .input-append .uneditable-input:focus { 861 | position: relative; 862 | z-index: 2; 863 | } 864 | .input-prepend .uneditable-input, .input-append .uneditable-input { 865 | border-left-color: #ccc; 866 | } 867 | .input-prepend .add-on, .input-append .add-on { 868 | float: left; 869 | display: block; 870 | width: auto; 871 | min-width: 16px; 872 | height: 18px; 873 | margin-right: -1px; 874 | padding: 4px 5px; 875 | font-weight: normal; 876 | line-height: 18px; 877 | color: #999999; 878 | text-align: center; 879 | text-shadow: 0 1px 0 #ffffff; 880 | background-color: #f5f5f5; 881 | border: 1px solid #ccc; 882 | -webkit-border-radius: 3px 0 0 3px; 883 | -moz-border-radius: 3px 0 0 3px; 884 | border-radius: 3px 0 0 3px; 885 | } 886 | .input-prepend .active, .input-append .active { 887 | background-color: #a9dba9; 888 | border-color: #46a546; 889 | } 890 | .input-prepend .add-on { 891 | *margin-top: 1px; 892 | /* IE6-7 */ 893 | 894 | } 895 | .input-append input, .input-append .uneditable-input { 896 | float: left; 897 | -webkit-border-radius: 3px 0 0 3px; 898 | -moz-border-radius: 3px 0 0 3px; 899 | border-radius: 3px 0 0 3px; 900 | } 901 | .input-append .uneditable-input { 902 | border-right-color: #ccc; 903 | } 904 | .input-append .add-on { 905 | margin-right: 0; 906 | margin-left: -1px; 907 | -webkit-border-radius: 0 3px 3px 0; 908 | -moz-border-radius: 0 3px 3px 0; 909 | border-radius: 0 3px 3px 0; 910 | } 911 | .input-append input:first-child { 912 | *margin-left: -160px; 913 | } 914 | .input-append input:first-child + .add-on { 915 | *margin-left: -21px; 916 | } 917 | .search-query { 918 | padding-left: 14px; 919 | padding-right: 14px; 920 | margin-bottom: 0; 921 | -webkit-border-radius: 14px; 922 | -moz-border-radius: 14px; 923 | border-radius: 14px; 924 | } 925 | .form-search input, 926 | .form-inline input, 927 | .form-horizontal input, 928 | .form-search textarea, 929 | .form-inline textarea, 930 | .form-horizontal textarea, 931 | .form-search select, 932 | .form-inline select, 933 | .form-horizontal select, 934 | .form-search .help-inline, 935 | .form-inline .help-inline, 936 | .form-horizontal .help-inline, 937 | .form-search .uneditable-input, 938 | .form-inline .uneditable-input, 939 | .form-horizontal .uneditable-input { 940 | display: inline-block; 941 | margin-bottom: 0; 942 | } 943 | .form-search label, 944 | .form-inline label, 945 | .form-search .input-append, 946 | .form-inline .input-append, 947 | .form-search .input-prepend, 948 | .form-inline .input-prepend { 949 | display: inline-block; 950 | } 951 | .form-search .input-append .add-on, 952 | .form-inline .input-prepend .add-on, 953 | .form-search .input-append .add-on, 954 | .form-inline .input-prepend .add-on { 955 | vertical-align: middle; 956 | } 957 | .control-group { 958 | margin-bottom: 9px; 959 | } 960 | .form-horizontal legend + .control-group { 961 | margin-top: 18px; 962 | -webkit-margin-top-collapse: separate; 963 | } 964 | .form-horizontal .control-group { 965 | margin-bottom: 18px; 966 | *zoom: 1; 967 | } 968 | .form-horizontal .control-group:before, .form-horizontal .control-group:after { 969 | display: table; 970 | content: ""; 971 | } 972 | .form-horizontal .control-group:after { 973 | clear: both; 974 | } 975 | .form-horizontal .control-group > label { 976 | float: left; 977 | width: 140px; 978 | padding-top: 5px; 979 | text-align: right; 980 | } 981 | .form-horizontal .controls { 982 | margin-left: 160px; 983 | } 984 | .form-horizontal .form-actions { 985 | padding-left: 160px; 986 | } 987 | table { 988 | max-width: 100%; 989 | border-collapse: collapse; 990 | border-spacing: 0; 991 | } 992 | .table { 993 | width: 100%; 994 | margin-bottom: 18px; 995 | } 996 | .table th, .table td { 997 | padding: 8px; 998 | line-height: 18px; 999 | text-align: left; 1000 | border-top: 1px solid #ddd; 1001 | } 1002 | .table th { 1003 | font-weight: bold; 1004 | vertical-align: bottom; 1005 | } 1006 | .table td { 1007 | vertical-align: top; 1008 | } 1009 | .table thead:first-child tr th, .table thead:first-child tr td { 1010 | border-top: 0; 1011 | } 1012 | .table tbody + tbody { 1013 | border-top: 2px solid #ddd; 1014 | } 1015 | .table-condensed th, .table-condensed td { 1016 | padding: 4px 5px; 1017 | } 1018 | .table-bordered { 1019 | border: 1px solid #ddd; 1020 | border-collapse: separate; 1021 | *border-collapse: collapsed; 1022 | -webkit-border-radius: 4px; 1023 | -moz-border-radius: 4px; 1024 | border-radius: 4px; 1025 | } 1026 | .table-bordered th + th, 1027 | .table-bordered td + td, 1028 | .table-bordered th + td, 1029 | .table-bordered td + th { 1030 | border-left: 1px solid #ddd; 1031 | } 1032 | .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td { 1033 | border-top: 0; 1034 | } 1035 | .table-bordered thead:first-child tr:first-child th:first-child, .table-bordered tbody:first-child tr:first-child td:first-child { 1036 | -webkit-border-radius: 4px 0 0 0; 1037 | -moz-border-radius: 4px 0 0 0; 1038 | border-radius: 4px 0 0 0; 1039 | } 1040 | .table-bordered thead:first-child tr:first-child th:last-child, .table-bordered tbody:first-child tr:first-child td:last-child { 1041 | -webkit-border-radius: 0 4px 0 0; 1042 | -moz-border-radius: 0 4px 0 0; 1043 | border-radius: 0 4px 0 0; 1044 | } 1045 | .table-bordered thead:last-child tr:last-child th:first-child, .table-bordered tbody:last-child tr:last-child td:first-child { 1046 | -webkit-border-radius: 0 0 0 4px; 1047 | -moz-border-radius: 0 0 0 4px; 1048 | border-radius: 0 0 0 4px; 1049 | } 1050 | .table-bordered thead:last-child tr:last-child th:last-child, .table-bordered tbody:last-child tr:last-child td:last-child { 1051 | -webkit-border-radius: 0 0 4px 0; 1052 | -moz-border-radius: 0 0 4px 0; 1053 | border-radius: 0 0 4px 0; 1054 | } 1055 | .table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th { 1056 | background-color: #f9f9f9; 1057 | } 1058 | table .span1 { 1059 | float: none; 1060 | width: 44px; 1061 | margin-left: 0; 1062 | } 1063 | table .span2 { 1064 | float: none; 1065 | width: 124px; 1066 | margin-left: 0; 1067 | } 1068 | table .span3 { 1069 | float: none; 1070 | width: 204px; 1071 | margin-left: 0; 1072 | } 1073 | table .span4 { 1074 | float: none; 1075 | width: 284px; 1076 | margin-left: 0; 1077 | } 1078 | table .span5 { 1079 | float: none; 1080 | width: 364px; 1081 | margin-left: 0; 1082 | } 1083 | table .span6 { 1084 | float: none; 1085 | width: 444px; 1086 | margin-left: 0; 1087 | } 1088 | table .span7 { 1089 | float: none; 1090 | width: 524px; 1091 | margin-left: 0; 1092 | } 1093 | table .span8 { 1094 | float: none; 1095 | width: 604px; 1096 | margin-left: 0; 1097 | } 1098 | table .span9 { 1099 | float: none; 1100 | width: 684px; 1101 | margin-left: 0; 1102 | } 1103 | table .span10 { 1104 | float: none; 1105 | width: 764px; 1106 | margin-left: 0; 1107 | } 1108 | table .span11 { 1109 | float: none; 1110 | width: 844px; 1111 | margin-left: 0; 1112 | } 1113 | table .span12 { 1114 | float: none; 1115 | width: 924px; 1116 | margin-left: 0; 1117 | } 1118 | [class^="icon-"] { 1119 | display: inline-block; 1120 | width: 14px; 1121 | height: 14px; 1122 | vertical-align: text-top; 1123 | background-image: url(../img/glyphicons-halflings.png); 1124 | background-position: 14px 14px; 1125 | background-repeat: no-repeat; 1126 | *margin-right: .3em; 1127 | } 1128 | [class^="icon-"]:last-child { 1129 | *margin-left: 0; 1130 | } 1131 | .icon-white { 1132 | background-image: url(../img/glyphicons-halflings-white.png); 1133 | } 1134 | .icon-glass { 1135 | background-position: 0 0; 1136 | } 1137 | .icon-music { 1138 | background-position: -24px 0; 1139 | } 1140 | .icon-search { 1141 | background-position: -48px 0; 1142 | } 1143 | .icon-envelope { 1144 | background-position: -72px 0; 1145 | } 1146 | .icon-heart { 1147 | background-position: -96px 0; 1148 | } 1149 | .icon-star { 1150 | background-position: -120px 0; 1151 | } 1152 | .icon-star-empty { 1153 | background-position: -144px 0; 1154 | } 1155 | .icon-user { 1156 | background-position: -168px 0; 1157 | } 1158 | .icon-film { 1159 | background-position: -192px 0; 1160 | } 1161 | .icon-th-large { 1162 | background-position: -216px 0; 1163 | } 1164 | .icon-th { 1165 | background-position: -240px 0; 1166 | } 1167 | .icon-th-list { 1168 | background-position: -264px 0; 1169 | } 1170 | .icon-ok { 1171 | background-position: -288px 0; 1172 | } 1173 | .icon-remove { 1174 | background-position: -312px 0; 1175 | } 1176 | .icon-zoom-in { 1177 | background-position: -336px 0; 1178 | } 1179 | .icon-zoom-out { 1180 | background-position: -360px 0; 1181 | } 1182 | .icon-off { 1183 | background-position: -384px 0; 1184 | } 1185 | .icon-signal { 1186 | background-position: -408px 0; 1187 | } 1188 | .icon-cog { 1189 | background-position: -432px 0; 1190 | } 1191 | .icon-trash { 1192 | background-position: -456px 0; 1193 | } 1194 | .icon-home { 1195 | background-position: 0 -24px; 1196 | } 1197 | .icon-file { 1198 | background-position: -24px -24px; 1199 | } 1200 | .icon-time { 1201 | background-position: -48px -24px; 1202 | } 1203 | .icon-road { 1204 | background-position: -72px -24px; 1205 | } 1206 | .icon-download-alt { 1207 | background-position: -96px -24px; 1208 | } 1209 | .icon-download { 1210 | background-position: -120px -24px; 1211 | } 1212 | .icon-upload { 1213 | background-position: -144px -24px; 1214 | } 1215 | .icon-inbox { 1216 | background-position: -168px -24px; 1217 | } 1218 | .icon-play-circle { 1219 | background-position: -192px -24px; 1220 | } 1221 | .icon-repeat { 1222 | background-position: -216px -24px; 1223 | } 1224 | .icon-refresh { 1225 | background-position: -240px -24px; 1226 | } 1227 | .icon-list-alt { 1228 | background-position: -264px -24px; 1229 | } 1230 | .icon-lock { 1231 | background-position: -287px -24px; 1232 | } 1233 | .icon-flag { 1234 | background-position: -312px -24px; 1235 | } 1236 | .icon-headphones { 1237 | background-position: -336px -24px; 1238 | } 1239 | .icon-volume-off { 1240 | background-position: -360px -24px; 1241 | } 1242 | .icon-volume-down { 1243 | background-position: -384px -24px; 1244 | } 1245 | .icon-volume-up { 1246 | background-position: -408px -24px; 1247 | } 1248 | .icon-qrcode { 1249 | background-position: -432px -24px; 1250 | } 1251 | .icon-barcode { 1252 | background-position: -456px -24px; 1253 | } 1254 | .icon-tag { 1255 | background-position: 0 -48px; 1256 | } 1257 | .icon-tags { 1258 | background-position: -25px -48px; 1259 | } 1260 | .icon-book { 1261 | background-position: -48px -48px; 1262 | } 1263 | .icon-bookmark { 1264 | background-position: -72px -48px; 1265 | } 1266 | .icon-print { 1267 | background-position: -96px -48px; 1268 | } 1269 | .icon-camera { 1270 | background-position: -120px -48px; 1271 | } 1272 | .icon-font { 1273 | background-position: -144px -48px; 1274 | } 1275 | .icon-bold { 1276 | background-position: -167px -48px; 1277 | } 1278 | .icon-italic { 1279 | background-position: -192px -48px; 1280 | } 1281 | .icon-text-height { 1282 | background-position: -216px -48px; 1283 | } 1284 | .icon-text-width { 1285 | background-position: -240px -48px; 1286 | } 1287 | .icon-align-left { 1288 | background-position: -264px -48px; 1289 | } 1290 | .icon-align-center { 1291 | background-position: -288px -48px; 1292 | } 1293 | .icon-align-right { 1294 | background-position: -312px -48px; 1295 | } 1296 | .icon-align-justify { 1297 | background-position: -336px -48px; 1298 | } 1299 | .icon-list { 1300 | background-position: -360px -48px; 1301 | } 1302 | .icon-indent-left { 1303 | background-position: -384px -48px; 1304 | } 1305 | .icon-indent-right { 1306 | background-position: -408px -48px; 1307 | } 1308 | .icon-facetime-video { 1309 | background-position: -432px -48px; 1310 | } 1311 | .icon-picture { 1312 | background-position: -456px -48px; 1313 | } 1314 | .icon-pencil { 1315 | background-position: 0 -72px; 1316 | } 1317 | .icon-map-marker { 1318 | background-position: -24px -72px; 1319 | } 1320 | .icon-adjust { 1321 | background-position: -48px -72px; 1322 | } 1323 | .icon-tint { 1324 | background-position: -72px -72px; 1325 | } 1326 | .icon-edit { 1327 | background-position: -96px -72px; 1328 | } 1329 | .icon-share { 1330 | background-position: -120px -72px; 1331 | } 1332 | .icon-check { 1333 | background-position: -144px -72px; 1334 | } 1335 | .icon-move { 1336 | background-position: -168px -72px; 1337 | } 1338 | .icon-step-backward { 1339 | background-position: -192px -72px; 1340 | } 1341 | .icon-fast-backward { 1342 | background-position: -216px -72px; 1343 | } 1344 | .icon-backward { 1345 | background-position: -240px -72px; 1346 | } 1347 | .icon-play { 1348 | background-position: -264px -72px; 1349 | } 1350 | .icon-pause { 1351 | background-position: -288px -72px; 1352 | } 1353 | .icon-stop { 1354 | background-position: -312px -72px; 1355 | } 1356 | .icon-forward { 1357 | background-position: -336px -72px; 1358 | } 1359 | .icon-fast-forward { 1360 | background-position: -360px -72px; 1361 | } 1362 | .icon-step-forward { 1363 | background-position: -384px -72px; 1364 | } 1365 | .icon-eject { 1366 | background-position: -408px -72px; 1367 | } 1368 | .icon-chevron-left { 1369 | background-position: -432px -72px; 1370 | } 1371 | .icon-chevron-right { 1372 | background-position: -456px -72px; 1373 | } 1374 | .icon-plus-sign { 1375 | background-position: 0 -96px; 1376 | } 1377 | .icon-minus-sign { 1378 | background-position: -24px -96px; 1379 | } 1380 | .icon-remove-sign { 1381 | background-position: -48px -96px; 1382 | } 1383 | .icon-ok-sign { 1384 | background-position: -72px -96px; 1385 | } 1386 | .icon-question-sign { 1387 | background-position: -96px -96px; 1388 | } 1389 | .icon-info-sign { 1390 | background-position: -120px -96px; 1391 | } 1392 | .icon-screenshot { 1393 | background-position: -144px -96px; 1394 | } 1395 | .icon-remove-circle { 1396 | background-position: -168px -96px; 1397 | } 1398 | .icon-ok-circle { 1399 | background-position: -192px -96px; 1400 | } 1401 | .icon-ban-circle { 1402 | background-position: -216px -96px; 1403 | } 1404 | .icon-arrow-left { 1405 | background-position: -240px -96px; 1406 | } 1407 | .icon-arrow-right { 1408 | background-position: -264px -96px; 1409 | } 1410 | .icon-arrow-up { 1411 | background-position: -289px -96px; 1412 | } 1413 | .icon-arrow-down { 1414 | background-position: -312px -96px; 1415 | } 1416 | .icon-share-alt { 1417 | background-position: -336px -96px; 1418 | } 1419 | .icon-resize-full { 1420 | background-position: -360px -96px; 1421 | } 1422 | .icon-resize-small { 1423 | background-position: -384px -96px; 1424 | } 1425 | .icon-plus { 1426 | background-position: -408px -96px; 1427 | } 1428 | .icon-minus { 1429 | background-position: -433px -96px; 1430 | } 1431 | .icon-asterisk { 1432 | background-position: -456px -96px; 1433 | } 1434 | .icon-exclamation-sign { 1435 | background-position: 0 -120px; 1436 | } 1437 | .icon-gift { 1438 | background-position: -24px -120px; 1439 | } 1440 | .icon-leaf { 1441 | background-position: -48px -120px; 1442 | } 1443 | .icon-fire { 1444 | background-position: -72px -120px; 1445 | } 1446 | .icon-eye-open { 1447 | background-position: -96px -120px; 1448 | } 1449 | .icon-eye-close { 1450 | background-position: -120px -120px; 1451 | } 1452 | .icon-warning-sign { 1453 | background-position: -144px -120px; 1454 | } 1455 | .icon-plane { 1456 | background-position: -168px -120px; 1457 | } 1458 | .icon-calendar { 1459 | background-position: -192px -120px; 1460 | } 1461 | .icon-random { 1462 | background-position: -216px -120px; 1463 | } 1464 | .icon-comment { 1465 | background-position: -240px -120px; 1466 | } 1467 | .icon-magnet { 1468 | background-position: -264px -120px; 1469 | } 1470 | .icon-chevron-up { 1471 | background-position: -288px -120px; 1472 | } 1473 | .icon-chevron-down { 1474 | background-position: -313px -119px; 1475 | } 1476 | .icon-retweet { 1477 | background-position: -336px -120px; 1478 | } 1479 | .icon-shopping-cart { 1480 | background-position: -360px -120px; 1481 | } 1482 | .icon-folder-close { 1483 | background-position: -384px -120px; 1484 | } 1485 | .icon-folder-open { 1486 | background-position: -408px -120px; 1487 | } 1488 | .icon-resize-vertical { 1489 | background-position: -432px -119px; 1490 | } 1491 | .icon-resize-horizontal { 1492 | background-position: -456px -118px; 1493 | } 1494 | .dropdown { 1495 | position: relative; 1496 | } 1497 | .dropdown-toggle { 1498 | *margin-bottom: -3px; 1499 | } 1500 | .dropdown-toggle:active, .open .dropdown-toggle { 1501 | outline: 0; 1502 | } 1503 | .caret { 1504 | display: inline-block; 1505 | width: 0; 1506 | height: 0; 1507 | text-indent: -99999px; 1508 | *text-indent: 0; 1509 | vertical-align: top; 1510 | border-left: 4px solid transparent; 1511 | border-right: 4px solid transparent; 1512 | border-top: 4px solid #000000; 1513 | opacity: 0.3; 1514 | filter: alpha(opacity=30); 1515 | content: "\2193"; 1516 | } 1517 | .dropdown .caret { 1518 | margin-top: 8px; 1519 | margin-left: 2px; 1520 | } 1521 | .dropdown:hover .caret, .open.dropdown .caret { 1522 | opacity: 1; 1523 | filter: alpha(opacity=100); 1524 | } 1525 | .dropdown-menu { 1526 | position: absolute; 1527 | top: 100%; 1528 | left: 0; 1529 | z-index: 1000; 1530 | float: left; 1531 | display: none; 1532 | min-width: 160px; 1533 | max-width: 220px; 1534 | _width: 160px; 1535 | padding: 4px 0; 1536 | margin: 0; 1537 | list-style: none; 1538 | background-color: #ffffff; 1539 | border-color: #ccc; 1540 | border-color: rgba(0, 0, 0, 0.2); 1541 | border-style: solid; 1542 | border-width: 1px; 1543 | -webkit-border-radius: 0 0 5px 5px; 1544 | -moz-border-radius: 0 0 5px 5px; 1545 | border-radius: 0 0 5px 5px; 1546 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1547 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1548 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 1549 | -webkit-background-clip: padding-box; 1550 | -moz-background-clip: padding; 1551 | background-clip: padding-box; 1552 | *border-right-width: 2px; 1553 | *border-bottom-width: 2px; 1554 | } 1555 | .dropdown-menu.bottom-up { 1556 | top: auto; 1557 | bottom: 100%; 1558 | margin-bottom: 2px; 1559 | } 1560 | .dropdown-menu .divider { 1561 | height: 1px; 1562 | margin: 5px 1px; 1563 | overflow: hidden; 1564 | background-color: #e5e5e5; 1565 | border-bottom: 1px solid #ffffff; 1566 | *width: 100%; 1567 | *margin: -5px 0 5px; 1568 | } 1569 | .dropdown-menu a { 1570 | display: block; 1571 | padding: 3px 15px; 1572 | clear: both; 1573 | font-weight: normal; 1574 | line-height: 18px; 1575 | color: #555555; 1576 | white-space: nowrap; 1577 | } 1578 | .dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover { 1579 | color: #ffffff !important; 1580 | text-decoration: none; 1581 | background-color: #0088cc; 1582 | } 1583 | .dropdown.open { 1584 | *z-index: 1000; 1585 | } 1586 | .dropdown.open .dropdown-toggle { 1587 | color: #ffffff; 1588 | background: #ccc; 1589 | background: rgba(0, 0, 0, 0.3); 1590 | } 1591 | .dropdown.open .dropdown-menu { 1592 | display: block; 1593 | } 1594 | .typeahead { 1595 | margin-top: 2px; 1596 | -webkit-border-radius: 4px; 1597 | -moz-border-radius: 4px; 1598 | border-radius: 4px; 1599 | } 1600 | .well { 1601 | min-height: 20px; 1602 | padding: 19px; 1603 | margin-bottom: 20px; 1604 | background-color: #f5f5f5; 1605 | border: 1px solid #eee; 1606 | border: 1px solid rgba(0, 0, 0, 0.05); 1607 | -webkit-border-radius: 4px; 1608 | -moz-border-radius: 4px; 1609 | border-radius: 4px; 1610 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1611 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1612 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 1613 | } 1614 | .well blockquote { 1615 | border-color: #ddd; 1616 | border-color: rgba(0, 0, 0, 0.15); 1617 | } 1618 | .fade { 1619 | -webkit-transition: opacity 0.15s linear; 1620 | -moz-transition: opacity 0.15s linear; 1621 | -ms-transition: opacity 0.15s linear; 1622 | -o-transition: opacity 0.15s linear; 1623 | transition: opacity 0.15s linear; 1624 | opacity: 0; 1625 | } 1626 | .fade.in { 1627 | opacity: 1; 1628 | } 1629 | .collapse { 1630 | -webkit-transition: height 0.35s ease; 1631 | -moz-transition: height 0.35s ease; 1632 | -ms-transition: height 0.35s ease; 1633 | -o-transition: height 0.35s ease; 1634 | transition: height 0.35s ease; 1635 | position: relative; 1636 | overflow: hidden; 1637 | height: 0; 1638 | } 1639 | .collapse.in { 1640 | height: auto; 1641 | } 1642 | .close { 1643 | float: right; 1644 | font-size: 20px; 1645 | font-weight: bold; 1646 | line-height: 18px; 1647 | color: #000000; 1648 | text-shadow: 0 1px 0 #ffffff; 1649 | opacity: 0.2; 1650 | filter: alpha(opacity=20); 1651 | } 1652 | .close:hover { 1653 | color: #000000; 1654 | text-decoration: none; 1655 | opacity: 0.4; 1656 | filter: alpha(opacity=40); 1657 | cursor: pointer; 1658 | } 1659 | .btn { 1660 | display: inline-block; 1661 | padding: 4px 10px 4px; 1662 | font-size: 13px; 1663 | line-height: 18px; 1664 | color: #333333; 1665 | text-align: center; 1666 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 1667 | background-color: #fafafa; 1668 | color: #333333; 1669 | background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); 1670 | background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); 1671 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); 1672 | background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); 1673 | background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); 1674 | background-image: linear-gradient(top, #ffffff, #e6e6e6); 1675 | background-repeat: repeat-x; 1676 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'ffffff, endColorstr='#'e6e6e6, GradientType=0); 1677 | border: 1px solid #ccc; 1678 | border-bottom-color: #bbb; 1679 | -webkit-border-radius: 4px; 1680 | -moz-border-radius: 4px; 1681 | border-radius: 4px; 1682 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1683 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1684 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1685 | cursor: pointer; 1686 | *margin-left: .3em; 1687 | } 1688 | .btn:first-child { 1689 | *margin-left: 0; 1690 | } 1691 | .btn:hover { 1692 | color: #333333; 1693 | text-decoration: none; 1694 | background-color: #e6e6e6; 1695 | background-position: 0 -15px; 1696 | -webkit-transition: background-position 0.1s linear; 1697 | -moz-transition: background-position 0.1s linear; 1698 | -ms-transition: background-position 0.1s linear; 1699 | -o-transition: background-position 0.1s linear; 1700 | transition: background-position 0.1s linear; 1701 | } 1702 | .btn:focus { 1703 | outline: thin dotted; 1704 | outline: 5px auto -webkit-focus-ring-color; 1705 | outline-offset: -2px; 1706 | } 1707 | .btn.active, .btn:active { 1708 | background-image: none; 1709 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1710 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1711 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 1712 | background-color: #e6e6e6; 1713 | background-color: #d9d9d9 \9; 1714 | color: rgba(0, 0, 0, 0.5); 1715 | outline: 0; 1716 | } 1717 | .btn.disabled, .btn[disabled] { 1718 | cursor: default; 1719 | background-image: none; 1720 | background-color: #e6e6e6; 1721 | opacity: 0.65; 1722 | filter: alpha(opacity=65); 1723 | -webkit-box-shadow: none; 1724 | -moz-box-shadow: none; 1725 | box-shadow: none; 1726 | } 1727 | .btn-large { 1728 | padding: 9px 14px; 1729 | font-size: 15px; 1730 | line-height: normal; 1731 | -webkit-border-radius: 5px; 1732 | -moz-border-radius: 5px; 1733 | border-radius: 5px; 1734 | } 1735 | .btn-large .icon { 1736 | margin-top: 1px; 1737 | } 1738 | .btn-small { 1739 | padding: 5px 9px; 1740 | font-size: 11px; 1741 | line-height: 16px; 1742 | } 1743 | .btn-small .icon { 1744 | margin-top: -1px; 1745 | } 1746 | .btn-primary, 1747 | .btn-primary:hover, 1748 | .btn-warning, 1749 | .btn-warning:hover, 1750 | .btn-danger, 1751 | .btn-danger:hover, 1752 | .btn-success, 1753 | .btn-success:hover, 1754 | .btn-info, 1755 | .btn-info:hover { 1756 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 1757 | color: #ffffff; 1758 | } 1759 | .btn-primary.active, 1760 | .btn-warning.active, 1761 | .btn-danger.active, 1762 | .btn-success.active, 1763 | .btn-info.active { 1764 | color: rgba(255, 255, 255, 0.75); 1765 | } 1766 | .btn-primary { 1767 | background-color: #006dcc; 1768 | color: #ffffff; 1769 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc); 1770 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc); 1771 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); 1772 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); 1773 | background-image: -o-linear-gradient(top, #0088cc, #0044cc); 1774 | background-image: linear-gradient(top, #0088cc, #0044cc); 1775 | background-repeat: repeat-x; 1776 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'0088cc, endColorstr='#'0044cc, GradientType=0); 1777 | border-color: #0044cc #0044cc #002a80; 1778 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1779 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1780 | } 1781 | .btn-primary:hover, 1782 | .btn-primary:active, 1783 | .btn-primary.active, 1784 | .btn-primary.disabled, 1785 | .btn-primary[disabled] { 1786 | background-color: #0044cc; 1787 | } 1788 | .btn-primary:active, .btn-primary.active { 1789 | background-color: #003399 \9; 1790 | } 1791 | .btn-warning { 1792 | background-color: #faa732; 1793 | color: #ffffff; 1794 | background-image: -moz-linear-gradient(top, #fbb450, #f89406); 1795 | background-image: -ms-linear-gradient(top, #fbb450, #f89406); 1796 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); 1797 | background-image: -webkit-linear-gradient(top, #fbb450, #f89406); 1798 | background-image: -o-linear-gradient(top, #fbb450, #f89406); 1799 | background-image: linear-gradient(top, #fbb450, #f89406); 1800 | background-repeat: repeat-x; 1801 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'fbb450, endColorstr='#'f89406, GradientType=0); 1802 | border-color: #f89406 #f89406 #ad6704; 1803 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1804 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1805 | } 1806 | .btn-warning:hover, 1807 | .btn-warning:active, 1808 | .btn-warning.active, 1809 | .btn-warning.disabled, 1810 | .btn-warning[disabled] { 1811 | background-color: #f89406; 1812 | } 1813 | .btn-warning:active, .btn-warning.active { 1814 | background-color: #c67605 \9; 1815 | } 1816 | .btn-danger { 1817 | background-color: #da4f49; 1818 | color: #ffffff; 1819 | background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); 1820 | background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); 1821 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); 1822 | background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); 1823 | background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); 1824 | background-image: linear-gradient(top, #ee5f5b, #bd362f); 1825 | background-repeat: repeat-x; 1826 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'ee5f5b, endColorstr='#'bd362f, GradientType=0); 1827 | border-color: #bd362f #bd362f #802420; 1828 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1829 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1830 | } 1831 | .btn-danger:hover, 1832 | .btn-danger:active, 1833 | .btn-danger.active, 1834 | .btn-danger.disabled, 1835 | .btn-danger[disabled] { 1836 | background-color: #bd362f} 1837 | .btn-danger:active, .btn-danger.active { 1838 | background-color: #942a25 \9; 1839 | } 1840 | .btn-success { 1841 | background-color: #5bb75b; 1842 | color: #ffffff; 1843 | background-image: -moz-linear-gradient(top, #62c462, #51a351); 1844 | background-image: -ms-linear-gradient(top, #62c462, #51a351); 1845 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); 1846 | background-image: -webkit-linear-gradient(top, #62c462, #51a351); 1847 | background-image: -o-linear-gradient(top, #62c462, #51a351); 1848 | background-image: linear-gradient(top, #62c462, #51a351); 1849 | background-repeat: repeat-x; 1850 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'62c462, endColorstr='#'51a351, GradientType=0); 1851 | border-color: #51a351 #51a351 #387038; 1852 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1853 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1854 | } 1855 | .btn-success:hover, 1856 | .btn-success:active, 1857 | .btn-success.active, 1858 | .btn-success.disabled, 1859 | .btn-success[disabled] { 1860 | background-color: #51a351; 1861 | } 1862 | .btn-success:active, .btn-success.active { 1863 | background-color: #408140 \9; 1864 | } 1865 | .btn-info { 1866 | background-color: #49afcd; 1867 | color: #ffffff; 1868 | background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); 1869 | background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); 1870 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); 1871 | background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); 1872 | background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); 1873 | background-image: linear-gradient(top, #5bc0de, #2f96b4); 1874 | background-repeat: repeat-x; 1875 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'5bc0de, endColorstr='#'2f96b4, GradientType=0); 1876 | border-color: #2f96b4 #2f96b4 #1f6377; 1877 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 1878 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 1879 | } 1880 | .btn-info:hover, 1881 | .btn-info:active, 1882 | .btn-info.active, 1883 | .btn-info.disabled, 1884 | .btn-info[disabled] { 1885 | background-color: #2f96b4; 1886 | } 1887 | .btn-info:active, .btn-info.active { 1888 | background-color: #24748c \9; 1889 | } 1890 | button.btn, input[type="submit"].btn { 1891 | *padding-top: 2px; 1892 | *padding-bottom: 2px; 1893 | } 1894 | button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { 1895 | padding: 0; 1896 | border: 0; 1897 | } 1898 | button.btn.large, input[type="submit"].btn.large { 1899 | *padding-top: 7px; 1900 | *padding-bottom: 7px; 1901 | } 1902 | button.btn.small, input[type="submit"].btn.small { 1903 | *padding-top: 3px; 1904 | *padding-bottom: 3px; 1905 | } 1906 | .btn-group { 1907 | position: relative; 1908 | *zoom: 1; 1909 | *margin-left: .3em; 1910 | } 1911 | .btn-group:before, .btn-group:after { 1912 | display: table; 1913 | content: ""; 1914 | } 1915 | .btn-group:after { 1916 | clear: both; 1917 | } 1918 | .btn-group:first-child { 1919 | *margin-left: 0; 1920 | } 1921 | .btn-group + .btn-group { 1922 | margin-left: 5px; 1923 | } 1924 | .btn-toolbar { 1925 | margin-top: 9px; 1926 | margin-bottom: 9px; 1927 | } 1928 | .btn-toolbar .btn-group { 1929 | display: inline-block; 1930 | *display: inline; 1931 | /* IE7 inline-block hack */ 1932 | 1933 | *zoom: 1; 1934 | } 1935 | .btn-group .btn { 1936 | position: relative; 1937 | float: left; 1938 | margin-left: -1px; 1939 | -webkit-border-radius: 0; 1940 | -moz-border-radius: 0; 1941 | border-radius: 0; 1942 | } 1943 | .btn-group .btn:first-child { 1944 | margin-left: 0; 1945 | -webkit-border-top-left-radius: 4px; 1946 | -moz-border-radius-topleft: 4px; 1947 | border-top-left-radius: 4px; 1948 | -webkit-border-bottom-left-radius: 4px; 1949 | -moz-border-radius-bottomleft: 4px; 1950 | border-bottom-left-radius: 4px; 1951 | } 1952 | .btn-group .btn:last-child, .btn-group .dropdown-toggle { 1953 | -webkit-border-top-right-radius: 4px; 1954 | -moz-border-radius-topright: 4px; 1955 | border-top-right-radius: 4px; 1956 | -webkit-border-bottom-right-radius: 4px; 1957 | -moz-border-radius-bottomright: 4px; 1958 | border-bottom-right-radius: 4px; 1959 | } 1960 | .btn-group .btn.large:first-child { 1961 | margin-left: 0; 1962 | -webkit-border-top-left-radius: 6px; 1963 | -moz-border-radius-topleft: 6px; 1964 | border-top-left-radius: 6px; 1965 | -webkit-border-bottom-left-radius: 6px; 1966 | -moz-border-radius-bottomleft: 6px; 1967 | border-bottom-left-radius: 6px; 1968 | } 1969 | .btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle { 1970 | -webkit-border-top-right-radius: 6px; 1971 | -moz-border-radius-topright: 6px; 1972 | border-top-right-radius: 6px; 1973 | -webkit-border-bottom-right-radius: 6px; 1974 | -moz-border-radius-bottomright: 6px; 1975 | border-bottom-right-radius: 6px; 1976 | } 1977 | .btn-group .btn:hover, 1978 | .btn-group .btn:focus, 1979 | .btn-group .btn:active, 1980 | .btn-group .btn.active { 1981 | z-index: 2; 1982 | } 1983 | .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { 1984 | outline: 0; 1985 | } 1986 | .btn-group .dropdown-toggle { 1987 | padding-left: 8px; 1988 | padding-right: 8px; 1989 | -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1990 | -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1991 | box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 1992 | *padding-top: 5px; 1993 | *padding-bottom: 5px; 1994 | } 1995 | .btn-group.open { 1996 | *z-index: 1000; 1997 | } 1998 | .btn-group.open .dropdown-menu { 1999 | display: block; 2000 | margin-top: 1px; 2001 | -webkit-border-radius: 5px; 2002 | -moz-border-radius: 5px; 2003 | border-radius: 5px; 2004 | } 2005 | .btn-group.open .dropdown-toggle { 2006 | background-image: none; 2007 | -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2008 | -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2009 | box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 2010 | } 2011 | .btn .caret { 2012 | margin-top: 7px; 2013 | margin-left: 0; 2014 | } 2015 | .btn:hover .caret, .open.btn-group .caret { 2016 | opacity: 1; 2017 | filter: alpha(opacity=100); 2018 | } 2019 | .btn-primary .caret, 2020 | .btn-danger .caret, 2021 | .btn-info .caret, 2022 | .btn-success .caret { 2023 | border-top-color: #ffffff; 2024 | opacity: 0.75; 2025 | filter: alpha(opacity=75); 2026 | } 2027 | .btn-small .caret { 2028 | margin-top: 4px; 2029 | } 2030 | .alert { 2031 | padding: 8px 35px 8px 14px; 2032 | margin-bottom: 18px; 2033 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2034 | background-color: #fcf8e3; 2035 | border: 1px solid #fbeed5; 2036 | -webkit-border-radius: 4px; 2037 | -moz-border-radius: 4px; 2038 | border-radius: 4px; 2039 | } 2040 | .alert, .alert-heading { 2041 | color: #fcf8e3; 2042 | } 2043 | .alert .close { 2044 | position: relative; 2045 | top: -2px; 2046 | right: -21px; 2047 | line-height: 18px; 2048 | } 2049 | .alert-success { 2050 | background-color: #dff0d8; 2051 | border-color: #d6e9c6; 2052 | } 2053 | .alert-success, .alert-success .alert-heading { 2054 | color: #468847; 2055 | } 2056 | .alert-danger, .alert-error { 2057 | background-color: #f2dede; 2058 | border-color: #eed3d7; 2059 | } 2060 | .alert-danger, 2061 | .alert-error, 2062 | .alert-danger .alert-heading, 2063 | .alert-error .alert-heading { 2064 | color: #b94a48; 2065 | } 2066 | .alert-info { 2067 | background-color: #d9edf7; 2068 | border-color: #bce8f1; 2069 | } 2070 | .alert-info, .alert-info .alert-heading { 2071 | color: #3a87ad; 2072 | } 2073 | .alert-block { 2074 | padding-top: 14px; 2075 | padding-bottom: 14px; 2076 | } 2077 | .alert-block > p, .alert-block > ul { 2078 | margin-bottom: 0; 2079 | } 2080 | .alert-block p + p { 2081 | margin-top: 5px; 2082 | } 2083 | .nav { 2084 | margin-left: 0; 2085 | margin-bottom: 18px; 2086 | list-style: none; 2087 | } 2088 | .nav > li > a { 2089 | display: block; 2090 | } 2091 | .nav > li > a:hover { 2092 | text-decoration: none; 2093 | background-color: #eeeeee; 2094 | } 2095 | .nav-list { 2096 | padding-left: 14px; 2097 | padding-right: 14px; 2098 | margin-bottom: 0; 2099 | } 2100 | .nav-list > li > a, .nav-list .nav-header { 2101 | display: block; 2102 | padding: 3px 15px; 2103 | margin-left: -15px; 2104 | margin-right: -15px; 2105 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2106 | } 2107 | .nav-list .nav-header { 2108 | font-size: 11px; 2109 | font-weight: bold; 2110 | line-height: 18px; 2111 | color: #999999; 2112 | text-transform: uppercase; 2113 | } 2114 | .nav-list > li + .nav-header { 2115 | margin-top: 9px; 2116 | } 2117 | .nav-list .active > a, .nav-list .active > a:hover { 2118 | color: #ffffff; 2119 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 2120 | background-color: #0088cc; 2121 | } 2122 | .nav-list [class^="icon-"] { 2123 | margin-right: 2px; 2124 | } 2125 | .nav-tabs, .nav-pills { 2126 | *zoom: 1; 2127 | } 2128 | .nav-tabs:before, 2129 | .nav-pills:before, 2130 | .nav-tabs:after, 2131 | .nav-pills:after { 2132 | display: table; 2133 | content: ""; 2134 | } 2135 | .nav-tabs:after, .nav-pills:after { 2136 | clear: both; 2137 | } 2138 | .nav-tabs > li, .nav-pills > li { 2139 | float: left; 2140 | } 2141 | .nav-tabs > li > a, .nav-pills > li > a { 2142 | padding-right: 12px; 2143 | padding-left: 12px; 2144 | margin-right: 2px; 2145 | line-height: 14px; 2146 | } 2147 | .nav-tabs { 2148 | border-bottom: 1px solid #ddd; 2149 | } 2150 | .nav-tabs > li { 2151 | margin-bottom: -1px; 2152 | } 2153 | .nav-tabs > li > a { 2154 | padding-top: 9px; 2155 | padding-bottom: 9px; 2156 | border: 1px solid transparent; 2157 | -webkit-border-radius: 4px 4px 0 0; 2158 | -moz-border-radius: 4px 4px 0 0; 2159 | border-radius: 4px 4px 0 0; 2160 | } 2161 | .nav-tabs > li > a:hover { 2162 | border-color: #eeeeee #eeeeee #dddddd; 2163 | } 2164 | .nav-tabs > .active > a, .nav-tabs > .active > a:hover { 2165 | color: #555555; 2166 | background-color: #ffffff; 2167 | border: 1px solid #ddd; 2168 | border-bottom-color: transparent; 2169 | cursor: default; 2170 | } 2171 | .nav-pills > li > a { 2172 | padding-top: 8px; 2173 | padding-bottom: 8px; 2174 | margin-top: 2px; 2175 | margin-bottom: 2px; 2176 | -webkit-border-radius: 5px; 2177 | -moz-border-radius: 5px; 2178 | border-radius: 5px; 2179 | } 2180 | .nav-pills .active > a, .nav-pills .active > a:hover { 2181 | color: #ffffff; 2182 | background-color: #0088cc; 2183 | } 2184 | .nav-stacked > li { 2185 | float: none; 2186 | } 2187 | .nav-stacked > li > a { 2188 | margin-right: 0; 2189 | } 2190 | .nav-tabs.nav-stacked { 2191 | border-bottom: 0; 2192 | } 2193 | .nav-tabs.nav-stacked > li > a { 2194 | border: 1px solid #ddd; 2195 | -webkit-border-radius: 0; 2196 | -moz-border-radius: 0; 2197 | border-radius: 0; 2198 | } 2199 | .nav-tabs.nav-stacked > li:first-child > a { 2200 | -webkit-border-radius: 4px 4px 0 0; 2201 | -moz-border-radius: 4px 4px 0 0; 2202 | border-radius: 4px 4px 0 0; 2203 | } 2204 | .nav-tabs.nav-stacked > li:last-child > a { 2205 | -webkit-border-radius: 0 0 4px 4px; 2206 | -moz-border-radius: 0 0 4px 4px; 2207 | border-radius: 0 0 4px 4px; 2208 | } 2209 | .nav-tabs.nav-stacked > li > a:hover { 2210 | border-color: #ddd; 2211 | z-index: 2; 2212 | } 2213 | .nav-pills.nav-stacked > li > a { 2214 | margin-bottom: 3px; 2215 | } 2216 | .nav-pills.nav-stacked > li:last-child > a { 2217 | margin-bottom: 1px; 2218 | } 2219 | .nav-tabs .dropdown-menu, .nav-pills .dropdown-menu { 2220 | margin-top: 1px; 2221 | border-width: 1px; 2222 | } 2223 | .nav-pills .dropdown-menu { 2224 | -webkit-border-radius: 4px; 2225 | -moz-border-radius: 4px; 2226 | border-radius: 4px; 2227 | } 2228 | .nav-tabs .dropdown-toggle .caret, .nav-pills .dropdown-toggle .caret { 2229 | border-top-color: #0088cc; 2230 | margin-top: 6px; 2231 | } 2232 | .nav-tabs .dropdown-toggle:hover .caret, .nav-pills .dropdown-toggle:hover .caret { 2233 | border-top-color: #005580; 2234 | } 2235 | .nav-tabs .active .dropdown-toggle .caret, .nav-pills .active .dropdown-toggle .caret { 2236 | border-top-color: #333333; 2237 | } 2238 | .nav > .dropdown.active > a:hover { 2239 | color: #000000; 2240 | cursor: pointer; 2241 | } 2242 | .nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > .open.active > a:hover { 2243 | color: #ffffff; 2244 | background-color: #999999; 2245 | border-color: #999999; 2246 | } 2247 | .nav .open .caret, .nav .open.active .caret, .nav .open a:hover .caret { 2248 | border-top-color: #ffffff; 2249 | opacity: 1; 2250 | filter: alpha(opacity=100); 2251 | } 2252 | .tabs-stacked .open > a:hover { 2253 | border-color: #999999; 2254 | } 2255 | .tabbable { 2256 | *zoom: 1; 2257 | } 2258 | .tabbable:before, .tabbable:after { 2259 | display: table; 2260 | content: ""; 2261 | } 2262 | .tabbable:after { 2263 | clear: both; 2264 | } 2265 | .tabs-below .nav-tabs, .tabs-right .nav-tabs, .tabs-left .nav-tabs { 2266 | border-bottom: 0; 2267 | } 2268 | .tab-content > .tab-pane, .pill-content > .pill-pane { 2269 | display: none; 2270 | } 2271 | .tab-content > .active, .pill-content > .active { 2272 | display: block; 2273 | } 2274 | .tabs-below .nav-tabs { 2275 | border-top: 1px solid #ddd; 2276 | } 2277 | .tabs-below .nav-tabs > li { 2278 | margin-top: -1px; 2279 | margin-bottom: 0; 2280 | } 2281 | .tabs-below .nav-tabs > li > a { 2282 | -webkit-border-radius: 0 0 4px 4px; 2283 | -moz-border-radius: 0 0 4px 4px; 2284 | border-radius: 0 0 4px 4px; 2285 | } 2286 | .tabs-below .nav-tabs > li > a:hover { 2287 | border-bottom-color: transparent; 2288 | border-top-color: #ddd; 2289 | } 2290 | .tabs-below .nav-tabs .active > a, .tabs-below .nav-tabs .active > a:hover { 2291 | border-color: transparent #ddd #ddd #ddd; 2292 | } 2293 | .tabs-left .nav-tabs > li, .tabs-right .nav-tabs > li { 2294 | float: none; 2295 | } 2296 | .tabs-left .nav-tabs > li > a, .tabs-right .nav-tabs > li > a { 2297 | min-width: 74px; 2298 | margin-right: 0; 2299 | margin-bottom: 3px; 2300 | } 2301 | .tabs-left .nav-tabs { 2302 | float: left; 2303 | margin-right: 19px; 2304 | border-right: 1px solid #ddd; 2305 | } 2306 | .tabs-left .nav-tabs > li > a { 2307 | margin-right: -1px; 2308 | -webkit-border-radius: 4px 0 0 4px; 2309 | -moz-border-radius: 4px 0 0 4px; 2310 | border-radius: 4px 0 0 4px; 2311 | } 2312 | .tabs-left .nav-tabs > li > a:hover { 2313 | border-color: #eeeeee #dddddd #eeeeee #eeeeee; 2314 | } 2315 | .tabs-left .nav-tabs .active > a, .tabs-left .nav-tabs .active > a:hover { 2316 | border-color: #ddd transparent #ddd #ddd; 2317 | *border-right-color: #ffffff; 2318 | } 2319 | .tabs-right .nav-tabs { 2320 | float: right; 2321 | margin-left: 19px; 2322 | border-left: 1px solid #ddd; 2323 | } 2324 | .tabs-right .nav-tabs > li > a { 2325 | margin-left: -1px; 2326 | -webkit-border-radius: 0 4px 4px 0; 2327 | -moz-border-radius: 0 4px 4px 0; 2328 | border-radius: 0 4px 4px 0; 2329 | } 2330 | .tabs-right .nav-tabs > li > a:hover { 2331 | border-color: #eeeeee #eeeeee #eeeeee #dddddd; 2332 | } 2333 | .tabs-right .nav-tabs .active > a, .tabs-right .nav-tabs .active > a:hover { 2334 | border-color: #ddd #ddd #ddd transparent; 2335 | *border-left-color: #ffffff; 2336 | } 2337 | .navbar { 2338 | overflow: visible; 2339 | margin-bottom: 18px; 2340 | } 2341 | .navbar-inner { 2342 | padding-left: 20px; 2343 | padding-right: 20px; 2344 | background-color: #2c2c2c; 2345 | background-image: -moz-linear-gradient(top, #333333, #222222); 2346 | background-image: -ms-linear-gradient(top, #333333, #222222); 2347 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); 2348 | background-image: -webkit-linear-gradient(top, #333333, #222222); 2349 | background-image: -o-linear-gradient(top, #333333, #222222); 2350 | background-image: linear-gradient(top, #333333, #222222); 2351 | background-repeat: repeat-x; 2352 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#'333333, endColorstr='#'222222, GradientType=0); 2353 | -webkit-border-radius: 4px; 2354 | -moz-border-radius: 4px; 2355 | border-radius: 4px; 2356 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2357 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2358 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 2359 | } 2360 | .btn-navbar { 2361 | display: none; 2362 | float: right; 2363 | padding: 7px 10px; 2364 | margin-left: 5px; 2365 | margin-right: 5px; 2366 | background-color: #2c2c2c; 2367 | background-image: -moz-linear-gradient(top, #333333, #222222); 2368 | background-image: -ms-linear-gradient(top, #333333, #222222); 2369 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); 2370 | background-image: -webkit-linear-gradient(top, #333333, #222222); 2371 | background-image: -o-linear-gradient(top, #333333, #222222); 2372 | background-image: linear-gradient(top, #333333, #222222); 2373 | background-repeat: repeat-x; 2374 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); 2375 | border-color: #222222 #222222 #000000; 2376 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 2377 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 2378 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2379 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2380 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); 2381 | } 2382 | .btn-navbar:hover, 2383 | .btn-navbar:active, 2384 | .btn-navbar.active, 2385 | .btn-navbar.disabled, 2386 | .btn-navbar[disabled] { 2387 | background-color: #222222; 2388 | } 2389 | .btn-navbar:active, .btn-navbar.active { 2390 | background-color: #080808 \9; 2391 | } 2392 | .btn-navbar .icon-bar { 2393 | display: block; 2394 | width: 18px; 2395 | height: 2px; 2396 | background-color: #f5f5f5; 2397 | -webkit-border-radius: 1px; 2398 | -moz-border-radius: 1px; 2399 | border-radius: 1px; 2400 | -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2401 | -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2402 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 2403 | } 2404 | .btn-navbar .icon-bar + .icon-bar { 2405 | margin-top: 3px; 2406 | } 2407 | .nav-collapse.collapse { 2408 | height: auto; 2409 | } 2410 | .navbar .brand:hover { 2411 | text-decoration: none; 2412 | } 2413 | .navbar .brand { 2414 | float: left; 2415 | display: block; 2416 | padding: 8px 20px 12px; 2417 | margin-left: -20px; 2418 | font-size: 20px; 2419 | font-weight: 200; 2420 | line-height: 1; 2421 | color: #ffffff; 2422 | } 2423 | .navbar .navbar-text { 2424 | margin-bottom: 0; 2425 | line-height: 40px; 2426 | color: #999999; 2427 | } 2428 | .navbar .navbar-text a:hover { 2429 | color: #ffffff; 2430 | background-color: transparent; 2431 | } 2432 | .navbar .btn, .navbar .btn-group { 2433 | margin-top: 5px; 2434 | } 2435 | .navbar .btn-group .btn { 2436 | margin-top: 0; 2437 | } 2438 | .navbar-form { 2439 | margin-bottom: 0; 2440 | *zoom: 1; 2441 | } 2442 | .navbar-form:before, .navbar-form:after { 2443 | display: table; 2444 | content: ""; 2445 | } 2446 | .navbar-form:after { 2447 | clear: both; 2448 | } 2449 | .navbar-form input, .navbar-form select { 2450 | display: inline-block; 2451 | margin-top: 5px; 2452 | margin-bottom: 0; 2453 | } 2454 | .navbar-form .radio, .navbar-form .checkbox { 2455 | margin-top: 5px; 2456 | } 2457 | .navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { 2458 | margin-top: 3px; 2459 | } 2460 | .navbar-search { 2461 | position: relative; 2462 | float: left; 2463 | margin-top: 6px; 2464 | margin-bottom: 0; 2465 | } 2466 | .navbar-search .search-query { 2467 | padding: 4px 9px; 2468 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 2469 | font-size: 13px; 2470 | font-weight: normal; 2471 | line-height: 1; 2472 | color: #ffffff; 2473 | color: rgba(255, 255, 255, 0.75); 2474 | background: #666; 2475 | background: rgba(255, 255, 255, 0.3); 2476 | border: 1px solid #111; 2477 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2478 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2479 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); 2480 | -webkit-transition: none; 2481 | -moz-transition: none; 2482 | -ms-transition: none; 2483 | -o-transition: none; 2484 | transition: none; 2485 | } 2486 | .navbar-search .search-query :-moz-placeholder { 2487 | color: #eeeeee; 2488 | } 2489 | .navbar-search .search-query::-webkit-input-placeholder { 2490 | color: #eeeeee; 2491 | } 2492 | .navbar-search .search-query:hover { 2493 | color: #ffffff; 2494 | background-color: #999999; 2495 | background-color: rgba(255, 255, 255, 0.5); 2496 | } 2497 | .navbar-search .search-query:focus, .navbar-search .search-query.focused { 2498 | padding: 5px 10px; 2499 | color: #333333; 2500 | text-shadow: 0 1px 0 #ffffff; 2501 | background-color: #ffffff; 2502 | border: 0; 2503 | -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2504 | -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2505 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); 2506 | outline: 0; 2507 | } 2508 | .navbar-fixed-top { 2509 | position: fixed; 2510 | top: 0; 2511 | right: 0; 2512 | left: 0; 2513 | z-index: 1030; 2514 | } 2515 | .navbar-fixed-top .navbar-inner { 2516 | padding-left: 0; 2517 | padding-right: 0; 2518 | -webkit-border-radius: 0; 2519 | -moz-border-radius: 0; 2520 | border-radius: 0; 2521 | } 2522 | .navbar .nav { 2523 | position: relative; 2524 | left: 0; 2525 | display: block; 2526 | float: left; 2527 | margin: 0 10px 0 0; 2528 | } 2529 | .navbar .nav.pull-right { 2530 | float: right; 2531 | } 2532 | .navbar .nav > li { 2533 | display: block; 2534 | float: left; 2535 | } 2536 | .navbar .nav > li > a { 2537 | float: none; 2538 | padding: 10px 10px 11px; 2539 | line-height: 19px; 2540 | font-size: 13px; 2541 | color: #999999; 2542 | text-decoration: none; 2543 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 2544 | } 2545 | .navbar .nav > li > a:hover { 2546 | background-color: transparent; 2547 | color: #ffffff !important; 2548 | text-decoration: none; 2549 | } 2550 | .navbar .nav .active > a, .navbar .nav .active > a:hover { 2551 | color: #ffffff; 2552 | text-decoration: none; 2553 | background-color: #222222; 2554 | background-color: rgba(0, 0, 0, 0.5); 2555 | } 2556 | .navbar .divider-vertical { 2557 | height: 40px; 2558 | width: 1px; 2559 | margin: 0 9px; 2560 | overflow: hidden; 2561 | background-color: #222222; 2562 | border-right: 1px solid #333333; 2563 | } 2564 | .navbar .nav.pull-right { 2565 | margin-left: 10px; 2566 | margin-right: 0; 2567 | } 2568 | .navbar .dropdown-menu { 2569 | margin-top: 1px; 2570 | -webkit-border-radius: 4px; 2571 | -moz-border-radius: 4px; 2572 | border-radius: 4px; 2573 | } 2574 | .navbar .dropdown-menu:before { 2575 | content: ''; 2576 | display: inline-block; 2577 | border-left: 7px solid transparent; 2578 | border-right: 7px solid transparent; 2579 | border-bottom: 7px solid #ccc; 2580 | border-bottom-color: rgba(0, 0, 0, 0.2); 2581 | position: absolute; 2582 | top: -7px; 2583 | left: 9px; 2584 | } 2585 | .navbar .dropdown-menu:after { 2586 | content: ''; 2587 | display: inline-block; 2588 | border-left: 6px solid transparent; 2589 | border-right: 6px solid transparent; 2590 | border-bottom: 6px solid #ffffff; 2591 | position: absolute; 2592 | top: -6px; 2593 | left: 10px; 2594 | } 2595 | .navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret { 2596 | border-top-color: #ffffff; 2597 | } 2598 | .navbar .nav .active .caret { 2599 | opacity: 1; 2600 | filter: alpha(opacity=100); 2601 | } 2602 | .navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle { 2603 | background-color: transparent; 2604 | } 2605 | .navbar .nav .active > .dropdown-toggle:hover { 2606 | color: #ffffff; 2607 | } 2608 | .navbar .nav.pull-right .dropdown-menu { 2609 | left: auto; 2610 | right: 0; 2611 | } 2612 | .navbar .nav.pull-right .dropdown-menu:before { 2613 | left: auto; 2614 | right: 12px; 2615 | } 2616 | .navbar .nav.pull-right .dropdown-menu:after { 2617 | left: auto; 2618 | right: 13px; 2619 | } 2620 | .breadcrumb { 2621 | padding: 7px 14px; 2622 | margin: 0 0 18px; 2623 | background-color: #fbfbfb; 2624 | background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); 2625 | background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); 2626 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); 2627 | background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); 2628 | background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); 2629 | background-image: linear-gradient(top, #ffffff, #f5f5f5); 2630 | background-repeat: repeat-x; 2631 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); 2632 | border: 1px solid #ddd; 2633 | -webkit-border-radius: 3px; 2634 | -moz-border-radius: 3px; 2635 | border-radius: 3px; 2636 | -webkit-box-shadow: inset 0 1px 0 #ffffff; 2637 | -moz-box-shadow: inset 0 1px 0 #ffffff; 2638 | box-shadow: inset 0 1px 0 #ffffff; 2639 | } 2640 | .breadcrumb li { 2641 | display: inline; 2642 | text-shadow: 0 1px 0 #ffffff; 2643 | } 2644 | .breadcrumb .divider { 2645 | padding: 0 5px; 2646 | color: #999999; 2647 | } 2648 | .breadcrumb .active a { 2649 | color: #333333; 2650 | } 2651 | .pagination { 2652 | height: 36px; 2653 | margin: 18px 0; 2654 | } 2655 | .pagination ul { 2656 | display: inline-block; 2657 | *display: inline; 2658 | /* IE7 inline-block hack */ 2659 | 2660 | *zoom: 1; 2661 | margin-left: 0; 2662 | margin-bottom: 0; 2663 | -webkit-border-radius: 3px; 2664 | -moz-border-radius: 3px; 2665 | border-radius: 3px; 2666 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2667 | -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2668 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 2669 | } 2670 | .pagination li { 2671 | display: inline; 2672 | } 2673 | .pagination a { 2674 | float: left; 2675 | padding: 0 14px; 2676 | line-height: 34px; 2677 | text-decoration: none; 2678 | border: 1px solid #ddd; 2679 | border-left-width: 0; 2680 | } 2681 | .pagination a:hover, .pagination .active a { 2682 | background-color: #f5f5f5; 2683 | } 2684 | .pagination .active a { 2685 | color: #999999; 2686 | cursor: default; 2687 | } 2688 | .pagination .disabled a, .pagination .disabled a:hover { 2689 | color: #999999; 2690 | background-color: transparent; 2691 | cursor: default; 2692 | } 2693 | .pagination li:first-child a { 2694 | border-left-width: 1px; 2695 | -webkit-border-radius: 3px 0 0 3px; 2696 | -moz-border-radius: 3px 0 0 3px; 2697 | border-radius: 3px 0 0 3px; 2698 | } 2699 | .pagination li:last-child a { 2700 | -webkit-border-radius: 0 3px 3px 0; 2701 | -moz-border-radius: 0 3px 3px 0; 2702 | border-radius: 0 3px 3px 0; 2703 | } 2704 | .pagination-centered { 2705 | text-align: center; 2706 | } 2707 | .pagination-right { 2708 | text-align: right; 2709 | } 2710 | .pager { 2711 | margin-left: 0; 2712 | margin-bottom: 18px; 2713 | list-style: none; 2714 | text-align: center; 2715 | *zoom: 1; 2716 | } 2717 | .pager:before, .pager:after { 2718 | display: table; 2719 | content: ""; 2720 | } 2721 | .pager:after { 2722 | clear: both; 2723 | } 2724 | .pager li { 2725 | display: inline; 2726 | } 2727 | .pager a { 2728 | display: inline-block; 2729 | padding: 5px 14px; 2730 | background-color: #fff; 2731 | border: 1px solid #ddd; 2732 | -webkit-border-radius: 15px; 2733 | -moz-border-radius: 15px; 2734 | border-radius: 15px; 2735 | } 2736 | .pager a:hover { 2737 | text-decoration: none; 2738 | background-color: #f5f5f5; 2739 | } 2740 | .pager .next a { 2741 | float: right; 2742 | } 2743 | .pager .previous a { 2744 | float: left; 2745 | } 2746 | .modal-open .dropdown-menu { 2747 | z-index: 2050; 2748 | } 2749 | .modal-open .dropdown.open { 2750 | *z-index: 2050; 2751 | } 2752 | .modal-open .popover { 2753 | z-index: 2060; 2754 | } 2755 | .modal-open .tooltip { 2756 | z-index: 2070; 2757 | } 2758 | .modal-backdrop { 2759 | position: fixed; 2760 | top: 0; 2761 | right: 0; 2762 | bottom: 0; 2763 | left: 0; 2764 | z-index: 1040; 2765 | background-color: #000000; 2766 | } 2767 | .modal-backdrop.fade { 2768 | opacity: 0; 2769 | } 2770 | .modal-backdrop, .modal-backdrop.fade.in { 2771 | opacity: 0.8; 2772 | filter: alpha(opacity=80); 2773 | } 2774 | .modal { 2775 | position: fixed; 2776 | top: 50%; 2777 | left: 50%; 2778 | z-index: 1050; 2779 | max-height: 500px; 2780 | overflow: auto; 2781 | width: 560px; 2782 | margin: -250px 0 0 -280px; 2783 | background-color: #ffffff; 2784 | border: 1px solid #999; 2785 | border: 1px solid rgba(0, 0, 0, 0.3); 2786 | *border: 1px solid #999; 2787 | /* IE6-7 */ 2788 | 2789 | -webkit-border-radius: 6px; 2790 | -moz-border-radius: 6px; 2791 | border-radius: 6px; 2792 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2793 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2794 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2795 | -webkit-background-clip: padding-box; 2796 | -moz-background-clip: padding-box; 2797 | background-clip: padding-box; 2798 | } 2799 | .modal.fade { 2800 | -webkit-transition: opacity .3s linear, top .3s ease-out; 2801 | -moz-transition: opacity .3s linear, top .3s ease-out; 2802 | -ms-transition: opacity .3s linear, top .3s ease-out; 2803 | -o-transition: opacity .3s linear, top .3s ease-out; 2804 | transition: opacity .3s linear, top .3s ease-out; 2805 | top: -25%; 2806 | } 2807 | .modal.fade.in { 2808 | top: 50%; 2809 | } 2810 | .modal-header { 2811 | padding: 9px 15px; 2812 | border-bottom: 1px solid #eee; 2813 | } 2814 | .modal-header .close { 2815 | margin-top: 2px; 2816 | } 2817 | .modal-body { 2818 | padding: 15px; 2819 | } 2820 | .modal-footer { 2821 | padding: 14px 15px 15px; 2822 | margin-bottom: 0; 2823 | background-color: #f5f5f5; 2824 | border-top: 1px solid #ddd; 2825 | -webkit-border-radius: 0 0 6px 6px; 2826 | -moz-border-radius: 0 0 6px 6px; 2827 | border-radius: 0 0 6px 6px; 2828 | -webkit-box-shadow: inset 0 1px 0 #ffffff; 2829 | -moz-box-shadow: inset 0 1px 0 #ffffff; 2830 | box-shadow: inset 0 1px 0 #ffffff; 2831 | *zoom: 1; 2832 | } 2833 | .modal-footer:before, .modal-footer:after { 2834 | display: table; 2835 | content: ""; 2836 | } 2837 | .modal-footer:after { 2838 | clear: both; 2839 | } 2840 | .modal-footer .btn { 2841 | float: right; 2842 | margin-left: 5px; 2843 | margin-bottom: 0; 2844 | } 2845 | .tooltip { 2846 | position: absolute; 2847 | z-index: 1020; 2848 | display: block; 2849 | visibility: visible; 2850 | padding: 5px; 2851 | font-size: 11px; 2852 | opacity: 0; 2853 | filter: alpha(opacity=0); 2854 | } 2855 | .tooltip.in { 2856 | opacity: 0.8; 2857 | filter: alpha(opacity=80); 2858 | } 2859 | .tooltip.top { 2860 | margin-top: -2px; 2861 | } 2862 | .tooltip.right { 2863 | margin-left: 2px; 2864 | } 2865 | .tooltip.bottom { 2866 | margin-top: 2px; 2867 | } 2868 | .tooltip.left { 2869 | margin-left: -2px; 2870 | } 2871 | .tooltip.top .tooltip-arrow { 2872 | bottom: 0; 2873 | left: 50%; 2874 | margin-left: -5px; 2875 | border-left: 5px solid transparent; 2876 | border-right: 5px solid transparent; 2877 | border-top: 5px solid #000000; 2878 | } 2879 | .tooltip.left .tooltip-arrow { 2880 | top: 50%; 2881 | right: 0; 2882 | margin-top: -5px; 2883 | border-top: 5px solid transparent; 2884 | border-bottom: 5px solid transparent; 2885 | border-left: 5px solid #000000; 2886 | } 2887 | .tooltip.bottom .tooltip-arrow { 2888 | top: 0; 2889 | left: 50%; 2890 | margin-left: -5px; 2891 | border-left: 5px solid transparent; 2892 | border-right: 5px solid transparent; 2893 | border-bottom: 5px solid #000000; 2894 | } 2895 | .tooltip.right .tooltip-arrow { 2896 | top: 50%; 2897 | left: 0; 2898 | margin-top: -5px; 2899 | border-top: 5px solid transparent; 2900 | border-bottom: 5px solid transparent; 2901 | border-right: 5px solid #000000; 2902 | } 2903 | .tooltip-inner { 2904 | max-width: 200px; 2905 | padding: 3px 8px; 2906 | color: #ffffff; 2907 | text-align: center; 2908 | text-decoration: none; 2909 | background-color: #000000; 2910 | -webkit-border-radius: 4px; 2911 | -moz-border-radius: 4px; 2912 | border-radius: 4px; 2913 | } 2914 | .tooltip-arrow { 2915 | position: absolute; 2916 | width: 0; 2917 | height: 0; 2918 | } 2919 | .popover { 2920 | position: absolute; 2921 | top: 0; 2922 | left: 0; 2923 | z-index: 1010; 2924 | display: none; 2925 | padding: 5px; 2926 | } 2927 | .popover.top { 2928 | margin-top: -5px; 2929 | } 2930 | .popover.right { 2931 | margin-left: 5px; 2932 | } 2933 | .popover.bottom { 2934 | margin-top: 5px; 2935 | } 2936 | .popover.left { 2937 | margin-left: -5px; 2938 | } 2939 | .popover.top .arrow { 2940 | bottom: 0; 2941 | left: 50%; 2942 | margin-left: -5px; 2943 | border-left: 5px solid transparent; 2944 | border-right: 5px solid transparent; 2945 | border-top: 5px solid #000000; 2946 | } 2947 | .popover.right .arrow { 2948 | top: 50%; 2949 | left: 0; 2950 | margin-top: -5px; 2951 | border-top: 5px solid transparent; 2952 | border-bottom: 5px solid transparent; 2953 | border-right: 5px solid #000000; 2954 | } 2955 | .popover.bottom .arrow { 2956 | top: 0; 2957 | left: 50%; 2958 | margin-left: -5px; 2959 | border-left: 5px solid transparent; 2960 | border-right: 5px solid transparent; 2961 | border-bottom: 5px solid #000000; 2962 | } 2963 | .popover.left .arrow { 2964 | top: 50%; 2965 | right: 0; 2966 | margin-top: -5px; 2967 | border-top: 5px solid transparent; 2968 | border-bottom: 5px solid transparent; 2969 | border-left: 5px solid #000000; 2970 | } 2971 | .popover .arrow { 2972 | position: absolute; 2973 | width: 0; 2974 | height: 0; 2975 | } 2976 | .popover-inner { 2977 | padding: 3px; 2978 | width: 280px; 2979 | overflow: hidden; 2980 | background: #000000; 2981 | background: rgba(0, 0, 0, 0.8); 2982 | -webkit-border-radius: 6px; 2983 | -moz-border-radius: 6px; 2984 | border-radius: 6px; 2985 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2986 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2987 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); 2988 | } 2989 | .popover-title { 2990 | padding: 9px 15px; 2991 | line-height: 1; 2992 | background-color: #f5f5f5; 2993 | border-bottom: 1px solid #eee; 2994 | -webkit-border-radius: 3px 3px 0 0; 2995 | -moz-border-radius: 3px 3px 0 0; 2996 | border-radius: 3px 3px 0 0; 2997 | } 2998 | .popover-content { 2999 | padding: 14px; 3000 | background-color: #ffffff; 3001 | -webkit-border-radius: 0 0 3px 3px; 3002 | -moz-border-radius: 0 0 3px 3px; 3003 | border-radius: 0 0 3px 3px; 3004 | -webkit-background-clip: padding-box; 3005 | -moz-background-clip: padding-box; 3006 | background-clip: padding-box; 3007 | } 3008 | .popover-content p, .popover-content ul, .popover-content ol { 3009 | margin-bottom: 0; 3010 | } 3011 | .thumbnails { 3012 | margin-left: -20px; 3013 | list-style: none; 3014 | *zoom: 1; 3015 | } 3016 | .thumbnails:before, .thumbnails:after { 3017 | display: table; 3018 | content: ""; 3019 | } 3020 | .thumbnails:after { 3021 | clear: both; 3022 | } 3023 | .thumbnails > li { 3024 | float: left; 3025 | margin: 0 0 18px 20px; 3026 | } 3027 | .thumbnail { 3028 | display: block; 3029 | padding: 4px; 3030 | line-height: 1; 3031 | border: 1px solid #ddd; 3032 | -webkit-border-radius: 4px; 3033 | -moz-border-radius: 4px; 3034 | border-radius: 4px; 3035 | -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3036 | -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3037 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); 3038 | } 3039 | a.thumbnail:hover { 3040 | border-color: #0088cc; 3041 | -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3042 | -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3043 | box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); 3044 | } 3045 | .thumbnail > img { 3046 | display: block; 3047 | max-width: 100%; 3048 | margin-left: auto; 3049 | margin-right: auto; 3050 | } 3051 | .thumbnail .caption { 3052 | padding: 9px; 3053 | } 3054 | .label { 3055 | padding: 1px 3px 2px; 3056 | font-size: 9.75px; 3057 | font-weight: bold; 3058 | color: #ffffff; 3059 | text-transform: uppercase; 3060 | background-color: #999999; 3061 | -webkit-border-radius: 3px; 3062 | -moz-border-radius: 3px; 3063 | border-radius: 3px; 3064 | } 3065 | .label-important { 3066 | background-color: #468847; 3067 | } 3068 | .label-warning { 3069 | background-color: #f89406; 3070 | } 3071 | .label-success { 3072 | background-color: #b94a48; 3073 | } 3074 | .label-info { 3075 | background-color: #3a87ad; 3076 | } 3077 | @-webkit-keyframes progress-bar-stripes { 3078 | from { 3079 | background-position: 0 0; 3080 | } 3081 | to { 3082 | background-position: 40px 0; 3083 | } 3084 | } 3085 | @-moz-keyframes progress-bar-stripes { 3086 | from { 3087 | background-position: 0 0; 3088 | } 3089 | to { 3090 | background-position: 40px 0; 3091 | } 3092 | } 3093 | @keyframes progress-bar-stripes { 3094 | from { 3095 | background-position: 0 0; 3096 | } 3097 | to { 3098 | background-position: 40px 0; 3099 | } 3100 | } 3101 | .progress { 3102 | overflow: hidden; 3103 | height: 18px; 3104 | margin-bottom: 18px; 3105 | background-color: #f7f7f7; 3106 | background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); 3107 | background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); 3108 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); 3109 | background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); 3110 | background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); 3111 | background-image: linear-gradient(top, #f5f5f5, #f9f9f9); 3112 | background-repeat: repeat-x; 3113 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); 3114 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3115 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3116 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 3117 | -webkit-border-radius: 4px; 3118 | -moz-border-radius: 4px; 3119 | border-radius: 4px; 3120 | } 3121 | .progress .bar { 3122 | width: 0%; 3123 | height: 18px; 3124 | color: #ffffff; 3125 | font-size: 12px; 3126 | text-align: center; 3127 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 3128 | background-color: #0e90d2; 3129 | background-image: -moz-linear-gradient(top, #149bdf, #0480be); 3130 | background-image: -ms-linear-gradient(top, #149bdf, #0480be); 3131 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); 3132 | background-image: -webkit-linear-gradient(top, #149bdf, #0480be); 3133 | background-image: -o-linear-gradient(top, #149bdf, #0480be); 3134 | background-image: linear-gradient(top, #149bdf, #0480be); 3135 | background-repeat: repeat-x; 3136 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); 3137 | -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3138 | -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3139 | box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 3140 | -webkit-box-sizing: border-box; 3141 | -moz-box-sizing: border-box; 3142 | box-sizing: border-box; 3143 | -webkit-transition: width 0.6s ease; 3144 | -moz-transition: width 0.6s ease; 3145 | -ms-transition: width 0.6s ease; 3146 | -o-transition: width 0.6s ease; 3147 | transition: width 0.6s ease; 3148 | } 3149 | .progress-striped .bar { 3150 | background-color: #62c462; 3151 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); 3152 | background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3153 | background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3154 | background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3155 | background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3156 | background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3157 | -webkit-background-size: 40px 40px; 3158 | -moz-background-size: 40px 40px; 3159 | -o-background-size: 40px 40px; 3160 | background-size: 40px 40px; 3161 | } 3162 | .progress.active .bar { 3163 | -webkit-animation: progress-bar-stripes 2s linear infinite; 3164 | -moz-animation: progress-bar-stripes 2s linear infinite; 3165 | animation: progress-bar-stripes 2s linear infinite; 3166 | } 3167 | .progress-danger .bar { 3168 | background-color: #dd514c; 3169 | background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); 3170 | background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); 3171 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); 3172 | background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); 3173 | background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); 3174 | background-image: linear-gradient(top, #ee5f5b, #c43c35); 3175 | background-repeat: repeat-x; 3176 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); 3177 | } 3178 | .progress-danger.progress-striped .bar { 3179 | background-color: #ee5f5b; 3180 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); 3181 | background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3182 | background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3183 | background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3184 | background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3185 | background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3186 | } 3187 | .progress-success .bar { 3188 | background-color: #5eb95e; 3189 | background-image: -moz-linear-gradient(top, #62c462, #57a957); 3190 | background-image: -ms-linear-gradient(top, #62c462, #57a957); 3191 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); 3192 | background-image: -webkit-linear-gradient(top, #62c462, #57a957); 3193 | background-image: -o-linear-gradient(top, #62c462, #57a957); 3194 | background-image: linear-gradient(top, #62c462, #57a957); 3195 | background-repeat: repeat-x; 3196 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); 3197 | } 3198 | .progress-success.progress-striped .bar { 3199 | background-color: #62c462; 3200 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); 3201 | background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3202 | background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3203 | background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3204 | background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3205 | background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3206 | } 3207 | .progress-info .bar { 3208 | background-color: #4bb1cf; 3209 | background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); 3210 | background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); 3211 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); 3212 | background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); 3213 | background-image: -o-linear-gradient(top, #5bc0de, #339bb9); 3214 | background-image: linear-gradient(top, #5bc0de, #339bb9); 3215 | background-repeat: repeat-x; 3216 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); 3217 | } 3218 | .progress-info.progress-striped .bar { 3219 | background-color: #5bc0de; 3220 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); 3221 | background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3222 | background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3223 | background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3224 | background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3225 | background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 3226 | } 3227 | .accordion { 3228 | margin-bottom: 18px; 3229 | } 3230 | .accordion-group { 3231 | margin-bottom: 2px; 3232 | border: 1px solid #e5e5e5; 3233 | -webkit-border-radius: 4px; 3234 | -moz-border-radius: 4px; 3235 | border-radius: 4px; 3236 | } 3237 | .accordion-heading { 3238 | border-bottom: 0; 3239 | } 3240 | .accordion-heading .accordion-toggle { 3241 | display: block; 3242 | padding: 8px 15px; 3243 | } 3244 | .accordion-inner { 3245 | padding: 9px 15px; 3246 | border-top: 1px solid #e5e5e5; 3247 | } 3248 | .carousel { 3249 | position: relative; 3250 | margin-bottom: 18px; 3251 | line-height: 1; 3252 | } 3253 | .carousel-inner { 3254 | overflow: hidden; 3255 | width: 100%; 3256 | position: relative; 3257 | } 3258 | .carousel .item { 3259 | display: none; 3260 | position: relative; 3261 | -webkit-transition: 0.6s ease-in-out left; 3262 | -moz-transition: 0.6s ease-in-out left; 3263 | -ms-transition: 0.6s ease-in-out left; 3264 | -o-transition: 0.6s ease-in-out left; 3265 | transition: 0.6s ease-in-out left; 3266 | } 3267 | .carousel .item > img { 3268 | display: block; 3269 | line-height: 1; 3270 | } 3271 | .carousel .active, .carousel .next, .carousel .prev { 3272 | display: block; 3273 | } 3274 | .carousel .active { 3275 | left: 0; 3276 | } 3277 | .carousel .next, .carousel .prev { 3278 | position: absolute; 3279 | top: 0; 3280 | width: 100%; 3281 | } 3282 | .carousel .next { 3283 | left: 100%; 3284 | } 3285 | .carousel .prev { 3286 | left: -100%; 3287 | } 3288 | .carousel .next.left, .carousel .prev.right { 3289 | left: 0; 3290 | } 3291 | .carousel .active.left { 3292 | left: -100%; 3293 | } 3294 | .carousel .active.right { 3295 | left: 100%; 3296 | } 3297 | .carousel-control { 3298 | position: absolute; 3299 | top: 40%; 3300 | left: 15px; 3301 | width: 40px; 3302 | height: 40px; 3303 | margin-top: -20px; 3304 | font-size: 60px; 3305 | font-weight: 100; 3306 | line-height: 30px; 3307 | color: #ffffff; 3308 | text-align: center; 3309 | background: #222222; 3310 | border: 3px solid #ffffff; 3311 | -webkit-border-radius: 23px; 3312 | -moz-border-radius: 23px; 3313 | border-radius: 23px; 3314 | opacity: 0.5; 3315 | filter: alpha(opacity=50); 3316 | } 3317 | .carousel-control.right { 3318 | left: auto; 3319 | right: 15px; 3320 | } 3321 | .carousel-control:hover { 3322 | color: #ffffff; 3323 | text-decoration: none; 3324 | opacity: 0.9; 3325 | filter: alpha(opacity=90); 3326 | } 3327 | .carousel-caption { 3328 | position: absolute; 3329 | left: 0; 3330 | right: 0; 3331 | bottom: 0; 3332 | padding: 10px 15px 5px; 3333 | background: #333333; 3334 | background: rgba(0, 0, 0, 0.75); 3335 | } 3336 | .carousel-caption h4, .carousel-caption p { 3337 | color: #ffffff; 3338 | } 3339 | .hero-unit { 3340 | padding: 60px; 3341 | margin-bottom: 30px; 3342 | background-color: #f5f5f5; 3343 | -webkit-border-radius: 6px; 3344 | -moz-border-radius: 6px; 3345 | border-radius: 6px; 3346 | } 3347 | .hero-unit h1 { 3348 | margin-bottom: 0; 3349 | font-size: 60px; 3350 | line-height: 1; 3351 | letter-spacing: -1px; 3352 | } 3353 | .hero-unit p { 3354 | font-size: 18px; 3355 | font-weight: 200; 3356 | line-height: 27px; 3357 | } 3358 | .pull-right { 3359 | float: right; 3360 | } 3361 | .pull-left { 3362 | float: left; 3363 | } 3364 | .hide { 3365 | display: none; 3366 | } 3367 | .show { 3368 | display: block; 3369 | } 3370 | .invisible { 3371 | visibility: hidden; 3372 | } --------------------------------------------------------------------------------